www.mooseframework.org
PorousFlowMassTimeDerivative.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
3 /* */
4 /* All contents are licensed under LGPL V2.1 */
5 /* See LICENSE for full restrictions */
6 /****************************************************************/
7 
9 
10 // MOOSE includes
11 #include "MooseVariable.h"
12 
13 #include "libmesh/quadrature.h"
14 
15 // C++ includes
16 #include <limits>
17 
18 template <>
19 InputParameters
21 {
22  InputParameters params = validParams<TimeKernel>();
23  params.addParam<bool>("strain_at_nearest_qp",
24  false,
25  "When calculating nodal porosity that depends on strain, use the strain at "
26  "the nearest quadpoint. This adds a small extra computational burden, and "
27  "is not necessary for simulations involving only linear lagrange elements. "
28  " If you set this to true, you will also want to set the same parameter to "
29  "true for related Kernels and Materials");
30  params.addParam<unsigned int>(
31  "fluid_component", 0, "The index corresponding to the component for this kernel");
32  params.addRequiredParam<UserObjectName>(
33  "PorousFlowDictator", "The UserObject that holds the list of Porous-Flow variable names.");
34  params.addClassDescription(
35  "Component mass derivative wrt time for component given by fluid_component");
36  return params;
37 }
38 
40  : TimeKernel(parameters),
41  _fluid_component(getParam<unsigned int>("fluid_component")),
42  _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
43  _var_is_porflow_var(_dictator.isPorousFlowVariable(_var.number())),
44  _num_phases(_dictator.numPhases()),
45  _strain_at_nearest_qp(getParam<bool>("strain_at_nearest_qp")),
46  _porosity(getMaterialProperty<Real>("PorousFlow_porosity_nodal")),
47  _porosity_old(getMaterialPropertyOld<Real>("PorousFlow_porosity_nodal")),
48  _dporosity_dvar(getMaterialProperty<std::vector<Real>>("dPorousFlow_porosity_nodal_dvar")),
49  _dporosity_dgradvar(
50  getMaterialProperty<std::vector<RealGradient>>("dPorousFlow_porosity_nodal_dgradvar")),
51  _nearest_qp(_strain_at_nearest_qp
52  ? &getMaterialProperty<unsigned int>("PorousFlow_nearestqp_nodal")
53  : nullptr),
54  _fluid_density(getMaterialProperty<std::vector<Real>>("PorousFlow_fluid_phase_density_nodal")),
55  _fluid_density_old(
56  getMaterialPropertyOld<std::vector<Real>>("PorousFlow_fluid_phase_density_nodal")),
57  _dfluid_density_dvar(getMaterialProperty<std::vector<std::vector<Real>>>(
58  "dPorousFlow_fluid_phase_density_nodal_dvar")),
59  _fluid_saturation_nodal(getMaterialProperty<std::vector<Real>>("PorousFlow_saturation_nodal")),
60  _fluid_saturation_nodal_old(
61  getMaterialPropertyOld<std::vector<Real>>("PorousFlow_saturation_nodal")),
62  _dfluid_saturation_nodal_dvar(
63  getMaterialProperty<std::vector<std::vector<Real>>>("dPorousFlow_saturation_nodal_dvar")),
64  _mass_frac(getMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_nodal")),
65  _mass_frac_old(
66  getMaterialPropertyOld<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_nodal")),
67  _dmass_frac_dvar(getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
68  "dPorousFlow_mass_frac_nodal_dvar"))
69 {
71  mooseError(
72  "The Dictator proclaims that the number of components in this simulation is ",
74  " whereas you have used the Kernel PorousFlowComponetMassTimeDerivative with component = ",
76  ". The Dictator does not take such mistakes lightly");
77 }
78 
79 Real
81 {
82  Real mass = 0.0;
83  Real mass_old = 0.0;
84  for (unsigned ph = 0; ph < _num_phases; ++ph)
85  {
86  mass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
88  mass_old += _fluid_density_old[_i][ph] * _fluid_saturation_nodal_old[_i][ph] *
90  }
91 
92  return _test[_i][_qp] * (_porosity[_i] * mass - _porosity_old[_i] * mass_old) / _dt;
93 }
94 
95 Real
97 {
100  return 0.0;
101  return computeQpJac(_dictator.porousFlowVariableNum(_var.number()));
102 }
103 
104 Real
106 {
109  return 0.0;
111 }
112 
113 Real
115 {
116  const unsigned nearest_qp = (_strain_at_nearest_qp ? (*_nearest_qp)[_i] : _i);
117 
118  // porosity is dependent on variables that are lumped to the nodes,
119  // but it can depend on the gradient
120  // of variables, which are NOT lumped to the nodes, hence:
121  Real dmass = 0.0;
122  for (unsigned ph = 0; ph < _num_phases; ++ph)
123  dmass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
124  _mass_frac[_i][ph][_fluid_component] * _dporosity_dgradvar[_i][pvar] *
125  _grad_phi[_j][nearest_qp];
126 
127  if (_i != _j)
128  return _test[_i][_qp] * dmass / _dt;
129 
131  for (unsigned ph = 0; ph < _num_phases; ++ph)
132  {
133  dmass += _dfluid_density_dvar[_i][ph][pvar] * _fluid_saturation_nodal[_i][ph] *
134  _mass_frac[_i][ph][_fluid_component] * _porosity[_i];
135  dmass += _fluid_density[_i][ph] * _dfluid_saturation_nodal_dvar[_i][ph][pvar] *
136  _mass_frac[_i][ph][_fluid_component] * _porosity[_i];
137  dmass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
138  _dmass_frac_dvar[_i][ph][_fluid_component][pvar] * _porosity[_i];
139  dmass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
140  _mass_frac[_i][ph][_fluid_component] * _dporosity_dvar[_i][pvar];
141  }
142  return _test[_i][_qp] * dmass / _dt;
143 }
const bool _strain_at_nearest_qp
whether the porosity uses the volumetric strain at the closest quadpoint
const MaterialProperty< Real > & _porosity_old
old value of porosity
const MaterialProperty< std::vector< Real > > & _fluid_density_old
old value of nodal fluid density
const MaterialProperty< Real > & _porosity
porosity at the nodes, but it can depend on grad(variables) which are actually evaluated at the qps ...
unsigned int numComponents() const
the number of fluid components
Real computeQpJac(unsigned int pvar)
Derivative of residual with respect to PorousFlow variable number pvar This is used by both computeQp...
const MaterialProperty< std::vector< Real > > & _fluid_density
nodal fluid density
const MaterialProperty< std::vector< Real > > & _fluid_saturation_nodal
nodal fluid saturation
const MaterialProperty< std::vector< RealGradient > > & _dporosity_dgradvar
d(porosity)/d(grad porous-flow variable) - remember these derivatives will be wrt grad(vars) at qps ...
const bool _var_is_porflow_var
whether the Variable for this Kernel is a porous-flow variable according to the Dictator ...
InputParameters validParams< PorousFlowMassTimeDerivative >()
PorousFlowMassTimeDerivative(const InputParameters &parameters)
const MaterialProperty< std::vector< Real > > & _fluid_saturation_nodal_old
old value of fluid saturation
const MaterialProperty< std::vector< std::vector< Real > > > & _mass_frac
nodal mass fraction
const PorousFlowDictator & _dictator
holds info on the PorousFlow variables
const MaterialProperty< std::vector< std::vector< Real > > > & _mass_frac_old
old value of nodal mass fraction
const MaterialProperty< std::vector< std::vector< Real > > > & _dfluid_saturation_nodal_dvar
d(nodal fluid saturation)/d(porous-flow variable)
const MaterialProperty< std::vector< std::vector< std::vector< Real > > > > & _dmass_frac_dvar
d(nodal mass fraction)/d(porous-flow variable)
const MaterialProperty< std::vector< std::vector< Real > > > & _dfluid_density_dvar
d(nodal fluid density)/d(porous-flow variable)
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
This holds maps between the nonlinear variables used in a PorousFlow simulation and the variable numb...
const unsigned int _num_phases
number of fluid phases
const unsigned int _fluid_component
the fluid component index
const MaterialProperty< std::vector< Real > > & _dporosity_dvar
d(porosity)/d(porous-flow variable) - these derivatives will be wrt variables at the nodes ...
bool notPorousFlowVariable(unsigned int moose_var_num) const
returns true if moose_var_num is not a porous flow variabe
unsigned int porousFlowVariableNum(unsigned int moose_var_num) const
the PorousFlow variable number