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 "NEML2Action.h"
11 : #include "NEML2ActionCommon.h"
12 : #include "FEProblem.h"
13 : #include "Factory.h"
14 : #include "NEML2Utils.h"
15 : #include "InputParameterWarehouse.h"
16 :
17 : #ifdef NEML2_ENABLED
18 : #include "neml2/neml2.h"
19 : #include "neml2/base/Settings.h"
20 : #include "neml2/models/VariableBase.h"
21 : #endif
22 :
23 : registerMooseAction("MooseApp", NEML2Action, "parse_neml2");
24 : registerMooseAction("MooseApp", NEML2Action, "add_material");
25 : registerMooseAction("MooseApp", NEML2Action, "add_user_object");
26 :
27 : #ifdef NEML2_ENABLED
28 : // NEML2 variable type --> MOOSE type
29 : const std::map<neml2::TensorType, std::string> tensor_type_map = {
30 : {neml2::TensorType::kScalar, "Real"},
31 : {neml2::TensorType::kSR2, "SymmetricRankTwoTensor"},
32 : {neml2::TensorType::kR2, "RankTwoTensor"},
33 : {neml2::TensorType::kSSR4, "SymmetricRankFourTensor"},
34 : {neml2::TensorType::kR4, "RankFourTensor"},
35 : {neml2::TensorType::kRot, "RealVectorValue"}};
36 : // NEML2 (output, input) type --> NEML2 derivative type
37 : const std::map<std::pair<neml2::TensorType, neml2::TensorType>, neml2::TensorType> deriv_type_map =
38 : {
39 : {{neml2::TensorType::kScalar, neml2::TensorType::kScalar}, neml2::TensorType::kScalar},
40 : {{neml2::TensorType::kSR2, neml2::TensorType::kSR2}, neml2::TensorType::kSSR4},
41 : {{neml2::TensorType::kSR2, neml2::TensorType::kScalar}, neml2::TensorType::kSR2},
42 : {{neml2::TensorType::kScalar, neml2::TensorType::kSR2}, neml2::TensorType::kSR2},
43 : {{neml2::TensorType::kR2, neml2::TensorType::kR2}, neml2::TensorType::kR4},
44 : {{neml2::TensorType::kR2, neml2::TensorType::kScalar}, neml2::TensorType::kR2},
45 : {{neml2::TensorType::kScalar, neml2::TensorType::kR2}, neml2::TensorType::kR2},
46 : };
47 : #endif
48 :
49 : InputParameters
50 67 : NEML2Action::validParams()
51 : {
52 67 : InputParameters params = NEML2ActionCommon::commonParams();
53 134 : params.addClassDescription("Set up the NEML2 material model");
54 268 : params.addParam<std::string>("executor_name",
55 : "Name of the NEML2ModelExecutor user object. The default name is "
56 : "'neml2_<model-name>_<block-name>' where <model-name> is the NEML2 "
57 : "model's name, and <block-name> is this action sub-block's name.");
58 268 : params.addParam<std::string>(
59 : "batch_index_generator_name",
60 : "Name of the NEML2BatchIndexGenerator user object. The default name is "
61 : "'neml2_index_<model-name>_<block-name>' where <model-name> is the NEML2 model's name, and "
62 : "<block-name> is this action sub-block's name.");
63 201 : params.addParam<std::vector<SubdomainName>>(
64 : "block", {}, "List of blocks (subdomains) where the material model is defined");
65 67 : return params;
66 0 : }
67 :
68 25 : NEML2Action::NEML2Action(const InputParameters & params)
69 : : Action(params),
70 75 : _executor_name(isParamValid("executor_name")
71 100 : ? getParam<std::string>("executor_name")
72 100 : : "neml2_" + getParam<std::string>("model") + "_" + name()),
73 75 : _idx_generator_name(isParamValid("batch_index_generator_name")
74 100 : ? getParam<std::string>("batch_index_generator_name")
75 100 : : "neml2_index_" + getParam<std::string>("model") + "_" + name()),
76 50 : _block(getParam<std::vector<SubdomainName>>("block")),
77 100 : _skip_input_variables(getParam<std::vector<std::string>>("skip_input_variables"))
78 : {
79 25 : NEML2Utils::assertNEML2Enabled();
80 :
81 : // Apply parameters under the common area, i.e., under [NEML2]
82 25 : const auto & all_params = _app.getInputParameterWarehouse().getInputParameters();
83 25 : auto & sub_block_params = *(all_params.find(uniqueActionName())->second.get());
84 25 : const auto & common_action = getCommonAction();
85 25 : sub_block_params.applyParameters(common_action.parameters());
86 :
87 : // Set up optional output variable initialization
88 75 : auto init_vars = getParam<std::vector<MaterialPropertyName>>("initialize_outputs");
89 50 : auto init_vals = getParam<std::vector<MaterialPropertyName>>("initialize_output_values");
90 25 : if (init_vars.size() != init_vals.size())
91 0 : paramError("initialize_outputs",
92 : "initialize_outputs should have the same length as initialize_output_values");
93 25 : for (auto i : index_range(init_vars))
94 0 : _initialize_output_values[init_vars[i]] = init_vals[i];
95 :
96 : // Set up additional outputs for each requested material property
97 50 : auto outputs = getParam<std::vector<MaterialPropertyName>>("export_outputs");
98 50 : auto output_targets = getParam<std::vector<std::vector<OutputName>>>("export_output_targets");
99 25 : if (outputs.size() != output_targets.size())
100 0 : paramError("export_outputs",
101 : "export_outputs should have the same length as export_output_targets");
102 85 : for (auto i : index_range(outputs))
103 60 : _export_output_targets[outputs[i]] = output_targets[i];
104 :
105 : #ifdef NEML2_ENABLED
106 : // File name and CLI args
107 50 : _fname = getParam<DataFileName>("input");
108 75 : _cli_args = getParam<std::vector<std::string>>("cli_args");
109 :
110 : // Load input file
111 25 : auto factory = neml2::load_input(std::string(_fname), neml2::utils::join(_cli_args, " "));
112 50 : _model = NEML2Utils::getModel(*factory, getParam<std::string>("model"));
113 : #endif
114 25 : }
115 :
116 : const NEML2ActionCommon &
117 25 : NEML2Action::getCommonAction() const
118 : {
119 25 : auto common_block = _awh.getActions<NEML2ActionCommon>();
120 : mooseAssert(common_block.size() == 1, "There must exist one and only one common NEML2 action.");
121 50 : return *common_block[0];
122 25 : }
123 :
124 : #ifndef NEML2_ENABLED
125 :
126 : void
127 0 : NEML2Action::act()
128 : {
129 0 : }
130 :
131 : #else
132 :
133 : static std::string
134 104 : obscureObjectName(const std::string & name,
135 : const std::string & prefix,
136 : const std::string & suffix,
137 : const std::string & block)
138 : {
139 104 : return "__" + prefix + "_" + name + "_" + suffix + "_" + block + "__";
140 : }
141 :
142 : void
143 74 : NEML2Action::act()
144 : {
145 74 : if (_current_task == "parse_neml2")
146 : {
147 25 : if (_app.parameters().have_parameter<bool>("parse_neml2_only"))
148 25 : if (!_app.parameters().get<bool>("parse_neml2_only"))
149 25 : return;
150 0 : printSummary();
151 : }
152 :
153 : // Look up the MOOSE tensor type string for a NEML2 tensor type, or error
154 104 : auto mooseType = [this](neml2::TensorType type) -> const std::string &
155 : {
156 104 : auto it = tensor_type_map.find(type);
157 104 : if (it == tensor_type_map.end())
158 0 : mooseError("NEML2 type ", type, " not yet mapped to MOOSE");
159 208 : return it->second;
160 49 : };
161 :
162 49 : if (_current_task == "add_user_object")
163 : {
164 25 : setupInputMappings(*_model);
165 24 : setupParameterMappings(*_model);
166 24 : setupOutputMappings(*_model);
167 24 : setupDerivativeMappings(*_model);
168 24 : setupParameterDerivativeMappings(*_model);
169 :
170 24 : printSummary();
171 :
172 : // Create and register a MOOSEToNEML2 gatherer user object, returning its name
173 41 : auto addGatherer = [&](const std::string & moose_name,
174 : const std::string & neml2_name,
175 : NEML2Utils::MOOSEIOType moose_type,
176 : neml2::TensorType neml2_type,
177 : const std::string & suffix,
178 : const std::string & type_prefix = "")
179 : {
180 82 : auto obj_name = obscureObjectName(moose_name, "moose_to_neml2", suffix, name());
181 41 : auto obj_type = "MOOSE" + type_prefix + mooseType(neml2_type) + "ToNEML2";
182 41 : auto obj_params = _factory.getValidParams(obj_type);
183 82 : obj_params.set<std::string>("from_moose") = moose_name;
184 82 : obj_params.set<std::string>("to_neml2") = neml2_name;
185 41 : obj_params.set<MooseEnum>("quantity_type").assign(static_cast<int>(moose_type));
186 82 : obj_params.set<std::vector<SubdomainName>>("block") = _block;
187 41 : _problem->addUserObject(obj_type, obj_name, obj_params);
188 82 : return obj_name;
189 41 : };
190 :
191 : // MOOSEToNEML2 input gatherers
192 24 : std::vector<UserObjectName> gatherers;
193 24 : const auto sep = _model->settings().history_separator();
194 63 : for (const auto & input : _inputs)
195 117 : gatherers.push_back(addGatherer(input.name,
196 39 : neml2::history_name(input.name, input.history_order, sep),
197 39 : input.moose_type,
198 39 : input.neml2_type,
199 78 : std::to_string(input.history_order),
200 39 : input.history_order == 1 ? "Old" : ""));
201 :
202 : // Additional NEML2Kernels that provide input data
203 72 : for (const auto & kernel_name : getParam<std::vector<std::string>>("input_kernels"))
204 : {
205 0 : if (!_model->input_variables().count(kernel_name))
206 0 : paramError("input_kernels",
207 : "The NEML2 kernel ",
208 : kernel_name,
209 : " name does not match any NEML2 input variable.");
210 0 : gatherers.push_back(kernel_name);
211 : }
212 :
213 : // MOOSEToNEML2 parameter gatherers
214 24 : std::vector<UserObjectName> param_gatherers;
215 26 : for (const auto & param : _params)
216 2 : param_gatherers.push_back(
217 10 : addGatherer(param.name, param.name, param.moose_type, param.neml2_type, ""));
218 :
219 : // The index generator UO
220 : {
221 24 : auto type = "NEML2BatchIndexGenerator";
222 48 : auto params = _factory.getValidParams(type);
223 24 : params.applyParameters(parameters());
224 48 : _problem->addUserObject(type, _idx_generator_name, params);
225 24 : }
226 :
227 : // The Executor UO
228 : {
229 24 : auto type = "NEML2ModelExecutor";
230 48 : auto params = _factory.getValidParams(type);
231 24 : params.applyParameters(parameters());
232 72 : params.set<UserObjectName>("batch_index_generator") = _idx_generator_name;
233 48 : params.set<std::vector<UserObjectName>>("gatherers") = gatherers;
234 24 : params.set<std::vector<UserObjectName>>("param_gatherers") = param_gatherers;
235 48 : _problem->addUserObject(type, _executor_name, params);
236 24 : }
237 24 : }
238 :
239 48 : if (_current_task == "add_material")
240 : {
241 : // Look up the NEML2 derivative tensor type for (y, x) variables, or error
242 : auto derivTensorType =
243 24 : [this](neml2::TensorType y_type, neml2::TensorType x_type, const std::string & deriv_name)
244 : {
245 24 : auto it = deriv_type_map.find({y_type, x_type});
246 24 : if (it == deriv_type_map.end())
247 0 : mooseError("NEML2 derivative type for ", deriv_name, " not yet mapped to MOOSE");
248 48 : return it->second;
249 24 : };
250 :
251 : // Create and register a NEML2ToMOOSE material property retriever; `extra` lets
252 : // each caller add the bits that are unique to outputs vs. (parameter) derivatives
253 63 : auto addRetriever = [&](const std::string & moose_name,
254 : const std::string & neml2_var,
255 : neml2::TensorType tensor_type,
256 : auto && extra)
257 : {
258 252 : auto obj_name = obscureObjectName(moose_name, "neml2_to_moose", "", name());
259 63 : auto obj_type = "NEML2ToMOOSE" + mooseType(tensor_type) + "MaterialProperty";
260 63 : auto obj_params = _factory.getValidParams(obj_type);
261 126 : obj_params.set<UserObjectName>("neml2_executor") = _executor_name;
262 189 : obj_params.set<MaterialPropertyName>("to_moose") = moose_name;
263 63 : obj_params.set<std::string>("from_neml2") = neml2_var;
264 126 : obj_params.set<std::vector<SubdomainName>>("block") = _block;
265 63 : if (_export_output_targets.count(moose_name))
266 144 : obj_params.set<std::vector<OutputName>>("outputs") = _export_output_targets[moose_name];
267 63 : extra(obj_params);
268 63 : _problem->addMaterial(obj_type, obj_name, obj_params);
269 87 : };
270 :
271 : // NEML2ToMOOSE output retrievers
272 63 : for (const auto & output : _outputs)
273 : {
274 39 : if (output.moose_type != NEML2Utils::MOOSEIOType::MATERIAL)
275 0 : paramError("moose_output_types",
276 : "Unsupported type corresponding to the moose output ",
277 0 : output.name);
278 39 : addRetriever(output.name,
279 39 : output.name,
280 39 : output.neml2_type,
281 39 : [&](InputParameters & p)
282 : {
283 39 : if (_initialize_output_values.count(output.name))
284 0 : p.set<MaterialPropertyName>("moose_material_property_init") =
285 0 : _initialize_output_values[output.name];
286 39 : });
287 : }
288 :
289 : // NEML2ToMOOSE derivative retrievers
290 48 : for (const auto & deriv : _derivs)
291 : {
292 24 : auto type = derivTensorType(_model->output_variable(deriv.y).type(),
293 24 : _model->input_variable(deriv.x).type(),
294 24 : deriv.name);
295 24 : addRetriever(deriv.name,
296 24 : deriv.y,
297 : type,
298 24 : [&](InputParameters & p)
299 72 : { p.set<std::string>("neml2_input_derivative") = deriv.x; });
300 : }
301 :
302 : // NEML2ToMOOSE parameter derivative retrievers
303 24 : for (const auto & param_deriv : _param_derivs)
304 : {
305 0 : auto type = derivTensorType(_model->output_variable(param_deriv.y).type(),
306 0 : _model->get_parameter(param_deriv.x).type(),
307 0 : param_deriv.name);
308 0 : addRetriever(param_deriv.name,
309 0 : param_deriv.y,
310 : type,
311 0 : [&](InputParameters & p)
312 0 : { p.set<std::string>("neml2_parameter_derivative") = param_deriv.x; });
313 : }
314 : }
315 : }
316 :
317 : NEML2Utils::MOOSEIOType
318 42 : NEML2Action::inferMOOSEIOType(const neml2::VariableName & name,
319 : const neml2::TensorType & type) const
320 : {
321 : // neml2::kScalar can only come from scalar variable, function, or variable
322 42 : if (type == neml2::TensorType::kScalar)
323 : {
324 42 : bool is_time = _problem->isTransient() && (name == "t" || name == "time");
325 42 : bool has_scalar = _problem->hasScalarVariable(name);
326 42 : bool has_func = _problem->hasFunction(name);
327 42 : bool has_var = _problem->hasVariable(name);
328 42 : if (int(is_time) + int(has_scalar) + int(has_func) + int(has_var) > 1)
329 2 : mooseError("Trying to infer MOOSE data type for NEML2 variable ",
330 : name,
331 : ". The name matches multiple types (",
332 1 : (is_time ? "time " : ""),
333 1 : (has_scalar ? "scalar variable " : ""),
334 1 : (has_func ? "function " : ""),
335 1 : (has_var ? "variable " : ""),
336 : "). To avoid ambiguity, please explicitly specify the type in the NEML2 action.");
337 41 : if (is_time)
338 0 : return NEML2Utils::MOOSEIOType::TIME;
339 41 : if (has_scalar)
340 0 : return NEML2Utils::MOOSEIOType::SCALAR;
341 41 : if (has_func)
342 0 : return NEML2Utils::MOOSEIOType::FUNCTION;
343 41 : if (has_var)
344 25 : return NEML2Utils::MOOSEIOType::VARIABLE;
345 : // if neither function nor variable exists, let's assume it's a material property
346 : // note that we can't explicitly check if a material property with the given name exists,
347 : // because materials are added _after_ user objects (see Moose.C)
348 16 : if (!has_func && !has_var)
349 16 : return NEML2Utils::MOOSEIOType::MATERIAL;
350 : }
351 :
352 : // non-scalar can only come from material properties
353 0 : return NEML2Utils::MOOSEIOType::MATERIAL;
354 : }
355 :
356 : void
357 25 : NEML2Action::setupInputMappings(const neml2::Model & model)
358 : {
359 50 : const auto & kernels = getParam<std::vector<std::string>>("input_kernels");
360 :
361 : // Default mapping
362 64 : for (const auto & [vname, var] : model.input_variables())
363 : {
364 : // user requested to skip
365 40 : if (std::find(_skip_input_variables.begin(), _skip_input_variables.end(), var->base_name()) !=
366 80 : _skip_input_variables.end())
367 0 : continue;
368 :
369 : // skip if the input is directly provided by a custom MOOSEToNEML2 object
370 40 : bool gathered_by_kernel = false;
371 40 : for (const auto & kernel_name : kernels)
372 0 : if (vname == kernel_name)
373 : {
374 0 : gathered_by_kernel = true;
375 0 : break;
376 : }
377 40 : if (gathered_by_kernel)
378 0 : continue;
379 :
380 : // skip if manage_state_advance is true and the variable is stateful (history_order > 0),
381 : // because in that case we will gather the variable on the compute device and do not need to set
382 : // up a gatherer for it
383 120 : if (getParam<bool>("manage_state_advance") && var->history_order() > 0)
384 0 : continue;
385 :
386 79 : _inputs.push_back({var->base_name(),
387 79 : inferMOOSEIOType(var->base_name(), var->type()),
388 39 : var->type(),
389 39 : var->history_order()});
390 : }
391 :
392 : // User-specified mapping (overrides default mapping)
393 24 : const auto [input_types, inputs] =
394 96 : getInputParameterMapping<NEML2Utils::MOOSEIOType, std::string>("input_types", "inputs");
395 :
396 24 : for (auto i : index_range(inputs))
397 : {
398 : // Check if the input variable also appears in skip_input_variables
399 : const auto itr =
400 0 : std::find(_skip_input_variables.begin(), _skip_input_variables.end(), inputs[i]);
401 0 : if (itr != _skip_input_variables.end())
402 0 : paramError("skip_input_variables",
403 : "The input variable ",
404 0 : inputs[i],
405 : " is listed in skip_input_variables, but it also appears in inputs. Please "
406 : "remove it from either list.");
407 : // Check if the input variable exists in the NEML2 model
408 0 : if (model.input_variables().count(inputs[i]) == 0)
409 0 : paramError("inputs", "The neml2 input variable ", inputs[i], " does not exist.");
410 : // Check if the input variable is already gathered by a custom MOOSEToNEML2 object
411 0 : bool gathered_by_kernel = false;
412 0 : for (const auto & kernel_name : kernels)
413 0 : if (inputs[i] == kernel_name)
414 : {
415 0 : gathered_by_kernel = true;
416 0 : break;
417 : }
418 0 : if (gathered_by_kernel)
419 0 : paramError("inputs",
420 : "The input variable ",
421 0 : inputs[i],
422 : " is listed in inputs, but it also appears in input_kernels. Please "
423 : "remove it from either list.");
424 : // Check if the input variable is stateful and manage_state_advance is true
425 0 : if (getParam<bool>("manage_state_advance"))
426 0 : if (model.input_variable(inputs[i]).history_order() > 0)
427 0 : paramError(
428 : "inputs",
429 : "The input variable ",
430 0 : inputs[i],
431 : " is listed in inputs, but it is stateful (history_order > 0) and manage_state_advance "
432 : "is true. Please remove it from inputs, or set manage_state_advance to false.");
433 :
434 : // Get the existing mapping for this neml2 input variable and override it
435 0 : for (auto & input : _inputs)
436 0 : if (input.name == inputs[i])
437 : {
438 0 : input.moose_type = input_types[i];
439 0 : break;
440 : }
441 : }
442 181 : }
443 :
444 : void
445 24 : NEML2Action::setupOutputMappings(const neml2::Model & model)
446 : {
447 72 : if (!getParam<bool>("auto_output"))
448 0 : return;
449 :
450 : // Outputs
451 63 : for (const auto & [name, var] : model.output_variables())
452 39 : _outputs.push_back({name,
453 : NEML2Utils::MOOSEIOType::MATERIAL,
454 39 : var->type(),
455 : /*history_order=*/0});
456 78 : }
457 :
458 : void
459 24 : NEML2Action::setupParameterMappings(const neml2::Model & model)
460 : {
461 : // User-specified mapping
462 24 : const auto [param_types, params] = getInputParameterMapping<NEML2Utils::MOOSEIOType, std::string>(
463 96 : "parameter_types", "parameters");
464 :
465 26 : for (auto i : index_range(params))
466 : {
467 2 : if (model.named_parameters().count(params[i]) == 0)
468 0 : paramError("parameters", "The neml2 parameter ", params[i], " does not exist.");
469 2 : const auto & param = model.get_parameter(params[i]);
470 6 : _params.push_back({params[i], inferMOOSEIOType(params[i], param.type()), param.type()});
471 : }
472 28 : }
473 :
474 : void
475 24 : NEML2Action::setupDerivativeMappings(const neml2::Model & model)
476 : {
477 48 : const auto derivs = getParam<std::vector<std::vector<std::string>>>("derivatives");
478 :
479 48 : for (auto i : index_range(derivs))
480 : {
481 24 : if (derivs[i].size() != 2)
482 0 : paramError("derivatives", "The length of each pair in derivatives must be 2.");
483 24 : if (model.output_variables().count(derivs[i][0]) == 0)
484 0 : paramError("derivatives", "The NEML2 output variable ", derivs[i][0], " does not exist.");
485 24 : if (model.input_variables().count(derivs[i][1]) == 0)
486 0 : paramError("derivatives", "The NEML2 input variable ", derivs[i][1], " does not exist.");
487 :
488 24 : const auto & y = derivs[i][0];
489 24 : const auto & x = derivs[i][1];
490 24 : const auto deriv_name = derivativePropertyNameFirst(y, x);
491 24 : _derivs.push_back({deriv_name, y, x});
492 24 : }
493 48 : }
494 :
495 : void
496 24 : NEML2Action::setupParameterDerivativeMappings(const neml2::Model & model)
497 : {
498 48 : const auto derivs = getParam<std::vector<std::vector<std::string>>>("parameter_derivatives");
499 :
500 24 : for (auto i : index_range(derivs))
501 : {
502 0 : if (derivs[i].size() != 2)
503 0 : paramError("parameter_derivatives",
504 : "The length of each pair in parameter_derivatives must be 2.");
505 0 : if (model.output_variables().count(derivs[i][0]) == 0)
506 0 : paramError(
507 0 : "parameter_derivatives", "The NEML2 output variable ", derivs[i][0], " does not exist.");
508 0 : if (model.named_parameters().count(derivs[i][1]) == 0)
509 0 : paramError("parameter_derivatives", "The NEML2 parameter ", derivs[i][1], " does not exist.");
510 :
511 0 : const auto & y = derivs[i][0];
512 0 : const auto & x = derivs[i][1];
513 0 : const auto deriv_name = derivativePropertyNameFirst(y, x);
514 0 : _param_derivs.push_back({deriv_name, y, x});
515 0 : }
516 24 : }
517 :
518 : void
519 24 : NEML2Action::printSummary() const
520 : {
521 24 : if (!_app.parameters().have_parameter<bool>("parse_neml2_only"))
522 0 : return;
523 :
524 : // Save formatting of the output stream so that we can restore it later
525 24 : const auto flags = _console.flags();
526 :
527 : // Default width for the summary
528 24 : const int width = 79;
529 :
530 24 : _console << std::endl;
531 24 : _console << COLOR_CYAN << std::setw(width) << std::setfill('*') << std::left
532 24 : << "NEML2 MATERIAL MODEL SUMMARY BEGIN " << std::setfill(' ') << COLOR_DEFAULT
533 24 : << std::endl;
534 :
535 : // Metadata
536 24 : _console << "NEML2 input file location: " << fname() << std::endl;
537 24 : _console << "NEML2 action path: " << parameters().blockFullpath() << std::endl;
538 :
539 : // List inputs, outputs, and parameters of the model
540 24 : _console << COLOR_CYAN << std::setw(width) << std::setfill('-') << std::left
541 24 : << "Material model structure " << std::setfill(' ') << COLOR_DEFAULT << std::endl;
542 24 : _console << *_model;
543 :
544 : // List transfer between MOOSE and NEML2
545 24 : if (!_app.parameters().get<bool>("parse_neml2_only"))
546 : {
547 24 : _console << COLOR_CYAN << std::setw(width) << std::setfill('-') << std::left
548 24 : << "Transfer between MOOSE and NEML2 " << std::setfill(' ') << COLOR_DEFAULT
549 24 : << std::endl;
550 :
551 24 : _console << "MOOSE --> NEML2" << std::endl;
552 :
553 : // List input transfer, MOOSE -> NEML2
554 63 : for (const auto & input : _inputs)
555 78 : _console << " - " << (input.history_order > 0 ? ("(old) " + input.name) : input.name) << " ("
556 39 : << NEML2Utils::stringify(input.moose_type) << ")" << std::endl;
557 :
558 : // List parameter transfer, MOOSE -> NEML2
559 26 : for (const auto & param : _params)
560 4 : _console << " - " << param.name << " (" << NEML2Utils::stringify(param.moose_type) << " --> "
561 2 : << param.neml2_type << ")" << std::endl;
562 :
563 24 : _console << "MOOSE <-- NEML2" << std::endl;
564 :
565 : // List output transfer, NEML2 -> MOOSE
566 63 : for (const auto & output : _outputs)
567 39 : _console << " - " << output.name << std::endl;
568 :
569 : // List derivative transfer, NEML2 -> MOOSE
570 48 : for (const auto & deriv : _derivs)
571 24 : _console << " - " << deriv.name << std::endl;
572 :
573 : // List parameter derivative transfer, NEML2 -> MOOSE
574 24 : for (const auto & param_deriv : _param_derivs)
575 0 : _console << " - " << param_deriv.name << std::endl;
576 : }
577 :
578 24 : _console << COLOR_CYAN << std::setw(width) << std::setfill('*') << std::left
579 24 : << "NEML2 MATERIAL MODEL SUMMARY END " << std::setfill(' ') << COLOR_DEFAULT << std::endl
580 24 : << std::endl;
581 :
582 : // Restore the formatting of the output stream
583 24 : _console.flags(flags);
584 : }
585 :
586 : std::size_t
587 0 : NEML2Action::getLongestMOOSEName() const
588 : {
589 0 : std::size_t max_moose_name_length = 0;
590 0 : for (const auto & input : _inputs)
591 : {
592 0 : auto n = input.name.size();
593 0 : if (input.history_order > 0)
594 0 : n += 6; // 6 is the length of "(old) "
595 0 : max_moose_name_length = std::max(max_moose_name_length, n);
596 : }
597 0 : for (const auto & param : _params)
598 0 : max_moose_name_length = std::max(max_moose_name_length, param.name.size());
599 0 : for (const auto & output : _outputs)
600 0 : max_moose_name_length = std::max(max_moose_name_length, output.name.size());
601 0 : for (const auto & deriv : _derivs)
602 0 : max_moose_name_length = std::max(max_moose_name_length, deriv.name.size());
603 0 : for (const auto & param_deriv : _param_derivs)
604 0 : max_moose_name_length = std::max(max_moose_name_length, param_deriv.name.size());
605 0 : return max_moose_name_length;
606 : }
607 : #endif // NEML2_ENABLED
|