https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Classes | Functions
PorousFlowVanGenuchten Namespace Reference

van Genuchten effective saturation, capillary pressure and relative permeability functions. More...

Classes

struct  HighCapillaryPressureExtension
 Parameters associated with the extension of the hysteretic wetting capillary pressure function to high saturation values @ ExtensionStrategy the type of extension used @ S liquid saturation at the point of extension @ Pc capillary pressure at the point of extension @ dPc d(Pc)/dS at the point of extension. More...
 
struct  LowCapillaryPressureExtension
 Parameters associated with the extension of the hysteretic capillary pressure function to low saturation values @ ExtensionStrategy the type of extension used @ S liquid saturation at the point of extension @ Pc capillary pressure at the point of extension @ dPc d(Pc)/dS at the point of extension. More...
 

Functions

Real effectiveSaturation (Real p, Real alpha, Real m)
 Effective saturation as a function of porepressure.
 
Real dEffectiveSaturation (Real p, Real alpha, Real m)
 Derivative of effective saturation wrt porepressure.
 
Real d2EffectiveSaturation (Real p, Real alpha, Real m)
 Second derivative of effective saturation wrt porepressure.
 
Real capillaryPressure (Real seff, Real alpha, Real m, Real pc_max)
 Capillary pressure as a function of effective saturation.
 
Real dCapillaryPressure (Real seff, Real alpha, Real m, Real pc_max)
 Derivative of capillary pressure wrt effective saturation.
 
Real d2CapillaryPressure (Real seff, Real alpha, Real m, Real pc_max)
 Second derivative of capillary pressure wrt effective saturation.
 
template<typename T >
T relativePermeability (const T &seff, Real m)
 Relative permeability as a function of effective saturation.
 
Real dRelativePermeability (Real seff, Real m)
 Derivative of relative permeability with respect to effective saturation.
 
Real d2RelativePermeability (Real seff, Real m)
 Second derivative of relative permeability with respect to effective saturation.
 
template<typename T >
T relativePermeabilityNW (const T &seff, Real m)
 Relative permeability for a non-wetting phase as a function of effective saturation.
 
Real dRelativePermeabilityNW (Real seff, Real m)
 Derivative of relative permeability for a non-wetting phase with respect to effective saturation.
 
Real d2RelativePermeabilityNW (Real seff, Real m)
 Second derivative of relative permeability for a non-wetting phase with respect to effective saturation.
 
void dataStore (std::ostream &stream, LowCapillaryPressureExtension &extension, void *context)
 
void dataLoad (std::istream &stream, LowCapillaryPressureExtension &extension, void *context)
 
void dataStore (std::ostream &stream, HighCapillaryPressureExtension &extension, void *context)
 
void dataLoad (std::istream &stream, HighCapillaryPressureExtension &extension, void *context)
 
