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 : #include "MooseVariableBase.h"
11 :
12 : #include "AddVariableAction.h"
13 : #include "SubProblem.h"
14 : #include "SystemBase.h"
15 : #include "MooseMesh.h"
16 : #include "MooseApp.h"
17 : #include "InputParameterWarehouse.h"
18 : #include "BlockRestrictable.h"
19 :
20 : #include "libmesh/variable.h"
21 : #include "libmesh/dof_map.h"
22 : #include "libmesh/system.h"
23 : #include "libmesh/fe_type.h"
24 : #include "libmesh/string_to_enum.h"
25 :
26 : using namespace libMesh;
27 :
28 : // Users should never actually create this object
29 : registerMooseObject("MooseApp", MooseVariableBase);
30 :
31 : InputParameters
32 476159 : MooseVariableBase::validParams()
33 : {
34 476159 : InputParameters params = MooseObject::validParams();
35 476159 : params += BlockRestrictable::validParams();
36 476159 : params += OutputInterface::validParams();
37 :
38 : MooseEnum order(
39 : "CONSTANT FIRST SECOND THIRD FOURTH FIFTH SIXTH SEVENTH EIGHTH NINTH TENTH ELEVENTH TWELFTH "
40 : "THIRTEENTH FOURTEENTH FIFTEENTH SIXTEENTH SEVENTEENTH EIGHTTEENTH NINETEENTH TWENTIETH "
41 : "TWENTYFIRST TWENTYSECOND TWENTYTHIRD TWENTYFOURTH TWENTYFIFTH TWENTYSIXTH TWENTYSEVENTH "
42 : "TWENTYEIGHTH TWENTYNINTH THIRTIETH THIRTYFIRST THIRTYSECOND THIRTYTHIRD THIRTYFOURTH "
43 : "THIRTYFIFTH THIRTYSIXTH THIRTYSEVENTH THIRTYEIGHTH THIRTYNINTH FORTIETH FORTYFIRST "
44 : "FORTYSECOND FORTYTHIRD",
45 : "FIRST",
46 476159 : true);
47 476159 : params.addParam<MooseEnum>("order",
48 : order,
49 : "Order of the FE shape function to use for this variable (additional "
50 : "orders not listed here are allowed, depending on the family).");
51 :
52 476159 : MooseEnum family{AddVariableAction::getNonlinearVariableFamilies()};
53 :
54 476159 : params.addParam<MooseEnum>(
55 : "family", family, "Specifies the family of FE shape functions to use for this variable.");
56 :
57 : // ArrayVariable capability
58 1428477 : params.addRangeCheckedParam<unsigned int>(
59 952318 : "components", 1, "components>0", "Number of components for an array variable");
60 :
61 : // Advanced input options
62 476159 : params.addParam<std::vector<Real>>("scaling",
63 : "Specifies a scaling factor to apply to this variable");
64 476159 : params.addParam<bool>("eigen", false, "True to make this variable an eigen variable");
65 476159 : params.addParam<bool>("fv", false, "True to make this variable a finite volume variable");
66 1428477 : params.addParam<bool>("array",
67 952318 : false,
68 : "True to make this variable a array variable regardless of number of "
69 : "components. If 'components' > 1, this will automatically be set to true.");
70 :
71 476159 : params.addParam<std::vector<std::string>>(
72 : "array_var_component_names",
73 : "Only for use with array variables, allows setting custom names for each array variable "
74 : "component. If this not set, the default name for each array variable componenet is "
75 : "`base_name`+'_'+component number. If used, a name must be provided for each component and "
76 : "the values are used to name the components as `base_name`+'_'+ "
77 : "`array_var_component_names[component]`.");
78 :
79 476159 : params.addParam<SolverSystemName>("solver_sys",
80 : "nl0",
81 : "If this variable is a solver variable, this is the "
82 : "solver system to which it should be added.");
83 476159 : params.addParam<bool>(
84 : "disable_p_refinement",
85 : "True to disable p-refinement for this variable. Note that because this happens on the "
86 : "family basis, users need to have this flag consistently set for all variables in the same "
87 : "family. Currently MOOSE disables p-refinement for variables in the following families by "
88 : "default: LAGRANGE NEDELEC_ONE RAVIART_THOMAS LAGRANGE_VEC CLOUGH BERNSTEIN and "
89 : "RATIONAL_BERNSTEIN.");
90 :
91 476159 : params.addParamNamesToGroup("scaling eigen", "Advanced");
92 :
93 476159 : params.addParam<bool>("use_dual", false, "True to use dual basis for Lagrange multipliers");
94 476159 : params.transferParam<std::vector<Real>>(AddVariableAction::validParams(), "initial_condition");
95 476159 : params.transferParam<std::string>(AddVariableAction::validParams(), "initial_from_file_var");
96 476159 : params.addParamNamesToGroup("scaling eigen use_dual", "Advanced");
97 :
98 476159 : params.registerBase("MooseVariableBase");
99 476159 : params.addPrivateParam<SystemBase *>("_system_base");
100 476159 : params.addPrivateParam<FEProblemBase *>("_fe_problem_base");
101 476159 : params.addPrivateParam<Moose::VarKindType>("_var_kind");
102 476159 : params.addPrivateParam<unsigned int>("_var_num");
103 476159 : params.addPrivateParam<THREAD_ID>("tid");
104 :
105 476159 : params.addClassDescription(
106 : "Base class for Moose variables. This should never be the terminal object type");
107 952318 : return params;
108 476159 : }
109 :
110 176154 : MooseVariableBase::MooseVariableBase(const InputParameters & parameters)
111 : : MooseObject(parameters),
112 : BlockRestrictable(this),
113 : OutputInterface(parameters),
114 : SetupInterface(this),
115 176154 : _sys(*getParam<SystemBase *>("_system_base")), // TODO: get from _fe_problem_base
116 176154 : _fe_type(Utility::string_to_enum<Order>(getParam<MooseEnum>("order")),
117 352308 : Utility::string_to_enum<FEFamily>(getParam<MooseEnum>("family"))),
118 176154 : _var_num(getParam<unsigned int>("_var_num")),
119 176154 : _is_eigen(getParam<bool>("eigen")),
120 176154 : _var_kind(getParam<Moose::VarKindType>("_var_kind")),
121 176154 : _subproblem(_sys.subproblem()),
122 176154 : _variable(_sys.system().variable(_var_num)),
123 176154 : _assembly(_subproblem.assembly(getParam<THREAD_ID>("_tid"),
124 176154 : (_var_kind == Moose::VAR_SOLVER) ? _sys.number() : 0)),
125 176154 : _dof_map(_sys.dofMap()),
126 176154 : _mesh(_subproblem.mesh()),
127 176154 : _tid(getParam<THREAD_ID>("tid")),
128 176154 : _count(getParam<unsigned int>("components")),
129 176154 : _scaling_factor(_count, 1.0),
130 528462 : _use_dual(getParam<bool>("use_dual"))
131 : {
132 528022 : scalingFactor(isParamValid("scaling") ? getParam<std::vector<Real>>("scaling")
133 351868 : : std::vector<Real>(_count, 1.));
134 176154 : if (getParam<bool>("fv") && getParam<bool>("eigen"))
135 0 : paramError("eigen", "finite volume (fv=true) variables do not have eigen support");
136 176154 : if (getParam<bool>("fv") && _fe_type.family != MONOMIAL)
137 0 : paramError("family", "finite volume (fv=true) variables must be have MONOMIAL family");
138 176154 : if (getParam<bool>("fv") && _fe_type.order != 0)
139 0 : paramError("order", "finite volume (fv=true) variables currently support CONST order only");
140 :
141 176154 : if (isParamValid("array_var_component_names"))
142 : {
143 2472 : auto name0 = _sys.system().variable(_var_num).name();
144 2472 : std::size_t found = name0.find_last_of("_");
145 2472 : if (found == std::string::npos)
146 0 : mooseError("Error creating ArrayMooseVariable name with base name ", name0);
147 2472 : _var_name = name0.substr(0, found);
148 2472 : const auto & name_endings = getParam<std::vector<std::string>>("array_var_component_names");
149 8112 : for (const auto & name : name_endings)
150 5640 : _array_var_component_names.push_back(_var_name + '_' + name);
151 2472 : }
152 : else
153 : {
154 173682 : _var_name = _sys.system().variable(_var_num).name();
155 173682 : if (_count != 1)
156 0 : mooseError(
157 0 : "Component size of normal variable (_count) must be one. This is not the case for '" +
158 0 : _var_name + "' (_count equals " + std::to_string(_count) + ").");
159 : }
160 :
161 : // check parameters set automatically by SystemBase related to array variables
162 : mooseAssert(
163 : isArray() ? _count == _array_var_component_names.size() : true,
164 : "An inconsistent numer of names or no names were provided for array variable components");
165 176154 : if (_count > 1)
166 : mooseAssert(isArray(), "Must be true with component > 1");
167 :
168 176154 : if (!blockRestricted())
169 167554 : _is_lower_d = false;
170 : else
171 : {
172 8600 : const auto & blk_ids = blockIDs();
173 8600 : if (blk_ids.empty())
174 0 : mooseError("Every variable should have at least one subdomain. For '" + _var_name +
175 : "' no subdomain is defined.");
176 :
177 8600 : _is_lower_d = _mesh.isLowerD(*blk_ids.begin());
178 : #ifdef DEBUG
179 : for (auto it = ++blk_ids.begin(); it != blk_ids.end(); ++it)
180 : if (_is_lower_d != _mesh.isLowerD(*it))
181 : mooseError("A user should not specify a mix of lower-dimensional and higher-dimensional "
182 : "blocks for variable '" +
183 : _var_name + "'. This variable is " + (_is_lower_d ? "" : "not ") +
184 : "recognised as lower-dimensional, but is also defined for the " +
185 : (_is_lower_d ? "higher" : "lower") + "-dimensional block '" +
186 : _mesh.getSubdomainName(*it) + "' (block-id " + std::to_string(*it) + ").");
187 : #endif
188 : }
189 176154 : }
190 :
191 : const std::string &
192 24216 : MooseVariableBase::arrayVariableComponent(const unsigned int i) const
193 : {
194 : mooseAssert(
195 : i < _array_var_component_names.size(),
196 : "Requested array variable component number is greater than the number of component names.");
197 24216 : return _array_var_component_names[i];
198 : }
199 :
200 : const std::vector<dof_id_type> &
201 22796 : MooseVariableBase::allDofIndices() const
202 : {
203 22796 : const auto it = _sys.subproblem()._var_dof_map.find(name());
204 22796 : if (it != _sys.subproblem()._var_dof_map.end())
205 22796 : return it->second;
206 : else
207 0 : mooseError("VariableAllDoFMap not prepared for ",
208 0 : name(),
209 : " . Check nonlocal coupling requirement for the variable.");
210 : }
211 :
212 : Order
213 380249337 : MooseVariableBase::order() const
214 : {
215 380249337 : return _fe_type.order;
216 : }
217 :
218 : std::vector<dof_id_type>
219 127526898 : MooseVariableBase::componentDofIndices(const std::vector<dof_id_type> & dof_indices,
220 : unsigned int component) const
221 : {
222 127526898 : std::vector<dof_id_type> new_dof_indices(dof_indices);
223 127526898 : if (component != 0)
224 : {
225 5371424 : if (isNodal())
226 26569632 : for (auto & id : new_dof_indices)
227 21262560 : id += component;
228 : else
229 : {
230 64352 : unsigned int n = dof_indices.size();
231 423424 : for (auto & id : new_dof_indices)
232 359072 : id += component * n;
233 : }
234 : }
235 127526898 : return new_dof_indices;
236 0 : }
237 :
238 : void
239 177456 : MooseVariableBase::scalingFactor(const std::vector<Real> & factor)
240 : {
241 : mooseAssert(factor.size() == _count, "Inconsistent scaling factor size");
242 358091 : for (const auto i : make_range(_count))
243 180635 : _scaling_factor[i] = factor[i];
244 177456 : }
245 :
246 : void
247 169537 : MooseVariableBase::initialSetup()
248 : {
249 : // Currently the scaling vector is only used through AD residual computing objects
250 181254 : if ((_var_kind == Moose::VAR_SOLVER) && _subproblem.haveADObjects() &&
251 34565 : (_subproblem.automaticScaling() || (std::find_if(_scaling_factor.begin(),
252 : _scaling_factor.end(),
253 11424 : [](const Real element) {
254 22848 : return !MooseUtils::absoluteFuzzyEqual(
255 11424 : element, 1.);
256 192385 : }) != _scaling_factor.end())))
257 :
258 352 : _sys.addScalingVector();
259 169537 : }
|