www.mooseframework.org
PorousFlowMassRadioactiveDecay.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 
19 
22 {
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<unsigned int>(
32  "fluid_component", 0, "The index corresponding to the fluid component for this kernel");
33  params.addRequiredParam<Real>("decay_rate",
34  "The decay rate (units 1/time) for the fluid component");
35  params.addRequiredParam<UserObjectName>(
36  "PorousFlowDictator", "The UserObject that holds the list of PorousFlow variable names.");
37  params.addClassDescription("Radioactive decay of a fluid component");
38  return params;
39 }
40 
42  : TimeKernel(parameters),
43  _decay_rate(getParam<Real>("decay_rate")),
44  _fluid_component(getParam<unsigned int>("fluid_component")),
45  _dictator(getUserObject<PorousFlowDictator>("PorousFlowDictator")),
46  _var_is_porflow_var(_dictator.isPorousFlowVariable(_var.number())),
47  _num_phases(_dictator.numPhases()),
48  _strain_at_nearest_qp(getParam<bool>("strain_at_nearest_qp")),
49  _porosity(getMaterialProperty<Real>("PorousFlow_porosity_nodal")),
50  _dporosity_dvar(getMaterialProperty<std::vector<Real>>("dPorousFlow_porosity_nodal_dvar")),
51  _dporosity_dgradvar(
52  getMaterialProperty<std::vector<RealGradient>>("dPorousFlow_porosity_nodal_dgradvar")),
53  _nearest_qp(_strain_at_nearest_qp
54  ? &getMaterialProperty<unsigned int>("PorousFlow_nearestqp_nodal")
55  : nullptr),
56  _fluid_density(getMaterialProperty<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  _dfluid_saturation_nodal_dvar(
61  getMaterialProperty<std::vector<std::vector<Real>>>("dPorousFlow_saturation_nodal_dvar")),
62  _mass_frac(getMaterialProperty<std::vector<std::vector<Real>>>("PorousFlow_mass_frac_nodal")),
63  _dmass_frac_dvar(getMaterialProperty<std::vector<std::vector<std::vector<Real>>>>(
64  "dPorousFlow_mass_frac_nodal_dvar"))
65 {
67  paramError(
68  "fluid_component",
69  "The Dictator proclaims that the maximum fluid component index in this simulation is ",
71  " whereas you have used ",
73  ". Remember that indexing starts at 0. The Dictator does not take such mistakes lightly.");
74 }
75 
76 Real
78 {
79  Real mass = 0.0;
80  for (unsigned ph = 0; ph < _num_phases; ++ph)
81  mass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
83 
84  return _test[_i][_qp] * _decay_rate * _porosity[_i] * mass;
85 }
86 
87 Real
89 {
90  // If the variable is not a PorousFlow variable (very unusual), the diag Jacobian terms are 0
92  return 0.0;
94 }
95 
96 Real
98 {
99  // If the variable is not a PorousFlow variable, the OffDiag Jacobian terms are 0
101  return 0.0;
103 }
104 
105 Real
107 {
108  const unsigned nearest_qp = (_strain_at_nearest_qp ? (*_nearest_qp)[_i] : _i);
109 
110  // porosity is dependent on variables that are lumped to the nodes,
111  // but it can depend on the gradient
112  // of variables, which are NOT lumped to the nodes, hence:
113  Real dmass = 0.0;
114  for (unsigned ph = 0; ph < _num_phases; ++ph)
115  dmass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
117  _grad_phi[_j][nearest_qp];
118 
119  if (_i != _j)
120  return _test[_i][_qp] * _decay_rate * dmass;
121 
122  // As the fluid mass is lumped to the nodes, only non-zero terms are for _i==_j
123  for (unsigned ph = 0; ph < _num_phases; ++ph)
124  {
125  dmass += _dfluid_density_dvar[_i][ph][pvar] * _fluid_saturation_nodal[_i][ph] *
127  dmass += _fluid_density[_i][ph] * _dfluid_saturation_nodal_dvar[_i][ph][pvar] *
129  dmass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
131  dmass += _fluid_density[_i][ph] * _fluid_saturation_nodal[_i][ph] *
133  }
134  return _test[_i][_qp] * _decay_rate * dmass;
135 }
const MaterialProperty< std::vector< std::vector< std::vector< Real > > > > & _dmass_frac_dvar
d(nodal mass fraction)/d(PorousFlow variable)
bool notPorousFlowVariable(unsigned int moose_var_num) const
Returns true if moose_var_num is not a porous flow variabe.
const MaterialProperty< std::vector< Real > > & _dporosity_dvar
d(porosity)/d(PorousFlow variable) - these derivatives will be wrt variables at the nodes ...
MooseVariable & _var
virtual Real computeQpOffDiagJacobian(unsigned int jvar) override
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const unsigned int _fluid_component
The fluid component index.
unsigned int number() const
const unsigned int _num_phases
Number of fluid phases.
const VariablePhiGradient & _grad_phi
registerMooseObject("PorousFlowApp", PorousFlowMassRadioactiveDecay)
const MaterialProperty< std::vector< std::vector< Real > > > & _mass_frac
Nodal mass fraction.
unsigned int numComponents() const
The number of fluid components.
const bool _strain_at_nearest_qp
Whether the porosity uses the volumetric strain at the closest quadpoint.
void addRequiredParam(const std::string &name, const std::string &doc_string)
const MaterialProperty< std::vector< RealGradient > > & _dporosity_dgradvar
d(porosity)/d(grad PorousFlow variable) - remember these derivatives will be wrt grad(vars) at qps ...
const MaterialProperty< std::vector< std::vector< Real > > > & _dfluid_density_dvar
d(nodal fluid density)/d(PorousFlow variable)
const VariableTestValue & _test
const MaterialProperty< std::vector< std::vector< Real > > > & _dfluid_saturation_nodal_dvar
d(nodal fluid saturation)/d(PorousFlow variable)
const PorousFlowDictator & _dictator
PorousFlowDictator UserObject.
unsigned int _i
void paramError(const std::string &param, Args... args) const
const MaterialProperty< std::vector< Real > > & _fluid_density
Nodal fluid density.
unsigned int _j
PorousFlowMassRadioactiveDecay(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...
const MaterialProperty< std::vector< Real > > & _fluid_saturation_nodal
Nodal fluid saturation.
void addClassDescription(const std::string &doc_string)
Kernel = _decay_rate * masscomponent where mass_component = porosity*sum_phases(density_phase*saturat...
unsigned int porousFlowVariableNum(unsigned int moose_var_num) const
The PorousFlow variable number.
Real computeQpJac(unsigned int pvar)
Derivative of residual with respect to PorousFlow variable number pvar This is used by both computeQp...
static InputParameters validParams()
const bool _var_is_porflow_var
Whether the Variable for this Kernel is a PorousFlow variable according to the Dictator.
void ErrorVector unsigned int
const MaterialProperty< Real > & _porosity
Porosity at the nodes, but it can depend on grad(variables) which are actually evaluated at the qps...
unsigned int _qp