Real capillaryPressureHys (Real sl, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
 Hysteretic capillary pressure function (Eqn(1) of Doughty2007) with extensions (page5 and Fig1 of Doughty2008).
 
Real dcapillaryPressureHys (Real sl, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
 Derivative of capillaryPressureHys with respect to sl.
 
Real d2capillaryPressureHys (Real sl, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
 Second derivative of capillaryPressureHys with respect to sl.
 
Real saturationHys (Real pc, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
 Hysteretic saturation function (Eqn(1) of Doughty2007) with extensions (page5 and Fig1 of Doughty2008), which is the inverse of capillaryPressureHys.
 
Real dsaturationHys (Real pc, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
 Derivative of Hysteretic saturation function with respect to pc.
 
Real d2saturationHys (Real pc, Real slmin, Real sgrdel, Real alpha, Real n, const LowCapillaryPressureExtension &low_ext=LowCapillaryPressureExtension(), const HighCapillaryPressureExtension &high_ext=HighCapillaryPressureExtension())
 Second derivative of Hysteretic saturation function with respect to pc.
 
Real relativePermeabilityHys (Real sl, Real slr, Real sgrdel, Real sgrmax, Real sldel, Real m, Real upper_liquid_param, Real y0, Real y0p, Real y1, Real y1p)
 Hysteretic relative permeability for liquid.
 
Real drelativePermeabilityHys (Real sl, Real slr, Real sgrdel, Real sgrmax, Real sldel, Real m, Real upper_liquid_param, Real y0, Real y0p, Real y1, Real y1p)
 Derivative of Hysteretic relative permeability for liquid, with respect to liquid saturation.
 
Real relativePermeabilityNWHys (Real sl, Real slr, Real sgrdel, Real sgrmax, Real sldel, Real m, Real gamma, Real k_rg_max, Real y0p)
 Hysteretic relative permeability for gas.
 
Real drelativePermeabilityNWHys (Real sl, Real slr, Real sgrdel, Real sgrmax, Real sldel, Real m, Real gamma, Real k_rg_max, Real y0p)
 Derivative of hysteretic relative permeability for gas with respect to the liquid saturation.
 

Detailed Description

van Genuchten effective saturation, capillary pressure and relative permeability functions.

Note: effective saturation is provided as a function of porepressure, not capillary pressure. Note: capillary pressure and relative permeability are functions of effective saturation. The derivatives are therefore given wrt effective saturation. These derivatives must be multiplied by the derivative of effective saturation wrt the true saturation in objects using these relations.

Based on van Genuchten, M. Th., A closed for equation for predicting the hydraulic conductivity of unsaturated soils, Soil Sci. Soc., 44, 892-898 (1980).

Function Documentation

◆ capillaryPressure()

Real PorousFlowVanGenuchten::capillaryPressure ( Real  seff,
Real  alpha,
Real  m,
Real  pc_max 
)

Capillary pressure as a function of effective saturation.

Parameters
seffeffective saturation
alphavan Genuchten parameter
mvan Genuchten exponent
pc_maxmaximum capillary pressure (Pa)
Returns
capillary pressure (Pa)

Definition at line 110 of file PorousFlowVanGenuchten.C.

111{
112 if (seff >= 1.0)
113 return 0.0;
114 else if (seff <= 0.0)
115 return pc_max;
116 else
117 {
118 Real a = std::pow(seff, -1.0 / m) - 1.0;
119 return std::min(std::pow(a, 1.0 - m) / alpha, pc_max);
120 }
121}

Referenced by PorousFlowCapillaryPressureVG::capillaryPressureCurve(), TEST(), and TEST().

◆ capillaryPressureHys()

Real PorousFlowVanGenuchten::capillaryPressureHys ( Real  sl,
Real  slmin,
Real  sgrdel,
Real  alpha,
Real  n,
const LowCapillaryPressureExtension low_ext = LowCapillaryPressureExtension(),
const HighCapillaryPressureExtension high_ext = HighCapillaryPressureExtension() 
)

Hysteretic capillary pressure function (Eqn(1) of Doughty2007) with extensions (page5 and Fig1 of Doughty2008).

NOTE: this function is undefined for sl < 0 and sl > 1, so you MUST ensure 0 <= sl <= 1 NOTE: this returns a non-negative quantity.

Parameters
slliquid saturation. 0 <= sl <= 1
slminvalue of liquid sat where the van Genuchten expression -> infinity. 0 <= slmin < 1
sgrdelvalue of gas saturation where van Genuchten expression -> 0. slmin < 1 - Sgrdel <= 1
alphavan Genuchten alpha parameter, with dimensions 1/Pa. alpha > 0
nvan Genuchten n parameter. n > 1
low_extstrategy and parameters to use for the extension in the small-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)
high_extstrategy and parameters to use for the extension in the high-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)

Definition at line 227 of file PorousFlowVanGenuchten.C.

234{
235 Real pc = 0.0;
236 if (sl < low_ext.S) // important for initializing low_ext that this is < and not <=
237 {
238 switch (low_ext.strategy)
239 {
240 case LowCapillaryPressureExtension::QUADRATIC:
241 pc = low_ext.Pc + low_ext.dPc * 0.5 * (sl * sl - low_ext.S * low_ext.S) / low_ext.S;
242 break;
243 case LowCapillaryPressureExtension::EXPONENTIAL:
244 pc = low_ext.Pc * std::exp(low_ext.dPc * (sl - low_ext.S) / low_ext.Pc);
245 break;
246 default:
247 pc = low_ext.Pc;
248 }
249 return pc;
250 }
251 if (sl > high_ext.S) // important for initializing high_ext that this is >, not >=
252 {
253 switch (high_ext.strategy)
254 {
255 case HighCapillaryPressureExtension::POWER:
256 {
257 if (sl >= 1.0)
258 pc = 0.0;
259 else
260 {
261 const Real expon = -high_ext.dPc / high_ext.Pc * (1.0 - high_ext.S);
262 pc = high_ext.Pc * std::pow((1.0 - sl) / (1.0 - high_ext.S), expon);
263 }
264 break;
265 }
266 default:
267 pc = 0.0;
268 }
269 return pc;
270 }
271 const Real seff = (sl - slmin) / (1.0 - sgrdel - slmin);
272 if (seff >= 1.0)
273 pc = 0.0; // no sensible high extension defined
274 else if (seff <= 0.0)
275 pc = low_ext.Pc; // no sensible low extension defined
276 else
277 {
278 const Real a = std::pow(seff, n / (1.0 - n)) - 1.0;
279 pc = (1.0 / alpha) * std::pow(a, 1.0 / n);
280 }
281 return pc;
282}
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

Referenced by PorousFlowHystereticCapillaryPressure::capillaryPressureQp(), PorousFlowHystereticCapillaryPressure::computeTurningPointInfo(), PorousFlowHystereticCapillaryPressure::firstOrderWettingPc(), PorousFlowHystereticCapillaryPressure::initQpStatefulProperties(), PorousFlowHystereticCapillaryPressure::secondOrderDryingPc(), TEST(), and TEST().

◆ d2CapillaryPressure()

Real PorousFlowVanGenuchten::d2CapillaryPressure ( Real  seff,
Real  alpha,
Real  m,
Real  pc_max 
)

Second derivative of capillary pressure wrt effective saturation.

Parameters
seffeffective saturation
alphavan Genuchten parameter
mvan Genuchten exponent
pc_maxmaximum capillary pressure (Pa)
Returns
second derivative of capillary pressure wrt effective saturation

Definition at line 140 of file PorousFlowVanGenuchten.C.

141{
142 if (seff <= 0.0 || seff >= 1.0)
143 return 0.0;
144 else
145 {
146 Real a = std::pow(seff, -1.0 / m) - 1.0;
147 // Return 0 if pc > pc_max
148 if (std::pow(a, 1.0 - m) / alpha > pc_max)
149 return 0.0;
150 else
151 {
152 Real d2pc = -std::pow(a, -1.0 - m) * std::pow(seff, -2.0 - 2.0 / m) +
153 ((1.0 + m) / m) * std::pow(a, -m) * std::pow(seff, -1.0 / m - 2.0);
154 d2pc *= (1.0 - m) / m / alpha;
155 return d2pc;
156 }
157 }
158}

Referenced by PorousFlowCapillaryPressureVG::d2CapillaryPressureCurve(), and TEST().

◆ d2capillaryPressureHys()

Real PorousFlowVanGenuchten::d2capillaryPressureHys ( Real  sl,
Real  slmin,
Real  sgrdel,
Real  alpha,
Real  n,
const LowCapillaryPressureExtension low_ext = LowCapillaryPressureExtension(),
const HighCapillaryPressureExtension high_ext = HighCapillaryPressureExtension() 
)

Second derivative of capillaryPressureHys with respect to sl.

NOTE: this function is undefined for sl < 0 and sl > 1, so you MUST ensure 0 <= sl <= 1

Parameters
slliquid saturation. 0 <= sl <= 1
slminvalue of liquid sat where the van Genuchten expression -> infinity. 0 <= slmin < 1
sgrdelvalue of gas saturation where van Genuchten expression -> 0. slmin < 1 - Sgrdel <= 1
alphavan Genuchten alpha parameter, with dimensions 1/Pa. alpha > 0
nvan Genuchten n parameter. n > 1
low_extstrategy and parameters to use for the extension in the small-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)
high_extstrategy and parameters to use for the extension in the high-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)

Definition at line 346 of file PorousFlowVanGenuchten.C.

353{
354 Real d2pc = 0.0;
355 if (sl < low_ext.S) // important for initializing low_ext that this is < and not <=
356 {
357 switch (low_ext.strategy)
358 {
359 case LowCapillaryPressureExtension::QUADRATIC:
360 d2pc = low_ext.dPc / low_ext.S;
361 break;
362 case LowCapillaryPressureExtension::EXPONENTIAL:
363 d2pc = std::pow(low_ext.dPc, 2) / low_ext.Pc *
364 std::exp(low_ext.dPc * (sl - low_ext.S) / low_ext.Pc);
365 break;
366 default:
367 d2pc = 0.0;
368 }
369 return d2pc;
370 }
371 if (sl > high_ext.S) // important for initializing high_ext that this is >, not >=
372 {
373 switch (high_ext.strategy)
374 {
375 case HighCapillaryPressureExtension::POWER:
376 {
377 if (sl >= 1.0)
378 d2pc = 0.0;
379 else
380 {
381 const Real expon = -high_ext.dPc / high_ext.Pc * (1.0 - high_ext.S);
382 d2pc = high_ext.dPc * (1.0 - expon) / (1.0 - high_ext.S) *
383 std::pow((1.0 - sl) / (1.0 - high_ext.S), expon - 2.0);
384 }
385 break;
386 }
387 default:
388 d2pc = 0.0;
389 }
390 return d2pc;
391 }
392 const Real seff = (sl - slmin) / (1.0 - sgrdel - slmin);
393 if (seff >= 1.0)
394 d2pc = 0.0; // no sensible high extension defined
395 else if (seff <= 0.0)
396 d2pc = 0.0; // no sensible low extension defined
397 else
398 {
399 const Real a = std::pow(seff, n / (1.0 - n)) - 1.0;
400 const Real dseff = 1.0 / (1.0 - sgrdel - slmin);
401 const Real d2pc_dseff =
402 (1.0 / alpha / (1.0 - n)) *
403 (std::pow(a, 1.0 / n - 2.0) * std::pow(seff, 2.0 * (n / (1.0 - n) - 1.0)) +
404 (n / (1.0 - n) - 1.0) * std::pow(a, 1.0 / n - 1.0) * std::pow(seff, n / (1.0 - n) - 2.0));
405 d2pc = d2pc_dseff * dseff * dseff;
406 }
407 return d2pc;
408}

Referenced by PorousFlowHystereticCapillaryPressure::d2capillaryPressureQp(), PorousFlowHystereticCapillaryPressure::d2firstOrderWettingPc(), PorousFlowHystereticCapillaryPressure::d2secondOrderDryingPc(), and TEST().

◆ d2EffectiveSaturation()

Real PorousFlowVanGenuchten::d2EffectiveSaturation ( Real  p,
Real  alpha,
Real  m 
)

Second derivative of effective saturation wrt porepressure.

Parameters
pporepressure
alphavan Genuchten parameter
mvan Genuchten exponent
Returns
second derivative of effective saturation wrt porepressure

Definition at line 93 of file PorousFlowVanGenuchten.C.

94{
95 if (p >= 0.0)
96 return 0.0;
97 else
98 {
99 Real n = 1.0 / (1.0 - m);
100 Real inner = 1.0 + std::pow(-alpha * p, n);
101 Real dinner_dp = -n * alpha * std::pow(-alpha * p, n - 1.0);
102 Real d2inner_dp2 = n * (n - 1.0) * alpha * alpha * std::pow(-alpha * p, n - 2.0);
103 Real d2seff_dp2 = m * (m + 1.0) * std::pow(inner, -m - 2.0) * std::pow(dinner_dp, 2.0) -
104 m * std::pow(inner, -m - 1.0) * d2inner_dp2;
105 return d2seff_dp2;
106 }
107}
const Real p

Referenced by PorousFlowCapillaryPressureVG::d2EffectiveSaturation(), and TEST().

◆ d2RelativePermeability()

Real PorousFlowVanGenuchten::d2RelativePermeability ( Real  seff,
Real  m 
)

Second derivative of relative permeability with respect to effective saturation.

Parameters
seffeffective saturation
mvan Genuchten exponent
Returns
second derivative of relative permeability wrt effective saturation

Definition at line 176 of file PorousFlowVanGenuchten.C.

177{
178 // Guard against division by zero
179 if (seff <= 0.0 || seff >= 1.0)
180 return 0.0;
181
182 const Real a = 1.0 - std::pow(seff, 1.0 / m);
183 const Real da = -1.0 / m * std::pow(seff, 1.0 / m - 1.0);
184 const Real d2a = -(1.0 / m) * (1.0 / m - 1.0) * std::pow(seff, 1.0 / m - 2.0);
185 const Real b = 1.0 - std::pow(a, m);
186 const Real db = -m * std::pow(a, m - 1.0) * da;
187 const Real d2b = -m * (m - 1.0) * std::pow(a, m - 2.0) * da * da - m * std::pow(a, m - 1.0) * d2a;
188
189 return -0.25 * std::pow(seff, -1.5) * Utility::pow<2>(b) + 2.0 * std::pow(seff, -0.5) * b * db +
190 2.0 * std::sqrt(seff) * db * db + 2.0 * std::sqrt(seff) * b * d2b;
191}
const GeochemicalDatabaseReader db("database/moose_testdb.json", true, true, false)

Referenced by TEST().

◆ d2RelativePermeabilityNW()

Real PorousFlowVanGenuchten::d2RelativePermeabilityNW ( Real  seff,
Real  m 
)

Second derivative of relative permeability for a non-wetting phase with respect to effective saturation.

Parameters
seffeffective saturation
mvan Genuchten exponent
Returns
second derivative of relative permeability wrt effective saturation

Definition at line 209 of file PorousFlowVanGenuchten.C.

210{
211 // Guard against division by zero
212 if (seff <= 0.0 || seff >= 1.0)
213 return 0.0;
214
215 const Real a = std::pow(1.0 - seff, 1.0 / m);
216 const Real da = -1.0 / m * a / (1.0 - seff);
217 const Real d2a = 1.0 / m * (1.0 / m - 1) * std::pow(1.0 - seff, 1.0 / m - 2.0);
218 const Real b = std::pow(1.0 - a, 2.0 * m);
219 const Real db = -2.0 * m * b / (1.0 - a) * da;
220 const Real d2b =
221 -2.0 * m * (db / (1.0 - a) * da + b * Utility::pow<2>(da / (1.0 - a)) + b / (1.0 - a) * d2a);
222
223 return -0.25 * std::pow(seff, -1.5) * b + std::pow(seff, -0.5) * db + std::sqrt(seff) * d2b;
224}

Referenced by TEST().

◆ d2saturationHys()

Real PorousFlowVanGenuchten::d2saturationHys ( Real  pc,
Real  slmin,
Real  sgrdel,
Real  alpha,
Real  n,
const LowCapillaryPressureExtension low_ext = LowCapillaryPressureExtension(),
const HighCapillaryPressureExtension high_ext = HighCapillaryPressureExtension() 
)

Second derivative of Hysteretic saturation function with respect to pc.

Parameters
pccapillary pressure. 0 <= pc
slminvalue of liquid sat where the van Genuchten expression -> infinity. 0 <= slmin < 1
sgrdelvalue of gas saturation where van Genuchten expression -> 0. slmin < 1 - Sgrdel <= 1
alphavan Genuchten alpha parameter, with dimensions 1/Pa. alpha > 0
nvan Genuchten n parameter. n > 1
low_extstrategy and parameters to use for the extension in the small-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)
high_extstrategy and parameters to use for the extension in the high-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)

