https://mooseframework.inl.gov
PorousFlowPorosityLinear.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.addParam<bool>("strain_at_nearest_qp",
19  false,
20  "When calculating nodal porosity that depends on strain, use the strain at "
21  "the nearest quadpoint. This adds a small extra computational burden, and "
22  "is not necessary for simulations involving only linear lagrange elements. "
23  " If you set this to true, you will also want to set the same parameter to "
24  "true for related Kernels and Materials");
25  params.addRequiredCoupledVar(
26  "porosity_ref",
27  "The porosity at reference effective porepressure, temperature and volumetric strain. This "
28  "must be a real number or a constant monomial variable (not a linear lagrange or other type "
29  "of variable)");
30  params.addCoupledVar(
31  "P_ref",
32  0.0,
33  "The reference effective porepressure. This should usually be a linear-lagrange variable");
34  params.addCoupledVar(
35  "T_ref",
36  0.0,
37  "The reference temperature. This should usually be a linear-lagrange variable");
38  params.addCoupledVar("epv_ref",
39  0.0,
40  "The reference volumetric strain. This must be a real number or a constant "
41  "monomial variable (not a linear lagrange or other type of variable)");
42  params.addParam<Real>("P_coeff", 0.0, "Effective porepressure coefficient");
43  params.addParam<Real>("T_coeff", 0.0, "Temperature coefficient");
44  params.addParam<Real>("epv_coeff", 0.0, "Volumetric-strain coefficient");
45  params.addRangeCheckedParam<Real>(
46  "porosity_min",
47  0.0,
48  "porosity_min >= 0",
49  "Minimum allowed value of the porosity: if the linear relationship gives "
50  "values less than this value, then porosity is set to this value instead");
51  params.addParam<Real>(
52  "zero_modifier",
53  1E-3,
54  "If the linear relationship produces porosity < porosity_min, then porosity is set "
55  "porosity_min. This means the derivatives of it will be zero. However, these zero "
56  "derivatives often result in poor NR convergence, so the derivatives are set to "
57  "_zero_modifier * (values that are relevant for min porosity) to hint to the NR that "
58  "porosity is not always constant");
59  params.addParamNamesToGroup("zero_modifier", "Advanced");
60  params.addClassDescription(
61  "This Material calculates the porosity in PorousFlow simulations using the relationship "
62  "porosity_ref + P_coeff * (P - P_ref) + T_coeff * (T - T_ref) + epv_coeff * (epv - epv_ref), "
63  "where P is the effective porepressure, T is the temperature and epv is the volumetric "
64  "strain");
65  return params;
66 }
67 
69  : PorousFlowPorosityBase(parameters),
70  _strain_at_nearest_qp(getParam<bool>("strain_at_nearest_qp")),
71  _porosity_min(getParam<Real>("porosity_min")),
72  _phi_ref(coupledValue("porosity_ref")),
73  _P_ref(_nodal_material ? coupledDofValues("P_ref") : coupledValue("P_ref")),
74  _T_ref(_nodal_material ? coupledDofValues("T_ref") : coupledValue("T_ref")),
75  _epv_ref(coupledValue("epv_ref")),
76  _P_coeff(getParam<Real>("P_coeff")),
77  _T_coeff(getParam<Real>("T_coeff")),
78  _epv_coeff(getParam<Real>("epv_coeff")),
79 
80  _uses_volstrain(parameters.isParamSetByUser("epv_coeff") && _epv_coeff != 0.0),
81  _vol_strain_qp(getOptionalMaterialProperty<Real>("PorousFlow_total_volumetric_strain_qp")),
82  _dvol_strain_qp_dvar(getOptionalMaterialProperty<std::vector<RealGradient>>(
83  "dPorousFlow_total_volumetric_strain_qp_dvar")),
84 
85  _uses_pf(parameters.isParamSetByUser("P_coeff") && _P_coeff != 0.0),
86  _pf_nodal(getOptionalMaterialProperty<Real>("PorousFlow_effective_fluid_pressure_nodal")),
87  _pf_qp(getOptionalMaterialProperty<Real>("PorousFlow_effective_fluid_pressure_qp")),
88  _dpf_dvar_nodal(getOptionalMaterialProperty<std::vector<Real>>(
89  "dPorousFlow_effective_fluid_pressure_nodal_dvar")),
90  _dpf_dvar_qp(getOptionalMaterialProperty<std::vector<Real>>(
91  "dPorousFlow_effective_fluid_pressure_qp_dvar")),
92 
93  _uses_T(parameters.isParamSetByUser("T_coeff") && _T_coeff != 0.0),
94  _temperature_nodal(getOptionalMaterialProperty<Real>("PorousFlow_temperature_nodal")),
95  _temperature_qp(getOptionalMaterialProperty<Real>("PorousFlow_temperature_qp")),
96  _dtemperature_dvar_nodal(
97  getOptionalMaterialProperty<std::vector<Real>>("dPorousFlow_temperature_nodal_dvar")),
98  _dtemperature_dvar_qp(
99  getOptionalMaterialProperty<std::vector<Real>>("dPorousFlow_temperature_qp_dvar")),
100  _zero_modifier(getParam<Real>("zero_modifier"))
101 {
102 }
103 
104 void
106 {
107  _pf = _nodal_material ? _pf_nodal.get() : _pf_qp.get();
108  _dpf_dvar = _nodal_material ? _dpf_dvar_nodal.get() : _dpf_dvar_qp.get();
109  if (!(_pf && _dpf_dvar) && _uses_pf)
110  {
111  mooseError("PorousFlowPorosityLinear: When P_coeff is given you must have an effective fluid "
112  "pressure Material");
113  }
114 
115  _temperature = _nodal_material ? _temperature_nodal.get() : _temperature_qp.get();
117  _nodal_material ? _dtemperature_dvar_nodal.get() : _dtemperature_dvar_qp.get();
118  if (!_temperature && _uses_T)
119  mooseError(
120  "PorousFlowPorosityLinear: When T_coeff is given you must have a temperature Material");
121 
123  mooseError("PorousFlowPorosityLinear: When epv_coeff is given you must have a "
124  "volumetric-strain Material");
125 
126  PorousFlowPorosityBase::initialSetup();
127 }
128 
129 void
131 {
132  _porosity[_qp] = _phi_ref[0];
133  (*_dporosity_dvar)[_qp].assign(_num_var, 0.0);
134  (*_dporosity_dgradvar)[_qp].assign(_num_var, 0.0);
135 }
136 
137 void
139 {
140  // note the [0] below: _phi_ref is a constant monomial and we use [0] regardless of
141  // _nodal_material
142  Real porosity = _phi_ref[0];
143  if (_uses_pf)
144  porosity += _P_coeff * ((*_pf)[_qp] - _P_ref[_qp]);
145  if (_uses_T)
146  porosity += _T_coeff * ((*_temperature)[_qp] - _T_ref[_qp]);
147  if (_uses_volstrain)
148  {
149  // Note that in the following _strain[_qp] is evaluated at q quadpoint
150  // So _porosity_nodal[_qp], which should be the nodal value of porosity
151  // actually uses the strain at a quadpoint. This
152  // is OK for LINEAR elements, as strain is constant over the element anyway.
153  const unsigned qp_to_use =
154  (_nodal_material && (_bnd || _strain_at_nearest_qp) ? nearestQP(_qp) : _qp);
155  porosity += _epv_coeff * (_vol_strain_qp[qp_to_use] - _epv_ref[0]);
156  }
157 
158  if (porosity < _porosity_min)
159  _porosity[_qp] = _porosity_min;
160  else
161  _porosity[_qp] = porosity;
162 
163  (*_dporosity_dvar)[_qp].resize(_num_var);
164  (*_dporosity_dgradvar)[_qp].resize(_num_var);
165  for (unsigned int pvar = 0; pvar < _num_var; ++pvar)
166  {
167  Real deriv = 0.0;
168  if (_uses_pf)
169  deriv += _P_coeff * (*_dpf_dvar)[_qp][pvar];
170  if (_uses_T)
171  deriv += _T_coeff * (*_dtemperature_dvar)[_qp][pvar];
172  if (porosity < _porosity_min)
173  (*_dporosity_dvar)[_qp][pvar] = _zero_modifier * deriv;
174  else
175  (*_dporosity_dvar)[_qp][pvar] = deriv;
176 
177  RealGradient deriv_grad(0.0, 0.0, 0.0);
178  if (_uses_volstrain)
179  {
180  const unsigned qp_to_use =
181  (_nodal_material && (_bnd || _strain_at_nearest_qp) ? nearestQP(_qp) : _qp);
182  deriv_grad += _epv_coeff * _dvol_strain_qp_dvar[qp_to_use][pvar];
183  }
184  if (porosity < _porosity_min)
185  (*_dporosity_dgradvar)[_qp][pvar] = _zero_modifier * deriv_grad;
186  else
187  (*_dporosity_dgradvar)[_qp][pvar] = deriv_grad;
188  }
189 }
const bool _strain_at_nearest_qp
When calculating nodal porosity, use the strain at the nearest quadpoint to the node.
Material designed to provide the porosity in PorousFlow simulations porosity_ref + P_coeff * (P - P_r...
const OptionalMaterialProperty< Real > & _temperature_nodal
Temperature at the quadpoints or nodes.
const VariableValue & _T_ref
Reference temperature.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
MaterialProperty< std::vector< RealGradient > > *const _dporosity_dgradvar
d(porosity)/d(grad PorousFlow variable)
void mooseError(Args &&... args)
const OptionalMaterialProperty< std::vector< Real > > & _dpf_dvar_nodal
d(effective porepressure)/(d porflow variable)
virtual void initialSetup() override
const Real _P_coeff
coefficient of effective porepressure
const Real _T_coeff
coefficient of temperature
const VariableValue & _epv_ref
Reference volumetric strain.
const OptionalMaterialProperty< Real > & _vol_strain_qp
Strain (first const means we never want to dereference and change the value, second means we&#39;ll alway...
const MaterialProperty< std::vector< Real > > * _dtemperature_dvar
static const std::string porosity
Definition: NS.h:104
const OptionalMaterialProperty< std::vector< Real > > & _dtemperature_dvar_qp
PorousFlowPorosityLinear(const InputParameters &parameters)
static InputParameters validParams()
const OptionalMaterialProperty< Real > & _pf_qp
static InputParameters validParams()
Real deriv(unsigned n, unsigned alpha, unsigned beta, Real x)
const bool _uses_pf
whether P_coeff has been set
const OptionalMaterialProperty< std::vector< Real > > & _dpf_dvar_qp
Base class Material designed to provide the porosity.
const MaterialProperty< Real > * _temperature
const unsigned int _num_var
Number of PorousFlow variables.
const bool _uses_T
whether T_coeff has been set
const Real _epv_coeff
coefficient of volumetric strain
const bool _uses_volstrain
whether epv_coeff has been set
void addCoupledVar(const std::string &name, const std::string &doc_string)
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
MaterialProperty< std::vector< Real > > *const _dporosity_dvar
d(porosity)/d(PorousFlow variable)
const Real _porosity_min
If the linear relationship produces porosity < _porosity_min, then porosity is set to _porosity_min...
const MaterialProperty< std::vector< Real > > * _dpf_dvar
GenericMaterialProperty< Real, is_ad > & _porosity
Computed porosity at the nodes or quadpoints.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void initQpStatefulProperties() override
const Real _zero_modifier
If the linear relationship produces porosity < _porosity_min, then porosity is set to _porosity_min...
void addClassDescription(const std::string &doc_string)
registerMooseObject("PorousFlowApp", PorousFlowPorosityLinear)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
const VariableValue & _P_ref
Reference effective porepressure.
const VariableValue & _phi_ref
Porosity at reference porepressure, temperature and volumetric strain.
const OptionalMaterialProperty< Real > & _pf_nodal
Effective porepressure at the quadpoints or nodes.
const OptionalMaterialProperty< std::vector< Real > > & _dtemperature_dvar_nodal
d(temperature)/(d porflow variable)
const OptionalMaterialProperty< std::vector< RealGradient > > & _dvol_strain_qp_dvar
d(strain)/(dvar) (first const means we never want to dereference and change the value, second means we&#39;ll always be pointing to the same address after initialization (like a reference))
virtual void computeQpProperties() override
const MaterialProperty< Real > * _pf
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
const OptionalMaterialProperty< Real > & _temperature_qp