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