27 #ifndef OPM_ECL_HYSTERESIS_TWO_PHASE_LAW_PARAMS_HPP 28 #define OPM_ECL_HYSTERESIS_TWO_PHASE_LAW_PARAMS_HPP 30 #include <opm/input/eclipse/EclipseState/WagHysteresisConfig.hpp> 48 template <
class EffLawT>
51 using EffLawParams =
typename EffLawT::Params;
52 using Scalar =
typename EffLawParams::Traits::Scalar;
55 using Traits =
typename EffLawParams::Traits;
60 result.deltaSwImbKrn_ = 1.0;
64 result.initialImb_ =
true;
65 result.pcSwMic_ = 3.0;
66 result.krnSwMdc_ = 4.0;
67 result.krwSwMdc_ = 4.5;
80 if (
config().enableHysteresis()) {
81 if (
config().krHysteresisModel() == 2 ||
config().krHysteresisModel() == 3 ||
config().krHysteresisModel() == 4 ||
config().pcHysteresisModel() == 0) {
82 C_ = 1.0/(Sncri_ - Sncrd_ + 1.0e-12) - 1.0/(Snmaxd_ - Sncrd_);
85 if (
config().krHysteresisModel() == 4) {
86 Cw_ = 1.0/(Swcri_ - Swcrd_ + 1.0e-12) - 1.0/(Swmaxd_ - Swcrd_);
87 Krwd_sncri_ = EffLawT::twoPhaseSatKrw(
drainageParams(), 1 - Sncri());
89 updateDynamicParams_();
119 {
return *wagConfig_; }
128 drainageParams_ =
value;
130 oilWaterSystem_ = (twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
131 gasWaterSystem_ = (twoPhaseSystem == EclTwoPhaseSystemType::GasWater);
132 gasOilSystem_ = (twoPhaseSystem == EclTwoPhaseSystemType::GasOil);
138 if (twoPhaseSystem == EclTwoPhaseSystemType::GasOil) {
139 Sncrd_ = info.Sgcr + info.Swl;
141 Snmaxd_ = info.Sgu + info.Swl;
142 KrndMax_ = EffLawT::twoPhaseSatKrn(
drainageParams(), 1.0-Snmaxd_);
144 else if (twoPhaseSystem == EclTwoPhaseSystemType::GasWater) {
148 KrndMax_ = EffLawT::twoPhaseSatKrn(
drainageParams(), 1.0-Snmaxd_);
151 assert(twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
154 Snmaxd_ = 1.0 - info.Swl - info.Sgl;
155 KrndMax_ = EffLawT::twoPhaseSatKrn(
drainageParams(), 1.0-Snmaxd_);
159 if (
config().krHysteresisModel() == 4) {
161 if (twoPhaseSystem == EclTwoPhaseSystemType::GasOil) {
162 Swmaxd_ = 1.0 - info.Sgl - info.Swl;
165 else if (twoPhaseSystem == EclTwoPhaseSystemType::GasWater) {
170 assert(twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
177 if (
config().pcHysteresisModel() == 0) {
178 if (twoPhaseSystem == EclTwoPhaseSystemType::GasOil) {
179 pcmaxd_ = info.maxPcgo;
180 }
else if (twoPhaseSystem == EclTwoPhaseSystemType::GasWater) {
181 pcmaxd_ = info.maxPcgo + info.maxPcow;
184 assert(twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
190 if (gasOilHysteresisWAG()) {
191 swatImbStart_ = Swco_;
192 swatImbStartNxt_ = -1.0;
194 krnSwDrainStart_ = Sncrd_;
195 krnSwDrainStartNxt_ = Sncrd_;
197 krnImbStartNxt_ = 0.0;
198 krnDrainStart_ = 0.0;
199 krnDrainStartNxt_ = 0.0;
202 krnSwImbStart_ = Sncrd_;
212 {
return drainageParams_; }
215 {
return drainageParams_; }
224 imbibitionParams_ =
value;
226 if (!
config().enableHysteresis())
230 if (twoPhaseSystem == EclTwoPhaseSystemType::GasOil) {
231 Sncri_ = info.Sgcr + info.Swl;
234 else if (twoPhaseSystem == EclTwoPhaseSystemType::GasWater) {
239 assert(twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
245 if (
config().pcHysteresisModel() == 0) {
246 if (twoPhaseSystem == EclTwoPhaseSystemType::GasOil) {
247 Swmaxi_ = 1.0 - info.Sgl - info.Swl;
248 pcmaxi_ = info.maxPcgo;
249 }
else if (twoPhaseSystem == EclTwoPhaseSystemType::GasWater) {
251 pcmaxi_ = info.maxPcgo + info.maxPcow;
254 assert(twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
256 pcmaxi_ = info.maxPcow;
260 if (
config().krHysteresisModel() == 4) {
270 {
return imbibitionParams_; }
273 {
return imbibitionParams_; }
282 Scalar pcSwMic()
const 289 {
return initialImb_; }
297 { krwSwMdc_ =
value; };
305 {
return krwSwMdc_; };
313 { krnSwMdc_ =
value; }
321 {
return krnSwMdc_; }
351 { deltaSwImbKrn_ =
value; }
361 {
return deltaSwImbKrn_; }
370 Scalar Swmaxi()
const 385 Scalar SnTrapped(
bool maximumTrapping)
const 387 if(!maximumTrapping && isDrain_)
391 if(
config().krHysteresisModel() > 1 )
394 return Sncri_ + deltaSwImbKrn_;
397 Scalar SnStranded(Scalar sg, Scalar krg)
const {
398 const Scalar sn = EffLawT::twoPhaseSatKrnInv(drainageParams_, krg);
399 return sg - (1.0 - sn) + Sncrd_;
402 Scalar SwTrapped()
const 404 if(
config().krHysteresisModel() == 0 ||
config().krHysteresisModel() == 2)
407 if(
config().krHysteresisModel() == 1 ||
config().krHysteresisModel() == 3)
411 if(
config().krHysteresisModel() == 4 )
419 Scalar SncrtWAG()
const 420 {
return SncrtWAG_; }
422 Scalar Snmaxd()
const 425 Scalar Swmaxd()
const 429 {
return 1.0 - krnSwMdc_; }
432 {
return krwSwMdc_; }
437 Scalar krnWght()
const 438 {
return KrndHy_/KrndMax_; }
440 template <
class Evaluation>
441 Evaluation krwWght(
const Evaluation& Krwd)
const 444 Scalar deltaKrw = Krwi_snrmax() - Krwd_sncri();
445 Scalar Krwi_snr = Krwd_sncrt() + deltaKrw * (Sncrt() / max(1e-12, Sncri()));
446 return (Krwi_snr - Krwd) / ( Krwi_snrmax() - Krwi_snmax());
449 Scalar krwdMax()
const 453 Scalar KrwdHy()
const 459 Scalar Krwd_sncri()
const 464 Scalar Krwi_snmax()
const 469 Scalar Krwi_snrmax()
const 474 Scalar Krwd_sncrt()
const 479 Scalar pcWght() const
482 return EffLawT::twoPhaseSatPcnw(
drainageParams(), 0.0)/(pcmaxi_+1e-6);
484 return pcmaxd_/(pcmaxi_+1e-6);
487 Scalar curvatureCapPrs()
const 488 {
return curvatureCapPrs_;}
490 bool gasOilHysteresisWAG()
const 491 {
return (
config().enableWagHysteresis() && gasOilSystem_ &&
wagConfig().wagGasFlag()) ; }
493 Scalar reductionDrain()
const 494 {
return std::pow(Swco_/(swatImbStart_+tolWAG_*
wagConfig().wagWaterThresholdSaturation()),
wagConfig().wagSecondaryDrainageReduction());}
496 Scalar reductionDrainNxt()
const 497 {
return std::pow(Swco_/(swatImbStartNxt_+tolWAG_*
wagConfig().wagWaterThresholdSaturation()),
wagConfig().wagSecondaryDrainageReduction());}
499 bool threePhaseState()
const 500 {
return (swatImbStart_ > (Swco_ +
wagConfig().wagWaterThresholdSaturation()) ); }
502 Scalar nState()
const 505 Scalar krnSwDrainRevert()
const 506 {
return krnSwDrainRevert_;}
508 Scalar krnDrainStart()
const 509 {
return krnDrainStart_;}
511 Scalar krnDrainStartNxt()
const 512 {
return krnDrainStartNxt_;}
514 Scalar krnImbStart()
const 515 {
return krnImbStart_;}
517 Scalar krnImbStartNxt()
const 518 {
return krnImbStartNxt_;}
520 Scalar krnSwWAG()
const 523 Scalar krnSwDrainStart()
const 524 {
return krnSwDrainStart_;}
526 Scalar krnSwDrainStartNxt()
const 527 {
return krnSwDrainStartNxt_;}
529 Scalar krnSwImbStart()
const 530 {
return krnSwImbStart_;}
532 Scalar tolWAG()
const 535 template <
class Evaluation>
536 Evaluation computeSwf(
const Evaluation& Sw)
const 538 Evaluation SgT = 1.0 - Sw - SncrtWAG();
539 Scalar SgCut =
wagConfig().wagImbCurveLinearFraction()*(Snhy()- SncrtWAG());
540 Evaluation Swf = 1.0;
545 Swf -= (Sncrd() + 0.5*( SgT + Opm::sqrt( SgT*SgT + 4.0/C*SgT)));
548 SgCut = std::max(Scalar(0.000001), SgCut);
549 Scalar SgCutValue = 0.5*( SgCut + Opm::sqrt( SgCut*SgCut + 4.0/C*SgCut));
550 Scalar SgCutSlope = SgCutValue/SgCut;
552 Swf -= (Sncrd() + SgT);
558 template <
class Evaluation>
559 Evaluation computeKrImbWAG(
const Evaluation& Sw)
const 563 Swf = computeSwf(Sw);
564 if (Swf <= krnSwDrainStart_) {
565 Evaluation Krg = EffLawT::twoPhaseSatKrn(drainageParams_, Swf);
566 Evaluation KrgImb2 = (Krg-krnDrainStart_)*reductionDrain() + krnImbStart_;
570 Evaluation Sn = Sncrd_;
571 if (Swf < 1.0-SncrtWAG_) {
573 Evaluation dd = (1.0-krnSwImbStart_ - Sncrd_) / (1.0-krnSwDrainStart_ - SncrtWAG_);
574 Sn += (1.0-Swf-SncrtWAG_)*dd;
576 Evaluation KrgDrn1 = EffLawT::twoPhaseSatKrn(drainageParams_, 1.0 - Sn);
587 bool update(Scalar pcSw, Scalar krwSw, Scalar krnSw)
589 bool updateParams =
false;
591 if (
config().pcHysteresisModel() == 0 && pcSw < pcSwMdc_) {
592 if (pcSwMdc_ == 2.0 && pcSw+1.0e-6 < Swcrd_ && (oilWaterSystem_ || gasWaterSystem_)) {
599 if (initialImb_ && pcSw > pcSwMic_) {
604 if (krnSw < krnSwMdc_) {
607 if (
config().krHysteresisModel() == 4) {
612 if (krwSw > krwSwMdc_) {
618 if (!gasOilHysteresisWAG()) {
619 this->isDrain_ = (krnSw <= this->krnSwMdc_);
621 wasDrain_ = isDrain_;
623 if (swatImbStartNxt_ < 0.0) {
624 swatImbStartNxt_ = std::max(Swco_, Swco_ + krnSw - krwSw);
627 if ( (swatImbStartNxt_ > Swco_ + tolWAG_) && krwSw > tolWAG_) {
628 swatImbStart_ = swatImbStartNxt_;
630 krnSwDrainStartNxt_ = krnSwWAG_;
631 krnSwDrainStart_ = krnSwDrainStartNxt_;
637 if (krnSw <= krnSwWAG_+tolWAG_) {
638 krnSwWAG_ = std::min(krnSw, krnSwWAG_);
639 krnSwDrainRevert_ = krnSwWAG_;
649 if (krnSw >= krnSwWAG_-tolWAG_) {
650 krnSwWAG_ = std::max(krnSw, krnSwWAG_);
651 krnSwDrainStartNxt_ = krnSwWAG_;
652 swatImbStartNxt_ = std::max(swatImbStartNxt_, Swco_ + krnSw - krwSw);
657 krnSwDrainStart_ = krnSwDrainStartNxt_;
658 swatImbStart_ = swatImbStartNxt_;
667 updateDynamicParams_();
672 template<
class Serializer>
676 serializer(deltaSwImbKrn_);
680 serializer(initialImb_);
681 serializer(pcSwMic_);
682 serializer(krnSwMdc_);
683 serializer(krwSwMdc_);
688 bool operator==(
const EclHysteresisTwoPhaseLawParams& rhs)
const 690 return this->deltaSwImbKrn_ == rhs.deltaSwImbKrn_ &&
692 this->Sncrt_ == rhs.Sncrt_ &&
693 this->Swcrt_ == rhs.Swcrt_ &&
694 this->initialImb_ == rhs.initialImb_ &&
695 this->pcSwMic_ == rhs.pcSwMic_ &&
696 this->krnSwMdc_ == rhs.krnSwMdc_ &&
697 this->krwSwMdc_ == rhs.krwSwMdc_ &&
698 this->KrndHy_ == rhs.KrndHy_ &&
699 this->KrwdHy_ == rhs.KrwdHy_;
703 void updateDynamicParams_()
712 if (
config().krHysteresisModel() == 0 ||
config().krHysteresisModel() == 1) {
713 Scalar krnMdcDrainage = EffLawT::twoPhaseSatKrn(
drainageParams(), krnSwMdc_);
714 Scalar SwKrnMdcImbibition = EffLawT::twoPhaseSatKrnInv(
imbibitionParams(), krnMdcDrainage);
715 deltaSwImbKrn_ = SwKrnMdcImbibition - krnSwMdc_;
722 if (
config().krHysteresisModel() == 2 ||
723 config().krHysteresisModel() == 3 ||
724 config().krHysteresisModel() == 4 ||
725 config().pcHysteresisModel() == 0)
727 const Scalar snhy = 1.0 - krnSwMdc_;
729 Sncrt_ = Sncrd_ + (snhy - Sncrd_) /
730 ((1.0 +
config().modParamTrapped()*(Snmaxd_ - snhy)) + C_ * (snhy - Sncrd_));
737 if (
config().krHysteresisModel() == 4) {
738 Scalar swhy = krnSwMdc_;
739 if (swhy >= Swcrd_) {
740 Swcrt_ = Swcrd_ + (swhy - Swcrd_) /
741 ((1.0 +
config().modParamTrapped() * (Swmaxd_ - swhy)) + Cw_ * (swhy - Swcrd_));
745 Krwd_sncrt_ = EffLawT::twoPhaseSatKrw(
drainageParams(), 1 - Sncrt());
749 if (gasOilHysteresisWAG()) {
750 if (isDrain_ && krnSwMdc_ == krnSwWAG_) {
751 Scalar snhy = 1.0 - krnSwMdc_;
754 SncrtWAG_ += (snhy - Sncrd_) /
756 wagConfig().wagLandsParam() * (snhy - Sncrd_));
760 if (isDrain_ && (1.0 - krnSwDrainRevert_) > SncrtWAG_) {
761 cTransf_ = 1.0 / (SncrtWAG_ - Sncrd_ + 1.0e-12) - 1.0 / (1.0 - krnSwDrainRevert_ - Sncrd_);
764 if (!wasDrain_ && isDrain_) {
765 if (threePhaseState() || nState_ > 1) {
767 krnDrainStart_ = EffLawT::twoPhaseSatKrn(
drainageParams(), krnSwDrainStart_);
768 krnImbStart_ = krnImbStartNxt_;
770 krnSwImbStart_ = EffLawT::twoPhaseSatKrnInv(
drainageParams(), krnImbStart_);
774 if (!wasDrain_ && !isDrain_) {
775 krnDrainStartNxt_ = EffLawT::twoPhaseSatKrn(
drainageParams(), krnSwWAG_);
776 if (threePhaseState()) {
777 krnImbStartNxt_ = computeKrImbWAG(krnSwWAG_);
780 Scalar swf = computeSwf(krnSwWAG_);
789 EclHysteresisConfig config_{};
790 std::shared_ptr<WagHysteresisConfig::WagHysteresisConfigRecord> wagConfig_{};
791 EffLawParams imbibitionParams_{};
792 EffLawParams drainageParams_{};
797 Scalar krwSwMdc_{-2.0};
798 Scalar krnSwMdc_{2.0};
799 Scalar pcSwMdc_{2.0};
802 Scalar pcSwMic_{1.0};
804 bool initialImb_{
false};
806 bool oilWaterSystem_{
false};
807 bool gasOilSystem_{
false};
808 bool gasWaterSystem_{
false};
815 Scalar deltaSwImbKrn_{};
849 Scalar Krwd_sncri_{};
850 Scalar Krwi_snmax_{};
851 Scalar Krwi_snrmax_{};
852 Scalar Krwd_sncrt_{};
858 Scalar curvatureCapPrs_{};
864 Scalar swatImbStart_{};
865 Scalar swatImbStartNxt_{};
866 Scalar krnSwWAG_{2.0};
867 Scalar krnSwDrainRevert_{2.0};
870 Scalar krnSwDrainStart_{-2.0};
871 Scalar krnSwDrainStartNxt_{};
872 Scalar krnImbStart_{};
873 Scalar krnImbStartNxt_{};
874 Scalar krnDrainStart_{};
875 Scalar krnDrainStartNxt_{};
878 Scalar krnSwImbStart_{};
883 Scalar tolWAG_{0.001};
double curvatureCapPrs() const
Curvature parameter used for capillary pressure hysteresis.
Definition: EclHysteresisConfig.hpp:120
Scalar krnSwMdc() const
Get the saturation of the wetting phase where the last switch from the main drainage curve to imbibit...
Definition: EclHysteresisTwoPhaseLawParams.hpp:320
void setImbibitionParams(const EffLawParams &value, const EclEpsScalingPointsInfo< Scalar > &info, EclTwoPhaseSystemType twoPhaseSystem)
Sets the parameters used for the imbibition curve.
Definition: EclHysteresisTwoPhaseLawParams.hpp:220
EclTwoPhaseSystemType
Specified which fluids are involved in a given twophase material law for endpoint scaling...
Definition: EclEpsConfig.hpp:40
Scalar krwSwMdc() const
Get the saturation of the wetting phase where the last switch from the main drainage curve to imbibit...
Definition: EclHysteresisTwoPhaseLawParams.hpp:304
const EffLawParams & imbibitionParams() const
Returns the parameters used for the imbibition curve.
Definition: EclHysteresisTwoPhaseLawParams.hpp:269
A default implementation of the parameters for the material law which implements the ECL relative per...
Definition: EclHysteresisTwoPhaseLawParams.hpp:49
void setDrainageParams(const EffLawParams &value, const EclEpsScalingPointsInfo< Scalar > &info, EclTwoPhaseSystemType twoPhaseSystem)
Sets the parameters used for the drainage curve.
Definition: EclHysteresisTwoPhaseLawParams.hpp:124
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
This structure represents all values which can be possibly used as scaling points in the endpoint sca...
Definition: EclEpsScalingPoints.hpp:54
void finalize()
Calculate all dependent quantities once the independent quantities of the parameter object have been ...
Definition: EclHysteresisTwoPhaseLawParams.hpp:78
Scalar pcSwMdc() const
Get the saturation of the wetting phase where the last switch from the main drainage curve to imbibit...
Definition: EclHysteresisTwoPhaseLawParams.hpp:279
const WagHysteresisConfig::WagHysteresisConfigRecord & wagConfig() const
Returns the WAG-hysteresis configuration object.
Definition: EclHysteresisTwoPhaseLawParams.hpp:118
Default implementation for asserting finalization of parameter objects.
Scalar deltaSwImbKrn() const
Returns the saturation value which must be added if krn is calculated using the imbibition curve...
Definition: EclHysteresisTwoPhaseLawParams.hpp:360
void setKrwSwMdc(Scalar value)
Set the saturation of the wetting phase where the last switch from the main drainage curve (MDC) to i...
Definition: EclHysteresisTwoPhaseLawParams.hpp:296
void setWagConfig(std::shared_ptr< WagHysteresisConfig::WagHysteresisConfigRecord > value)
Set the WAG-hysteresis configuration object.
Definition: EclHysteresisTwoPhaseLawParams.hpp:109
bool update(Scalar pcSw, Scalar krwSw, Scalar krnSw)
Notify the hysteresis law that a given wetting-phase saturation has been seen.
Definition: EclHysteresisTwoPhaseLawParams.hpp:587
void setConfig(const EclHysteresisConfig &value)
Set the hysteresis configuration object.
Definition: EclHysteresisTwoPhaseLawParams.hpp:97
Specifies the configuration used by the ECL kr/pC hysteresis code.
Definition: EclHysteresisConfig.hpp:39
Specifies the configuration used by the endpoint scaling code.
const EffLawParams & drainageParams() const
Returns the parameters used for the drainage curve.
Definition: EclHysteresisTwoPhaseLawParams.hpp:211
Definition: WagHysteresisConfig.hpp:33
bool enableHysteresis() const
Returns whether hysteresis is enabled.
Definition: EclHysteresisConfig.hpp:51
OPM_HOST_DEVICE void finalize()
Mark the object as finalized.
Definition: EnsureFinalized.hpp:82
void setDeltaSwImbKrn(Scalar value)
Sets the saturation value which must be added if krw is calculated using the imbibition curve...
Definition: EclHysteresisTwoPhaseLawParams.hpp:350
Default implementation for asserting finalization of parameter objects.
Definition: EnsureFinalized.hpp:48
void setKrnSwMdc(Scalar value)
Set the saturation of the wetting phase where the last switch from the main drainage curve (MDC) to i...
Definition: EclHysteresisTwoPhaseLawParams.hpp:312
double modParamTrapped() const
Regularisation parameter used for Killough model.
Definition: EclHysteresisConfig.hpp:112
Class for (de-)serializing.
Definition: Serializer.hpp:94
bool initialImb() const
Status of initial process.
Definition: EclHysteresisTwoPhaseLawParams.hpp:288
int pcHysteresisModel() const
Return the type of the hysteresis model which is used for capillary pressure.
Definition: EclHysteresisConfig.hpp:69
int krHysteresisModel() const
Return the type of the hysteresis model which is used for relative permeability.
Definition: EclHysteresisConfig.hpp:104
const EclHysteresisConfig & config() const
Returns the hysteresis configuration object.
Definition: EclHysteresisTwoPhaseLawParams.hpp:103
Specifies the configuration used by the ECL kr/pC hysteresis code.