https://mooseframework.inl.gov
PorousFlowMassRadioactiveDecay.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 
14 #include "libmesh/quadrature.h"
15 
16 #include <limits>
17 
20 
21 template <bool is_ad>
24 {
26  params.set<MultiMooseEnum>("vector_tags") = "time";
27  params.set<MultiMooseEnum>("matrix_tags") = "system time";
28  params.addParam<bool>("strain_at_nearest_qp",
29  false,
30  "When calculating nodal porosity that depends on strain, use the strain at "
31  "the nearest quadpoint. This adds a small extra computational burden, and "
32  "is not necessary for simulations involving only linear lagrange elements. "
33  " If you set this to true, you will also want to set the same parameter to "
34  "true for related Kernels and Materials");
35  params.addParam<unsigned int>(
36  "fluid_component", 0, "The index corresponding to the fluid component for this kernel");
37  params.addRequiredParam<Real>("decay_rate",
38  "The decay rate (units 1/time) for the fluid component");
39  params.addRequiredParam<UserObjectName>(
40  "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names.");
41  params.addClassDescription("Radioactive decay of a fluid component");
42  return params;
43 }
44 
45 template <bool is_ad>
47  const InputParameters & parameters)
48  : PorousFlowLumpedKernelBaseTempl<is_ad>(parameters),
49  _decay_rate(this->template getParam<Real>("decay_rate")),
50  _fluid_component(this->template getParam<unsigned int>("fluid_component")),
51  _dictator(this->template getUserObject<PorousFlowDictator>("PorousFlowDictator")),
52  _var_is_porflow_var(_dictator.isPorousFlowVariable(_var.number())),
53  _num_phases(_dictator.numPhases()),
54  _strain_at_nearest_qp(this->template getParam<bool>("strain_at_nearest_qp")),
55  _porosity(this->template getGenericMaterialProperty<Real, is_ad>("PorousFlow_porosity_nodal")),
56  _dporosity_dvar(is_ad ? nullptr
57  : &this->template getMaterialProperty<std::vector<Real>>(
58  "dPorousFlow_porosity_nodal_dvar")),
59  _dporosity_dgradvar(is_ad ? nullptr
60  : &this->template getMaterialProperty<std::vector<RealGradient>>(
61  "dPorousFlow_porosity_nodal_dgradvar")),
62  _nearest_qp(_strain_at_nearest_qp ? &this->template getMaterialProperty<unsigned int>(
63  "PorousFlow_nearestqp_nodal")
64  : nullptr),
65  _fluid_density(this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
66  "PorousFlow_fluid_phase_density_nodal")),
67  _dfluid_density_dvar(is_ad
68  ? nullptr
69  : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
70  "dPorousFlow_fluid_phase_density_nodal_dvar")),
71  _fluid_saturation_nodal(this->template getGenericMaterialProperty<std::vector<Real>, is_ad>(
72  "PorousFlow_saturation_nodal")),
73  _dfluid_saturation_nodal_dvar(
74  is_ad ? nullptr
75  : &this->template getMaterialProperty<std::vector<std::vector<Real>>>(
76  "dPorousFlow_saturation_nodal_dvar")),
77  _mass_frac(this->template getGenericMaterialProperty<std::vector<std::vector<Real>>, is_ad>(
78  "PorousFlow_mass_frac_nodal")),
79  _dmass_frac_dvar(
80  is_ad ? nullptr
81  : &this->template getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
82  "dPorousFlow_mass_frac_nodal_dvar"))
83 {
85  this->paramError(
86  "fluid_component",
87  "The Dictator proclaims that the maximum fluid component index in this simulation is ",
89  " whereas you have used ",
91  ". Remember that indexing starts at 0. The Dictator does not take such mistakes lightly.");
92 }
93 
94 template <bool is_ad>
97 {
98  GenericReal<is_ad> mass = 0.0;
99  for (unsigned ph = 0; ph < _num_phases; ++ph)
100  mass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
101  _mass_frac[_i][ph][_fluid_component];
102 
103  return _test[_i][_qp] * _decay_rate * _porosity[_i] * mass;
104 }
105 
106 template <bool is_ad>
107 Real
109 {
110  if constexpr (!is_ad)
111  {
112  if (!_var_is_porflow_var)
113  return 0.0;
114  return computeQpJac(_dictator.porousFlowVariableNum(_var.number()));
115  }
116  return 0.0;
117 }
118 
119 template <bool is_ad>
120 Real
122 {
123  if constexpr (!is_ad)
124  {
125  if (_dictator.notPorousFlowVariable(jvar))
126  return 0.0;
127  return computeQpJac(_dictator.porousFlowVariableNum(jvar));
128  }
129  else
130  libmesh_ignore(jvar);
131  return 0.0;
132 }
133 
134 template <bool is_ad>
135 Real
137 {
138  if constexpr (!is_ad)
139  {
140  const unsigned nearest_qp = (_strain_at_nearest_qp ? (*_nearest_qp)[_i] : _i);
141 
142  // porosity can depend on grad(variables) evaluated at qps, so the grad-term is nonzero even
143  // for off-node DOFs
144  Real dmass = 0.0;
145  for (unsigned ph = 0; ph < _num_phases; ++ph)
146  dmass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
147  _mass_frac[_i][ph][_fluid_component] * (*_dporosity_dgradvar)[_i][pvar] *
148  _grad_phi[_j][nearest_qp];
149 
150  if (_i != _j)
151  return _test[_i][_qp] * _decay_rate * dmass;
152 
153  // As the fluid mass is lumped to the nodes, only non-zero terms are for _i==_j
154  for (unsigned ph = 0; ph < _num_phases; ++ph)
155  {
156  dmass += (*_dfluid_density_dvar)[_i][ph][pvar] * _fluid_saturation_nodal[_i][ph] *
157  _mass_frac[_i][ph][_fluid_component] * _porosity[_i];
158  dmass += _fluid_density[_i][ph] * (*_dfluid_saturation_nodal_dvar)[_i][ph][pvar] *
159  _mass_frac[_i][ph][_fluid_component] * _porosity[_i];
160  dmass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
161  (*_dmass_frac_dvar)[_i][ph][_fluid_component][pvar] * _porosity[_i];
162  dmass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
163  _mass_frac[_i][ph][_fluid_component] * (*_dporosity_dvar)[_i][pvar];
164  }
165  return _test[_i][_qp] * _decay_rate * dmass;
166  }
167  else
168  libmesh_ignore(pvar);
169  return 0.0;
170 }
171 
Moose::GenericType< Real, is_ad > GenericReal
const unsigned int _fluid_component
The fluid component index.
void paramError(const std::string &param, Args... args) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
static InputParameters validParams()
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
T & set(const std::string &name, bool quiet_mode=false)
registerMooseObject("PorousFlowApp", PorousFlowMassRadioactiveDecay)
unsigned int numComponents() const
The number of fluid components.
virtual GenericReal< is_ad > computeQpResidual() override
void addRequiredParam(const std::string &name, const std::string &doc_string)
const PorousFlowDictator & _dictator
PorousFlowDictator UserObject.
void libmesh_ignore(const Args &...)
Real computeQpJac(unsigned int pvar)
Derivative of residual wrt PorousFlow variable pvar (non-AD path only)
PorousFlowMassRadioactiveDecayTempl(const InputParameters &parameters)
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...
void addClassDescription(const std::string &doc_string)
Base class for PorousFlow kernels that use mass-lumped (nodal) material properties.
Kernel = _decay_rate * masscomponent where mass_component = porosity*sum_phases(density_phase*saturat...
void ErrorVector unsigned int