Line data Source code
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 :
10 : #include "FunctionMaterialPropertyDescriptor.h"
11 : #include "DerivativeMaterialInterface.h"
12 : #include "Material.h"
13 : #include "Kernel.h"
14 : #include <algorithm>
15 :
16 : template <bool is_ad>
17 3456 : FunctionMaterialPropertyDescriptor<is_ad>::FunctionMaterialPropertyDescriptor(
18 : const std::string & expression, MooseObject * parent, bool required)
19 3456 : : _state(PropertyState::CURRENT),
20 3456 : _dependent_symbols(),
21 3456 : _derivative_symbols(),
22 3456 : _value(nullptr),
23 3456 : _old_older_value(nullptr),
24 3456 : _parent(parent),
25 6912 : _required(required)
26 : {
27 3456 : auto define = expression.find_last_of(":=");
28 :
29 : // expression contains a ':='
30 3456 : if (define != std::string::npos)
31 : {
32 : // section before ':=' is the name used in the function expression
33 2748 : _fparser_name = expression.substr(0, define - 1);
34 :
35 : // parse right hand side
36 2748 : parseDerivative(expression.substr(define + 1));
37 : }
38 : else
39 : {
40 : // parse entire expression and use natural material property base name
41 : // for D(x(t),t,t) this would simply be 'x'!
42 708 : parseDerivative(expression);
43 708 : _fparser_name = _base_name;
44 : }
45 :
46 3456 : updatePropertyName();
47 3456 : }
48 :
49 : template <bool is_ad>
50 9792 : FunctionMaterialPropertyDescriptor<is_ad>::FunctionMaterialPropertyDescriptor(
51 : const FunctionMaterialPropertyDescriptor & rhs)
52 9792 : : _state(rhs._state),
53 9792 : _fparser_name(rhs._fparser_name),
54 9792 : _base_name(rhs._base_name),
55 9792 : _dependent_symbols(rhs._dependent_symbols),
56 9792 : _derivative_symbols(rhs._derivative_symbols),
57 9792 : _value(nullptr),
58 9792 : _old_older_value(nullptr),
59 9792 : _parent(rhs._parent),
60 9792 : _property_name(rhs._property_name),
61 9792 : _required(false)
62 : {
63 9792 : }
64 :
65 : template <bool is_ad>
66 162 : FunctionMaterialPropertyDescriptor<is_ad>::FunctionMaterialPropertyDescriptor(
67 : const FunctionMaterialPropertyDescriptor & rhs, MooseObject * parent)
68 162 : : _state(rhs._state),
69 162 : _fparser_name(rhs._fparser_name),
70 162 : _base_name(rhs._base_name),
71 162 : _dependent_symbols(rhs._dependent_symbols),
72 162 : _derivative_symbols(rhs._derivative_symbols),
73 162 : _value(nullptr),
74 162 : _old_older_value(nullptr),
75 162 : _parent(parent),
76 162 : _property_name(rhs._property_name),
77 162 : _required(false)
78 : {
79 162 : }
80 :
81 : template <bool is_ad>
82 : std::vector<FunctionMaterialPropertyDescriptor<is_ad>>
83 0 : FunctionMaterialPropertyDescriptor<is_ad>::parseVector(
84 : const std::vector<std::string> & expression_list, MooseObject * parent)
85 : {
86 0 : std::vector<FunctionMaterialPropertyDescriptor> fmpds;
87 0 : for (auto & ex : expression_list)
88 0 : fmpds.push_back(FunctionMaterialPropertyDescriptor(ex, parent));
89 0 : return fmpds;
90 0 : }
91 :
92 : template <bool is_ad>
93 : void
94 1656 : FunctionMaterialPropertyDescriptor<is_ad>::addDerivative(const SymbolName & var)
95 : {
96 1656 : _derivative_symbols.push_back(var);
97 1656 : _value = nullptr;
98 1656 : updatePropertyName();
99 1656 : }
100 :
101 : template <bool is_ad>
102 : bool
103 2412 : FunctionMaterialPropertyDescriptor<is_ad>::dependsOn(const std::string & var) const
104 : {
105 2412 : return std::find(_dependent_symbols.begin(), _dependent_symbols.end(), var) !=
106 7020 : _dependent_symbols.end() ||
107 2196 : std::find(_derivative_symbols.begin(), _derivative_symbols.end(), var) !=
108 4608 : _derivative_symbols.end();
109 : }
110 :
111 : template <bool is_ad>
112 : std::vector<DerivativeMaterialPropertyNameInterface::SymbolName>
113 0 : FunctionMaterialPropertyDescriptor<is_ad>::getDependentSymbols()
114 : {
115 0 : std::set<SymbolName> all(_dependent_symbols.begin(), _dependent_symbols.end());
116 0 : all.insert(_derivative_symbols.begin(), _derivative_symbols.end());
117 :
118 0 : return std::vector<SymbolName>(all.begin(), all.end());
119 0 : }
120 :
121 : template <bool is_ad>
122 : void
123 3456 : FunctionMaterialPropertyDescriptor<is_ad>::parseDerivative(const std::string & expression)
124 : {
125 3456 : auto open = expression.find_first_of("[");
126 3456 : auto close = expression.find_last_of("]");
127 :
128 3456 : if (open == std::string::npos && close == std::string::npos)
129 : {
130 : // no derivative requested
131 2319 : parseDependentSymbols(expression);
132 :
133 2319 : return;
134 : }
135 1137 : if (open != std::string::npos && close != std::string::npos)
136 : {
137 1137 : if (expression.substr(0, open) == "Old")
138 : {
139 39 : _base_name = expression.substr(open + 1, close - open - 1);
140 39 : _dependent_symbols.clear();
141 39 : _state = PropertyState::OLD;
142 39 : return;
143 : }
144 1098 : if (expression.substr(0, open) == "Older")
145 : {
146 39 : _base_name = expression.substr(open + 1, close - open - 1);
147 39 : _dependent_symbols.clear();
148 39 : _state = PropertyState::OLDER;
149 39 : return;
150 : }
151 1059 : else if (expression.substr(0, open) == "D")
152 : {
153 1059 : auto arguments = expression.substr(open + 1, close - open - 1);
154 1059 : auto close2 = arguments.find_last_of(")");
155 :
156 1059 : if (close2 == std::string::npos)
157 : {
158 : // rest of argument list 0 is the function and 1,.. are the variable to take the derivative
159 : // w.r.t.
160 1059 : MooseUtils::tokenize(arguments, _derivative_symbols, 0, ",");
161 :
162 : // check for empty [] brackets
163 1059 : if (_derivative_symbols.size() > 0)
164 : {
165 : // parse argument zero of D[] as the function material property
166 1059 : parseDependentSymbols(_derivative_symbols[0]);
167 :
168 : // remove function from the _derivative_symbols vector
169 1059 : _derivative_symbols.erase(_derivative_symbols.begin());
170 1059 : updatePropertyName();
171 :
172 1059 : return;
173 : }
174 : }
175 : else
176 : {
177 0 : parseDependentSymbols(arguments.substr(0, close2 + 1));
178 0 : MooseUtils::tokenize(arguments.substr(close2 + 2), _derivative_symbols, 0, ",");
179 0 : updatePropertyName();
180 0 : return;
181 : }
182 1059 : }
183 : }
184 :
185 0 : mooseError("Malformed material_properties expression '", expression, "'");
186 : }
187 :
188 : template <bool is_ad>
189 : void
190 3378 : FunctionMaterialPropertyDescriptor<is_ad>::parseDependentSymbols(const std::string & expression)
191 : {
192 3378 : auto open = expression.find_first_of("(");
193 3378 : auto close = expression.find_last_of(")");
194 :
195 3378 : if (open == std::string::npos && close == std::string::npos)
196 : {
197 : // material property name without arguments
198 3300 : _base_name = expression;
199 : }
200 78 : else if (open != std::string::npos && close != std::string::npos)
201 : {
202 : // take material property name before bracket
203 78 : _base_name = expression.substr(0, open);
204 :
205 : // parse argument list
206 78 : MooseUtils::tokenize(expression.substr(open + 1, close - open - 1), _dependent_symbols, 0, ",");
207 :
208 : // remove duplicates from dependent variable list
209 78 : std::sort(_dependent_symbols.begin(), _dependent_symbols.end());
210 78 : _dependent_symbols.erase(std::unique(_dependent_symbols.begin(), _dependent_symbols.end()),
211 156 : _dependent_symbols.end());
212 : }
213 : else
214 0 : mooseError("Malformed material_properties expression '", expression, "'");
215 3378 : }
216 :
217 : template <bool is_ad>
218 : void
219 0 : FunctionMaterialPropertyDescriptor<is_ad>::printDebug()
220 : {
221 0 : Moose::out << "MPD: " << _fparser_name << ' ' << _base_name << " deriv = [";
222 0 : for (auto & dv : _derivative_symbols)
223 0 : Moose::out << dv << ' ';
224 0 : Moose::out << "] dep = [";
225 0 : for (auto & dv : _dependent_symbols)
226 0 : Moose::out << dv << ' ';
227 0 : Moose::out << "] " << getPropertyName() << '\n';
228 0 : }
229 :
230 : template <bool is_ad>
231 : GenericReal<is_ad>
232 3547797 : FunctionMaterialPropertyDescriptor<is_ad>::value(unsigned int qp) const
233 : {
234 : // current property
235 3547797 : if (_state == PropertyState::CURRENT)
236 : {
237 3547559 : if (_value == nullptr)
238 : {
239 5160 : DerivativeMaterialInterface<Material> * _material_parent =
240 5160 : dynamic_cast<DerivativeMaterialInterface<Material> *>(_parent);
241 5160 : DerivativeMaterialInterface<Kernel> * _kernel_parent =
242 5160 : dynamic_cast<DerivativeMaterialInterface<Kernel> *>(_parent);
243 :
244 : // property name
245 5160 : auto name = derivativePropertyName(_base_name, _derivative_symbols);
246 :
247 : // get the material property reference
248 5160 : if (_material_parent)
249 9183 : _value = _required ? &(_material_parent->getGenericMaterialProperty<Real, is_ad>(name))
250 4023 : : &(_material_parent->getGenericZeroMaterialProperty<Real, is_ad>(name));
251 0 : else if (_kernel_parent)
252 0 : _value = _required ? &(_kernel_parent->getGenericMaterialProperty<Real, is_ad>(name))
253 0 : : &(_kernel_parent->getGenericZeroMaterialProperty<Real, is_ad>(name));
254 : else
255 0 : mooseError("A FunctionMaterialPropertyDescriptor must be owned by either a Material or a "
256 : "Kernel object.");
257 5160 : }
258 :
259 3547559 : return qp != libMesh::invalid_uint ? (*_value)[qp] : 0.0;
260 : }
261 :
262 : // old or older property
263 238 : if (_old_older_value == nullptr)
264 : {
265 : mooseAssert(_derivative_symbols.empty(), "Don't take derivatives of old/older properties.");
266 :
267 78 : DerivativeMaterialInterface<Material> * _material_parent =
268 78 : dynamic_cast<DerivativeMaterialInterface<Material> *>(_parent);
269 78 : DerivativeMaterialInterface<Kernel> * _kernel_parent =
270 78 : dynamic_cast<DerivativeMaterialInterface<Kernel> *>(_parent);
271 :
272 : // get the material property reference
273 78 : if (_material_parent)
274 78 : _old_older_value = (_state == PropertyState::OLD)
275 78 : ? &(_material_parent->getMaterialPropertyOld<Real>(_base_name))
276 39 : : &(_material_parent->getMaterialPropertyOlder<Real>(_base_name));
277 0 : else if (_kernel_parent)
278 0 : _old_older_value = (_state == PropertyState::OLD)
279 0 : ? &(_kernel_parent->getMaterialPropertyOld<Real>(_base_name))
280 0 : : &(_kernel_parent->getMaterialPropertyOlder<Real>(_base_name));
281 : else
282 0 : mooseError("A FunctionMaterialPropertyDescriptor must be owned by either a Material or a "
283 : "Kernel object.");
284 : }
285 :
286 238 : return qp != libMesh::invalid_uint ? (*_old_older_value)[qp] : 0.0;
287 : }
288 :
289 : template <bool is_ad>
290 : void
291 6171 : FunctionMaterialPropertyDescriptor<is_ad>::updatePropertyName()
292 : {
293 6171 : _property_name = derivativePropertyName(_base_name, _derivative_symbols);
294 6171 : }
295 :
296 : // explicit instantiation
297 : template class FunctionMaterialPropertyDescriptor<false>;
298 : template class FunctionMaterialPropertyDescriptor<true>;
|