LCOV - code coverage report
Current view: top level - src/neml2/actions - NEML2Action.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 260 350 74.3 %
Date: 2025-07-17 01:28:37 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          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/base/Parser.h"
      19             : #endif
      20             : 
      21             : registerMooseAction("MooseApp", NEML2Action, "parse_neml2");
      22             : registerMooseAction("MooseApp", NEML2Action, "add_material");
      23             : registerMooseAction("MooseApp", NEML2Action, "add_user_object");
      24             : 
      25             : #ifdef NEML2_ENABLED
      26             : // NEML2 variable type --> MOOSE type
      27             : const std::map<neml2::TensorType, std::string> tensor_type_map = {
      28             :     {neml2::TensorType::kScalar, "Real"},
      29             :     {neml2::TensorType::kSR2, "SymmetricRankTwoTensor"},
      30             :     {neml2::TensorType::kR2, "RankTwoTensor"},
      31             :     {neml2::TensorType::kSSR4, "SymmetricRankFourTensor"},
      32             :     {neml2::TensorType::kR4, "RankFourTensor"},
      33             :     {neml2::TensorType::kRot, "RealVectorValue"}};
      34             : // NEML2 (output, input) type --> NEML2 derivative type
      35             : const std::map<std::pair<neml2::TensorType, neml2::TensorType>, neml2::TensorType> deriv_type_map =
      36             :     {
      37             :         {{neml2::TensorType::kScalar, neml2::TensorType::kScalar}, neml2::TensorType::kScalar},
      38             :         {{neml2::TensorType::kSR2, neml2::TensorType::kSR2}, neml2::TensorType::kSSR4},
      39             :         {{neml2::TensorType::kSR2, neml2::TensorType::kScalar}, neml2::TensorType::kSR2},
      40             :         {{neml2::TensorType::kScalar, neml2::TensorType::kSR2}, neml2::TensorType::kSR2},
      41             :         {{neml2::TensorType::kR2, neml2::TensorType::kR2}, neml2::TensorType::kR4},
      42             :         {{neml2::TensorType::kR2, neml2::TensorType::kScalar}, neml2::TensorType::kR2},
      43             :         {{neml2::TensorType::kScalar, neml2::TensorType::kR2}, neml2::TensorType::kR2},
      44             : };
      45             : #endif
      46             : 
      47             : InputParameters
      48         225 : NEML2Action::validParams()
      49             : {
      50         225 :   InputParameters params = NEML2ActionCommon::commonParams();
      51         225 :   params.addClassDescription(NEML2Utils::docstring("Set up the NEML2 material model"));
      52         225 :   params.addParam<std::string>(
      53             :       "executor_name",
      54         450 :       NEML2Utils::docstring("Name of the NEML2ModelExecutor user object. The default name is "
      55             :                             "'neml2_<model-name>_<block-name>' where <model-name> is the NEML2 "
      56             :                             "model's name, and <block-name> is this action sub-block's name."));
      57         225 :   params.addParam<std::string>(
      58             :       "batch_index_generator_name",
      59         450 :       NEML2Utils::docstring(
      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, "
      62             :           "and <block-name> is this action sub-block's name."));
      63         225 :   params.addParam<std::vector<SubdomainName>>(
      64             :       "block",
      65             :       {},
      66         450 :       NEML2Utils::docstring("List of blocks (subdomains) where the material model is defined"));
      67         225 :   return params;
      68           0 : }
      69             : 
      70          22 : NEML2Action::NEML2Action(const InputParameters & params)
      71             :   : Action(params),
      72          66 :     _executor_name(isParamValid("executor_name")
      73          88 :                        ? getParam<std::string>("executor_name")
      74          44 :                        : "neml2_" + getParam<std::string>("model") + "_" + name()),
      75          66 :     _idx_generator_name(isParamValid("batch_index_generator_name")
      76          88 :                             ? getParam<std::string>("batch_index_generator_name")
      77          44 :                             : "neml2_index_" + getParam<std::string>("model") + "_" + name()),
      78          44 :     _block(getParam<std::vector<SubdomainName>>("block"))
      79             : {
      80          22 :   NEML2Utils::assertNEML2Enabled();
      81             : 
      82             :   // Apply parameters under the common area, i.e., under [NEML2]
      83          22 :   const auto & all_params = _app.getInputParameterWarehouse().getInputParameters();
      84          22 :   auto & sub_block_params = *(all_params.find(uniqueActionName())->second.get());
      85          22 :   const auto & common_action = getCommonAction();
      86          22 :   sub_block_params.applyParameters(common_action.parameters());
      87             : 
      88             :   // Set up optional output variable initialization
      89          22 :   auto init_vars = getParam<std::vector<MaterialPropertyName>>("initialize_outputs");
      90          22 :   auto init_vals = getParam<std::vector<MaterialPropertyName>>("initialize_output_values");
      91          22 :   if (init_vars.size() != init_vals.size())
      92           0 :     paramError("initialize_outputs",
      93             :                "initialize_outputs should have the same length as initialize_output_values");
      94          22 :   for (auto i : index_range(init_vars))
      95           0 :     _initialize_output_values[init_vars[i]] = init_vals[i];
      96             : 
      97             :   // Set up additional outputs for each requested material property
      98          22 :   auto outputs = getParam<std::vector<MaterialPropertyName>>("export_outputs");
      99          22 :   auto output_targets = getParam<std::vector<std::vector<OutputName>>>("export_output_targets");
     100          22 :   if (outputs.size() != output_targets.size())
     101           0 :     paramError("export_outputs",
     102             :                "export_outputs should have the same length as export_output_targets");
     103          76 :   for (auto i : index_range(outputs))
     104          54 :     _export_output_targets[outputs[i]] = output_targets[i];
     105             : 
     106             : #ifdef NEML2_ENABLED
     107             :   // File name and CLI args
     108          22 :   _fname = getParam<DataFileName>("input");
     109          22 :   _cli_args = getParam<std::vector<std::string>>("cli_args");
     110             : 
     111             :   // Load input file
     112          22 :   auto factory = neml2::load_input(std::string(_fname), neml2::utils::join(_cli_args, " "));
     113          22 :   _model = NEML2Utils::getModel(*factory, getParam<std::string>("model"));
     114             : #endif
     115          22 : }
     116             : 
     117             : const NEML2ActionCommon &
     118          22 : NEML2Action::getCommonAction() const
     119             : {
     120          22 :   auto common_block = _awh.getActions<NEML2ActionCommon>();
     121             :   mooseAssert(common_block.size() == 1, "There must exist one and only one common NEML2 action.");
     122          44 :   return *common_block[0];
     123          22 : }
     124             : 
     125             : #ifndef NEML2_ENABLED
     126             : 
     127             : void
     128           0 : NEML2Action::act()
     129             : {
     130           0 : }
     131             : 
     132             : #else
     133             : 
     134             : void
     135          66 : NEML2Action::act()
     136             : {
     137          66 :   if (_current_task == "parse_neml2")
     138             :   {
     139          22 :     if (_app.parameters().have_parameter<bool>("parse_neml2_only"))
     140          22 :       if (!_app.parameters().get<bool>("parse_neml2_only"))
     141          22 :         return;
     142           0 :     printSummary();
     143             :   }
     144             : 
     145          44 :   if (_current_task == "add_user_object")
     146             :   {
     147          22 :     setupInputMappings(*_model);
     148          22 :     setupParameterMappings(*_model);
     149          22 :     setupOutputMappings(*_model);
     150          22 :     setupDerivativeMappings(*_model);
     151          22 :     setupParameterDerivativeMappings(*_model);
     152             : 
     153          22 :     printSummary();
     154             : 
     155             :     // MOOSEToNEML2 input gatherers
     156          22 :     std::vector<UserObjectName> gatherers;
     157          57 :     for (const auto & input : _inputs)
     158             :     {
     159          35 :       if (input.moose.type == MOOSEIOType::MATERIAL)
     160             :       {
     161          26 :         auto obj_name = "__moose(" + input.moose.name + ")->neml2(" +
     162          39 :                         neml2::utils::stringify(input.neml2.name) + ")_" + name() + "__";
     163          13 :         if (!tensor_type_map.count(input.neml2.type))
     164           0 :           mooseError("NEML2 type ", input.neml2.type, " not yet mapped to MOOSE");
     165          13 :         auto obj_moose_type = tensor_type_map.at(input.neml2.type) + "MaterialProperty";
     166          13 :         if (input.neml2.name.is_old_force() || input.neml2.name.is_old_state())
     167           0 :           obj_moose_type = "Old" + obj_moose_type;
     168          13 :         auto obj_type = "MOOSE" + obj_moose_type + "ToNEML2";
     169          13 :         auto obj_params = _factory.getValidParams(obj_type);
     170          13 :         obj_params.set<MaterialPropertyName>("from_moose") = input.moose.name;
     171          13 :         obj_params.set<std::string>("to_neml2") = neml2::utils::stringify(input.neml2.name);
     172          13 :         obj_params.set<std::vector<SubdomainName>>("block") = _block;
     173          13 :         _problem->addUserObject(obj_type, obj_name, obj_params);
     174          13 :         gatherers.push_back(obj_name);
     175          13 :       }
     176          22 :       else if (input.moose.type == MOOSEIOType::VARIABLE)
     177             :       {
     178          44 :         auto obj_name = "__moose(" + input.moose.name + ")->neml2(" +
     179          66 :                         neml2::utils::stringify(input.neml2.name) + ")_" + name() + "__";
     180          22 :         std::string obj_moose_type = "Variable";
     181          22 :         if (input.neml2.name.is_old_force() || input.neml2.name.is_old_state())
     182           0 :           obj_moose_type = "Old" + obj_moose_type;
     183          22 :         auto obj_type = "MOOSE" + obj_moose_type + "ToNEML2";
     184          22 :         auto obj_params = _factory.getValidParams(obj_type);
     185          44 :         obj_params.set<std::vector<VariableName>>("from_moose") = {input.moose.name};
     186          22 :         obj_params.set<std::string>("to_neml2") = neml2::utils::stringify(input.neml2.name);
     187          22 :         obj_params.set<std::vector<SubdomainName>>("block") = _block;
     188          22 :         _problem->addUserObject(obj_type, obj_name, obj_params);
     189          22 :         gatherers.push_back(obj_name);
     190          22 :       }
     191           0 :       else if (input.moose.type == MOOSEIOType::POSTPROCESSOR)
     192             :       {
     193           0 :         auto obj_name = "__moose(" + input.moose.name + ")->neml2(" +
     194           0 :                         neml2::utils::stringify(input.neml2.name) + ")" + name() + "__";
     195           0 :         auto obj_moose_type = std::string("Postprocessor");
     196           0 :         if (input.neml2.name.is_old_force() || input.neml2.name.is_old_state())
     197           0 :           obj_moose_type = "Old" + obj_moose_type;
     198           0 :         auto obj_type = "MOOSE" + obj_moose_type + "ToNEML2";
     199           0 :         auto obj_params = _factory.getValidParams(obj_type);
     200           0 :         obj_params.set<PostprocessorName>("from_moose") = input.moose.name;
     201           0 :         obj_params.set<std::string>("to_neml2") = neml2::utils::stringify(input.neml2.name);
     202           0 :         _problem->addUserObject(obj_type, obj_name, obj_params);
     203           0 :         gatherers.push_back(obj_name);
     204           0 :       }
     205             :       else
     206           0 :         paramError("moose_input_types",
     207             :                    "Unsupported type corresponding to the moose input ",
     208           0 :                    input.moose.name);
     209             :     }
     210             : 
     211             :     // MOOSEToNEML2 parameter gatherers
     212          22 :     std::vector<UserObjectName> param_gatherers;
     213          24 :     for (const auto & param : _params)
     214             :     {
     215           2 :       if (param.moose.type == MOOSEIOType::MATERIAL)
     216             :       {
     217             :         auto obj_name =
     218           1 :             "__moose(" + param.moose.name + ")->neml2(" + param.neml2.name + ")_" + name() + "__";
     219           1 :         if (!tensor_type_map.count(param.neml2.type))
     220           0 :           mooseError("NEML2 type ", param.neml2.type, " not yet mapped to MOOSE");
     221           1 :         auto obj_moose_type = tensor_type_map.at(param.neml2.type);
     222           1 :         auto obj_type = "MOOSE" + obj_moose_type + "MaterialPropertyToNEML2";
     223           1 :         auto obj_params = _factory.getValidParams(obj_type);
     224           1 :         obj_params.set<MaterialPropertyName>("from_moose") = param.moose.name;
     225           1 :         obj_params.set<std::string>("to_neml2") = param.neml2.name;
     226           1 :         obj_params.set<std::vector<SubdomainName>>("block") = _block;
     227           1 :         _problem->addUserObject(obj_type, obj_name, obj_params);
     228           1 :         param_gatherers.push_back(obj_name);
     229           1 :       }
     230           1 :       else if (param.moose.type == MOOSEIOType::VARIABLE)
     231             :       {
     232             :         auto obj_name =
     233           1 :             "__moose(" + param.moose.name + ")->neml2(" + param.neml2.name + ")_" + name() + "__";
     234           1 :         auto obj_type = "MOOSEVariableToNEML2";
     235           1 :         auto obj_params = _factory.getValidParams(obj_type);
     236           2 :         obj_params.set<std::vector<VariableName>>("from_moose") = {param.moose.name};
     237           1 :         obj_params.set<std::string>("to_neml2") = neml2::utils::stringify(param.neml2.name);
     238           1 :         obj_params.set<std::vector<SubdomainName>>("block") = _block;
     239           1 :         _problem->addUserObject(obj_type, obj_name, obj_params);
     240           1 :         param_gatherers.push_back(obj_name);
     241           1 :       }
     242           0 :       else if (param.moose.type == MOOSEIOType::POSTPROCESSOR)
     243             :       {
     244             :         auto obj_name =
     245           0 :             "__moose(" + param.moose.name + ")->neml2(" + param.neml2.name + ")" + name() + "__";
     246           0 :         auto obj_moose_type = std::string("Postprocessor");
     247           0 :         auto obj_type = "MOOSE" + obj_moose_type + "ToNEML2";
     248           0 :         auto obj_params = _factory.getValidParams(obj_type);
     249           0 :         obj_params.set<PostprocessorName>("from_moose") = param.moose.name;
     250           0 :         obj_params.set<std::string>("to_neml2") = param.neml2.name;
     251           0 :         _problem->addUserObject(obj_type, obj_name, obj_params);
     252           0 :         param_gatherers.push_back(obj_name);
     253           0 :       }
     254             :       else
     255           0 :         paramError("moose_parameter_types",
     256             :                    "Unsupported type corresponding to the moose parameter ",
     257           0 :                    param.moose.name);
     258             :     }
     259             : 
     260             :     // The index generator UO
     261             :     {
     262          22 :       auto type = "NEML2BatchIndexGenerator";
     263          22 :       auto params = _factory.getValidParams(type);
     264          22 :       params.applyParameters(parameters());
     265          22 :       _problem->addUserObject(type, _idx_generator_name, params);
     266          22 :     }
     267             : 
     268             :     // The Executor UO
     269             :     {
     270          22 :       auto type = "NEML2ModelExecutor";
     271          22 :       auto params = _factory.getValidParams(type);
     272          22 :       params.applyParameters(parameters());
     273          22 :       params.set<UserObjectName>("batch_index_generator") = _idx_generator_name;
     274          22 :       params.set<std::vector<UserObjectName>>("gatherers") = gatherers;
     275          22 :       params.set<std::vector<UserObjectName>>("param_gatherers") = param_gatherers;
     276          22 :       _problem->addUserObject(type, _executor_name, params);
     277          22 :     }
     278          22 :   }
     279             : 
     280          44 :   if (_current_task == "add_material")
     281             :   {
     282             :     // NEML2ToMOOSE output retrievers
     283          57 :     for (const auto & output : _outputs)
     284             :     {
     285          35 :       if (output.moose.type == MOOSEIOType::MATERIAL)
     286             :       {
     287          70 :         auto obj_name = "__neml2(" + neml2::utils::stringify(output.neml2.name) + ")->moose(" +
     288          70 :                         output.moose.name + ")_" + name() + "__";
     289          35 :         if (!tensor_type_map.count(output.neml2.type))
     290           0 :           mooseError("NEML2 type ", output.neml2.type, " not yet mapped to MOOSE");
     291          35 :         auto obj_type = "NEML2ToMOOSE" + tensor_type_map.at(output.neml2.type) + "MaterialProperty";
     292          35 :         auto obj_params = _factory.getValidParams(obj_type);
     293          35 :         obj_params.set<UserObjectName>("neml2_executor") = _executor_name;
     294          35 :         obj_params.set<MaterialPropertyName>("to_moose") = output.moose.name;
     295          35 :         obj_params.set<std::string>("from_neml2") = neml2::utils::stringify(output.neml2.name);
     296          35 :         obj_params.set<std::vector<SubdomainName>>("block") = _block;
     297          35 :         if (_initialize_output_values.count(output.moose.name))
     298           0 :           obj_params.set<MaterialPropertyName>("moose_material_property_init") =
     299           0 :               _initialize_output_values[output.moose.name];
     300          35 :         if (_export_output_targets.count(output.moose.name))
     301          66 :           obj_params.set<std::vector<OutputName>>("outputs") =
     302          99 :               _export_output_targets[output.moose.name];
     303          35 :         _problem->addMaterial(obj_type, obj_name, obj_params);
     304          35 :       }
     305             :       else
     306           0 :         paramError("moose_output_types",
     307             :                    "Unsupported type corresponding to the moose output ",
     308           0 :                    output.moose.name);
     309             :     }
     310             : 
     311             :     // NEML2ToMOOSE derivative retrievers
     312          44 :     for (const auto & deriv : _derivs)
     313             :     {
     314          22 :       if (deriv.moose.type == MOOSEIOType::MATERIAL)
     315             :       {
     316          44 :         auto obj_name = "__neml2(d(" + neml2::utils::stringify(deriv.neml2.y.name) + ")/d(" +
     317          66 :                         neml2::utils::stringify(deriv.neml2.x.name) + "))->moose(" +
     318          44 :                         deriv.moose.name + ")_" + name() + "__";
     319          22 :         if (!deriv_type_map.count({deriv.neml2.y.type, deriv.neml2.x.type}))
     320           0 :           mooseError("NEML2 derivative type for d(",
     321           0 :                      deriv.neml2.y.type,
     322             :                      ")/d(",
     323           0 :                      deriv.neml2.x.type,
     324             :                      ") not yet mapped to MOOSE");
     325          22 :         auto deriv_type = deriv_type_map.at({deriv.neml2.y.type, deriv.neml2.x.type});
     326          22 :         if (!tensor_type_map.count(deriv_type))
     327           0 :           mooseError("NEML2 type ", deriv_type, " not yet mapped to MOOSE");
     328          22 :         auto obj_type = "NEML2ToMOOSE" + tensor_type_map.at(deriv_type) + "MaterialProperty";
     329          22 :         auto obj_params = _factory.getValidParams(obj_type);
     330          22 :         obj_params.set<UserObjectName>("neml2_executor") = _executor_name;
     331          22 :         obj_params.set<MaterialPropertyName>("to_moose") = deriv.moose.name;
     332          22 :         obj_params.set<std::string>("from_neml2") = neml2::utils::stringify(deriv.neml2.y.name);
     333          44 :         obj_params.set<std::string>("neml2_input_derivative") =
     334          66 :             neml2::utils::stringify(deriv.neml2.x.name);
     335          22 :         obj_params.set<std::vector<SubdomainName>>("block") = _block;
     336          22 :         if (_export_output_targets.count(deriv.moose.name))
     337          24 :           obj_params.set<std::vector<OutputName>>("outputs") =
     338          36 :               _export_output_targets[deriv.moose.name];
     339          22 :         _problem->addMaterial(obj_type, obj_name, obj_params);
     340          22 :       }
     341             :       else
     342           0 :         paramError("moose_derivative_types",
     343             :                    "Unsupported type corresponding to the moose derivative ",
     344           0 :                    deriv.moose.name);
     345             :     }
     346             : 
     347             :     // NEML2ToMOOSE parameter derivative retrievers
     348          22 :     for (const auto & param_deriv : _param_derivs)
     349             :     {
     350           0 :       if (param_deriv.moose.type == MOOSEIOType::MATERIAL)
     351             :       {
     352           0 :         auto obj_name = "__neml2(d(" + neml2::utils::stringify(param_deriv.neml2.y.name) + ")/d(" +
     353           0 :                         param_deriv.neml2.x.name + "))->moose(" + param_deriv.moose.name + ")_" +
     354           0 :                         name() + "__";
     355           0 :         if (!deriv_type_map.count({param_deriv.neml2.y.type, param_deriv.neml2.x.type}))
     356           0 :           mooseError("NEML2 derivative type for d(",
     357           0 :                      param_deriv.neml2.y.type,
     358             :                      ")/d(",
     359           0 :                      param_deriv.neml2.x.type,
     360             :                      ") not yet mapped to MOOSE");
     361           0 :         auto deriv_type = deriv_type_map.at({param_deriv.neml2.y.type, param_deriv.neml2.x.type});
     362           0 :         if (!tensor_type_map.count(deriv_type))
     363           0 :           mooseError("NEML2 type ", deriv_type, " not yet mapped to MOOSE");
     364           0 :         auto obj_type = "NEML2ToMOOSE" + tensor_type_map.at(deriv_type) + "MaterialProperty";
     365           0 :         auto obj_params = _factory.getValidParams(obj_type);
     366           0 :         obj_params.set<UserObjectName>("neml2_executor") = _executor_name;
     367           0 :         obj_params.set<MaterialPropertyName>("to_moose") = param_deriv.moose.name;
     368           0 :         obj_params.set<std::string>("from_neml2") =
     369           0 :             neml2::utils::stringify(param_deriv.neml2.y.name);
     370           0 :         obj_params.set<std::string>("neml2_parameter_derivative") = param_deriv.neml2.x.name;
     371           0 :         obj_params.set<std::vector<SubdomainName>>("block") = _block;
     372           0 :         if (_export_output_targets.count(param_deriv.moose.name))
     373           0 :           obj_params.set<std::vector<OutputName>>("outputs") =
     374           0 :               _export_output_targets[param_deriv.moose.name];
     375           0 :         _problem->addMaterial(obj_type, obj_name, obj_params);
     376           0 :       }
     377             :       else
     378           0 :         paramError("moose_parameter_derivative_types",
     379             :                    "Unsupported type corresponding to the moose parameter derivative ",
     380           0 :                    param_deriv.moose.name);
     381             :     }
     382             :   }
     383          23 : }
     384             : 
     385             : void
     386          22 : NEML2Action::setupInputMappings(const neml2::Model & model)
     387             : {
     388          22 :   const auto [moose_input_types, moose_inputs, neml2_inputs] =
     389             :       getInputParameterMapping<MOOSEIOType, std::string, std::string>(
     390          22 :           "moose_input_types", "moose_inputs", "neml2_inputs");
     391             : 
     392          57 :   for (auto i : index_range(moose_inputs))
     393             :   {
     394          35 :     auto neml2_input = NEML2Utils::parseVariableName(neml2_inputs[i]);
     395          35 :     _inputs.push_back({
     396          35 :         {moose_inputs[i], moose_input_types[i]},
     397          35 :         {neml2_input, model.input_variable(neml2_input).type()},
     398             :     });
     399          35 :   }
     400          92 : }
     401             : 
     402             : void
     403          22 : NEML2Action::setupParameterMappings(const neml2::Model & model)
     404             : {
     405          22 :   const auto [moose_param_types, moose_params, neml2_params] =
     406             :       getInputParameterMapping<MOOSEIOType, std::string, std::string>(
     407          22 :           "moose_parameter_types", "moose_parameters", "neml2_parameters");
     408             : 
     409          24 :   for (auto i : index_range(moose_params))
     410           4 :     _params.push_back({{moose_params[i], moose_param_types[i]},
     411           2 :                        {neml2_params[i], model.get_parameter(neml2_params[i]).type()}});
     412          26 : }
     413             : 
     414             : void
     415          22 : NEML2Action::setupOutputMappings(const neml2::Model & model)
     416             : {
     417          22 :   const auto [moose_output_types, moose_outputs, neml2_outputs] =
     418             :       getInputParameterMapping<MOOSEIOType, std::string, std::string>(
     419          22 :           "moose_output_types", "moose_outputs", "neml2_outputs");
     420             : 
     421          57 :   for (auto i : index_range(moose_outputs))
     422             :   {
     423          35 :     auto neml2_output = NEML2Utils::parseVariableName(neml2_outputs[i]);
     424          35 :     _outputs.push_back({
     425          35 :         {moose_outputs[i], moose_output_types[i]},
     426          35 :         {neml2_output, model.output_variable(neml2_output).type()},
     427             :     });
     428          35 :   }
     429          92 : }
     430             : 
     431             : void
     432          22 : NEML2Action::setupDerivativeMappings(const neml2::Model & model)
     433             : {
     434          22 :   const auto [moose_deriv_types, moose_derivs, neml2_derivs] =
     435             :       getInputParameterMapping<MOOSEIOType, std::string, std::vector<std::string>>(
     436          22 :           "moose_derivative_types", "moose_derivatives", "neml2_derivatives");
     437             : 
     438          44 :   for (auto i : index_range(moose_derivs))
     439             :   {
     440          22 :     if (neml2_derivs[i].size() != 2)
     441           0 :       paramError("neml2_derivatives", "The length of each pair in neml2_derivatives must be 2.");
     442             : 
     443          22 :     auto neml2_y = NEML2Utils::parseVariableName(neml2_derivs[i][0]);
     444          22 :     auto neml2_x = NEML2Utils::parseVariableName(neml2_derivs[i][1]);
     445          22 :     _derivs.push_back({
     446          22 :         {moose_derivs[i], moose_deriv_types[i]},
     447          22 :         {{neml2_y, model.output_variable(neml2_y).type()},
     448          22 :          {neml2_x, model.input_variable(neml2_x).type()}},
     449             :     });
     450          22 :   }
     451          88 : }
     452             : 
     453             : void
     454          22 : NEML2Action::setupParameterDerivativeMappings(const neml2::Model & model)
     455             : {
     456          22 :   const auto [moose_param_deriv_types, moose_param_derivs, neml2_param_derivs] =
     457             :       getInputParameterMapping<MOOSEIOType, std::string, std::vector<std::string>>(
     458             :           "moose_parameter_derivative_types",
     459             :           "moose_parameter_derivatives",
     460          22 :           "neml2_parameter_derivatives");
     461             : 
     462          22 :   for (auto i : index_range(moose_param_derivs))
     463             :   {
     464           0 :     if (neml2_param_derivs[i].size() != 2)
     465           0 :       paramError("neml2_parameter_derivatives",
     466             :                  "The length of each pair in neml2_parameter_derivatives must be 2.");
     467             : 
     468           0 :     auto neml2_y = NEML2Utils::parseVariableName(neml2_param_derivs[i][0]);
     469           0 :     auto neml2_x = neml2_param_derivs[i][1];
     470           0 :     _param_derivs.push_back({
     471           0 :         {moose_param_derivs[i], moose_param_deriv_types[i]},
     472           0 :         {{neml2_y, model.output_variable(neml2_y).type()},
     473           0 :          {neml2_x, model.get_parameter(neml2_x).type()}},
     474             :     });
     475           0 :   }
     476          22 : }
     477             : 
     478             : void
     479          22 : NEML2Action::printSummary() const
     480             : {
     481          22 :   if (!_app.parameters().have_parameter<bool>("parse_neml2_only"))
     482           0 :     return;
     483             : 
     484             :   // Save formatting of the output stream so that we can restore it later
     485          22 :   const auto flags = _console.flags();
     486             : 
     487             :   // Default width for the summary
     488          22 :   const int width = 79;
     489             : 
     490          22 :   _console << std::endl;
     491          22 :   _console << COLOR_CYAN << std::setw(width) << std::setfill('*') << std::left
     492          22 :            << "NEML2 MATERIAL MODEL SUMMARY BEGIN " << std::setfill(' ') << COLOR_DEFAULT
     493          22 :            << std::endl;
     494             : 
     495             :   // Metadata
     496          22 :   _console << "NEML2 input file location: " << fname() << std::endl;
     497          22 :   _console << "NEML2 action path:         " << parameters().blockFullpath() << std::endl;
     498             : 
     499             :   // List inputs, outputs, and parameters of the model
     500          22 :   _console << COLOR_CYAN << std::setw(width) << std::setfill('-') << std::left
     501          22 :            << "Material model structure " << std::setfill(' ') << COLOR_DEFAULT << std::endl;
     502          22 :   _console << *_model;
     503             : 
     504             :   // List transfer between MOOSE and NEML2
     505          22 :   if (!_app.parameters().get<bool>("parse_neml2_only"))
     506             :   {
     507          22 :     _console << COLOR_CYAN << std::setw(width) << std::setfill('-') << std::left
     508          22 :              << "Transfer between MOOSE and NEML2 " << std::setfill(' ') << COLOR_DEFAULT
     509          22 :              << std::endl;
     510             : 
     511             :     // Figure out the longest name length so that we could align the arrows
     512          22 :     const auto max_moose_name_length = getLongestMOOSEName();
     513             : 
     514             :     // List input transfer, MOOSE -> NEML2
     515          57 :     for (const auto & input : _inputs)
     516             :     {
     517          35 :       _console << std::setw(max_moose_name_length) << std::right
     518          70 :                << (input.neml2.name.is_old_force() || input.neml2.name.is_old_state()
     519          70 :                        ? ("(old) " + input.moose.name)
     520          35 :                        : input.moose.name)
     521          35 :                << " --> " << input.neml2.name << std::endl;
     522             :     }
     523             : 
     524             :     // List parameter transfer, MOOSE -> NEML2
     525          24 :     for (const auto & param : _params)
     526           2 :       _console << std::setw(max_moose_name_length) << std::right << param.moose.name << " --> "
     527           2 :                << param.neml2.name << std::endl;
     528             : 
     529             :     // List output transfer, NEML2 -> MOOSE
     530          57 :     for (const auto & output : _outputs)
     531          35 :       _console << std::setw(max_moose_name_length) << std::right << output.moose.name << " <-- "
     532          35 :                << output.neml2.name << std::endl;
     533             : 
     534             :     // List derivative transfer, NEML2 -> MOOSE
     535          44 :     for (const auto & deriv : _derivs)
     536          22 :       _console << std::setw(max_moose_name_length) << std::right << deriv.moose.name << " <-- d("
     537          22 :                << deriv.neml2.y.name << ")/d(" << deriv.neml2.x.name << ")" << std::endl;
     538             : 
     539             :     // List parameter derivative transfer, NEML2 -> MOOSE
     540          22 :     for (const auto & param_deriv : _param_derivs)
     541           0 :       _console << std::setw(max_moose_name_length) << std::right << param_deriv.moose.name
     542           0 :                << " <-- d(" << param_deriv.neml2.y.name << ")/d(" << param_deriv.neml2.x.name << ")"
     543           0 :                << std::endl;
     544             :   }
     545             : 
     546          22 :   _console << COLOR_CYAN << std::setw(width) << std::setfill('*') << std::left
     547          22 :            << "NEML2 MATERIAL MODEL SUMMARY END " << std::setfill(' ') << COLOR_DEFAULT << std::endl
     548          22 :            << std::endl;
     549             : 
     550             :   // Restore the formatting of the output stream
     551          22 :   _console.flags(flags);
     552             : }
     553             : 
     554             : std::size_t
     555          22 : NEML2Action::getLongestMOOSEName() const
     556             : {
     557          22 :   std::size_t max_moose_name_length = 0;
     558          57 :   for (const auto & input : _inputs)
     559          35 :     max_moose_name_length =
     560          70 :         std::max(max_moose_name_length,
     561          70 :                  input.neml2.name.is_old_force() || input.neml2.name.is_old_state()
     562          70 :                      ? input.moose.name.size() + 6
     563          35 :                      : input.moose.name.size()); // 6 is the length of "(old) "
     564          24 :   for (const auto & param : _params)
     565           2 :     max_moose_name_length = std::max(max_moose_name_length, param.moose.name.size());
     566          57 :   for (const auto & output : _outputs)
     567          35 :     max_moose_name_length = std::max(max_moose_name_length, output.moose.name.size());
     568          44 :   for (const auto & deriv : _derivs)
     569          22 :     max_moose_name_length = std::max(max_moose_name_length, deriv.moose.name.size());
     570          22 :   for (const auto & param_deriv : _param_derivs)
     571           0 :     max_moose_name_length = std::max(max_moose_name_length, param_deriv.moose.name.size());
     572          22 :   return max_moose_name_length;
     573             : }
     574             : #endif // NEML2_ENABLED

Generated by: LCOV version 1.14