Skip to content
Snippets Groups Projects
Commit 45c16d33 authored by wenqing's avatar wenqing Committed by Dmitri Naumov
Browse files

[MPL/RelPermNonWettingPhaseVanGenuchtenMualem] use the Regula-Falsi method

to seek the saturation corresponding to the minimum relative permeability.
parent a4cabe1a
No related branches found
No related tags found
No related merge requests found
...@@ -18,9 +18,17 @@ ...@@ -18,9 +18,17 @@
#include "BaseLib/Error.h" #include "BaseLib/Error.h"
#include "MaterialLib/MPL/Medium.h" #include "MaterialLib/MPL/Medium.h"
#include "MaterialLib/MPL/Utils/CheckVanGenuchtenExponentRange.h" #include "MaterialLib/MPL/Utils/CheckVanGenuchtenExponentRange.h"
#include "MathLib/Nonlinear/Root1D.h"
namespace MaterialPropertyLib namespace MaterialPropertyLib
{ {
double computeVanGenuchtenMualemValue(const double S_L, const double S_L_r,
const double S_L_max, const double m)
{
const double Se = (S_L - S_L_r) / (S_L_max - S_L_r);
return std::sqrt(1.0 - Se) * std::pow(1.0 - std::pow(Se, 1.0 / m), 2.0 * m);
}
RelPermNonWettingPhaseVanGenuchtenMualem:: RelPermNonWettingPhaseVanGenuchtenMualem::
RelPermNonWettingPhaseVanGenuchtenMualem(std::string name, RelPermNonWettingPhaseVanGenuchtenMualem(std::string name,
const double S_L_r, const double S_L_r,
...@@ -47,7 +55,8 @@ PropertyDataType RelPermNonWettingPhaseVanGenuchtenMualem::value( ...@@ -47,7 +55,8 @@ PropertyDataType RelPermNonWettingPhaseVanGenuchtenMualem::value(
variable_array[static_cast<int>(Variable::liquid_saturation)]), variable_array[static_cast<int>(Variable::liquid_saturation)]),
S_L_r_, S_L_max_); S_L_r_, S_L_max_);
const double krel = computeValue(S_L); const double krel =
computeVanGenuchtenMualemValue(S_L, S_L_r_, S_L_max_, m_);
return std::max(krel_min_, krel); return std::max(krel_min_, krel);
} }
...@@ -70,20 +79,6 @@ PropertyDataType RelPermNonWettingPhaseVanGenuchtenMualem::dValue( ...@@ -70,20 +79,6 @@ PropertyDataType RelPermNonWettingPhaseVanGenuchtenMualem::dValue(
return 0.0; return 0.0;
} }
return computeDerivative(S_L);
}
double RelPermNonWettingPhaseVanGenuchtenMualem::computeValue(
const double S_L) const
{
const double Se = (S_L - S_L_r_) / (S_L_max_ - S_L_r_);
return std::sqrt(1.0 - Se) *
std::pow(1.0 - std::pow(Se, 1.0 / m_), 2.0 * m_);
}
double RelPermNonWettingPhaseVanGenuchtenMualem::computeDerivative(
const double S_L) const
{
if (std::fabs(S_L - S_L_max_) < std::numeric_limits<double>::epsilon()) if (std::fabs(S_L - S_L_max_) < std::numeric_limits<double>::epsilon())
{ {
return 0.0; return 0.0;
...@@ -99,28 +94,23 @@ double RelPermNonWettingPhaseVanGenuchtenMualem::computeDerivative( ...@@ -99,28 +94,23 @@ double RelPermNonWettingPhaseVanGenuchtenMualem::computeDerivative(
std::pow(val2, 2.0 * m_ - 1.0)) / std::pow(val2, 2.0 * m_ - 1.0)) /
(S_L_max_ - S_L_r_); (S_L_max_ - S_L_r_);
} }
double RelPermNonWettingPhaseVanGenuchtenMualem:: double RelPermNonWettingPhaseVanGenuchtenMualem::
computeSaturationForMinimumRelativePermeability() const computeSaturationForMinimumRelativePermeability() const
{ {
double S_for_k_rel_min = 0.5 * (S_L_r_ + S_L_max_); auto f = [this](double S_L) -> double
const double tolerance = 1.e-16;
const double r0 = computeValue(S_for_k_rel_min) - krel_min_;
for (int iterations = 0; iterations < 1000; ++iterations)
{ {
const double r = computeValue(S_for_k_rel_min) - krel_min_; return computeVanGenuchtenMualemValue(S_L, this->S_L_r_, this->S_L_max_,
S_for_k_rel_min = std::clamp(S_for_k_rel_min, S_L_r_, S_L_max_); this->m_) -
S_for_k_rel_min -= r / computeDerivative(S_for_k_rel_min); this->krel_min_;
};
if (std::fabs(r / r0) < tolerance)
{ auto root_finder =
return S_for_k_rel_min; MathLib::Nonlinear::makeRegulaFalsi<MathLib::Nonlinear::Pegasus>(
} f, S_L_r_, S_L_max_);
}
root_finder.step(1000);
OGS_FATAL( return root_finder.getResult();
"The given minimum relative permeability, {:g}, is not "
"associated with the saturation in the range of '('{:f}, {:f}')'. "
"Please try another one in '(0, 1)', which should be close to zero",
krel_min_, S_L_r_, S_L_max_);
} }
} // namespace MaterialPropertyLib } // namespace MaterialPropertyLib
...@@ -33,6 +33,16 @@ class Medium; ...@@ -33,6 +33,16 @@ class Medium;
* &S^L_{\mbox{max}}& \mbox{maximum saturation of wetting phase,}\\ * &S^L_{\mbox{max}}& \mbox{maximum saturation of wetting phase,}\\
* &m\, \in (0, 1) & \mbox{ exponent.}\\ * &m\, \in (0, 1) & \mbox{ exponent.}\\
* \f} * \f}
*
* The derivative of the relative permeability with respect to saturation is
* computed as
* \f[\frac{\mathrm{d} k_{rel}^n}{\mathrm{d}S^L}=
* -(\dfrac{[1-S_e^{1/m}]^{2m}}{2\sqrt{1-S_e}}+2\sqrt{1-S_e}
* {(1-S_e^{1/m})}^{2*m-1}
* S_e^{1/m-1})/(S^L_\mbox{max}-S^L_r) \f]
* As \f$S^L \to S^L_\mbox{max}\f$, or \f$S_e \to 1\f$,
* \f$\dfrac{[1-S_e^{1/m}]^{2m}}{2\sqrt{1-S_e}}\f$ has a limit of zero.
*
*/ */
class RelPermNonWettingPhaseVanGenuchtenMualem final : public Property class RelPermNonWettingPhaseVanGenuchtenMualem final : public Property
{ {
...@@ -74,6 +84,13 @@ public: ...@@ -74,6 +84,13 @@ public:
ParameterLib::SpatialPosition const& pos, ParameterLib::SpatialPosition const& pos,
double const t, double const dt) const override; double const t, double const dt) const override;
/**
* Computes the saturation that gives the minimum relative permeability by
* using the Regula–Falsi Method.
* @return \f$ S^L\f$ that gives the minimum relative permeability.
*/
double computeSaturationForMinimumRelativePermeability() const;
private: private:
const double S_L_r_; ///< Residual saturation of wetting phase. const double S_L_r_; ///< Residual saturation of wetting phase.
const double S_L_max_; ///< Maximum saturation of wetting phase. const double S_L_max_; ///< Maximum saturation of wetting phase.
...@@ -81,31 +98,5 @@ private: ...@@ -81,31 +98,5 @@ private:
const double krel_min_; ///< Minimum relative permeability. const double krel_min_; ///< Minimum relative permeability.
const double const double
S_L_for_krel_min_; ///< Liquid saturation that gives \c krel_min_. S_L_for_krel_min_; ///< Liquid saturation that gives \c krel_min_.
/**
*
* @param S_L Liquid saturation.
* @return \return \\return \f$k_{rel}^n \f$.
*/
double computeValue(const double S_L) const;
/**
* Computes
* \f[\frac{\mathrm{d} k_{rel}^n}{\mathrm{d}S^L}=
* -(\dfrac{[1-S_e^{1/m}]^{2m}}{2\sqrt{1-S_e}}+2\sqrt{1-S_e}
* {(1-S_e^{1/m})}^{2*m-1}
* S_e^{1/m-1})/(S^L_\mbox{max}-S^L_r) \f]
* As \f$S^L \to S^L_\mbox{max}\f$, or \f$S_e \to 1\f$,
* \f$\dfrac{[1-S_e^{1/m}]^{2m}}{2\sqrt{1-S_e}}\f$ has
* limit zero.
* @param S_L Liquid saturation.
* @return \return \f$ \frac{\mathrm{d} k_{rel}^n}{\mathrm{d}S^L} \f$.
*/
double computeDerivative(const double S_L) const;
/**
* Computes the saturation that gives the minimum relative permeability by
* using the Newton-Raphson method.
* @return \f$ S^L\f$ that gives the minimum relative permeability.
*/
double computeSaturationForMinimumRelativePermeability() const;
}; };
} // namespace MaterialPropertyLib } // namespace MaterialPropertyLib
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment