LCOV - code coverage report
Current view: top level - src/actions - AddVariableAction.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 124 145 85.5 %
Date: 2026-05-29 20:35:17 Functions: 10 12 83.3 %
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             : // MOOSE includes
      11             : #include "AddVariableAction.h"
      12             : #include "FEProblem.h"
      13             : #include "Factory.h"
      14             : #include "MooseEnum.h"
      15             : #include "MooseEigenSystem.h"
      16             : #include "MooseObjectAction.h"
      17             : #include "MooseMesh.h"
      18             : #include "CopyNodalVarsAction.h"
      19             : 
      20             : #include "libmesh/string_to_enum.h"
      21             : #include "libmesh/fe_interface.h"
      22             : 
      23             : using namespace libMesh;
      24             : 
      25             : registerMooseAction("MooseApp", AddVariableAction, "add_variable");
      26             : 
      27             : InputParameters
      28     2148837 : AddVariableAction::validParams()
      29             : {
      30     2148837 :   auto params = MooseObjectAction::validParams();
      31     4297674 :   params.addClassDescription("Add a non-linear variable to the simulation.");
      32             : 
      33             :   // The user may specify a type in the Variables block, but if they don't we'll just use all the
      34             :   // parameters available from MooseVariableBase
      35     4297674 :   params.set<std::string>("type") = "MooseVariableBase";
      36             : 
      37             :   // The below is for backwards compatibility
      38     6446511 :   params.addParam<MooseEnum>("family",
      39     4297674 :                              AddVariableAction::getNonlinearVariableFamilies(),
      40             :                              "Specifies the family of FE shape functions to use for this variable");
      41     6446511 :   params.addParam<MooseEnum>("order",
      42     4297674 :                              AddVariableAction::getNonlinearVariableOrders(),
      43             :                              "Specifies the order of the FE shape function to use for this "
      44             :                              "variable (additional orders not listed are allowed)");
      45     8595348 :   params.addParam<std::vector<Real>>("scaling",
      46             :                                      "Specifies a scaling factor to apply to this variable");
      47     8595348 :   params.addParam<std::vector<Real>>("initial_condition",
      48             :                                      "Specifies a constant initial condition for this variable");
      49    10744185 :   params.transferParam<std::string>(CopyNodalVarsAction::validParams(), "initial_from_file_var");
      50     2148837 :   return params;
      51           0 : }
      52             : 
      53      123869 : AddVariableAction::AddVariableAction(const InputParameters & params)
      54             :   : MooseObjectAction(params),
      55      123869 :     _fe_type(feType(params)),
      56      123869 :     _scalar_var(_fe_type.family == SCALAR),
      57      123869 :     _fv_var(false),
      58      123869 :     _components(1)
      59             : {
      60      123869 : }
      61             : 
      62             : MooseEnum
      63     2148926 : AddVariableAction::getNonlinearVariableFamilies()
      64             : {
      65             :   return MooseEnum("LAGRANGE MONOMIAL HERMITE SCALAR HIERARCHIC CLOUGH XYZ SZABAB BERNSTEIN "
      66             :                    "L2_LAGRANGE L2_HIERARCHIC NEDELEC_ONE LAGRANGE_VEC MONOMIAL_VEC "
      67             :                    "RAVIART_THOMAS RATIONAL_BERNSTEIN SIDE_HIERARCHIC L2_HIERARCHIC_VEC "
      68             :                    "L2_LAGRANGE_VEC L2_RAVIART_THOMAS",
      69     8595704 :                    "LAGRANGE");
      70             : }
      71             : 
      72             : MooseEnum
      73     2167734 : AddVariableAction::getNonlinearVariableOrders()
      74             : {
      75             :   return MooseEnum(
      76             :       "CONSTANT FIRST SECOND THIRD FOURTH FIFTH SIXTH SEVENTH EIGHTH NINTH TENTH ELEVENTH TWELFTH "
      77             :       "THIRTEENTH FOURTEENTH FIFTEENTH SIXTEENTH SEVENTEENTH EIGHTTEENTH NINETEENTH TWENTIETH "
      78             :       "TWENTYFIRST TWENTYSECOND TWENTYTHIRD TWENTYFOURTH TWENTYFIFTH TWENTYSIXTH TWENTYSEVENTH "
      79             :       "TWENTYEIGHTH TWENTYNINTH THIRTIETH THIRTYFIRST THIRTYSECOND THIRTYTHIRD THIRTYFOURTH "
      80             :       "THIRTYFIFTH THIRTYSIXTH THIRTYSEVENTH THIRTYEIGHTH THIRTYNINTH FORTIETH FORTYFIRST "
      81             :       "FORTYSECOND FORTYTHIRD",
      82             :       "FIRST",
      83     8670936 :       true);
      84             : }
      85             : 
      86             : FEType
      87      123963 : AddVariableAction::feType(const InputParameters & params)
      88             : {
      89      123963 :   return {Utility::string_to_enum<Order>(params.get<MooseEnum>("order")),
      90      123963 :           Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"))};
      91             : }
      92             : 
      93             : void
      94      120370 : AddVariableAction::init()
      95             : {
      96      120370 :   _components = _moose_object_pars.get<unsigned int>("components");
      97      120370 :   if (_components == 0)
      98           0 :     mooseError("There must be at least one variable component, but somehow 0 has been specified");
      99             : 
     100             :   // We have to do some sanity checks because of our work to maintain backwards compatibility.
     101             :   // `family`, `order`, and `scaling` are all parameters duplicated between this action and the
     102             :   // `MooseVariable*` object itself. Consequently during input file parsing, the params objects for
     103             :   // both the action and MooseVariable object can be populated with the exact same parameters.
     104             :   // However, some applications actually create their variables solely through creation and setting
     105             :   // of `AddVariableAction` parameters which means that the `MooseVariableBase*` params will never
     106             :   // be populated. So we should apply the parameters directly from the action. There should be no
     107             :   // case in which both params objects get set by the user and they have different values
     108             : 
     109      655492 :   if (isParamSetByUser("family") && _moose_object_pars.isParamSetByUser("family") &&
     110      294382 :       !getParam<MooseEnum>("family").compareCurrent(_moose_object_pars.get<MooseEnum>("family")))
     111           0 :     mooseError("Both the MooseVariable* and Add*VariableAction parameters objects have had the "
     112             :                "`family` parameter set, and they are different values: ",
     113           0 :                _moose_object_pars.get<MooseEnum>("family"),
     114             :                " and ",
     115             :                getParam<MooseEnum>("family"),
     116             :                " respectively. I don't know how you achieved this, but you need to rectify it.");
     117             : 
     118      660475 :   if (isParamSetByUser("order") && _moose_object_pars.isParamSetByUser("order") &&
     119      299365 :       !getParam<MooseEnum>("order").compareCurrent(_moose_object_pars.get<MooseEnum>("order")))
     120           0 :     mooseError("Both the MooseVariable* and Add*VariableAction parameters objects have had the "
     121             :                "`order` parameter set, and they are different values: ",
     122           0 :                _moose_object_pars.get<MooseEnum>("order"),
     123             :                " and ",
     124             :                getParam<MooseEnum>("order"),
     125             :                " respectively. I don't know how you achieved this, but you need to rectify it.");
     126             : 
     127      482665 :   if (isParamSetByUser("scaling") && _moose_object_pars.isParamSetByUser("scaling") &&
     128      121555 :       getParam<std::vector<Real>>("scaling") !=
     129         285 :           _moose_object_pars.get<std::vector<Real>>("scaling"))
     130           0 :     mooseError("Both the MooseVariable* and Add*VariableAction parameters objects have had the "
     131             :                "`scaling` parameter set, and they are different values. I don't know how you "
     132             :                "achieved this, but you need to rectify it.");
     133             : 
     134      394454 :   if (isParamSetByUser("initial_condition") && isParamSetByUser("initial_from_file_var"))
     135           6 :     paramError("initial_condition",
     136             :                "Two initial conditions have been provided for the variable ",
     137           3 :                name(),
     138             :                " using the 'initial_condition' and 'initial_from_file_var' parameters. Please "
     139             :                "remove one of them.");
     140             : 
     141      240734 :   _moose_object_pars.applySpecificParameters(_pars, {"order", "family", "scaling"});
     142             : 
     143             :   // Determine the MooseVariable type
     144      120367 :   _fv_var = _moose_object_pars.get<bool>("fv");
     145      120367 :   const auto is_array = _components > 1 || _moose_object_pars.get<bool>("array");
     146      120367 :   if (_type == "MooseVariableBase")
     147      112440 :     _type = variableType(_fe_type, _fv_var, is_array);
     148      120367 :   if (_fv_var)
     149        6133 :     _problem->needFV();
     150             : 
     151             :   // Need static_cast to resolve overloads
     152      240734 :   _problem_add_var_method = static_cast<void (FEProblemBase::*)(
     153      120367 :       const std::string &, const std::string &, InputParameters &)>(&FEProblemBase::addVariable);
     154      120367 : }
     155             : 
     156             : void
     157      120370 : AddVariableAction::act()
     158             : {
     159             :   // If we've been called that means that current_task == "add_variable"
     160      120370 :   init();
     161             : 
     162             :   // Get necessary data for creating a variable
     163      120364 :   const auto var_name = varName();
     164      120364 :   addVariable(var_name);
     165             : 
     166             :   // Set the initial condition
     167      361020 :   if (isParamValid("initial_condition"))
     168             :   {
     169       33320 :     const auto & value = getParam<std::vector<Real>>("initial_condition");
     170       16660 :     createInitialConditionAction(value);
     171             :   }
     172      120340 : }
     173             : 
     174             : void
     175       16660 : AddVariableAction::createInitialConditionAction(const std::vector<Real> & value)
     176             : {
     177             :   // Variable name
     178       16660 :   const auto var_name = varName();
     179             : 
     180             :   // Create the object name
     181       16660 :   std::string long_name("");
     182       16660 :   long_name += var_name;
     183       16660 :   long_name += "_moose";
     184             : 
     185             :   // Set the parameters for the action
     186       33320 :   InputParameters action_params = _action_factory.getValidParams("AddOutputAction");
     187       33320 :   action_params.set<ActionWarehouse *>("awh") = &_awh;
     188             : 
     189             :   // Associate all action and initial condition errors with "initial_condition"
     190       33320 :   associateWithParameter("initial_condition", action_params);
     191             : 
     192       16660 :   const auto fe_field_type = FEInterface::field_type(_fe_type);
     193       16660 :   const bool is_vector = fe_field_type == TYPE_VECTOR;
     194       16660 :   const auto is_array = _components > 1 || _moose_object_pars.get<bool>("array");
     195             : 
     196       16660 :   if (_scalar_var)
     197        2042 :     action_params.set<std::string>("type") = "ScalarConstantIC";
     198       15639 :   else if (!is_array)
     199             :   {
     200       15200 :     if (is_vector)
     201         168 :       action_params.set<std::string>("type") = "VectorConstantIC";
     202             :     else
     203             :     {
     204       15116 :       if (_fv_var)
     205        4112 :         action_params.set<std::string>("type") = "FVConstantIC";
     206             :       else
     207       26120 :         action_params.set<std::string>("type") = "ConstantIC";
     208             :     }
     209             :   }
     210             :   else
     211             :   {
     212         439 :     action_params.set<std::string>("type") = "ArrayConstantIC";
     213         439 :     if (value.size() != _components)
     214           0 :       mooseError("Size of 'initial_condition' is not consistent");
     215             :   }
     216             : 
     217             :   // Create the action
     218       16660 :   std::shared_ptr<MooseObjectAction> action;
     219       16660 :   if (_fv_var)
     220        4112 :     action = std::static_pointer_cast<MooseObjectAction>(
     221       10280 :         _action_factory.create("AddFVInitialConditionAction", long_name, action_params));
     222             :   else
     223       29208 :     action = std::static_pointer_cast<MooseObjectAction>(
     224       73020 :         _action_factory.create("AddInitialConditionAction", long_name, action_params));
     225             : 
     226             :   // Set the required parameters for the object to be created
     227       49980 :   action->getObjectParams().set<VariableName>("variable") = var_name;
     228       16660 :   if (is_array)
     229             :   {
     230         439 :     RealEigenVector v(_components);
     231        1437 :     for (unsigned int i = 0; i < _components; ++i)
     232         998 :       v(i) = value[i];
     233         878 :     action->getObjectParams().set<RealEigenVector>("value") = v;
     234         439 :   }
     235       16221 :   else if (is_vector)
     236             :   {
     237         168 :     action->getObjectParams().set<Real>("x_value") = value[0];
     238          84 :     if (value.size() > 0)
     239         252 :       action->getObjectParams().set<Real>("y_value") = value[1];
     240          84 :     if (value.size() > 1)
     241         252 :       action->getObjectParams().set<Real>("z_value") = value[2];
     242             :   }
     243             :   else
     244       48411 :     action->getObjectParams().set<Real>("value") = value[0];
     245             : 
     246             :   // Store the action in the ActionWarehouse
     247       16660 :   _awh.addActionBlock(action);
     248       16660 : }
     249             : 
     250             : std::string
     251           0 : AddVariableAction::determineType(const FEType & fe_type, unsigned int components, bool is_fv)
     252             : {
     253           0 :   ::mooseDeprecated("AddVariableAction::determineType() is deprecated. Use "
     254             :                     "AddVariableAction::variableType() instead.");
     255           0 :   return variableType(fe_type, is_fv, components > 1);
     256             : }
     257             : 
     258             : std::string
     259      112570 : AddVariableAction::variableType(const FEType & fe_type, const bool is_fv, const bool is_array)
     260             : {
     261      112570 :   if (is_fv)
     262        2932 :     return "MooseVariableFVReal";
     263             : 
     264      111104 :   const auto fe_field_type = FEInterface::field_type(fe_type);
     265             : 
     266      111104 :   if (is_array)
     267             :   {
     268        2090 :     if (fe_field_type == TYPE_VECTOR)
     269           0 :       ::mooseError("Vector finite element families do not currently have ArrayVariable support");
     270             :     else
     271        4180 :       return "ArrayMooseVariable";
     272             :   }
     273      109014 :   else if (fe_type == FEType(0, MONOMIAL))
     274       40806 :     return "MooseVariableConstMonomial";
     275       88611 :   else if (fe_type.family == SCALAR)
     276        5350 :     return "MooseVariableScalar";
     277       85936 :   else if (fe_field_type == TYPE_VECTOR)
     278        2832 :     return "VectorMooseVariable";
     279             :   else
     280      169040 :     return "MooseVariable";
     281             : }
     282             : 
     283             : void
     284      123028 : AddVariableAction::addVariable(const std::string & var_name)
     285             : {
     286             :   // Compare sizes of scaling_factor and components for Array Variables
     287      246056 :   const auto & scale_factor = _moose_object_pars.isParamValid("scaling")
     288      123313 :                                   ? _moose_object_pars.get<std::vector<Real>>("scaling")
     289      368294 :                                   : std::vector<Real>(_components, 1);
     290      123028 :   if (scale_factor.size() != _components)
     291           0 :     mooseError("Size of 'scaling' is not consistent");
     292             : 
     293      123028 :   _problem_add_var_method(*_problem, _type, var_name, _moose_object_pars);
     294             : 
     295      123004 :   if (_moose_object_pars.get<bool>("eigen"))
     296             :   {
     297             :     // MooseEigenSystem will be eventually removed. NonlinearEigenSystem will be used intead.
     298             :     // It is legal for NonlinearEigenSystem to specify a variable as eigen in input file,
     299             :     // but we do not need to do anything here.
     300             :     MooseEigenSystem * esys =
     301          22 :         dynamic_cast<MooseEigenSystem *>(&_problem->getNonlinearSystemBase(/*nl_sys=*/0));
     302          22 :     if (esys)
     303          10 :       esys->markEigenVariable(var_name);
     304             :   }
     305      123004 : }
     306             : 
     307             : std::set<SubdomainID>
     308           0 : AddVariableAction::getSubdomainIDs()
     309             : {
     310             :   // Extract and return the block ids supplied in the input
     311           0 :   std::set<SubdomainID> blocks;
     312             :   std::vector<SubdomainName> block_param =
     313           0 :       _moose_object_pars.get<std::vector<SubdomainName>>("block");
     314           0 :   for (const auto & subdomain_name : block_param)
     315             :   {
     316           0 :     SubdomainID blk_id = _problem->mesh().getSubdomainID(subdomain_name);
     317           0 :     blocks.insert(blk_id);
     318             :   }
     319           0 :   return blocks;
     320           0 : }

Generated by: LCOV version 1.14