opm-common
Loading...
Searching...
No Matches
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
54namespace Opm {
55
56class EclipseState;
57class Schedule;
58class Co2StoreConfig;
59class EzrokhiTable;
60
61// forward declaration of the class so the function in the next namespace can be declared
62template <class Scalar, template <class> class Storage>
63class BrineCo2Pvt;
64
65#if HAVE_CUDA
66// declaration of make_view in correct namespace so friend function can be declared in the class
67namespace gpuistl {
68 template <class ScalarT>
69 BrineCo2Pvt<ScalarT, GpuView>
70 make_view(BrineCo2Pvt<ScalarT, GpuBuffer>&);
71}
72#endif
73
78template <class Scalar, template <class> class Storage = Opm::VectorWithDefaultAllocator>
79class BrineCo2Pvt
80{
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
93public:
94 using H2O = SimpleHuDuanH2O<Scalar>;
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
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 }
221
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 }
326
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 }
343
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
585private:
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
852namespace 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
A class for the brine fluid properties.
Binary coefficients for brine and CO2.
A class for the CO2 fluid properties.
Provides the OPM specific exception classes.
Binary coefficients for water and CO2.
PiecewiseLinearTwoPhaseMaterialParams< TraitsT, GPUContainerType > copy_to_gpu(const PiecewiseLinearTwoPhaseMaterialParams< TraitsT > &params)
Move a PiecewiseLinearTwoPhaseMaterialParams-object to the GPU.
Definition PiecewiseLinearTwoPhaseMaterialParams.hpp:285
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 simple version of pure water with density from Hu et al.
A generic class which tabulates all thermodynamic properties of a given component.
Implements a scalar function that depends on two variables and which is sampled on an uniform X-Y gri...
Binary coefficients for brine and CO2.
Definition Brine_CO2.hpp:48
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
This class represents the Pressure-Volume-Temperature relations of the liquid phase for a CO2-Brine s...
Definition BrineCo2Pvt.hpp:80
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
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
void initFromState(const EclipseState &eclState, const Schedule &)
Initialize the parameters for Brine-CO2 system using an ECL deck.
Definition BrineCo2Pvt.cpp:67
void setActivityModelSalt(int activityModel)
Set activity coefficient model for salt in solubility model.
Definition BrineCo2Pvt.cpp:171
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
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 initEnd()
Finish initializing the oil phase PVT properties.
Definition BrineCo2Pvt.hpp:156
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
void setThermalMixingModel(int thermalMixingModelSalt, int thermalMixingModelLiquid)
Set thermal mixing model for co2 in brine.
Definition BrineCo2Pvt.cpp:183
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 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
BinaryCoeff::Brine_CO2< Scalar, H2O, CO2 > BinaryCoeffBrineCO2
The binary coefficients for brine and CO2 used by this fluid system.
Definition BrineCo2Pvt.hpp:99
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
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 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
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
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
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
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
unsigned numRegions() const
Return the number of PVT regions which are considered by this PVT-object.
Definition BrineCo2Pvt.hpp:195
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
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
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
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 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
A class for the brine fluid properties.
Definition BrineDynamic.hpp:49
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
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
Definition CO2Tables.hpp:63
A class for the CO2 fluid properties.
Definition CO2.hpp:58
static OPM_HOST_DEVICE Scalar molarMass()
Definition CO2.hpp:73
static OPM_HOST_DEVICE Evaluation gasEnthalpy(const Params &params, const Evaluation &temperature, const Evaluation &pressure, bool extrapolate=false)
Definition CO2.hpp:171
Definition Co2StoreConfig.hpp:33
static Scalar molarMass()
Definition Component.hpp:93
Definition EclipseState.hpp:66
Definition EzrokhiTable.hpp:57
Definition Schedule.hpp:101
A simple version of pure water with density from Hu et al.
Definition SimpleHuDuanH2O.hpp:66
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
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 Scalar molarMass()
The molar mass in of water.
Definition SimpleHuDuanH2O.hpp:103
static OPM_HOST_DEVICE Evaluation liquidEnthalpy(const Evaluation &temperature, const Evaluation &)
Specific enthalpy of liquid water .
Definition SimpleHuDuanH2O.hpp:202
Convience header to include the gpuistl headers if HAVE_CUDA is defined.
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition Exceptions.hpp:30
Scalar Brine< Scalar, H2O >::salinity
Default value for the salinity of the brine (dimensionless).
Definition Brine.hpp:391