https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
21template <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
45template <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
94template <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
106template <bool is_ad>
107Real
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
119template <bool is_ad>
120Real
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
134template <bool is_ad>
135Real
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
registerMooseObject("PorousFlowApp", PorousFlowMassRadioactiveDecay)
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)
T & set(const std::string &name, bool quiet_mode=false)
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.
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...
Real computeQpJac(unsigned int pvar)
Derivative of residual wrt PorousFlow variable pvar (non-AD path only)
virtual GenericReal< is_ad > computeQpResidual() override
const PorousFlowDictator & _dictator
PorousFlowDictator UserObject.
PorousFlowMassRadioactiveDecayTempl(const InputParameters &parameters)
const unsigned int _fluid_component
The fluid component index.
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override