https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ParsedMaterialHelper.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 "libmesh/quadrature.h"
13#include "Conversion.h"
14
15template <bool is_ad>
18{
21 params.addClassDescription("Parsed Function Material.");
22 params.addParam<bool>("error_on_missing_material_properties",
23 true,
24 "Throw an error if any explicitly requested non-derivative material "
25 "property does not exist. Otherwise assume it to be zero. Requested "
26 "derivative properties (the D[u,x] syntax) are always optional and "
27 "default to zero when they do not exist.");
29 "extra_symbols",
30 MultiMooseEnum(getExtraSymbolsOptions()),
31 "Special symbols, like point coordinates, time, and timestep size.");
32 params.addParam<std::vector<MaterialName>>(
33 "upstream_materials",
34 std::vector<MaterialName>(),
35 "List of upstream material properties that must be evaluated when compute=false");
36 return params;
37}
38
39template <bool is_ad>
41 const InputParameters & parameters,
42 const VariableNameMappingMode map_mode,
43 const std::optional<std::string> & function_param_name /* = {} */)
44 : FunctionMaterialBase<is_ad>(parameters),
45 FunctionParserUtils<is_ad>(parameters),
46 _symbol_names(_nargs),
47 _extra_symbols(this->template getParam<MultiMooseEnum>("extra_symbols")
48 .template getSetValueIDs<ExtraSymbols>()),
49 _tol(0),
50 _map_mode(map_mode),
51 _function_param_name(function_param_name),
52 _upstream_mat_names(this->template getParam<std::vector<MaterialName>>("upstream_materials")),
53 _error_on_missing_material_properties(
54 this->template getParam<bool>("error_on_missing_material_properties")),
55 _params(parameters)
56{
58 mooseAssert(_params.have_parameter<std::string>(*_function_param_name),
59 "Does not have parameter");
60}
61
62template <bool is_ad>
63void
64ParsedMaterialHelper<is_ad>::insertReservedNames(std::set<std::string> & reserved_names)
65{
66 for (const auto symbol : _extra_symbols)
67 switch (symbol)
68 {
69 case ExtraSymbols::x:
70 reserved_names.insert("x");
71 break;
72 case ExtraSymbols::y:
73 reserved_names.insert("y");
74 break;
75 case ExtraSymbols::z:
76 reserved_names.insert("z");
77 break;
78 case ExtraSymbols::t:
79 reserved_names.insert("t");
80 break;
81 case ExtraSymbols::dt:
82 reserved_names.insert("dt");
83 break;
84 };
85}
86
87template <bool is_ad>
88void
89ParsedMaterialHelper<is_ad>::functionParse(const std::string & function_expression)
90{
91 const std::vector<std::string> empty_string_vector;
92 functionParse(function_expression, empty_string_vector, empty_string_vector);
93}
94
95template <bool is_ad>
96void
97ParsedMaterialHelper<is_ad>::functionParse(const std::string & function_expression,
98 const std::vector<std::string> & constant_names,
99 const std::vector<std::string> & constant_expressions)
100{
101 const std::vector<std::string> empty_string_vector;
102 const std::vector<Real> empty_real_vector;
103 functionParse(function_expression,
104 constant_names,
105 constant_expressions,
106 empty_string_vector,
107 empty_string_vector,
108 empty_real_vector);
109}
110
111template <bool is_ad>
112void
113ParsedMaterialHelper<is_ad>::functionParse(const std::string & function_expression,
114 const std::vector<std::string> & constant_names,
115 const std::vector<std::string> & constant_expressions,
116 const std::vector<std::string> & mat_prop_expressions,
117 const std::vector<std::string> & tol_names,
118 const std::vector<Real> & tol_values)
119{
120 const std::vector<PostprocessorName> empty_pp_name_vector;
121 functionParse(function_expression,
122 constant_names,
123 constant_expressions,
124 mat_prop_expressions,
125 empty_pp_name_vector,
126 tol_names,
127 tol_values);
128}
129
130template <bool is_ad>
131void
133 const std::string & function_expression,
134 const std::vector<std::string> & constant_names,
135 const std::vector<std::string> & constant_expressions,
136 const std::vector<std::string> & mat_prop_expressions,
137 const std::vector<PostprocessorName> & postprocessor_names,
138 const std::vector<std::string> & tol_names,
139 const std::vector<Real> & tol_values)
140{
141 const std::vector<MooseFunctorName> empty_functor_vector;
142 const std::vector<std::string> empty_string_vector;
143 functionParse(function_expression,
144 constant_names,
145 constant_expressions,
146 mat_prop_expressions,
147 postprocessor_names,
148 tol_names,
149 tol_values,
150 empty_functor_vector,
151 empty_string_vector);
152}
153
154template <bool is_ad>
155void
157 const std::string & function_expression,
158 const std::vector<std::string> & constant_names,
159 const std::vector<std::string> & constant_expressions,
160 const std::vector<std::string> & mat_prop_expressions,
161 const std::vector<PostprocessorName> & postprocessor_names,
162 const std::vector<std::string> & tol_names,
163 const std::vector<Real> & tol_values,
164 const std::vector<MooseFunctorName> & functor_names,
165 const std::vector<std::string> & functor_symbols)
166{
167 // build base function object
168 _func_F = std::make_shared<SymFunction>();
169
170 // set FParser internal feature flags
171 setParserFeatureFlags(_func_F);
172
173 // initialize constants
174 addFParserConstants(_func_F, constant_names, constant_expressions);
175
176 // add further constants coming from default value coupling
177 if (_map_mode == VariableNameMappingMode::USE_PARAM_NAMES)
178 for (const auto & acd : _arg_constant_defaults)
179 if (!_func_F->AddConstant(acd, this->_pars.defaultCoupledValue(acd)))
180 _params.mooseError("Invalid constant name in parsed function object");
181
182 // set variable names based on map_mode
183 switch (_map_mode)
184 {
185 case VariableNameMappingMode::USE_MOOSE_NAMES:
186 for (unsigned int i = 0; i < _nargs; ++i)
187 _symbol_names[i] = _arg_names[i];
188 break;
189
190 case VariableNameMappingMode::USE_PARAM_NAMES:
191 for (unsigned i = 0; i < _nargs; ++i)
192 {
193 if (_arg_param_numbers[i] < 0)
194 _symbol_names[i] = _arg_param_names[i];
195 else
196 _symbol_names[i] = _arg_param_names[i] + std::to_string(_arg_param_numbers[i]);
197 }
198 break;
199
200 default:
201 _params.mooseError("Unknown variable mapping mode.");
202 }
203
204 // tolerance vectors
205 if (tol_names.size() != tol_values.size())
206 _params.mooseError("The parameter vectors tol_names and tol_values must have equal length.");
207
208 // set tolerances
209 _tol.resize(_nargs);
210 for (const auto i : make_range(_nargs))
211 {
212 _tol[i] = -1.0;
213
214 // for every argument look through the entire tolerance vector to find a match
215 for (const auto j : index_range(tol_names))
216 if (_symbol_names[i] == tol_names[j])
217 {
218 _tol[i] = tol_values[j];
219 break;
220 }
221 }
222
223 // get all material properties
224 unsigned int nmat_props = mat_prop_expressions.size();
225 for (const auto i : make_range(nmat_props))
226 {
227 // parse the material property parameter entry into a FunctionMaterialPropertyDescriptor
228 _mat_prop_descriptors.emplace_back(
229 mat_prop_expressions[i], this, _error_on_missing_material_properties);
230
231 // get the fparser symbol name for the new material property
232 _symbol_names.push_back(_mat_prop_descriptors.back().getSymbolName());
233 }
234
235 // get all coupled postprocessors
236 for (const auto & pp : postprocessor_names)
237 {
238 _postprocessor_values.push_back(&this->getPostprocessorValueByName(pp));
239 _symbol_names.push_back(pp);
240 }
241
242 // get all extra symbols
243 for (const auto symbol : _extra_symbols)
244 switch (symbol)
245 {
246 case ExtraSymbols::x:
247 _symbol_names.push_back("x");
248 break;
249 case ExtraSymbols::y:
250 _symbol_names.push_back("y");
251 break;
252 case ExtraSymbols::z:
253 _symbol_names.push_back("z");
254 break;
255 case ExtraSymbols::t:
256 _symbol_names.push_back("t");
257 break;
258 case ExtraSymbols::dt:
259 _symbol_names.push_back("dt");
260 break;
261 }
262
263 // get all functors
264 if (!functor_symbols.empty() && functor_symbols.size() != functor_names.size())
265 _params.mooseError(
266 "The parameter vector functor_symbols must be of same length as functor_names, if "
267 "not empty.");
268 _functors.resize(functor_names.size());
269 for (const auto i : index_range(functor_names))
270 {
271 if (functor_symbols.empty())
272 {
273 auto functor_name = functor_names[i];
274 _symbol_names.push_back(functor_name);
275 _functors[i] = &FunctorInterface::getFunctor<Real>(functor_name);
276 }
277 else
278 {
279 auto functor_name = functor_names[i];
280 auto symbol_name = functor_symbols[i];
281 _symbol_names.push_back(symbol_name);
282 _functors[i] = &FunctorInterface::getFunctor<Real>(functor_name);
283 }
284 }
285
286 // build 'variables' argument for fparser
287 std::string variables = Moose::stringify(_symbol_names);
288
289 // build the base function
290 if (_func_F->Parse(function_expression, variables) >= 0)
291 parseError("Invalid parsed material function \"" + function_expression +
292 "\" with variables \"" + variables + "\"; " + _func_F->ErrorMsg());
293
294 // create parameter passing buffer
295 _func_params.resize(_nargs + nmat_props + _postprocessor_values.size() + _extra_symbols.size() +
296 functor_names.size());
297
298 // perform next steps (either optimize or take derivatives and then optimize)
299
300 // let rank 0 do the work first to populate caches
301 if (_communicator.rank() != 0)
302 _communicator.barrier();
303
304 functionsPostParse();
305
306 // wait for ranks > 0 to catch up
307 if (_communicator.rank() == 0)
308 _communicator.barrier();
309}
310
311template <bool is_ad>
312void
314{
315 functionsOptimize(_func_F);
316
317 // force a value update to get the property at least once and register it for the dependencies
318 for (auto & mpd : _mat_prop_descriptors)
319 mpd.value();
320}
321
322template <bool is_ad>
323void
325{
326 _upstream_mat.resize(_upstream_mat_names.size());
327 for (const auto i : make_range(_upstream_mat_names.size()))
328 _upstream_mat[i] = &this->getMaterialByName(_upstream_mat_names[i]);
329}
330
331template <bool is_ad>
332void
334{
335 computeQpProperties();
336}
337
338template <bool is_ad>
339void
341{
342 if (!(this->_compute))
343 {
344 for (const auto i : make_range(_upstream_mat_names.size()))
345 _upstream_mat[i]->computePropertiesAtQp(_qp);
346 }
347
348 // fill the parameter vector, apply tolerances
349 for (const auto i : make_range(_nargs))
350 {
351 if (_tol[i] < 0.0)
352 _func_params[i] = (*_args[i])[_qp];
353 else
354 {
355 auto a = (*_args[i])[_qp];
356 _func_params[i] = a < _tol[i] ? _tol[i] : (a > 1.0 - _tol[i] ? 1.0 - _tol[i] : a);
357 }
358 }
359 auto offset = _nargs;
360
361 // insert material property values
362 for (const auto i : index_range(_mat_prop_descriptors))
363 _func_params[i + offset] = _mat_prop_descriptors[i].value(_qp);
364 offset += _mat_prop_descriptors.size();
365
366 // insert postprocessor values
367 auto npps = _postprocessor_values.size();
368 for (MooseIndex(_postprocessor_values) i = 0; i < npps; ++i)
369 _func_params[i + offset] = *_postprocessor_values[i];
370 offset += _postprocessor_values.size();
371
372 // insert extra symbol values
373 for (const auto i : index_range(_extra_symbols))
374 {
375 const auto j = offset + i;
376 switch (_extra_symbols[i])
377 {
378 case ExtraSymbols::x:
379 _func_params[j] = _q_point[_qp](0);
380 break;
381 case ExtraSymbols::y:
382 _func_params[j] = _q_point[_qp](1);
383 break;
384 case ExtraSymbols::z:
385 _func_params[j] = _q_point[_qp](2);
386 break;
387 case ExtraSymbols::t:
388 _func_params[j] = _t;
389 break;
390 case ExtraSymbols::dt:
391 _func_params[j] = _dt;
392 break;
393 }
394 }
395 offset += _extra_symbols.size();
396
397 // insert functor values
398 const auto & state = TransientInterface::determineState();
399 const Moose::ElemQpArg qp_arg = {_current_elem, _qp, _qrule, _q_point[_qp]};
400 for (const auto i : index_range(_functors))
401 _func_params[offset + i] = (*_functors[i])(qp_arg, state);
402
403 // set function value
404 if (_prop_F)
405 (*_prop_F)[_qp] = evaluate(_func_F, _name);
406}
407
408template <bool is_ad>
409void
410ParsedMaterialHelper<is_ad>::parseError(const std::string & message) const
411{
412 if (_function_param_name)
413 _params.paramError(*_function_param_name, message);
414 else
415 _params.mooseError(message);
416}
417
418// explicit instantiation
419template class ParsedMaterialHelper<false>;
420template class ParsedMaterialHelper<true>;
T evaluate(Real, const Point &)
The general evaluation method is not defined.
Material base class, central to all Materials that provide a Function as a material property value.
static InputParameters validParams()
static InputParameters validParams()
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.
bool have_parameter(std::string_view name) const
A wrapper around the Parameters base class method.
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.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type.
Helper class to perform the parsing and optimization of the function expression.
virtual void initialSetup() override final
Gets called at the beginning of the simulation before this object is asked to do its job.
void initQpStatefulProperties() override
Initialize stateful properties at quadrature points.
void computeQpProperties() override
Users must override this method.
void parseError(const std::string &message) const
Helper for reporting a parse error with a much as context as possible.
void insertReservedNames(std::set< std::string > &reserved_names)
Populates the given set with names not to be used as user-defined symbol (e.g.
virtual void functionsPostParse()
const std::optional< std::string > _function_param_name
Optional parameter name that represents the function to associate errors with.
static InputParameters validParams()
ParsedMaterialHelper(const InputParameters &parameters, const VariableNameMappingMode map_mode, const std::optional< std::string > &function_param_name={})
void functionParse(const std::string &function_expression)
This method sets up and parses the function string given by the user.
const InputParameters & _params
The underlying parameters.
Moose::StateArg determineState() const
Create a functor state argument that corresponds to the implicit state of this object.
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:65
Argument for requesting functor evaluation at a quadrature point location in an element.