https://mooseframework.inl.gov
PorousFlowFluidState.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 "PorousFlowFluidState.h"
11 
14 
15 template <bool is_ad>
18 {
20  params.addRequiredCoupledVar("gas_porepressure",
21  "Variable that is the porepressure of the gas phase");
22  params.addRequiredCoupledVar("z", "Total mass fraction of component i summed over all phases");
23  params.addCoupledVar(
24  "temperature", 20, "The fluid temperature (C or K, depending on temperature_unit)");
25  params.addCoupledVar("xnacl", 0, "The salt mass fraction in the brine (kg/kg)");
26  params.addRequiredParam<UserObjectName>("fluid_state", "Name of the FluidState UserObject");
27  params.addClassDescription("Class for fluid state calculations using persistent primary "
28  "variables and a vapor-liquid flash");
29  return params;
30 }
31 
32 template <bool is_ad>
34  : PorousFlowFluidStateBaseMaterialTempl<is_ad>(parameters),
35  _gas_porepressure(_nodal_material
36  ? this->template coupledGenericDofValue<is_ad>("gas_porepressure")
37  : this->template coupledGenericValue<is_ad>("gas_porepressure")),
38  _gas_gradp_qp(this->template coupledGenericGradient<is_ad>("gas_porepressure")),
39  _gas_porepressure_varnum(coupled("gas_porepressure")),
40  _pvar(_dictator.isPorousFlowVariable(_gas_porepressure_varnum)
41  ? _dictator.porousFlowVariableNum(_gas_porepressure_varnum)
42  : 0),
43  _num_Z_vars(coupledComponents("z")),
44  _is_Xnacl_nodal(isCoupled("xnacl") ? getFieldVar("xnacl", 0)->isNodal() : false),
45  _Xnacl(_nodal_material && _is_Xnacl_nodal
46  ? this->template coupledGenericDofValue<is_ad>("xnacl")
47  : this->template coupledGenericValue<is_ad>("xnacl")),
48  _grad_Xnacl_qp(this->template coupledGenericGradient<is_ad>("xnacl")),
49  _Xnacl_varnum(coupled("xnacl")),
50  _Xvar(_dictator.isPorousFlowVariable(_Xnacl_varnum)
51  ? _dictator.porousFlowVariableNum(_Xnacl_varnum)
52  : 0),
53  _fs(this->template getUserObject<PorousFlowFluidStateMultiComponentBase>("fluid_state")),
54  _aqueous_phase_number(_fs.aqueousPhaseIndex()),
55  _gas_phase_number(_fs.gasPhaseIndex()),
56  _aqueous_fluid_component(_fs.aqueousComponentIndex()),
57  _gas_fluid_component(_fs.gasComponentIndex()),
58  _salt_component(_fs.saltComponentIndex()),
59  _temperature(
60  this->template getGenericMaterialProperty<Real, is_ad>("PorousFlow_temperature" + _sfx)),
61  _gradT_qp(_nodal_material ? nullptr
62  : &this->template getGenericMaterialProperty<RealGradient, is_ad>(
63  "PorousFlow_grad_temperature" + _sfx)),
64  _dtemperature_dvar(is_ad ? nullptr
65  : &this->template getMaterialProperty<std::vector<Real>>(
66  "dPorousFlow_temperature" + _sfx + "_dvar")),
67  _temperature_varnum(coupled("temperature")),
68  _Tvar(_dictator.isPorousFlowVariable(_temperature_varnum)
69  ? _dictator.porousFlowVariableNum(_temperature_varnum)
70  : 0),
71  _pidx(_fs.getPressureIndex()),
72  _Tidx(_fs.getTemperatureIndex()),
73  _Zidx(_fs.getZIndex()),
74  _Xidx(_fs.getXIndex())
75 {
76  // Check that the number of phases in the fluidstate class is also provided in the Dictator
77  if (_fs.numPhases() != _num_phases)
78  mooseError(name(),
79  ": only ",
80  _fs.numPhases(),
81  " phases are allowed. Please check the number of phases entered in the dictator is "
82  "correct");
83 
84  // Store all total mass fractions and associated variable numbers
85  _Z.resize(_num_Z_vars);
86  _gradZ_qp.resize(_num_Z_vars);
87  _Z_varnum.resize(_num_Z_vars);
88  _Zvar.resize(_num_Z_vars);
89 
90  for (unsigned int i = 0; i < _num_Z_vars; ++i)
91  {
92  _Z[i] = (_nodal_material ? &this->template coupledGenericDofValue<is_ad>("z", i)
93  : &this->template coupledGenericValue<is_ad>("z", i));
94  _gradZ_qp[i] = &this->template coupledGenericGradient<is_ad>("z", i);
95  _Z_varnum[i] = coupled("z", i);
96  _Zvar[i] = (_dictator.isPorousFlowVariable(_Z_varnum[i])
97  ? _dictator.porousFlowVariableNum(_Z_varnum[i])
98  : 0);
99  }
100 }
101 
102 template <bool is_ad>
103 void
105 {
106  // The FluidProperty objects use temperature in K
107  const GenericReal<is_ad> Tk = _temperature[_qp] + _T_c2k;
108 
109  _fs.clearFluidStateProperties(_fsp);
110  _fs.thermophysicalProperties(_gas_porepressure[_qp], Tk, _Xnacl[_qp], (*_Z[0])[_qp], _qp, _fsp);
111 }
112 
113 template <bool is_ad>
114 void
116 {
118 }
119 
120 template <bool is_ad>
121 void
123 {
125 
126  // If the material isn't AD, we need to compute the derivatives
127  if (!is_ad)
128  {
129  // Derivative of properties wrt variables (calculated in fluid state class)
130  for (unsigned int ph = 0; ph < _num_phases; ++ph)
131  {
132  // If porepressure is a PorousFlow variable (it usually is), add derivatives wrt
133  // porepressure
134  if (_dictator.isPorousFlowVariable(_gas_porepressure_varnum))
135  {
136  (*_dporepressure_dvar)[_qp][ph][_pvar] = _fsp[ph].pressure.derivatives()[_pidx];
137  (*_dsaturation_dvar)[_qp][ph][_pvar] = _fsp[ph].saturation.derivatives()[_pidx];
138  (*_dfluid_density_dvar)[_qp][ph][_pvar] = _fsp[ph].density.derivatives()[_pidx];
139  (*_dfluid_viscosity_dvar)[_qp][ph][_pvar] = _fsp[ph].viscosity.derivatives()[_pidx];
140  (*_dfluid_enthalpy_dvar)[_qp][ph][_pvar] = _fsp[ph].enthalpy.derivatives()[_pidx];
141  (*_dfluid_internal_energy_dvar)[_qp][ph][_pvar] =
142  _fsp[ph].internal_energy.derivatives()[_pidx];
143 
144  for (unsigned int comp = 0; comp < _num_components; ++comp)
145  (*_dmass_frac_dvar)[_qp][ph][comp][_pvar] =
146  _fsp[ph].mass_fraction[comp].derivatives()[_pidx];
147  }
148 
149  // If Z is a PorousFlow variable (it usually is), add derivatives wrt Z
150  if (_dictator.isPorousFlowVariable(_Z_varnum[0]))
151  {
152  (*_dporepressure_dvar)[_qp][ph][_Zvar[0]] = _fsp[ph].pressure.derivatives()[_Zidx];
153  (*_dsaturation_dvar)[_qp][ph][_Zvar[0]] = _fsp[ph].saturation.derivatives()[_Zidx];
154  (*_dfluid_density_dvar)[_qp][ph][_Zvar[0]] = _fsp[ph].density.derivatives()[_Zidx];
155  (*_dfluid_viscosity_dvar)[_qp][ph][_Zvar[0]] = _fsp[ph].viscosity.derivatives()[_Zidx];
156  (*_dfluid_enthalpy_dvar)[_qp][ph][_Zvar[0]] = _fsp[ph].enthalpy.derivatives()[_Zidx];
157  (*_dfluid_internal_energy_dvar)[_qp][ph][_Zvar[0]] =
158  _fsp[ph].internal_energy.derivatives()[_Zidx];
159 
160  for (unsigned int comp = 0; comp < _num_components; ++comp)
161  (*_dmass_frac_dvar)[_qp][ph][comp][_Zvar[0]] =
162  _fsp[ph].mass_fraction[comp].derivatives()[_Zidx];
163  }
164 
165  // If temperature is a PorousFlow variable (nonisothermal case), add derivatives wrt
166  // temperature
167  if (_dictator.isPorousFlowVariable(_temperature_varnum))
168  {
169  (*_dporepressure_dvar)[_qp][ph][_Tvar] = _fsp[ph].pressure.derivatives()[_Tidx];
170  (*_dsaturation_dvar)[_qp][ph][_Tvar] = _fsp[ph].saturation.derivatives()[_Tidx];
171  (*_dfluid_density_dvar)[_qp][ph][_Tvar] = _fsp[ph].density.derivatives()[_Tidx];
172  (*_dfluid_viscosity_dvar)[_qp][ph][_Tvar] = _fsp[ph].viscosity.derivatives()[_Tidx];
173  (*_dfluid_enthalpy_dvar)[_qp][ph][_Tvar] = _fsp[ph].enthalpy.derivatives()[_Tidx];
174  (*_dfluid_internal_energy_dvar)[_qp][ph][_Tvar] =
175  _fsp[ph].internal_energy.derivatives()[_Tidx];
176 
177  for (unsigned int comp = 0; comp < _num_components; ++comp)
178  (*_dmass_frac_dvar)[_qp][ph][comp][_Tvar] =
179  _fsp[ph].mass_fraction[comp].derivatives()[_Tidx];
180  }
181 
182  // If Xnacl is a PorousFlow variable, add derivatives wrt Xnacl
183  if (_dictator.isPorousFlowVariable(_Xnacl_varnum))
184  {
185  (*_dporepressure_dvar)[_qp][ph][_Xvar] = _fsp[ph].pressure.derivatives()[_Xidx];
186  (*_dsaturation_dvar)[_qp][ph][_Xvar] = _fsp[ph].saturation.derivatives()[_Xidx];
187  (*_dfluid_density_dvar)[_qp][ph][_Xvar] += _fsp[ph].density.derivatives()[_Xidx];
188  (*_dfluid_viscosity_dvar)[_qp][ph][_Xvar] += _fsp[ph].viscosity.derivatives()[_Xidx];
189  (*_dfluid_enthalpy_dvar)[_qp][ph][_Xvar] = _fsp[ph].enthalpy.derivatives()[_Xidx];
190  (*_dfluid_internal_energy_dvar)[_qp][ph][_Xvar] =
191  _fsp[ph].internal_energy.derivatives()[_Xidx];
192 
193  for (unsigned int comp = 0; comp < _num_components; ++comp)
194  (*_dmass_frac_dvar)[_qp][ph][comp][_Xvar] =
195  _fsp[ph].mass_fraction[comp].derivatives()[_Xidx];
196  }
197  }
198  }
199 
200  // If the material properties are being evaluated at the qps, calculate the gradients as well
201  // Note: only nodal properties are evaluated in initQpStatefulProperties(), so no need to check
202  // _is_initqp flag for qp properties
203  if (!_nodal_material)
204  if constexpr (!is_ad)
205  {
206  // Derivatives of capillary pressure
207  const Real dpc = _pc.dCapillaryPressure(_fsp[_aqueous_phase_number].saturation.value(), _qp);
208  const Real d2pc =
209  _pc.d2CapillaryPressure(_fsp[_aqueous_phase_number].saturation.value(), _qp);
210 
211  // Gradients of saturation and porepressure in all phases
212  (*_grads_qp)[_qp][_gas_phase_number] =
213  (*_dsaturation_dvar)[_qp][_gas_phase_number][_pvar] * _gas_gradp_qp[_qp] +
214  (*_dsaturation_dvar)[_qp][_gas_phase_number][_Zvar[0]] * (*_gradZ_qp[0])[_qp] +
215  (*_dsaturation_dvar)[_qp][_gas_phase_number][_Tvar] * (*_gradT_qp)[_qp];
216  (*_grads_qp)[_qp][_aqueous_phase_number] = -(*_grads_qp)[_qp][_gas_phase_number];
217 
218  (*_gradp_qp)[_qp][_gas_phase_number] = _gas_gradp_qp[_qp];
219  (*_gradp_qp)[_qp][_aqueous_phase_number] =
220  _gas_gradp_qp[_qp] - dpc * (*_grads_qp)[_qp][_aqueous_phase_number];
221 
222  // Gradients of mass fractions for each component in each phase
223  (*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_aqueous_fluid_component] =
224  _fsp[_aqueous_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_pidx] *
225  _gas_gradp_qp[_qp] +
226  _fsp[_aqueous_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Zidx] *
227  (*_gradZ_qp[0])[_qp] +
228  _fsp[_aqueous_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Tidx] *
229  (*_gradT_qp)[_qp];
230  (*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_gas_fluid_component] =
231  -(*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_aqueous_fluid_component];
232 
233  (*_grad_mass_frac_qp)[_qp][_gas_phase_number][_aqueous_fluid_component] =
234  _fsp[_gas_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_pidx] *
235  _gas_gradp_qp[_qp] +
236  _fsp[_gas_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Zidx] *
237  (*_gradZ_qp[0])[_qp] +
238  _fsp[_gas_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Tidx] *
239  (*_gradT_qp)[_qp];
240  (*_grad_mass_frac_qp)[_qp][_gas_phase_number][_gas_fluid_component] =
241  -(*_grad_mass_frac_qp)[_qp][_gas_phase_number][_aqueous_fluid_component];
242 
243  // Derivatives of gradients wrt variables
244  if (_dictator.isPorousFlowVariable(_gas_porepressure_varnum))
245  {
246  for (unsigned int ph = 0; ph < _num_phases; ++ph)
247  (*_dgradp_qp_dgradv)[_qp][ph][_pvar] = 1.0;
248 
249  (*_dgradp_qp_dgradv)[_qp][_aqueous_phase_number][_pvar] +=
250  -dpc * (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_pvar];
251 
252  (*_dgradp_qp_dv)[_qp][_aqueous_phase_number][_pvar] =
253  -d2pc * (*_grads_qp)[_qp][_aqueous_phase_number] *
254  (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_pvar];
255  }
256 
257  if (_dictator.isPorousFlowVariable(_Z_varnum[0]))
258  {
259  (*_dgradp_qp_dgradv)[_qp][_aqueous_phase_number][_Zvar[0]] =
260  -dpc * (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Zvar[0]];
261 
262  (*_dgradp_qp_dv)[_qp][_aqueous_phase_number][_Zvar[0]] =
263  -d2pc * (*_grads_qp)[_qp][_aqueous_phase_number] *
264  (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Zvar[0]];
265  }
266 
267  if (_dictator.isPorousFlowVariable(_temperature_varnum))
268  {
269  (*_dgradp_qp_dgradv)[_qp][_aqueous_phase_number][_Tvar] =
270  -dpc * (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Tvar];
271 
272  (*_dgradp_qp_dv)[_qp][_aqueous_phase_number][_Tvar] =
273  -d2pc * (*_grads_qp)[_qp][_aqueous_phase_number] *
274  (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Tvar];
275  }
276 
277  // If Xnacl is a PorousFlow variable, add gradients and derivatives wrt Xnacl
278  if (_dictator.isPorousFlowVariable(_Xnacl_varnum))
279  {
280  (*_dgradp_qp_dgradv)[_qp][_aqueous_phase_number][_Xvar] =
281  -dpc * (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Xvar];
282 
283  (*_grads_qp)[_qp][_aqueous_phase_number] +=
284  (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Xvar] * _grad_Xnacl_qp[_qp];
285 
286  (*_grads_qp)[_qp][_gas_phase_number] -=
287  (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Xvar] * _grad_Xnacl_qp[_qp];
288 
289  (*_gradp_qp)[_qp][_aqueous_phase_number] -=
290  dpc * (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Xvar] * _grad_Xnacl_qp[_qp];
291 
292  (*_dgradp_qp_dv)[_qp][_aqueous_phase_number][_Xvar] =
293  -d2pc * (*_grads_qp)[_qp][_aqueous_phase_number] *
294  (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Xvar];
295 
296  (*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_salt_component] = _grad_Xnacl_qp[_qp];
297  (*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_aqueous_fluid_component] +=
298  _fsp[_aqueous_phase_number]
299  .mass_fraction[_aqueous_fluid_component]
300  .derivatives()[_Xidx] *
301  _grad_Xnacl_qp[_qp];
302  (*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_gas_fluid_component] -=
303  _fsp[_aqueous_phase_number]
304  .mass_fraction[_aqueous_fluid_component]
305  .derivatives()[_Xidx] *
306  _grad_Xnacl_qp[_qp];
307  (*_grad_mass_frac_qp)[_qp][_gas_phase_number][_aqueous_fluid_component] +=
308  _fsp[_gas_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Xidx] *
309  _grad_Xnacl_qp[_qp];
310  (*_grad_mass_frac_qp)[_qp][_gas_phase_number][_gas_fluid_component] -=
311  _fsp[_gas_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Xidx] *
312  _grad_Xnacl_qp[_qp];
313  }
314  }
315 }
316 
317 template class PorousFlowFluidStateTempl<false>;
318 template class PorousFlowFluidStateTempl<true>;
std::vector< unsigned int > _Zvar
PorousFlow variable number of Z.
Moose::GenericType< Real, is_ad > GenericReal
virtual void thermophysicalProperties() override
Calculates all required thermophysical properties and derivatives for each phase and fluid component...
registerMooseObject("PorousFlowApp", PorousFlowFluidState)
void mooseError(Args &&... args)
Compositional flash routines for miscible multiphase flow classes with multiple fluid components...
static InputParameters validParams()
void addRequiredParam(const std::string &name, const std::string &doc_string)
virtual void initQpStatefulProperties() override
std::vector< const GenericVariableGradient< is_ad > * > _gradZ_qp
Gradient(s) of total mass fraction(s) of the gas component(s) (only defined at the qps) ...
Fluid state class using a persistent set of primary variables for the mutliphase, multicomponent case...
const PorousFlowFluidStateMultiComponentBase & _fs
FluidState UserObject.
const std::string name
Definition: Setup.h:20
std::vector< unsigned int > _Z_varnum
Moose variable number of Z.
PorousFlowFluidStateTempl(const InputParameters &parameters)
std::vector< const GenericVariableValue< is_ad > * > _Z
Total mass fraction(s) of the gas component(s) summed over all phases.
virtual void computeQpProperties() override
void addCoupledVar(const std::string &name, const std::string &doc_string)
Fluid state base class using a persistent set of primary variables for multiphase, single and multicomponent cases.
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
const unsigned int _num_phases
Number of phases.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int numPhases() const
The maximum number of phases in this model.
void addClassDescription(const std::string &doc_string)
const unsigned int _num_Z_vars
Number of coupled total mass fractions. Should be _num_phases - 1.