https://mooseframework.inl.gov
MooseVariableBase.C
Go to the documentation of this file.
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"
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
30 
33 {
36  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  true);
47  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 
53 
54  params.addParam<MooseEnum>(
55  "family", family, "Specifies the family of FE shape functions to use for this variable.");
56 
57  // ArrayVariable capability
58  params.addRangeCheckedParam<unsigned int>(
59  "components", 1, "components>0", "Number of components for an array variable");
60 
61  // Advanced input options
62  params.addParam<std::vector<Real>>("scaling",
63  "Specifies a scaling factor to apply to this variable");
64  params.addParam<bool>("eigen", false, "True to make this variable an eigen variable");
65  params.addParam<bool>("fv", false, "True to make this variable a finite volume variable");
66  params.addParam<bool>("array",
67  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  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  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  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  params.addParamNamesToGroup("scaling eigen", "Advanced");
92 
93  params.addParam<bool>("use_dual", false, "True to use dual basis for Lagrange multipliers");
94  params.transferParam<std::vector<Real>>(AddVariableAction::validParams(), "initial_condition");
95  params.transferParam<std::string>(AddVariableAction::validParams(), "initial_from_file_var");
96  params.addParamNamesToGroup("scaling eigen use_dual", "Advanced");
97 
98  params.registerBase("MooseVariableBase");
99  params.addPrivateParam<SystemBase *>("_system_base");
100  params.addPrivateParam<FEProblemBase *>("_fe_problem_base");
101  params.addPrivateParam<Moose::VarKindType>("_var_kind");
102  params.addPrivateParam<unsigned int>("_var_num");
103  params.addPrivateParam<THREAD_ID>("tid");
104 
105  params.addClassDescription(
106  "Base class for Moose variables. This should never be the terminal object type");
107  return params;
108 }
109 
111  : MooseObject(parameters),
112  BlockRestrictable(this),
113  OutputInterface(parameters),
114  SetupInterface(this),
115  _sys(*getParam<SystemBase *>("_system_base")), // TODO: get from _fe_problem_base
116  _fe_type(Utility::string_to_enum<Order>(getParam<MooseEnum>("order")),
117  Utility::string_to_enum<FEFamily>(getParam<MooseEnum>("family"))),
118  _var_num(getParam<unsigned int>("_var_num")),
119  _is_eigen(getParam<bool>("eigen")),
120  _var_kind(getParam<Moose::VarKindType>("_var_kind")),
121  _subproblem(_sys.subproblem()),
122  _variable(_sys.system().variable(_var_num)),
123  _assembly(_subproblem.assembly(getParam<THREAD_ID>("_tid"),
124  (_var_kind == Moose::VAR_SOLVER) ? _sys.number() : 0)),
125  _dof_map(_sys.dofMap()),
126  _mesh(_subproblem.mesh()),
127  _tid(getParam<THREAD_ID>("tid")),
128  _count(getParam<unsigned int>("components")),
129  _scaling_factor(_count, 1.0),
130  _use_dual(getParam<bool>("use_dual"))
131 {
132  scalingFactor(isParamValid("scaling") ? getParam<std::vector<Real>>("scaling")
133  : std::vector<Real>(_count, 1.));
134  if (getParam<bool>("fv") && getParam<bool>("eigen"))
135  paramError("eigen", "finite volume (fv=true) variables do not have eigen support");
136  if (getParam<bool>("fv") && _fe_type.family != MONOMIAL)
137  paramError("family", "finite volume (fv=true) variables must be have MONOMIAL family");
138  if (getParam<bool>("fv") && _fe_type.order != 0)
139  paramError("order", "finite volume (fv=true) variables currently support CONST order only");
140 
141  if (isParamValid("array_var_component_names"))
142  {
143  auto name0 = _sys.system().variable(_var_num).name();
144  std::size_t found = name0.find_last_of("_");
145  if (found == std::string::npos)
146  mooseError("Error creating ArrayMooseVariable name with base name ", name0);
147  const auto name_base = name0.substr(0, found);
148  const auto & name_endings = getParam<std::vector<std::string>>("array_var_component_names");
149  for (const auto & name : name_endings)
150  _array_var_component_names.push_back(name_base + '_' + name);
151  }
152  else if (_count != 1)
153  mooseError("Component size of normal variable (_count) must be one; equals " +
154  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  if (_count > 1)
161  mooseAssert(isArray(), "Must be true with component > 1");
162 
163  if (!blockRestricted())
164  _is_lower_d = false;
165  else
166  {
167  const auto & blk_ids = blockIDs();
168  if (blk_ids.empty())
169  paramError("block",
170  "Every variable should have at least one subdomain. For '" + name() +
171  "' no subdomain is defined.");
172 
173  _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 }
186 
187 const std::string &
188 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  return _array_var_component_names[i];
194 }
195 
196 const std::vector<dof_id_type> &
198 {
199  const auto it = _sys.subproblem()._var_dof_map.find(name());
200  if (it != _sys.subproblem()._var_dof_map.end())
201  return it->second;
202  else
203  mooseError("VariableAllDoFMap not prepared for ",
204  name(),
205  " . Check nonlocal coupling requirement for the variable.");
206 }
207 
208 Order
210 {
211  return _fe_type.order;
212 }
213 
214 std::vector<dof_id_type>
215 MooseVariableBase::componentDofIndices(const std::vector<dof_id_type> & dof_indices,
216  unsigned int component) const
217 {
218  std::vector<dof_id_type> new_dof_indices(dof_indices);
219  if (component != 0)
220  {
221  if (isNodal())
222  for (auto & id : new_dof_indices)
223  id += component;
224  else
225  {
226  unsigned int n = dof_indices.size();
227  for (auto & id : new_dof_indices)
228  id += component * n;
229  }
230  }
231  return new_dof_indices;
232 }
233 
234 void
235 MooseVariableBase::scalingFactor(const std::vector<Real> & factor)
236 {
237  mooseAssert(factor.size() == _count, "Inconsistent scaling factor size");
238  for (const auto i : make_range(_count))
239  _scaling_factor[i] = factor[i];
240 }
241 
242 void
244 {
245  // Currently the scaling vector is only used through AD residual computing objects
247  (_subproblem.automaticScaling() || (std::find_if(_scaling_factor.begin(),
248  _scaling_factor.end(),
249  [](const Real element) {
251  element, 1.);
252  }) != _scaling_factor.end())))
253 
255 }
256 
257 const NumericVector<Number> &
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  return (state.state == 0) ? *this->_sys.currentSolution()
265  : this->_sys.solutionState(state.state, state.iteration_type);
266 }
static InputParameters validParams()
const libMesh::NumericVector< libMesh::Number > & getSolution(const Moose::StateArg &state) const
Get the solution corresponding to the provided state.
virtual bool isNodal() const
Is this variable nodal.
virtual const NumericVector< Number > *const & currentSolution() const =0
The solution vector that is currently being operated on.
static InputParameters validParams()
std::vector< dof_id_type > componentDofIndices(const std::vector< dof_id_type > &dof_indices, unsigned int component) const
Obtain DoF indices of a component with the indices of the 0th component.
Order
const Variable & variable(unsigned int var) const
virtual void haveADObjects(bool have_ad_objects)
Method for setting whether we have any ad objects.
Definition: SubProblem.h:767
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
Definition: MooseUtils.h:380
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition: MooseBase.h:435
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition: MooseBase.h:384
static InputParameters validParams()
void addPrivateParam(const std::string &name, const T &value)
These method add a parameter to the InputParameters object which can be retrieved like any other para...
std::vector< std::string > _array_var_component_names
Array variable names when the variable is an array variable.
bool _is_lower_d
Whether this variable lives on lower dimensional blocks.
virtual libMesh::System & system()=0
Get the reference to the libMesh system.
virtual NumericVector< Number > & solutionState(const unsigned int state, Moose::SolutionIterationType iteration_type=Moose::SolutionIterationType::Time)
Get a state of the solution (0 = current, 1 = old, 2 = older, etc).
Definition: SystemBase.C:1431
A class to provide an common interface to objects requiring "outputs" option.
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
OrderWrapper order
virtual const std::set< SubdomainID > & blockIDs() const
Return the block subdomain ids for this object Note, if this is not block restricted, this function returns all mesh subdomain ids.
virtual bool blockRestricted() const
Returns true if this object has been restricted to a block.
void addScalingVector()
Add the scaling factor vector to the system.
Definition: SystemBase.C:1545
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
Base class for a system (of equations)
Definition: SystemBase.h:84
void initialSetup() override
Gets called at the beginning of the simulation before this object is asked to do its job...
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
const std::string & getSubdomainName(SubdomainID subdomain_id) const
Return the name of a block given an id.
Definition: MooseMesh.C:1763
static MooseEnum getNonlinearVariableFamilies()
Get the possible variable families.
bool isLowerD(const SubdomainID subdomain_id) const
Definition: MooseMesh.h:2197
static InputParameters validParams()
void registerBase(const std::string &value)
This method must be called from every base "Moose System" to create linkage with the Action System...
std::map< std::string, std::vector< dof_id_type > > _var_dof_map
Definition: SubProblem.h:674
registerMooseObject("MooseApp", MooseVariableBase)
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:99
SubProblem & _subproblem
Problem this variable is part of.
libMesh::FEType _fe_type
The FEType associated with this variable.
Every object that can be built by the factory should be derived from this class.
Definition: MooseObject.h:27
SystemBase & _sys
System this variable is part of.
SolutionIterationType iteration_type
The solution iteration type, e.g. time or nonlinear.
T string_to_enum(const std::string &s)
VarKindType
Framework-wide stuff.
Definition: MooseTypes.h:715
SubProblem & subproblem()
Definition: SystemBase.h:101
std::vector< Real > _scaling_factor
scaling factor for this variable
virtual bool isArray() const
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
Moose::VarKindType _var_kind
Variable type (see MooseTypes.h)
Real scalingFactor() const
Get the scaling factor for this variable.
virtual void automaticScaling(bool automatic_scaling)
Automatic scaling setter.
Definition: SubProblem.C:1155
const unsigned int _count
Number of variables in the array.
void transferParam(const InputParameters &source_param, const std::string &name, const std::string &new_name="", const std::string &new_description="")
A routine to transfer a parameter from one class&#39; validParams to another.
MONOMIAL
MooseMesh & _mesh
mesh the variable is active in
libMesh::Order order() const
Get the order of this variable Note: Order enum can be implicitly converted to unsigned int...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::vector< dof_id_type > & allDofIndices() const
Get all global dofindices for the variable.
unsigned int _var_num
variable number (from libMesh)
const std::string & arrayVariableComponent(const unsigned int i) const
Returns the variable name of a component of an array variable.
An interface that restricts an object to subdomains via the &#39;blocks&#39; input parameter.
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:267
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
State argument for evaluating functors.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseBase.h:195
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
const std::string & name() const
static InputParameters validParams()
Definition: MooseObject.C:25
FEFamily
void ErrorVector unsigned int
MooseVariableBase(const InputParameters &parameters)
unsigned int state
The state.
Base variable class.
unsigned int THREAD_ID
Definition: MooseTypes.h:209
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...