15 #include "libmesh/utility.h"
24 params.addRequiredRangeCheckedParam<Real>(
27 "Low saturation. This must be < Ss, and non-negative. This is BW's "
28 "initial effective saturation, below which effective saturation never goes "
29 "in their simulations/models. If Kn=0 then Sn is the immobile saturation. "
30 "This form of effective saturation is only correct for Kn small.");
31 params.addRangeCheckedParam<Real>(
35 "High saturation. This must be > Sn and <= 1. Effective saturation "
36 "where porepressure = 0. Effective saturation never exceeds this "
37 "value in BW's simulations/models.");
38 params.addRequiredRangeCheckedParam<Real>(
39 "C",
"C > 1",
"BW's C parameter. Must be > 1. Typical value would be 1.05.");
40 params.addRequiredRangeCheckedParam<Real>(
"las",
42 "BW's lambda_s parameter multiplied "
43 "by (fluiddensity*gravity). Must be "
44 "> 0. Typical value would be 1E5");
45 params.addClassDescription(
"Broadbridge-white form of effective saturation for negligable Kn. "
46 "Then porepressure = -las*( (1-th)/th - (1/c)Ln((C-th)/((C-1)th))), "
47 "for th = (Seff - Sn)/(Ss - Sn). A Lambert-W function must be "
48 "evaluated to express Seff in terms of porepressure, which can be "
55 _sn(getParam<Real>(
"Sn")),
56 _ss(getParam<Real>(
"Ss")),
57 _c(getParam<Real>(
"C")),
58 _las(getParam<Real>(
"las"))
61 mooseError(
"In BW effective saturation Sn set to ",
65 " but these must obey Ss > Sn");
93 mooseAssert(z > 0,
"LambertW function in RichardsSeff1BWsmall called with negative argument");
96 const Real eps = 4.0e-16;
125 p = std::sqrt(2.0 * (2.7182818284590452353602874713526625 * z + 1.0));
126 w = -1.0 + p * (1.0 + p * (-0.333333333333333333333 + p * 0.152777777777777777777777));
132 for (i = 0; i < 10; i++)
138 t /= e * p - 0.5 * (p + 1.0) * t / p;
140 if (std::abs(t) < eps * (1.0 + std::abs(w)))
144 mooseError(
"LambertW: No convergence at z= ", z,
"\n");
150 Real pp = (*p[0])[qp];
154 Real x = (
_c - 1.0) * std::exp(
_c - 1 -
_c * pp /
_las);
162 std::vector<Real> & result)
const
166 Real pp = (*p[0])[qp];
170 Real x = (
_c - 1) * std::exp(
_c - 1.0 -
_c * pp /
_las);
172 result[0] = Utility::pow<2>(
_c) /
_las * lamw / Utility::pow<3>(1 + lamw);
178 std::vector<std::vector<Real>> & result)
const
182 Real pp = (*p[0])[qp];
186 Real x = (
_c - 1) * std::exp(
_c - 1 -
_c * pp /
_las);
188 result[0][0] = -Utility::pow<3>(
_c) / Utility::pow<2>(
_las) * lamw * (1.0 - 2.0 * lamw) /
189 Utility::pow<5>(1 + lamw);