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 : }
|