https://mooseframework.inl.gov
PorousFlowHystereticInfo.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 
13 
16 {
18  params.addCoupledVar("pc_var",
19  0,
20  "Variable that represents capillary pressure. Depending on info_required, "
21  "this may not be used to compute the info");
22  params.addRequiredCoupledVar(
23  "sat_var",
24  "Variable that represent liquid saturation. This is always needed to "
25  "ensure the hysteretic order is computed correctly");
26  MooseEnum property_enum("pc sat sat_given_pc dS_dPc_err dPc_dS_err d2S_dPc2_err d2Pc_dS2_err",
27  "pc");
28  params.addParam<MooseEnum>(
29  "info_required",
30  property_enum,
31  "The type of information required. pc: capillary pressure given the saturation (pc_var is "
32  "not used in this case). sat: given the liquid saturation, compute the capillary pressure, "
33  "then invert the relationship to yield liquid saturation again (pc_var is not used in this "
34  "case). This is useful to understand the non-invertibility of the hysteretic relationships. "
35  " sat_given_pc: given the capillary pressure, compute the saturation. dS_dPc_err: relative "
36  "error in d(sat)/d(pc) calculation, ie (S(Pc + fd_eps) - S(Pc - fd_eps))/(2 * eps * S'(Pc)) "
37  "- 1, where S' is the coded derivative (Pc is computed from sat in this case: pc_var is not "
38  "used). This is useful for checking derivatives. dPc_dS_err: relative error in "
39  "d(pc)/d(sat) calculation, ie (Pc(S + fd_eps) - Pc(S - fd_eps)) / (2 * eps * Pc'(S)) - 1, "
40  "where Pc' is the coded derative (pc_var is not used in this case). d2S_dPc2_err: relative "
41  "error in d^2(sat)/d(pc)^2 (Pc is computed from sat in this case: pc_var is not used). "
42  "d2Pc_dS2_err: relative error in d^2(pc)/d(sat)^2.");
43  params.addParam<Real>(
44  "fd_eps",
45  1E-8,
46  "Small quantity used in computing the finite-difference approximations to derivatives");
47  params.addClassDescription(
48  "This Material computes capillary pressure or saturation, etc. It is primarily "
49  "of use when users desire to compute hysteretic quantities such as capillary pressure for "
50  "visualisation purposes. The "
51  "result is written into PorousFlow_hysteretic_info_nodal or "
52  "PorousFlow_hysteretic_info_qp (depending on the at_nodes flag). It "
53  "does not "
54  "compute porepressure and should not be used in simulations that employ "
55  "PorousFlow*PhaseHys* "
56  "Materials.");
57  return params;
58 }
59 
62  _pc(_nodal_material ? declareProperty<Real>("PorousFlow_hysteretic_capillary_pressure_nodal")
63  : declareProperty<Real>("PorousFlow_hysteretic_capillary_pressure_qp")),
64  _info(_nodal_material ? declareProperty<Real>("PorousFlow_hysteretic_info_nodal")
65  : declareProperty<Real>("PorousFlow_hysteretic_info_qp")),
66  _pc_val(_nodal_material ? coupledDofValues("pc_var") : coupledValue("pc_var")),
67  _sat_val(_nodal_material ? coupledDofValues("sat_var") : coupledValue("sat_var")),
68  _fd_eps(getParam<Real>("fd_eps")),
69  _info_enum(getParam<MooseEnum>("info_required").getEnum<InfoTypeEnum>())
70 {
71  // note that _num_phases must be positive, otherwise get a problem with using
72  // PorousFlowHysteresisOrder, so _num_phases > 0 needn't be checked here
73 }
74 
75 void
77 {
79  _saturation[_qp][0] = _sat_val[_qp];
80  _pc[_qp] = capillaryPressureQp(_sat_val[_qp]);
81  computeQpInfo();
82 }
83 
84 void
86 {
88  _saturation[_qp][0] = _sat_val[_qp];
89  _pc[_qp] = capillaryPressureQp(_sat_val[_qp]);
90  computeQpInfo();
91 }
92 
93 void
95 {
96  switch (_info_enum)
97  {
98  case InfoTypeEnum::PC:
99  _info[_qp] = capillaryPressureQp(_sat_val[_qp]);
100  break;
101  case InfoTypeEnum::SAT:
102  {
103  const Real pc = capillaryPressureQp(_sat_val[_qp]);
104  _info[_qp] = liquidSaturationQp(pc);
105  break;
106  }
108  _info[_qp] = liquidSaturationQp(_pc_val[_qp]);
109  break;
111  {
112  const Real pc = capillaryPressureQp(_sat_val[_qp]);
113  const Real fd =
115  _info[_qp] = relativeError(fd, dliquidSaturationQp(pc));
116  break;
117  }
119  {
120  const Real fd = 0.5 *
123  _fd_eps;
125  break;
126  }
128  {
129  const Real pc = capillaryPressureQp(_sat_val[_qp]);
130  const Real fd =
132  _info[_qp] = relativeError(fd, d2liquidSaturationQp(pc));
133  break;
134  }
136  {
137  const Real fd = 0.5 *
140  _fd_eps;
142  break;
143  }
144  }
145 }
146 
147 Real
148 PorousFlowHystereticInfo::relativeError(Real finite_difference, Real hand_coded)
149 {
150  if (finite_difference == 0.0 && hand_coded == 0.0)
151  return 0.0;
152  else if (finite_difference > 0.0 && hand_coded == 0.0)
153  return std::numeric_limits<Real>::max();
154  else if (finite_difference < 0.0 && hand_coded == 0.0)
155  return std::numeric_limits<Real>::min();
156  return finite_difference / hand_coded - 1.0;
157 }
const Real _fd_eps
small parameter to use in the finite-difference approximations to the derivative
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
InfoTypeEnum
Type of info required.
virtual void computeQpProperties() override
const VariableValue & _sat_val
Nodal or quadpoint value of liquid saturation.
MaterialProperty< Real > & _pc
Computed nodal or quadpoint value of capillary pressure (needed for hysteretic order computation) ...
void computeQpInfo()
Fill _info with the required information.
MaterialProperty< Real > & _info
Computed nodal or quadpoint value: the meaning of this depends on info_enum.
static InputParameters validParams()
PorousFlowHystereticInfo(const InputParameters &parameters)
virtual void initQpStatefulProperties() override
Real relativeError(Real finite_difference, Real hand_coded)
Computes the relative error between a finite-difference approximation to the derivative and a hand-co...
Base material designed to calculate and store quantities relevant for hysteretic capillary pressure c...
void addCoupledVar(const std::string &name, const std::string &doc_string)
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Material designed to calculate the capillary pressure as a function of saturation, or the saturation as a function of capillary pressure, or derivative information, etc.
void addClassDescription(const std::string &doc_string)
enum PorousFlowHystereticInfo::InfoTypeEnum _info_enum
GenericMaterialProperty< std::vector< Real >, is_ad > & _saturation
Computed nodal or qp saturation of the phases.
registerMooseObject("PorousFlowApp", PorousFlowHystereticInfo)
const VariableValue & _pc_val
Nodal or quadpoint value of capillary pressure.