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 506850 : MooseVariableBase::validParams()
33 : {
34 506850 : InputParameters params = MooseObject::validParams();
35 506850 : params += BlockRestrictable::validParams();
36 506850 : 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 2027400 : true);
47 1520550 : 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 506850 : MooseEnum family{AddVariableAction::getNonlinearVariableFamilies()};
53 :
54 2027400 : params.addParam<MooseEnum>(
55 : "family", family, "Specifies the family of FE shape functions to use for this variable.");
56 :
57 : // ArrayVariable capability
58 2534250 : params.addRangeCheckedParam<unsigned int>(
59 1013700 : "components", 1, "components>0", "Number of components for an array variable");
60 :
61 : // Advanced input options
62 2027400 : params.addParam<std::vector<Real>>("scaling",
63 : "Specifies a scaling factor to apply to this variable");
64 2027400 : params.addParam<bool>("eigen", false, "True to make this variable an eigen variable");
65 2027400 : params.addParam<bool>("fv", false, "True to make this variable a finite volume variable");
66 1520550 : params.addParam<bool>("array",
67 1013700 : 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 2027400 : 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 2027400 : 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 2027400 : 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 2027400 : params.addParamNamesToGroup("scaling eigen", "Advanced");
92 :
93 2027400 : params.addParam<bool>("use_dual", false, "True to use dual basis for Lagrange multipliers");
94 3041100 : params.transferParam<std::vector<Real>>(AddVariableAction::validParams(), "initial_condition");
95 3041100 : params.transferParam<std::string>(AddVariableAction::validParams(), "initial_from_file_var");
96 2027400 : params.addParamNamesToGroup("scaling eigen use_dual", "Advanced");
97 :
98 1013700 : params.registerBase("MooseVariableBase");
99 1013700 : params.addPrivateParam<SystemBase *>("_system_base");
100 1013700 : params.addPrivateParam<FEProblemBase *>("_fe_problem_base");
101 1013700 : params.addPrivateParam<Moose::VarKindType>("_var_kind");
102 1013700 : params.addPrivateParam<unsigned int>("_var_num");
103 1013700 : params.addPrivateParam<THREAD_ID>("tid");
104 :
105 506850 : params.addClassDescription(
106 : "Base class for Moose variables. This should never be the terminal object type");
107 1013700 : return params;
108 506850 : }
109 :
110 190158 : MooseVariableBase::MooseVariableBase(const InputParameters & parameters)
111 : : MooseObject(parameters),
112 : BlockRestrictable(this),
113 : OutputInterface(parameters),
114 : SetupInterface(this),
115 190158 : _sys(*getParam<SystemBase *>("_system_base")), // TODO: get from _fe_problem_base
116 570474 : _fe_type(Utility::string_to_enum<Order>(getParam<MooseEnum>("order")),
117 570474 : Utility::string_to_enum<FEFamily>(getParam<MooseEnum>("family"))),
118 380316 : _var_num(getParam<unsigned int>("_var_num")),
119 380316 : _is_eigen(getParam<bool>("eigen")),
120 380316 : _var_kind(getParam<Moose::VarKindType>("_var_kind")),
121 190158 : _subproblem(_sys.subproblem()),
122 190158 : _variable(_sys.system().variable(_var_num)),
123 380316 : _assembly(_subproblem.assembly(getParam<THREAD_ID>("_tid"),
124 190158 : (_var_kind == Moose::VAR_SOLVER) ? _sys.number() : 0)),
125 190158 : _dof_map(_sys.dofMap()),
126 190158 : _mesh(_subproblem.mesh()),
127 380316 : _tid(getParam<THREAD_ID>("tid")),
128 380316 : _count(getParam<unsigned int>("components")),
129 380316 : _scaling_factor(_count, 1.0),
130 950790 : _use_dual(getParam<bool>("use_dual"))
131 : {
132 761096 : scalingFactor(isParamValid("scaling") ? getParam<std::vector<Real>>("scaling")
133 379852 : : std::vector<Real>(_count, 1.));
134 587106 : if (getParam<bool>("fv") && getParam<bool>("eigen"))
135 0 : paramError("eigen", "finite volume (fv=true) variables do not have eigen support");
136 570474 : if (getParam<bool>("fv") && _fe_type.family != MONOMIAL)
137 0 : paramError("family", "finite volume (fv=true) variables must be have MONOMIAL family");
138 570474 : if (getParam<bool>("fv") && _fe_type.order != 0)
139 0 : paramError("order", "finite volume (fv=true) variables currently support CONST order only");
140 :
141 570474 : if (isParamValid("array_var_component_names"))
142 : {
143 2622 : auto name0 = _sys.system().variable(_var_num).name();
144 2622 : std::size_t found = name0.find_last_of("_");
145 2622 : if (found == std::string::npos)
146 0 : mooseError("Error creating ArrayMooseVariable name with base name ", name0);
147 2622 : const auto name_base = name0.substr(0, found);
148 5244 : const auto & name_endings = getParam<std::vector<std::string>>("array_var_component_names");
149 8604 : for (const auto & name : name_endings)
150 5982 : _array_var_component_names.push_back(name_base + '_' + name);
151 2622 : }
152 187536 : else if (_count != 1)
153 0 : mooseError("Component size of normal variable (_count) must be one; equals " +
154 0 : std::to_string(_count) + "");
155 :
156 : // check parameters set automatically by SystemBase related to array variables
157 : mooseAssert(
158 : isArray() ? _count == _array_var_component_names.size() : true,
159 : "An inconsistent numer of names or no names were provided for array variable components");
160 190158 : if (_count > 1)
161 : mooseAssert(isArray(), "Must be true with component > 1");
162 :
163 190158 : if (!blockRestricted())
164 179960 : _is_lower_d = false;
165 : else
166 : {
167 10198 : const auto & blk_ids = blockIDs();
168 10198 : if (blk_ids.empty())
169 0 : paramError("block",
170 0 : "Every variable should have at least one subdomain. For '" + name() +
171 : "' no subdomain is defined.");
172 :
173 10198 : _is_lower_d = _mesh.isLowerD(*blk_ids.begin());
174 : #ifdef DEBUG
175 : for (auto it = ++blk_ids.begin(); it != blk_ids.end(); ++it)
176 : if (_is_lower_d != _mesh.isLowerD(*it))
177 : mooseError("A user should not specify a mix of lower-dimensional and higher-dimensional "
178 : "blocks for variable '" +
179 : name() + "'. This variable is " + (_is_lower_d ? "" : "not ") +
180 : "recognised as lower-dimensional, but is also defined for the " +
181 : (_is_lower_d ? "higher" : "lower") + "-dimensional block '" +
182 : _mesh.getSubdomainName(*it) + "' (block-id " + std::to_string(*it) + ").");
183 : #endif
184 : }
185 190158 : }
186 :
187 : const std::string &
188 26252 : MooseVariableBase::arrayVariableComponent(const unsigned int i) const
189 : {
190 : mooseAssert(
191 : i < _array_var_component_names.size(),
192 : "Requested array variable component number is greater than the number of component names.");
193 26252 : return _array_var_component_names[i];
194 : }
195 :
196 : const std::vector<dof_id_type> &
197 25876 : MooseVariableBase::allDofIndices() const
198 : {
199 25876 : const auto it = _sys.subproblem()._var_dof_map.find(name());
200 25876 : if (it != _sys.subproblem()._var_dof_map.end())
201 51752 : return it->second;
202 : else
203 0 : mooseError("VariableAllDoFMap not prepared for ",
204 0 : name(),
205 : " . Check nonlocal coupling requirement for the variable.");
206 : }
207 :
208 : Order
209 382749205 : MooseVariableBase::order() const
210 : {
211 382749205 : return _fe_type.order;
212 : }
213 :
214 : std::vector<dof_id_type>
215 142666484 : MooseVariableBase::componentDofIndices(const std::vector<dof_id_type> & dof_indices,
216 : unsigned int component) const
217 : {
218 142666484 : std::vector<dof_id_type> new_dof_indices(dof_indices);
219 142666484 : if (component != 0)
220 : {
221 6167982 : if (isNodal())
222 30510962 : for (auto & id : new_dof_indices)
223 24415624 : id += component;
224 : else
225 : {
226 72644 : unsigned int n = dof_indices.size();
227 476896 : for (auto & id : new_dof_indices)
228 404252 : id += component * n;
229 : }
230 : }
231 142666484 : return new_dof_indices;
232 0 : }
233 :
234 : void
235 191474 : MooseVariableBase::scalingFactor(const std::vector<Real> & factor)
236 : {
237 : mooseAssert(factor.size() == _count, "Inconsistent scaling factor size");
238 386319 : for (const auto i : make_range(_count))
239 194845 : _scaling_factor[i] = factor[i];
240 191474 : }
241 :
242 : void
243 183464 : MooseVariableBase::initialSetup()
244 : {
245 : // Currently the scaling vector is only used through AD residual computing objects
246 196173 : if ((_var_kind == Moose::VAR_SOLVER) && _subproblem.haveADObjects() &&
247 37523 : (_subproblem.automaticScaling() || (std::find_if(_scaling_factor.begin(),
248 : _scaling_factor.end(),
249 12407 : [](const Real element) {
250 24814 : return !MooseUtils::absoluteFuzzyEqual(
251 12407 : element, 1.);
252 208278 : }) != _scaling_factor.end())))
253 :
254 363 : _sys.addScalingVector();
255 183464 : }
256 :
257 : const NumericVector<Number> &
258 1062960 : MooseVariableBase::getSolution(const Moose::StateArg & state) const
259 : {
260 : // It's not safe to use solutionState(0) because it returns the libMesh System solution member
261 : // which is wrong during things like finite difference Jacobian evaluation, e.g. when PETSc
262 : // perturbs the solution vector we feed these perturbations into the current_local_solution
263 : // while the libMesh solution is frozen in the non-perturbed state
264 1062960 : return (state.state == 0) ? *this->_sys.currentSolution()
265 1062960 : : this->_sys.solutionState(state.state, state.iteration_type);
266 : }
|