EquilibrationHelpers.hpp
Go to the documentation of this file.
1/*
2 Copyright 2014 SINTEF ICT, Applied Mathematics.
3 Copyright 2017 IRIS
4
5 This file is part of the Open Porous Media project (OPM).
6
7 OPM is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 OPM is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with OPM. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#ifndef OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED
22#define OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED
23
24#include <opm/core/utility/linearInterpolation.hpp>
25#include <opm/core/utility/RegionMapping.hpp>
26#include <opm/core/utility/RootFinders.hpp>
27
28#include <opm/parser/eclipse/EclipseState/InitConfig/Equil.hpp>
29
30#include <opm/material/fluidsystems/BlackOilFluidSystem.hpp>
31#include <opm/material/fluidstates/SimpleModularFluidState.hpp>
32#include <opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp>
33
34#include <memory>
35
36
37/*
38---- synopsis of EquilibrationHelpers.hpp ----
39
40namespace Opm
41{
42 namespace EQUIL {
43
44 namespace Miscibility {
45 class RsFunction;
46 class NoMixing;
47 template <class FluidSystem>
48 class RsVD;
49 template <class FluidSystem>
50 class RsSatAtContact;
51 }
52
53 class EquilReg;
54
55
56 template <class FluidSystem, class MaterialLaw, class MaterialLawManager>
57 struct PcEq;
58
59 template <class FluidSystem, class MaterialLaw, class MaterialLawManager >
60 inline double satFromPc(const MaterialLawManager& materialLawManager,
61 const int phase,
62 const int cell,
63 const double target_pc,
64 const bool increasing = false)
65 template <class FluidSystem, class MaterialLaw, class MaterialLawManager>
66 inline double satFromSumOfPcs(const MaterialLawManager& materialLawManager,
67 const int phase1,
68 const int phase2,
69 const int cell,
70 const double target_pc)
71 } // namespace Equil
72} // namespace Opm
73
74---- end of synopsis of EquilibrationHelpers.hpp ----
75*/
76
77
78namespace Opm
79{
87 namespace EQUIL {
88
89
90 typedef Opm::FluidSystems::BlackOil<double> FluidSystemSimple;
91
92 // Adjust oil pressure according to gas saturation and cap pressure
93 typedef Opm::SimpleModularFluidState<double,
94 /*numPhases=*/3,
95 /*numComponents=*/3,
97 /*storePressure=*/false,
98 /*storeTemperature=*/false,
99 /*storeComposition=*/false,
100 /*storeFugacity=*/false,
101 /*storeSaturation=*/true,
102 /*storeDensity=*/false,
103 /*storeViscosity=*/false,
104 /*storeEnthalpy=*/false> SatOnlyFluidState;
105
110 namespace Miscibility {
111
116 {
117 public:
133 virtual double operator()(const double depth,
134 const double press,
135 const double temp,
136 const double sat = 0.0) const = 0;
137 };
138
139
143 class NoMixing : public RsFunction {
144 public:
161 double
162 operator()(const double /* depth */,
163 const double /* press */,
164 const double /* temp */,
165 const double /* sat */ = 0.0) const
166 {
167 return 0.0;
168 }
169 };
170
171
177 template <class FluidSystem>
178 class RsVD : public RsFunction {
179 public:
187 RsVD(const int pvtRegionIdx,
188 const std::vector<double>& depth,
189 const std::vector<double>& rs)
190 : pvtRegionIdx_(pvtRegionIdx)
191 , depth_(depth)
192 , rs_(rs)
193 {
194 }
195
211 double
212 operator()(const double depth,
213 const double press,
214 const double temp,
215 const double sat_gas = 0.0) const
216 {
217 if (sat_gas > 0.0) {
218 return satRs(press, temp);
219 } else {
220 return std::min(satRs(press, temp), linearInterpolationNoExtrapolation(depth_, rs_, depth));
221 }
222 }
223
224 private:
225 const int pvtRegionIdx_;
226 std::vector<double> depth_;
227 std::vector<double> rs_;
229 double satRs(const double press, const double temp) const
230 {
231 return FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp, press);
232 }
233 };
234
235
241 template <class FluidSystem>
242 class RvVD : public RsFunction {
243 public:
251 RvVD(const int pvtRegionIdx,
252 const std::vector<double>& depth,
253 const std::vector<double>& rv)
254 : pvtRegionIdx_(pvtRegionIdx)
255 , depth_(depth)
256 , rv_(rv)
257 {
258 }
259
275 double
276 operator()(const double depth,
277 const double press,
278 const double temp,
279 const double sat_oil = 0.0 ) const
280 {
281 if (std::abs(sat_oil) > 1e-16) {
282 return satRv(press, temp);
283 } else {
284 return std::min(satRv(press, temp), linearInterpolationNoExtrapolation(depth_, rv_, depth));
285 }
286 }
287
288 private:
289 const int pvtRegionIdx_;
290 std::vector<double> depth_;
291 std::vector<double> rv_;
293 double satRv(const double press, const double temp) const
294 {
295 return FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp, press);
296 }
297 };
298
299
314 template <class FluidSystem>
315 class RsSatAtContact : public RsFunction {
316 public:
324 RsSatAtContact(const int pvtRegionIdx, const double p_contact, const double T_contact)
325 : pvtRegionIdx_(pvtRegionIdx)
326 {
327 rs_sat_contact_ = satRs(p_contact, T_contact);
328 }
329
345 double
346 operator()(const double /* depth */,
347 const double press,
348 const double temp,
349 const double sat_gas = 0.0) const
350 {
351 if (sat_gas > 0.0) {
352 return satRs(press, temp);
353 } else {
354 return std::min(satRs(press, temp), rs_sat_contact_);
355 }
356 }
357
358 private:
359 const int pvtRegionIdx_;
360 double rs_sat_contact_;
361
362 double satRs(const double press, const double temp) const
363 {
364 return FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp, press);
365 }
366 };
367
368
383 template <class FluidSystem>
384 class RvSatAtContact : public RsFunction {
385 public:
393 RvSatAtContact(const int pvtRegionIdx, const double p_contact, const double T_contact)
394 :pvtRegionIdx_(pvtRegionIdx)
395 {
396 rv_sat_contact_ = satRv(p_contact, T_contact);
397 }
398
414 double
415 operator()(const double /*depth*/,
416 const double press,
417 const double temp,
418 const double sat_oil = 0.0) const
419 {
420 if (sat_oil > 0.0) {
421 return satRv(press, temp);
422 } else {
423 return std::min(satRv(press, temp), rv_sat_contact_);
424 }
425 }
426
427 private:
428 const int pvtRegionIdx_;
429 double rv_sat_contact_;
430
431 double satRv(const double press, const double temp) const
432 {
433 return FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp, press);;
434 }
435 };
436
437 } // namespace Miscibility
438
458 class EquilReg {
459 public:
468 EquilReg(const EquilRecord& rec,
469 std::shared_ptr<Miscibility::RsFunction> rs,
470 std::shared_ptr<Miscibility::RsFunction> rv,
471 const int pvtIdx)
472 : rec_ (rec)
473 , rs_ (rs)
474 , rv_ (rv)
475 , pvtIdx_ (pvtIdx)
476 {
477 }
478
483
488
492 double datum() const { return this->rec_.datumDepth(); }
493
497 double pressure() const { return this->rec_.datumDepthPressure(); }
498
502 double zwoc() const { return this->rec_.waterOilContactDepth(); }
503
509 double pcow_woc() const { return this->rec_.waterOilContactCapillaryPressure(); }
510
514 double zgoc() const { return this->rec_.gasOilContactDepth(); }
515
521 double pcgo_goc() const { return this->rec_.gasOilContactCapillaryPressure(); }
522
523
528 const CalcDissolution&
529 dissolutionCalculator() const { return *this->rs_; }
530
535 const CalcEvaporation&
536 evaporationCalculator() const { return *this->rv_; }
537
541 int pvtIdx() const { return this->pvtIdx_; }
542
543
544 private:
545 EquilRecord rec_;
546 std::shared_ptr<Miscibility::RsFunction> rs_;
547 std::shared_ptr<Miscibility::RsFunction> rv_;
548 const int pvtIdx_;
549 };
550
551
552
556 template <class FluidSystem, class MaterialLaw, class MaterialLawManager>
557 struct PcEq
558 {
559 PcEq(const MaterialLawManager& materialLawManager,
560 const int phase,
561 const int cell,
562 const double target_pc)
563 : materialLawManager_(materialLawManager),
564 phase_(phase),
565 cell_(cell),
566 target_pc_(target_pc)
567 {
568
569 }
570 double operator()(double s) const
571 {
572 const auto& matParams = materialLawManager_.materialLawParams(cell_);
573 SatOnlyFluidState fluidState;
574 fluidState.setSaturation(FluidSystem::waterPhaseIdx, 0.0);
575 fluidState.setSaturation(FluidSystem::oilPhaseIdx, 0.0);
576 fluidState.setSaturation(FluidSystem::gasPhaseIdx, 0.0);
577 fluidState.setSaturation(phase_, s);
578
579 double pc[FluidSystem::numPhases];
580 std::fill(pc, pc + FluidSystem::numPhases, 0.0);
581 MaterialLaw::capillaryPressures(pc, matParams, fluidState);
582 double sign = (phase_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0;
583 double pcPhase = pc[FluidSystem::oilPhaseIdx] + sign * pc[phase_];
584 return pcPhase - target_pc_;
585 }
586 private:
587 const MaterialLawManager& materialLawManager_;
588 const int phase_;
589 const int cell_;
590 const double target_pc_;
591 };
592
593 template <class FluidSystem, class MaterialLawManager>
594 double minSaturations(const MaterialLawManager& materialLawManager, const int phase, const int cell) {
595 const auto& scaledDrainageInfo =
596 materialLawManager.oilWaterScaledEpsInfoDrainage(cell);
597
598 // Find minimum and maximum saturations.
599 switch(phase) {
600 case FluidSystem::waterPhaseIdx :
601 {
602 return scaledDrainageInfo.Swl;
603 break;
604 }
605 case FluidSystem::gasPhaseIdx :
606 {
607 return scaledDrainageInfo.Sgl;
608 break;
609 }
610 case FluidSystem::oilPhaseIdx :
611 {
612 OPM_THROW(std::runtime_error, "Min saturation not implemented for oil phase.");
613 break;
614 }
615 default: OPM_THROW(std::runtime_error, "Unknown phaseIdx .");
616 }
617 return -1.0;
618 }
619
620 template <class FluidSystem, class MaterialLawManager>
621 double maxSaturations(const MaterialLawManager& materialLawManager, const int phase, const int cell) {
622 const auto& scaledDrainageInfo =
623 materialLawManager.oilWaterScaledEpsInfoDrainage(cell);
624
625 // Find minimum and maximum saturations.
626 switch(phase) {
627 case FluidSystem::waterPhaseIdx :
628 {
629 return scaledDrainageInfo.Swu;
630 break;
631 }
632 case FluidSystem::gasPhaseIdx :
633 {
634 return scaledDrainageInfo.Sgu;
635 break;
636 }
637 case FluidSystem::oilPhaseIdx :
638 {
639 OPM_THROW(std::runtime_error, "Max saturation not implemented for oil phase.");
640 break;
641 }
642 default: OPM_THROW(std::runtime_error, "Unknown phaseIdx .");
643 }
644 return -1.0;
645 }
646
647
650 template <class FluidSystem, class MaterialLaw, class MaterialLawManager >
651 inline double satFromPc(const MaterialLawManager& materialLawManager,
652 const int phase,
653 const int cell,
654 const double target_pc,
655 const bool increasing = false)
656 {
657 // Find minimum and maximum saturations.
658 const double s0 = increasing ? maxSaturations<FluidSystem>(materialLawManager, phase, cell) : minSaturations<FluidSystem>(materialLawManager, phase, cell);
659 const double s1 = increasing ? minSaturations<FluidSystem>(materialLawManager, phase, cell) : maxSaturations<FluidSystem>(materialLawManager, phase, cell);
660
661 // Create the equation f(s) = pc(s) - target_pc
662 const PcEq<FluidSystem, MaterialLaw, MaterialLawManager> f(materialLawManager, phase, cell, target_pc);
663 const double f0 = f(s0);
664 const double f1 = f(s1);
665
666 if (f0 <= 0.0) {
667 return s0;
668 } else if (f1 > 0.0) {
669 return s1;
670 } else {
671 const int max_iter = 60;
672 const double tol = 1e-6;
673 int iter_used = -1;
674 typedef RegulaFalsi<ThrowOnError> ScalarSolver;
675 const double sol = ScalarSolver::solve(f, std::min(s0, s1), std::max(s0, s1), max_iter, tol, iter_used);
676 return sol;
677 }
678 }
679
680
684 template <class FluidSystem, class MaterialLaw, class MaterialLawManager>
685 struct PcEqSum
686 {
687 PcEqSum(const MaterialLawManager& materialLawManager,
688 const int phase1,
689 const int phase2,
690 const int cell,
691 const double target_pc)
692 : materialLawManager_(materialLawManager),
693 phase1_(phase1),
694 phase2_(phase2),
695 cell_(cell),
696 target_pc_(target_pc)
697 {
698 }
699 double operator()(double s) const
700 {
701 const auto& matParams = materialLawManager_.materialLawParams(cell_);
702 SatOnlyFluidState fluidState;
703 fluidState.setSaturation(FluidSystem::waterPhaseIdx, 0.0);
704 fluidState.setSaturation(FluidSystem::oilPhaseIdx, 0.0);
705 fluidState.setSaturation(FluidSystem::gasPhaseIdx, 0.0);
706 fluidState.setSaturation(phase1_, s);
707 fluidState.setSaturation(phase2_, 1.0 - s);
708
709 double pc[FluidSystem::numPhases];
710 std::fill(pc, pc + FluidSystem::numPhases, 0.0);
711
712 MaterialLaw::capillaryPressures(pc, matParams, fluidState);
713 double sign1 = (phase1_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0;
714 double pc1 = pc[FluidSystem::oilPhaseIdx] + sign1 * pc[phase1_];
715 double sign2 = (phase2_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0;
716 double pc2 = pc[FluidSystem::oilPhaseIdx] + sign2 * pc[phase2_];
717 return pc1 + pc2 - target_pc_;
718 }
719 private:
720 const MaterialLawManager& materialLawManager_;
721 const int phase1_;
722 const int phase2_;
723 const int cell_;
724 const double target_pc_;
725 };
726
727
728
729
733 template <class FluidSystem, class MaterialLaw, class MaterialLawManager>
734 inline double satFromSumOfPcs(const MaterialLawManager& materialLawManager,
735 const int phase1,
736 const int phase2,
737 const int cell,
738 const double target_pc)
739 {
740 // Find minimum and maximum saturations.
741 const double smin = minSaturations<FluidSystem>(materialLawManager, phase1, cell);
742 const double smax = maxSaturations<FluidSystem>(materialLawManager, phase1, cell);
743
744 // Create the equation f(s) = pc1(s) + pc2(1-s) - target_pc
745 const PcEqSum<FluidSystem, MaterialLaw, MaterialLawManager> f(materialLawManager, phase1, phase2, cell, target_pc);
746 const double f0 = f(smin);
747 const double f1 = f(smax);
748 if (f0 <= 0.0) {
749 return smin;
750 } else if (f1 > 0.0) {
751 return smax;
752 } else {
753 const int max_iter = 30;
754 const double tol = 1e-6;
755 int iter_used = -1;
756 typedef RegulaFalsi<ThrowOnError> ScalarSolver;
757 const double sol = ScalarSolver::solve(f, smin, smax, max_iter, tol, iter_used);
758 return sol;
759 }
760 }
761
763 template <class FluidSystem, class MaterialLaw, class MaterialLawManager>
764 inline double satFromDepth(const MaterialLawManager& materialLawManager,
765 const double cellDepth,
766 const double contactDepth,
767 const int phase,
768 const int cell,
769 const bool increasing = false)
770 {
771 const double s0 = increasing ? maxSaturations<FluidSystem>(materialLawManager, phase, cell) : minSaturations<FluidSystem>(materialLawManager, phase, cell);
772 const double s1 = increasing ? minSaturations<FluidSystem>(materialLawManager, phase, cell) : maxSaturations<FluidSystem>(materialLawManager, phase, cell);
773
774 if (cellDepth < contactDepth){
775 return s0;
776 } else {
777 return s1;
778 }
779
780 }
781
783 template <class FluidSystem, class MaterialLaw, class MaterialLawManager>
784 inline bool isConstPc(const MaterialLawManager& materialLawManager,
785 const int phase,
786 const int cell)
787 {
788 // Create the equation f(s) = pc(s);
789 const PcEq<FluidSystem, MaterialLaw, MaterialLawManager> f(materialLawManager, phase, cell, 0);
790 const double f0 = f(minSaturations<FluidSystem>(materialLawManager, phase, cell));
791 const double f1 = f(maxSaturations<FluidSystem>(materialLawManager, phase, cell));
792 return std::abs(f0 - f1) < std::numeric_limits<double>::epsilon();
793 }
794
795 } // namespace Equil
796} // namespace Opm
797
798
799#endif // OPM_EQUILIBRATIONHELPERS_HEADER_INCLUDED
Definition: EquilibrationHelpers.hpp:458
EquilReg(const EquilRecord &rec, std::shared_ptr< Miscibility::RsFunction > rs, std::shared_ptr< Miscibility::RsFunction > rv, const int pvtIdx)
Definition: EquilibrationHelpers.hpp:468
double pcgo_goc() const
Definition: EquilibrationHelpers.hpp:521
double datum() const
Definition: EquilibrationHelpers.hpp:492
double zgoc() const
Definition: EquilibrationHelpers.hpp:514
double pcow_woc() const
Definition: EquilibrationHelpers.hpp:509
Miscibility::RsFunction CalcDissolution
Definition: EquilibrationHelpers.hpp:482
double zwoc() const
Definition: EquilibrationHelpers.hpp:502
Miscibility::RsFunction CalcEvaporation
Definition: EquilibrationHelpers.hpp:487
double pressure() const
Definition: EquilibrationHelpers.hpp:497
int pvtIdx() const
Definition: EquilibrationHelpers.hpp:541
const CalcEvaporation & evaporationCalculator() const
Definition: EquilibrationHelpers.hpp:536
const CalcDissolution & dissolutionCalculator() const
Definition: EquilibrationHelpers.hpp:529
Definition: EquilibrationHelpers.hpp:143
double operator()(const double, const double, const double, const double=0.0) const
Definition: EquilibrationHelpers.hpp:162
Definition: EquilibrationHelpers.hpp:116
virtual double operator()(const double depth, const double press, const double temp, const double sat=0.0) const =0
Definition: EquilibrationHelpers.hpp:315
RsSatAtContact(const int pvtRegionIdx, const double p_contact, const double T_contact)
Definition: EquilibrationHelpers.hpp:324
double operator()(const double, const double press, const double temp, const double sat_gas=0.0) const
Definition: EquilibrationHelpers.hpp:346
Definition: EquilibrationHelpers.hpp:178
RsVD(const int pvtRegionIdx, const std::vector< double > &depth, const std::vector< double > &rs)
Definition: EquilibrationHelpers.hpp:187
double operator()(const double depth, const double press, const double temp, const double sat_gas=0.0) const
Definition: EquilibrationHelpers.hpp:212
Definition: EquilibrationHelpers.hpp:384
double operator()(const double, const double press, const double temp, const double sat_oil=0.0) const
Definition: EquilibrationHelpers.hpp:415
RvSatAtContact(const int pvtRegionIdx, const double p_contact, const double T_contact)
Definition: EquilibrationHelpers.hpp:393
Definition: EquilibrationHelpers.hpp:242
double operator()(const double depth, const double press, const double temp, const double sat_oil=0.0) const
Definition: EquilibrationHelpers.hpp:276
RvVD(const int pvtRegionIdx, const std::vector< double > &depth, const std::vector< double > &rv)
Definition: EquilibrationHelpers.hpp:251
double satFromSumOfPcs(const MaterialLawManager &materialLawManager, const int phase1, const int phase2, const int cell, const double target_pc)
Definition: EquilibrationHelpers.hpp:734
Opm::FluidSystems::BlackOil< double > FluidSystemSimple
Definition: EquilibrationHelpers.hpp:90
Opm::SimpleModularFluidState< double, 3, 3, FluidSystemSimple, false, false, false, false, true, false, false, false > SatOnlyFluidState
Definition: EquilibrationHelpers.hpp:104
bool isConstPc(const MaterialLawManager &materialLawManager, const int phase, const int cell)
Return true if capillary pressure function is constant.
Definition: EquilibrationHelpers.hpp:784
double satFromPc(const MaterialLawManager &materialLawManager, const int phase, const int cell, const double target_pc, const bool increasing=false)
Definition: EquilibrationHelpers.hpp:651
double maxSaturations(const MaterialLawManager &materialLawManager, const int phase, const int cell)
Definition: EquilibrationHelpers.hpp:621
double satFromDepth(const MaterialLawManager &materialLawManager, const double cellDepth, const double contactDepth, const int phase, const int cell, const bool increasing=false)
Compute saturation from depth. Used for constant capillary pressure function.
Definition: EquilibrationHelpers.hpp:764
double minSaturations(const MaterialLawManager &materialLawManager, const int phase, const int cell)
Definition: EquilibrationHelpers.hpp:594
Definition: AnisotropicEikonal.hpp:44
Definition: EquilibrationHelpers.hpp:558
double operator()(double s) const
Definition: EquilibrationHelpers.hpp:570
PcEq(const MaterialLawManager &materialLawManager, const int phase, const int cell, const double target_pc)
Definition: EquilibrationHelpers.hpp:559
Definition: EquilibrationHelpers.hpp:686
PcEqSum(const MaterialLawManager &materialLawManager, const int phase1, const int phase2, const int cell, const double target_pc)
Definition: EquilibrationHelpers.hpp:687
double operator()(double s) const
Definition: EquilibrationHelpers.hpp:699