Definition at line 554 of file PorousFlowVanGenuchten.C.

561{
562 if (pc <= 0)
563 return 0.0;
564 Real d2s = 0.0;
565 if (pc > low_ext.Pc) // important for initialization of the low_ext that this is > and not >=
566 {
567 switch (low_ext.strategy)
568 {
569 case LowCapillaryPressureExtension::QUADRATIC:
570 {
571 const Real s2 = low_ext.S * low_ext.S + 2.0 * (pc - low_ext.Pc) * low_ext.S / low_ext.dPc;
572 if (s2 <= 0.0) // this occurs when we're trying to find a saturation on the wetting curve
573 // defined by sl = sgrDel at pc = Pcd_Del, if this pc is actually impossible
574 // to achieve on this wetting curve
575 d2s = 0.0;
576 else
577 {
578 const Real ds2 = 2.0 * low_ext.S / low_ext.dPc;
579 d2s = -0.25 * ds2 * ds2 / std::pow(s2, 1.5);
580 }
581 break;
582 }
583 case LowCapillaryPressureExtension::EXPONENTIAL:
584 {
585 const Real s = low_ext.S + std::log(pc / low_ext.Pc) * low_ext.Pc / low_ext.dPc;
586 if (s <= 0.0) // this occurs when we're trying to find a saturation on the
587 // wetting curve defined by sl = sgrDel at pc = Pcd_Del, if this
588 // pc is actually impossible to achieve on this wetting curve
589 d2s = 0.0;
590 else
591 d2s = -low_ext.Pc / std::pow(pc, 2.0) / low_ext.dPc;
592 break;
593 }
594 default:
595 d2s = 0.0;
596 }
597 return d2s;
598 }
599 if (pc < high_ext.Pc) // important for initialization of the high_ext that this is < and not <=
600 {
601 switch (high_ext.strategy)
602 {
603 case HighCapillaryPressureExtension::POWER:
604 {
605 const Real expon = -high_ext.dPc / high_ext.Pc * (1.0 - high_ext.S);
606 d2s = -(1.0 - high_ext.S) * (1.0 / expon) * (1.0 / expon - 1.0) /
607 std::pow(high_ext.Pc, 2.0) * std::pow(pc / high_ext.Pc, 1.0 / expon - 2.0);
608 break;
609 }
610 default:
611 d2s = 0.0;
612 }
613 return d2s;
614 }
615 if (pc == std::numeric_limits<Real>::max())
616 d2s = 0.0;
617 else
618 {
619 const Real seffpow = 1.0 + std::pow(pc * alpha, n);
620 const Real dseffpow = n * (seffpow - 1.0) / pc;
621 const Real d2seffpow = (n - 1.0) * dseffpow / pc;
622 const Real seff = std::pow(seffpow, (1.0 - n) / n);
623 const Real dseff = (1.0 - n) / n * seff / seffpow * dseffpow;
624 const Real d2seff =
625 (1.0 - n) / n *
626 (dseff * dseffpow - seff * dseffpow * dseffpow / seffpow + seff * d2seffpow) / seffpow;
627 d2s = (1.0 - sgrdel - slmin) * d2seff;
628 }
629 return d2s;
630}

Referenced by PorousFlowHystereticCapillaryPressure::d2firstOrderWettingSat(), PorousFlowHystereticCapillaryPressure::d2liquidSaturationQp(), PorousFlowHystereticCapillaryPressure::d2secondOrderDryingSat(), and TEST().

