opm-common
Loading...
Searching...
No Matches
EclHysteresisTwoPhaseLawParams.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_ECL_HYSTERESIS_TWO_PHASE_LAW_PARAMS_HPP
28#define OPM_ECL_HYSTERESIS_TWO_PHASE_LAW_PARAMS_HPP
29
30#include <opm/input/eclipse/EclipseState/WagHysteresisConfig.hpp>
31
37
38#include <cassert>
39#include <cmath>
40#include <memory>
41namespace Opm {
48template <class EffLawT>
50{
51 using EffLawParams = typename EffLawT::Params;
52 using Scalar = typename EffLawParams::Traits::Scalar;
53
54public:
55 using Traits = typename EffLawParams::Traits;
56
57 static EclHysteresisTwoPhaseLawParams serializationTestObject()
58 {
60 result.deltaSwImbKrn_ = 1.0;
61 //result.deltaSwImbKrw_ = 1.0;
62 result.Sncrt_ = 2.0;
63 result.Swcrt_ = 2.5;
64 result.initialImb_ = true;
65 result.pcSwMic_ = 3.0;
66 result.krnSwMdc_ = 4.0;
67 result.krwSwMdc_ = 4.5;
68 result.KrndHy_ = 5.0;
69 result.KrwdHy_ = 6.0;
70
71 return result;
72 }
73
78 void finalize()
79 {
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_);
83 curvatureCapPrs_ = config().curvatureCapPrs();
84 }
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());
88 }
89 updateDynamicParams_();
90 }
91 EnsureFinalized :: finalize();
92 }
93
97 void setConfig(const EclHysteresisConfig& value)
98 { config_ = value; }
99
104 { return config_; }
105
109 void setWagConfig(std::shared_ptr<WagHysteresisConfig::WagHysteresisConfigRecord> value)
110 {
111 wagConfig_ = value;
112 cTransf_ = wagConfig().wagLandsParam();
113 }
114
119 { return *wagConfig_; }
120
124 void setDrainageParams(const EffLawParams& value,
126 EclTwoPhaseSystemType twoPhaseSystem)
127 {
128 drainageParams_ = value;
129
130 oilWaterSystem_ = (twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
131 gasWaterSystem_ = (twoPhaseSystem == EclTwoPhaseSystemType::GasWater);
132 gasOilSystem_ = (twoPhaseSystem == EclTwoPhaseSystemType::GasOil);
133
134 if (!config().enableHysteresis())
135 return;
136 if (config().krHysteresisModel() == 2 || config().krHysteresisModel() == 3 || config().krHysteresisModel() == 4 || config().pcHysteresisModel() == 0 || gasOilHysteresisWAG()) {
137 Swco_ = info.Swl;
138 if (twoPhaseSystem == EclTwoPhaseSystemType::GasOil) {
139 Sncrd_ = info.Sgcr + info.Swl;
140 Swcrd_ = info.Sogcr;
141 Snmaxd_ = info.Sgu + info.Swl;
142 KrndMax_ = EffLawT::twoPhaseSatKrn(drainageParams(), 1.0-Snmaxd_);
143 }
144 else if (twoPhaseSystem == EclTwoPhaseSystemType::GasWater) {
145 Sncrd_ = info.Sgcr;
146 Swcrd_ = info.Swcr;
147 Snmaxd_ = info.Sgu;
148 KrndMax_ = EffLawT::twoPhaseSatKrn(drainageParams(), 1.0-Snmaxd_);
149 }
150 else {
151 assert(twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
152 Sncrd_ = info.Sowcr;
153 Swcrd_ = info.Swcr;
154 Snmaxd_ = 1.0 - info.Swl - info.Sgl;
155 KrndMax_ = EffLawT::twoPhaseSatKrn(drainageParams(), 1.0-Snmaxd_);
156 }
157 }
158
159 if (config().krHysteresisModel() == 4) {
160 //Swco_ = info.Swl;
161 if (twoPhaseSystem == EclTwoPhaseSystemType::GasOil) {
162 Swmaxd_ = 1.0 - info.Sgl - info.Swl;
163 KrwdMax_ = EffLawT::twoPhaseSatKrw(drainageParams(), Swmaxd_);
164 }
165 else if (twoPhaseSystem == EclTwoPhaseSystemType::GasWater) {
166 Swmaxd_ = info.Swu;
167 KrwdMax_ = EffLawT::twoPhaseSatKrw(drainageParams(), Swmaxd_);
168 }
169 else {
170 assert(twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
171 Swmaxd_ = info.Swu;
172 KrwdMax_ = EffLawT::twoPhaseSatKrw(drainageParams(), Swmaxd_);
173 }
174 }
175
176 // Additional Killough hysteresis model for pc
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;
182 }
183 else {
184 assert(twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
185 pcmaxd_ = -17.0; // At this point 'info.maxPcow' holds pre-swatinit value ...;
186 }
187 }
188
189 // For WAG hysteresis, assume initial state along primary drainage curve.
190 if (gasOilHysteresisWAG()) {
191 swatImbStart_ = Swco_;
192 swatImbStartNxt_ = -1.0; // Trigger check for saturation gt Swco at first update ...
193 cTransf_ = wagConfig().wagLandsParam();
194 krnSwDrainStart_ = Sncrd_;
195 krnSwDrainStartNxt_ = Sncrd_;
196 krnImbStart_ = 0.0;
197 krnImbStartNxt_ = 0.0;
198 krnDrainStart_ = 0.0;
199 krnDrainStartNxt_ = 0.0;
200 isDrain_ = true;
201 wasDrain_ = true;
202 krnSwImbStart_ = Sncrd_;
203 SncrtWAG_ = Sncrd_;
204 nState_ = 1;
205 }
206 }
207
211 const EffLawParams& drainageParams() const
212 { return drainageParams_; }
213
214 EffLawParams& drainageParams()
215 { return drainageParams_; }
216
220 void setImbibitionParams(const EffLawParams& value,
222 EclTwoPhaseSystemType twoPhaseSystem)
223 {
224 imbibitionParams_ = value;
225
226 if (!config().enableHysteresis())
227 return;
228
229 // Store critical nonwetting saturation
230 if (twoPhaseSystem == EclTwoPhaseSystemType::GasOil) {
231 Sncri_ = info.Sgcr + info.Swl;
232 Swcri_ = info.Sogcr;
233 }
234 else if (twoPhaseSystem == EclTwoPhaseSystemType::GasWater) {
235 Sncri_ = info.Sgcr;
236 Swcri_ = info.Swcr;
237 }
238 else {
239 assert(twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
240 Sncri_ = info.Sowcr;
241 Swcri_ = info.Swcr;
242 }
243
244 // Killough hysteresis model for pc
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) {
250 Swmaxi_ = info.Swu;
251 pcmaxi_ = info.maxPcgo + info.maxPcow;
252 }
253 else {
254 assert(twoPhaseSystem == EclTwoPhaseSystemType::OilWater);
255 Swmaxi_ = info.Swu;
256 pcmaxi_ = info.maxPcow;
257 }
258 }
259
260 if (config().krHysteresisModel() == 4) {
261 Krwi_snmax_ = EffLawT::twoPhaseSatKrw(imbibitionParams(), 1 - Snmaxd());
262 Krwi_snrmax_ = EffLawT::twoPhaseSatKrw(imbibitionParams(), 1 - Sncri());
263 }
264 }
265
269 const EffLawParams& imbibitionParams() const
270 { return imbibitionParams_; }
271
272 EffLawParams& imbibitionParams()
273 { return imbibitionParams_; }
274
279 Scalar pcSwMdc() const
280 { return pcSwMdc_; }
281
282 Scalar pcSwMic() const
283 { return pcSwMic_; }
284
288 bool initialImb() const
289 { return initialImb_; }
290
296 void setKrwSwMdc(Scalar value)
297 { krwSwMdc_ = value; };
298
304 Scalar krwSwMdc() const
305 { return krwSwMdc_; };
306
312 void setKrnSwMdc(Scalar value)
313 { krnSwMdc_ = value; }
314
320 Scalar krnSwMdc() const
321 { return krnSwMdc_; }
322
330 //void setDeltaSwImbKrw(Scalar value)
331 //{ deltaSwImbKrw_ = value; }
332
340 //Scalar deltaSwImbKrw() const
341 //{ return deltaSwImbKrw_; }
342
350 void setDeltaSwImbKrn(Scalar value)
351 { deltaSwImbKrn_ = value; }
352
360 Scalar deltaSwImbKrn() const
361 { return deltaSwImbKrn_; }
362
363
364 Scalar Swcri() const
365 { return Swcri_; }
366
367 Scalar Swcrd() const
368 { return Swcrd_; }
369
370 Scalar Swmaxi() const
371 { return Swmaxi_; }
372
373 Scalar Sncri() const
374 { return Sncri_; }
375
376 Scalar Sncrd() const
377 { return Sncrd_; }
378
379 Scalar Sncrt() const
380 { return Sncrt_; }
381
382 Scalar Swcrt() const
383 { return Swcrt_; }
384
385 Scalar SnTrapped(bool maximumTrapping) const
386 {
387 if(!maximumTrapping && isDrain_)
388 return 0.0;
389
390 // For Killough the trapped saturation is already computed
391 if( config().krHysteresisModel() > 1 )
392 return Sncrt_;
393 else // For Carlson we use the shift to compute it from the critial saturation
394 return Sncri_ + deltaSwImbKrn_;
395 }
396
397 Scalar SnStranded(Scalar sg, Scalar krg) const {
398 const Scalar sn = EffLawT::twoPhaseSatKrnInv(drainageParams_, krg);
399 return sg - (1.0 - sn) + Sncrd_;
400 }
401
402 Scalar SwTrapped() const
403 {
404 if( config().krHysteresisModel() == 0 || config().krHysteresisModel() == 2)
405 return Swcrd_;
406
407 if( config().krHysteresisModel() == 1 || config().krHysteresisModel() == 3)
408 return Swcri_;
409
410 // For Killough the trapped saturation is already computed
411 if( config().krHysteresisModel() == 4 )
412 return Swcrt_;
413
414 return 0.0;
415 //else // For Carlson we use the shift to compute it from the critial saturation
416 // return Swcri_ + deltaSwImbKrw_;
417 }
418
419 Scalar SncrtWAG() const
420 { return SncrtWAG_; }
421
422 Scalar Snmaxd() const
423 { return Snmaxd_; }
424
425 Scalar Swmaxd() const
426 { return Swmaxd_; }
427
428 Scalar Snhy() const
429 { return 1.0 - krnSwMdc_; }
430
431 Scalar Swhy() const
432 { return krwSwMdc_; }
433
434 Scalar Swco() const
435 { return Swco_; }
436
437 Scalar krnWght() const
438 { return KrndHy_/KrndMax_; }
439
440 template <class Evaluation>
441 Evaluation krwWght(const Evaluation& Krwd) const
442 {
443 // a = 1 (deltaKrw)^a Formulation according to KILLOUGH 1976
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());
447 }
448
449 Scalar krwdMax() const
450 {
451 return KrwdMax_; }
452
453 Scalar KrwdHy() const
454 {
455 return KrwdHy_;
456 }
457
458
459 Scalar Krwd_sncri() const
460 {
461 return Krwd_sncri_;
462 }
463
464 Scalar Krwi_snmax() const
465 {
466 return Krwi_snmax_;
467 }
468
469 Scalar Krwi_snrmax() const
470 {
471 return Krwi_snrmax_;
472 }
473
474 Scalar Krwd_sncrt() const
475 {
476 return Krwd_sncrt_;
477 }
478
479 Scalar pcWght() const // Aligning pci and pcd at Swir
480 {
481 if (pcmaxd_ < 0.0)
482 return EffLawT::twoPhaseSatPcnw(drainageParams(), 0.0)/(pcmaxi_+1e-6);
483 else
484 return pcmaxd_/(pcmaxi_+1e-6);
485 }
486
487 Scalar curvatureCapPrs() const
488 { return curvatureCapPrs_;}
489
490 bool gasOilHysteresisWAG() const
491 { return (config().enableWagHysteresis() && gasOilSystem_ && wagConfig().wagGasFlag()) ; }
492
493 Scalar reductionDrain() const
494 { return std::pow(Swco_/(swatImbStart_+tolWAG_*wagConfig().wagWaterThresholdSaturation()), wagConfig().wagSecondaryDrainageReduction());}
495
496 Scalar reductionDrainNxt() const
497 { return std::pow(Swco_/(swatImbStartNxt_+tolWAG_*wagConfig().wagWaterThresholdSaturation()), wagConfig().wagSecondaryDrainageReduction());}
498
499 bool threePhaseState() const
500 { return (swatImbStart_ > (Swco_ + wagConfig().wagWaterThresholdSaturation()) ); }
501
502 Scalar nState() const
503 { return nState_;}
504
505 Scalar krnSwDrainRevert() const
506 { return krnSwDrainRevert_;}
507
508 Scalar krnDrainStart() const
509 { return krnDrainStart_;}
510
511 Scalar krnDrainStartNxt() const
512 { return krnDrainStartNxt_;}
513
514 Scalar krnImbStart() const
515 { return krnImbStart_;}
516
517 Scalar krnImbStartNxt() const
518 { return krnImbStartNxt_;}
519
520 Scalar krnSwWAG() const
521 { return krnSwWAG_;}
522
523 Scalar krnSwDrainStart() const
524 { return krnSwDrainStart_;}
525
526 Scalar krnSwDrainStartNxt() const
527 { return krnSwDrainStartNxt_;}
528
529 Scalar krnSwImbStart() const
530 { return krnSwImbStart_;}
531
532 Scalar tolWAG() const
533 { return tolWAG_;}
534
535 template <class Evaluation>
536 Evaluation computeSwf(const Evaluation& Sw) const
537 {
538 Evaluation SgT = 1.0 - Sw - SncrtWAG(); // Sg-Sg_crit_trapped
539 Scalar SgCut = wagConfig().wagImbCurveLinearFraction()*(Snhy()- SncrtWAG());
540 Evaluation Swf = 1.0;
541 //Scalar C = wagConfig().wagLandsParam();
542 Scalar C = cTransf_;
543
544 if (SgT > SgCut) {
545 Swf -= (Sncrd() + 0.5*( SgT + Opm::sqrt( SgT*SgT + 4.0/C*SgT))); // 1-Sgf
546 }
547 else {
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;
551 SgT *= SgCutSlope;
552 Swf -= (Sncrd() + SgT);
553 }
554
555 return Swf;
556 }
557
558 template <class Evaluation>
559 Evaluation computeKrImbWAG(const Evaluation& Sw) const
560 {
561 Evaluation Swf = Sw;
562 if (nState_ <= 2) // Skipping for "higher order" curves seems consistent with benchmark, further investigations needed ...
563 Swf = computeSwf(Sw);
564 if (Swf <= krnSwDrainStart_) { // Use secondary drainage curve
565 Evaluation Krg = EffLawT::twoPhaseSatKrn(drainageParams_, Swf);
566 Evaluation KrgImb2 = (Krg-krnDrainStart_)*reductionDrain() + krnImbStart_;
567 return KrgImb2;
568 }
569 else { // Fallback to primary drainage curve
570 Evaluation Sn = Sncrd_;
571 if (Swf < 1.0-SncrtWAG_) {
572 // Notation: Sn.. = Sg.. + Swco
573 Evaluation dd = (1.0-krnSwImbStart_ - Sncrd_) / (1.0-krnSwDrainStart_ - SncrtWAG_);
574 Sn += (1.0-Swf-SncrtWAG_)*dd;
575 }
576 Evaluation KrgDrn1 = EffLawT::twoPhaseSatKrn(drainageParams_, 1.0 - Sn);
577 return KrgDrn1;
578 }
579 }
580
587 bool update(Scalar pcSw, Scalar krwSw, Scalar krnSw)
588 {
589 bool updateParams = false;
590
591 if (config().pcHysteresisModel() == 0 && pcSw < pcSwMdc_) {
592 if (pcSwMdc_ == 2.0 && pcSw+1.0e-6 < Swcrd_ && (oilWaterSystem_ || gasWaterSystem_)) {
593 initialImb_ = true;
594 }
595 pcSwMdc_ = pcSw;
596 updateParams = true;
597 }
598
599 if (initialImb_ && pcSw > pcSwMic_) {
600 pcSwMic_ = pcSw;
601 updateParams = true;
602 }
603
604 if (krnSw < krnSwMdc_) {
605 krnSwMdc_ = krnSw;
606 KrndHy_ = EffLawT::twoPhaseSatKrn(drainageParams(), krnSwMdc_);
607 if (config().krHysteresisModel() == 4) {
608 KrwdHy_ = EffLawT::twoPhaseSatKrw(drainageParams(), krnSwMdc_);
609 }
610 updateParams = true;
611 }
612 if (krwSw > krwSwMdc_) {
613 krwSwMdc_ = krwSw; // Only used for output at the moment
614 }
615
616 // for non WAG hysteresis we still keep track of the process
617 // for output purpose.
618 if (!gasOilHysteresisWAG()) {
619 this->isDrain_ = (krnSw <= this->krnSwMdc_);
620 } else {
621 wasDrain_ = isDrain_;
622
623 if (swatImbStartNxt_ < 0.0) { // Initial check ...
624 swatImbStartNxt_ = std::max(Swco_, Swco_ + krnSw - krwSw);
625 // check if we are in threephase state sw > swco + tolWag and so > tolWag
626 // (sw = swco + krnSw - krwSw and so = krwSw for oil/gas params)
627 if ( (swatImbStartNxt_ > Swco_ + tolWAG_) && krwSw > tolWAG_) {
628 swatImbStart_ = swatImbStartNxt_;
629 krnSwWAG_ = krnSw;
630 krnSwDrainStartNxt_ = krnSwWAG_;
631 krnSwDrainStart_ = krnSwDrainStartNxt_;
632 wasDrain_ = false; // Signal start from threephase state ...
633 }
634 }
635
636 if (isDrain_) {
637 if (krnSw <= krnSwWAG_+tolWAG_) { // continue along drainage curve
638 krnSwWAG_ = std::min(krnSw, krnSwWAG_);
639 krnSwDrainRevert_ = krnSwWAG_;
640 updateParams = true;
641 }
642 else { // start new imbibition curve
643 isDrain_ = false;
644 krnSwWAG_ = krnSw;
645 updateParams = true;
646 }
647 }
648 else {
649 if (krnSw >= krnSwWAG_-tolWAG_) { // continue along imbibition curve
650 krnSwWAG_ = std::max(krnSw, krnSwWAG_);
651 krnSwDrainStartNxt_ = krnSwWAG_;
652 swatImbStartNxt_ = std::max(swatImbStartNxt_, Swco_ + krnSw - krwSw);
653 updateParams = true;
654 }
655 else { // start new drainage curve
656 isDrain_ = true;
657 krnSwDrainStart_ = krnSwDrainStartNxt_;
658 swatImbStart_ = swatImbStartNxt_;
659 krnSwWAG_ = krnSw;
660 updateParams = true;
661 }
662 }
663
664 }
665
666 if (updateParams)
667 updateDynamicParams_();
668
669 return updateParams;
670 }
671
672 template<class Serializer>
673 void serializeOp(Serializer& serializer)
674 {
675 // only serializes dynamic state - see update() and updateDynamic_()
676 serializer(deltaSwImbKrn_);
677 //serializer(deltaSwImbKrw_);
678 serializer(Sncrt_);
679 serializer(Swcrt_);
680 serializer(initialImb_);
681 serializer(pcSwMic_);
682 serializer(krnSwMdc_);
683 serializer(krwSwMdc_);
684 serializer(KrndHy_);
685 serializer(KrwdHy_);
686 }
687
688 bool operator==(const EclHysteresisTwoPhaseLawParams& rhs) const
689 {
690 return this->deltaSwImbKrn_ == rhs.deltaSwImbKrn_ &&
691 //this->deltaSwImbKrw_ == rhs.deltaSwImbKrw_ &&
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_;
700 }
701
702private:
703 void updateDynamicParams_()
704 {
705 // calculate the saturation deltas for the relative permeabilities
706 //if (false) { // we dont support Carlson for wetting phase hysteresis
707 //Scalar krwMdcDrainage = EffLawT::twoPhaseSatKrw(drainageParams(), krwSwMdc_);
708 //Scalar SwKrwMdcImbibition = EffLawT::twoPhaseSatKrwInv(imbibitionParams(), krwMdcDrainage);
709 //deltaSwImbKrw_ = SwKrwMdcImbibition - krwSwMdc_;
710 //}
711
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_;
716 }
717
718 // Scalar pcMdcDrainage = EffLawT::twoPhaseSatPcnw(drainageParams(), pcSwMdc_);
719 // Scalar SwPcMdcImbibition = EffLawT::twoPhaseSatPcnwInv(imbibitionParams(), pcMdcDrainage);
720 // deltaSwImbPc_ = SwPcMdcImbibition - pcSwMdc_;
721
722 if (config().krHysteresisModel() == 2 ||
723 config().krHysteresisModel() == 3 ||
724 config().krHysteresisModel() == 4 ||
725 config().pcHysteresisModel() == 0)
726 {
727 const Scalar snhy = 1.0 - krnSwMdc_;
728 if (snhy > Sncrd_) {
729 Sncrt_ = Sncrd_ + (snhy - Sncrd_) /
730 ((1.0 + config().modParamTrapped()*(Snmaxd_ - snhy)) + C_ * (snhy - Sncrd_));
731 }
732 else {
733 Sncrt_ = Sncrd_;
734 }
735 }
736
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_));
742 } else {
743 Swcrt_ = Swcrd_;
744 }
745 Krwd_sncrt_ = EffLawT::twoPhaseSatKrw(drainageParams(), 1 - Sncrt());
746 }
747
748
749 if (gasOilHysteresisWAG()) {
750 if (isDrain_ && krnSwMdc_ == krnSwWAG_) {
751 Scalar snhy = 1.0 - krnSwMdc_;
752 SncrtWAG_ = Sncrd_;
753 if (snhy > Sncrd_) {
754 SncrtWAG_ += (snhy - Sncrd_) /
755 (1.0 + config().modParamTrapped() * (Snmaxd_ - snhy) +
756 wagConfig().wagLandsParam() * (snhy - Sncrd_));
757 }
758 }
759
760 if (isDrain_ && (1.0 - krnSwDrainRevert_) > SncrtWAG_) { // Reversal from drain to imb
761 cTransf_ = 1.0 / (SncrtWAG_ - Sncrd_ + 1.0e-12) - 1.0 / (1.0 - krnSwDrainRevert_ - Sncrd_);
762 }
763
764 if (!wasDrain_ && isDrain_) { // Start of new drainage cycle
765 if (threePhaseState() || nState_ > 1) { // Never return to primary (two-phase) state after leaving
766 nState_ += 1;
767 krnDrainStart_ = EffLawT::twoPhaseSatKrn(drainageParams(), krnSwDrainStart_);
768 krnImbStart_ = krnImbStartNxt_;
769 // Scanning shift for primary drainage
770 krnSwImbStart_ = EffLawT::twoPhaseSatKrnInv(drainageParams(), krnImbStart_);
771 }
772 }
773
774 if (!wasDrain_ && !isDrain_) { //Moving along current imb curve
775 krnDrainStartNxt_ = EffLawT::twoPhaseSatKrn(drainageParams(), krnSwWAG_);
776 if (threePhaseState()) {
777 krnImbStartNxt_ = computeKrImbWAG(krnSwWAG_);
778 }
779 else {
780 Scalar swf = computeSwf(krnSwWAG_);
781 krnImbStartNxt_ = EffLawT::twoPhaseSatKrn(drainageParams(), swf);
782 }
783 }
784
785 }
786
787 }
788
789 EclHysteresisConfig config_{};
790 std::shared_ptr<WagHysteresisConfig::WagHysteresisConfigRecord> wagConfig_{};
791 EffLawParams imbibitionParams_{};
792 EffLawParams drainageParams_{};
793
794 // largest wettinging phase saturation which is on the main-drainage curve. These are
795 // three different values because the sourounding code can choose to use different
796 // definitions for the saturations for different quantities
797 Scalar krwSwMdc_{-2.0};
798 Scalar krnSwMdc_{2.0};
799 Scalar pcSwMdc_{2.0};
800
801 // largest wettinging phase saturation along main imbibition curve
802 Scalar pcSwMic_{1.0};
803 // Initial process is imbibition (for initial saturations at or below critical drainage saturation)
804 bool initialImb_{false};
805
806 bool oilWaterSystem_{false};
807 bool gasOilSystem_{false};
808 bool gasWaterSystem_{false};
809
810
811 // offsets added to wetting phase saturation uf using the imbibition curves need to
812 // be used to calculate the wetting phase relperm, the non-wetting phase relperm and
813 // the capillary pressure
814 //Scalar deltaSwImbKrw_{};
815 Scalar deltaSwImbKrn_{};
816 //Scalar deltaSwImbPc_;
817
818 // the following uses the conventions of the Eclipse technical description:
819 //
820 // Sncrd_: critical non-wetting phase saturation for the drainage curve
821 // Sncri_: critical non-wetting phase saturation for the imbibition curve
822 // Swcri_: critical wetting phase saturation for the imbibition curve
823 // Swcrd_: critical wetting phase saturation for the drainage curve
824 // Swmaxi_; maximum wetting phase saturation for the imbibition curve
825 // Snmaxd_: non-wetting phase saturation where the non-wetting relperm reaches its
826 // maximum on the drainage curve
827 // C_: factor required to calculate the trapped non-wetting phase saturation using
828 // the Killough approach
829 // Cw_: factor required to calculate the trapped wetting phase saturation using
830 // the Killough approach
831 // Swcod_: connate water saturation value used for wag hysteresis (2. drainage)
832 Scalar Sncrd_{};
833 Scalar Sncri_{};
834 Scalar Swcri_{};
835 Scalar Swcrd_{};
836 Scalar Swmaxi_{};
837 Scalar Snmaxd_{};
838 Scalar Swmaxd_{};
839 Scalar C_{};
840
841 Scalar KrndMax_{}; // Krn_drain(Snmaxd_)
842 Scalar KrwdMax_{}; // Krw_drain(Swmaxd_)
843 Scalar KrndHy_{}; // Krn_drain(1-krnSwMdc_)
844
845
846 // For wetting hysterese Killough
847 Scalar Cw_{};
848 Scalar KrwdHy_{};
849 Scalar Krwd_sncri_{};
850 Scalar Krwi_snmax_{};
851 Scalar Krwi_snrmax_{};
852 Scalar Krwd_sncrt_{};
853 Scalar Swcrt_{}; // trapped wetting phase saturation
854
855 Scalar pcmaxd_{}; // max pc for drain
856 Scalar pcmaxi_{}; // max pc for imb
857
858 Scalar curvatureCapPrs_{}; // curvature parameter used for capillary pressure hysteresis
859
860 Scalar Sncrt_{}; // trapped non-wetting phase saturation
861
862 // Used for WAG hysteresis
863 Scalar Swco_{}; // Connate water.
864 Scalar swatImbStart_{}; // Water saturation at start of current drainage curve (end of previous imb curve).
865 Scalar swatImbStartNxt_{}; // Water saturation at start of next drainage curve (end of current imb curve).
866 Scalar krnSwWAG_{2.0}; // Saturation value after latest completed timestep.
867 Scalar krnSwDrainRevert_{2.0}; // Saturation value at end of current drainage curve.
868 Scalar cTransf_{}; // Modified Lands constant used for free gas calculations to obtain consistent scanning curve
869 // when reversion to imb occurs above historical maximum gas saturation (i.e. Sw > krwSwMdc_).
870 Scalar krnSwDrainStart_{-2.0}; // Saturation value at start of current drainage curve (end of previous imb curve).
871 Scalar krnSwDrainStartNxt_{}; // Saturation value at start of current drainage curve (end of previous imb curve).
872 Scalar krnImbStart_{}; // Relperm at start of current drainage curve (end of previous imb curve).
873 Scalar krnImbStartNxt_{}; // Relperm at start of next drainage curve (end of current imb curve).
874 Scalar krnDrainStart_{}; // Primary (input) relperm evaluated at start of current drainage curve.
875 Scalar krnDrainStartNxt_{}; // Primary (input) relperm evaluated at start of next drainage curve.
876 bool isDrain_{true}; // Status is either drainage or imbibition
877 bool wasDrain_{}; // Previous status.
878 Scalar krnSwImbStart_{}; // Saturation value where primary drainage relperm equals krnImbStart_
879
880 int nState_{}; // Number of cycles. Primary cycle is nState_=1.
881
882 Scalar SncrtWAG_{};
883 Scalar tolWAG_{0.001};
884};
885
886} // namespace Opm
887
888#endif
Specifies the configuration used by the endpoint scaling code.
Specifies the configuration used by the ECL kr/pC hysteresis code.
Default implementation for asserting finalization of parameter objects.
A traits class which provides basic mathematical functions for arbitrary scalar floating point values...
Specifies the configuration used by the ECL kr/pC hysteresis code.
Definition EclHysteresisConfig.hpp:40
double curvatureCapPrs() const
Curvature parameter used for capillary pressure hysteresis.
Definition EclHysteresisConfig.hpp:120
A default implementation of the parameters for the material law which implements the ECL relative per...
Definition EclHysteresisTwoPhaseLawParams.hpp:50
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
bool initialImb() const
Status of initial process.
Definition EclHysteresisTwoPhaseLawParams.hpp:288
const EclHysteresisConfig & config() const
Returns the hysteresis configuration object.
Definition EclHysteresisTwoPhaseLawParams.hpp:103
void setDeltaSwImbKrn(Scalar value)
Sets the saturation value which must be added if krw is calculated using the imbibition curve.
Definition EclHysteresisTwoPhaseLawParams.hpp:350
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
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 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
void setWagConfig(std::shared_ptr< WagHysteresisConfig::WagHysteresisConfigRecord > value)
Set the WAG-hysteresis configuration object.
Definition EclHysteresisTwoPhaseLawParams.hpp:109
void finalize()
Calculate all dependent quantities once the independent quantities of the parameter object have been ...
Definition EclHysteresisTwoPhaseLawParams.hpp:78
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 setDrainageParams(const EffLawParams &value, const EclEpsScalingPointsInfo< Scalar > &info, EclTwoPhaseSystemType twoPhaseSystem)
Sets the parameters used for the drainage curve.
Definition EclHysteresisTwoPhaseLawParams.hpp:124
const WagHysteresisConfig::WagHysteresisConfigRecord & wagConfig() const
Returns the WAG-hysteresis configuration object.
Definition EclHysteresisTwoPhaseLawParams.hpp:118
Scalar deltaSwImbKrn() const
Returns the saturation value which must be added if krn is calculated using the imbibition curve.
Definition EclHysteresisTwoPhaseLawParams.hpp:360
void setImbibitionParams(const EffLawParams &value, const EclEpsScalingPointsInfo< Scalar > &info, EclTwoPhaseSystemType twoPhaseSystem)
Sets the parameters used for the imbibition curve.
Definition EclHysteresisTwoPhaseLawParams.hpp:220
const EffLawParams & imbibitionParams() const
Returns the parameters used for the imbibition curve.
Definition EclHysteresisTwoPhaseLawParams.hpp:269
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
void setConfig(const EclHysteresisConfig &value)
Set the hysteresis configuration object.
Definition EclHysteresisTwoPhaseLawParams.hpp:97
const EffLawParams & drainageParams() const
Returns the parameters used for the drainage curve.
Definition EclHysteresisTwoPhaseLawParams.hpp:211
OPM_HOST_DEVICE EnsureFinalized()
The default constructor.
Definition EnsureFinalized.hpp:58
Class for (de-)serializing.
Definition Serializer.hpp:94
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition Exceptions.hpp:30
EclTwoPhaseSystemType
Specified which fluids are involved in a given twophase material law for endpoint scaling.
Definition EclEpsConfig.hpp:40
This structure represents all values which can be possibly used as scaling points in the endpoint sca...
Definition EclEpsScalingPoints.hpp:55
Definition WagHysteresisConfig.hpp:33