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