◆ dataLoad() [1/2]

void PorousFlowVanGenuchten::dataLoad ( std::istream &  stream,
HighCapillaryPressureExtension extension,
void *  context 
)

Definition at line 52 of file PorousFlowVanGenuchten.C.

53{
54 std::underlying_type_t<HighCapillaryPressureExtension::ExtensionStrategy> strategy;
55 ::dataLoad(stream, strategy, context);
56 extension.strategy = static_cast<HighCapillaryPressureExtension::ExtensionStrategy>(strategy);
57 ::dataLoad(stream, extension.S, context);
58 ::dataLoad(stream, extension.Pc, context);
59 ::dataLoad(stream, extension.dPc, context);
60}

◆ dataLoad() [2/2]

void PorousFlowVanGenuchten::dataLoad ( std::istream &  stream,
LowCapillaryPressureExtension extension,
void *  context 
)

Definition at line 29 of file PorousFlowVanGenuchten.C.

30{
31 std::underlying_type_t<LowCapillaryPressureExtension::ExtensionStrategy> strategy;
32 ::dataLoad(stream, strategy, context);
33 extension.strategy = static_cast<LowCapillaryPressureExtension::ExtensionStrategy>(strategy);
34 ::dataLoad(stream, extension.S, context);
35 ::dataLoad(stream, extension.Pc, context);
36 ::dataLoad(stream, extension.dPc, context);
37}

Referenced by dataLoad(), and dataLoad().

◆ dataStore() [1/2]

void PorousFlowVanGenuchten::dataStore ( std::ostream &  stream,
HighCapillaryPressureExtension extension,
void *  context 
)

Definition at line 40 of file PorousFlowVanGenuchten.C.

41{
42 auto strategy =
43 static_cast<std::underlying_type_t<HighCapillaryPressureExtension::ExtensionStrategy>>(
44 extension.strategy);
45 ::dataStore(stream, strategy, context);
46 ::dataStore(stream, extension.S, context);
47 ::dataStore(stream, extension.Pc, context);
48 ::dataStore(stream, extension.dPc, context);
49}

◆ dataStore() [2/2]

void PorousFlowVanGenuchten::dataStore ( std::ostream &  stream,
LowCapillaryPressureExtension extension,
void *  context 
)

Definition at line 17 of file PorousFlowVanGenuchten.C.

18{
19 auto strategy =
20 static_cast<std::underlying_type_t<LowCapillaryPressureExtension::ExtensionStrategy>>(
21 extension.strategy);
22 ::dataStore(stream, strategy, context);
23 ::dataStore(stream, extension.S, context);
24 ::dataStore(stream, extension.Pc, context);
25 ::dataStore(stream, extension.dPc, context);
26}

Referenced by dataStore(), and dataStore().

◆ dCapillaryPressure()

Real PorousFlowVanGenuchten::dCapillaryPressure ( Real  seff,
Real  alpha,
Real  m,
Real  pc_max 
)

Derivative of capillary pressure wrt effective saturation.

Parameters
seffeffective saturation
alphavan Genuchten parameter
mvan Genuchten exponent
pc_maxmaximum capillary pressure (Pa)
Returns
derivative of capillary pressure wrt effective saturation

Definition at line 124 of file PorousFlowVanGenuchten.C.

125{
126 if (seff <= 0.0 || seff >= 1.0)
127 return 0.0;
128 else
129 {
130 Real a = std::pow(seff, -1.0 / m) - 1.0;
131 // Return 0 if pc > pc_max
132 if (std::pow(a, 1.0 - m) / alpha > pc_max)
133 return 0.0;
134 else
135 return (m - 1.0) * std::pow(a, -m) * std::pow(seff, -1.0 - 1.0 / m) / m / alpha;
136 }
137}

Referenced by PorousFlowCapillaryPressureVG::dCapillaryPressureCurve(), TEST(), and TEST().

◆ dcapillaryPressureHys()

Real PorousFlowVanGenuchten::dcapillaryPressureHys ( Real  sl,
Real  slmin,
Real  sgrdel,
Real  alpha,
Real  n,
const LowCapillaryPressureExtension low_ext = LowCapillaryPressureExtension(),
const HighCapillaryPressureExtension high_ext = HighCapillaryPressureExtension() 
)

Derivative of capillaryPressureHys with respect to sl.

NOTE: this function is undefined for sl < 0 and sl > 1, so you MUST ensure 0 <= sl <= 1 NOTE: this returns a negative quantity.

Parameters
slliquid saturation. 0 <= sl <= 1
slminvalue of liquid sat where the van Genuchten expression -> infinity. 0 <= slmin < 1
sgrdelvalue of gas saturation where van Genuchten expression -> 0. slmin < 1 - Sgrdel <= 1
alphavan Genuchten alpha parameter, with dimensions 1/Pa. alpha > 0
nvan Genuchten n parameter. n > 1
low_extstrategy and parameters to use for the extension in the small-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)
high_extstrategy and parameters to use for the extension in the high-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)

Definition at line 285 of file PorousFlowVanGenuchten.C.

292{
293 Real dpc = 0.0;
294 if (sl < low_ext.S) // important for initializing low_ext that this is < and not <=
295 {
296 switch (low_ext.strategy)
297 {
298 case LowCapillaryPressureExtension::QUADRATIC:
299 dpc = low_ext.dPc * sl / low_ext.S;
300 break;
301 case LowCapillaryPressureExtension::EXPONENTIAL:
302 dpc = low_ext.dPc * std::exp(low_ext.dPc * (sl - low_ext.S) / low_ext.Pc);
303 break;
304 default:
305 dpc = 0.0;
306 }
307 return dpc;
308 }
309 if (sl > high_ext.S) // important for initializing high_ext that this is >, not >=
310 {
311 switch (high_ext.strategy)
312 {
313 case HighCapillaryPressureExtension::POWER:
314 {
315 if (sl >= 1.0)
316 dpc = 0.0;
317 else
318 {
319 const Real expon = -high_ext.dPc / high_ext.Pc * (1.0 - high_ext.S);
320 dpc = high_ext.dPc * std::pow((1.0 - sl) / (1.0 - high_ext.S), expon - 1.0);
321 }
322 break;
323 }
324 default:
325 dpc = 0.0;
326 }
327 return dpc;
328 }
329 const Real seff = (sl - slmin) / (1.0 - sgrdel - slmin);
330 if (seff >= 1.0)
331 dpc = 0.0; // no sensible high extension defined
332 else if (seff <= 0.0)
333 dpc = 0.0; // no sensible low extension defined
334 else
335 {
336 const Real a = std::pow(seff, n / (1.0 - n)) - 1.0;
337 const Real dseff = 1.0 / (1.0 - sgrdel - slmin);
338 const Real dpc_dseff = (1.0 / alpha / (1.0 - n)) * std::pow(a, 1.0 / n - 1.0) *
339 std::pow(seff, n / (1.0 - n) - 1.0);
340 dpc = dpc_dseff * dseff;
341 }
342 return dpc;
343}

Referenced by PorousFlowHystereticCapillaryPressure::computeTurningPointInfo(), PorousFlowHystereticCapillaryPressure::dcapillaryPressureQp(), PorousFlowHystereticCapillaryPressure::dfirstOrderWettingPc(), PorousFlowHystereticCapillaryPressure::dsecondOrderDryingPc(), TEST(), and TEST().

◆ dEffectiveSaturation()

Real PorousFlowVanGenuchten::dEffectiveSaturation ( Real  p,
Real  alpha,
Real  m 
)

Derivative of effective saturation wrt porepressure.

Parameters
pporepressure
alphavan Genuchten parameter
mvan Genuchten exponent
Returns
derivative of effective saturation wrt porepressure

