https://mooseframework.inl.gov
PorousFlowEnergyTimeDerivative.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 
17 template <bool is_ad>
20 {
22  params.set<MultiMooseEnum>("vector_tags") = "time";
23  params.set<MultiMooseEnum>("matrix_tags") = "system time";
24  params.addParam<bool>("strain_at_nearest_qp",
25  false,
26  "When calculating nodal porosity that depends on strain, use the strain at "
27  "the nearest quadpoint. This adds a small extra computational burden, and "
28  "is not necessary for simulations involving only linear lagrange elements. "
29  " If you set this to true, you will also want to set the same parameter to "
30  "true for related Kernels and Materials");
31  params.addParam<std::string>(
32  "base_name",
33  "For mechanically-coupled systems, this Kernel will depend on the volumetric strain. "
34  "base_name should almost always be the same base_name as given to the TensorMechanics object "
35  "that computes strain. Supplying a base_name to this Kernel but not defining an associated "
36  "TensorMechanics strain calculator means that this Kernel will not depend on volumetric "
37  "strain. That could be useful when models contain solid mechanics that is not coupled to "
38  "porous flow, for example");
39  params.addRequiredParam<UserObjectName>(
40  "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names.");
41  params.set<bool>("use_displaced_mesh") = false;
42  params.suppressParameter<bool>("use_displaced_mesh");
43  params.addClassDescription("Derivative of heat-energy-density wrt time");
44  return params;
45 }
46 
47 template <bool is_ad>
49  const InputParameters & parameters)
50  : PorousFlowLumpedKernelBaseTempl<is_ad>(parameters),
51  _dictator(this->template getUserObject<PorousFlowDictator>("PorousFlowDictator")),
52  _var_is_porflow_var(_dictator.isPorousFlowVariable(_var.number())),
53  _num_phases(_dictator.numPhases()),
54  _fluid_present(_num_phases > 0),
55  _strain_at_nearest_qp(this->template getParam<bool>("strain_at_nearest_qp")),
56  _base_name(this->isParamValid("base_name")
57  ? this->template getParam<std::string>("base_name") + "_"
58  : ""),
59  _has_total_strain(
60  this->template hasMaterialProperty<RankTwoTensor>(_base_name + "total_strain")),
61  _total_strain_old(_has_total_strain ? &this->template getMaterialPropertyOld<RankTwoTensor>(
62  _base_name + "total_strain")
63  : nullptr),
64  _porosity(this->template getGenericMaterialProperty<Real, is_ad>("PorousFlow_porosity_nodal")),
65  _porosity_old(this->template getMaterialPropertyOld<Real>("PorousFlow_porosity_nodal")),
66  _dporosity_dvar(is_ad ? nullptr
67  : &this->template getMaterialProperty<std::vector<Real>>(
68  "dPorousFlow_porosity_nodal_dvar")),
69  _dporosity_dgradvar(is_ad ? nullptr
70  : &this->template getMaterialProperty<std::vector<RealGradient>>(
71  "dPorousFlow_porosity_nodal_dgradvar")),
72  _nearest_qp(_strain_at_nearest_qp ? &this->template getMaterialProperty<unsigned int>(
73  "PorousFlow_nearestqp_nodal")
74  : nullptr),
75  _rock_energy_nodal(this->template getGenericMaterialProperty<Real, is_ad>(
76  "PorousFlow_matrix_internal_energy_nodal")),
77  _rock_energy_nodal_old(
78  this->template getMaterialPropertyOld<Real>("PorousFlow_matrix_internal_energy_nodal")),
79  _drock_energy_nodal_dvar(is_ad ? nullptr
80  : &this->template getMaterialProperty<std::vector<Real>>(
81  "dPorousFlow_matrix_internal_energy_nodal_dvar")),
82  _fluid_density(_fluid_present
83  ? &this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
84  "PorousFlow_fluid_phase_density_nodal")
85  : nullptr),
86  _fluid_density_old(_fluid_present ? &this->template getMaterialPropertyOld<std::vector<Real>>(
87  "PorousFlow_fluid_phase_density_nodal")
88  : nullptr),
89  _dfluid_density_dvar(_fluid_present && !is_ad
90  ? &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
91  "dPorousFlow_fluid_phase_density_nodal_dvar")
92  : nullptr),
93  _fluid_saturation_nodal(
94  _fluid_present ? &this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
95  "PorousFlow_saturation_nodal")
96  : nullptr),
97  _fluid_saturation_nodal_old(_fluid_present
98  ? &this->template getMaterialPropertyOld<std::vector<Real>>(
99  "PorousFlow_saturation_nodal")
100  : nullptr),
101  _dfluid_saturation_nodal_dvar(
102  _fluid_present && !is_ad
103  ? &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
104  "dPorousFlow_saturation_nodal_dvar")
105  : nullptr),
106  _energy_nodal(_fluid_present
107  ? &this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
108  "PorousFlow_fluid_phase_internal_energy_nodal")
109  : nullptr),
110  _energy_nodal_old(_fluid_present ? &this->template getMaterialPropertyOld<std::vector<Real>>(
111  "PorousFlow_fluid_phase_internal_energy_nodal")
112  : nullptr),
113  _denergy_nodal_dvar(_fluid_present && !is_ad
114  ? &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
115  "dPorousFlow_fluid_phase_internal_energy_nodal_dvar")
116  : nullptr)
117 {
118 }
119 
120 template <bool is_ad>
123 {
125  GenericReal<is_ad> energy = (1.0 - _porosity[_i]) * _rock_energy_nodal[_i];
126  Real energy_old = (1.0 - _porosity_old[_i]) * _rock_energy_nodal_old[_i];
127 
129  if (_fluid_present)
130  for (unsigned ph = 0; ph < _num_phases; ++ph)
131  {
132  energy += (*_fluid_density)[_i][ph] * (*_fluid_saturation_nodal)[_i][ph] *
133  (*_energy_nodal)[_i][ph] * _porosity[_i];
134  energy_old += (*_fluid_density_old)[_i][ph] * (*_fluid_saturation_nodal_old)[_i][ph] *
135  (*_energy_nodal_old)[_i][ph] * _porosity_old[_i];
136  }
137  const Real strain = (_has_total_strain ? (*_total_strain_old)[_qp].trace() : 0.0);
138 
139  return _test[_i][_qp] * (1.0 + strain) * (energy - energy_old) / _dt;
140 }
141 
142 template <bool is_ad>
143 Real
145 {
146  if constexpr (!is_ad)
147  {
148  // If the variable is not a PorousFlow variable (very unusual), the diag Jacobian terms are 0
149  if (!_var_is_porflow_var)
150  return 0.0;
151  return computeQpJac(_dictator.porousFlowVariableNum(_var.number()));
152  }
153  return 0.0;
154 }
155 
156 template <bool is_ad>
157 Real
159 {
160  if constexpr (!is_ad)
161  {
162  // If the variable is not a PorousFlow variable, the OffDiag Jacobian terms are 0
163  if (_dictator.notPorousFlowVariable(jvar))
164  return 0.0;
165  return computeQpJac(_dictator.porousFlowVariableNum(jvar));
166  }
167  else
168  libmesh_ignore(jvar);
169  return 0.0;
170 }
171 
172 template <bool is_ad>
173 Real
175 {
176  if constexpr (!is_ad)
177  {
178  const unsigned nearest_qp = (_strain_at_nearest_qp ? (*_nearest_qp)[_i] : _i);
179 
180  const Real strain = (_has_total_strain ? (*_total_strain_old)[_qp].trace() : 0.0);
181 
182  // porosity is dependent on variables that are lumped to the nodes,
183  // but it can depend on the gradient
184  // of variables, which are NOT lumped to the nodes, hence:
185  Real denergy = -(*_dporosity_dgradvar)[_i][pvar] * _grad_phi[_j][_i] * _rock_energy_nodal[_i];
186  for (unsigned ph = 0; ph < _num_phases; ++ph)
187  denergy += (*_fluid_density)[_i][ph] * (*_fluid_saturation_nodal)[_i][ph] *
188  (*_energy_nodal)[_i][ph] * (*_dporosity_dgradvar)[_i][pvar] *
189  _grad_phi[_j][nearest_qp];
190 
191  if (_i != _j)
192  return _test[_i][_qp] * (1.0 + strain) * denergy / _dt;
193 
194  // As the fluid energy is lumped to the nodes, only non-zero terms are for _i==_j
195  denergy += -(*_dporosity_dvar)[_i][pvar] * _rock_energy_nodal[_i];
196  denergy += (1.0 - _porosity[_i]) * (*_drock_energy_nodal_dvar)[_i][pvar];
197  for (unsigned ph = 0; ph < _num_phases; ++ph)
198  {
199  denergy += (*_dfluid_density_dvar)[_i][ph][pvar] * (*_fluid_saturation_nodal)[_i][ph] *
200  (*_energy_nodal)[_i][ph] * _porosity[_i];
201  denergy += (*_fluid_density)[_i][ph] * (*_dfluid_saturation_nodal_dvar)[_i][ph][pvar] *
202  (*_energy_nodal)[_i][ph] * _porosity[_i];
203  denergy += (*_fluid_density)[_i][ph] * (*_fluid_saturation_nodal)[_i][ph] *
204  (*_denergy_nodal_dvar)[_i][ph][pvar] * _porosity[_i];
205  denergy += (*_fluid_density)[_i][ph] * (*_fluid_saturation_nodal)[_i][ph] *
206  (*_energy_nodal)[_i][ph] * (*_dporosity_dvar)[_i][pvar];
207  }
208  return _test[_i][_qp] * (1.0 + strain) * denergy / _dt;
209  }
210  else
211  libmesh_ignore(pvar);
212  return 0.0;
213 }
214 
Moose::GenericType< Real, is_ad > GenericReal
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
static InputParameters validParams()
Real computeQpJac(unsigned int pvar) const
Derivative of residual with respect to PorousFlow variable number pvar (non-AD path only) ...
T & set(const std::string &name, bool quiet_mode=false)
PorousFlowEnergyTimeDerivativeTempl(const InputParameters &parameters)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void suppressParameter(const std::string &name)
virtual GenericReal< is_ad > computeQpResidual() override
void libmesh_ignore(const Args &...)
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...
Kernel = (heat_energy - heat_energy_old)/dt It is lumped to the nodes.
void addClassDescription(const std::string &doc_string)
Base class for PorousFlow kernels that use mass-lumped (nodal) material properties.
registerMooseObject("PorousFlowApp", PorousFlowEnergyTimeDerivative)
void ErrorVector unsigned int