https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PorousFlowPorosityExponentialBase.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 <limits>
13
14template <bool is_ad>
17{
19 params.addParam<bool>("strain_at_nearest_qp",
20 false,
21 "When calculating nodal porosity that depends on strain, use the strain at "
22 "the nearest quadpoint. This adds a small extra computational burden, and "
23 "is not necessary for simulations involving only linear lagrange elements. "
24 " If you set this to true, you will also want to set the same parameter to "
25 "true for related Kernels and Materials");
26 params.addParam<bool>("ensure_positive",
27 true,
28 "Modify the usual exponential relationships that "
29 "governs porosity so that porosity is always "
30 "positive");
31 params.setDocString(
32 "porosity_min",
33 "Minimum allowed value of the porosity: if the computed porosity is less than this value, "
34 "porosity is set to this value instead. The default of zero means porosity is never "
35 "negative. The ensure_positive transform only acts for decay > 0, so chemistry-driven "
36 "(precipitation) porosity would otherwise become negative once pore space is filled by "
37 "mineral; a small positive value may be preferable in that case.");
38 params.addClassDescription("Base class Material for porosity that is computed via an exponential "
39 "relationship with coupled variables (strain, porepressure, "
40 "temperature, chemistry)");
41 return params;
42}
43
44template <bool is_ad>
46 const InputParameters & parameters)
47 : PorousFlowPorosityBaseTempl<is_ad>(parameters),
48 _strain_at_nearest_qp(this->template getParam<bool>("strain_at_nearest_qp")),
49 _ensure_positive(this->template getParam<bool>("ensure_positive"))
50{
51}
52
53template <bool is_ad>
54void
56{
57 // Unqualified calls so ADL finds the MetaPhysicL overloads for the AD (DualNumber) instantiation
58 using std::exp;
59 using std::log;
60
61 const GenericReal<is_ad> a = atNegInfinityQp();
62 const GenericReal<is_ad> b = atZeroQp();
63 mooseAssert(a > b, "PorousFlowPorosityExponentialBase a must be larger than b");
64 const GenericReal<is_ad> decay = decayQp();
65
66 if (decay <= 0.0 || !_ensure_positive)
67 _porosity[_qp] = a + (b - a) * exp(decay);
68 else
69 {
70 const GenericReal<is_ad> c = log(a / (a - b));
71 const GenericReal<is_ad> expx = exp(-decay / c);
72 _porosity[_qp] = a + (b - a) * exp(c * (1.0 - expx));
73 }
74
75 if (_porosity[_qp] < _porosity_min)
76 _porosity[_qp] = _porosity_min;
77}
78
79template <bool is_ad>
80void
82{
83 // Unqualified calls so ADL finds the MetaPhysicL overloads for the AD (DualNumber) instantiation
84 using std::exp;
85 using std::log;
86 using std::pow;
87
88 const GenericReal<is_ad> a = atNegInfinityQp();
89 const GenericReal<is_ad> b = atZeroQp();
90 const GenericReal<is_ad> decay = decayQp();
91 GenericReal<is_ad> exp_term = 1.0; // set appropriately below
92
93 if (decay <= 0.0 || !_ensure_positive)
94 {
95 exp_term = exp(decay);
96 _porosity[_qp] = a + (b - a) * exp_term;
97 }
98 else
99 {
100 const GenericReal<is_ad> c = log(a / (a - b));
101 // note that at decay = 0, we have expx = 1, so porosity = a + b - a = b
102 // and at decay = infinity, expx = 0, so porosity = a + (b - a) * a / (a - b) = 0
103 const GenericReal<is_ad> expx = exp(-decay / c);
104 exp_term = exp(c * (1.0 - expx));
105 _porosity[_qp] = a + (b - a) * exp_term;
106 }
107
108 if constexpr (!is_ad)
109 {
110 // The AD path carries the derivatives with respect to the PorousFlow variables inside the AD
111 // porosity value, so only the non-AD path builds these derivative material properties.
112 Real deriv = 0.0; // = d(porosity)/d(decay)
113 if (decay <= 0.0 || !_ensure_positive)
114 deriv = _porosity[_qp] - a;
115 else
116 {
117 const Real c = log(a / (a - b));
118 const Real expx = exp(-decay / c);
119 deriv = (_porosity[_qp] - a) * expx;
120 }
121
122 (*_dporosity_dvar)[_qp].resize(_num_var);
123 (*_dporosity_dgradvar)[_qp].resize(_num_var);
124 for (unsigned int v = 0; v < _num_var; ++v)
125 {
126 (*_dporosity_dvar)[_qp][v] = ddecayQp_dvar(v) * deriv;
127 (*_dporosity_dgradvar)[_qp][v] = ddecayQp_dgradvar(v) * deriv;
128
129 const Real da = datNegInfinityQp(v);
130 const Real db = datZeroQp(v);
131 (*_dporosity_dvar)[_qp][v] += da * (1 - exp_term) + db * exp_term;
132
133 if (!(decay <= 0.0 || !_ensure_positive))
134 {
135 const Real c = log(a / (a - b));
136 const Real expx = exp(-decay / c);
137 const Real dc = (a - b) * (da * b / a - db) / Utility::pow<2>(a);
138 (*_dporosity_dvar)[_qp][v] += (b - a) * exp_term * dc * (1 - expx - expx / c);
139 }
140 }
141 }
142
143 // Apply the porosity floor last, after the unfloored derivatives above have been
144 // formed (see PorousFlowPorosityBaseTempl::applyPorosityMin)
145 applyPorosityMin();
146}
147
const double v
const GeochemicalDatabaseReader db("database/moose_testdb.json", true, true, false)
Moose::GenericType< Real, is_ad > GenericReal
void setDocString(const std::string &name, const std::string &doc)
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)
Base class Material designed to provide the porosity.
static InputParameters validParams()
Base class Material designed to provide the porosity.
PorousFlowPorosityExponentialBaseTempl(const InputParameters &parameters)