LCOV - code coverage report
Current view: top level - src/actions - AddVariableAction.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 124 144 86.1 %
Date: 2025-07-17 01:28:37 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     1068726 : AddVariableAction::validParams()
      29             : {
      30     1068726 :   auto params = MooseObjectAction::validParams();
      31     1068726 :   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     1068726 :   params.set<std::string>("type") = "MooseVariableBase";
      36             : 
      37             :   // The below is for backwards compatibility
      38     1068726 :   MooseEnum families(AddVariableAction::getNonlinearVariableFamilies());
      39     1068726 :   MooseEnum orders(AddVariableAction::getNonlinearVariableOrders());
      40     1068726 :   params.addParam<MooseEnum>(
      41             :       "family", families, "Specifies the family of FE shape functions to use for this variable");
      42     1068726 :   params.addParam<MooseEnum>("order",
      43             :                              orders,
      44             :                              "Specifies the order of the FE shape function to use "
      45             :                              "for this variable (additional orders not listed are "
      46             :                              "allowed)");
      47     1068726 :   params.addParam<std::vector<Real>>("scaling",
      48             :                                      "Specifies a scaling factor to apply to this variable");
      49     1068726 :   params.addParam<std::vector<Real>>("initial_condition",
      50             :                                      "Specifies a constant initial condition for this variable");
      51     1068726 :   params.transferParam<std::string>(CopyNodalVarsAction::validParams(), "initial_from_file_var");
      52     2137452 :   return params;
      53     1068726 : }
      54             : 
      55      115411 : AddVariableAction::AddVariableAction(const InputParameters & params)
      56             :   : MooseObjectAction(params),
      57      115411 :     _fe_type(feType(params)),
      58      115411 :     _scalar_var(_fe_type.family == SCALAR),
      59      115411 :     _fv_var(false),
      60      115411 :     _components(1)
      61             : {
      62      115411 : }
      63             : 
      64             : MooseEnum
      65     1545135 : AddVariableAction::getNonlinearVariableFamilies()
      66             : {
      67             :   return MooseEnum("LAGRANGE MONOMIAL HERMITE SCALAR HIERARCHIC CLOUGH XYZ SZABAB BERNSTEIN "
      68             :                    "L2_LAGRANGE L2_HIERARCHIC NEDELEC_ONE LAGRANGE_VEC MONOMIAL_VEC "
      69             :                    "RAVIART_THOMAS RATIONAL_BERNSTEIN SIDE_HIERARCHIC L2_HIERARCHIC_VEC "
      70             :                    "L2_LAGRANGE_VEC L2_RAVIART_THOMAS",
      71     1545135 :                    "LAGRANGE");
      72             : }
      73             : 
      74             : MooseEnum
      75     1112173 : AddVariableAction::getNonlinearVariableOrders()
      76             : {
      77     1112173 :   return MooseEnum("CONSTANT FIRST SECOND THIRD FOURTH", "FIRST", true);
      78             : }
      79             : 
      80             : FEType
      81      115507 : AddVariableAction::feType(const InputParameters & params)
      82             : {
      83      115507 :   return {Utility::string_to_enum<Order>(params.get<MooseEnum>("order")),
      84      115507 :           Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"))};
      85             : }
      86             : 
      87             : void
      88      111856 : AddVariableAction::init()
      89             : {
      90      111856 :   _components = _moose_object_pars.get<unsigned int>("components");
      91      111856 :   if (_components == 0)
      92           0 :     mooseError("There must be at least one variable component, but somehow 0 has been specified");
      93             : 
      94             :   // We have to do some sanity checks because of our work to maintain backwards compatibility.
      95             :   // `family`, `order`, and `scaling` are all parameters duplicated between this action and the
      96             :   // `MooseVariable*` object itself. Consequently during input file parsing, the params objects for
      97             :   // both the action and MooseVariable object can be populated with the exact same parameters.
      98             :   // However, some applications actually create their variables solely through creation and setting
      99             :   // of `AddVariableAction` parameters which means that the `MooseVariableBase*` params will never
     100             :   // be populated. So we should apply the parameters directly from the action. There should be no
     101             :   // case in which both params objects get set by the user and they have different values
     102             : 
     103      279072 :   if (isParamSetByUser("family") && _moose_object_pars.isParamSetByUser("family") &&
     104      167216 :       !getParam<MooseEnum>("family").compareCurrent(_moose_object_pars.get<MooseEnum>("family")))
     105           0 :     mooseError("Both the MooseVariable* and Add*VariableAction parameters objects have had the "
     106             :                "`family` parameter set, and they are different values: ",
     107           0 :                _moose_object_pars.get<MooseEnum>("family"),
     108             :                " and ",
     109             :                getParam<MooseEnum>("family"),
     110             :                " respectively. I don't know how you achieved this, but you need to rectify it.");
     111             : 
     112      279450 :   if (isParamSetByUser("order") && _moose_object_pars.isParamSetByUser("order") &&
     113      167594 :       !getParam<MooseEnum>("order").compareCurrent(_moose_object_pars.get<MooseEnum>("order")))
     114           0 :     mooseError("Both the MooseVariable* and Add*VariableAction parameters objects have had the "
     115             :                "`order` parameter set, and they are different values: ",
     116           0 :                _moose_object_pars.get<MooseEnum>("order"),
     117             :                " and ",
     118             :                getParam<MooseEnum>("order"),
     119             :                " respectively. I don't know how you achieved this, but you need to rectify it.");
     120             : 
     121      224107 :   if (isParamSetByUser("scaling") && _moose_object_pars.isParamSetByUser("scaling") &&
     122      112251 :       getParam<std::vector<Real>>("scaling") !=
     123          42 :           _moose_object_pars.get<std::vector<Real>>("scaling"))
     124           0 :     mooseError("Both the MooseVariable* and Add*VariableAction parameters objects have had the "
     125             :                "`scaling` parameter set, and they are different values. I don't know how you "
     126             :                "achieved this, but you need to rectify it.");
     127             : 
     128      111856 :   if (isParamSetByUser("initial_condition") && isParamSetByUser("initial_from_file_var"))
     129           4 :     paramError("initial_condition",
     130             :                "Two initial conditions have been provided for the variable ",
     131           4 :                name(),
     132             :                " using the 'initial_condition' and 'initial_from_file_var' parameters. Please "
     133             :                "remove one of them.");
     134             : 
     135      447408 :   _moose_object_pars.applySpecificParameters(_pars, {"order", "family", "scaling"});
     136             : 
     137             :   // Determine the MooseVariable type
     138      111852 :   _fv_var = _moose_object_pars.get<bool>("fv");
     139      111852 :   const auto is_array = _components > 1 || _moose_object_pars.get<bool>("array");
     140      111852 :   if (_type == "MooseVariableBase")
     141      105860 :     _type = variableType(_fe_type, _fv_var, is_array);
     142      111852 :   if (_fv_var)
     143        7171 :     _problem->needFV();
     144             : 
     145             :   // Need static_cast to resolve overloads
     146      223704 :   _problem_add_var_method = static_cast<void (FEProblemBase::*)(
     147      111852 :       const std::string &, const std::string &, InputParameters &)>(&FEProblemBase::addVariable);
     148      335556 : }
     149             : 
     150             : void
     151      111856 : AddVariableAction::act()
     152             : {
     153             :   // If we've been called that means that current_task == "add_variable"
     154      111856 :   init();
     155             : 
     156             :   // Get necessary data for creating a variable
     157      111848 :   const auto var_name = varName();
     158      111848 :   addVariable(var_name);
     159             : 
     160             :   // Set the initial condition
     161      111816 :   if (isParamValid("initial_condition"))
     162             :   {
     163       14831 :     const auto & value = getParam<std::vector<Real>>("initial_condition");
     164       14831 :     createInitialConditionAction(value);
     165             :   }
     166      111816 : }
     167             : 
     168             : void
     169       14831 : AddVariableAction::createInitialConditionAction(const std::vector<Real> & value)
     170             : {
     171             :   // Variable name
     172       14831 :   const auto var_name = varName();
     173             : 
     174             :   // Create the object name
     175       14831 :   std::string long_name("");
     176       14831 :   long_name += var_name;
     177       14831 :   long_name += "_moose";
     178             : 
     179             :   // Set the parameters for the action
     180       14831 :   InputParameters action_params = _action_factory.getValidParams("AddOutputAction");
     181       14831 :   action_params.set<ActionWarehouse *>("awh") = &_awh;
     182             : 
     183             :   // Associate all action and initial condition errors with "initial_condition"
     184       14831 :   associateWithParameter("initial_condition", action_params);
     185             : 
     186       14831 :   const auto fe_field_type = FEInterface::field_type(_fe_type);
     187       14831 :   const bool is_vector = fe_field_type == TYPE_VECTOR;
     188             : 
     189       14831 :   if (_scalar_var)
     190        1088 :     action_params.set<std::string>("type") = "ScalarConstantIC";
     191       13743 :   else if (_components == 1)
     192             :   {
     193       13291 :     if (is_vector)
     194          84 :       action_params.set<std::string>("type") = "VectorConstantIC";
     195             :     else
     196             :     {
     197       13207 :       if (_fv_var)
     198        2300 :         action_params.set<std::string>("type") = "FVConstantIC";
     199             :       else
     200       10907 :         action_params.set<std::string>("type") = "ConstantIC";
     201             :     }
     202             :   }
     203             :   else
     204             :   {
     205         452 :     action_params.set<std::string>("type") = "ArrayConstantIC";
     206         452 :     if (value.size() != _components)
     207           0 :       mooseError("Size of 'initial_condition' is not consistent");
     208             :   }
     209             : 
     210             :   // Create the action
     211       14831 :   std::shared_ptr<MooseObjectAction> action;
     212       14831 :   if (_fv_var)
     213        4600 :     action = std::static_pointer_cast<MooseObjectAction>(
     214        6900 :         _action_factory.create("AddFVInitialConditionAction", long_name, action_params));
     215             :   else
     216       25062 :     action = std::static_pointer_cast<MooseObjectAction>(
     217       37593 :         _action_factory.create("AddInitialConditionAction", long_name, action_params));
     218             : 
     219             :   // Set the required parameters for the object to be created
     220       14831 :   action->getObjectParams().set<VariableName>("variable") = var_name;
     221       14831 :   if (_components > 1)
     222             :   {
     223         452 :     RealEigenVector v(_components);
     224        1492 :     for (unsigned int i = 0; i < _components; ++i)
     225        1040 :       v(i) = value[i];
     226         452 :     action->getObjectParams().set<RealEigenVector>("value") = v;
     227         452 :   }
     228       14379 :   else if (is_vector)
     229             :   {
     230          84 :     action->getObjectParams().set<Real>("x_value") = value[0];
     231          84 :     if (value.size() > 0)
     232          84 :       action->getObjectParams().set<Real>("y_value") = value[1];
     233          84 :     if (value.size() > 1)
     234          84 :       action->getObjectParams().set<Real>("z_value") = value[2];
     235             :   }
     236             :   else
     237       14295 :     action->getObjectParams().set<Real>("value") = value[0];
     238             : 
     239             :   // Store the action in the ActionWarehouse
     240       14831 :   _awh.addActionBlock(action);
     241       14831 : }
     242             : 
     243             : std::string
     244           0 : AddVariableAction::determineType(const FEType & fe_type, unsigned int components, bool is_fv)
     245             : {
     246           0 :   ::mooseDeprecated("AddVariableAction::determineType() is deprecated. Use "
     247             :                     "AddVariableAction::variableType() instead.");
     248           0 :   return variableType(fe_type, is_fv, components > 1);
     249             : }
     250             : 
     251             : std::string
     252      105992 : AddVariableAction::variableType(const FEType & fe_type, const bool is_fv, const bool is_array)
     253             : {
     254      105992 :   if (is_fv)
     255        1539 :     return "MooseVariableFVReal";
     256             : 
     257      104453 :   const auto fe_field_type = FEInterface::field_type(fe_type);
     258             : 
     259      104453 :   if (is_array)
     260             :   {
     261        2093 :     if (fe_field_type == TYPE_VECTOR)
     262           0 :       ::mooseError("Vector finite element families do not currently have ArrayVariable support");
     263             :     else
     264        2093 :       return "ArrayMooseVariable";
     265             :   }
     266      102360 :   else if (fe_type == FEType(0, MONOMIAL))
     267       18441 :     return "MooseVariableConstMonomial";
     268       83919 :   else if (fe_type.family == SCALAR)
     269        2832 :     return "MooseVariableScalar";
     270       81087 :   else if (fe_field_type == TYPE_VECTOR)
     271        1434 :     return "VectorMooseVariable";
     272             :   else
     273       79653 :     return "MooseVariable";
     274             : }
     275             : 
     276             : void
     277      114392 : AddVariableAction::addVariable(const std::string & var_name)
     278             : {
     279             :   // Compare sizes of scaling_factor and components for Array Variables
     280      228784 :   const auto & scale_factor = _moose_object_pars.isParamValid("scaling")
     281      114434 :                                   ? _moose_object_pars.get<std::vector<Real>>("scaling")
     282      114392 :                                   : std::vector<Real>(_components, 1);
     283      114392 :   if (scale_factor.size() != _components)
     284           0 :     mooseError("Size of 'scaling' is not consistent");
     285             : 
     286      114392 :   _problem_add_var_method(*_problem, _type, var_name, _moose_object_pars);
     287             : 
     288      114360 :   if (_moose_object_pars.get<bool>("eigen"))
     289             :   {
     290             :     // MooseEigenSystem will be eventually removed. NonlinearEigenSystem will be used intead.
     291             :     // It is legal for NonlinearEigenSystem to specify a variable as eigen in input file,
     292             :     // but we do not need to do anything here.
     293             :     MooseEigenSystem * esys =
     294          22 :         dynamic_cast<MooseEigenSystem *>(&_problem->getNonlinearSystemBase(/*nl_sys=*/0));
     295          22 :     if (esys)
     296          10 :       esys->markEigenVariable(var_name);
     297             :   }
     298      114360 : }
     299             : 
     300             : std::set<SubdomainID>
     301           0 : AddVariableAction::getSubdomainIDs()
     302             : {
     303             :   // Extract and return the block ids supplied in the input
     304           0 :   std::set<SubdomainID> blocks;
     305             :   std::vector<SubdomainName> block_param =
     306           0 :       _moose_object_pars.get<std::vector<SubdomainName>>("block");
     307           0 :   for (const auto & subdomain_name : block_param)
     308             :   {
     309           0 :     SubdomainID blk_id = _problem->mesh().getSubdomainID(subdomain_name);
     310           0 :     blocks.insert(blk_id);
     311             :   }
     312           0 :   return blocks;
     313           0 : }

Generated by: LCOV version 1.14