Definition at line 78 of file PorousFlowVanGenuchten.C.

79{
80 if (p >= 0.0)
81 return 0.0;
82 else
83 {
84 Real n = 1.0 / (1.0 - m);
85 Real inner = 1.0 + std::pow(-alpha * p, n);
86 Real dinner_dp = -n * alpha * std::pow(-alpha * p, n - 1.0);
87 Real dseff_dp = -m * std::pow(inner, -m - 1) * dinner_dp;
88 return dseff_dp;
89 }
90}

Referenced by PorousFlowCapillaryPressureVG::dEffectiveSaturation(), TEST(), and TEST().

◆ dRelativePermeability()

Real PorousFlowVanGenuchten::dRelativePermeability ( Real  seff,
Real  m 
)

Derivative of relative permeability with respect to effective saturation.

Parameters
seffeffective saturation
mvan Genuchten exponent
Returns
derivative of relative permeability wrt effective saturation

Definition at line 161 of file PorousFlowVanGenuchten.C.

162{
163 // Guard against division by zero
164 if (seff <= 0.0 || seff >= 1.0)
165 return 0.0;
166
167 const Real a = 1.0 - std::pow(seff, 1.0 / m);
168 const Real da = -1.0 / m * std::pow(seff, 1.0 / m - 1.0);
169 const Real b = 1.0 - std::pow(a, m);
170 const Real db = -m * std::pow(a, m - 1.0) * da;
171
172 return 0.5 * std::pow(seff, -0.5) * Utility::pow<2>(b) + 2.0 * std::sqrt(seff) * b * db;
173}

Referenced by PorousFlowRelativePermeabilityVGTempl< is_ad >::dRelativePermeability(), TEST(), TEST(), and TEST().

◆ drelativePermeabilityHys()

Real PorousFlowVanGenuchten::drelativePermeabilityHys ( Real  sl,
Real  slr,
Real  sgrdel,
Real  sgrmax,
Real  sldel,
Real  m,
Real  upper_liquid_param,
Real  y0,
Real  y0p,
Real  y1,
Real  y1p 
)

Derivative of Hysteretic relative permeability for liquid, with respect to liquid saturation.

Parameters
slliquid saturation
slrresidual liquid saturation. For sl < slr, this function will always return 0
sgrdelvalue of gas saturation where van Genuchten wetting capillary-pressure expression -> 0. This depends on the turning-point saturation when drying became wetting, using the Land equation
sgrmaxmaximum value possible for sgrdel. This will be equal to sgrdel if the turning-point saturation is small
sldelvalue of the turning-point saturation when drying became wetting
mvan-Genuchten m parameter
upper_liquid_paramcubic modification of the wetting relative permeability will occur between upper_liquid_param * (1 - sgrdel) and 1 - 0.5 * sgrdel. 0 < upper_liquid_param <= 1. Usually upper_liquid_param is close to 1 (eg 0.9)
y0value of the unmodified wetting relative permeability at sl = upper_liquid_param * (1 - sgrdel)
y0pvalue of the derivtaive of the unmodified wetting relative permeability at sl = upper_liquid_param * (1 - sgrdel)
y1value of the unmodified wetting relative permeability at sl = 1 - 0.5 * sgrdel
y1pvalue of the derivtaive of the unmodified wetting relative permeability at sl = 1 - 0.5 * sgrdel

Definition at line 689 of file PorousFlowVanGenuchten.C.

700{
701 if (sl <= slr) // by the definition of slr, always return 0
702 return 0.0;
703 if (sl == 1.0) // derivative is infinite at this point
704 return std::numeric_limits<Real>::max();
705 const Real sl_bar = (sl - slr) / (1.0 - slr); // effective saturation
706 const Real sl_bar_prime = 1.0 / (1.0 - slr);
707 // a and b are useful parameters. Define b along the drying curve initially, and
708 // modify a and b appropriately if the wetting result is required
709 Real a = 0;
710 Real a_prime = 0.0;
711 Real b = 0;
712 Real b_prime = 0.0;
713 if (sgrdel == 0.0 || sl <= sldel) // along the drying curve
714 {
715 const Real c = std::pow(sl_bar, 1.0 / m);
716 const Real dc_dsbar = c / m / sl_bar;
717 a = std::pow(1.0 - c, m);
718 const Real da_dsbar = -m * a / (1.0 - c) * dc_dsbar;
719 a_prime = da_dsbar * sl_bar_prime;
720 }
721 else // along the wetting curve
722 {
723 // In most cases, use sldel and sgrdel as provided to this function. However, because "there is
724 // no hysteresis along the extension" according to p6 of Doughty2008, if the turning point is
725 // less than slr, then use the expressions for the case when the turning point was slr
726 const Real my_sldel = (sldel < slr) ? slr : sldel;
727 const Real my_sgrdel = (sldel < slr) ? sgrmax : sgrdel;
728 if (sl >= 1.0 - 0.5 * my_sgrdel)
729 {
730 // follow the drying curve. The parameter b has already been defined. It
731 // is important for initialization of the curic that the above condition is >= and not >
732 const Real c = std::pow(sl_bar, 1.0 / m);
733 const Real dc_dsbar = c / m / sl_bar;
734 a = std::pow(1.0 - c, m);
735 const Real da_dsbar = -m * a / (1.0 - c) * dc_dsbar;
736 a_prime = da_dsbar * sl_bar_prime;
737 }
738 else if (sl > upper_liquid_param * (1.0 - my_sgrdel))
739 {
740 // follow the cubic modification of the wetting curve. Immediately exit from this function by
741 // returning the cubic result
743 sl, upper_liquid_param * (1.0 - my_sgrdel), y0, y0p, 1.0 - 0.5 * my_sgrdel, y1, y1p);
744 }
745 else
746 {
747 // standard case of wetting curve outside the cubic-modification and drying-curve regions
748 const Real sl_bar_del = (my_sldel - slr) / (1.0 - slr);
749 const Real s_gt_bar =
750 my_sgrdel * (sl - my_sldel) / (1.0 - slr) / (1.0 - my_sldel - my_sgrdel);
751 const Real s_gt_bar_prime = my_sgrdel / (1.0 - slr) / (1.0 - my_sldel - my_sgrdel);
752 const Real c = std::pow(sl_bar + s_gt_bar, 1.0 / m);
753 const Real c_prime = c / m / (sl_bar + s_gt_bar) * (sl_bar_prime + s_gt_bar_prime);
754 a = (1 - s_gt_bar / (1.0 - sl_bar_del)) * std::pow(1.0 - c, m);
755 a_prime =
756 -s_gt_bar_prime / (1.0 - sl_bar_del) * std::pow(1.0 - c, m) - m * a / (1.0 - c) * c_prime;
757 b = s_gt_bar / (1.0 - sl_bar_del) * std::pow(1.0 - std::pow(sl_bar_del, 1.0 / m), m);
758 b_prime = s_gt_bar_prime * b / s_gt_bar;
759 }
760 }
761 const Real kr = std::sqrt(sl_bar) * Utility::pow<2>(1.0 - a - b);
762 return 0.5 * kr / sl_bar * sl_bar_prime -
763 std::sqrt(sl_bar) * 2.0 * (1.0 - a - b) * (a_prime + b_prime);
764}
Real dcubic(Real x, Real x0, Real y0, Real y0p, Real x1, Real y1, Real y1p)
Derivative of cubic function, f(x), with respect to x.

Referenced by PorousFlowHystereticRelativePermeabilityLiquid::computeRelPermQp(), PorousFlowHystereticRelativePermeabilityLiquid::computeTurningPoint0Info(), and TEST().

◆ dRelativePermeabilityNW()

Real PorousFlowVanGenuchten::dRelativePermeabilityNW ( Real  seff,
Real  m 
)

