https://mooseframework.inl.gov
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 
15 
18 {
20  params.addParam<unsigned int>(
21  "fluid_component", 0, "The index corresponding to the fluid component for this kernel");
22  params.addRequiredParam<UserObjectName>(
23  "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names");
24  params.addRequiredParam<std::vector<Real>>(
25  "disp_long", "Vector of longitudinal dispersion coefficients for each phase");
26  params.addRequiredParam<std::vector<Real>>(
27  "disp_trans", "Vector of transverse dispersion coefficients for each phase");
28  params.addRequiredParam<RealVectorValue>("gravity",
29  "Gravitational acceleration vector downwards (m/s^2)");
30  params.addClassDescription(
31  "Dispersive and diffusive flux of the component given by fluid_component in all phases");
32  return params;
33 }
34 
36  : Kernel(parameters),
37 
38  _fluid_density_qp(getMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_density_qp")),
39  _dfluid_density_qp_dvar(getMaterialProperty<std::vector<std::vector<Real>>>(
40  "dPorousFlow_fluid_phase_density_qp_dvar")),
41  _grad_mass_frac(getMaterialProperty<std::vector<std::vector<RealGradient>>>(
42  "PorousFlow_grad_mass_frac_qp")),
43  _dmass_frac_dvar(getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
44  "dPorousFlow_mass_frac_qp_dvar")),
45  _porosity_qp(getMaterialProperty<Real>("PorousFlow_porosity_qp")),
46  _dporosity_qp_dvar(getMaterialProperty<std::vector<Real>>("dPorousFlow_porosity_qp_dvar")),
47  _tortuosity(getMaterialProperty<std::vector<Real>>("PorousFlow_tortuosity_qp")),
48  _dtortuosity_dvar(
49  getMaterialProperty<std::vector<std::vector<Real>>>("dPorousFlow_tortuosity_qp_dvar")),
50  _diffusion_coeff(
51  getMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_diffusion_coeff_qp")),
52  _ddiffusion_coeff_dvar(getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
53  "dPorousFlow_diffusion_coeff_qp_dvar")),
54  _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
55  _fluid_component(getParam<unsigned int>("fluid_component")),
56  _num_phases(_dictator.numPhases()),
57  _identity_tensor(RankTwoTensor::initIdentity),
58  _relative_permeability(
59  getMaterialProperty<std::vector<Real>>("PorousFlow_relative_permeability_qp")),
60  _drelative_permeability_dvar(getMaterialProperty<std::vector<std::vector<Real>>>(
61  "dPorousFlow_relative_permeability_qp_dvar")),
62  _fluid_viscosity(getMaterialProperty<std::vector<Real>>("PorousFlow_viscosity_qp")),
63  _dfluid_viscosity_dvar(
64  getMaterialProperty<std::vector<std::vector<Real>>>("dPorousFlow_viscosity_qp_dvar")),
65  _permeability(getMaterialProperty<RealTensorValue>("PorousFlow_permeability_qp")),
66  _dpermeability_dvar(
67  getMaterialProperty<std::vector<RealTensorValue>>("dPorousFlow_permeability_qp_dvar")),
68  _dpermeability_dgradvar(getMaterialProperty<std::vector<std::vector<RealTensorValue>>>(
69  "dPorousFlow_permeability_qp_dgradvar")),
70  _grad_p(getMaterialProperty<std::vector<RealGradient>>("PorousFlow_grad_porepressure_qp")),
71  _dgrad_p_dgrad_var(getMaterialProperty<std::vector<std::vector<Real>>>(
72  "dPorousFlow_grad_porepressure_qp_dgradvar")),
73  _dgrad_p_dvar(getMaterialProperty<std::vector<std::vector<RealGradient>>>(
74  "dPorousFlow_grad_porepressure_qp_dvar")),
75  _gravity(getParam<RealVectorValue>("gravity")),
76  _disp_long(getParam<std::vector<Real>>("disp_long")),
77  _disp_trans(getParam<std::vector<Real>>("disp_trans")),
78  _perm_derivs(_dictator.usePermDerivs())
79 {
81  paramError(
82  "fluid_component",
83  "The Dictator proclaims that the maximum fluid component index in this simulation is ",
85  " whereas you have used ",
87  ". Remember that indexing starts at 0. The Dictator does not take such mistakes lightly.");
88 
89  // Check that sufficient values of the dispersion coefficients have been entered
90  if (_disp_long.size() != _num_phases)
91  paramError(
92  "disp_long",
93  "The number of longitudinal dispersion coefficients is not equal to the number of phases");
94 
95  if (_disp_trans.size() != _num_phases)
96  paramError("disp_trans",
97  "The number of transverse dispersion coefficients disp_trans is not equal to the "
98  "number of phases");
99 }
100 
101 Real
103 {
104  RealVectorValue flux = 0.0;
106  Real velocity_abs;
107  RankTwoTensor v2;
108  RankTwoTensor dispersion;
109  dispersion.zero();
110  Real diffusion;
111 
112  for (unsigned int ph = 0; ph < _num_phases; ++ph)
113  {
114  // Diffusive component
115  diffusion =
117 
118  // Calculate Darcy velocity
121  velocity_abs = std::sqrt(velocity * velocity);
122 
123  if (velocity_abs > 0.0)
124  {
126 
127  // Add longitudinal dispersion to diffusive component
128  diffusion += _disp_trans[ph] * velocity_abs;
129  dispersion = (_disp_long[ph] - _disp_trans[ph]) * v2 / velocity_abs;
130  }
131 
132  flux += _fluid_density_qp[_qp][ph] * (diffusion * _identity_tensor + dispersion) *
134  }
135  return _grad_test[_i][_qp] * flux;
136 }
137 
138 Real
140 {
141  return computeQpJac(_var.number());
142 }
143 
144 Real
146 {
147  return computeQpJac(jvar);
148 }
149 
150 Real
152 {
153  // If the variable is not a valid PorousFlow variable, set the Jacobian to 0
155  return 0.0;
156 
157  const unsigned int pvar = _dictator.porousFlowVariableNum(jvar);
158 
160  Real velocity_abs;
161  RankTwoTensor v2;
162  RankTwoTensor dispersion;
163  dispersion.zero();
164  Real diffusion;
165  RealVectorValue dflux = 0.0;
166 
167  for (unsigned int ph = 0; ph < _num_phases; ++ph)
168  {
169  // Diffusive component
170  diffusion =
172 
173  // Calculate Darcy velocity
176  velocity_abs = std::sqrt(velocity * velocity);
177 
178  if (velocity_abs > 0.0)
179  {
181 
182  // Add longitudinal dispersion to diffusive component
183  diffusion += _disp_trans[ph] * velocity_abs;
184  dispersion = (_disp_long[ph] - _disp_trans[ph]) * v2 / velocity_abs;
185  }
186 
187  // Derivative of Darcy velocity
188  RealVectorValue dvelocity =
189  _permeability[_qp] * (_grad_phi[_j][_qp] * _dgrad_p_dgrad_var[_qp][ph][pvar] -
190  _phi[_j][_qp] * _dfluid_density_qp_dvar[_qp][ph][pvar] * _gravity);
191  dvelocity += _permeability[_qp] * (_dgrad_p_dvar[_qp][ph][pvar] * _phi[_j][_qp]);
192 
193  if (_perm_derivs)
194  {
195  dvelocity += _dpermeability_dvar[_qp][pvar] * _phi[_j][_qp] *
196  (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity);
197 
198  for (const auto i : make_range(Moose::dim))
199  dvelocity += _dpermeability_dgradvar[_qp][i][pvar] * _grad_phi[_j][_qp](i) *
200  (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity);
201  }
202 
203  dvelocity = dvelocity * _relative_permeability[_qp][ph] / _fluid_viscosity[_qp][ph] +
204  (_permeability[_qp] * (_grad_p[_qp][ph] - _fluid_density_qp[_qp][ph] * _gravity)) *
207  std::pow(_fluid_viscosity[_qp][ph], 2)) *
208  _phi[_j][_qp];
209 
210  Real dvelocity_abs = 0.0;
211  if (velocity_abs > 0.0)
212  dvelocity_abs = velocity * dvelocity / velocity_abs;
213 
214  // Derivative of diffusion term (note: dispersivity is assumed constant)
215  Real ddiffusion = _phi[_j][_qp] * _dporosity_qp_dvar[_qp][pvar] * _tortuosity[_qp][ph] *
217  ddiffusion += _phi[_j][_qp] * _porosity_qp[_qp] * _dtortuosity_dvar[_qp][ph][pvar] *
219  ddiffusion += _phi[_j][_qp] * _porosity_qp[_qp] * _tortuosity[_qp][ph] *
221  ddiffusion += _disp_trans[ph] * dvelocity_abs;
222 
223  // Derivative of dispersion term (note: dispersivity is assumed constant)
224  RankTwoTensor ddispersion;
225  ddispersion.zero();
226  if (velocity_abs > 0.0)
227  {
228  RankTwoTensor dv2a, dv2b;
229  dv2a = RankTwoTensor::outerProduct(velocity, dvelocity);
230  dv2b = RankTwoTensor::outerProduct(dvelocity, velocity);
231  ddispersion = (_disp_long[ph] - _disp_trans[ph]) * (dv2a + dv2b) / velocity_abs;
232  ddispersion -=
233  (_disp_long[ph] - _disp_trans[ph]) * v2 * dvelocity_abs / velocity_abs / velocity_abs;
234  }
235 
236  dflux += _phi[_j][_qp] * _dfluid_density_qp_dvar[_qp][ph][pvar] *
237  (diffusion * _identity_tensor + dispersion) *
239  dflux += _fluid_density_qp[_qp][ph] * (ddiffusion * _identity_tensor + ddispersion) *
241 
242  // NOTE: Here we assume that d(grad_mass_frac)/d(var) = d(mass_frac)/d(var) * grad_phi
243  // This is true for most PorousFlow scenarios, but not for chemical reactions
244  // where mass_frac is a nonlinear function of the primary MOOSE Variables
245  dflux += _fluid_density_qp[_qp][ph] * (diffusion * _identity_tensor + dispersion) *
247  }
248 
249  return _grad_test[_i][_qp] * dflux;
250 }
RankFourTensorTempl< Real > outerProduct(const RankTwoTensorTempl< Real > &b) const
registerMooseObject("PorousFlowApp", PorousFlowDispersiveFlux)
const MaterialProperty< std::vector< std::vector< Real > > > & _dtortuosity_dvar
Derivative of tortuosity wrt PorousFlow variables.
const RankTwoTensor _identity_tensor
Identity tensor.
static InputParameters validParams()
bool notPorousFlowVariable(unsigned int moose_var_num) const
Returns true if moose_var_num is not a porous flow variabe.
MooseVariable & _var
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const MaterialProperty< std::vector< RealGradient > > & _grad_p
Gradient of the pore pressure in each phase.
unsigned int number() const
virtual Real computeQpJacobian() override
const VariablePhiGradient & _grad_phi
const MaterialProperty< std::vector< Real > > & _tortuosity
Tortuosity tau_0 * tau_{alpha} for fluid phase alpha.
const MaterialProperty< std::vector< RealTensorValue > > & _dpermeability_dvar
Derivative of permeability wrt PorousFlow variables.
const MaterialProperty< std::vector< std::vector< RealGradient > > > & _dgrad_p_dvar
Derivative of Grad porepressure in each phase wrt PorousFlow variables.
unsigned int numComponents() const
The number of fluid components.
const RealVectorValue _gravity
Gravitational acceleration.
const MaterialProperty< std::vector< Real > > & _fluid_density_qp
Fluid density for each phase (at the qp)
const MaterialProperty< std::vector< std::vector< Real > > > & _diffusion_coeff
Diffusion coefficients of component k in fluid phase alpha.
static constexpr std::size_t dim
const MaterialProperty< std::vector< std::vector< RealGradient > > > & _grad_mass_frac
Gradient of mass fraction of each component in each phase.
const MaterialProperty< std::vector< Real > > & _fluid_viscosity
Viscosity of each component in each phase.
const MaterialProperty< std::vector< std::vector< RealTensorValue > > > & _dpermeability_dgradvar
d(permeabiity)/d(grad(PorousFlow variable))
const MaterialProperty< std::vector< std::vector< Real > > > & _dfluid_viscosity_dvar
Derivative of viscosity wrt PorousFlow variables.
void addRequiredParam(const std::string &name, const std::string &doc_string)
const unsigned int _num_phases
The number of fluid phases.
virtual Real computeQpResidual() override
static RankTwoTensorTempl< Real > selfOuterProduct(const libMesh::TypeVector< Real > &)
const MaterialProperty< std::vector< Real > > & _dporosity_qp_dvar
Derivative of porosity wrt PorousFlow variables (at the qps)
TensorValue< Real > RealTensorValue
Real computeQpJac(unsigned int jvar) const
Derivative of the residual with respect to the PorousFLow Variable with variable number jvar...
const PorousFlowDictator & _dictator
PorousFlowDictator UserObject.
PorousFlowDispersiveFlux(const InputParameters &parameters)
unsigned int _i
void paramError(const std::string &param, Args... args) const
const MaterialProperty< RealTensorValue > & _permeability
Permeability of porous material.
const std::vector< Real > _disp_long
Longitudinal dispersivity for each phase.
unsigned int _j
const MaterialProperty< std::vector< std::vector< Real > > > & _dfluid_density_qp_dvar
Derivative of the fluid density for each phase wrt PorousFlow variables (at the qp) ...
const MaterialProperty< std::vector< Real > > & _relative_permeability
Relative permeability of each phase.
static InputParameters validParams()
Dispersive flux of component k in fluid phase alpha.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
This holds maps between the nonlinear variables used in a PorousFlow simulation and the variable numb...
const MaterialProperty< std::vector< std::vector< Real > > > & _drelative_permeability_dvar
Derivative of relative permeability wrt PorousFlow variables.
const VariableTestGradient & _grad_test
IntRange< T > make_range(T beg, T end)
void addClassDescription(const std::string &doc_string)
const bool _perm_derivs
Flag to check whether permeabiity derivatives are non-zero.
const MaterialProperty< std::vector< std::vector< std::vector< Real > > > > & _ddiffusion_coeff_dvar
Derivative of the diffusion coefficients wrt PorousFlow variables.
static const std::string velocity
Definition: NS.h:45
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
unsigned int porousFlowVariableNum(unsigned int moose_var_num) const
The PorousFlow variable number.
const unsigned int _fluid_component
Index of the fluid component that this kernel acts on.
const MaterialProperty< std::vector< std::vector< std::vector< Real > > > > & _dmass_frac_dvar
Derivative of mass fraction wrt PorousFlow variables.
const MaterialProperty< std::vector< std::vector< Real > > > & _dgrad_p_dgrad_var
Derivative of Grad porepressure in each phase wrt grad(PorousFlow variables)
const VariablePhiValue & _phi
MooseUnits pow(const MooseUnits &, int)
void ErrorVector unsigned int
const MaterialProperty< Real > & _porosity_qp
Porosity at the qps.
const std::vector< Real > _disp_trans
Transverse dispersivity for each phase.
unsigned int _qp