https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
11
14
15template <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
32template <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 // These are read with coupledGenericDofValue when at_nodes = true, so they must be
77 // nodal (Lagrange) variables. See #33370.
78 if (this->_nodal_material)
79 this->checkNodalVariables({"gas_porepressure", "z"});
80 // Check that the number of phases in the fluidstate class is also provided in the Dictator
81 if (_fs.numPhases() != _num_phases)
83 ": only ",
84 _fs.numPhases(),
85 " phases are allowed. Please check the number of phases entered in the dictator is "
86 "correct");
87
88 // Store all total mass fractions and associated variable numbers
89 _Z.resize(_num_Z_vars);
90 _gradZ_qp.resize(_num_Z_vars);
91 _Z_varnum.resize(_num_Z_vars);
92 _Zvar.resize(_num_Z_vars);
93
94 for (unsigned int i = 0; i < _num_Z_vars; ++i)
95 {
96 _Z[i] = (_nodal_material ? &this->template coupledGenericDofValue<is_ad>("z", i)
97 : &this->template coupledGenericValue<is_ad>("z", i));
98 _gradZ_qp[i] = &this->template coupledGenericGradient<is_ad>("z", i);
99 _Z_varnum[i] = coupled("z", i);
100 _Zvar[i] = (_dictator.isPorousFlowVariable(_Z_varnum[i])
101 ? _dictator.porousFlowVariableNum(_Z_varnum[i])
102 : 0);
103 }
104}
105
106template <bool is_ad>
107void
109{
110 // The FluidProperty objects use temperature in K
111 const GenericReal<is_ad> Tk = _temperature[_qp] + _T_c2k;
112
113 _fs.clearFluidStateProperties(_fsp);
114 _fs.thermophysicalProperties(_gas_porepressure[_qp], Tk, _Xnacl[_qp], (*_Z[0])[_qp], _qp, _fsp);
115}
116
117template <bool is_ad>
118void
123
124template <bool is_ad>
125void
127{
129
130 // If the material isn't AD, we need to compute the derivatives
131 if (!is_ad)
132 {
133 // Derivative of properties wrt variables (calculated in fluid state class)
134 for (unsigned int ph = 0; ph < _num_phases; ++ph)
135 {
136 // If porepressure is a PorousFlow variable (it usually is), add derivatives wrt
137 // porepressure
138 if (_dictator.isPorousFlowVariable(_gas_porepressure_varnum))
139 {
140 (*_dporepressure_dvar)[_qp][ph][_pvar] = _fsp[ph].pressure.derivatives()[_pidx];
141 (*_dsaturation_dvar)[_qp][ph][_pvar] = _fsp[ph].saturation.derivatives()[_pidx];
142 (*_dfluid_density_dvar)[_qp][ph][_pvar] = _fsp[ph].density.derivatives()[_pidx];
143 (*_dfluid_viscosity_dvar)[_qp][ph][_pvar] = _fsp[ph].viscosity.derivatives()[_pidx];
144 (*_dfluid_enthalpy_dvar)[_qp][ph][_pvar] = _fsp[ph].enthalpy.derivatives()[_pidx];
145 (*_dfluid_internal_energy_dvar)[_qp][ph][_pvar] =
146 _fsp[ph].internal_energy.derivatives()[_pidx];
147
148 for (unsigned int comp = 0; comp < _num_components; ++comp)
149 (*_dmass_frac_dvar)[_qp][ph][comp][_pvar] =
150 _fsp[ph].mass_fraction[comp].derivatives()[_pidx];
151 }
152
153 // If Z is a PorousFlow variable (it usually is), add derivatives wrt Z
154 if (_dictator.isPorousFlowVariable(_Z_varnum[0]))
155 {
156 (*_dporepressure_dvar)[_qp][ph][_Zvar[0]] = _fsp[ph].pressure.derivatives()[_Zidx];
157 (*_dsaturation_dvar)[_qp][ph][_Zvar[0]] = _fsp[ph].saturation.derivatives()[_Zidx];
158 (*_dfluid_density_dvar)[_qp][ph][_Zvar[0]] = _fsp[ph].density.derivatives()[_Zidx];
159 (*_dfluid_viscosity_dvar)[_qp][ph][_Zvar[0]] = _fsp[ph].viscosity.derivatives()[_Zidx];
160 (*_dfluid_enthalpy_dvar)[_qp][ph][_Zvar[0]] = _fsp[ph].enthalpy.derivatives()[_Zidx];
161 (*_dfluid_internal_energy_dvar)[_qp][ph][_Zvar[0]] =
162 _fsp[ph].internal_energy.derivatives()[_Zidx];
163
164 for (unsigned int comp = 0; comp < _num_components; ++comp)
165 (*_dmass_frac_dvar)[_qp][ph][comp][_Zvar[0]] =
166 _fsp[ph].mass_fraction[comp].derivatives()[_Zidx];
167 }
168
169 // If temperature is a PorousFlow variable (nonisothermal case), add derivatives wrt
170 // temperature
171 if (_dictator.isPorousFlowVariable(_temperature_varnum))
172 {
173 (*_dporepressure_dvar)[_qp][ph][_Tvar] = _fsp[ph].pressure.derivatives()[_Tidx];
174 (*_dsaturation_dvar)[_qp][ph][_Tvar] = _fsp[ph].saturation.derivatives()[_Tidx];
175 (*_dfluid_density_dvar)[_qp][ph][_Tvar] = _fsp[ph].density.derivatives()[_Tidx];
176 (*_dfluid_viscosity_dvar)[_qp][ph][_Tvar] = _fsp[ph].viscosity.derivatives()[_Tidx];
177 (*_dfluid_enthalpy_dvar)[_qp][ph][_Tvar] = _fsp[ph].enthalpy.derivatives()[_Tidx];
178 (*_dfluid_internal_energy_dvar)[_qp][ph][_Tvar] =
179 _fsp[ph].internal_energy.derivatives()[_Tidx];
180
181 for (unsigned int comp = 0; comp < _num_components; ++comp)
182 (*_dmass_frac_dvar)[_qp][ph][comp][_Tvar] =
183 _fsp[ph].mass_fraction[comp].derivatives()[_Tidx];
184 }
185
186 // If Xnacl is a PorousFlow variable, add derivatives wrt Xnacl
187 if (_dictator.isPorousFlowVariable(_Xnacl_varnum))
188 {
189 (*_dporepressure_dvar)[_qp][ph][_Xvar] = _fsp[ph].pressure.derivatives()[_Xidx];
190 (*_dsaturation_dvar)[_qp][ph][_Xvar] = _fsp[ph].saturation.derivatives()[_Xidx];
191 (*_dfluid_density_dvar)[_qp][ph][_Xvar] += _fsp[ph].density.derivatives()[_Xidx];
192 (*_dfluid_viscosity_dvar)[_qp][ph][_Xvar] += _fsp[ph].viscosity.derivatives()[_Xidx];
193 (*_dfluid_enthalpy_dvar)[_qp][ph][_Xvar] = _fsp[ph].enthalpy.derivatives()[_Xidx];
194 (*_dfluid_internal_energy_dvar)[_qp][ph][_Xvar] =
195 _fsp[ph].internal_energy.derivatives()[_Xidx];
196
197 for (unsigned int comp = 0; comp < _num_components; ++comp)
198 (*_dmass_frac_dvar)[_qp][ph][comp][_Xvar] =
199 _fsp[ph].mass_fraction[comp].derivatives()[_Xidx];
200 }
201 }
202 }
203
204 // If the material properties are being evaluated at the qps, calculate the gradients as well
205 // Note: only nodal properties are evaluated in initQpStatefulProperties(), so no need to check
206 // _is_initqp flag for qp properties
207 if (!_nodal_material)
208 if constexpr (!is_ad)
209 {
210 // Derivatives of capillary pressure
211 const Real dpc = _pc.dCapillaryPressure(_fsp[_aqueous_phase_number].saturation.value(), _qp);
212 const Real d2pc =
213 _pc.d2CapillaryPressure(_fsp[_aqueous_phase_number].saturation.value(), _qp);
214
215 // Gradients of saturation and porepressure in all phases
216 (*_grads_qp)[_qp][_gas_phase_number] =
217 (*_dsaturation_dvar)[_qp][_gas_phase_number][_pvar] * _gas_gradp_qp[_qp] +
218 (*_dsaturation_dvar)[_qp][_gas_phase_number][_Zvar[0]] * (*_gradZ_qp[0])[_qp] +
219 (*_dsaturation_dvar)[_qp][_gas_phase_number][_Tvar] * (*_gradT_qp)[_qp];
220 (*_grads_qp)[_qp][_aqueous_phase_number] = -(*_grads_qp)[_qp][_gas_phase_number];
221
222 (*_gradp_qp)[_qp][_gas_phase_number] = _gas_gradp_qp[_qp];
223 (*_gradp_qp)[_qp][_aqueous_phase_number] =
224 _gas_gradp_qp[_qp] - dpc * (*_grads_qp)[_qp][_aqueous_phase_number];
225
226 // Gradients of mass fractions for each component in each phase
227 (*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_aqueous_fluid_component] =
228 _fsp[_aqueous_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_pidx] *
229 _gas_gradp_qp[_qp] +
230 _fsp[_aqueous_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Zidx] *
231 (*_gradZ_qp[0])[_qp] +
232 _fsp[_aqueous_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Tidx] *
233 (*_gradT_qp)[_qp];
234 (*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_gas_fluid_component] =
235 -(*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_aqueous_fluid_component];
236
237 (*_grad_mass_frac_qp)[_qp][_gas_phase_number][_aqueous_fluid_component] =
238 _fsp[_gas_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_pidx] *
239 _gas_gradp_qp[_qp] +
240 _fsp[_gas_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Zidx] *
241 (*_gradZ_qp[0])[_qp] +
242 _fsp[_gas_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Tidx] *
243 (*_gradT_qp)[_qp];
244 (*_grad_mass_frac_qp)[_qp][_gas_phase_number][_gas_fluid_component] =
245 -(*_grad_mass_frac_qp)[_qp][_gas_phase_number][_aqueous_fluid_component];
246
247 // Derivatives of gradients wrt variables
248 if (_dictator.isPorousFlowVariable(_gas_porepressure_varnum))
249 {
250 for (unsigned int ph = 0; ph < _num_phases; ++ph)
251 (*_dgradp_qp_dgradv)[_qp][ph][_pvar] = 1.0;
252
253 (*_dgradp_qp_dgradv)[_qp][_aqueous_phase_number][_pvar] +=
254 -dpc * (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_pvar];
255
256 (*_dgradp_qp_dv)[_qp][_aqueous_phase_number][_pvar] =
257 -d2pc * (*_grads_qp)[_qp][_aqueous_phase_number] *
258 (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_pvar];
259 }
260
261 if (_dictator.isPorousFlowVariable(_Z_varnum[0]))
262 {
263 (*_dgradp_qp_dgradv)[_qp][_aqueous_phase_number][_Zvar[0]] =
264 -dpc * (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Zvar[0]];
265
266 (*_dgradp_qp_dv)[_qp][_aqueous_phase_number][_Zvar[0]] =
267 -d2pc * (*_grads_qp)[_qp][_aqueous_phase_number] *
268 (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Zvar[0]];
269 }
270
271 if (_dictator.isPorousFlowVariable(_temperature_varnum))
272 {
273 (*_dgradp_qp_dgradv)[_qp][_aqueous_phase_number][_Tvar] =
274 -dpc * (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Tvar];
275
276 (*_dgradp_qp_dv)[_qp][_aqueous_phase_number][_Tvar] =
277 -d2pc * (*_grads_qp)[_qp][_aqueous_phase_number] *
278 (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Tvar];
279 }
280
281 // If Xnacl is a PorousFlow variable, add gradients and derivatives wrt Xnacl
282 if (_dictator.isPorousFlowVariable(_Xnacl_varnum))
283 {
284 (*_dgradp_qp_dgradv)[_qp][_aqueous_phase_number][_Xvar] =
285 -dpc * (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Xvar];
286
287 (*_grads_qp)[_qp][_aqueous_phase_number] +=
288 (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Xvar] * _grad_Xnacl_qp[_qp];
289
290 (*_grads_qp)[_qp][_gas_phase_number] -=
291 (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Xvar] * _grad_Xnacl_qp[_qp];
292
293 (*_gradp_qp)[_qp][_aqueous_phase_number] -=
294 dpc * (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Xvar] * _grad_Xnacl_qp[_qp];
295
296 (*_dgradp_qp_dv)[_qp][_aqueous_phase_number][_Xvar] =
297 -d2pc * (*_grads_qp)[_qp][_aqueous_phase_number] *
298 (*_dsaturation_dvar)[_qp][_aqueous_phase_number][_Xvar];
299
300 (*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_salt_component] = _grad_Xnacl_qp[_qp];
301 (*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_aqueous_fluid_component] +=
302 _fsp[_aqueous_phase_number]
303 .mass_fraction[_aqueous_fluid_component]
304 .derivatives()[_Xidx] *
305 _grad_Xnacl_qp[_qp];
306 (*_grad_mass_frac_qp)[_qp][_aqueous_phase_number][_gas_fluid_component] -=
307 _fsp[_aqueous_phase_number]
308 .mass_fraction[_aqueous_fluid_component]
309 .derivatives()[_Xidx] *
310 _grad_Xnacl_qp[_qp];
311 (*_grad_mass_frac_qp)[_qp][_gas_phase_number][_aqueous_fluid_component] +=
312 _fsp[_gas_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Xidx] *
313 _grad_Xnacl_qp[_qp];
314 (*_grad_mass_frac_qp)[_qp][_gas_phase_number][_gas_fluid_component] -=
315 _fsp[_gas_phase_number].mass_fraction[_aqueous_fluid_component].derivatives()[_Xidx] *
316 _grad_Xnacl_qp[_qp];
317 }
318 }
319}
320
void mooseError(Args &&... args)
Moose::GenericType< Real, is_ad > GenericReal
registerMooseObject("PorousFlowApp", PorousFlowFluidState)
const std::string name
Definition Setup.h:21
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void addCoupledVar(const std::string &name, const std::string &doc_string)
Fluid state base class using a persistent set of primary variables for multiphase,...
unsigned int numPhases() const
The maximum number of phases in this model.
Compositional flash routines for miscible multiphase flow classes with multiple fluid components.
Fluid state class using a persistent set of primary variables for the mutliphase, multicomponent case...
PorousFlowFluidStateTempl(const InputParameters &parameters)
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)
virtual void computeQpProperties() override
std::vector< unsigned int > _Zvar
PorousFlow variable number of Z.
const PorousFlowFluidStateMultiComponentBase & _fs
FluidState UserObject.
virtual void initQpStatefulProperties() override
const unsigned int _num_Z_vars
Number of coupled total mass fractions. Should be _num_phases - 1.
std::vector< unsigned int > _Z_varnum
Moose variable number of Z.
static InputParameters validParams()
std::vector< const GenericVariableValue< is_ad > * > _Z
Total mass fraction(s) of the gas component(s) summed over all phases.
virtual void thermophysicalProperties() override
Calculates all required thermophysical properties and derivatives for each phase and fluid component.
const unsigned int _num_phases
Number of phases.