opm-simulators
EquilibrationHelpers_impl.hpp
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 3 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 */
23 
24 #include <opm/common/TimingMacros.hpp>
25 
26 #include <opm/common/utility/numeric/RootFinders.hpp>
27 
28 #include <opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp>
29 #include <opm/material/fluidstates/SimpleModularFluidState.hpp>
30 #include <opm/material/fluidsystems/BlackOilFluidSystem.hpp>
31 
33 
34 #include <algorithm>
35 #include <array>
36 #include <cmath>
37 #include <limits>
38 #include <stdexcept>
39 
40 #include <fmt/format.h>
41 
42 namespace Opm {
43 namespace EQUIL {
44 
45 using FluidSystemSimple = BlackOilFluidSystem<double>;
46 
47 // Adjust oil pressure according to gas saturation and cap pressure
48 using SatOnlyFluidState = SimpleModularFluidState<double,
49  /*numPhases=*/3,
50  /*numComponents=*/3,
51  FluidSystemSimple,
52  /*storePressure=*/false,
53  /*storeTemperature=*/false,
54  /*storeComposition=*/false,
55  /*storeFugacity=*/false,
56  /*storeSaturation=*/true,
57  /*storeDensity=*/false,
58  /*storeViscosity=*/false,
59  /*storeEnthalpy=*/false>;
60 
61 namespace Miscibility {
62 
63 template<class FluidSystem>
64 RsVD<FluidSystem>::RsVD(const int pvtRegionIdx,
65  const std::vector<Scalar>& depth,
66  const std::vector<Scalar>& rs)
67  : pvtRegionIdx_(pvtRegionIdx)
68  , rsVsDepth_(depth, rs)
69 {
70 }
71 
72 template<class FluidSystem>
73 typename RsVD<FluidSystem>::Scalar
75 operator()(const Scalar depth,
76  const Scalar press,
77  const Scalar temp,
78  const Scalar satGas) const
79 {
80  const auto sat_rs = satRs(press, temp);
81  if (satGas > std::sqrt(std::numeric_limits<Scalar>::epsilon())) {
82  return sat_rs;
83  }
84  else {
85  if (rsVsDepth_.xMin() > depth)
86  return std::min(sat_rs, rsVsDepth_.valueAt(0));
87  else if (rsVsDepth_.xMax() < depth)
88  return std::min(sat_rs, rsVsDepth_.valueAt(rsVsDepth_.numSamples() - 1));
89  return std::min(sat_rs, rsVsDepth_.eval(depth, /*extrapolate=*/false));
90  }
91 }
92 
93 template<class FluidSystem>
94 typename RsVD<FluidSystem>::Scalar
96 satRs(const Scalar press, const Scalar temp) const
97 {
98  return FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp, press);
99 }
100 
101 template<class FluidSystem>
102 PBVD<FluidSystem>::PBVD(const int pvtRegionIdx,
103  const std::vector<Scalar>& depth,
104  const std::vector<Scalar>& pbub)
105  : pvtRegionIdx_(pvtRegionIdx)
106  , pbubVsDepth_(depth, pbub)
107 {
108 }
109 
110 template<class FluidSystem>
111 typename PBVD<FluidSystem>::Scalar
113 operator()(const Scalar depth,
114  const Scalar cellPress,
115  const Scalar temp,
116  const Scalar satGas) const
117 {
118  Scalar press = cellPress;
119  if (satGas <= 0.0) {
120  if (pbubVsDepth_.xMin() > depth)
121  press = pbubVsDepth_.valueAt(0);
122  else if (pbubVsDepth_.xMax() < depth)
123  press = pbubVsDepth_.valueAt(pbubVsDepth_.numSamples() - 1);
124  else
125  press = pbubVsDepth_.eval(depth, /*extrapolate=*/false);
126  }
127  return satRs(std::min(press, cellPress), temp);
128 }
129 
130 template<class FluidSystem>
131 typename PBVD<FluidSystem>::Scalar
133 satRs(const Scalar press, const Scalar temp) const
134 {
135  return FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp, press);
136 }
137 
138 template<class FluidSystem>
139 PDVD<FluidSystem>::PDVD(const int pvtRegionIdx,
140  const std::vector<Scalar>& depth,
141  const std::vector<Scalar>& pdew)
142  : pvtRegionIdx_(pvtRegionIdx)
143  , pdewVsDepth_(depth, pdew)
144 {
145 }
146 
147 template<class FluidSystem>
148 typename PDVD<FluidSystem>::Scalar
150 operator()(const Scalar depth,
151  const Scalar cellPress,
152  const Scalar temp,
153  const Scalar satOil) const
154 {
155  Scalar press = cellPress;
156  if (satOil <= 0.0) {
157  if (pdewVsDepth_.xMin() > depth)
158  press = pdewVsDepth_.valueAt(0);
159  else if (pdewVsDepth_.xMax() < depth)
160  press = pdewVsDepth_.valueAt(pdewVsDepth_.numSamples() - 1);
161  else
162  press = pdewVsDepth_.eval(depth, /*extrapolate=*/false);
163  }
164  return satRv(std::min(press, cellPress), temp);
165 }
166 
167 template<class FluidSystem>
168 typename PDVD<FluidSystem>::Scalar
170 satRv(const Scalar press, const Scalar temp) const
171 {
172  return FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp, press);
173 }
174 
175 template<class FluidSystem>
176 RvVD<FluidSystem>::RvVD(const int pvtRegionIdx,
177  const std::vector<Scalar>& depth,
178  const std::vector<Scalar>& rv)
179  : pvtRegionIdx_(pvtRegionIdx)
180  , rvVsDepth_(depth, rv)
181 {
182 }
183 
184 template<class FluidSystem>
185 typename RvVD<FluidSystem>::Scalar
187 operator()(const Scalar depth,
188  const Scalar press,
189  const Scalar temp,
190  const Scalar satOil) const
191 {
192  if (satOil < - std::sqrt(std::numeric_limits<Scalar>::epsilon())) {
193  throw std::logic_error {
194  "Must not pass negative oil saturation"
195  };
196  }
197  const auto sat_rv = satRv(press, temp);
198  if (satOil > std::sqrt(std::numeric_limits<Scalar>::epsilon())) {
199  return sat_rv;
200  }
201  else {
202  if (rvVsDepth_.xMin() > depth)
203  return std::min(sat_rv, rvVsDepth_.valueAt(0));
204  else if (rvVsDepth_.xMax() < depth)
205  return std::min(sat_rv, rvVsDepth_.valueAt(rvVsDepth_.numSamples() - 1));
206  return std::min(sat_rv, rvVsDepth_.eval(depth, /*extrapolate=*/false));
207  }
208 }
209 
210 template<class FluidSystem>
211 typename RvVD<FluidSystem>::Scalar
213 satRv(const Scalar press, const Scalar temp) const
214 {
215  return FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp, press);
216 }
217 
218 template<class FluidSystem>
219 RvwVD<FluidSystem>::RvwVD(const int pvtRegionIdx,
220  const std::vector<Scalar>& depth,
221  const std::vector<Scalar>& rvw)
222  : pvtRegionIdx_(pvtRegionIdx)
223  , rvwVsDepth_(depth, rvw)
224 {
225 }
226 
227 template<class FluidSystem>
228 typename RvwVD<FluidSystem>::Scalar
230 operator()(const Scalar depth,
231  const Scalar press,
232  const Scalar temp,
233  const Scalar satWat) const
234 {
235  if (satWat < - std::sqrt(std::numeric_limits<double>::epsilon())) {
236  throw std::logic_error {
237  "Must not pass negative water saturation"
238  };
239  }
240 
241  const auto sat_rvw = satRvw(press, temp);
242  if (satWat > std::sqrt(std::numeric_limits<double>::epsilon())) {
243  return sat_rvw; //saturated Rvw
244  }
245  else {
246  if (rvwVsDepth_.xMin() > depth)
247  return std::min(sat_rvw,rvwVsDepth_.valueAt(0));
248  else if (rvwVsDepth_.xMax() < depth)
249  return std::min(sat_rvw, rvwVsDepth_.valueAt(rvwVsDepth_.numSamples() - 1));
250  return std::min(sat_rvw, rvwVsDepth_.eval(depth, /*extrapolate=*/false));
251  }
252 }
253 
254 template<class FluidSystem>
255 typename RvwVD<FluidSystem>::Scalar
257 satRvw(const Scalar press, const Scalar temp) const
258 {
259  return FluidSystem::gasPvt().saturatedWaterVaporizationFactor(pvtRegionIdx_, temp, press);
260 }
261 
262 template<class FluidSystem>
264 RsSatAtContact(const int pvtRegionIdx, const Scalar pContact, const Scalar T_contact)
265  : pvtRegionIdx_(pvtRegionIdx)
266 {
267  rsSatContact_ = satRs(pContact, T_contact);
268 }
269 
270 template<class FluidSystem>
271 typename RsSatAtContact<FluidSystem>::Scalar
273 operator()(const Scalar /* depth */,
274  const Scalar press,
275  const Scalar temp,
276  const Scalar satGas) const
277 {
278  if (satGas > std::sqrt(std::numeric_limits<Scalar>::epsilon())) {
279  return satRs(press, temp);
280  }
281  else {
282  return std::min(satRs(press, temp), rsSatContact_);
283  }
284 }
285 
286 template<class FluidSystem>
287 typename RsSatAtContact<FluidSystem>::Scalar
289 satRs(const Scalar press, const Scalar temp) const
290 {
291  return FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_, temp, press);
292 }
293 
294 template<class FluidSystem>
296 RvSatAtContact(const int pvtRegionIdx, const Scalar pContact, const Scalar T_contact)
297  : pvtRegionIdx_(pvtRegionIdx)
298 {
299  rvSatContact_ = satRv(pContact, T_contact);
300 }
301 
302 template<class FluidSystem>
303 typename RvSatAtContact<FluidSystem>::Scalar
305 operator()(const Scalar /*depth*/,
306  const Scalar press,
307  const Scalar temp,
308  const Scalar satOil) const
309 {
310  if (satOil > std::sqrt(std::numeric_limits<Scalar>::epsilon())) {
311  return satRv(press, temp);
312  }
313  else {
314  return std::min(satRv(press, temp), rvSatContact_);
315  }
316 }
317 
318 template<class FluidSystem>
319 typename RvSatAtContact<FluidSystem>::Scalar
321 satRv(const Scalar press, const Scalar temp) const
322 {
323  return FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp, press);;
324 }
325 
326 template<class FluidSystem>
328 RvwSatAtContact(const int pvtRegionIdx, const Scalar pContact, const Scalar T_contact)
329  : pvtRegionIdx_(pvtRegionIdx)
330 {
331  rvwSatContact_ = satRvw(pContact, T_contact);
332 }
333 
334 template<class FluidSystem>
335 typename RvwSatAtContact<FluidSystem>::Scalar
337 operator()(const Scalar /*depth*/,
338  const Scalar press,
339  const Scalar temp,
340  const Scalar satWat) const
341 {
342  if (satWat > std::sqrt(std::numeric_limits<Scalar>::epsilon())) {
343  return satRvw(press, temp);
344  }
345  else {
346  return std::min(satRvw(press, temp), rvwSatContact_);
347  }
348 }
349 
350 template<class FluidSystem>
351 typename RvwSatAtContact<FluidSystem>::Scalar
353 satRvw(const Scalar press, const Scalar temp) const
354 {
355  return FluidSystem::gasPvt().saturatedWaterVaporizationFactor(pvtRegionIdx_, temp, press);;
356 }
357 
358 template <class FluidSystem>
359 RsConst<FluidSystem>::RsConst(const Scalar rs_constant,
360  const Scalar pb_constant)
361  : rs_constant_(rs_constant)
362  , pb_constant_(pb_constant)
363 {
364  // Validate that rs_constant is reasonable
365  if (this->rs_constant_ < 0.0) {
366  throw std::invalid_argument("RSCONST RS value cannot be negative");
367  }
368 
369  if (this->pb_constant_ <= 0.0) {
370  throw std::invalid_argument("RSCONST bubble point pressure must be positive");
371  }
372 }
373 
374 template <class FluidSystem>
375 typename FluidSystem::Scalar
376 RsConst<FluidSystem>::satRs([[maybe_unused]] const Scalar press,
377  [[maybe_unused]] const Scalar temp) const
378 {
379  // For RSCONST, the saturated Rs is the constant value.
380  return this->rs_constant_;
381 }
382 
383 template <class FluidSystem>
384 typename FluidSystem::Scalar
385 RsConst<FluidSystem>::operator()([[maybe_unused]] const Scalar depth,
386  [[maybe_unused]] const Scalar press,
387  [[maybe_unused]] const Scalar temp,
388  [[maybe_unused]] const Scalar satGas) const
389 {
390  // For RSCONST with PVDO (dead oil):
391  // 1. Oil is always treated as undersaturated with constant dissolved gas.
392  // 2. Simulation should terminate if pressure < pb_constant_.
393  // 3. Always ensure we use undersaturated PVT calculation.
394 
395  if (press < this->pb_constant_) {
396  throw std::invalid_argument {
397  fmt::format("Pressure {} is below bubble point pressure {}",
398  press, this->pb_constant_)
399  };
400  }
401 
402  return this->rs_constant_;
403 }
404 
405 } // namespace Miscibility
406 
407 template<class Scalar>
408 EquilReg<Scalar>::EquilReg(const EquilRecord& rec,
409  std::shared_ptr<Miscibility::RsFunction<Scalar>> rs,
410  std::shared_ptr<Miscibility::RsFunction<Scalar>> rv,
411  std::shared_ptr<Miscibility::RsFunction<Scalar>> rvw,
412  const TabulatedFunction& tempVdTable,
413  const TabulatedFunction& saltVdTable,
414  const int pvtIdx)
415  : rec_ (rec)
416  , rs_ (rs)
417  , rv_ (rv)
418  , rvw_ (rvw)
419  , tempVdTable_ (tempVdTable)
420  , saltVdTable_ (saltVdTable)
421  , pvtIdx_ (pvtIdx)
422 {
423 }
424 
425 template<class Scalar>
427 {
428  return this->rec_.datumDepth();
429 }
430 
431 template<class Scalar>
433 {
434  return this->rec_.datumDepthPressure();
435 }
436 
437 template<class Scalar>
439 {
440  return this->rec_.waterOilContactDepth();
441 }
442 
443 template<class Scalar>
445 {
446  return this->rec_.waterOilContactCapillaryPressure();
447 }
448 
449 template<class Scalar>
451 {
452  return this->rec_.gasOilContactDepth();
453 }
454 
455 template<class Scalar>
457 {
458  return this->rec_.gasOilContactCapillaryPressure();
459 }
460 
461 template<class Scalar>
463 {
464  return this->rec_.initializationTargetAccuracy();
465 }
466 
467 template<class Scalar>
468 const typename EquilReg<Scalar>::CalcDissolution&
470 {
471  return *this->rs_;
472 }
473 
474 template<class Scalar>
475 const typename EquilReg<Scalar>::CalcEvaporation&
477 {
478  return *this->rv_;
479 }
480 
481 template<class Scalar>
484 {
485  return *this->rvw_;
486 }
487 
488 template<class Scalar>
489 const typename EquilReg<Scalar>::TabulatedFunction&
491 {
492  return saltVdTable_;
493 }
494 
495 template<class Scalar>
496 const typename EquilReg<Scalar>::TabulatedFunction&
497 EquilReg<Scalar>::tempVdTable() const
498 {
499  return tempVdTable_;
500 }
501 
502 template<class Scalar>
504 {
505  return this->pvtIdx_;
506 }
507 
508 template<class FluidSystem, class MaterialLawManager>
510 PcEq(const MaterialLawManager& materialLawManager,
511  const int phase,
512  const int cell,
513  const Scalar targetPc)
514  : materialLawManager_(materialLawManager)
515  , phase_(phase)
516  , cell_(cell)
517  , targetPc_(targetPc)
518 {
519 }
520 
521 template<class FluidSystem, class MaterialLawManager>
522 typename PcEq<FluidSystem,MaterialLawManager>::Scalar
523 PcEq<FluidSystem,MaterialLawManager>::
524 operator()(Scalar s) const
525 {
526  const auto& matParams = materialLawManager_.materialLawParams(cell_);
527  SatOnlyFluidState fluidState;
528  fluidState.setSaturation(FluidSystem::waterPhaseIdx, 0.0);
529  fluidState.setSaturation(FluidSystem::oilPhaseIdx, 0.0);
530  fluidState.setSaturation(FluidSystem::gasPhaseIdx, 0.0);
531  fluidState.setSaturation(phase_, s);
532 
533  // This code should only be called for water or gas phase
534  assert(phase_ != FluidSystem::oilPhaseIdx);
535  // The capillaryPressure code only uses the wetting phase saturation
536  if (phase_ == FluidSystem::gasPhaseIdx) {
537  fluidState.setSaturation(FluidSystem::waterPhaseIdx, 1.0 - s);
538  fluidState.setSaturation(FluidSystem::oilPhaseIdx, 1.0 - s);
539  }
540  std::array<Scalar, FluidSystem::numPhases> pc{0.0};
541  using MaterialLaw = typename MaterialLawManager::MaterialLaw;
542  MaterialLaw::capillaryPressures(pc, matParams, fluidState);
543  Scalar sign = (phase_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0;
544  Scalar pcPhase = pc[FluidSystem::oilPhaseIdx] + sign * pc[phase_];
545  return pcPhase - targetPc_;
546 }
547 
548 template<class FluidSystem, class MaterialLawManager>
549 PcEqSum<FluidSystem,MaterialLawManager>::
550 PcEqSum(const MaterialLawManager& materialLawManager,
551  const int phase1,
552  const int phase2,
553  const int cell,
554  const Scalar targetPc)
555  : materialLawManager_(materialLawManager)
556  , phase1_(phase1)
557  , phase2_(phase2)
558  , cell_(cell)
559  , targetPc_(targetPc)
560 {
561 }
562 
563 template<class FluidSystem, class MaterialLawManager>
564 typename PcEqSum<FluidSystem,MaterialLawManager>::Scalar
565 PcEqSum<FluidSystem,MaterialLawManager>::
566 operator()(Scalar s) const
567 {
568  const auto& matParams = materialLawManager_.materialLawParams(cell_);
569  SatOnlyFluidState fluidState;
570  fluidState.setSaturation(FluidSystem::waterPhaseIdx, 0.0);
571  fluidState.setSaturation(FluidSystem::oilPhaseIdx, 0.0);
572  fluidState.setSaturation(FluidSystem::gasPhaseIdx, 0.0);
573  fluidState.setSaturation(phase1_, s);
574  fluidState.setSaturation(phase2_, 1.0 - s);
575 
576  std::array<Scalar, FluidSystem::numPhases> pc {0.0};
577 
578  using MaterialLaw = typename MaterialLawManager::MaterialLaw;
579  MaterialLaw::capillaryPressures(pc, matParams, fluidState);
580  Scalar sign1 = (phase1_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0;
581  Scalar pc1 = pc[FluidSystem::oilPhaseIdx] + sign1 * pc[phase1_];
582  Scalar sign2 = (phase2_ == FluidSystem::waterPhaseIdx)? -1.0 : 1.0;
583  Scalar pc2 = pc[FluidSystem::oilPhaseIdx] + sign2 * pc[phase2_];
584  return pc1 + pc2 - targetPc_;
585 }
586 
587 template <class FluidSystem, class MaterialLawManager>
588 typename FluidSystem::Scalar
589 minSaturations(const MaterialLawManager& materialLawManager,
590  const int phase, const int cell)
591 {
592  const auto& scaledDrainageInfo =
593  materialLawManager.oilWaterScaledEpsInfoDrainage(cell);
594 
595  // Find minimum and maximum saturations.
596  switch(phase) {
597  case FluidSystem::waterPhaseIdx:
598  return scaledDrainageInfo.Swl;
599 
600  case FluidSystem::gasPhaseIdx:
601  return scaledDrainageInfo.Sgl;
602 
603  case FluidSystem::oilPhaseIdx:
604  throw std::runtime_error("Min saturation not implemented for oil phase.");
605 
606  default:
607  throw std::runtime_error("Unknown phaseIdx .");
608  }
609  return -1.0;
610 }
611 
612 template <class FluidSystem, class MaterialLawManager>
613 typename FluidSystem::Scalar
614 maxSaturations(const MaterialLawManager& materialLawManager,
615  const int phase, const int cell)
616 {
617  const auto& scaledDrainageInfo =
618  materialLawManager.oilWaterScaledEpsInfoDrainage(cell);
619 
620  // Find minimum and maximum saturations.
621  switch(phase) {
622  case FluidSystem::waterPhaseIdx:
623  return scaledDrainageInfo.Swu;
624 
625  case FluidSystem::gasPhaseIdx:
626  return scaledDrainageInfo.Sgu;
627 
628  case FluidSystem::oilPhaseIdx:
629  throw std::runtime_error("Max saturation not implemented for oil phase.");
630 
631  default:
632  throw std::runtime_error("Unknown phaseIdx .");
633  }
634  return -1.0;
635 }
636 
637 template <class FluidSystem, class MaterialLawManager>
638 typename FluidSystem::Scalar
639 satFromPc(const MaterialLawManager& materialLawManager,
640  const int phase,
641  const int cell,
642  const typename FluidSystem::Scalar targetPc,
643  const bool increasing)
644 {
645  using Scalar = typename FluidSystem::Scalar;
646  // Find minimum and maximum saturations.
647  Scalar s0 = increasing ? maxSaturations<FluidSystem>(materialLawManager, phase, cell) : minSaturations<FluidSystem>(materialLawManager, phase, cell);
648  Scalar s1 = increasing ? minSaturations<FluidSystem>(materialLawManager, phase, cell) : maxSaturations<FluidSystem>(materialLawManager, phase, cell);
649 
650  // Create the equation f(s) = pc(s) - targetPc
651  const PcEq<FluidSystem, MaterialLawManager> f(materialLawManager, phase, cell, targetPc);
652  Scalar f0 = f(s0);
653  Scalar f1 = f(s1);
654  if (!std::isfinite(f0 + f1))
655  throw std::logic_error(fmt::format("The capillary pressure values {} and {} are not finite", f0, f1));
656 
657  if (f0 <= 0.0)
658  return s0;
659  else if (f1 >= 0.0)
660  return s1;
661 
662  const Scalar tol = 1e-10;
663  // should at least converge in 2 times bisection but some safety here:
664  const int maxIter = -2*static_cast<int>(std::log2(tol)) + 10;
665  int usedIterations = -1;
666  const Scalar root = RegulaFalsiBisection<ThrowOnError>::solve(f, s0, s1, maxIter, tol, usedIterations);
667  return root;
668 }
669 
670 template<class FluidSystem, class MaterialLawManager>
671 typename FluidSystem::Scalar
672 satFromSumOfPcs(const MaterialLawManager& materialLawManager,
673  const int phase1,
674  const int phase2,
675  const int cell,
676  const typename FluidSystem::Scalar targetPc)
677 {
678  using Scalar = typename FluidSystem::Scalar;
679  // Find minimum and maximum saturations.
680  Scalar s0 = minSaturations<FluidSystem>(materialLawManager, phase1, cell);
681  Scalar s1 = maxSaturations<FluidSystem>(materialLawManager, phase1, cell);
682 
683  // Create the equation f(s) = pc1(s) + pc2(1-s) - targetPc
684  const PcEqSum<FluidSystem, MaterialLawManager> f(materialLawManager, phase1, phase2, cell, targetPc);
685  Scalar f0 = f(s0);
686  Scalar f1 = f(s1);
687  if (f0 <= 0.0)
688  return s0;
689  else if (f1 >= 0.0)
690  return s1;
691 
692  assert(f0 > 0.0 && f1 < 0.0);
693  const Scalar tol = 1e-10;
694  // should at least converge in 2 times bisection but some safety here:
695  const int maxIter = -2*static_cast<int>(std::log2(tol)) + 10;
696  int usedIterations = -1;
697  const Scalar root = RegulaFalsiBisection<ThrowOnError>::solve(f, s0, s1, maxIter, tol, usedIterations);
698  return root;
699 }
700 
701 template<class FluidSystem, class MaterialLawManager>
702 typename FluidSystem::Scalar
703 satFromDepth(const MaterialLawManager& materialLawManager,
704  const typename FluidSystem::Scalar cellDepth,
705  const typename FluidSystem::Scalar contactDepth,
706  const int phase,
707  const int cell,
708  const bool increasing)
709 {
710  using Scalar = typename FluidSystem::Scalar;
711  const Scalar s0 = increasing ? maxSaturations<FluidSystem>(materialLawManager, phase, cell) : minSaturations<FluidSystem>(materialLawManager, phase, cell);
712  const Scalar s1 = increasing ? minSaturations<FluidSystem>(materialLawManager, phase, cell) : maxSaturations<FluidSystem>(materialLawManager, phase, cell);
713 
714  if (cellDepth <= contactDepth) {
715  return s0;
716  }
717  else {
718  return s1;
719  }
720 }
721 
722 template<class FluidSystem, class MaterialLawManager>
723 bool isConstPc(const MaterialLawManager& materialLawManager,
724  const int phase,
725  const int cell)
726 {
727  using Scalar = typename FluidSystem::Scalar;
728  // Create the equation f(s) = pc(s);
729  const PcEq<FluidSystem, MaterialLawManager> f(materialLawManager, phase, cell, 0);
730  const Scalar f0 = f(minSaturations<FluidSystem>(materialLawManager, phase, cell));
731  const Scalar f1 = f(maxSaturations<FluidSystem>(materialLawManager, phase, cell));
732  return std::abs(f0 - f1) < std::numeric_limits<Scalar>::epsilon();
733 }
734 
735 }
736 }
Scalar zgoc() const
Depth of gas-oil contact.
Definition: EquilibrationHelpers_impl.hpp:450
RsConst(const Scalar rs_constant, const Scalar pb_constant)
Constructor.
Definition: EquilibrationHelpers_impl.hpp:359
const CalcEvaporation & evaporationCalculator() const
Retrieve vapourised oil-gas ratio calculator of current region.
Definition: EquilibrationHelpers_impl.hpp:476
Aggregate information base of an equilibration region.
Definition: EquilibrationHelpers.hpp:675
int pvtIdx() const
Retrieve pvtIdx of the region.
Definition: EquilibrationHelpers_impl.hpp:503
const CalcDissolution & dissolutionCalculator() const
Retrieve dissolved gas-oil ratio calculator of current region.
Definition: EquilibrationHelpers_impl.hpp:469
RvVD(const int pvtRegionIdx, const std::vector< Scalar > &depth, const std::vector< Scalar > &rv)
Constructor.
Definition: EquilibrationHelpers_impl.hpp:176
Scalar datum() const
Datum depth in current region.
Definition: EquilibrationHelpers_impl.hpp:426
Type that implements "dissolved gas-oil ratio" tabulated as a function of depth policy.
Definition: EquilibrationHelpers.hpp:215
Scalar operator()(const Scalar depth, const Scalar press, const Scalar temp, const Scalar satGas=0.0) const override
Function call.
Definition: EquilibrationHelpers_impl.hpp:75
Type that implements "vaporized oil-gas ratio" tabulated as a function of depth policy.
Definition: EquilibrationHelpers.hpp:268
RvSatAtContact(const int pvtRegionIdx, const Scalar pContact, const Scalar T_contact)
Constructor.
Definition: EquilibrationHelpers_impl.hpp:296
FluidSystem::Scalar satFromPc(const MaterialLawManager &materialLawManager, const int phase, const int cell, const typename FluidSystem::Scalar targetPc, const bool increasing=false)
Compute saturation of some phase corresponding to a given capillary pressure.
Definition: EquilibrationHelpers_impl.hpp:639
int equilibrationAccuracy() const
Accuracy/strategy for initial fluid-in-place calculation.
Definition: EquilibrationHelpers_impl.hpp:462
Class that implements "vaporized oil-gas ratio" (Rv) as function of depth and pressure as follows: ...
Definition: EquilibrationHelpers.hpp:499
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Scalar operator()(const Scalar depth, const Scalar press, const Scalar temp, const Scalar satWat=0.0) const override
Function call.
Definition: EquilibrationHelpers_impl.hpp:337
Scalar operator()(const Scalar depth, const Scalar press, const Scalar temp, const Scalar satOil=0.0) const override
Function call.
Definition: EquilibrationHelpers_impl.hpp:187
Auxiliary routines that to solve the ODEs that emerge from the hydrostatic equilibrium problem...
Functor for inverting a sum of capillary pressure functions.
Definition: EquilibrationHelpers.hpp:841
Scalar operator()(const Scalar depth, const Scalar cellPress, const Scalar temp, const Scalar satGas=0.0) const override
Function call.
Definition: EquilibrationHelpers_impl.hpp:113
Scalar operator()(const Scalar depth, const Scalar press, const Scalar temp, const Scalar satWat=0.0) const override
Function call.
Definition: EquilibrationHelpers_impl.hpp:230
PBVD(const int pvtRegionIdx, const std::vector< Scalar > &depth, const std::vector< Scalar > &pbub)
Constructor.
Definition: EquilibrationHelpers_impl.hpp:102
RvwSatAtContact(const int pvtRegionIdx, const Scalar pContact, const Scalar T_contact)
Constructor.
Definition: EquilibrationHelpers_impl.hpp:328
Functor for inverting capillary pressure function.
Definition: EquilibrationHelpers.hpp:800
Class that implements "vaporized water-gas ratio" (Rvw) as function of depth and pressure as follows:...
Definition: EquilibrationHelpers.hpp:559
Scalar operator()(const Scalar depth, const Scalar press, const Scalar temp, const Scalar satOil=0.0) const override
Function call.
Definition: EquilibrationHelpers_impl.hpp:305
bool isConstPc(const MaterialLawManager &materialLawManager, const int phase, const int cell)
Return true if capillary pressure function is constant.
Definition: EquilibrationHelpers_impl.hpp:723
Scalar pcgoGoc() const
Gas-oil capillary pressure at gas-oil contact.
Definition: EquilibrationHelpers_impl.hpp:456
Scalar operator()(const Scalar depth, const Scalar cellPress, const Scalar temp, const Scalar satOil=0.0) const override
Function call.
Definition: EquilibrationHelpers_impl.hpp:150
RvwVD(const int pvtRegionIdx, const std::vector< Scalar > &depth, const std::vector< Scalar > &rvw)
Constructor.
Definition: EquilibrationHelpers_impl.hpp:219
Scalar pressure() const
Pressure at datum depth in current region.
Definition: EquilibrationHelpers_impl.hpp:432
RsVD(const int pvtRegionIdx, const std::vector< Scalar > &depth, const std::vector< Scalar > &rs)
Constructor.
Definition: EquilibrationHelpers_impl.hpp:64
FluidSystem::Scalar satFromSumOfPcs(const MaterialLawManager &materialLawManager, const int phase1, const int phase2, const int cell, const typename FluidSystem::Scalar targetPc)
Compute saturation of some phase corresponding to a given capillary pressure, where the capillary pre...
Definition: EquilibrationHelpers_impl.hpp:672
FluidSystem::Scalar satFromDepth(const MaterialLawManager &materialLawManager, const typename FluidSystem::Scalar cellDepth, const typename FluidSystem::Scalar contactDepth, const int phase, const int cell, const bool increasing=false)
Compute saturation from depth. Used for constant capillary pressure function.
Definition: EquilibrationHelpers_impl.hpp:703
Scalar zwoc() const
Depth of water-oil contact.
Definition: EquilibrationHelpers_impl.hpp:438
Type that implements "constant dissolved gas-oil ratio" (Rs) from RSCONST keyword.
Definition: EquilibrationHelpers.hpp:611
PDVD(const int pvtRegionIdx, const std::vector< Scalar > &depth, const std::vector< Scalar > &pdew)
Constructor.
Definition: EquilibrationHelpers_impl.hpp:139
Scalar operator()(const Scalar depth, const Scalar press, const Scalar temp, const Scalar satGas=0.0) const override
Function call - returns constant Rs if pressure above bubble point.
Definition: EquilibrationHelpers_impl.hpp:385
Type that implements "vaporized water-gas ratio" tabulated as a function of depth policy...
Definition: EquilibrationHelpers.hpp:375
Base class for phase mixing functions.
Definition: EquilibrationHelpers.hpp:100
EquilReg(const EquilRecord &rec, std::shared_ptr< Miscibility::RsFunction< Scalar >> rs, std::shared_ptr< Miscibility::RsFunction< Scalar >> rv, std::shared_ptr< Miscibility::RsFunction< Scalar >> rvw, const TabulatedFunction &tempVdTable, const TabulatedFunction &saltVdTable, const int pvtIdx)
Constructor.
Definition: EquilibrationHelpers_impl.hpp:408
const CalcWaterEvaporation & waterEvaporationCalculator() const
Retrieve vapourised water-gas ratio calculator of current region.
Definition: EquilibrationHelpers_impl.hpp:483
Scalar pcowWoc() const
water-oil capillary pressure at water-oil contact.
Definition: EquilibrationHelpers_impl.hpp:444
Type that implements "vaporized oil-gas ratio" tabulated as a function of depth policy.
Definition: EquilibrationHelpers.hpp:321
Type that implements "dissolved gas-oil ratio" tabulated as a function of depth policy.
Definition: EquilibrationHelpers.hpp:161
RsSatAtContact(const int pvtRegionIdx, const Scalar pContact, const Scalar T_contact)
Constructor.
Definition: EquilibrationHelpers_impl.hpp:264
Scalar operator()(const Scalar depth, const Scalar press, const Scalar temp, const Scalar satGas=0.0) const override
Function call.
Definition: EquilibrationHelpers_impl.hpp:273
Class that implements "dissolved gas-oil ratio" (Rs) as function of depth and pressure as follows: ...
Definition: EquilibrationHelpers.hpp:438