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 // Check that the number of phases in the fluidstate class is also provided in the Dictator
77 if (_fs.numPhases() != _num_phases)
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
102template <bool is_ad>
103void
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
113template <bool is_ad>
114void
119
120template <bool is_ad>
121void
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
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.