Derivative of relative permeability for a non-wetting phase with respect to effective saturation.

Parameters
seffeffective saturation
mvan Genuchten exponent
Returns
derivative of relative permeability wrt effective saturation

Definition at line 194 of file PorousFlowVanGenuchten.C.

195{
196 // Guard against division by zero
197 if (seff <= 0.0 || seff >= 1.0)
198 return 0.0;
199
200 const Real a = std::pow(1.0 - seff, 1.0 / m);
201 const Real da = -1.0 / m * a / (1.0 - seff);
202 const Real b = std::pow(1.0 - a, 2.0 * m);
203 const Real db = -2.0 * m * b / (1.0 - a) * da;
204
205 return 0.5 * std::pow(seff, -0.5) * b + std::sqrt(seff) * db;
206}

Referenced by PorousFlowRelativePermeabilityVGTempl< is_ad >::dRelativePermeability(), TEST(), TEST(), and TEST().

◆ drelativePermeabilityNWHys()

Real PorousFlowVanGenuchten::drelativePermeabilityNWHys ( Real  sl,
Real  slr,
Real  sgrdel,
Real  sgrmax,
Real  sldel,
Real  m,
Real  gamma,
Real  k_rg_max,
Real  y0p 
)

Derivative of hysteretic relative permeability for gas with respect to the liquid saturation.

Parameters
slliquid saturation
slrresidual liquid saturation. For sl < slr, this function will always return 0
sgrdelvalue of gas saturation where van Genuchten wetting capillary-pressure expression -> 0. This depends on the turning-point saturation when drying became wetting, using the Land equation
sgrmaxmaximum value possible for sgrdel. This will be equal to sgrdel if the turning-point saturation is small
sldelvalue of the turning-point saturation when drying became wetting
mvan-Genuchten m parameter
gammaindex satisfying gamma > 0. Usually gamma = 1/3.
k_rg_maxMaximum value of unextended gas relative permeability. If no low-saturation extension is used then gas relative permeability = k_rg_max for sl <= slr. Satisfies 0 < k_rg_max <= 1. Frequently k_rg_max = 1 is used
y0pValue of the derivative of the low-saturation extension at sl = slr. If an extension is used then the gas relative permeability in the region sl <= slr is a cubic whose value is unity at sl = 0, and derivative is zero at sl = 0

Definition at line 811 of file PorousFlowVanGenuchten.C.

820{
821 if (sl < slr)
822 {
823 // in the extended region, so immediately return with the relevant value
824 if (k_rg_max == 1.0)
825 return 0.0;
826 return PorousFlowCubic::dcubic(sl, 0.0, 1.0, 0.0, slr, k_rg_max, y0p);
827 }
828 if (sl > 1.0 - sgrdel) // saturation is above 1.0 - residual gas saturation
829 return 0.0;
830 const Real sl_bar = (sl - slr) / (1.0 - slr);
831 const Real sl_bar_prime = 1.0 / (1.0 - slr);
832 Real s_gt_bar = 0.0; // initialize this parameter as if on the drying curve
833 Real s_gt_bar_prime = 0.0; // again, assume on drying curve
834 if (sgrdel != 0.0 && sl > sldel)
835 {
836 // On the wetting curve
837 // In most cases, use sldel and sgrdel as provided to this function. However, because "there is
838 // no hysteresis along the extension" according to p6 of Doughty2008, if the turning point is
839 // less than slr, then use the expressions for the case when the turning point was slr
840 const Real my_sldel = (sldel < slr) ? slr : sldel;
841 const Real my_sgrdel = (sldel < slr) ? sgrmax : sgrdel;
842 s_gt_bar = my_sgrdel * (sl - my_sldel) / (1.0 - slr) / (1.0 - my_sldel - my_sgrdel);
843 s_gt_bar_prime = my_sgrdel / (1.0 - slr) / (1.0 - my_sldel - my_sgrdel);
844 }
845 Real kr_prime = 0.0;
846 if (sl_bar + s_gt_bar < 1.0) // check for the condition where sl is too big, in which case kr =
847 // 0, irrespective of hysteresis
848 {
849 const Real a = std::pow(1.0 - (sl_bar + s_gt_bar), gamma);
850 const Real a_prime = -gamma * a / (1.0 - (sl_bar + s_gt_bar)) * (sl_bar_prime + s_gt_bar_prime);
851 const Real c = std::pow(sl_bar + s_gt_bar, 1.0 / m);
852 const Real c_prime =
853 (c == 0 ? 0.0 : c / m / (sl_bar + s_gt_bar) * (sl_bar_prime + s_gt_bar_prime));
854 const Real b = std::pow(1.0 - c, 2.0 * m);
855 const Real b_prime = -2.0 * m * b / (1.0 - c) * c_prime;
856 kr_prime = k_rg_max * (a * b_prime + a_prime * b);
857 }
858 return kr_prime;
859}

Referenced by PorousFlowHystereticRelativePermeabilityGas::computeRelPermQp(), and TEST().

◆ dsaturationHys()

Real PorousFlowVanGenuchten::dsaturationHys ( Real  pc,
Real  slmin,
Real  sgrdel,
Real  alpha,
Real  n,
const LowCapillaryPressureExtension low_ext = LowCapillaryPressureExtension(),
const HighCapillaryPressureExtension high_ext = HighCapillaryPressureExtension() 
)

Derivative of Hysteretic saturation function with respect to pc.

Parameters
pccapillary pressure. 0 <= pc
slminvalue of liquid sat where the van Genuchten expression -> infinity. 0 <= slmin < 1
sgrdelvalue of gas saturation where van Genuchten expression -> 0. slmin < 1 - Sgrdel <= 1
alphavan Genuchten alpha parameter, with dimensions 1/Pa. alpha > 0
nvan Genuchten n parameter. n > 1
low_extstrategy and parameters to use for the extension in the small-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)
high_extstrategy and parameters to use for the extension in the high-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)

Definition at line 480 of file PorousFlowVanGenuchten.C.

487{
488 if (pc <= 0)
489 return 0.0;
490 Real ds = 0.0;
491 if (pc > low_ext.Pc) // important for initialization of the low_ext that this is > and not >=
492 {
493 switch (low_ext.strategy)
494 {
495 case LowCapillaryPressureExtension::QUADRATIC:
496 {
497 const Real s2 = low_ext.S * low_ext.S + 2.0 * (pc - low_ext.Pc) * low_ext.S / low_ext.dPc;
498 if (s2 <= 0.0) // this occurs when we're trying to find a saturation on the wetting curve
499 // defined by sl = sgrDel at pc = Pcd_Del, if this pc is actually impossible
500 // to achieve on this wetting curve
501 ds = 0.0;
502 else
503 {
504 const Real ds2 = 2.0 * low_ext.S / low_ext.dPc;
505 ds = 0.5 * ds2 / std::sqrt(s2);
506 }
507 break;
508 }
509 case LowCapillaryPressureExtension::EXPONENTIAL:
510 {
511 const Real s = low_ext.S + std::log(pc / low_ext.Pc) * low_ext.Pc / low_ext.dPc;
512 if (s <= 0.0) // this occurs when we're trying to find a saturation on the
513 // wetting curve defined by sl = sgrDel at pc = Pcd_Del, if this
514 // pc is actually impossible to achieve on this wetting curve
515 ds = 0.0;
516 else
517 ds = low_ext.Pc / pc / low_ext.dPc;
518 break;
519 }
520 default:
521 ds = 0.0;
522 }
523 return ds;
524 }
525 if (pc < high_ext.Pc) // important for initialization of the high_ext that this is < and not <=
526 {
527 switch (high_ext.strategy)
528 {
529 case HighCapillaryPressureExtension::POWER:
530 {
531 const Real expon = -high_ext.dPc / high_ext.Pc * (1.0 - high_ext.S);
532 ds = -(1.0 - high_ext.S) / pc / expon * std::pow(pc / high_ext.Pc, 1.0 / expon);
533 break;
534 }
535 default:
536 ds = 0.0;
537 }
538 return ds;
539 }
540 if (pc == std::numeric_limits<Real>::max())
541 ds = 0.0;
542 else
543 {
544 const Real seffpow = 1.0 + std::pow(pc * alpha, n);
545 const Real dseffpow = n * (seffpow - 1.0) / pc;
546 const Real seff = std::pow(seffpow, (1.0 - n) / n);
547 const Real dseff = (1.0 - n) / n * seff / seffpow * dseffpow;
548 ds = (1.0 - sgrdel - slmin) * dseff;
549 }
550 return ds;
551}

