https://mooseframework.inl.gov
PorousFlowPorosity.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 
10 #include "PorousFlowPorosity.h"
11 
12 registerMooseObject("PorousFlowApp", PorousFlowPorosity);
13 
16 {
18  params.addParam<bool>(
19  "mechanical", false, "If true, porosity will be a function of total volumetric strain");
20  params.addParam<bool>(
21  "fluid", false, "If true, porosity will be a function of effective porepressure");
22  params.addParam<bool>("thermal", false, "If true, porosity will be a function of temperature");
23  params.addParam<bool>("chemical", false, "If true, porosity will be a function of precipitate");
24  params.addRequiredCoupledVar("porosity_zero",
25  "The porosity at zero volumetric strain and "
26  "reference temperature and reference effective "
27  "porepressure and reference chemistry. This must be a real number "
28  "or a constant monomial variable (not a linear lagrange or other "
29  "type of variable)");
30  params.addParam<Real>("thermal_expansion_coeff",
31  "Volumetric thermal expansion coefficient of the drained porous solid "
32  "skeleton (only used if thermal=true)");
33  params.addRangeCheckedParam<Real>(
34  "biot_coefficient", 1, "biot_coefficient>=0 & biot_coefficient<=1", "Biot coefficient");
35  params.addParam<Real>("biot_coefficient_prime",
36  "Biot coefficient that appears in the term (biot_coefficient_prime - 1) * "
37  "(P - reference_porepressure) / solid_bulk. If not provided, this "
38  "defaults to the standard biot_coefficient");
39  params.addRangeCheckedParam<Real>(
40  "solid_bulk",
41  "solid_bulk>0",
42  "Bulk modulus of the drained porous solid skeleton (only used if fluid=true)");
43  params.addCoupledVar(
44  "reference_temperature", 0.0, "Reference temperature (only used if thermal=true)");
45  params.addCoupledVar(
46  "reference_porepressure", 0.0, "Reference porepressure (only used if fluid=true)");
47  params.addCoupledVar("reference_chemistry",
48  "Reference values of the solid mineral concentrations "
49  "(m^3(precipitate)/m^3(porous material)), entered as "
50  "a vector (one value per mineral). (Only used if chemical=true)");
51  params.addCoupledVar(
52  "initial_mineral_concentrations",
53  "Initial mineral concentrations (m^3(precipitate)/m^3(porous material)), entered as "
54  "a vector (one value per mineral). (Only used if chemical=true)");
55  params.addParam<std::vector<Real>>("chemical_weights",
56  "When chemical=true, porosity is a linear combination of the "
57  "solid mineral concentrations multiplied by these weights. "
58  "Default=1 for all minerals.");
59  params.addClassDescription("This Material calculates the porosity PorousFlow simulations");
60  return params;
61 }
62 
65 
66  _mechanical(getParam<bool>("mechanical")),
67  _fluid(getParam<bool>("fluid")),
68  _thermal(getParam<bool>("thermal")),
69  _chemical(getParam<bool>("chemical")),
70  _phi0(coupledValue("porosity_zero")),
71  _biot(getParam<Real>("biot_coefficient")),
72  _exp_coeff(isParamValid("thermal_expansion_coeff") ? getParam<Real>("thermal_expansion_coeff")
73  : 0.0),
74  _solid_bulk(isParamValid("solid_bulk") ? getParam<Real>("solid_bulk")
75  : std::numeric_limits<Real>::max()),
76  _coeff(isParamValid("biot_coefficient_prime")
77  ? (getParam<Real>("biot_coefficient_prime") - 1.0) / _solid_bulk
78  : (_biot - 1.0) / _solid_bulk),
79 
80  _t_reference(_nodal_material ? coupledDofValues("reference_temperature")
81  : coupledValue("reference_temperature")),
82  _p_reference(_nodal_material ? coupledDofValues("reference_porepressure")
83  : coupledValue("reference_porepressure")),
84  _num_c_ref(coupledComponents("reference_chemistry")),
85  _c_reference(_num_c_ref),
86  _num_initial_c(coupledComponents("initial_mineral_concentrations")),
87  _initial_c(_num_initial_c),
88  _c_weights(isParamValid("chemical_weights") ? getParam<std::vector<Real>>("chemical_weights")
89  : std::vector<Real>(_num_c_ref, 1.0)),
90 
91  _porosity_old(_chemical ? (_nodal_material
92  ? &getMaterialPropertyOld<Real>("PorousFlow_porosity_nodal")
93  : &getMaterialPropertyOld<Real>("PorousFlow_porosity_qp"))
94  : nullptr),
95  _vol_strain_qp(_mechanical ? &getMaterialProperty<Real>("PorousFlow_total_volumetric_strain_qp")
96  : nullptr),
97  _dvol_strain_qp_dvar(_mechanical ? &getMaterialProperty<std::vector<RealGradient>>(
98  "dPorousFlow_total_volumetric_strain_qp_dvar")
99  : nullptr),
100 
101  _pf(_fluid ? (_nodal_material
102  ? &getMaterialProperty<Real>("PorousFlow_effective_fluid_pressure_nodal")
103  : &getMaterialProperty<Real>("PorousFlow_effective_fluid_pressure_qp"))
104  : nullptr),
105  _dpf_dvar(_fluid ? (_nodal_material ? &getMaterialProperty<std::vector<Real>>(
106  "dPorousFlow_effective_fluid_pressure_nodal_dvar")
107  : &getMaterialProperty<std::vector<Real>>(
108  "dPorousFlow_effective_fluid_pressure_qp_dvar"))
109  : nullptr),
110 
111  _temperature(_thermal
112  ? (_nodal_material ? &getMaterialProperty<Real>("PorousFlow_temperature_nodal")
113  : &getMaterialProperty<Real>("PorousFlow_temperature_qp"))
114  : nullptr),
115  _dtemperature_dvar(
116  _thermal
117  ? (_nodal_material
118  ? &getMaterialProperty<std::vector<Real>>("dPorousFlow_temperature_nodal_dvar")
119  : &getMaterialProperty<std::vector<Real>>("dPorousFlow_temperature_qp_dvar"))
120  : nullptr),
121 
122  _mineral_conc_old(_chemical ? (_nodal_material ? &getMaterialPropertyOld<std::vector<Real>>(
123  "PorousFlow_mineral_concentration_nodal")
124  : &getMaterialPropertyOld<std::vector<Real>>(
125  "PorousFlow_mineral_concentration_qp"))
126  : nullptr),
127  _reaction_rate(_chemical ? (_nodal_material ? &getMaterialProperty<std::vector<Real>>(
128  "PorousFlow_mineral_reaction_rate_nodal")
129  : &getMaterialProperty<std::vector<Real>>(
130  "PorousFlow_mineral_reaction_rate_qp"))
131  : nullptr),
132  _dreaction_rate_dvar(_chemical ? (_nodal_material
133  ? &getMaterialProperty<std::vector<std::vector<Real>>>(
134  "dPorousFlow_mineral_reaction_rate_nodal_dvar")
135  : &getMaterialProperty<std::vector<std::vector<Real>>>(
136  "dPorousFlow_mineral_reaction_rate_qp_dvar"))
137  : nullptr),
138  _aq_ph(_dictator.aqueousPhaseNumber()),
139  _saturation(_chemical
140  ? (_nodal_material
141  ? &getMaterialProperty<std::vector<Real>>("PorousFlow_saturation_nodal")
142  : &getMaterialProperty<std::vector<Real>>("PorousFlow_saturation_qp"))
143  : nullptr),
144  _dsaturation_dvar(_chemical
145  ? (_nodal_material ? &getMaterialProperty<std::vector<std::vector<Real>>>(
146  "dPorousFlow_saturation_nodal_dvar")
147  : &getMaterialProperty<std::vector<std::vector<Real>>>(
148  "dPorousFlow_saturation_qp_dvar"))
149  : nullptr)
150 {
151  if (_thermal && !isParamValid("thermal_expansion_coeff"))
152  mooseError("PorousFlowPorosity: When thermal=true you must provide a thermal_expansion_coeff");
153  if (_fluid && !isParamValid("solid_bulk"))
154  mooseError("PorousFlowPorosity: When fluid=true you must provide a solid_bulk");
155  if (_chemical && _num_c_ref != _dictator.numAqueousKinetic())
156  mooseError("PorousFlowPorosity: When chemical=true you must provide the reference_chemistry "
157  "values. The Dictator proclaims there should be ",
158  _dictator.numAqueousKinetic(),
159  " of these");
160  if (_chemical && _num_initial_c != _dictator.numAqueousKinetic())
161  mooseError("PorousFlowPorosity: When chemical=true you must provide the "
162  "initial_mineral_concentrations. "
163  "The Dictator proclaims there should be ",
164  _dictator.numAqueousKinetic(),
165  " of these");
166  if (_chemical && _c_weights.size() != _dictator.numAqueousKinetic())
167  mooseError(
168  "PorousFlowPorosity: When chemical=true you must provde the correct number of "
169  "chemical_weights (which the Dictator knows is ",
170  _dictator.numAqueousKinetic(),
171  ") or do not provide any chemical_weights and use the default value of 1 for each mineral");
172 
173  for (unsigned i = 0; i < _num_c_ref; ++i)
174  {
175  _c_reference[i] = (_nodal_material ? &coupledDofValues("reference_chemistry", i)
176  : &coupledValue("reference_chemistry", i));
177  _initial_c[i] = (_nodal_material ? &coupledDofValues("initial_mineral_concentrations", i)
178  : &coupledValue("initial_mineral_concentrations", i));
179  }
180 }
181 
182 Real
184 {
185  /*
186  *
187  * Note the use of the OLD value of porosity here.
188  * This strategy, which breaks the cyclic dependency between porosity
189  * and mineral concentration, is used in
190  * Kernel: PorousFlowPreDis
191  * Material: PorousFlowPorosity
192  * Material: PorousFlowAqueousPreDisChemistry
193  * Material: PorousFlowAqueousPreDisMineral
194  *
195  */
196  Real result = _biot;
197  if (_chemical)
198  {
199  if (_t_step == 0 && !_app.isRestarting())
200  for (unsigned i = 0; i < _num_c_ref; ++i)
201  result -= _c_weights[i] * (*_initial_c[i])[_qp];
202  else
203  for (unsigned i = 0; i < _num_c_ref; ++i)
204  result -= _c_weights[i] * ((*_mineral_conc_old)[_qp][i] + _dt * (*_porosity_old)[_qp] *
205  (*_saturation)[_qp][_aq_ph] *
206  (*_reaction_rate)[_qp][i]);
207  }
208  return result;
209 }
210 
211 Real
213 {
214  Real result = 0.0;
215  if (_chemical && (_t_step >= 1 || _app.isRestarting()))
216  for (unsigned i = 0; i < _num_c_ref; ++i)
217  result -= _c_weights[i] * _dt * (*_porosity_old)[_qp] *
218  ((*_saturation)[_qp][_aq_ph] * (*_dreaction_rate_dvar)[_qp][i][pvar] +
219  (*_dsaturation_dvar)[_qp][_aq_ph][pvar] * (*_reaction_rate)[_qp][i]);
220  return result;
221 }
222 
223 Real
225 {
226  // note the [0] below: _phi0 is a constant monomial and we use [0] regardless of _nodal_material
227  Real result = _phi0[0];
228  if (_chemical)
229  {
230  if (_t_step == 0 && !_app.isRestarting())
231  for (unsigned i = 0; i < _num_c_ref; ++i)
232  result -= _c_weights[i] * ((*_initial_c[i])[_qp] - (*_c_reference[i])[_qp]);
233  else
234  for (unsigned i = 0; i < _num_c_ref; ++i)
235  result -= _c_weights[i] * ((*_mineral_conc_old)[_qp][i] +
236  _dt * (*_porosity_old)[_qp] * (*_saturation)[_qp][_aq_ph] *
237  (*_reaction_rate)[_qp][i] -
238  (*_c_reference[i])[_qp]);
239  }
240  return result;
241 }
242 
243 Real
244 PorousFlowPorosity::datZeroQp(unsigned pvar) const
245 {
246  Real result = 0.0;
247  if (_chemical && (_t_step >= 1 || _app.isRestarting()))
248  for (unsigned i = 0; i < _num_c_ref; ++i)
249  result -= _c_weights[i] * _dt * (*_porosity_old)[_qp] *
250  ((*_saturation)[_qp][_aq_ph] * (*_dreaction_rate_dvar)[_qp][i][pvar] +
251  (*_dsaturation_dvar)[_qp][_aq_ph][pvar] * (*_reaction_rate)[_qp][i]);
252  return result;
253 }
254 
255 Real
257 {
258  Real result = 0.0;
259 
260  if (_thermal)
261  result += _exp_coeff * ((*_temperature)[_qp] - _t_reference[_qp]);
262 
263  if (_fluid)
264  result += _coeff * ((*_pf)[_qp] - _p_reference[_qp]);
265 
266  if (_mechanical)
267  {
268  // Note that in the following _strain[_qp] is evaluated at q quadpoint
269  // So _porosity_nodal[_qp], which should be the nodal value of porosity
270  // actually uses the strain at a quadpoint. This
271  // is OK for LINEAR elements, as strain is constant over the element anyway.
272  const unsigned qp_to_use =
273  (_nodal_material && (_bnd || _strain_at_nearest_qp) ? nearestQP(_qp) : _qp);
274  result += -(*_vol_strain_qp)[qp_to_use];
275  }
276 
277  return result;
278 }
279 
280 Real
282 {
283  Real result = 0.0;
284 
285  if (_thermal)
286  result += _exp_coeff * (*_dtemperature_dvar)[_qp][pvar];
287 
288  if (_fluid)
289  result += _coeff * (*_dpf_dvar)[_qp][pvar];
290 
291  return result;
292 }
293 
296 {
297  RealGradient result(0.0, 0.0, 0.0);
298  if (_mechanical)
299  {
300  const unsigned qp_to_use =
301  (_nodal_material && (_bnd || _strain_at_nearest_qp) ? nearestQP(_qp) : _qp);
302  result += -(*_dvol_strain_qp_dvar)[qp_to_use][pvar];
303  }
304  return result;
305 }
const Real _coeff
Short-hand number (biot-1)/solid_bulk.
Base class Material designed to provide the porosity.
const Real _biot
Biot coefficient.
const VariableValue & _t_reference
Reference temperature.
const VariableValue & _phi0
Porosity at zero strain and zero porepressure and zero temperature.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const bool _strain_at_nearest_qp
When calculating nodal porosity, use the strain at the nearest quadpoint to the node.
void mooseError(Args &&... args)
virtual RealGradient ddecayQp_dgradvar(unsigned pvar) const override
d(decay)/d(grad(PorousFlow variable pvar))
const MaterialProperty< std::vector< Real > > *const _mineral_conc_old
Old value of mineral concentration at the quadpoints or nodes.
const bool _thermal
Porosity is a function of temperature.
std::vector< Real > _c_weights
Weights for the mineral concentrations.
const bool _chemical
Porosity is a function of chemistry.
virtual Real datZeroQp(unsigned pvar) const override
d(a)/d(PorousFlow variable pvar)
const unsigned _num_c_ref
Number of reference mineral concentrations provided by user.
const MaterialProperty< Real > *const _porosity_old
Old value of porosity.
auto max(const L &left, const R &right)
const unsigned int _aq_ph
Aqueous phase number.
registerMooseObject("PorousFlowApp", PorousFlowPorosity)
std::vector< const VariableValue * > _initial_c
Reference mineral concentrations.
const Real _exp_coeff
Thermal expansion coefficient of the solid porous skeleton.
const VariableValue & _p_reference
Reference porepressure.
const unsigned _num_initial_c
Number of reference mineral concentrations provided by user.
const bool _fluid
Porosity is a function of effective porepressure.
void addCoupledVar(const std::string &name, const std::string &doc_string)
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
PorousFlowPorosity(const InputParameters &parameters)
std::vector< const VariableValue * > _c_reference
Reference mineral concentrations.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Material designed to provide the porosity in PorousFlow simulations chemistry + biot + (phi0 - refere...
virtual Real atZeroQp() const override
Returns "b" at the quadpoint (porosity = a + (b - a) * exp(decay))
const bool _mechanical
Porosity is a function of volumetric strain.
virtual Real datNegInfinityQp(unsigned pvar) const override
d(a)/d(PorousFlow variable pvar)
void addClassDescription(const std::string &doc_string)
virtual Real decayQp() const override
Returns "decay" at the quadpoint (porosity = a + (b - a) * exp(decay))
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
virtual Real atNegInfinityQp() const override
Returns "a" at the quadpoint (porosity = a + (b - a) * exp(decay))
virtual Real ddecayQp_dvar(unsigned pvar) const override
d(decay)/d(PorousFlow variable pvar)
static InputParameters validParams()