opm-common
BrineCo2Pvt.hpp
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 2 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 
19  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
27 #ifndef OPM_BRINE_CO2_PVT_HPP
28 #define OPM_BRINE_CO2_PVT_HPP
29 
31 #include <opm/common/TimingMacros.hpp>
32 #include <opm/common/ErrorMacros.hpp>
33 #include <opm/common/utility/gpuDecorators.hpp>
35 #include <opm/common/utility/VectorWithDefaultAllocator.hpp>
36 
38 
44 #include <opm/material/components/CO2Tables.hpp>
48 
49 #include <opm/input/eclipse/EclipseState/Co2StoreConfig.hpp>
50 
51 #include <cstddef>
52 #include <vector>
53 
54 namespace Opm {
55 
56 class EclipseState;
57 class Schedule;
58 class Co2StoreConfig;
59 class EzrokhiTable;
60 
61 // forward declaration of the class so the function in the next namespace can be declared
62 template <class Scalar, template <class> class Storage>
64 
65 #if HAVE_CUDA
66 // declaration of make_view in correct namespace so friend function can be declared in the class
67 namespace gpuistl {
68  template <class ScalarT>
71 }
72 #endif
73 
78 template <class Scalar, template <class> class Storage = Opm::VectorWithDefaultAllocator>
79 class BrineCo2Pvt
80 {
81  using Params = Opm::CO2Tables<double, Storage>;
82  using ContainerT = Storage<Scalar>;
83  static constexpr bool extrapolate = true;
84  //typedef H2O<Scalar> H2O_IAPWS;
85  //typedef Brine<Scalar, H2O_IAPWS> Brine_IAPWS;
86  //typedef TabulatedComponent<Scalar, H2O_IAPWS> H2O_Tabulated;
87  //typedef TabulatedComponent<Scalar, Brine_IAPWS> Brine_Tabulated;
88 
89  //typedef H2O_Tabulated H2O;
90  //typedef Brine_Tabulated Brine;
91 
92 
93 public:
97 
100 
101  BrineCo2Pvt() = default;
102 
103  explicit BrineCo2Pvt(const ContainerT& salinity,
104  int activityModel = 3,
105  int thermalMixingModelSalt = 1,
106  int thermalMixingModelLiquid = 2,
107  Scalar T_ref = 288.71, //(273.15 + 15.56)
108  Scalar P_ref = 101325);
109 
110  BrineCo2Pvt(const ContainerT& brineReferenceDensity,
111  const ContainerT& co2ReferenceDensity,
112  const ContainerT& salinity,
113  int activityModel,
114  Co2StoreConfig::SaltMixingType thermalMixingModelSalt,
115  Co2StoreConfig::LiquidMixingType thermalMixingModelLiquid,
116  Params params)
117  : brineReferenceDensity_(brineReferenceDensity)
118  , co2ReferenceDensity_(co2ReferenceDensity)
119  , salinity_(salinity)
120  , activityModel_(activityModel)
121  , liquidMixType_(thermalMixingModelLiquid)
122  , saltMixType_(thermalMixingModelSalt)
123  , co2Tables_(params)
124 {
125 }
126 
131  void initFromState(const EclipseState& eclState, const Schedule&);
132 
133  void setNumRegions(std::size_t numRegions);
134 
135  void setVapPars(const Scalar, const Scalar)
136  {
137  }
138 
139 
140  OPM_HOST_DEVICE static constexpr bool isActive()
141  {
142  return true;
143  }
144 
148  void setReferenceDensities(unsigned regionIdx,
149  Scalar rhoRefBrine,
150  Scalar rhoRefCO2,
151  Scalar /*rhoRefWater*/);
152 
156  void initEnd()
157  {
158  }
159 
166  void setEnableDissolvedGas(bool yesno)
167  { enableDissolution_ = yesno; }
168 
175  void setEnableSaltConcentration(bool yesno)
176  { enableSaltConcentration_ = yesno; }
177 
181  void setActivityModelSalt(int activityModel);
182 
186  void setThermalMixingModel(int thermalMixingModelSalt, int thermalMixingModelLiquid);
187 
188  void setEzrokhiDenCoeff(const std::vector<EzrokhiTable>& denaqa);
189 
190  void setEzrokhiViscCoeff(const std::vector<EzrokhiTable>& viscaqa);
191 
195  unsigned numRegions() const
196  { return brineReferenceDensity_.size(); }
197 
198  OPM_HOST_DEVICE Scalar hVap(unsigned ) const{
199  return 0;
200  }
201 
205  template <class Evaluation>
206  OPM_HOST_DEVICE Evaluation internalEnergy(unsigned regionIdx,
207  const Evaluation& temperature,
208  const Evaluation& pressure,
209  const Evaluation& Rs,
210  const Evaluation& saltConcentration) const
211  {
212  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
213  const Evaluation salinity = salinityFromConcentration(regionIdx, temperature, pressure, saltConcentration);
214  const Evaluation xlCO2 = convertRsToXoG_(Rs,regionIdx);
215  return (liquidEnthalpyBrineCO2_(temperature,
216  pressure,
217  salinity,
218  xlCO2)
219  - pressure / density(regionIdx, temperature, pressure, Rs, salinity ));
220  }
224  template <class Evaluation>
225  OPM_HOST_DEVICE Evaluation internalEnergy(unsigned regionIdx,
226  const Evaluation& temperature,
227  const Evaluation& pressure,
228  const Evaluation& Rs) const
229  {
230  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
231  const Evaluation xlCO2 = convertRsToXoG_(Rs,regionIdx);
232  return (liquidEnthalpyBrineCO2_(temperature,
233  pressure,
234  Evaluation(salinity_[regionIdx]),
235  xlCO2)
236  - pressure / density(regionIdx, temperature, pressure, Rs, Evaluation(salinity_[regionIdx])));
237  }
238 
242  template <class Evaluation>
243  OPM_HOST_DEVICE Evaluation viscosity(unsigned regionIdx,
244  const Evaluation& temperature,
245  const Evaluation& pressure,
246  const Evaluation& /*Rs*/) const
247  {
248  //TODO: The viscosity does not yet depend on the composition
249  return saturatedViscosity(regionIdx, temperature, pressure);
250  }
251 
255  template <class Evaluation>
256  OPM_HOST_DEVICE Evaluation saturatedViscosity(unsigned regionIdx,
257  const Evaluation& temperature,
258  const Evaluation& pressure,
259  const Evaluation& saltConcentration) const
260  {
261  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
262  const Evaluation salinity = salinityFromConcentration(regionIdx, temperature, pressure, saltConcentration);
263  if (enableEzrokhiViscosity_) {
264  const Evaluation& mu_pure = H2O::liquidViscosity(temperature, pressure, extrapolate);
265  const Evaluation& nacl_exponent = ezrokhiExponent_(temperature, ezrokhiViscNaClCoeff_);
266  return mu_pure * pow(10.0, nacl_exponent * salinity);
267  }
268  else {
269  return Brine::liquidViscosity(temperature, pressure, salinity);
270  }
271  }
272 
276  template <class Evaluation>
277  OPM_HOST_DEVICE Evaluation viscosity(unsigned regionIdx,
278  const Evaluation& temperature,
279  const Evaluation& pressure,
280  const Evaluation& /*Rsw*/,
281  const Evaluation& saltConcentration) const
282  {
283  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
284  //TODO: The viscosity does not yet depend on the composition
285  return saturatedViscosity(regionIdx, temperature, pressure, saltConcentration);
286  }
287 
291  template <class Evaluation>
292  OPM_HOST_DEVICE Evaluation saturatedViscosity(unsigned regionIdx,
293  const Evaluation& temperature,
294  const Evaluation& pressure) const
295  {
296  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
297  if (enableEzrokhiViscosity_) {
298  const Evaluation& mu_pure = H2O::liquidViscosity(temperature, pressure, extrapolate);
299  const Evaluation& nacl_exponent = ezrokhiExponent_(temperature, ezrokhiViscNaClCoeff_);
300  return mu_pure * pow(10.0, nacl_exponent * Evaluation(salinity_[regionIdx]));
301  }
302  else {
303  return Brine::liquidViscosity(temperature, pressure, Evaluation(salinity_[regionIdx]));
304  }
305 
306  }
307 
308 
312  template <class Evaluation>
313  OPM_HOST_DEVICE Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx,
314  const Evaluation& temperature,
315  const Evaluation& pressure,
316  const Evaluation& saltconcentration) const
317  {
318  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
319  const Evaluation salinity = salinityFromConcentration(regionIdx, temperature,
320  pressure, saltconcentration);
321  Evaluation rs_sat = rsSat(regionIdx, temperature, pressure, salinity);
322  return (1.0 - convertRsToXoG_(rs_sat,regionIdx)) * density(regionIdx, temperature,
323  pressure, rs_sat, salinity)
324  / brineReferenceDensity_[regionIdx];
325  }
329  template <class Evaluation>
330  OPM_HOST_DEVICE Evaluation inverseFormationVolumeFactor(unsigned regionIdx,
331  const Evaluation& temperature,
332  const Evaluation& pressure,
333  const Evaluation& Rs,
334  const Evaluation& saltConcentration) const
335  {
336  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
337  const Evaluation salinity = salinityFromConcentration(regionIdx, temperature,
338  pressure, saltConcentration);
339  return (1.0 - convertRsToXoG_(Rs,regionIdx)) * density(regionIdx, temperature,
340  pressure, Rs, salinity)
341  / brineReferenceDensity_[regionIdx];
342  }
346  template <class Evaluation>
347  OPM_HOST_DEVICE Evaluation inverseFormationVolumeFactor(unsigned regionIdx,
348  const Evaluation& temperature,
349  const Evaluation& pressure,
350  const Evaluation& Rs) const
351  {
352  return (1.0 - convertRsToXoG_(Rs,regionIdx)) * density(regionIdx, temperature, pressure,
353  Rs, Evaluation(salinity_[regionIdx]))
354  / brineReferenceDensity_[regionIdx];
355  }
356 
360  template <class FluidState, class LhsEval = typename FluidState::ValueType>
361  std::pair<LhsEval, LhsEval>
362  inverseFormationVolumeFactorAndViscosity(const FluidState& fluidState, unsigned regionIdx)
363  {
364  // Deal with the possibility that we are in a two-phase CO2STORE with OIL and GAS as phases.
365  const bool waterIsActive = fluidState.phaseIsActive(FluidState::waterPhaseIdx);
366  const int myPhaseIdx = waterIsActive ? FluidState::waterPhaseIdx : FluidState::oilPhaseIdx;
367  const LhsEval& Rsw = waterIsActive ? decay<LhsEval>(fluidState.Rsw()) : decay<LhsEval>(fluidState.Rs());
368 
369  const LhsEval& T = decay<LhsEval>(fluidState.temperature(myPhaseIdx));
370  const LhsEval& p = decay<LhsEval>(fluidState.pressure(myPhaseIdx));
371  const LhsEval& saltConcentration
372  = BlackOil::template getSaltConcentration_<FluidState, LhsEval>(fluidState, regionIdx);
373  // TODO: The viscosity does not yet depend on the composition
374  return { this->inverseFormationVolumeFactor(regionIdx, T, p, Rsw, saltConcentration) ,
375  this->saturatedViscosity(regionIdx, T, p, saltConcentration) };
376  }
377 
381  template <class Evaluation>
382  OPM_HOST_DEVICE Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx,
383  const Evaluation& temperature,
384  const Evaluation& pressure) const
385  {
386  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
387  Evaluation rs_sat = rsSat(regionIdx, temperature, pressure, Evaluation(salinity_[regionIdx]));
388  return (1.0 - convertRsToXoG_(rs_sat,regionIdx)) * density(regionIdx, temperature, pressure,
389  rs_sat, Evaluation(salinity_[regionIdx]))
390  / brineReferenceDensity_[regionIdx];
391  }
392 
399  template <class Evaluation>
400  OPM_HOST_DEVICE Evaluation saturationPressure(unsigned /*regionIdx*/,
401  const Evaluation& /*temperature*/,
402  const Evaluation& /*Rs*/) const
403  {
404 #if OPM_IS_INSIDE_DEVICE_FUNCTION
405  assert(false && "Requested the saturation pressure for the brine-co2 pvt module. Not yet implemented.");
406 #else
407  throw std::runtime_error("Requested the saturation pressure for the brine-co2 pvt module. "
408  "Not yet implemented.");
409 #endif
410  }
411 
418  template <class Evaluation>
419  OPM_HOST_DEVICE Evaluation saturationPressure(unsigned /*regionIdx*/,
420  const Evaluation& /*temperature*/,
421  const Evaluation& /*Rs*/,
422  const Evaluation& /*saltConcentration*/) const
423  {
424 #if OPM_IS_INSIDE_DEVICE_FUNCTION
425  assert(false && "Requested the saturation pressure for the brine-co2 pvt module. Not yet implemented.");
426 #else
427  throw std::runtime_error("Requested the saturation pressure for the brine-co2 pvt module. "
428  "Not yet implemented.");
429 #endif
430  }
431 
435  template <class Evaluation>
436  OPM_HOST_DEVICE Evaluation saturatedGasDissolutionFactor(unsigned regionIdx,
437  const Evaluation& temperature,
438  const Evaluation& pressure,
439  const Evaluation& /*oilSaturation*/,
440  const Evaluation& /*maxOilSaturation*/) const
441  {
442  //TODO support VAPPARS
443  return rsSat(regionIdx, temperature, pressure, Evaluation(salinity_[regionIdx]));
444  }
445 
449  template <class Evaluation>
450  OPM_HOST_DEVICE Evaluation saturatedGasDissolutionFactor(unsigned regionIdx,
451  const Evaluation& temperature,
452  const Evaluation& pressure,
453  const Evaluation& saltConcentration) const
454  {
455  const Evaluation salinity = salinityFromConcentration(regionIdx, temperature,
456  pressure, saltConcentration);
457  return rsSat(regionIdx, temperature, pressure, salinity);
458  }
459 
463  template <class Evaluation>
464  OPM_HOST_DEVICE Evaluation saturatedGasDissolutionFactor(unsigned regionIdx,
465  const Evaluation& temperature,
466  const Evaluation& pressure) const
467  {
468  return rsSat(regionIdx, temperature, pressure, Evaluation(salinity_[regionIdx]));
469  }
470 
471  OPM_HOST_DEVICE Scalar oilReferenceDensity(unsigned regionIdx) const
472  { return brineReferenceDensity_[regionIdx]; }
473 
474  OPM_HOST_DEVICE Scalar waterReferenceDensity(unsigned regionIdx) const
475  { return brineReferenceDensity_[regionIdx]; }
476 
477  OPM_HOST_DEVICE Scalar gasReferenceDensity(unsigned regionIdx) const
478  { return co2ReferenceDensity_[regionIdx]; }
479 
480  OPM_HOST_DEVICE Scalar salinity(unsigned regionIdx) const
481  { return salinity_[regionIdx]; }
482 
483  OPM_HOST_DEVICE const ContainerT& getBrineReferenceDensity() const
484  { return brineReferenceDensity_; }
485 
486  OPM_HOST_DEVICE const ContainerT& getCo2ReferenceDensity() const
487  { return co2ReferenceDensity_; }
488 
489  OPM_HOST_DEVICE const ContainerT& getSalinity() const
490  { return salinity_; }
491 
492  OPM_HOST_DEVICE const Params& getParams() const
493  { return co2Tables_; }
494 
495  OPM_HOST_DEVICE Co2StoreConfig::SaltMixingType getThermalMixingModelSalt() const
496  { return saltMixType_; }
497 
498  OPM_HOST_DEVICE Co2StoreConfig::LiquidMixingType getThermalMixingModelLiquid() const
499  { return liquidMixType_; }
500 
501  OPM_HOST_DEVICE int getActivityModel() const
502  { return activityModel_; }
503 
504  template <class Evaluation>
505  OPM_HOST_DEVICE Evaluation diffusionCoefficient(const Evaluation& temperature,
506  const Evaluation& pressure,
507  unsigned /*compIdx*/,
508  unsigned regionIdx = 0) const
509  {
510  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
511  // Diffusion coefficient of CO2 in pure water according to
512  // (McLachlan and Danckwerts, 1972)
513  const Evaluation log_D_H20 = -4.1764 + 712.52 / temperature
514  -2.5907e5 / (temperature * temperature);
515 
516  // Diffusion coefficient of CO2 in the brine phase modified following
517  // (Ratcliff and Holdcroft,1963 and Al-Rawajfeh, 2004)
518 
519  // Water viscosity
520  const Evaluation& mu_H20 = H2O::liquidViscosity(temperature, pressure, extrapolate);
521  Evaluation mu_Brine;
522  if (enableEzrokhiViscosity_) {
523  const Evaluation& nacl_exponent = ezrokhiExponent_(temperature,
524  ezrokhiViscNaClCoeff_);
525  mu_Brine = mu_H20 * pow(10.0, nacl_exponent * Evaluation(salinity_[regionIdx]));
526  }
527  else {
528  // Brine viscosity
529  mu_Brine = Brine::liquidViscosity(temperature, pressure, Evaluation(salinity_[regionIdx]));
530  }
531  const Evaluation log_D_Brine = log_D_H20 - 0.87*log10(mu_Brine / mu_H20);
532 
533  return pow(Evaluation(10), log_D_Brine) * 1e-4; // convert from cm2/s to m2/s
534  }
535 
536  template <class Evaluation>
537  OPM_HOST_DEVICE Evaluation density(unsigned regionIdx,
538  const Evaluation& temperature,
539  const Evaluation& pressure,
540  const Evaluation& Rs,
541  const Evaluation& salinity) const
542  {
543  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
544  Evaluation xlCO2 = convertXoGToxoG_(convertRsToXoG_(Rs,regionIdx), salinity);
545  Evaluation result = liquidDensity_(temperature,
546  pressure,
547  xlCO2,
548  salinity);
549 
550  Valgrind::CheckDefined(result);
551  return result;
552  }
553 
554  template <class Evaluation>
555  OPM_HOST_DEVICE Evaluation rsSat(unsigned regionIdx,
556  const Evaluation& temperature,
557  const Evaluation& pressure,
558  const Evaluation& salinity) const
559  {
560  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
561  if (!enableDissolution_) {
562  return 0.0;
563  }
564 
565  // calulate the equilibrium composition for the given
566  // temperature and pressure.
567  Evaluation xgH2O;
568  Evaluation xlCO2;
570  temperature,
571  pressure,
572  salinity,
573  /*knownPhaseIdx=*/-1,
574  xlCO2,
575  xgH2O,
576  activityModel_,
577  extrapolate);
578 
579  // normalize the phase compositions
580  xlCO2 = max(0.0, min(1.0, xlCO2));
581 
582  return convertXoGToRs(convertxoGToXoG(xlCO2, salinity), regionIdx);
583  }
584 
585 private:
586  template <class LhsEval>
587  OPM_HOST_DEVICE LhsEval ezrokhiExponent_(const LhsEval& temperature,
588  const ContainerT& ezrokhiCoeff) const
589  {
590  const LhsEval& tempC = temperature - 273.15;
591  return ezrokhiCoeff[0] + tempC * (ezrokhiCoeff[1] + ezrokhiCoeff[2] * tempC);
592  }
593 
594  template <class LhsEval>
595  OPM_HOST_DEVICE LhsEval liquidDensity_(const LhsEval& T,
596  const LhsEval& pl,
597  const LhsEval& xlCO2,
598  const LhsEval& salinity) const
599  {
600  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
601  Valgrind::CheckDefined(T);
602  Valgrind::CheckDefined(pl);
603  Valgrind::CheckDefined(xlCO2);
604 
605  if (!extrapolate && T < 273.15) {
606 #if OPM_IS_INSIDE_DEVICE_FUNCTION
607  assert(false && "Liquid density for Brine and CO2 is only defined above 273.15K");
608 #else
609  const std::string msg =
610  "Liquid density for Brine and CO2 is only "
611  "defined above 273.15K (is " +
612  std::to_string(getValue(T)) + "K)";
613  throw NumericalProblem(msg);
614 #endif
615  }
616  if (!extrapolate && pl >= 2.5e8) {
617 #if OPM_IS_INSIDE_DEVICE_FUNCTION
618  assert(false && "Liquid density for Brine and CO2 is only defined below 250MPa");
619 #else
620  const std::string msg =
621  "Liquid density for Brine and CO2 is only "
622  "defined below 250MPa (is " +
623  std::to_string(getValue(pl)) + "Pa)";
624  throw NumericalProblem(msg);
625 #endif
626  }
627 
628  const LhsEval& rho_pure = H2O::liquidDensity(T, pl, extrapolate);
629  if (enableEzrokhiDensity_) {
630  const LhsEval& nacl_exponent = ezrokhiExponent_(T, ezrokhiDenNaClCoeff_);
631  const LhsEval& co2_exponent = ezrokhiExponent_(T, ezrokhiDenCo2Coeff_);
632  const LhsEval& XCO2 = convertxoGToXoG(xlCO2, salinity);
633  return rho_pure * pow(10.0, nacl_exponent * salinity + co2_exponent * XCO2);
634  }
635  else {
636  const LhsEval& rho_brine = Brine::liquidDensity(T, pl, salinity, rho_pure);
637  const LhsEval& rho_lCO2 = liquidDensityWaterCO2_(T, xlCO2, rho_pure);
638  const LhsEval& contribCO2 = rho_lCO2 - rho_pure;
639  return rho_brine + contribCO2;
640  }
641  }
642 
643  template <class LhsEval>
644  OPM_HOST_DEVICE LhsEval liquidDensityWaterCO2_(const LhsEval& temperature,
645  const LhsEval& xlCO2,
646  const LhsEval& rho_pure) const
647  {
648  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
649  Scalar M_CO2 = CO2::molarMass();
650  Scalar M_H2O = H2O::molarMass();
651 
652  const LhsEval& tempC = temperature - 273.15; /* tempC : temperature in °C */
653  // calculate the mole fraction of CO2 in the liquid. note that xlH2O is available
654  // as a function parameter, but in the case of a pure gas phase the value of M_T
655  // for the virtual liquid phase can become very large
656  const LhsEval xlH2O = 1.0 - xlCO2;
657  const LhsEval& M_T = M_H2O * xlH2O + M_CO2 * xlCO2;
658  const LhsEval& V_phi =
659  (37.51 +
660  tempC*(-9.585e-2 +
661  tempC*(8.74e-4 -
662  tempC*5.044e-7))) / 1.0e6;
663  return 1 / (xlCO2 * V_phi/M_T + M_H2O * xlH2O / (rho_pure * M_T));
664  }
665 
670  template <class LhsEval>
671  OPM_HOST_DEVICE LhsEval convertRsToXoG_(const LhsEval& Rs, unsigned regionIdx) const
672  {
673  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
674  Scalar rho_oRef = brineReferenceDensity_[regionIdx];
675  Scalar rho_gRef = co2ReferenceDensity_[regionIdx];
676 
677  const LhsEval& rho_oG = Rs*rho_gRef;
678  return rho_oG/(rho_oRef + rho_oG);
679  }
680 
684  template <class LhsEval>
685  OPM_HOST_DEVICE LhsEval convertXoGToxoG_(const LhsEval& XoG, const LhsEval& salinity) const
686  {
687  OPM_TIMEFUNCTION_LOCAL(Subsystem::PvtProps);
688  Scalar M_CO2 = CO2::molarMass();
689  LhsEval M_Brine = Brine::molarMass(salinity);
690  return XoG*M_Brine / (M_CO2*(1 - XoG) + XoG*M_Brine);
691  }
692 
696  template <class LhsEval>
697  OPM_HOST_DEVICE LhsEval convertxoGToXoG(const LhsEval& xoG, const LhsEval& salinity) const
698  {
699  OPM_TIMEBLOCK_LOCAL(convertxoGToXoG, Subsystem::PvtProps);
700  Scalar M_CO2 = CO2::molarMass();
701  LhsEval M_Brine = Brine::molarMass(salinity);
702 
703  return xoG*M_CO2 / (xoG*(M_CO2 - M_Brine) + M_Brine);
704  }
705 
710  template <class LhsEval>
711  OPM_HOST_DEVICE LhsEval convertXoGToRs(const LhsEval& XoG, unsigned regionIdx) const
712  {
713  Scalar rho_oRef = brineReferenceDensity_[regionIdx];
714  Scalar rho_gRef = co2ReferenceDensity_[regionIdx];
715 
716  return XoG/(1.0 - XoG)*(rho_oRef/rho_gRef);
717  }
718 
719  template <class LhsEval>
720  OPM_HOST_DEVICE LhsEval liquidEnthalpyBrineCO2_(const LhsEval& T,
721  const LhsEval& p,
722  const LhsEval& salinity,
723  const LhsEval& X_CO2_w) const
724  {
725  if (liquidMixType_ == Co2StoreConfig::LiquidMixingType::NONE
726  && saltMixType_ == Co2StoreConfig::SaltMixingType::NONE)
727  {
728  return H2O::liquidEnthalpy(T, p);
729  }
730 
731  LhsEval hw = H2O::liquidEnthalpy(T, p) /1E3; /* kJ/kg */
732  LhsEval h_ls1 = hw;
733  // Use mixing model for salt by MICHAELIDES
734  if (saltMixType_ == Co2StoreConfig::SaltMixingType::MICHAELIDES) {
735 
736  /* X_CO2_w : mass fraction of CO2 in brine */
737 
738  /* same function as enthalpy_brine, only extended by CO2 content */
739 
740  /*Numerical coefficents from PALLISER*/
741  static constexpr Scalar f[] = {
742  2.63500E-1, 7.48368E-6, 1.44611E-6, -3.80860E-10
743  };
744 
745  /*Numerical coefficents from MICHAELIDES for the enthalpy of brine*/
746  static constexpr Scalar a[4][3] = {
747  { 9633.6, -4080.0, +286.49 },
748  { +166.58, +68.577, -4.6856 },
749  { -0.90963, -0.36524, +0.249667E-1 },
750  { +0.17965E-2, +0.71924E-3, -0.4900E-4 }
751  };
752 
753  LhsEval theta, h_NaCl;
754  LhsEval d_h, delta_h;
755 
756  theta = T - 273.15;
757 
758  // Regularization
759  Scalar scalarTheta = scalarValue(theta);
760  Scalar S_lSAT = f[0] + scalarTheta*(f[1] + scalarTheta*(f[2] + scalarTheta*f[3]));
761 
762  LhsEval S = salinity;
763  if (S > S_lSAT)
764  S = S_lSAT;
765 
766  /*DAUBERT and DANNER*/
767  /*U=*/h_NaCl = (3.6710E4*T + 0.5*(6.2770E1)*T*T - ((6.6670E-2)/3)*T*T*T
768  +((2.8000E-5)/4)*(T*T*T*T))/(58.44E3)- 2.045698e+02; /* kJ/kg */
769 
770  LhsEval m = 1E3 / 58.44 * S / (1 - S);
771  d_h = 0;
772 
773  for (int i = 0; i <=3; ++i) {
774  for (int j = 0; j <= 2; ++j) {
775  d_h += a[i][j] * pow(theta, static_cast<Scalar>(i)) * pow(m, j);
776  }
777  }
778  /* heat of dissolution for halite according to Michaelides 1971 */
779  delta_h = (4.184/(1E3 + (58.44 * m)))*d_h;
780 
781  /* Enthalpy of brine without CO2 */
782  h_ls1 =(1-S)*hw + S*h_NaCl + S*delta_h; /* kJ/kg */
783 
784  // Use Enthalpy of brine without CO2
785  if (liquidMixType_ == Co2StoreConfig::LiquidMixingType::NONE) {
786  return h_ls1*1E3;
787  }
788  }
789 
790  LhsEval delta_hCO2, hg;
791  /* heat of dissolution for CO2 according to Fig. 6 in Duan and Sun 2003. (kJ/kg)
792  In the relevant temperature ranges CO2 dissolution is
793  exothermal */
794  if (liquidMixType_ == Co2StoreConfig::LiquidMixingType::DUANSUN) {
795  delta_hCO2 = (-57.4375 + T * 0.1325) * 1000/44;
796  }
797  else {
798  delta_hCO2 = 0.0;
799  }
800 
801  /* enthalpy contribution of CO2 (kJ/kg) */
802  hg = CO2::gasEnthalpy(co2Tables_, T, p, extrapolate)/1E3 + delta_hCO2;
803 
804  /* Enthalpy of brine with dissolved CO2 */
805  return (h_ls1 - X_CO2_w*hw + hg*X_CO2_w)*1E3; /*J/kg*/
806  }
807 
808  template <class LhsEval>
809  OPM_HOST_DEVICE const LhsEval salinityFromConcentration(unsigned regionIdx,
810  const LhsEval&T,
811  const LhsEval& P,
812  const LhsEval& saltConcentration) const
813  {
814  if (enableSaltConcentration_) {
815  // Convert concentration [kg/m³] to mass fraction [kg_salt/kg_solution].
816  // First approximation using pure water density
817  const LhsEval rho_w = H2O::liquidDensity(T, P, true);
818  const LhsEval S_approx = saltConcentration / rho_w;
819  // Improved estimate using Batzle-Wang brine density
820  const LhsEval rho_brine = Brine::liquidDensity(T, P, S_approx, rho_w);
821  return saltConcentration / rho_brine;
822  }
823 
824  return salinity(regionIdx);
825  }
826 
827  #if HAVE_CUDA
828  template <class ScalarT>
829  friend BrineCo2Pvt<ScalarT, gpuistl::GpuView>
830  gpuistl::make_view(BrineCo2Pvt<ScalarT, gpuistl::GpuBuffer>&);
831  #endif
832 
833  ContainerT brineReferenceDensity_{};
834  ContainerT co2ReferenceDensity_{};
835  ContainerT salinity_{};
836  ContainerT ezrokhiDenNaClCoeff_{};
837  ContainerT ezrokhiDenCo2Coeff_{};
838  ContainerT ezrokhiViscNaClCoeff_{};
839  bool enableEzrokhiDensity_ = false;
840  bool enableEzrokhiViscosity_ = false;
841  bool enableDissolution_ = true;
842  bool enableSaltConcentration_ = false;
843  int activityModel_{};
844  Co2StoreConfig::LiquidMixingType liquidMixType_{};
845  Co2StoreConfig::SaltMixingType saltMixType_{};
846  Params co2Tables_;
847 };
848 
849 } // namespace Opm
850 
851 #if HAVE_CUDA
852 namespace Opm::gpuistl
853 {
854 
855  template<class ScalarT>
856  BrineCo2Pvt<ScalarT, GpuBuffer>
857  copy_to_gpu(const BrineCo2Pvt<ScalarT>& cpuBrineCo2)
858  {
859  return BrineCo2Pvt<ScalarT, GpuBuffer>(
860  GpuBuffer<ScalarT>(cpuBrineCo2.getBrineReferenceDensity()),
861  GpuBuffer<ScalarT>(cpuBrineCo2.getCo2ReferenceDensity()),
862  GpuBuffer<ScalarT>(cpuBrineCo2.getSalinity()),
863  cpuBrineCo2.getActivityModel(),
864  cpuBrineCo2.getThermalMixingModelSalt(),
865  cpuBrineCo2.getThermalMixingModelLiquid(),
866  copy_to_gpu(cpuBrineCo2.getParams())
867  );
868  }
869 
870  template <class ScalarT>
871  BrineCo2Pvt<ScalarT, GpuView>
872  make_view(BrineCo2Pvt<ScalarT, GpuBuffer>& brineCo2Pvt)
873  {
874 
875  using ContainedType = ScalarT;
876 
877  auto newBrineReferenceDensity = make_view<ContainedType>(brineCo2Pvt.brineReferenceDensity_);
878  auto newGasReferenceDensity = make_view<ContainedType>(brineCo2Pvt.co2ReferenceDensity_);
879  auto newSalinity = make_view<ContainedType>(brineCo2Pvt.salinity_);
880 
881  return BrineCo2Pvt<ScalarT, GpuView>(
882  newBrineReferenceDensity,
883  newGasReferenceDensity,
884  newSalinity,
885  brineCo2Pvt.getActivityModel(),
886  brineCo2Pvt.getThermalMixingModelSalt(),
887  brineCo2Pvt.getThermalMixingModelLiquid(),
888  make_view(brineCo2Pvt.co2Tables_)
889  );
890  }
891 } // namespace Opm::gpuistl
892 #endif // HAVE_CUDA
893 
894 #endif
Material properties of pure water .
Definition: H2O.hpp:64
This class represents the Pressure-Volume-Temperature relations of the liquid phase for a CO2-Brine s...
Definition: BrineCo2Pvt.hpp:63
static OPM_HOST_DEVICE Scalar molarMass()
The mass in [kg] of one mole of CO2.
Definition: CO2.hpp:73
OPM_HOST_DEVICE Evaluation viscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition: BrineCo2Pvt.hpp:243
A class for the brine fluid properties.
Definition: BrineDynamic.hpp:48
void initFromState(const EclipseState &eclState, const Schedule &)
Initialize the parameters for Brine-CO2 system using an ECL deck.
Definition: BrineCo2Pvt.cpp:67
A class for the CO2 fluid properties.
unsigned numRegions() const
Return the number of PVT regions which are considered by this PVT-object.
Definition: BrineCo2Pvt.hpp:195
OPM_HOST_DEVICE Evaluation saturationPressure(unsigned, const Evaluation &, const Evaluation &) const
Returns the saturation pressure of the brine phase [Pa] depending on its mass fraction of the gas com...
Definition: BrineCo2Pvt.hpp:400
static OPM_HOST_DEVICE Evaluation liquidViscosity(const Evaluation &temperature, const Evaluation &pressure, bool extrapolate)
The dynamic viscosity of pure water.
Definition: SimpleHuDuanH2O.hpp:361
static OPM_HOST_DEVICE Evaluation gasEnthalpy(const Params &params, const Evaluation &temperature, const Evaluation &pressure, bool extrapolate=false)
Specific enthalpy of gaseous CO2 [J/kg].
Definition: CO2.hpp:171
Definition: Schedule.hpp:100
static OPM_HOST_DEVICE Evaluation liquidEnthalpy(const Evaluation &temperature, const Evaluation &)
Specific enthalpy of liquid water .
Definition: SimpleHuDuanH2O.hpp:202
static OPM_HOST_DEVICE Scalar molarMass()
The molar mass in of water.
Definition: SimpleHuDuanH2O.hpp:103
OPM_HOST_DEVICE Evaluation inverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rs, const Evaluation &saltConcentration) const
Returns the formation volume factor [-] of the fluid phase.
Definition: BrineCo2Pvt.hpp:330
Provides the OPM specific exception classes.
static OPM_HOST_DEVICE Evaluation liquidViscosity(const Evaluation &temperature, const Evaluation &, const Evaluation &salinity)
The dynamic liquid viscosity of the pure component.
Definition: BrineDynamic.hpp:385
void setThermalMixingModel(int thermalMixingModelSalt, int thermalMixingModelLiquid)
Set thermal mixing model for co2 in brine.
Definition: BrineCo2Pvt.cpp:183
static OPM_HOST_DEVICE Evaluation liquidDensity(const Evaluation &temperature, const Evaluation &pressure, bool extrapolate)
The density of pure water at a given pressure and temperature .
Definition: SimpleHuDuanH2O.hpp:316
PiecewiseLinearTwoPhaseMaterialParams< TraitsT, ViewType > make_view(PiecewiseLinearTwoPhaseMaterialParams< TraitsT, ContainerType > &params)
this function is intented to make a GPU friendly view of the PiecewiseLinearTwoPhaseMaterialParams ...
Definition: PiecewiseLinearTwoPhaseMaterialParams.hpp:312
A class for the brine fluid properties.
Definition: Brine.hpp:47
OPM_HOST_DEVICE Evaluation saturatedViscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the dynamic viscosity [Pa s] of oil saturated gas at given pressure.
Definition: BrineCo2Pvt.hpp:292
OPM_HOST_DEVICE Evaluation saturatedViscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &saltConcentration) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition: BrineCo2Pvt.hpp:256
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
Convience header to include the gpuistl headers if HAVE_CUDA is defined.
void setEnableSaltConcentration(bool yesno)
Specify whether the PVT model should consider salt concentration from the fluidstate or a fixed salin...
Definition: BrineCo2Pvt.hpp:175
OPM_HOST_DEVICE Evaluation saturatedGasDissolutionFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &saltConcentration) const
Returns the gas dissoluiton factor [m^3/m^3] of the liquid phase.
Definition: BrineCo2Pvt.hpp:450
Binary coefficients for water and CO2.
Binary coefficients for brine and CO2.
Definition: Brine_CO2.hpp:48
OPM_HOST_DEVICE Evaluation inverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rs) const
Returns the formation volume factor [-] of the fluid phase.
Definition: BrineCo2Pvt.hpp:347
OPM_HOST_DEVICE Evaluation internalEnergy(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rs) const
Returns the specific enthalpy [J/kg] of gas given a set of parameters.
Definition: BrineCo2Pvt.hpp:225
Definition: EclipseState.hpp:66
OPM_HOST_DEVICE Evaluation saturatedGasDissolutionFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns thegas dissoluiton factor [m^3/m^3] of the liquid phase.
Definition: BrineCo2Pvt.hpp:464
void setReferenceDensities(unsigned regionIdx, Scalar rhoRefBrine, Scalar rhoRefCO2, Scalar)
Initialize the reference densities of all fluids for a given PVT region.
Definition: BrineCo2Pvt.cpp:160
A class for the CO2 fluid properties.
Definition: CO2.hpp:57
OPM_HOST_DEVICE Evaluation saturatedGasDissolutionFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &, const Evaluation &) const
Returns the gas dissoluiton factor [m^3/m^3] of the liquid phase.
Definition: BrineCo2Pvt.hpp:436
A simple version of pure water with density from Hu et al.
std::pair< LhsEval, LhsEval > inverseFormationVolumeFactorAndViscosity(const FluidState &fluidState, unsigned regionIdx)
Returns the formation volume factor [-] and viscosity [Pa s] of the fluid phase.
Definition: BrineCo2Pvt.hpp:362
Implements a scalar function that depends on two variables and which is sampled on an uniform X-Y gri...
A simple version of pure water with density from Hu et al.
Definition: SimpleHuDuanH2O.hpp:65
A class for the brine fluid properties.
static OPM_HOST_DEVICE void calculateMoleFractions(const CO2Params &params, const Evaluation &temperature, const Evaluation &pg, const Evaluation &salinity, const int knownPhaseIdx, Evaluation &xlCO2, Evaluation &ygH2O, const int &activityModel, bool extrapolate=false)
Returns the mol (!) fraction of CO2 in the liquid phase and the mol_ (!) fraction of H2O in the gas p...
Definition: Brine_CO2.hpp:113
A generic class which tabulates all thermodynamic properties of a given component.
static OPM_HOST_DEVICE Evaluation liquidDensity(const Evaluation &temperature, const Evaluation &pressure, const Evaluation &salinity, bool extrapolate=false)
The density of the liquid component at a given pressure in and temperature in . ...
Definition: BrineDynamic.hpp:283
void initEnd()
Finish initializing the oil phase PVT properties.
Definition: BrineCo2Pvt.hpp:156
PiecewiseLinearTwoPhaseMaterialParams< TraitsT, GPUContainerType > copy_to_gpu(const PiecewiseLinearTwoPhaseMaterialParams< TraitsT > &params)
Move a PiecewiseLinearTwoPhaseMaterialParams-object to the GPU.
Definition: PiecewiseLinearTwoPhaseMaterialParams.hpp:285
Definition: PiecewiseLinearTwoPhaseMaterialParams.hpp:47
OPM_HOST_DEVICE Evaluation internalEnergy(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &Rs, const Evaluation &saltConcentration) const
Returns the specific enthalpy [J/kg] of gas given a set of parameters.
Definition: BrineCo2Pvt.hpp:206
Binary coefficients for brine and CO2.
static Scalar molarMass()
The molar mass in of the component.
Definition: Component.hpp:93
OPM_HOST_DEVICE Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &saltconcentration) const
Returns the formation volume factor [-] of the fluid phase.
Definition: BrineCo2Pvt.hpp:313
OPM_HOST_DEVICE Evaluation saturationPressure(unsigned, const Evaluation &, const Evaluation &, const Evaluation &) const
Returns the saturation pressure of the brine phase [Pa] depending on its mass fraction of the gas com...
Definition: BrineCo2Pvt.hpp:419
OPM_HOST_DEVICE Evaluation saturatedInverseFormationVolumeFactor(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure) const
Returns the formation volume factor [-] of brine saturated with CO2 at a given pressure.
Definition: BrineCo2Pvt.hpp:382
OPM_HOST_DEVICE Evaluation viscosity(unsigned regionIdx, const Evaluation &temperature, const Evaluation &pressure, const Evaluation &, const Evaluation &saltConcentration) const
Returns the dynamic viscosity [Pa s] of the fluid phase given a set of parameters.
Definition: BrineCo2Pvt.hpp:277
void setEnableDissolvedGas(bool yesno)
Specify whether the PVT model should consider that the CO2 component can dissolve in the brine phase...
Definition: BrineCo2Pvt.hpp:166
void setActivityModelSalt(int activityModel)
Set activity coefficient model for salt in solubility model.
Definition: BrineCo2Pvt.cpp:171