LCOV - code coverage report
Current view: top level - src/variables - MooseVariableBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 103 114 90.4 %
Date: 2025-07-17 01:28:37 Functions: 9 9 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      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 : }

Generated by: LCOV version 1.14