https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PorousFlowDispersiveFlux.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
12#include "MooseVariable.h"
13
16
17template <bool is_ad>
20{
22 params.addParam<unsigned int>(
23 "fluid_component", 0, "The index corresponding to the fluid component for this kernel");
24 params.addRequiredParam<UserObjectName>(
25 "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names");
26 params.addRequiredParam<std::vector<Real>>(
27 "disp_long", "Vector of longitudinal dispersion coefficients for each phase");
28 params.addRequiredParam<std::vector<Real>>(
29 "disp_trans", "Vector of transverse dispersion coefficients for each phase");
30 params.addRequiredParam<RealVectorValue>("gravity",
31 "Gravitational acceleration vector downwards (m/s^2)");
33 "Dispersive and diffusive flux of the component given by fluid_component in all phases");
34 return params;
35}
36
37template <bool is_ad>
39 const InputParameters & parameters)
40 : GenericKernel<is_ad>(parameters),
41 _fluid_density_qp(this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
42 "PorousFlow_fluid_phase_density_qp")),
43 _dfluid_density_qp_dvar(
44 is_ad ? nullptr
45 : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
46 "dPorousFlow_fluid_phase_density_qp_dvar")),
47 _grad_mass_frac(
48 this->template getGenericMaterialProperty<std::vector<std::vector<RealGradient>>, is_ad>(
49 "PorousFlow_grad_mass_frac_qp")),
50 _dmass_frac_dvar(
51 is_ad ? nullptr
52 : &this->template getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
53 "dPorousFlow_mass_frac_qp_dvar")),
54 _porosity_qp(this->template getGenericMaterialProperty<Real, is_ad>("PorousFlow_porosity_qp")),
55 _dporosity_qp_dvar(is_ad ? nullptr
56 : &this->template getMaterialProperty<std::vector<Real>>(
57 "dPorousFlow_porosity_qp_dvar")),
58 _tortuosity(this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
59 "PorousFlow_tortuosity_qp")),
60 _dtortuosity_dvar(is_ad ? nullptr
61 : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
62 "dPorousFlow_tortuosity_qp_dvar")),
63 _diffusion_coeff(this->template getMaterialProperty<std::vector<std::vector<Real>>>(
64 "PorousFlow_diffusion_coeff_qp")),
65 _ddiffusion_coeff_dvar(
66 is_ad ? nullptr
67 : &this->template getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
68 "dPorousFlow_diffusion_coeff_qp_dvar")),
69 _dictator(this->template getUserObject<PorousFlowDictator>("PorousFlowDictator")),
70 _fluid_component(this->template getParam<unsigned int>("fluid_component")),
71 _num_phases(_dictator.numPhases()),
72 _identity_tensor(GenericRankTwoTensor<is_ad>::initIdentity),
73 _relative_permeability(this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
74 "PorousFlow_relative_permeability_qp")),
75 _drelative_permeability_dvar(
76 is_ad ? nullptr
77 : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
78 "dPorousFlow_relative_permeability_qp_dvar")),
79 _fluid_viscosity(this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
80 "PorousFlow_viscosity_qp")),
81 _dfluid_viscosity_dvar(
82 is_ad ? nullptr
83 : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
84 "dPorousFlow_viscosity_qp_dvar")),
85 _permeability(this->template getGenericMaterialProperty<RealTensorValue, is_ad>(
86 "PorousFlow_permeability_qp")),
87 _dpermeability_dvar(is_ad ? nullptr
88 : &this->template getMaterialProperty<std::vector<RealTensorValue>>(
89 "dPorousFlow_permeability_qp_dvar")),
90 _dpermeability_dgradvar(
91 is_ad ? nullptr
92 : &this->template getMaterialProperty<std::vector<std::vector<RealTensorValue>>>(
93 "dPorousFlow_permeability_qp_dgradvar")),
94 _grad_p(this->template getGenericMaterialProperty<std::vector<RealGradient>, is_ad>(
95 "PorousFlow_grad_porepressure_qp")),
96 _dgrad_p_dgrad_var(is_ad ? nullptr
97 : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
98 "dPorousFlow_grad_porepressure_qp_dgradvar")),
99 _dgrad_p_dvar(is_ad
100 ? nullptr
101 : &this->template getMaterialProperty<std::vector<std::vector<RealGradient>>>(
102 "dPorousFlow_grad_porepressure_qp_dvar")),
103 _gravity(this->template getParam<RealVectorValue>("gravity")),
104 _disp_long(this->template getParam<std::vector<Real>>("disp_long")),
105 _disp_trans(this->template getParam<std::vector<Real>>("disp_trans")),
106 _perm_derivs(_dictator.usePermDerivs())
107{
109 this->paramError(
110 "fluid_component",
111 "The Dictator proclaims that the maximum fluid component index in this simulation is ",
113 " whereas you have used ",
115 ". Remember that indexing starts at 0. The Dictator does not take such mistakes lightly.");
116
117 if (_disp_long.size() != _num_phases)
118 this->paramError(
119 "disp_long",
120 "The number of longitudinal dispersion coefficients is not equal to the number of phases");
121
122 if (_disp_trans.size() != _num_phases)
123 this->paramError("disp_trans",
124 "The number of transverse dispersion coefficients disp_trans is not equal to "
125 "the number of phases");
126}
127
128template <bool is_ad>
131{
134 GenericReal<is_ad> velocity_abs;
137 dispersion.zero();
138 GenericReal<is_ad> diffusion;
139
140 for (unsigned int ph = 0; ph < _num_phases; ++ph)
141 {
142 diffusion =
143 _porosity_qp[_qp] * _tortuosity[_qp][ph] * _diffusion_coeff[_qp][ph][_fluid_component];
144
145 velocity = _permeability[_qp] * (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity) *
146 _relative_permeability[_qp][ph] / _fluid_viscosity[_qp][ph];
147 velocity_abs = velocity.norm();
148
149 if (MetaPhysicL::raw_value(velocity_abs) > 0.0)
150 {
152 diffusion += GenericReal<is_ad>(_disp_trans[ph]) * velocity_abs;
153 dispersion = GenericReal<is_ad>(_disp_long[ph] - _disp_trans[ph]) * v2 / velocity_abs;
154 }
155
156 flux += _fluid_density_qp[_qp][ph] * (diffusion * _identity_tensor + dispersion) *
157 _grad_mass_frac[_qp][ph][_fluid_component];
158 }
159 return _grad_test[_i][_qp] * flux;
160}
161
162template <bool is_ad>
163Real
165{
166 return computeQpJac(_var.number());
167}
168
169template <bool is_ad>
170Real
172{
173 return computeQpJac(jvar);
174}
175
176template <bool is_ad>
177Real
179{
180 if constexpr (!is_ad)
181 {
182 if (_dictator.notPorousFlowVariable(jvar))
183 return 0.0;
184
185 const unsigned int pvar = _dictator.porousFlowVariableNum(jvar);
186
187 RealVectorValue velocity;
188 Real velocity_abs;
189 RankTwoTensor v2;
190 RankTwoTensor dispersion;
191 dispersion.zero();
192 Real diffusion;
193 RealVectorValue dflux = 0.0;
194
195 for (unsigned int ph = 0; ph < _num_phases; ++ph)
196 {
197 diffusion =
198 _porosity_qp[_qp] * _tortuosity[_qp][ph] * _diffusion_coeff[_qp][ph][_fluid_component];
199
200 velocity = _permeability[_qp] * (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity) *
201 _relative_permeability[_qp][ph] / _fluid_viscosity[_qp][ph];
202 velocity_abs = MetaPhysicL::raw_value(velocity).norm();
203
204 if (velocity_abs > 0.0)
205 {
206 v2 = RankTwoTensor::selfOuterProduct(velocity);
207 diffusion += _disp_trans[ph] * velocity_abs;
208 dispersion = (_disp_long[ph] - _disp_trans[ph]) * v2 / velocity_abs;
209 }
210
211 RealVectorValue dvelocity =
212 _permeability[_qp] *
213 (_grad_phi[_j][_qp] * (*_dgrad_p_dgrad_var)[_qp][ph][pvar] -
214 _phi[_j][_qp] * (*_dfluid_density_qp_dvar)[_qp][ph][pvar] * _gravity);
215 dvelocity += _permeability[_qp] * ((*_dgrad_p_dvar)[_qp][ph][pvar] * _phi[_j][_qp]);
216
217 if (_perm_derivs)
218 {
219 dvelocity += (*_dpermeability_dvar)[_qp][pvar] * _phi[_j][_qp] *
220 (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity);
221
222 for (const auto i : make_range(Moose::dim))
223 dvelocity += (*_dpermeability_dgradvar)[_qp][i][pvar] * _grad_phi[_j][_qp](i) *
224 (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity);
225 }
226
227 dvelocity =
228 dvelocity * _relative_permeability[_qp][ph] / _fluid_viscosity[_qp][ph] +
229 (_permeability[_qp] * (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity)) *
230 ((*_drelative_permeability_dvar)[_qp][ph][pvar] / _fluid_viscosity[_qp][ph] -
231 _relative_permeability[_qp][ph] * (*_dfluid_viscosity_dvar)[_qp][ph][pvar] /
232 std::pow(_fluid_viscosity[_qp][ph], 2)) *
233 _phi[_j][_qp];
234
235 Real dvelocity_abs = 0.0;
236 if (velocity_abs > 0.0)
237 dvelocity_abs = velocity * dvelocity / velocity_abs;
238
239 Real ddiffusion = _phi[_j][_qp] * (*_dporosity_qp_dvar)[_qp][pvar] * _tortuosity[_qp][ph] *
240 _diffusion_coeff[_qp][ph][_fluid_component];
241 ddiffusion += _phi[_j][_qp] * _porosity_qp[_qp] * (*_dtortuosity_dvar)[_qp][ph][pvar] *
242 _diffusion_coeff[_qp][ph][_fluid_component];
243 ddiffusion += _phi[_j][_qp] * _porosity_qp[_qp] * _tortuosity[_qp][ph] *
244 (*_ddiffusion_coeff_dvar)[_qp][ph][_fluid_component][pvar];
245 ddiffusion += _disp_trans[ph] * dvelocity_abs;
246
247 RankTwoTensor ddispersion;
248 ddispersion.zero();
249 if (velocity_abs > 0.0)
250 {
251 RankTwoTensor dv2a, dv2b;
252 dv2a = RankTwoTensor::outerProduct(velocity, dvelocity);
253 dv2b = RankTwoTensor::outerProduct(dvelocity, velocity);
254 ddispersion = (_disp_long[ph] - _disp_trans[ph]) * (dv2a + dv2b) / velocity_abs;
255 ddispersion -=
256 (_disp_long[ph] - _disp_trans[ph]) * v2 * dvelocity_abs / velocity_abs / velocity_abs;
257 }
258
259 dflux += _phi[_j][_qp] * (*_dfluid_density_qp_dvar)[_qp][ph][pvar] *
260 (diffusion * _identity_tensor + dispersion) *
261 _grad_mass_frac[_qp][ph][_fluid_component];
262 dflux += _fluid_density_qp[_qp][ph] * (ddiffusion * _identity_tensor + ddispersion) *
263 _grad_mass_frac[_qp][ph][_fluid_component];
264
265 // NOTE: Here we assume that d(grad_mass_frac)/d(var) = d(mass_frac)/d(var) * grad_phi
266 // This is true for most PorousFlow scenarios, but not for chemical reactions
267 // where mass_frac is a nonlinear function of the primary MOOSE Variables
268 dflux += _fluid_density_qp[_qp][ph] * (diffusion * _identity_tensor + dispersion) *
269 (*_dmass_frac_dvar)[_qp][ph][_fluid_component][pvar] * _grad_phi[_j][_qp];
270 }
271
272 return _grad_test[_i][_qp] * dflux;
273 }
274 else
275 libmesh_ignore(jvar);
276 return 0.0;
277}
278
Moose::GenericType< Real, is_ad > GenericReal
Moose::GenericType< RealVectorValue, is_ad > GenericRealVectorValue
Moose::GenericType< RankTwoTensor, is_ad > GenericRankTwoTensor
registerMooseObject("PorousFlowApp", PorousFlowDispersiveFlux)
void ErrorVector unsigned int
static InputParameters validParams()
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void paramError(const std::string &param, Args... args) const
This holds maps between the nonlinear variables used in a PorousFlow simulation and the variable numb...
unsigned int numComponents() const
The number of fluid components.
Dispersive flux of component k in fluid phase alpha.
virtual Real computeQpJacobian() override
Real computeQpJac(unsigned int jvar) const
Derivative of the residual with respect to the PorousFlow variable with variable number jvar.
virtual GenericReal< is_ad > computeQpResidual() override
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
const PorousFlowDictator & _dictator
PorousFlowDictator UserObject.
const unsigned int _num_phases
The number of fluid phases.
PorousFlowDispersiveFluxTempl(const InputParameters &parameters)
const std::vector< Real > _disp_trans
Transverse dispersivity for each phase.
const unsigned int _fluid_component
Index of the fluid component that this kernel acts on.
const std::vector< Real > _disp_long
Longitudinal dispersivity for each phase.
static RankTwoTensorTempl< T > selfOuterProduct(const libMesh::TypeVector< T > &)
RankFourTensorTempl< T > outerProduct(const RankTwoTensorTempl< T > &b) const
auto raw_value(const Eigen::Map< T > &in)
static constexpr std::size_t dim