22 "van Genuchten alpha parameter for the primary drying curve. If using standard units, this " 23 "is measured in Pa^-1. Suggested value is around 1E-5");
27 "van Genuchten alpha parameter for the primary wetting curve. If using standard units, this " 28 "is measured in Pa^-1. Suggested value is around 1E-5");
31 "van Genuchten n parameter for the primary drying " 32 "curve. Dimensionless. Suggested value is around 2");
35 "van Genuchten n parameter for the primary wetting " 36 "curve. Dimensionless. Suggested value is around 2");
39 "S_l_min >= 0 & S_l_min < 1",
40 "Minimum liquid saturation for which the van Genuchten expression is valid. If no lower " 41 "extension is used then Pc = Pc_max for liquid saturation <= S_l_min");
45 "S_lr >= 0 & S_lr < 1",
46 "Liquid residual saturation where the liquid relative permeability is zero. This is used in " 47 "the Land expression to find S_gr_del. Almost definitely you need to set S_lr equal to the " 48 "quantity used for your relative-permeability curves. Almost definitely you should set S_lr " 53 "Residual gas saturation. 1 - S_gr_max is the maximum saturation for which the " 54 "van Genuchten expression is valid for the wetting curve. You must ensure S_gr_max < 1 - " 55 "S_l_min. Often S_gr_max = -0.3136 * ln(porosity) - 0.1334 is used");
58 std::numeric_limits<Real>::max(),
60 "Value of capillary pressure at which the lower extension commences. The default value " 61 "means capillary pressure uses the van Genuchten expression for S > S_l_min and is " 62 "'infinity' for S <= S_l_min. This will result in poor convergence around S = S_l_min");
63 MooseEnum low_ext_enum(
"none quadratic exponential",
"exponential");
67 "Type of extension to use for small liquid saturation values. The extensions modify the " 68 "capillary pressure for all saturation values less than S(Pc_max). That is, if the " 70 "expression would produce Pc > Pc_max, then the extension is used instead. NONE: Simply " 71 "cut-off the capillary-pressure at Pc_max, so that Pc <= Pc_max for all S. QUADRATIC: Pc is " 72 "a quadratic in S that is continuous and differentiable at S(Pc_max) and has zero derivative " 73 "at S = 0 (hence, its value at S = 0 will be greater than Pc_max). EXPONENTIAL: Pc is an " 74 "exponential in S that is continuous and differentiable at S(Pc_max) (hence, its value at S " 75 "= 0 will be much greater than Pc_max");
79 "high_ratio > 0 & high_ratio < 1",
80 "The extension to the wetting curves commences at high_ratio * (1 - S_gr_del), where 1 - " 81 "S_gr_del is the value of the liquid saturation when Pc = 0 (on the wetting curve)");
82 MooseEnum high_ext_enum(
"none power",
"power");
84 "high_extension_type",
86 "Type of extension to use for the wetting curves when the liquid saturation is around 1. " 87 "The extensions modify the wetting capillary pressure for all saturation values greater than " 88 "high_ratio * (1 - S_gr_del), where 1 - S_gr_del is the value of liquid saturation when the " 89 "van Genuchten expression gives Pc = 0. NONE: use the van Genuchten expression and when S > " 90 "1 - S_gr_del, set Pc = 0. POWER: Pc is proportional to (1 - S)^power, where the " 91 "coefficient of proportionality and the power are chosen so the resulting curve is " 92 "continuous and differentiable");
94 "This Material computes information that is required for the computation of hysteretic " 95 "capillary pressures in single and multi phase situations");
102 _alpha_d(getParam<
Real>(
"alpha_d")),
103 _alpha_w(getParam<
Real>(
"alpha_w")),
104 _n_d(getParam<
Real>(
"n_d")),
105 _n_w(getParam<
Real>(
"n_w")),
106 _s_l_min(getParam<
Real>(
"S_l_min")),
107 _s_lr(getParam<
Real>(
"S_lr")),
108 _s_gr_max(getParam<
Real>(
"S_gr_max")),
109 _pc_max(getParam<
Real>(
"Pc_max")),
110 _high_ratio(getParam<
Real>(
"high_ratio")),
112 getParam<
MooseEnum>(
"low_extension_type")
117 _low_ext_d(_low_ext_type, _s_low_d, _pc_max, _dpc_low_d),
120 _s_low_w, _s_l_min, _s_gr_max, _alpha_w, _n_w)),
121 _low_ext_w(_low_ext_type, _s_low_w, _pc_max, _dpc_low_w),
123 getParam<
MooseEnum>(
"high_extension_type")
125 _s_high(_high_ratio * (1 - _s_gr_max)),
129 _s_high, _s_l_min, _s_gr_max, _alpha_w, _n_w)),
130 _high_ext(_high_ext_type, _s_high, _pc_high, _dpc_high),
131 _hys_order(_nodal_material ? getMaterialProperty<unsigned>(
"PorousFlow_hysteresis_order_nodal")
132 : getMaterialProperty<unsigned>(
"PorousFlow_hysteresis_order_qp")),
133 _hys_order_old(_nodal_material
134 ? getMaterialPropertyOld<unsigned>(
"PorousFlow_hysteresis_order_nodal")
135 : getMaterialPropertyOld<unsigned>(
"PorousFlow_hysteresis_order_qp")),
139 "PorousFlow_hysteresis_saturation_tps_nodal")
141 "PorousFlow_hysteresis_saturation_tps_qp")),
142 _pc_older(_nodal_material
143 ? getMaterialPropertyOlder<
Real>(
"PorousFlow_hysteretic_capillary_pressure_nodal")
144 : getMaterialPropertyOlder<
Real>(
"PorousFlow_hysteretic_capillary_pressure_qp")),
145 _pc_tps(_nodal_material
147 "PorousFlow_hysteresis_Pc_tps_nodal")
149 "PorousFlow_hysteresis_Pc_tps_qp")),
150 _s_d_tps(_nodal_material
152 "PorousFlow_hysteresis_s_d_tps_nodal")
154 "PorousFlow_hysteresis_s_d_tps_qp")),
155 _s_gr_tps(_nodal_material
157 "PorousFlow_hysteresis_s_gr_tps_nodal")
159 "PorousFlow_hysteresis_s_gr_tps_qp")),
164 "PorousFlow_hysteresis_w_low_ext_tps_nodal")
167 "PorousFlow_hysteresis_w_low_ext_tps_qp")),
172 "PorousFlow_hysteresis_w_high_ext_tps_nodal")
175 "PorousFlow_hysteresis_w_high_ext_tps_qp")),
176 _s_w_tps(_nodal_material
178 "PorousFlow_hysteresis_s_w_tps_nodal")
180 "PorousFlow_hysteresis_s_w_tps_qp"))
183 paramError(
"S_gr_max",
"Must be less than 1 - S_l_min");
185 paramError(
"high_ratio",
186 "Should be chosen sufficiently close to 1 so that the high extension does not " 187 "interfere with the low extension. Instead, you may have chosen Pc_max too low");
189 mooseWarning(
"S_lr should usually be greater than S_l_min");
236 return (1.0 - slDel) / (1.0 +
a * (1.0 - slDel));
244 _pc_tps[_qp].at(tp_num) = tp_pc;
265 const Real s_w_high_ext =
272 const Real pc_w_high_ext =
279 const Real dpc_w_high_ext =
323 else if (pc1 <= 0.0 || pc2 <= 0.0)
326 pc = std::exp(std::log(pc1) + (sat - tp1) * (std::log(pc2) - std::log(pc1)) / (tp2 - tp1));
355 else if (pc1 <= 0.0 || pc2 <= 0.0)
360 std::exp(std::log(pc1) + (sat - tp1) * (std::log(pc2) - std::log(pc1)) / (tp2 - tp1));
363 dpc = pc * (dpc1 / pc1 + (std::log(pc2) - std::log(pc1)) / (tp2 - tp1) +
364 (sat - tp1) * (dpc2 / pc2 - dpc1 / pc1) / (tp2 - tp1));
394 else if (pc1 <= 0.0 || pc2 <= 0.0)
399 std::exp(std::log(pc1) + (sat - tp1) * (std::log(pc2) - std::log(pc1)) / (tp2 - tp1));
402 const Real dpc = pc * (dpc1 / pc1 + (std::log(pc2) - std::log(pc1)) / (tp2 - tp1) +
403 (sat - tp1) * (dpc2 / pc2 - dpc1 / pc1) / (tp2 - tp1));
407 dpc * (dpc1 / pc1 + (std::log(pc2) - std::log(pc1)) / (tp2 - tp1) +
408 (sat - tp1) * (dpc2 / pc2 - dpc1 / pc1) / (tp2 - tp1)) +
410 (d2pc1 / pc1 - dpc1 * dpc1 / pc1 / pc1 + (dpc2 / pc2 - dpc1 / pc1) / (tp2 - tp1) +
411 (dpc2 / pc2 - dpc1 / pc1) / (tp2 - tp1) +
413 (d2pc2 / pc2 - dpc2 * dpc2 / pc2 / pc2 - d2pc1 / pc1 + dpc1 * dpc1 / pc1 / pc1) /
484 dsat_to_use * dsat_to_use;
496 const Real sat_to_use =
497 (sat >= tp0) ? tp0 + (sat - tp0) * (s1 - tp0) / (tp1 - tp0)
509 const Real sat_to_use = (sat >= tp0) ? tp0 + (sat - tp0) * (s1 - tp0) / (tp1 - tp0) : sat;
510 const Real dsat_to_use = (sat >= tp0) ? (s1 - tp0) / (tp1 - tp0) : 1.0;
522 const Real sat_to_use = (sat >= tp0) ? tp0 + (sat - tp0) * (s1 - tp0) / (tp1 - tp0) : sat;
523 const Real dsat_to_use = (sat >= tp0) ? (s1 - tp0) / (tp1 - tp0) : 1.0;
526 dsat_to_use * dsat_to_use;
544 if (sat_to_use > max_s)
595 const Real sat_to_use =
600 return (sat_to_use >= tp0) ? (sat_to_use - tp0) * (tp1 - tp0) / (s1 - tp0) + tp0 : sat_to_use;
606 const Real sat_to_use =
608 const Real dsat_to_use =
613 return (sat_to_use >= tp0) ? dsat_to_use * (tp1 - tp0) / (s1 - tp0) : dsat_to_use;
619 const Real sat_to_use =
621 const Real d2sat_to_use =
626 return (sat_to_use >= tp0) ? d2sat_to_use * (tp1 - tp0) / (s1 - tp0) : d2sat_to_use;
651 if (pc_tp1 <= 0.0 || pc <= 0.0 ||
656 else if (pc > pc_tp2)
658 else if (pc < pc_tp1)
661 sat = sat1 + (std::log(pc) - std::log(pc_tp1)) * (sat2 - sat1) / std::log(pc_tp2 / pc_tp1);
684 if (pc_tp1 <= 0.0 || pc <= 0.0 || pc_tp2 <= 0.0)
686 else if (pc > pc_tp2)
688 else if (pc < pc_tp1)
691 dsat = dsat1 + 1.0 / pc * (sat2 - sat1) / std::log(pc_tp2 / pc_tp1) +
692 (std::log(pc) - std::log(pc_tp1)) * (dsat2 - dsat1) / std::log(pc_tp2 / pc_tp1);
717 if (pc_tp1 <= 0.0 || pc <= 0.0 || pc_tp2 <= 0.0)
719 else if (pc > pc_tp2)
721 else if (pc < pc_tp1)
724 d2sat = d2sat1 - 1.0 / pc / pc * (sat2 - sat1) / std::log(pc_tp2 / pc_tp1) +
725 2.0 / pc * (dsat2 - dsat1) / std::log(pc_tp2 / pc_tp1) +
726 (std::log(pc) - std::log(pc_tp1)) * (d2sat2 - d2sat1) / std::log(pc_tp2 / pc_tp1);
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.
virtual void computeQpProperties() override
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.
const MaterialProperty< Real > & _pc_older
Older value of capillary pressure.
Real dsecondOrderDryingPc(Real sat) const
Real d2capillaryPressureQp(Real sat) const
virtual void initQpStatefulProperties() override
const Real _s_gr_max
Residual gas saturation: 1 - _s_gr_max is the maximum saturation for which the van Genuchten expressi...
Real d2firstOrderWettingSat(Real pc) const
MaterialProperty< std::array< PorousFlowVanGenuchten::LowCapillaryPressureExtension, PorousFlowConstants::MAX_HYSTERESIS_ORDER > > & _w_low_ext_tps
Nodal or quadpoint values of the low extension of the wetting curve defined by _s_gr_tps.
MaterialProperty< std::array< PorousFlowVanGenuchten::HighCapillaryPressureExtension, PorousFlowConstants::MAX_HYSTERESIS_ORDER > > & _w_high_ext_tps
Nodal or quadpoint values of the high extension of the wetting curve defined by _s_gr_tps.
const PorousFlowVanGenuchten::LowCapillaryPressureExtension::ExtensionStrategy _low_ext_type
Type of low-saturation extension.
const MaterialProperty< unsigned > & _hys_order
Hysteresis order, as computed by PorousFlowHysteresisOrder.
const Real _high_ratio
The high-saturation extension to the wetting will commence at _high_ratio * (1 - _s_gr_del) ...
const Real _pc_max
Maximum capillary pressure: for Pc above this value, a "lower" extension will be used.
Parameters associated with the extension of the hysteretic wetting capillary pressure function to hig...
Real capillaryPressureQp(Real sat) const
void mooseWarning(Args &&... args)
static InputParameters validParams()
const Real _s_lr
Liquid saturation below which the liquid relative permeability is zero.
Real d2firstOrderWettingPc(Real sat) const
const PorousFlowVanGenuchten::HighCapillaryPressureExtension::ExtensionStrategy _high_ext_type
Type of high-saturation extension of the wetting curves.
van Genuchten effective saturation, capillary pressure and relative permeability functions.
void computeTurningPointInfo(unsigned tp_num, Real tp_sat, Real tp_pc)
Compute all relevant quantities at the given turning point.
const Real _alpha_d
van Genuchten alpha parameter for the primary drying curve
Real d2secondOrderDryingSat(Real pc) const
const Real _s_high
Saturation at the point of high-saturation extension.
const Real _n_d
van Genuchten n parameter for the primary drying curve
PorousFlowHystereticCapillaryPressure(const InputParameters ¶meters)
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 Dou...
constexpr unsigned MAX_HYSTERESIS_ORDER
const MaterialProperty< std::array< Real, PorousFlowConstants::MAX_HYSTERESIS_ORDER > > & _hys_sat_tps
Saturation values at the turning points, as computed by PorousFlowHysteresisOrder.
Parameters associated with the extension of the hysteretic capillary pressure function to low saturat...
virtual void computeQpProperties() override
Real dliquidSaturationQp(Real pc) const
Base class for thermophysical variable materials, which assemble materials for primary variables such...
registerMooseObject("PorousFlowApp", PorousFlowHystereticCapillaryPressure)
static InputParameters validParams()
Real landSat(Real slDel) const
Real dsecondOrderDryingSat(Real pc) const
const Real _alpha_w
van Genuchten alpha parameter for the primary wetting curve
Real d2liquidSaturationQp(Real pc) const
Base material designed to calculate and store quantities relevant for hysteretic capillary pressure c...
MaterialProperty< std::array< Real, PorousFlowConstants::MAX_HYSTERESIS_ORDER > > & _pc_tps
Nodal or quadpoint values of Pc at the turning points.
const Real _n_w
van Genuchten n parameter for the primary wetting curve
virtual void initQpStatefulProperties() override
Real liquidSaturationQp(Real pc) const
Real secondOrderDryingSat(Real pc) const
Real firstOrderWettingSat(Real pc) const
Real secondOrderDryingPc(Real sat) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Real d2secondOrderDryingPc(Real sat) const
const PorousFlowVanGenuchten::LowCapillaryPressureExtension _low_ext_d
Parameters involved in the low-saturation extension of the primary drying curve.
const Real _s_low_w
Saturation on the primary wetting curve where low-saturation extension commences. ...
Real dfirstOrderWettingPc(Real sat) const
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.
MaterialProperty< std::array< Real, PorousFlowConstants::MAX_HYSTERESIS_ORDER > > & _s_gr_tps
Computed nodal or quadpoint values of S_gr_Del, ie, the Land expression, at the turning points...
MaterialProperty< std::array< Real, PorousFlowConstants::MAX_HYSTERESIS_ORDER > > & _s_w_tps
Computed nodal or quadpoint values of liquid saturation on the wetting curve defined by _s_gr_del...
Real dfirstOrderWettingSat(Real pc) const
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.
const Real _s_l_min
Minimum liquid saturation for which the van Genuchten expression is valid (Pc(_s_l_min) = infinity) ...
MaterialProperty< std::array< Real, PorousFlowConstants::MAX_HYSTERESIS_ORDER > > & _s_d_tps
Computed nodal or quadpoint values of saturation on the drying curve at _pc_tps.
Real firstOrderWettingPc(Real sat) const
Real dcapillaryPressureQp(Real sat) const
const MaterialProperty< unsigned > & _hys_order_old
Old value of hysteresis order, as computed by PorousFlowHysteresisOrder.
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...