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