18 #include "neml2/neml2.h" 19 #include "neml2/base/Settings.h" 20 #include "neml2/models/VariableBase.h" 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"}};
37 const std::map<std::pair<neml2::TensorType, neml2::TensorType>, neml2::TensorType>
deriv_type_map =
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},
54 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.");
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 params.
addParam<std::vector<SubdomainName>>(
64 "block", {},
"List of blocks (subdomains) where the material model is defined");
70 _executor_name(isParamValid(
"executor_name")
71 ? getParam<
std::string>(
"executor_name")
72 :
"neml2_" + getParam<
std::string>(
"model") +
"_" +
name()),
73 _idx_generator_name(isParamValid(
"batch_index_generator_name")
74 ? getParam<
std::string>(
"batch_index_generator_name")
75 :
"neml2_index_" + getParam<
std::string>(
"model") +
"_" +
name()),
76 _block(getParam<
std::vector<SubdomainName>>(
"block")),
77 _skip_input_variables(getParam<
std::vector<
std::string>>(
"skip_input_variables"))
83 auto & sub_block_params = *(all_params.find(
uniqueActionName())->second.get());
85 sub_block_params.applyParameters(common_action.parameters());
88 auto init_vars = getParam<std::vector<MaterialPropertyName>>(
"initialize_outputs");
89 auto init_vals = getParam<std::vector<MaterialPropertyName>>(
"initialize_output_values");
90 if (init_vars.size() != init_vals.size())
92 "initialize_outputs should have the same length as initialize_output_values");
97 auto outputs = getParam<std::vector<MaterialPropertyName>>(
"export_outputs");
98 auto output_targets = getParam<std::vector<std::vector<OutputName>>>(
"export_output_targets");
99 if (outputs.size() != output_targets.size())
101 "export_outputs should have the same length as export_output_targets");
107 _fname = getParam<DataFileName>(
"input");
108 _cli_args = getParam<std::vector<std::string>>(
"cli_args");
111 auto factory = neml2::load_input(std::string(
_fname), neml2::utils::join(
_cli_args,
" "));
120 mooseAssert(common_block.size() == 1,
"There must exist one and only one common NEML2 action.");
121 return *common_block[0];
124 #ifndef NEML2_ENABLED 135 const std::string & prefix,
136 const std::string & suffix,
137 const std::string & block)
139 return "__" + prefix +
"_" +
name +
"_" + suffix +
"_" + block +
"__";
154 auto mooseType = [
this](neml2::TensorType
type) ->
const std::string &
173 auto addGatherer = [&](
const std::string & moose_name,
174 const std::string & neml2_name,
176 neml2::TensorType neml2_type,
177 const std::string & suffix,
178 const std::string & type_prefix =
"")
181 auto obj_type =
"MOOSE" + type_prefix + mooseType(neml2_type) +
"ToNEML2";
183 obj_params.
set<std::string>(
"from_moose") = moose_name;
184 obj_params.set<std::string>(
"to_neml2") = neml2_name;
185 obj_params.set<
MooseEnum>(
"quantity_type").assign(static_cast<int>(moose_type));
186 obj_params.set<std::vector<SubdomainName>>(
"block") =
_block;
187 _problem->addUserObject(obj_type, obj_name, obj_params);
192 std::vector<UserObjectName> gatherers;
193 const auto sep =
_model->settings().history_separator();
194 for (
const auto & input :
_inputs)
195 gatherers.push_back(addGatherer(input.name,
196 neml2::history_name(input.name, input.history_order, sep),
199 std::to_string(input.history_order),
200 input.history_order == 1 ?
"Old" :
""));
203 for (
const auto & kernel_name :
getParam<std::vector<std::string>>(
"input_kernels"))
205 if (!
_model->input_variables().count(kernel_name))
209 " name does not match any NEML2 input variable.");
210 gatherers.push_back(kernel_name);
214 std::vector<UserObjectName> param_gatherers;
215 for (
const auto & param :
_params)
216 param_gatherers.push_back(
217 addGatherer(param.name, param.name, param.moose_type, param.neml2_type,
""));
221 auto type =
"NEML2BatchIndexGenerator";
229 auto type =
"NEML2ModelExecutor";
233 params.set<std::vector<UserObjectName>>(
"gatherers") = gatherers;
234 params.set<std::vector<UserObjectName>>(
"param_gatherers") = param_gatherers;
242 auto derivTensorType =
243 [
this](neml2::TensorType y_type, neml2::TensorType x_type,
const std::string & deriv_name)
247 mooseError(
"NEML2 derivative type for ", deriv_name,
" not yet mapped to MOOSE");
253 auto addRetriever = [&](
const std::string & moose_name,
254 const std::string & neml2_var,
255 neml2::TensorType tensor_type,
259 auto obj_type =
"NEML2ToMOOSE" + mooseType(tensor_type) +
"MaterialProperty";
262 obj_params.set<MaterialPropertyName>(
"to_moose") = moose_name;
263 obj_params.set<std::string>(
"from_neml2") = neml2_var;
264 obj_params.set<std::vector<SubdomainName>>(
"block") =
_block;
268 _problem->addMaterial(obj_type, obj_name, obj_params);
272 for (
const auto & output :
_outputs)
276 "Unsupported type corresponding to the moose output ",
278 addRetriever(output.name,
283 if (_initialize_output_values.count(output.name))
284 p.set<MaterialPropertyName>(
"moose_material_property_init") =
285 _initialize_output_values[output.name];
290 for (
const auto & deriv :
_derivs)
295 addRetriever(
deriv.name,
299 { p.set<std::string>(
"neml2_input_derivative") = deriv.x; });
305 auto type = derivTensorType(
_model->output_variable(param_deriv.y).type(),
306 _model->get_parameter(param_deriv.x).type(),
308 addRetriever(param_deriv.name,
312 { p.set<std::string>(
"neml2_parameter_derivative") = param_deriv.x; });
319 const neml2::TensorType & type)
const 322 if (
type == neml2::TensorType::kScalar)
328 if (
int(is_time) +
int(has_scalar) +
int(has_func) +
int(has_var) > 1)
329 mooseError(
"Trying to infer MOOSE data type for NEML2 variable ",
331 ". The name matches multiple types (",
332 (is_time ?
"time " :
""),
333 (has_scalar ?
"scalar variable " :
""),
334 (has_func ?
"function " :
""),
335 (has_var ?
"variable " :
""),
336 "). To avoid ambiguity, please explicitly specify the type in the NEML2 action.");
348 if (!has_func && !has_var)
359 const auto & kernels = getParam<std::vector<std::string>>(
"input_kernels");
362 for (
const auto & [vname, var] : model.input_variables())
370 bool gathered_by_kernel =
false;
371 for (
const auto & kernel_name : kernels)
372 if (vname == kernel_name)
374 gathered_by_kernel =
true;
377 if (gathered_by_kernel)
383 if (getParam<bool>(
"manage_state_advance") && var->history_order() > 0)
386 _inputs.push_back({var->base_name(),
389 var->history_order()});
393 const auto [input_types, inputs] =
394 getInputParameterMapping<NEML2Utils::MOOSEIOType, std::string>(
"input_types",
"inputs");
403 "The input variable ",
405 " is listed in skip_input_variables, but it also appears in inputs. Please " 406 "remove it from either list.");
408 if (model.input_variables().count(inputs[i]) == 0)
409 paramError(
"inputs",
"The neml2 input variable ", inputs[i],
" does not exist.");
411 bool gathered_by_kernel =
false;
412 for (
const auto & kernel_name : kernels)
413 if (inputs[i] == kernel_name)
415 gathered_by_kernel =
true;
418 if (gathered_by_kernel)
420 "The input variable ",
422 " is listed in inputs, but it also appears in input_kernels. Please " 423 "remove it from either list.");
425 if (getParam<bool>(
"manage_state_advance"))
426 if (model.input_variable(inputs[i]).history_order() > 0)
429 "The input variable ",
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.");
436 if (input.name == inputs[i])
438 input.moose_type = input_types[i];
447 if (!getParam<bool>(
"auto_output"))
451 for (
const auto & [
name, var] : model.output_variables())
453 NEML2Utils::MOOSEIOType::MATERIAL,
462 const auto [param_types, params] = getInputParameterMapping<NEML2Utils::MOOSEIOType, std::string>(
463 "parameter_types",
"parameters");
467 if (model.named_parameters().count(params[i]) == 0)
468 paramError(
"parameters",
"The neml2 parameter ", params[i],
" does not exist.");
469 const auto & param = model.get_parameter(params[i]);
477 const auto derivs = getParam<std::vector<std::vector<std::string>>>(
"derivatives");
481 if (derivs[i].size() != 2)
482 paramError(
"derivatives",
"The length of each pair in derivatives must be 2.");
483 if (model.output_variables().count(derivs[i][0]) == 0)
484 paramError(
"derivatives",
"The NEML2 output variable ", derivs[i][0],
" does not exist.");
485 if (model.input_variables().count(derivs[i][1]) == 0)
486 paramError(
"derivatives",
"The NEML2 input variable ", derivs[i][1],
" does not exist.");
488 const auto & y = derivs[i][0];
489 const auto & x = derivs[i][1];
491 _derivs.push_back({deriv_name, y, x});
498 const auto derivs = getParam<std::vector<std::vector<std::string>>>(
"parameter_derivatives");
502 if (derivs[i].size() != 2)
504 "The length of each pair in parameter_derivatives must be 2.");
505 if (model.output_variables().count(derivs[i][0]) == 0)
507 "parameter_derivatives",
"The NEML2 output variable ", derivs[i][0],
" does not exist.");
508 if (model.named_parameters().count(derivs[i][1]) == 0)
509 paramError(
"parameter_derivatives",
"The NEML2 parameter ", derivs[i][1],
" does not exist.");
511 const auto & y = derivs[i][0];
512 const auto & x = derivs[i][1];
528 const int width = 79;
531 _console << COLOR_CYAN << std::setw(width) << std::setfill(
'*') << std::left
532 <<
"NEML2 MATERIAL MODEL SUMMARY BEGIN " << std::setfill(
' ') << COLOR_DEFAULT
536 _console <<
"NEML2 input file location: " <<
fname() << std::endl;
540 _console << COLOR_CYAN << std::setw(width) << std::setfill(
'-') << std::left
541 <<
"Material model structure " << std::setfill(
' ') << COLOR_DEFAULT << std::endl;
547 _console << COLOR_CYAN << std::setw(width) << std::setfill(
'-') << std::left
548 <<
"Transfer between MOOSE and NEML2 " << std::setfill(
' ') << COLOR_DEFAULT
551 _console <<
"MOOSE --> NEML2" << std::endl;
554 for (
const auto & input :
_inputs)
555 _console <<
" - " << (input.history_order > 0 ? (
"(old) " + input.name) : input.name) <<
" (" 559 for (
const auto & param :
_params)
561 << param.neml2_type <<
")" << std::endl;
563 _console <<
"MOOSE <-- NEML2" << std::endl;
566 for (
const auto & output :
_outputs)
567 _console <<
" - " << output.name << std::endl;
575 _console <<
" - " << param_deriv.name << std::endl;
578 _console << COLOR_CYAN << std::setw(width) << std::setfill(
'*') << std::left
579 <<
"NEML2 MATERIAL MODEL SUMMARY END " << std::setfill(
' ') << COLOR_DEFAULT << std::endl
589 std::size_t max_moose_name_length = 0;
590 for (
const auto & input :
_inputs)
592 auto n = input.name.size();
593 if (input.history_order > 0)
595 max_moose_name_length =
std::max(max_moose_name_length, n);
597 for (
const auto & param :
_params)
598 max_moose_name_length =
std::max(max_moose_name_length, param.name.size());
599 for (
const auto & output :
_outputs)
600 max_moose_name_length =
std::max(max_moose_name_length, output.name.size());
602 max_moose_name_length =
std::max(max_moose_name_length,
deriv.name.size());
604 max_moose_name_length =
std::max(max_moose_name_length, param_deriv.name.size());
605 return max_moose_name_length;
607 #endif // NEML2_ENABLED
std::string name(const ElemQuality q)
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
std::vector< DerivativeMapping > _param_derivs
MOOSE-NEML2 parameter derivative mappings.
ActionWarehouse & _awh
Reference to ActionWarehouse where we store object build by actions.
std::vector< std::string > _cli_args
List of cli-args.
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Factory & _factory
The Factory associated with the MooseApp.
const FileName & fname() const
InputParameterWarehouse & getInputParameterWarehouse()
Get the InputParameterWarehouse for MooseObjects.
std::ios_base::fmtflags flags() const
Return the current flags.
std::vector< DerivativeMapping > _derivs
MOOSE-NEML2 derivative mappings.
const InputParameters & parameters() const
Get the parameters of the object.
std::map< MaterialPropertyName, std::vector< OutputName > > _export_output_targets
Material property additional outputs.
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Action to set up NEML2 objects.
const MaterialPropertyName derivativePropertyNameFirst(const MaterialPropertyName &base, const SymbolName &c1) const
Helper functions to generate the material property names for the first derivatives.
Input parameters common to all block-restricted NEML2Actions.
const std::map< neml2::TensorType, std::string > tensor_type_map
MooseObjectName uniqueActionName() const
The unique name for accessing input parameters of this action in the InputParameterWarehouse.
void setupParameterDerivativeMappings(const neml2::Model &)
Set up MOOSE-NEML2 parameter derivative mappings.
std::string stringify(MOOSEIOType type)
auto max(const L &left, const R &right)
const std::vector< SubdomainName > _block
Blocks this sub-block action applies to.
virtual void act() override
Method to add objects to the simulation or perform other setup tasks.
const UserObjectName _executor_name
Name of the NEML2Executor user object.
const std::string & name() const
Get the name of the class.
Real deriv(unsigned n, unsigned alpha, unsigned beta, Real x)
std::shared_ptr< neml2::Model > _model
The neml2 model.
void printSummary() const
Print a summary of the NEML2 model.
const std::string & type() const
Get the type of this class.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
const std::string & _current_task
The current action (even though we have separate instances for each action)
std::map< MaterialPropertyName, MaterialPropertyName > _initialize_output_values
Material property initial conditions.
const std::map< std::pair< neml2::TensorType, neml2::TensorType >, neml2::TensorType > deriv_type_map
MooseApp & _app
The MOOSE application this is associated with.
void setupParameterMappings(const neml2::Model &)
Set up MOOSE-NEML2 model parameter mappings.
FileName _fname
Name of the NEML2 input file.
const NEML2ActionCommon & getCommonAction() const
NEML2Action(const InputParameters &)
NEML2Utils::MOOSEIOType inferMOOSEIOType(const neml2::VariableName &name, const neml2::TensorType &type) const
Infer the MOOSE IO type from the variable name and type.
void assertNEML2Enabled()
Assert that NEML2 is enabled.
std::shared_ptr< neml2::Model > getModel(neml2::Factory &factory, const std::string &name, neml2::Dtype dtype=neml2::kFloat64)
Get the NEML2 Model.
void setupInputMappings(const neml2::Model &)
Set up MOOSE-NEML2 input variable mappings.
void setupDerivativeMappings(const neml2::Model &)
Set up MOOSE-NEML2 derivative mappings.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
static InputParameters validParams()
std::shared_ptr< FEProblemBase > & _problem
Convenience reference to a problem this action works on.
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
std::vector< std::string > _skip_input_variables
Input variables to skip (i.e., not to set up mappings for)
void setupOutputMappings(const neml2::Model &)
Set up MOOSE-NEML2 output variable mappings.
const UserObjectName _idx_generator_name
Name of the NEML2BatchIndexGenerator user object.
registerMooseAction("MooseApp", NEML2Action, "parse_neml2")
std::vector< const T * > getActions()
Retrieve all actions in a specific type ordered by their names.
std::size_t getLongestMOOSEName() const
Get the maximum length of all MOOSE names (for printing purposes)
std::vector< VariableMapping > _outputs
MOOSE-NEML2 output variable mappings.
std::vector< ParameterMapping > _params
MOOSE-NEML2 model parameter mappings.
auto index_range(const T &sizable)
std::vector< VariableMapping > _inputs
MOOSE-NEML2 input variable mappings.
static InputParameters commonParams()
Parameters that can be specified EITHER under the common area OR under sub-blocks.
static std::string obscureObjectName(const std::string &name, const std::string &prefix, const std::string &suffix, const std::string &block)