From 2d9cff730988e52d483b9bd983de97e952fbf816 Mon Sep 17 00:00:00 2001 From: Wenqing Wang <wenqing.wang@ufz.de> Date: Thu, 10 Nov 2016 15:48:13 +0100 Subject: [PATCH] [Unsat] Added the calculation of the derivative of relative permeability with respect to saturation. --- .../NonWettingPhaseBrookCoreyOilGas.cpp | 14 ++++++- .../NonWettingPhaseBrookCoreyOilGas.h | 4 ++ .../NonWettingPhaseVanGenuchten.cpp | 15 ++++++- .../NonWettingPhaseVanGenuchten.h | 4 ++ .../RelativePermeability.h | 4 ++ .../RelativePermeabilityCurve.h | 10 +++++ .../WettingPhaseBrookCoreyOilGas.cpp | 9 ++++- .../WettingPhaseBrookCoreyOilGas.h | 4 ++ .../WettingPhaseVanGenuchten.cpp | 16 +++++++- .../WettingPhaseVanGenuchten.h | 4 ++ .../TestRelativePermeabilityModel.cpp | 39 +++++++++++++++++++ 11 files changed, 119 insertions(+), 4 deletions(-) diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.cpp b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.cpp index 5a6d09da797..f81ba6d8b7b 100644 --- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.cpp +++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.cpp @@ -28,7 +28,19 @@ double NonWettingPhaseBrookCoreyOilGas::getValue( const double Se = (S - _Sr) / (_Smax - _Sr); const double krel = (1.0 - Se) * (1.0 - Se) * (1.0 - std::pow(Se, 1.0 + 2.0 / _mm)); - return krel < _krel_min ? _krel_min : krel; + return std::max(_krel_min, krel); +} + +double NonWettingPhaseBrookCoreyOilGas::getdValue( + const double saturation_w) const +{ + const double S = MathLib::limitValueInInterval( + saturation_w, _Sr + _minor_offset, _Smax - _minor_offset); + const double Se = (S - _Sr) / (_Smax - _Sr); + return (-2. * (1.0 - Se) * (1.0 - std::pow(Se, 1.0 + 2.0 / _mm)) - + (1.0 + 2.0 / _mm) * (1.0 - Se) * (1.0 - Se) * + std::pow(Se, 2.0 / _mm)) / + (_Smax - _Sr); } } // end namespace diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.h index 32a91922a79..9b34f2e54f9 100644 --- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.h +++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.h @@ -60,6 +60,10 @@ public: /// \param saturation_w Wetting phase saturation double getValue(const double saturation_w) const override; + /// Get the derivative of relative permeability with respect to saturation. + /// \param saturation_w Wetting phase saturation + double getdValue(const double saturation_w) const override; + private: const double _Sr; ///< Residual saturation of wetting phase, 1-Snmax. const double _Smax; ///< Maximum saturation of wetting phase, 1-Snr. diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.cpp b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.cpp index 435c52dc387..f3d397ad26a 100644 --- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.cpp +++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.cpp @@ -27,7 +27,20 @@ double NonWettingPhaseVanGenuchten::getValue(const double saturation_w) const const double Se = (S - _Sr) / (_Smax - _Sr); const double krel = std::cbrt(1.0 - Se) * std::pow(1.0 - std::pow(Se, 1.0 / _mm), 2.0 * _mm); - return krel < _krel_min ? _krel_min : krel; + return std::max(_krel_min, krel); +} + +double NonWettingPhaseVanGenuchten::getdValue(const double saturation_w) const +{ + const double S = MathLib::limitValueInInterval( + saturation_w, _Sr + _minor_offset, _Smax - _minor_offset); + const double Se = (S - _Sr) / (_Smax - _Sr); + const double cbrt1_Se = std::cbrt(1.0 - Se); + const double temp_val = 1.0 - std::pow(Se, 1.0 / _mm); + return (-std::pow(temp_val, 2. * _mm) / (3. * cbrt1_Se * cbrt1_Se) - + 2. * cbrt1_Se * std::pow(temp_val, 2. * _mm - 1.) * + std::pow(Se, (1. - _mm) / _mm)) / + (_Smax - _Sr); } } // end namespace } // end namespace diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.h index f24ecd4d22c..a039616fdb6 100644 --- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.h +++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.h @@ -62,6 +62,10 @@ public: /// \param saturation_w Wetting phase saturation double getValue(const double saturation_w) const override; + /// Get the derivative of relative permeability with respect to saturation. + /// \param saturation_w Wetting phase saturation + double getdValue(const double saturation_w) const override; + private: const double _Sr; ///< Residual saturation of wetting phase, 1-Snmax. const double _Smax; ///< Maximum saturation of wetting phase, 1-Snr. diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeability.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeability.h index 0b62d8ac50b..da69bb2a25b 100644 --- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeability.h +++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeability.h @@ -32,6 +32,10 @@ public: /// \param saturation Wetting phase saturation virtual double getValue(const double saturation) const = 0; + /// Get the derivative of relative permeability with respect to saturation. + /// \param saturation Wetting phase saturation + virtual double getdValue(const double saturation) const = 0; + protected: /** A small number for an offset: * 1. to set the bound of S, the saturation, such that diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeabilityCurve.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeabilityCurve.h index 8232932a5ef..b89b4c7524e 100644 --- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeabilityCurve.h +++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeabilityCurve.h @@ -49,6 +49,16 @@ public: return _curve_data->getValue(S); } + /// Get the derivative of relative permeability with respect to saturation. + /// \param saturation Wetting phase saturation + double getdValue(const double saturation) const override + { + const double S = MathLib::limitValueInInterval( + saturation, _Sr + _minor_offset, _Smax - _minor_offset); + + return _curve_data->getDerivative(S); + } + private: const double _Sr; ///< Residual saturation. const double _Smax; ///< Maximum saturation. diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.cpp b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.cpp index 938bf57d250..cb8cebc589a 100644 --- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.cpp +++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.cpp @@ -26,8 +26,15 @@ double WettingPhaseBrookCoreyOilGas::getValue(const double saturation) const saturation, _Sr + _minor_offset, _Smax - _minor_offset); const double Se = (S - _Sr) / (_Smax - _Sr); const double krel = std::pow(Se, 3.0 + 2.0 / _mm); - return krel < _krel_min ? _krel_min : krel; + return std::max(_krel_min, krel); } +double WettingPhaseBrookCoreyOilGas::getdValue(const double saturation) const +{ + const double S = MathLib::limitValueInInterval( + saturation, _Sr + _minor_offset, _Smax - _minor_offset); + const double Se = (S - _Sr) / (_Smax - _Sr); + return ((3.0 + 2.0 / _mm) * std::pow(Se, 2.0 + 2.0 / _mm)) / (_Smax - _Sr); +} } // end namespace } // end namespace diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.h index 28b095d9982..93283367763 100644 --- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.h +++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.h @@ -56,6 +56,10 @@ public: /// Get relative permeability value. double getValue(const double saturation) const override; + /// Get the derivative of relative permeability with respect to saturation. + /// \param saturation Wetting phase saturation + double getdValue(const double saturation) const override; + private: const double _Sr; ///< Residual saturation. const double _Smax; ///< Maximum saturation. diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.cpp b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.cpp index fdcb70908ac..e1429bce38b 100644 --- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.cpp +++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.cpp @@ -27,7 +27,21 @@ double WettingPhaseVanGenuchten::getValue(const double saturation) const const double Se = (S - _Sr) / (_Smax - _Sr); const double val = 1.0 - std::pow(1.0 - std::pow(Se, 1.0 / _mm), _mm); const double krel = std::sqrt(Se) * val * val; - return krel < _krel_min ? _krel_min : krel; + return std::max(_krel_min, krel); +} + +double WettingPhaseVanGenuchten::getdValue(const double saturation) const +{ + const double S = MathLib::limitValueInInterval( + saturation, _Sr + _minor_offset, _Smax - _minor_offset); + const double Se = (S - _Sr) / (_Smax - _Sr); + const double sqrtSe = std::sqrt(Se); + const double temp_val = 1.0 - std::pow(1.0 - std::pow(Se, 1.0 / _mm), _mm); + return (0.5 * temp_val * temp_val / sqrtSe + + 2. * sqrtSe * temp_val * + std::pow(1.0 - std::pow(Se, 1.0 / _mm), _mm - 1.) * + std::pow(Se, (1.0 - _mm) / _mm)) / + (_Smax - _Sr); } } // end namespace diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.h index 8fd580f378e..c69b0850b8d 100644 --- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.h +++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.h @@ -59,6 +59,10 @@ public: /// Get relative permeability value. double getValue(const double saturation) const override; + /// Get the derivative of relative permeability with respect to saturation. + /// \param saturation Wetting phase saturation + double getdValue(const double saturation) const override; + private: const double _Sr; ///< Residual saturation. const double _Smax; ///< Maximum saturation. diff --git a/Tests/MaterialLib/TestRelativePermeabilityModel.cpp b/Tests/MaterialLib/TestRelativePermeabilityModel.cpp index ae340266fab..7612ed4d8e0 100644 --- a/Tests/MaterialLib/TestRelativePermeabilityModel.cpp +++ b/Tests/MaterialLib/TestRelativePermeabilityModel.cpp @@ -58,9 +58,16 @@ TEST(MaterialPorousMedium, checkWettingPhaseVanGenuchten) 0.0074049488610241927, 0.13546615958442240}; + const double purterbation = 1.e-9; for (std::size_t i = 0; i < S.size(); i++) { ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9); + + // Compare the derivative with numerical one. + ASSERT_NEAR((perm_model->getValue(S[i] + purterbation) - + perm_model->getValue(S[i])) / + purterbation, + perm_model->getdValue(S[i]), 1.e-6); } } @@ -81,9 +88,16 @@ TEST(MaterialPorousMedium, checkNonWettingPhaseVanGenuchten) 0.59527539448807487, 0.49976666464188485, 0.38520070797257489, 0.041219134248319585}; + const double purterbation = 1.e-9; for (std::size_t i = 0; i < S.size(); i++) { ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9); + + // Compare the derivative with numerical one. + ASSERT_NEAR((perm_model->getValue(S[i] + purterbation) - + perm_model->getValue(S[i])) / + purterbation, + perm_model->getdValue(S[i]), 1.e-6); } } @@ -107,9 +121,20 @@ TEST(MaterialPorousMedium, checkWettingPhaseBrookCoreyOilGas) 0.19753086419753069, 1.0}; + const double purterbation = 1.e-9; for (std::size_t i = 0; i < S.size(); i++) { ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9); + + // i == S.size() -1, S(=0.85) is limited to 0.8, and the numerical + // derivative of krel is unavailable. + if (i == S.size() - 1) + continue; + // Compare the derivative with numerical one. + ASSERT_NEAR((perm_model->getValue(S[i] + purterbation) - + perm_model->getValue(S[i])) / + purterbation, + perm_model->getdValue(S[i]), 1.e-6); } } @@ -133,9 +158,16 @@ TEST(MaterialPorousMedium, checkNonWettingPhaseBrookCoreyOilGas) 0.061728395061728412, .0}; + const double purterbation = 1.e-9; for (std::size_t i = 0; i < S.size(); i++) { ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9); + + // Compare the derivative with numerical one. + ASSERT_NEAR((perm_model->getValue(S[i] + purterbation) - + perm_model->getValue(S[i])) / + purterbation, + perm_model->getdValue(S[i]), 1.e-6); } } @@ -155,8 +187,15 @@ TEST(MaterialPorousMedium, checkReletivePermeabilityCurve) std::vector<double> S = {0.2, 0.33, 0.45, 0.52, 0.6, 0.85}; std::vector<double> krel = {0.7, 0.57, 0.451, 0.3824, 0.304, 0.059}; + const double purterbation = 1.e-9; for (std::size_t i = 0; i < S.size(); i++) { ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9); + + // Compare the derivative with numerical one. + ASSERT_NEAR((perm_model->getValue(S[i] + purterbation) - + perm_model->getValue(S[i])) / + purterbation, + perm_model->getdValue(S[i]), 1.e-6); } } -- GitLab