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 62475 : ParsedMaterialHelper<is_ad>::validParams()
18 : {
19 62475 : InputParameters params = FunctionMaterialBase<is_ad>::validParams();
20 62475 : params += FunctionParserUtils<is_ad>::validParams();
21 62475 : params.addClassDescription("Parsed Function Material.");
22 187425 : params.addParam<bool>("error_on_missing_material_properties",
23 124950 : true,
24 : "Throw an error if any explicitly requested material property does not "
25 : "exist. Otherwise assume it to be zero.");
26 62475 : MultiMooseEnum extra_symbols("x y z t dt");
27 62475 : params.addParam<MultiMooseEnum>(
28 : "extra_symbols",
29 : extra_symbols,
30 : "Special symbols, like point coordinates, time, and timestep size.");
31 187425 : params.addParam<std::vector<MaterialName>>(
32 : "upstream_materials",
33 124950 : std::vector<MaterialName>(),
34 : "List of upstream material properties that must be evaluated when compute=false");
35 124950 : return params;
36 62475 : }
37 :
38 : template <bool is_ad>
39 4149 : ParsedMaterialHelper<is_ad>::ParsedMaterialHelper(const InputParameters & parameters,
40 : VariableNameMappingMode map_mode)
41 : : FunctionMaterialBase<is_ad>(parameters),
42 : FunctionParserUtils<is_ad>(parameters),
43 4149 : _symbol_names(_nargs),
44 4149 : _extra_symbols(this->template getParam<MultiMooseEnum>("extra_symbols")
45 : .template getSetValueIDs<ExtraSymbols>()),
46 4149 : _tol(0),
47 4149 : _map_mode(map_mode),
48 4149 : _upstream_mat_names(this->template getParam<std::vector<MaterialName>>("upstream_materials")),
49 4149 : _error_on_missing_material_properties(
50 16596 : this->template getParam<bool>("error_on_missing_material_properties"))
51 : {
52 4149 : }
53 :
54 : template <bool is_ad>
55 : void
56 1530 : ParsedMaterialHelper<is_ad>::insertReservedNames(std::set<std::string> & reserved_names)
57 : {
58 1530 : 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 1530 : }
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 4149 : 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 4149 : _func_F = std::make_shared<SymFunction>();
161 :
162 : // set FParser internal feature flags
163 4149 : setParserFeatureFlags(_func_F);
164 :
165 : // initialize constants
166 4149 : addFParserConstants(_func_F, constant_names, constant_expressions);
167 :
168 : // add further constants coming from default value coupling
169 4149 : 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 4149 : switch (_map_mode)
176 : {
177 4149 : case VariableNameMappingMode::USE_MOOSE_NAMES:
178 7218 : for (unsigned int i = 0; i < _nargs; ++i)
179 3069 : _symbol_names[i] = _arg_names[i];
180 4149 : 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 4149 : 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 4149 : _tol.resize(_nargs);
202 7218 : for (const auto i : make_range(_nargs))
203 : {
204 3069 : _tol[i] = -1.0;
205 :
206 : // for every argument look through the entire tolerance vector to find a match
207 3069 : 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 4149 : unsigned int nmat_props = mat_prop_expressions.size();
217 7851 : for (const auto i : make_range(nmat_props))
218 : {
219 : // parse the material property parameter entry into a FunctionMaterialPropertyDescriptor
220 3702 : _mat_prop_descriptors.emplace_back(
221 3702 : mat_prop_expressions[i], this, _error_on_missing_material_properties);
222 :
223 : // get the fparser symbol name for the new material property
224 3702 : _symbol_names.push_back(_mat_prop_descriptors.back().getSymbolName());
225 : }
226 :
227 : // get all coupled postprocessors
228 4317 : for (const auto & pp : postprocessor_names)
229 : {
230 168 : _postprocessor_values.push_back(&this->getPostprocessorValueByName(pp));
231 168 : _symbol_names.push_back(pp);
232 : }
233 :
234 : // get all extra symbols
235 4593 : for (const auto symbol : _extra_symbols)
236 444 : switch (symbol)
237 : {
238 156 : case ExtraSymbols::x:
239 156 : _symbol_names.push_back("x");
240 156 : break;
241 72 : case ExtraSymbols::y:
242 72 : _symbol_names.push_back("y");
243 72 : break;
244 72 : case ExtraSymbols::z:
245 72 : _symbol_names.push_back("z");
246 72 : break;
247 72 : case ExtraSymbols::t:
248 72 : _symbol_names.push_back("t");
249 72 : break;
250 72 : case ExtraSymbols::dt:
251 72 : _symbol_names.push_back("dt");
252 72 : break;
253 : }
254 :
255 : // get all functors
256 4149 : 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 4149 : _functors.resize(functor_names.size());
260 4191 : for (const auto i : index_range(functor_names))
261 : {
262 42 : 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 42 : auto functor_name = functor_names[i];
271 42 : auto symbol_name = functor_symbols[i];
272 42 : _symbol_names.push_back(symbol_name);
273 42 : _functors[i] = &FunctorInterface::getFunctor<Real>(functor_name);
274 42 : }
275 : }
276 :
277 : // build 'variables' argument for fparser
278 4149 : std::string variables = Moose::stringify(_symbol_names);
279 :
280 : // build the base function
281 4149 : 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 8298 : _func_params.resize(_nargs + nmat_props + _postprocessor_values.size() + _extra_symbols.size() +
291 4149 : 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 4149 : if (_communicator.rank() != 0)
297 834 : _communicator.barrier();
298 :
299 4149 : functionsPostParse();
300 :
301 : // wait for ranks > 0 to catch up
302 4137 : if (_communicator.rank() == 0)
303 3303 : _communicator.barrier();
304 4137 : }
305 :
306 : template <bool is_ad>
307 : void
308 1530 : ParsedMaterialHelper<is_ad>::functionsPostParse()
309 : {
310 1530 : functionsOptimize(_func_F);
311 :
312 : // force a value update to get the property at least once and register it for the dependencies
313 4044 : for (auto & mpd : _mat_prop_descriptors)
314 2514 : mpd.value();
315 1530 : }
316 :
317 : template <bool is_ad>
318 : void
319 4017 : ParsedMaterialHelper<is_ad>::initialSetup()
320 : {
321 4017 : _upstream_mat.resize(_upstream_mat_names.size());
322 4017 : for (const auto i : make_range(_upstream_mat_names.size()))
323 0 : _upstream_mat[i] = &this->getMaterialByName(_upstream_mat_names[i]);
324 4017 : }
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 6415749 : ParsedMaterialHelper<is_ad>::computeQpProperties()
336 : {
337 6415749 : 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 12427211 : for (const auto i : make_range(_nargs))
345 : {
346 6011462 : if (_tol[i] < 0.0)
347 6011462 : _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 6415749 : auto offset = _nargs;
355 :
356 : // insert material property values
357 10772162 : for (const auto i : index_range(_mat_prop_descriptors))
358 4356413 : _func_params[i + offset] = _mat_prop_descriptors[i].value(_qp);
359 6415749 : offset += _mat_prop_descriptors.size();
360 :
361 : // insert postprocessor values
362 6415749 : auto npps = _postprocessor_values.size();
363 6415893 : for (MooseIndex(_postprocessor_values) i = 0; i < npps; ++i)
364 144 : _func_params[i + offset] = *_postprocessor_values[i];
365 6415749 : offset += _postprocessor_values.size();
366 :
367 : // insert extra symbol values
368 6962565 : for (const auto i : index_range(_extra_symbols))
369 : {
370 546816 : const auto j = offset + i;
371 546816 : switch (_extra_symbols[i])
372 : {
373 522240 : case ExtraSymbols::x:
374 522240 : _func_params[j] = _q_point[_qp](0);
375 522240 : break;
376 6144 : case ExtraSymbols::y:
377 6144 : _func_params[j] = _q_point[_qp](1);
378 6144 : break;
379 6144 : case ExtraSymbols::z:
380 6144 : _func_params[j] = _q_point[_qp](2);
381 6144 : break;
382 6144 : case ExtraSymbols::t:
383 6144 : _func_params[j] = _t;
384 6144 : break;
385 6144 : case ExtraSymbols::dt:
386 6144 : _func_params[j] = _dt;
387 6144 : break;
388 : }
389 : }
390 6415749 : offset += _extra_symbols.size();
391 :
392 : // insert functor values
393 6415749 : const auto & state = TransientInterface::determineState();
394 6415749 : const Moose::ElemQpArg qp_arg = {_current_elem, _qp, _qrule, _q_point[_qp]};
395 7117249 : for (const auto i : index_range(_functors))
396 701500 : _func_params[offset + i] = (*_functors[i])(qp_arg, state);
397 :
398 : // set function value
399 6415749 : if (_prop_F)
400 6415749 : (*_prop_F)[_qp] = evaluate(_func_F, _name);
401 6415716 : }
402 :
403 : // explicit instantiation
404 : template class ParsedMaterialHelper<false>;
405 : template class ParsedMaterialHelper<true>;
|