Referenced by PorousFlowHystereticCapillaryPressure::dfirstOrderWettingSat(), PorousFlowHystereticCapillaryPressure::dliquidSaturationQp(), PorousFlowHystereticCapillaryPressure::dsecondOrderDryingSat(), TEST(), and TEST().

◆ effectiveSaturation()

Real PorousFlowVanGenuchten::effectiveSaturation ( Real  p,
Real  alpha,
Real  m 
)

Effective saturation as a function of porepressure.

Note: seff = 1 for p >= 0

Parameters
pporepressure
alphavan Genuchten parameter
mvan Genuchten exponent
Returns
effective saturation

Definition at line 63 of file PorousFlowVanGenuchten.C.

64{
65 Real n, seff;
66
67 if (p >= 0.0)
68 return 1.0;
69 else
70 {
71 n = 1.0 / (1.0 - m);
72 seff = 1.0 + std::pow(-alpha * p, n);
73 return std::pow(seff, -m);
74 }
75}

Referenced by PorousFlowCapillaryPressureVG::effectiveSaturation(), TEST(), and TEST().

◆ relativePermeability()

template<typename T >
T PorousFlowVanGenuchten::relativePermeability ( const T seff,
Real  m 
)

Relative permeability as a function of effective saturation.

Parameters
seffeffective saturation
mvan Genuchten exponent
Returns
relative permeability

Definition at line 103 of file PorousFlowVanGenuchten.h.

104{
105 if (MetaPhysicL::raw_value(seff) <= 0.0)
106 return 0.0;
107 else if (MetaPhysicL::raw_value(seff) >= 1.0)
108 return 1.0;
109
110 using std::pow, std::sqrt;
111
112 const T a = 1.0 - pow(seff, 1.0 / m);
113 const T b = 1.0 - pow(a, m);
114
115 return sqrt(seff) * Utility::pow<2>(b);
116}
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const double T
auto raw_value(const Eigen::Map< T > &in)

Referenced by PorousFlowRelativePermeabilityVGTempl< is_ad >::relativePermeability(), TEST(), TEST(), and TEST().

◆ relativePermeabilityHys()

Real PorousFlowVanGenuchten::relativePermeabilityHys ( Real  sl,
Real  slr,
Real  sgrdel,
Real  sgrmax,
Real  sldel,
Real  m,
Real  upper_liquid_param,
Real  y0,
Real  y0p,
Real  y1,
Real  y1p 
)

Hysteretic relative permeability for liquid.

Parameters
slliquid saturation
slrresidual liquid saturation. For sl < slr, this function will always return 0
sgrdelvalue of gas saturation where van Genuchten wetting capillary-pressure expression -> 0. This depends on the turning-point saturation when drying became wetting, using the Land equation
sgrmaxmaximum value possible for sgrdel. This will be equal to sgrdel if the turning-point saturation is small
sldelvalue of the turning-point saturation when drying became wetting
mvan-Genuchten m parameter
upper_liquid_paramcubic modification of the wetting relative permeability will occur between upper_liquid_param * (1 - sgrdel) and 1 - 0.5 * sgrdel. 0 < upper_liquid_param <= 1. Usually upper_liquid_param is close to 1 (eg 0.9)
y0value of the unmodified wetting relative permeability at sl = upper_liquid_param * (1 - sgrdel)
y0pvalue of the derivtaive of the unmodified wetting relative permeability at sl = upper_liquid_param * (1 - sgrdel)
y1value of the unmodified wetting relative permeability at sl = 1 - 0.5 * sgrdel
y1pvalue of the derivtaive of the unmodified wetting relative permeability at sl = 1 - 0.5 * sgrdel

Definition at line 633 of file PorousFlowVanGenuchten.C.

644{
645 if (sl <= slr) // by the definition of slr, always return 0
646 return 0.0;
647 const Real sl_bar = (sl - slr) / (1.0 - slr); // effective saturation
648 // a and b are useful parameters. Define b along the drying curve initially, and
649 // modify a and b appropriately if the wetting result is required
650 Real a = 0;
651 Real b = 0;
652 if (sgrdel == 0.0 || sl <= sldel) // along the drying curve
653 a = std::pow(1.0 - std::pow(sl_bar, 1.0 / m), m);
654 else // along the wetting curve
655 {
656 // In most cases, use sldel and sgrdel as provided to this function. However, because "there is
657 // no hysteresis along the extension" according to p6 of Doughty2008, if the turning point is
658 // less than slr, then use the expressions for the case when the turning point was slr
659 const Real my_sldel = (sldel < slr) ? slr : sldel;
660 const Real my_sgrdel = (sldel < slr) ? sgrmax : sgrdel;
661 if (sl >= 1.0 - 0.5 * my_sgrdel)
662 {
663 // follow the drying curve. The parameter b has already been defined. It
664 // is important for initialization of the curic that the above condition is >= and not >
665 a = std::pow(1.0 - std::pow(sl_bar, 1.0 / m), m);
666 }
667 else if (sl > upper_liquid_param * (1.0 - my_sgrdel))
668 {
669 // follow the cubic modification of the wetting curve. Immediately exit from this function by
670 // returning the cubic result
672 sl, upper_liquid_param * (1.0 - my_sgrdel), y0, y0p, 1.0 - 0.5 * my_sgrdel, y1, y1p);
673 }
674 else
675 {
676 // standard case of wetting curve outside the cubic-modification and drying-curve regions
677 const Real sl_bar_del = (my_sldel - slr) / (1.0 - slr);
678 const Real s_gt_bar =
679 my_sgrdel * (sl - my_sldel) / (1.0 - slr) / (1.0 - my_sldel - my_sgrdel);
680 a = (1 - s_gt_bar / (1.0 - sl_bar_del)) *
681 std::pow(1.0 - std::pow(sl_bar + s_gt_bar, 1.0 / m), m);
682 b = s_gt_bar / (1.0 - sl_bar_del) * std::pow(1.0 - std::pow(sl_bar_del, 1.0 / m), m);
683 }
684 }
685 return std::sqrt(sl_bar) * Utility::pow<2>(1.0 - a - b);
686}
Real cubic(Real x, Real x0, Real y0, Real y0p, Real x1, Real y1, Real y1p)
Cubic function f(x) that satisfies f(x0) = y0 f'(x0) = y0p f(x1) = y1 f'(x1) = y1p.

Referenced by PorousFlowHystereticRelativePermeabilityLiquid::computeRelPermQp(), PorousFlowHystereticRelativePermeabilityLiquid::computeTurningPoint0Info(), TEST(), and TEST().

◆ relativePermeabilityNW()

template<typename T >
T PorousFlowVanGenuchten::relativePermeabilityNW ( const T seff,
Real  m 
)

Relative permeability for a non-wetting phase as a function of effective saturation.

Parameters
seffeffective saturation
mvan Genuchten exponent
Returns
relative permeability

Definition at line 142 of file PorousFlowVanGenuchten.h.

