OGS
RelPermNonWettingPhaseVanGenuchtenMualem.cpp
Go to the documentation of this file.
1 
13 
14 #include <algorithm>
15 #include <cmath>
16 #include <limits>
17 
18 #include "BaseLib/Error.h"
19 #include "MaterialLib/MPL/Medium.h"
21 
22 namespace MaterialPropertyLib
23 {
26  const double S_L_r,
27  const double S_n_r,
28  const double m,
29  const double krel_min)
30  : S_L_r_(S_L_r),
31  S_L_max_(1. - S_n_r),
32  m_(m),
33  krel_min_(krel_min),
34  S_L_for_krel_min_(computeSaturationForMinimumRelativePermeability())
35 {
36  name_ = std::move(name);
38 }
39 
41  VariableArray const& variable_array,
42  ParameterLib::SpatialPosition const& /*pos*/, double const /*t*/,
43  double const /*dt*/) const
44 {
45  const double S_L = std::clamp(
46  std::get<double>(
47  variable_array[static_cast<int>(Variable::liquid_saturation)]),
48  S_L_r_, S_L_max_);
49 
50  const double krel = computeValue(S_L);
51  return std::max(krel_min_, krel);
52 }
53 
55  VariableArray const& variable_array, Variable const variable,
56  ParameterLib::SpatialPosition const& /*pos*/, double const /*t*/,
57  double const /*dt*/) const
58 {
59  if (variable != Variable::liquid_saturation)
60  {
61  OGS_FATAL(
62  "RelPermNonWettingPhaseVanGenuchtenMualem::dValue is implemented "
63  "for the derivative with respect to liquid saturation only.");
64  }
65 
66  const double S_L = std::get<double>(
67  variable_array[static_cast<int>(Variable::liquid_saturation)]);
68  if (S_L < S_L_r_ || S_L > S_L_for_krel_min_)
69  {
70  return 0.0;
71  }
72 
73  return computeDerivative(S_L);
74 }
75 
77  const double S_L) const
78 {
79  const double Se = (S_L - S_L_r_) / (S_L_max_ - S_L_r_);
80  return std::sqrt(1.0 - Se) *
81  std::pow(1.0 - std::pow(Se, 1.0 / m_), 2.0 * m_);
82 }
83 
85  const double S_L) const
86 {
87  if (std::fabs(S_L - S_L_max_) < std::numeric_limits<double>::epsilon())
88  {
89  return 0.0;
90  }
91 
92  const double Se = (S_L - S_L_r_) / (S_L_max_ - S_L_r_);
93 
94  const double val1 = std::sqrt(1.0 - Se);
95  const double val2 = 1.0 - std::pow(Se, 1.0 / m_);
96 
97  return (-0.5 * std::pow(val2, 2.0 * m_) / val1 -
98  2.0 * std::pow(Se, -1.0 + 1.0 / m_) * val1 *
99  std::pow(val2, 2.0 * m_ - 1.0)) /
100  (S_L_max_ - S_L_r_);
101 }
104 {
105  double S_for_k_rel_min = 0.5 * (S_L_r_ + S_L_max_);
106  const double tolerance = 1.e-16;
107  const double r0 = computeValue(S_for_k_rel_min) - krel_min_;
108  for (int iterations = 0; iterations < 1000; ++iterations)
109  {
110  const double r = computeValue(S_for_k_rel_min) - krel_min_;
111  S_for_k_rel_min = std::clamp(S_for_k_rel_min, S_L_r_, S_L_max_);
112  S_for_k_rel_min -= r / computeDerivative(S_for_k_rel_min);
113 
114  if (std::fabs(r / r0) < tolerance)
115  {
116  return S_for_k_rel_min;
117  }
118  }
119 
120  OGS_FATAL(
121  "The given minimum relative permeability, {:g}, is not "
122  "associated with the saturation in the range of '('{:f}, {:f}')'. "
123  "Please try another one in '(0, 1)', which should be close to zero",
125 }
126 } // namespace MaterialPropertyLib
#define OGS_FATAL(...)
Definition: Error.h:26
virtual PropertyDataType value() const
Definition: Property.cpp:72
RelPermNonWettingPhaseVanGenuchtenMualem(std::string name, const double S_L_r, const double S_n_r, const double m, const double krel_min)
PropertyDataType dValue(VariableArray const &variable_array, Variable const variable, ParameterLib::SpatialPosition const &pos, double const t, double const dt) const override
std::variant< double, Eigen::Matrix< double, 2, 1 >, Eigen::Matrix< double, 3, 1 >, Eigen::Matrix< double, 2, 2 >, Eigen::Matrix< double, 3, 3 >, Eigen::Matrix< double, 4, 1 >, Eigen::Matrix< double, 6, 1 > > PropertyDataType
Definition: Property.h:35
std::array< VariableType, static_cast< int >(Variable::number_of_variables)> VariableArray
Definition: VariableType.h:108
void checkVanGenuchtenExponentRange(const double m)
static const double r
static double const tolerance