www.mooseframework.org
AddVariableAction.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 // Standard includes
11 #include <sstream>
12 #include <stdexcept>
13 
14 // MOOSE includes
15 #include "AddVariableAction.h"
16 #include "FEProblem.h"
17 #include "Factory.h"
18 #include "MooseEnum.h"
19 #include "MooseEigenSystem.h"
20 #include "MooseObjectAction.h"
21 #include "MooseMesh.h"
22 
23 #include "libmesh/libmesh.h"
24 #include "libmesh/exodusII_io.h"
25 #include "libmesh/equation_systems.h"
26 #include "libmesh/nonlinear_implicit_system.h"
27 #include "libmesh/explicit_system.h"
28 #include "libmesh/string_to_enum.h"
29 
30 registerMooseAction("MooseApp", AddVariableAction, "add_variable");
31 
34 {
35  auto params = MooseObjectAction::validParams();
36  params.addClassDescription("Add a non-linear variable to the simulation.");
37 
38  // The user may specify a type in the Variables block, but if they don't we'll just use all the
39  // parameters available from MooseVariableBase
40  params.set<std::string>("type") = "MooseVariableBase";
41 
42  // The below is for backwards compatibility
45  params.addParam<MooseEnum>(
46  "family", families, "Specifies the family of FE shape functions to use for this variable");
47  params.addParam<MooseEnum>("order",
48  orders,
49  "Specifies the order of the FE shape function to use "
50  "for this variable (additional orders not listed are "
51  "allowed)");
52  params.addParam<std::vector<Real>>("scaling",
53  "Specifies a scaling factor to apply to this variable");
54  params.addParam<std::vector<Real>>("initial_condition",
55  "Specifies a constant initial condition for this variable");
56  return params;
57 }
58 
60  : MooseObjectAction(params),
61  _fe_type(feType(params)),
62  _scalar_var(_fe_type.family == SCALAR),
63  _fv_var(false),
64  _components(1)
65 {
66 }
67 
70 {
71  return MooseEnum("LAGRANGE MONOMIAL HERMITE SCALAR HIERARCHIC CLOUGH XYZ SZABAB BERNSTEIN "
72  "L2_LAGRANGE L2_HIERARCHIC NEDELEC_ONE LAGRANGE_VEC MONOMIAL_VEC "
73  "RAVIART_THOMAS RATIONAL_BERNSTEIN SIDE_HIERARCHIC",
74  "LAGRANGE");
75 }
76 
79 {
80  return MooseEnum("CONSTANT FIRST SECOND THIRD FOURTH", "FIRST", true);
81 }
82 
83 FEType
85 {
86  return {Utility::string_to_enum<Order>(params.get<MooseEnum>("order")),
87  Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"))};
88 }
89 
90 void
92 {
93  _components = _moose_object_pars.get<unsigned int>("components");
94  if (_components == 0)
95  mooseError("There must be at least one variable component, but somehow 0 has been specified");
96 
97  // We have to do some sanity checks because of our work to maintain backwards compatibility.
98  // `family`, `order`, and `scaling` are all parameters duplicated between this action and the
99  // `MooseVariable*` object itself. Consequently during input file parsing, the params objects for
100  // both the action and MooseVariable object can be populated with the exact same parameters.
101  // However, some applications actually create their variables solely through creation and setting
102  // of `AddVariableAction` parameters which means that the `MooseVariableBase*` params will never
103  // be populated. So we should apply the parameters directly from the action. There should be no
104  // case in which both params objects get set by the user and they have different values
105 
106  if (_pars.isParamSetByUser("family") && _moose_object_pars.isParamSetByUser("family") &&
107  !_pars.get<MooseEnum>("family").compareCurrent(_moose_object_pars.get<MooseEnum>("family")))
108  mooseError("Both the MooseVariable* and Add*VariableAction parameters objects have had the "
109  "`family` parameter set, and they are different values: ",
110  _moose_object_pars.get<MooseEnum>("family"),
111  " and ",
112  _pars.get<MooseEnum>("family"),
113  " respectively. I don't know how you achieved this, but you need to rectify it.");
114 
115  if (_pars.isParamSetByUser("order") && _moose_object_pars.isParamSetByUser("order") &&
116  !_pars.get<MooseEnum>("order").compareCurrent(_moose_object_pars.get<MooseEnum>("order")))
117  mooseError("Both the MooseVariable* and Add*VariableAction parameters objects have had the "
118  "`order` parameter set, and they are different values: ",
119  _moose_object_pars.get<MooseEnum>("order"),
120  " and ",
121  _pars.get<MooseEnum>("order"),
122  " respectively. I don't know how you achieved this, but you need to rectify it.");
123 
124  if (_pars.isParamSetByUser("scaling") && _moose_object_pars.isParamSetByUser("scaling") &&
125  _pars.get<std::vector<Real>>("scaling") !=
126  _moose_object_pars.get<std::vector<Real>>("scaling"))
127  mooseError("Both the MooseVariable* and Add*VariableAction parameters objects have had the "
128  "`scaling` parameter set, and they are different values. I don't know how you "
129  "achieved this, but you need to rectify it.");
130 
131  _moose_object_pars.applySpecificParameters(_pars, {"order", "family", "scaling"});
132 
133  // Determine the MooseVariable type
134  _fv_var = _moose_object_pars.get<bool>("fv");
135  const auto is_array = _components > 1 || _moose_object_pars.get<bool>("array");
136  if (_type == "MooseVariableBase")
137  _type = variableType(_fe_type, _fv_var, is_array);
138  if (_fv_var)
139  _problem->needFV();
140 
141  // Need static_cast to resolve overloads
142  _problem_add_var_method = static_cast<void (FEProblemBase::*)(
143  const std::string &, const std::string &, InputParameters &)>(&FEProblemBase::addVariable);
144 }
145 
146 void
148 {
149  // If we've been called that means that current_task == "add_variable"
150  init();
151 
152  // Get necessary data for creating a variable
153  std::string var_name = name();
154  addVariable(var_name);
155 
156  // Set the initial condition
157  if (_pars.isParamValid("initial_condition"))
159 }
160 
161 void
163 {
164  // Variable name
165  std::string var_name = name();
166 
167  auto value = _pars.get<std::vector<Real>>("initial_condition");
168 
169  // Create the object name
170  std::string long_name("");
171  long_name += var_name;
172  long_name += "_moose";
173 
174  // Set the parameters for the action
175  InputParameters action_params = _action_factory.getValidParams("AddOutputAction");
176  action_params.set<ActionWarehouse *>("awh") = &_awh;
177 
178  // Associate all action and initial condition errors with "initial_condition"
179  associateWithParameter("initial_condition", action_params);
180 
181  bool is_vector = (_fe_type.family == LAGRANGE_VEC || _fe_type.family == NEDELEC_ONE ||
182  _fe_type.family == MONOMIAL_VEC || _fe_type.family == RAVIART_THOMAS);
183 
184  if (_scalar_var)
185  action_params.set<std::string>("type") = "ScalarConstantIC";
186  else if (_components == 1)
187  {
188  if (is_vector)
189  action_params.set<std::string>("type") = "VectorConstantIC";
190  else
191  {
192  if (_fv_var)
193  action_params.set<std::string>("type") = "FVConstantIC";
194  else
195  action_params.set<std::string>("type") = "ConstantIC";
196  }
197  }
198  else
199  {
200  action_params.set<std::string>("type") = "ArrayConstantIC";
201  if (value.size() != _components)
202  mooseError("Size of 'initial_condition' is not consistent");
203  }
204 
205  // Create the action
206  std::shared_ptr<MooseObjectAction> action;
207  if (_fv_var)
208  action = std::static_pointer_cast<MooseObjectAction>(
209  _action_factory.create("AddFVInitialConditionAction", long_name, action_params));
210  else
211  action = std::static_pointer_cast<MooseObjectAction>(
212  _action_factory.create("AddInitialConditionAction", long_name, action_params));
213 
214  // Set the required parameters for the object to be created
215  action->getObjectParams().set<VariableName>("variable") = var_name;
216  if (_components > 1)
217  {
219  for (unsigned int i = 0; i < _components; ++i)
220  v(i) = value[i];
221  action->getObjectParams().set<RealEigenVector>("value") = v;
222  }
223  else if (is_vector)
224  {
225  action->getObjectParams().set<Real>("x_value") = value[0];
226  if (value.size() > 0)
227  action->getObjectParams().set<Real>("y_value") = value[1];
228  if (value.size() > 1)
229  action->getObjectParams().set<Real>("z_value") = value[2];
230  }
231  else
232  action->getObjectParams().set<Real>("value") = value[0];
233 
234  // Store the action in the ActionWarehouse
235  _awh.addActionBlock(action);
236 }
237 
238 std::string
239 AddVariableAction::determineType(const FEType & fe_type, unsigned int components, bool is_fv)
240 {
241  ::mooseDeprecated("AddVariableAction::determineType() is deprecated. Use "
242  "AddVariableAction::variableType() instead.");
243  return variableType(fe_type, is_fv, components > 1);
244 }
245 
246 std::string
247 AddVariableAction::variableType(const FEType & fe_type, const bool is_fv, const bool is_array)
248 {
249  if (is_fv)
250  return "MooseVariableFVReal";
251 
252  if (is_array)
253  {
254  if (fe_type.family == LAGRANGE_VEC || fe_type.family == NEDELEC_ONE ||
255  fe_type.family == MONOMIAL_VEC || fe_type.family == RAVIART_THOMAS)
256  ::mooseError("Vector finite element families do not currently have ArrayVariable support");
257  else
258  return "ArrayMooseVariable";
259  }
260  else if (fe_type == FEType(0, MONOMIAL))
261  return "MooseVariableConstMonomial";
262  else if (fe_type.family == SCALAR)
263  return "MooseVariableScalar";
264  else if (fe_type.family == LAGRANGE_VEC || fe_type.family == NEDELEC_ONE ||
265  fe_type.family == MONOMIAL_VEC || fe_type.family == RAVIART_THOMAS)
266  return "VectorMooseVariable";
267  else
268  return "MooseVariable";
269 }
270 
271 void
272 AddVariableAction::addVariable(const std::string & var_name)
273 {
274  // Compare sizes of scaling_factor and components for Array Variables
275  const auto & scale_factor = _moose_object_pars.isParamValid("scaling")
276  ? _moose_object_pars.get<std::vector<Real>>("scaling")
277  : std::vector<Real>(_components, 1);
278  if (scale_factor.size() != _components)
279  mooseError("Size of 'scaling' is not consistent");
280 
282 
283  if (_moose_object_pars.get<bool>("eigen"))
284  {
285  // MooseEigenSystem will be eventually removed. NonlinearEigenSystem will be used intead.
286  // It is legal for NonlinearEigenSystem to specify a variable as eigen in input file,
287  // but we do not need to do anything here.
288  MooseEigenSystem * esys =
289  dynamic_cast<MooseEigenSystem *>(&_problem->getNonlinearSystemBase(/*nl_sys=*/0));
290  if (esys)
291  esys->markEigenVariable(var_name);
292  }
293 }
294 
295 std::set<SubdomainID>
297 {
298  // Extract and return the block ids supplied in the input
299  std::set<SubdomainID> blocks;
300  std::vector<SubdomainName> block_param =
301  _moose_object_pars.get<std::vector<SubdomainName>>("block");
302  for (const auto & subdomain_name : block_param)
303  {
304  SubdomainID blk_id = _problem->mesh().getSubdomainID(subdomain_name);
305  blocks.insert(blk_id);
306  }
307  return blocks;
308 }
static InputParameters validParams()
Class constructor.
std::set< SubdomainID > getSubdomainIDs()
Get the block ids from the input parameters.
bool _scalar_var
True if the variable being created is a scalar.
virtual void act() override
Method to add objects to the simulation or perform other setup tasks.
void mooseDeprecated(Args &&... args) const
LAGRANGE_VEC
static std::string variableType(const FEType &fe_type, const bool is_fv=false, const bool is_array=false)
Determines a variable type.
ActionWarehouse & _awh
Reference to ActionWarehouse where we store object build by actions.
Definition: Action.h:170
SCALAR
Adds nonlinear variable.
void applySpecificParameters(const InputParameters &common, const std::vector< std::string > &include, bool allow_private=false)
Method for applying common parameters.
InputParameters getValidParams(const std::string &name)
Definition: ActionFactory.C:92
static InputParameters validParams()
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
FEType _fe_type
FEType for the variable being created.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
Storage for action instances.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
void addActionBlock(std::shared_ptr< Action > blk)
This method add an Action instance to the warehouse.
registerMooseAction("MooseApp", AddVariableAction, "add_variable")
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:57
std::shared_ptr< Action > create(const std::string &action, const std::string &action_name, InputParameters &parameters)
Definition: ActionFactory.C:39
static MooseEnum getNonlinearVariableFamilies()
Get the possible variable families.
MONOMIAL_VEC
bool _fv_var
True if the variable being created is finite volume.
InputParameters & getObjectParams()
Retreive the parameters of the object to be created by this action.
static MooseEnum getNonlinearVariableOrders()
Get the possible variable orders.
unsigned int _components
Number of components for an array variable.
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
static std::string determineType(const FEType &fe_type, unsigned int components, bool is_fv=false)
DEPRECATED: Use variableType instead.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:31
virtual void markEigenVariable(const VariableName &var_name)
Mark a variable as a variable of the eigen system.
ActionFactory & _action_factory
Builds Actions.
virtual void addVariable(const std::string &var_type, const std::string &var_name, InputParameters &params)
Canonical method for adding a non-linear variable.
MONOMIAL
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was by the user.
static FEType feType(const InputParameters &params)
determine the FEType by examining family and order in the provided parameters
std::string _type
The Object type that is being created.
RAVIART_THOMAS
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
InputParameters _moose_object_pars
The parameters for the object to be created.
virtual void init()
Initialize the action&#39;s member variables.
void associateWithParameter(const std::string &param_name, InputParameters &params) const
Associates the object&#39;s parameters params with the input location from this Action&#39;s parameter with t...
Definition: Action.C:160
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
const InputParameters & _pars
Parameters of this object, references the InputParameters stored in the InputParametersWarehouse.
std::shared_ptr< FEProblemBase > & _problem
Convenience reference to a problem this action works on.
Definition: Action.h:179
void addVariable(const std::string &var_name)
Adds a nonlinear variable to the system.
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
Definition: MooseTypes.h:138
AddVariableAction(const InputParameters &params)
NEDELEC_ONE
void createInitialConditionAction()
Create the action to generate the InitialCondition object.
std::function< void(FEProblemBase &, const std::string &, const std::string &, InputParameters &)> _problem_add_var_method
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another, i.e.