Implement Three-Point Vertical Scaling for Krn

This commit implements the vertical scaling mode activated by the
keywords KRORW, KRORG, and KRGR.  This is the same scaling mode as
the KRWR feature implemented, but requires reversing the logic since
we implement the non-wetting phase's relative permeability function
in terms of the wetting phase's saturation.
This commit is contained in:
Bård Skaflestad 2021-01-12 15:06:17 +01:00
parent 2f07358322
commit a56df026be
2 changed files with 85 additions and 9 deletions

View File

@ -124,6 +124,20 @@ public:
bool enableThreePointKrwScaling() const
{ return this->enableThreePointKrwScaling_; }
/*!
* \brief Specify whether three-point relative permeability value
* scaling is enabled for the wetting phase (e.g., KRORW + KRO).
*/
void setEnableThreePointKrnScaling(const bool enable)
{ this->enableThreePointKrnScaling_ = enable; }
/*!
* \brief Whether or not three-point relative permeability value scaling
* is enabled for the non-wetting phase (e.g., KRORW + KRO).
*/
bool enableThreePointKrnScaling() const
{ return this->enableThreePointKrnScaling_; }
/*!
* \brief Specify whether relative permeability scaling is enabled for the non-wetting phase.
*/
@ -220,15 +234,20 @@ public:
// check if we are supposed to scale the Y axis of the capillary pressure
if (twoPhaseSystemType == EclOilWaterSystem) {
this->setEnableThreePointKrwScaling(hasKR("WR"));
this->setEnableThreePointKrnScaling(hasKR("ORW"));
this->enableKrnScaling_ = hasKR("O");
this->enableKrnScaling_ = hasKR("O") || this->enableThreePointKrnScaling();
this->enableKrwScaling_ = hasKR("W") || this->enableThreePointKrwScaling();
this->enablePcScaling_ = hasPC("W") || fp.has_double("SWATINIT");
}
else {
assert(twoPhaseSystemType == EclGasOilSystem);
this->enableKrnScaling_ = hasKR("G");
this->enableKrwScaling_ = hasKR("O");
this->setEnableThreePointKrwScaling(hasKR("ORG"));
this->setEnableThreePointKrnScaling(hasKR("GR"));
this->enableKrnScaling_ = hasKR("G") || this->enableThreePointKrnScaling();
this->enableKrwScaling_ = hasKR("O") || this->enableThreePointKrwScaling();
this->enablePcScaling_ = hasPC("G");
}
@ -262,6 +281,9 @@ private:
// Employ three-point vertical scaling (e.g., KRWR and KRW).
bool enableThreePointKrwScaling_{false};
// Employ three-point vertical scaling (e.g., KRORW and KRO).
bool enableThreePointKrnScaling_{false};
};
} // namespace Opm

View File

@ -250,7 +250,7 @@ public:
{
const Evaluation SwUnscaled = scaledToUnscaledSatKrn(params, SwScaled);
const Evaluation krnUnscaled = EffLaw::twoPhaseSatKrn(params.effectiveLawParams(), SwUnscaled);
return unscaledToScaledKrn_(params, krnUnscaled);
return unscaledToScaledKrn_(SwScaled, params, krnUnscaled);
}
template <class Evaluation>
@ -581,14 +581,68 @@ private:
* \brief Scale the non-wetting phase relative permeability of a phase according to the given parameters
*/
template <class Evaluation>
static Evaluation unscaledToScaledKrn_(const Params& params, const Evaluation& unscaledKrn)
static Evaluation unscaledToScaledKrn_(const Evaluation& SwScaled,
const Params& params,
const Evaluation& unscaledKrn)
{
if (!params.config().enableKrnScaling())
const auto& cfg = params.config();
if (! cfg.enableKrnScaling())
return unscaledKrn;
//TODO: three point krn y-scaling
Scalar alpha = params.scaledPoints().maxKrn()/params.unscaledPoints().maxKrn();
return unscaledKrn*alpha;
const auto& scaled = params.scaledPoints();
const auto& unscaled = params.unscaledPoints();
if (! cfg.enableThreePointKrnScaling()) {
// Simple case: Run uses pure vertical scaling of non-wetting
// phase's relative permeability (e.g., KRG)
const Scalar alpha = scaled.maxKrn() / unscaled.maxKrn();
return unscaledKrn * alpha;
}
// Otherwise, run uses three-point vertical scaling (e.g., keywords KRGR and KRG)
const auto fdisp = unscaled.krnr();
const auto fmax = unscaled.maxKrn();
const auto sl = scaled.saturationKrnPoints()[0];
const auto sr = std::max(scaled.saturationKrnPoints()[1], sl);
const auto fr = scaled.krnr();
const auto fm = scaled.maxKrn();
// Note logic here. Krn is a decreasing function of Sw (dKrn/dSw <=
// 0) so the roles of left and right intervals are reversed viz
// unscaledToScaledKrw_().
if (! (SwScaled < sr)) {
// Pure vertical scaling in right-hand interval ([SR, SWU])
return unscaledKrn * (fr / fdisp);
}
else if (fmax > fdisp) {
// s \in [SWL, SR), SWL < SR; normal case: Kr(Swl) > Kr(Sr).
//
// Linear function between (sr,fr) and (sl,fm) in terms of
// function value 'unscaledKrn'. This usually alters the shape
// of the relative permeability function in this interval (e.g.,
// roughly quadratic to linear).
const auto t = (unscaledKrn - fdisp) / (fmax - fdisp);
return fr + t*(fm - fr);
}
else if (sr > sl) {
// s \in [SWL, SR), SWL < SR; special case: Kr(Swl) == Kr(Sr).
//
// Linear function between (sr,fr) and (sl,fm) in terms of
// saturation value 'SwScaled'. This usually alters the shape
// of the relative permeability function in this interval (e.g.,
// roughly quadratic to linear).
const auto t = (sr - SwScaled) / (sr - sl);
return fr + t*(fm - fr);
}
else {
// sl == sr (pure scaling). Almost arbitrarily pick 'fm'.
return fm;
}
}
template <class Evaluation>