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 bool enableThreePointKrwScaling() const
{ return this->enableThreePointKrwScaling_; } { 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. * \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 // check if we are supposed to scale the Y axis of the capillary pressure
if (twoPhaseSystemType == EclOilWaterSystem) { if (twoPhaseSystemType == EclOilWaterSystem) {
this->setEnableThreePointKrwScaling(hasKR("WR")); 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->enableKrwScaling_ = hasKR("W") || this->enableThreePointKrwScaling();
this->enablePcScaling_ = hasPC("W") || fp.has_double("SWATINIT"); this->enablePcScaling_ = hasPC("W") || fp.has_double("SWATINIT");
} }
else { else {
assert(twoPhaseSystemType == EclGasOilSystem); 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"); this->enablePcScaling_ = hasPC("G");
} }
@ -262,6 +281,9 @@ private:
// Employ three-point vertical scaling (e.g., KRWR and KRW). // Employ three-point vertical scaling (e.g., KRWR and KRW).
bool enableThreePointKrwScaling_{false}; bool enableThreePointKrwScaling_{false};
// Employ three-point vertical scaling (e.g., KRORW and KRO).
bool enableThreePointKrnScaling_{false};
}; };
} // namespace Opm } // namespace Opm

View File

@ -250,7 +250,7 @@ public:
{ {
const Evaluation SwUnscaled = scaledToUnscaledSatKrn(params, SwScaled); const Evaluation SwUnscaled = scaledToUnscaledSatKrn(params, SwScaled);
const Evaluation krnUnscaled = EffLaw::twoPhaseSatKrn(params.effectiveLawParams(), SwUnscaled); const Evaluation krnUnscaled = EffLaw::twoPhaseSatKrn(params.effectiveLawParams(), SwUnscaled);
return unscaledToScaledKrn_(params, krnUnscaled); return unscaledToScaledKrn_(SwScaled, params, krnUnscaled);
} }
template <class Evaluation> template <class Evaluation>
@ -581,14 +581,68 @@ private:
* \brief Scale the non-wetting phase relative permeability of a phase according to the given parameters * \brief Scale the non-wetting phase relative permeability of a phase according to the given parameters
*/ */
template <class Evaluation> 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; return unscaledKrn;
//TODO: three point krn y-scaling const auto& scaled = params.scaledPoints();
Scalar alpha = params.scaledPoints().maxKrn()/params.unscaledPoints().maxKrn(); const auto& unscaled = params.unscaledPoints();
return unscaledKrn*alpha;
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> template <class Evaluation>