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 "ParameterRegistration.h"
11 :
12 : #include "ParameterRegistry.h"
13 : #include "MooseTypes.h"
14 : #include "ReporterName.h"
15 : #include "MooseEnum.h"
16 : #include "MultiMooseEnum.h"
17 : #include "ExecFlagEnum.h"
18 :
19 : namespace Moose::ParameterRegistration
20 : {
21 :
22 : template <>
23 : void
24 195492 : setScalarValue(bool & value, const hit::Field & field)
25 : {
26 : // Handles non-quoted values
27 : try
28 : {
29 195492 : value = field.boolVal();
30 : }
31 : // Handles quoted values
32 109 : catch (hit::Error &)
33 : {
34 218 : const auto strval = field.param<std::string>();
35 109 : if (strval == "1")
36 2 : value = true;
37 107 : else if (strval == "0")
38 2 : value = false;
39 105 : else if (!hit::toBool(strval, &value))
40 4 : throw std::invalid_argument("invalid boolean syntax for parameter: " + field.path() + "='" +
41 6 : strval + "'");
42 111 : }
43 195490 : }
44 :
45 : /*******************************************************************************/
46 : /* This contains the initialization time registration of all of the base */
47 : /* parameter types that are registered for use in the Builder for MOOSE. */
48 : /*******************************************************************************/
49 :
50 : namespace detail
51 : {
52 :
53 : static Moose::ParameterRegistry & registry = Moose::ParameterRegistry::get();
54 :
55 : /*******************************************************************************/
56 : /* Derivative string registration */
57 : /* */
58 : /* Registers for scalars, vectors, double vectors, and triple vectors */
59 : /* */
60 : /* See MooseDerivativeStringClass macro usage in MooseTypes.h */
61 : /* Please keep the ordering consistent */
62 : /*******************************************************************************/
63 :
64 : // Special cases that aren't included: CLIArgString
65 10015 : registerParameter(FileName);
66 1199 : registerParameter(FileNameNoExtension);
67 0 : registerParameter(RelativeFileName);
68 41 : registerParameter(DataFileName);
69 8139 : registerParameter(MeshFileName);
70 45 : registerParameter(MatrixFileName);
71 0 : registerParameter(OutFileBase);
72 181395 : registerParameter(NonlinearVariableName);
73 4221 : registerParameter(LinearVariableName);
74 0 : registerParameter(SolverVariableName);
75 44204 : registerParameter(AuxVariableName);
76 95609 : registerParameter(VariableName);
77 139125 : registerParameter(BoundaryName);
78 50854 : registerParameter(SubdomainName);
79 9875 : registerParameter(PostprocessorName);
80 1566 : registerParameter(VectorPostprocessorName);
81 1269 : registerParameter(MeshDivisionName);
82 45113 : registerParameter(FunctionName);
83 12 : registerParameter(DistributionName);
84 287 : registerParameter(SamplerName);
85 5718 : registerParameter(UserObjectName);
86 571 : registerParameter(InterpolationMethodName);
87 506 : registerParameter(IndicatorName);
88 1947 : registerParameter(MarkerName);
89 14729 : registerParameter(MultiAppName);
90 6622 : registerParameter(OutputName);
91 13088 : registerParameter(MaterialPropertyName);
92 17523 : registerParameter(MooseFunctorName);
93 128 : registerParameter(MaterialName);
94 6530 : registerParameter(TagName);
95 26997 : registerParameter(MeshGeneratorName);
96 1057 : registerParameter(ExtraElementIDName);
97 2768 : registerParameter(ReporterValueName);
98 252 : registerParameter(ComponentName);
99 99 : registerParameter(PhysicsName);
100 977 : registerParameter(PositionsName);
101 75 : registerParameter(TimesName);
102 33 : registerParameter(ExecutorName);
103 1017 : registerParameter(ParsedFunctionExpression);
104 970 : registerParameter(NonlinearSystemName);
105 1360 : registerParameter(ConvergenceName);
106 2042 : registerParameter(LinearSystemName);
107 2569 : registerParameter(SolverSystemName);
108 : #ifdef MOOSE_MFEM_ENABLED
109 3088 : registerParameter(MFEMScalarCoefficientName);
110 761 : registerParameter(MFEMVectorCoefficientName);
111 0 : registerParameter(MFEMMatrixCoefficientName);
112 3211 : registerParameter(MFEMFESpaceName);
113 808 : registerParameter(MFEMSolverName);
114 : #endif
115 :
116 : /*******************************************************************************/
117 : /* Native type registration */
118 : /* */
119 : /* Registers for scalars, vectors, double vectors, and triple vectors */
120 : /*******************************************************************************/
121 :
122 279467 : registerParameter(double);
123 703374 : registerParameter(std::string);
124 1742 : registerParameter(short int);
125 3902 : registerParameter(int);
126 80 : registerParameter(long int);
127 15054 : registerParameter(unsigned short);
128 168010 : registerParameter(unsigned int);
129 3524 : registerParameter(unsigned long);
130 4 : registerParameter(unsigned long long);
131 :
132 : /*******************************************************************************/
133 : /* Bool registration */
134 : /*******************************************************************************/
135 :
136 195492 : registerScalarParameter(bool);
137 1925 : registerVectorParameter(bool);
138 :
139 : /*******************************************************************************/
140 : /* Helpers used across types */
141 : /*******************************************************************************/
142 :
143 : /// Helper for converting a string to a ReporterName, which requires splitting
144 : /// the string at the '/' delimiter
145 3208 : const auto convert_reporter_name = [](const std::string & val,
146 : const hit::Field & field) -> ReporterName
147 : {
148 3208 : const auto names = MooseUtils::rsplit(val, "/", 2);
149 3208 : if (names.size() != 2)
150 8 : throw std::invalid_argument("invalid syntax in ReporterName parameter " + field.fullpath() +
151 12 : ": supplied name '" + val + "' must contain the '/' delimiter");
152 6408 : return {names[0], names[1]};
153 3208 : };
154 :
155 : /*******************************************************************************/
156 : /* Component-typed scalar registration */
157 : /*******************************************************************************/
158 :
159 : /// Helper for setting a scalar component value (one with 3 real values)
160 29321 : const auto set_scalar_component_value = [](auto & value, const hit::Field & field)
161 : {
162 58642 : const auto vec = field.param<std::vector<double>>();
163 29321 : if (vec.size() != LIBMESH_DIM)
164 2 : throw std::invalid_argument("wrong number of values in " + MooseUtils::prettyCppType(&value) +
165 : " parameter '" + field.fullpath() + "': was given " +
166 : std::to_string(vec.size()) + " component(s) but should have " +
167 : std::to_string(LIBMESH_DIM));
168 :
169 117276 : for (const auto d : make_range(LIBMESH_DIM))
170 87957 : value(d) = Real(vec[d]);
171 29321 : };
172 :
173 : // Point
174 8891 : static auto point = registry.add<Point>([](Point & value, const hit::Field & field)
175 8891 : { set_scalar_component_value(value, field); });
176 : // RealVectorValue
177 : static auto realvectorvalue =
178 20430 : registry.add<RealVectorValue>([](RealVectorValue & value, const hit::Field & field)
179 20430 : { set_scalar_component_value(value, field); });
180 :
181 : /*******************************************************************************/
182 : /* Custom scalar registration */
183 : /*******************************************************************************/
184 :
185 : // We only support CLIArgString and std::vector<CLIArgString>, so this isn't
186 : // added in the main MooseDerivativeString case
187 0 : registerScalarParameter(CLIArgString);
188 : // RealEigenVector
189 : static auto realeigenvector = registry.add<RealEigenVector>(
190 2030 : [](RealEigenVector & value, const hit::Field & field)
191 : {
192 4062 : const auto vec = field.param<std::vector<double>>();
193 2028 : value.resize(vec.size());
194 6506 : for (const auto i : index_range(vec))
195 4478 : value(i) = Real(vec[i]);
196 2028 : });
197 : // RealEigenVector
198 : static auto realeigenmatrix = registry.add<RealEigenMatrix>(
199 216 : [](RealEigenMatrix & value, const hit::Field & field)
200 : {
201 216 : value.resize(0, 0);
202 216 : std::vector<std::string> tokens;
203 648 : MooseUtils::tokenize(field.param<std::string>(), tokens, 1, ";");
204 :
205 625 : for (const auto i : index_range(tokens))
206 : {
207 413 : const auto token = MooseUtils::trim(tokens[i]);
208 413 : std::vector<Real> values;
209 826 : if (!MooseUtils::tokenizeAndConvert<Real>(token, values))
210 4 : throw std::invalid_argument("invalid syntax for parameter: " + field.fullpath() + "[" +
211 6 : std::to_string(i) + "]='" + token + "'");
212 411 : if (i == 0)
213 216 : value.resize(tokens.size(), values.size());
214 195 : else if (libMesh::cast_int<std::size_t>(value.cols()) != values.size())
215 2 : throw std::invalid_argument("matrix is not square for parameter " + field.fullpath());
216 1243 : for (const auto j : index_range(values))
217 834 : value(i, j) = values[j];
218 417 : }
219 216 : });
220 : // MooseEnum
221 421883 : static auto mooseenum = registry.add<MooseEnum>([](MooseEnum & value, const hit::Field & field)
222 1265658 : { value = field.param<std::string>(); });
223 : // MultiMooseEnum
224 : static auto multimooseenum = registry.add<MultiMooseEnum>(
225 31220 : [](MultiMooseEnum & value, const hit::Field & field)
226 124880 : { value = MooseUtils::stringJoin(field.param<std::vector<std::string>>(), " "); });
227 : // ExecFlagEnum
228 : static auto execflagenum = registry.add<ExecFlagEnum>(
229 55924 : [](ExecFlagEnum & value, const hit::Field & field)
230 223696 : { value = MooseUtils::stringJoin(field.param<std::vector<std::string>>(), " "); });
231 : // RealTensorValue
232 : static auto realtensorvalue = registry.add<RealTensorValue>(
233 42 : [](RealTensorValue & value, const hit::Field & field)
234 : {
235 86 : const auto vec = field.param<std::vector<double>>();
236 40 : if (vec.size() != LIBMESH_DIM * LIBMESH_DIM)
237 4 : throw std::invalid_argument("invalid RealTensorValue parameter '" + field.fullpath() +
238 8 : "': size is " + std::to_string(vec.size()) + " but should be " +
239 6 : std::to_string(LIBMESH_DIM * LIBMESH_DIM));
240 :
241 152 : for (const auto i : make_range(LIBMESH_DIM))
242 456 : for (const auto j : make_range(LIBMESH_DIM))
243 342 : value(i, j) = Real(vec[i * LIBMESH_DIM + j]);
244 40 : });
245 : // ReporterName
246 : static auto reportername = registry.add<ReporterName>(
247 1033 : [](ReporterName & value, const hit::Field & field)
248 3101 : { value = convert_reporter_name(field.param<std::string>(), field); });
249 :
250 : /*******************************************************************************/
251 : /* Component-typed vector registration */
252 : /*******************************************************************************/
253 :
254 : /// Helper for setting a vector component value (one with 3 real values)
255 8428 : const auto set_vector_component_value = [](auto & value, const hit::Field & field)
256 : {
257 8428 : value.clear();
258 16858 : const auto vec = field.param<std::vector<double>>();
259 :
260 8426 : if (vec.size() % LIBMESH_DIM)
261 5 : throw std::invalid_argument("wrong number of values in vector parameter '" + field.fullpath() +
262 : "': size " + std::to_string(vec.size()) + " is not a multiple of " +
263 : std::to_string(LIBMESH_DIM));
264 :
265 8421 : const std::size_t size = vec.size() / LIBMESH_DIM;
266 8421 : value.resize(size);
267 31153 : for (const auto i : make_range(size))
268 90928 : for (const auto d : make_range(LIBMESH_DIM))
269 68196 : value[i](d) = vec[i * LIBMESH_DIM + d];
270 8426 : };
271 :
272 : // std::vector<Point>
273 : static auto vector_point =
274 8377 : registry.add<std::vector<Point>>([](std::vector<Point> & value, const hit::Field & field)
275 8377 : { set_vector_component_value(value, field); });
276 : // std::vector<RealVectorValue>
277 : static auto vector_realvectorvalue = registry.add<std::vector<RealVectorValue>>(
278 51 : [](std::vector<RealVectorValue> & value, const hit::Field & field)
279 51 : { set_vector_component_value(value, field); });
280 :
281 : /*******************************************************************************/
282 : /* Custom vector registration */
283 : /*******************************************************************************/
284 :
285 : // std::vector<MooseEnum>
286 : static auto vector_mooseenum = registry.add<std::vector<MooseEnum>>(
287 260 : [](std::vector<MooseEnum> & value, const hit::Field & field)
288 : {
289 : mooseAssert(!value.empty(), "Missing a value to initialize on");
290 :
291 : // With MOOSE enums we need a default object so it should have been
292 : // passed in the param pointer. We are only going to use the first
293 : // item in the vector (value[0]) and ignore the rest.
294 520 : const auto vec = field.param<std::vector<std::string>>();
295 260 : value.resize(vec.size(), value[0]);
296 732 : for (const auto i : index_range(vec))
297 475 : value[i] = vec[i];
298 260 : });
299 : // std::vector<MooseEnum>
300 : static auto vector_multimooseenum = registry.add<std::vector<MultiMooseEnum>>(
301 17 : [](std::vector<MultiMooseEnum> & value, const hit::Field & field)
302 : {
303 : mooseAssert(!value.empty(), "Missing a value to initialize on");
304 :
305 68 : const auto tokens = MooseUtils::split(field.param<std::string>(), ";");
306 78 : for (const auto i : index_range(tokens))
307 : {
308 64 : const auto & entry = tokens[i];
309 128 : if (MooseUtils::trim(entry) == "")
310 6 : throw std::invalid_argument("entry " + std::to_string(i) + " in '" + field.fullpath() +
311 9 : "' is empty");
312 : }
313 14 : value.resize(tokens.size(), value[0]);
314 69 : for (const auto i : index_range(tokens))
315 : {
316 58 : std::vector<std::string> strvals;
317 58 : MooseUtils::tokenize<std::string>(tokens[i], strvals, 1, " ");
318 58 : value[i] = strvals;
319 58 : }
320 17 : });
321 : // std::vector<ReporterName>
322 : static auto vector_reportername = registry.add<std::vector<ReporterName>>(
323 1136 : [](std::vector<ReporterName> & value, const hit::Field & field)
324 : {
325 1136 : value.clear();
326 2272 : const auto names = field.param<std::vector<std::string>>();
327 1136 : value.resize(names.size());
328 3309 : for (const auto i : index_range(names))
329 2175 : value[i] = convert_reporter_name(names[i], field);
330 1136 : });
331 : // std::vector<CLIArgString>
332 : static auto vector_cliargstring = registry.add<std::vector<CLIArgString>>(
333 1902 : [](std::vector<CLIArgString> & value, const hit::Field & field)
334 : {
335 1902 : value.clear();
336 3804 : const auto strvals = field.param<std::vector<std::string>>();
337 1902 : if (strvals.empty())
338 3 : return;
339 :
340 : // slightly oversized if vectors have been split
341 1899 : value.resize(strvals.size());
342 :
343 : // Re-assemble vector parameters
344 1899 : unsigned int i_param = 0;
345 1899 : bool vector_param_detected = false;
346 5106 : for (const auto i : index_range(strvals))
347 : {
348 : // Look for a quote, both types
349 : const auto double_split =
350 6414 : MooseUtils::rsplit(strvals[i], "\"", std::numeric_limits<std::size_t>::max());
351 : const auto single_split =
352 6414 : MooseUtils::rsplit(strvals[i], "\'", std::numeric_limits<std::size_t>::max());
353 3207 : if (double_split.size() + single_split.size() >= 3)
354 : // Either entering or exiting a vector parameter (>3 is entering another vector)
355 : // Even and >2 number of quotes means both finished and started another vector parameter
356 1451 : if ((double_split.size() + single_split.size()) % 2 == 1)
357 216 : vector_param_detected = !vector_param_detected;
358 :
359 : // We're building a vector parameters, just append the text, rebuild the spaces
360 3207 : if (vector_param_detected)
361 360 : value[i_param] += strvals[i] + ' ';
362 : else
363 : {
364 2847 : value[i_param] += strvals[i];
365 2847 : i_param++;
366 : }
367 3207 : }
368 : // Use actual size after re-forming vector parameters
369 1899 : value.resize(i_param);
370 1902 : });
371 :
372 : /*******************************************************************************/
373 : /* Component-typed double vector registration */
374 : /*******************************************************************************/
375 :
376 : /// Helper for setting a double vector component value (one with 3 real values)
377 96 : const auto set_double_vector_component_value = [](auto & value, const hit::Field & field)
378 : {
379 192 : const auto strval = field.param<std::string>();
380 :
381 : // Split vector at delim ";" (substrings are not of type T yet)
382 96 : std::vector<std::string> tokens;
383 96 : MooseUtils::tokenize(strval, tokens, 1, ";");
384 96 : value.resize(tokens.size());
385 :
386 : // Split each token at spaces
387 96 : std::vector<std::vector<double>> vecvec(tokens.size());
388 284 : for (const auto i : index_range(tokens))
389 380 : if (!MooseUtils::tokenizeAndConvert<double>(tokens[i], vecvec[i]))
390 2 : throw std::invalid_argument("invalid format for parameter '" + field.fullpath() +
391 : "' at index " + std::to_string(i));
392 :
393 280 : for (const auto i : index_range(vecvec))
394 : {
395 188 : const auto & vec = vecvec[i];
396 188 : if (vec.size() % LIBMESH_DIM)
397 2 : throw std::invalid_argument(
398 : "wrong number of values in double-indexed vector component parameter '" +
399 : field.fullpath() + "' at index " + std::to_string(i) + ": subcomponent size " +
400 : std::to_string(vec.size()) + " is not a multiple of " + std::to_string(LIBMESH_DIM));
401 : }
402 :
403 : // convert vector<vector<double>> to vector<vector<T>>
404 92 : value.resize(vecvec.size());
405 276 : for (const auto i : index_range(vecvec))
406 : {
407 184 : const auto & vec_entry = vecvec[i];
408 184 : auto & value_entry = value[i];
409 184 : const std::size_t size = vec_entry.size() / LIBMESH_DIM;
410 184 : value_entry.resize(size);
411 636 : for (const auto j : make_range(size))
412 1808 : for (const auto d : make_range(LIBMESH_DIM))
413 1356 : value_entry[j](d) = vec_entry[j * LIBMESH_DIM + d];
414 : }
415 104 : };
416 :
417 : // std::vector<std::vector<Point>>
418 : static auto doublevector_point = registry.add<std::vector<std::vector<Point>>>(
419 94 : [](std::vector<std::vector<Point>> & value, const hit::Field & field)
420 94 : { set_double_vector_component_value(value, field); });
421 : // std::vector<std::vector<RealVectorValue>>
422 : static auto doublevector_realvectorvalue = registry.add<std::vector<std::vector<RealVectorValue>>>(
423 2 : [](std::vector<std::vector<RealVectorValue>> & value, const hit::Field & field)
424 2 : { set_double_vector_component_value(value, field); });
425 :
426 : /*******************************************************************************/
427 : /* Map registration */
428 : /*******************************************************************************/
429 :
430 0 : registerMapParameter(std::string, unsigned int);
431 48 : registerMapParameter(std::string, Real);
432 240 : registerMapParameter(std::string, std::string);
433 12 : registerMapParameter(unsigned int, unsigned int);
434 12 : registerMapParameter(unsigned long, unsigned int);
435 12 : registerMapParameter(unsigned long long, unsigned int);
436 :
437 : } // end of namespace detail
438 : } // end of namespace Moose::ParameterRegistration
|