143{
144 if (MetaPhysicL::raw_value(seff) <= 0.0)
145 return 0.0;
146 else if (MetaPhysicL::raw_value(seff) >= 1.0)
147 return 1.0;
148
149 using std::pow, std::sqrt;
150
151 const T a = pow(1.0 - seff, 1.0 / m);
152 const T b = pow(1.0 - a, 2.0 * m);
153
154 return sqrt(seff) * b;
155}

Referenced by PorousFlowRelativePermeabilityVGTempl< is_ad >::relativePermeability(), TEST(), TEST(), and TEST().

◆ relativePermeabilityNWHys()

Real PorousFlowVanGenuchten::relativePermeabilityNWHys ( Real  sl,
Real  slr,
Real  sgrdel,
Real  sgrmax,
Real  sldel,
Real  m,
Real  gamma,
Real  k_rg_max,
Real  y0p 
)

Hysteretic relative permeability for gas.

Parameters
slliquid saturation
slrresidual liquid saturation. For sl < slr, this function will always return 0
sgrdelvalue of gas saturation where van Genuchten wetting capillary-pressure expression -> 0. This depends on the turning-point saturation when drying became wetting, using the Land equation
sgrmaxmaximum value possible for sgrdel. This will be equal to sgrdel if the turning-point saturation is small
sldelvalue of the turning-point saturation when drying became wetting
mvan-Genuchten m parameter
gammaindex satisfying gamma > 0. Usually gamma = 1/3.
k_rg_maxMaximum value of unextended gas relative permeability. If no low-saturation extension is used then gas relative permeability = k_rg_max for sl <= slr. Satisfies 0 < k_rg_max <= 1. Frequently k_rg_max = 1 is used
y0pValue of the derivative of the low-saturation extension at sl = slr. If an extension is used then the gas relative permeability in the region sl <= slr is a cubic whose value is unity at sl = 0, and derivative is zero at sl = 0

Definition at line 767 of file PorousFlowVanGenuchten.C.

776{
777 if (sl < slr)
778 {
779 // in the extended region, so immediately return with the relevant value
780 if (k_rg_max == 1.0)
781 return 1.0;
782 return PorousFlowCubic::cubic(sl, 0.0, 1.0, 0.0, slr, k_rg_max, y0p);
783 }
784 if (sl > 1.0 - sgrdel) // saturation is above 1.0 - residual gas saturation
785 return 0.0;
786 const Real sl_bar = (sl - slr) / (1.0 - slr);
787 Real s_gt_bar = 0.0; // initialize this parameter as if on the drying curve
788 if (sgrdel != 0.0 && sl > sldel)
789 {
790 // On the wetting curve
791 // In most cases, use sldel and sgrdel as provided to this function. However, because "there is
792 // no hysteresis along the extension" according to p6 of Doughty2008, if the turning point is
793 // less than slr, then use the expressions for the case when the turning point was slr
794 const Real my_sldel = (sldel < slr) ? slr : sldel;
795 const Real my_sgrdel = (sldel < slr) ? sgrmax : sgrdel;
796 s_gt_bar = my_sgrdel * (sl - my_sldel) / (1.0 - slr) / (1.0 - my_sldel - my_sgrdel);
797 }
798 Real kr = 0.0;
799 if (sl_bar + s_gt_bar < 1.0) // check for the condition where sl is too big, in which case kr =
800 // 0, irrespective of hysteresis
801 {
802 const Real a = std::pow(1.0 - (sl_bar + s_gt_bar), gamma);
803 const Real c = std::pow(sl_bar + s_gt_bar, 1.0 / m);
804 const Real b = std::pow(1.0 - c, 2.0 * m);
805 kr = k_rg_max * a * b;
806 }
807 return kr;
808}

Referenced by PorousFlowHystereticRelativePermeabilityGas::computeRelPermQp(), TEST(), and TEST().

◆ saturationHys()

Real PorousFlowVanGenuchten::saturationHys ( Real  pc,
Real  slmin,
Real  sgrdel,
Real  alpha,
Real  n,
const LowCapillaryPressureExtension low_ext = LowCapillaryPressureExtension(),
const HighCapillaryPressureExtension high_ext = HighCapillaryPressureExtension() 
)

Hysteretic saturation function (Eqn(1) of Doughty2007) with extensions (page5 and Fig1 of Doughty2008), which is the inverse of capillaryPressureHys.

Parameters
pccapillary pressure. 0 <= pc
slminvalue of liquid sat where the van Genuchten expression -> infinity. 0 <= slmin < 1
sgrdelvalue of gas saturation where van Genuchten expression -> 0. slmin < 1 - Sgrdel <= 1
alphavan Genuchten alpha parameter, with dimensions 1/Pa. alpha > 0
nvan Genuchten n parameter. n > 1
low_extstrategy and parameters to use for the extension in the small-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)
high_extstrategy and parameters to use for the extension in the high-saturation region (defaults to no extension: this default is not recommended for simulations of real phenomena)

Definition at line 411 of file PorousFlowVanGenuchten.C.

418{
419 if (pc <= 0)
420 return 1.0;
421 Real s = 1.0;
422 if (pc > low_ext.Pc) // important for initialization of the low_ext that this is > and not >=
423 {
424 switch (low_ext.strategy)
425 {
426 case LowCapillaryPressureExtension::QUADRATIC:
427 {
428 const Real s2 = low_ext.S * low_ext.S + 2.0 * (pc - low_ext.Pc) * low_ext.S / low_ext.dPc;
429 if (s2 <= 0.0) // this occurs when we're trying to find a saturation on the wetting curve
430 // defined by sl = sgrDel at pc = Pcd_Del, if this pc is actually impossible
431 // to achieve on this wetting curve
432 s = 0.0;
433 else
434 s = std::sqrt(s2);
435 break;
436 }
437 case LowCapillaryPressureExtension::EXPONENTIAL:
438 {
439 const Real ss = low_ext.S + std::log(pc / low_ext.Pc) * low_ext.Pc / low_ext.dPc;
440 if (ss <= 0.0) // this occurs when we're trying to find a saturation on the
441 // wetting curve defined by sl = sgrDel at pc = Pcd_Del, if this
442 // pc is actually impossible to achieve on this wetting curve
443 s = 0.0;
444 else
445 s = ss;
446 break;
447 }
448 default:
449 s = low_ext.S;
450 }
451 return s;
452 }
453 if (pc < high_ext.Pc) // important for initialization of the high_ext that this is < and not <=
454 {
455 switch (high_ext.strategy)
456 {
457 case HighCapillaryPressureExtension::POWER:
458 {
459 const Real expon = -high_ext.dPc / high_ext.Pc * (1.0 - high_ext.S);
460 s = 1.0 - std::pow(pc / high_ext.Pc, 1.0 / expon) * (1.0 - high_ext.S);
461 break;
462 }
463 default:
464 s = high_ext.S;
465 }
466 return s;
467 }
468 if (pc == std::numeric_limits<Real>::max())
469 s = 0.0;
470 else
471 {
472 const Real seffpow = 1.0 + std::pow(pc * alpha, n);
473 const Real seff = std::pow(seffpow, (1.0 - n) / n);
474 s = (1.0 - sgrdel - slmin) * seff + slmin;
475 }
476 return s;
477}

Referenced by PorousFlowHystereticCapillaryPressure::computeTurningPointInfo(), PorousFlowHystereticCapillaryPressure::d2secondOrderDryingSat(), PorousFlowHystereticCapillaryPressure::dsecondOrderDryingSat(), PorousFlowHystereticCapillaryPressure::firstOrderWettingSat(), PorousFlowHystereticCapillaryPressure::liquidSaturationQp(), PorousFlowHystereticCapillaryPressure::secondOrderDryingSat(), TEST(), and TEST().