https://mooseframework.inl.gov
Loading...
Searching...
No Matches
DerivativeParsedMaterialHelper.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#include "Conversion.h"
12
13#include <deque>
14
15#include "libmesh/quadrature.h"
16
17template <bool is_ad>
20{
22 params.addClassDescription("Parsed Function Material with automatic derivatives.");
23 params.addParam<unsigned int>("derivative_order", 3, "Maximum order of derivatives taken");
24 params.addParam<std::vector<SymbolName>>(
25 "additional_derivative_symbols",
26 {},
27 "A list of additional (non-variable) symbols (such as material property or postprocessor "
28 "names) to take derivatives w.r.t.");
29 return params;
30}
31
32template <bool is_ad>
34 const InputParameters & parameters,
35 const VariableNameMappingMode map_mode,
36 const std::optional<std::string> & function_param_name /* = {} */)
37 : ParsedMaterialHelper<is_ad>(parameters, map_mode, function_param_name),
38 _derivative_order(this->template getParam<unsigned int>("derivative_order")),
39 _dmatvar_base("matpropautoderiv"),
40 _dmatvar_index(0)
41{
42}
43
44template <bool is_ad>
45void
47{
48 // set up the list of all FParser symbols to derive w.r.t.
49 auto additional_derivative_symbols =
50 this->template getParam<std::vector<SymbolName>>("additional_derivative_symbols");
51
52 // build a list of indices into _symbol_table for all symbols we want to derive w.r.t.
53 // we start with all MOOSE variables, which we _always_ take the derivatives w.r.t.
54 _derivative_symbol_table.reserve(_nargs + additional_derivative_symbols.size());
55 for (unsigned i = 0; i < _nargs; ++i)
56 _derivative_symbol_table.push_back(i);
57
58 // then we add the additional derivative symbols
59 for (auto & ads : additional_derivative_symbols)
60 {
61 // find the index of the symbol if it exists
62 auto it = std::find(_symbol_names.begin(), _symbol_names.end(), ads);
63 if (it == _symbol_names.end())
64 this->paramError("additional_derivative_symbols", "Invalid symbol name '", ads, "'.");
65 auto idx = std::distance(_symbol_names.begin(), it);
66
67 // make sure it is not a MOOSE variable (we already added those) - their index is < nargs
68 if (idx < _nargs)
69 this->paramError(
70 "additional_derivative_symbols",
71 "Symbol name '",
72 ads,
73 "' is a coupled variable. Derivatives w.r.t. coupled variables are always taken "
74 "and they must not be specified again.");
75
76 // check that the user did not specify any duplicates in the additional_derivative_symbols
77 // parameter
78 if (std::count(
79 additional_derivative_symbols.begin(), additional_derivative_symbols.end(), ads) > 1)
80 this->paramError(
81 "additional_derivative_symbols", "Symbol name '", ads, "' was given more than once.");
82
83 // if all checks passed, add the symbol index to the list
84 _derivative_symbol_table.push_back(idx);
85 }
86
87 // optimize base function
89
90 // generate derivatives
91 assembleDerivatives();
92
93 // force a value update to get the property at least once and register it for the dependencies
94 for (auto & mpd : _mat_prop_descriptors)
95 mpd.value();
96
97 // batch compilation
98}
99
100template <bool is_ad>
101void
103 unsigned int var, unsigned int order, const MatPropDescriptorList & parent_mpd_list)
104{
105 // quit if we have exceeded the requested derivative order
106 if (order > _derivative_order)
107 return;
108
109 // FParser symbol we are deriving w.r.t.
110 auto derivative_var = _derivative_symbol_table[var];
111 auto derivative_symbol = _symbol_names[derivative_var];
112
113 // generate parent material property descriptors derivatives
114 MatPropDescriptorList mpd_list;
115 for (const auto & parent_mpd : parent_mpd_list)
116 {
117 // if this material property does not depend on the variable we are deriving w.r.t. skip it
118 if (!parent_mpd.dependsOn(derivative_symbol))
119 continue;
120
121 // otherwise add it to _mat_prop_descriptors
123 mpd.addDerivative(derivative_symbol);
124
125 // create a new symbol name for it
126 std::string newvarname = _dmatvar_base + Moose::stringify(_dmatvar_index++);
127 mpd.setSymbolName(newvarname);
128
129 // add the new mpd and register it as the current variable derivative of the parent mpd
130 _bulk_rules.emplace_back(parent_mpd.getSymbolName(), derivative_symbol, newvarname);
131
132 // append to list
133 mpd_list.push_back(mpd);
134 }
135
136 // append material property descriptors
137 for (const auto & mpd : mpd_list)
138 _mat_prop_descriptors.push_back(mpd);
139
140 // go one order deeper
141 for (unsigned int i = var; i < _derivative_symbol_table.size(); ++i)
142 recurseMatProps(i, order + 1, mpd_list);
143}
144
145template <bool is_ad>
146void
148 unsigned int order,
149 const Derivative & parent_derivative)
150{
151 // quit if we have exceeded the requested derivative order
152 if (order > _derivative_order)
153 return;
154
155 // FParser symbol we are deriving w.r.t.
156 auto derivative_var = _derivative_symbol_table[var];
157 auto derivative_symbol = _symbol_names[derivative_var];
158
159 // current derivative starts off of the parent function
160 Derivative current;
161 current._darg_names = parent_derivative._darg_names;
162
163 // the moose variable name goes into the derivative property name
164 current._darg_names.push_back(derivative_var < _nargs ? _arg_names[derivative_var]
165 : derivative_symbol);
166
167 current._F = std::make_shared<SymFunction>(*parent_derivative._F);
168
169 // execute derivative
170 if (current._F->AutoDiff(derivative_symbol) != -1)
171 mooseError("Failed to take order ", order, " derivative in material ", _name);
172
173 // optimize
174 if (!_disable_fpoptimizer)
175 current._F->Optimize();
176
177 // proceed only if the derivative is not zero
178 if (!current._F->isZero() || is_ad)
179 {
180 // compile
181 if (_enable_jit && !current._F->JITCompile())
182 mooseInfo("Failed to JIT compile expression, falling back to byte code interpretation.");
183
184 // go one order deeper
185 for (unsigned int i = var; i < _derivative_symbol_table.size(); ++i)
186 recurseDerivative(i, order + 1, current);
187
188 // set up a material property for the derivative
189 current._mat_prop =
190 &this->template declarePropertyDerivative<Real, is_ad>(_F_name, current._darg_names);
191
192 // save off current derivative
193 _derivatives.push_back(current);
194 }
195}
196
200template <bool is_ad>
201void
203{
204 // need to check for zero derivatives here, otherwise at least one order is generated
205 if (_derivative_order < 1)
206 return;
207
208 // if we are not on thread 0 we fetch all data from the thread 0 copy that already did all the
209 // work
210 if (_tid > 0)
211 {
212 // get the master object from thread 0
213 const MaterialWarehouse & material_warehouse = this->_fe_problem.getMaterialWarehouse();
214 const MooseObjectWarehouse<MaterialBase> & warehouse = material_warehouse[_material_data_type];
215
216 MooseSharedPointer<DerivativeParsedMaterialHelperTempl> master =
217 MooseSharedNamespace::dynamic_pointer_cast<DerivativeParsedMaterialHelperTempl>(
218 warehouse.getActiveObject(name()));
219
220 // copy parsers and declare properties
221 for (const auto & D : master->_derivatives)
222 {
223 Derivative newderivative;
224 newderivative._mat_prop =
225 &this->template declarePropertyDerivative<Real, is_ad>(_F_name, D._darg_names);
226 newderivative._F = std::make_shared<SymFunction>(*D._F);
227 _derivatives.push_back(newderivative);
228 }
229
230 // copy coupled material properties
231 auto start = _mat_prop_descriptors.size();
232 for (MooseIndex(master->_mat_prop_descriptors) i = start;
233 i < master->_mat_prop_descriptors.size();
234 ++i)
235 {
236 FunctionMaterialPropertyDescriptor<is_ad> newdescriptor(master->_mat_prop_descriptors[i],
237 this);
238 _mat_prop_descriptors.push_back(newdescriptor);
239 }
240
241 // size parameter buffer
242 _func_params.resize(master->_func_params.size());
243 return;
244 }
245
246 // generate all coupled material property mappings
247 for (unsigned int i = 0; i < _derivative_symbol_table.size(); ++i)
248 recurseMatProps(i, 1, _mat_prop_descriptors);
249
250 // bulk register material property derivative rules to avoid repeated calls
251 // to the (slow) AddVariable method
252 if (!_bulk_rules.empty())
253 {
254 std::string vars = _bulk_rules[0]._child;
255 for (MooseIndex(_bulk_rules) i = 1; i < _bulk_rules.size(); ++i)
256 vars += ',' + _bulk_rules[i]._child;
257 _func_F->AddVariable(vars);
258
259 for (const auto & rule : _bulk_rules)
260 _func_F->RegisterDerivative(rule._parent, rule._var, rule._child);
261 }
262
263 // generate all derivatives
264 Derivative root;
265 root._F = _func_F;
266 root._mat_prop = nullptr;
267 for (unsigned int i = 0; i < _derivative_symbol_table.size(); ++i)
268 recurseDerivative(i, 1, root);
269
270 // increase the parameter buffer to provide storage for the material property derivatives
271 _func_params.resize(_nargs + _mat_prop_descriptors.size() + _postprocessor_values.size() +
272 _extra_symbols.size() + _functors.size());
273}
274
275template <bool is_ad>
276void
281
282template <bool is_ad>
283void
285{
287
288 // set derivatives
289 for (auto & D : _derivatives)
290 (*D._mat_prop)[_qp] = evaluate(D._F, _name);
291}
292
293// explicit instantiation
void mooseInfo(Args &&... args)
Emit an informational message with the given stringified, concatenated args.
Definition MooseError.h:401
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
T evaluate(Real, const Point &)
The general evaluation method is not defined.
char ** vars
void ErrorVector unsigned int
Helper class to perform the auto derivative taking.
DerivativeParsedMaterialHelperTempl(const InputParameters &parameters, const VariableNameMappingMode map_mode=VariableNameMappingMode::USE_PARAM_NAMES, const std::optional< std::string > &function_param_name={})
void computeQpProperties() override
Users must override this method.
void recurseMatProps(unsigned int var, unsigned int order, const MatPropDescriptorList &parent_mpd)
void recurseDerivative(unsigned int var, unsigned int order, const Derivative &parent_derivative)
void assembleDerivatives()
Perform construction of all requested derivatives.
void initQpStatefulProperties() override
Initialize stateful properties at quadrature points.
Material properties get fully described using this structure, including their dependent variables and...
void setSymbolName(const std::string &n)
set the fparser symbol name
void addDerivative(const SymbolName &symbol)
take another derivative
virtual void functionsOptimize(SymFunctionPtr &parsed_function)
run FPOptimizer on the parsed function
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
MaterialBase objects are special in that they have additional objects created automatically (see FEPr...
std::shared_ptr< T > getActiveObject(const std::string &name, THREAD_ID tid=0) const
A storage container for MooseObjects that inherit from SetupInterface.
Helper class to perform the parsing and optimization of the function expression.
void computeQpProperties() override
Users must override this method.
static InputParameters validParams()
std::vector< FunctionMaterialPropertyDescriptor< is_ad > > MatPropDescriptorList
convenience typedef for the material property descriptors
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64