LCOV - code coverage report
Current view: top level - src/variables - MooseVariableBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: fef103 Lines: 105 116 90.5 %
Date: 2025-09-03 20:01:23 Functions: 10 10 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14