LCOV - code coverage report
Current view: top level - src/auxkernels - AuxKernel.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 203 224 90.6 %
Date: 2025-07-17 01:28:37 Functions: 29 47 61.7 %
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 "AuxKernel.h"
      11             : 
      12             : // local includes
      13             : #include "FEProblem.h"
      14             : #include "SubProblem.h"
      15             : #include "AuxiliarySystem.h"
      16             : #include "MooseTypes.h"
      17             : #include "Assembly.h"
      18             : #include "MortarNodalAuxKernel.h"
      19             : 
      20             : #include "libmesh/numeric_vector.h"
      21             : #include "libmesh/dof_map.h"
      22             : #include "libmesh/quadrature.h"
      23             : #include "libmesh/boundary_info.h"
      24             : 
      25             : template <typename ComputeValueType>
      26             : InputParameters
      27     2157238 : AuxKernelTempl<ComputeValueType>::validParams()
      28             : {
      29     2157238 :   InputParameters params = MooseObject::validParams();
      30     2157238 :   params += BlockRestrictable::validParams();
      31     2157238 :   params += BoundaryRestrictable::validParams();
      32     2157238 :   params += RandomInterface::validParams();
      33     2157238 :   params += MeshChangedInterface::validParams();
      34     2157238 :   params += MaterialPropertyInterface::validParams();
      35     2157238 :   params += FunctorInterface::validParams();
      36             : 
      37             :   // Add the SetupInterface parameter 'execute_on' with 'linear' and 'timestep_end'
      38     2157238 :   params += SetupInterface::validParams();
      39     2157238 :   ExecFlagEnum & exec_enum = params.set<ExecFlagEnum>("execute_on", true);
      40     2157238 :   exec_enum.addAvailableFlags(EXEC_PRE_DISPLACE);
      41     6471714 :   exec_enum = {EXEC_LINEAR, EXEC_TIMESTEP_END};
      42     2157238 :   params.setDocString("execute_on", exec_enum.getDocString());
      43             : 
      44     2157238 :   params.addRequiredParam<AuxVariableName>("variable",
      45             :                                            "The name of the variable that this object applies to");
      46             : 
      47     6471714 :   params.addParam<bool>("use_displaced_mesh",
      48     4314476 :                         false,
      49             :                         "Whether or not this object should use the "
      50             :                         "displaced mesh for computation.  Note that "
      51             :                         "in the case this is true but no "
      52             :                         "displacements are provided in the Mesh block "
      53             :                         "the undisplaced mesh will still be used.");
      54     2157238 :   params.addParamNamesToGroup("use_displaced_mesh", "Advanced");
      55     6471714 :   params.addParam<bool>("check_boundary_restricted",
      56     4314476 :                         true,
      57             :                         "Whether to check for multiple element sides on the boundary "
      58             :                         "in the case of a boundary restricted, element aux variable. "
      59             :                         "Setting this to false will allow contribution to a single element's "
      60             :                         "elemental value(s) from multiple boundary sides on the same element "
      61             :                         "(example: when the restricted boundary exists on two or more sides "
      62             :                         "of an element, such as at a corner of a mesh");
      63             : 
      64             :   // This flag is set to true if the AuxKernelTempl is being used on a boundary
      65     2157238 :   params.addPrivateParam<bool>("_on_boundary", false);
      66             : 
      67     2157238 :   params.addRelationshipManager("GhostLowerDElems",
      68             :                                 Moose::RelationshipManagerType::GEOMETRIC |
      69             :                                     Moose::RelationshipManagerType::ALGEBRAIC);
      70             : 
      71     2157238 :   params.declareControllable("enable"); // allows Control to enable/disable this type of object
      72     2157238 :   params.registerBase("AuxKernel");
      73     2157238 :   params.registerSystemAttributeName("AuxKernel");
      74             : 
      75     2157238 :   if (typeid(AuxKernelTempl<ComputeValueType>).name() == typeid(VectorAuxKernel).name())
      76      100248 :     params.registerBase("VectorAuxKernel");
      77     2157238 :   if (typeid(AuxKernelTempl<ComputeValueType>).name() == typeid(ArrayAuxKernel).name())
      78      114442 :     params.registerBase("ArrayAuxKernel");
      79     2157238 :   return params;
      80     2157238 : }
      81             : 
      82             : template <typename ComputeValueType>
      83       68664 : AuxKernelTempl<ComputeValueType>::AuxKernelTempl(const InputParameters & parameters)
      84             :   : MooseObject(parameters),
      85             :     MooseVariableInterface<ComputeValueType>(
      86             :         this,
      87             :         parameters.getCheckedPointerParam<SystemBase *>("_sys")
      88      205988 :             ->getVariable(parameters.get<THREAD_ID>("_tid"),
      89      137324 :                           parameters.get<AuxVariableName>("variable"))
      90       68660 :             .isNodal(),
      91             :         "variable",
      92             :         Moose::VarKindType::VAR_AUXILIARY,
      93             :         std::is_same<Real, ComputeValueType>::value
      94             :             ? Moose::VarFieldType::VAR_FIELD_STANDARD
      95             :             : (std::is_same<RealVectorValue, ComputeValueType>::value
      96             :                    ? Moose::VarFieldType::VAR_FIELD_VECTOR
      97             :                    : Moose::VarFieldType::VAR_FIELD_ARRAY)),
      98             :     BlockRestrictable(this),
      99       68660 :     BoundaryRestrictable(this, mooseVariableBase()->isNodal()),
     100             :     SetupInterface(this),
     101       68660 :     CoupleableMooseVariableDependencyIntermediateInterface(this, mooseVariableBase()->isNodal()),
     102             :     FunctionInterface(this),
     103             :     UserObjectInterface(this),
     104             :     TransientInterface(this),
     105             :     MaterialPropertyInterface(this, blockIDs(), boundaryIDs()),
     106             :     PostprocessorInterface(this),
     107             :     DependencyResolverInterface(),
     108             :     RandomInterface(parameters,
     109      137320 :                     *parameters.getCheckedPointerParam<FEProblemBase *>("_fe_problem_base"),
     110       68660 :                     parameters.get<THREAD_ID>("_tid"),
     111       68660 :                     mooseVariableBase()->isNodal()),
     112             :     GeometricSearchInterface(this),
     113             :     Restartable(this, "AuxKernels"),
     114             :     MeshChangedInterface(parameters),
     115             :     VectorPostprocessorInterface(this),
     116             :     ElementIDInterface(this),
     117             :     NonADFunctorInterface(this),
     118       68660 :     _check_boundary_restricted(getParam<bool>("check_boundary_restricted")),
     119       68660 :     _subproblem(*getCheckedPointerParam<SubProblem *>("_subproblem")),
     120       68660 :     _sys(*getCheckedPointerParam<SystemBase *>("_sys")),
     121       68660 :     _nl_sys(*getCheckedPointerParam<SystemBase *>("_nl_sys")),
     122       68660 :     _aux_sys(static_cast<AuxiliarySystem &>(_sys)),
     123       68660 :     _tid(parameters.get<THREAD_ID>("_tid")),
     124      205980 :     _var(_aux_sys.getActualFieldVariable<ComputeValueType>(
     125       68660 :         _tid, parameters.get<AuxVariableName>("variable"))),
     126       68660 :     _nodal(_var.isNodal()),
     127       68660 :     _u(_nodal ? _var.nodalValueArray() : _var.sln()),
     128             : 
     129       68660 :     _assembly(_subproblem.assembly(_tid, 0)),
     130       68660 :     _bnd(boundaryRestricted()),
     131       68660 :     _mesh(_subproblem.mesh()),
     132             : 
     133       68660 :     _test(_bnd ? _var.phiFace() : _var.phi()),
     134       68660 :     _q_point(_bnd ? _assembly.qPointsFace() : _assembly.qPoints()),
     135       68660 :     _qrule(_bnd ? _assembly.qRuleFace() : _assembly.qRule()),
     136       68660 :     _JxW(_bnd ? _assembly.JxWFace() : _assembly.JxW()),
     137       68660 :     _coord(_assembly.coordTransformation()),
     138             : 
     139       68660 :     _current_elem(_assembly.elem()),
     140       68660 :     _current_side(_assembly.side()),
     141       68660 :     _current_elem_volume(_assembly.elemVolume()),
     142       68660 :     _current_side_volume(_assembly.sideElemVolume()),
     143             : 
     144       68660 :     _current_node(_assembly.node()),
     145       68660 :     _current_boundary_id(_assembly.currentBoundaryID()),
     146       68660 :     _solution(_aux_sys.solution()),
     147             : 
     148       68660 :     _current_lower_d_elem(_assembly.lowerDElem()),
     149      686604 :     _coincident_lower_d_calc(_bnd && !isNodal() && _var.isLowerD())
     150             : {
     151       68660 :   addMooseVariableDependency(&_var);
     152       68660 :   _supplied_vars.insert(parameters.get<AuxVariableName>("variable"));
     153             : 
     154       68660 :   if (_bnd && !isNodal() && !_coincident_lower_d_calc && _check_boundary_restricted)
     155             :   {
     156             :     // when the variable is elemental and this aux kernel operates on boundaries,
     157             :     // we need to check that no elements are visited more than once through visiting
     158             :     // all the sides on the boundaries
     159        1214 :     auto boundaries = _mesh.getMesh().get_boundary_info().build_side_list();
     160        1214 :     std::set<dof_id_type> elements;
     161      180823 :     for (const auto & t : boundaries)
     162             :     {
     163      179613 :       if (hasBoundary(std::get<2>(t)))
     164             :       {
     165       67219 :         const auto eid = std::get<0>(t);
     166       67219 :         const auto stat = elements.insert(eid);
     167       67219 :         if (!stat.second) // already existed in the set
     168           4 :           mooseError(
     169             :               "Boundary restricted auxiliary kernel '",
     170           4 :               name(),
     171             :               "' has element (id=",
     172             :               eid,
     173             :               ") connected with more than one boundary sides.\nTo skip this error check, "
     174             :               "set 'check_boundary_restricted = false'.\nRefer to the AuxKernel "
     175             :               "documentation on boundary restricted aux kernels for understanding this error.");
     176             :       }
     177             :     }
     178        1210 :   }
     179             : 
     180             :   // Check for supported variable types
     181             :   // Any 'nodal' family that actually has DoFs outside of nodes, or gradient dofs at nodes is
     182             :   // not properly set by AuxKernelTempl::compute
     183             :   // NOTE: We could add a few exceptions, lower order from certain unsupported families and on
     184             :   //       certain element types only have value-DoFs on nodes
     185       68656 :   const auto type = _var.feType();
     186       68656 :   if (_var.isNodal() && !((type.family == LAGRANGE) || (type.order <= FIRST)))
     187           0 :     paramError("variable",
     188           0 :                "Variable family " + Moose::stringify(type.family) + " is not supported at order " +
     189             :                    Moose::stringify(type.order) + " by the AuxKernel system.");
     190       68656 : }
     191             : 
     192             : template <typename ComputeValueType>
     193             : const std::set<std::string> &
     194      223387 : AuxKernelTempl<ComputeValueType>::getRequestedItems()
     195             : {
     196      223387 :   return _depend_vars;
     197             : }
     198             : 
     199             : template <typename ComputeValueType>
     200             : const std::set<std::string> &
     201      223387 : AuxKernelTempl<ComputeValueType>::getSuppliedItems()
     202             : {
     203      223387 :   return _supplied_vars;
     204             : }
     205             : 
     206             : template <typename ComputeValueType>
     207             : void
     208        4936 : AuxKernelTempl<ComputeValueType>::addUserObjectDependencyHelper(const UserObject & uo) const
     209             : {
     210        4936 :   _depend_uo.insert(uo.name());
     211        5011 :   for (const auto & indirect_dependent : uo.getDependObjects())
     212          75 :     _depend_uo.insert(indirect_dependent);
     213        4936 : }
     214             : 
     215             : template <typename ComputeValueType>
     216             : void
     217         210 : AuxKernelTempl<ComputeValueType>::addPostprocessorDependencyHelper(
     218             :     const PostprocessorName & name) const
     219             : {
     220         210 :   getUserObjectBaseByName(name); // getting the UO will call addUserObjectDependencyHelper()
     221         210 : }
     222             : 
     223             : template <typename ComputeValueType>
     224             : void
     225         227 : AuxKernelTempl<ComputeValueType>::addVectorPostprocessorDependencyHelper(
     226             :     const VectorPostprocessorName & name) const
     227             : {
     228         227 :   getUserObjectBaseByName(name); // getting the UO will call addUserObjectDependencyHelper()
     229         227 : }
     230             : 
     231             : template <typename ComputeValueType>
     232             : void
     233        8317 : AuxKernelTempl<ComputeValueType>::coupledCallback(const std::string & var_name, bool is_old) const
     234             : {
     235        8317 :   if (!is_old)
     236             :   {
     237        8126 :     const auto & var_names = getParam<std::vector<VariableName>>(var_name);
     238        8126 :     _depend_vars.insert(var_names.begin(), var_names.end());
     239             :   }
     240        8317 : }
     241             : 
     242             : template <typename ComputeValueType>
     243             : const VariableValue &
     244          69 : AuxKernelTempl<ComputeValueType>::coupledDot(const std::string & var_name, unsigned int comp) const
     245             : {
     246          69 :   auto var = getVar(var_name, comp);
     247          69 :   if (var->kind() == Moose::VAR_AUXILIARY)
     248           8 :     mooseError(
     249           4 :         name(),
     250             :         ": Unable to couple time derivative of an auxiliary variable into the auxiliary system.");
     251             : 
     252          65 :   return Coupleable::coupledDot(var_name, comp);
     253             : }
     254             : 
     255             : template <typename ComputeValueType>
     256             : const VariableValue &
     257           0 : AuxKernelTempl<ComputeValueType>::coupledDotDu(const std::string & var_name,
     258             :                                                unsigned int comp) const
     259             : {
     260           0 :   auto var = getVar(var_name, comp);
     261           0 :   if (var->kind() == Moose::VAR_AUXILIARY)
     262           0 :     mooseError(
     263           0 :         name(),
     264             :         ": Unable to couple time derivative of an auxiliary variable into the auxiliary system.");
     265             : 
     266           0 :   return Coupleable::coupledDotDu(var_name, comp);
     267             : }
     268             : 
     269             : template <>
     270             : void
     271      172480 : AuxKernelTempl<Real>::setDofValueHelper(const Real & value)
     272             : {
     273             :   mooseAssert(_n_local_dofs == 1,
     274             :               "Should only be calling setDofValue if there is one dof for the aux var");
     275      172480 :   _var.setDofValue(value, 0);
     276      172480 : }
     277             : 
     278             : template <>
     279             : void
     280           0 : AuxKernelTempl<RealVectorValue>::setDofValueHelper(const RealVectorValue &)
     281             : {
     282           0 :   mooseError("Not implemented");
     283             : }
     284             : 
     285             : template <typename ComputeValueType>
     286             : void
     287      118000 : AuxKernelTempl<ComputeValueType>::insert()
     288             : {
     289      118000 :   if (_coincident_lower_d_calc)
     290        1644 :     _var.insertLower(_aux_sys.solution());
     291             :   else
     292      116356 :     _var.insert(_aux_sys.solution());
     293      118000 : }
     294             : 
     295             : template <typename ComputeValueType>
     296             : void
     297    45960456 : AuxKernelTempl<ComputeValueType>::compute()
     298             : {
     299    45960456 :   precalculateValue();
     300             : 
     301    45960456 :   if (isNodal()) /* nodal variables */
     302             :   {
     303             :     mooseAssert(!_coincident_lower_d_calc,
     304             :                 "Nodal evaluations are point evaluations. We don't have to concern ourselves with "
     305             :                 "coincidence of lower-d blocks and higher-d faces because they share nodes");
     306    30708298 :     if (_var.isNodalDefined())
     307             :     {
     308    28314274 :       _qp = 0;
     309    28314274 :       ComputeValueType value = computeValue();
     310             :       // update variable data, which is referenced by other kernels, so the value is up-to-date
     311    28314270 :       _var.setNodalValue(value);
     312             :     }
     313             :   }
     314             :   else /* elemental variables */
     315             :   {
     316    15252158 :     _n_local_dofs = _coincident_lower_d_calc ? _var.dofIndicesLower().size() : _var.numberOfDofs();
     317             : 
     318    15252158 :     if (_coincident_lower_d_calc)
     319             :     {
     320        1650 :       static const std::string lower_error = "Make sure that the lower-d variable lives on a "
     321             :                                              "lower-d block that is a superset of the boundary";
     322        1650 :       if (!_current_lower_d_elem)
     323           3 :         mooseError("No lower-dimensional element. ", lower_error);
     324        1647 :       if (!_n_local_dofs)
     325           3 :         mooseError("No degrees of freedom. ", lower_error);
     326             :     }
     327             : 
     328    15252152 :     if (_n_local_dofs == 1) /* p0 */
     329             :     {
     330    14684475 :       ComputeValueType value = 0;
     331    86967800 :       for (_qp = 0; _qp < _qrule->n_points(); _qp++)
     332    72283337 :         value += _JxW[_qp] * _coord[_qp] * computeValue();
     333    14684463 :       value /= (_bnd ? _current_side_volume : _current_elem_volume);
     334    14684463 :       if (_var.isFV())
     335      172480 :         setDofValueHelper(value);
     336             :       else
     337             :       {
     338             :         // update the variable data referenced by other kernels.
     339             :         // Note that this will update the values at the quadrature points too
     340             :         // (because this is an Elemental variable)
     341    14511983 :         if (_coincident_lower_d_calc)
     342             :         {
     343         822 :           _local_sol.resize(1);
     344             :           if constexpr (std::is_same<Real, ComputeValueType>::value)
     345         822 :             _local_sol(0) = value;
     346             :           else
     347             :             mooseAssert(false, "We should not enter the single dof branch with a vector variable");
     348         822 :           _var.setLowerDofValues(_local_sol);
     349             :         }
     350             :         else
     351    14511161 :           _var.setNodalValue(value);
     352             :       }
     353             :     }
     354             :     else /* high-order */
     355             :     {
     356      567677 :       _local_re.resize(_n_local_dofs);
     357      567677 :       _local_re.zero();
     358      567677 :       _local_ke.resize(_n_local_dofs, _n_local_dofs);
     359      567677 :       _local_ke.zero();
     360             : 
     361      567677 :       const auto & test = _coincident_lower_d_calc ? _var.phiLower() : _test;
     362             : 
     363             :       // assemble the local mass matrix and the load
     364     3278953 :       for (unsigned int i = 0; i < test.size(); i++)
     365    24756903 :         for (_qp = 0; _qp < _qrule->n_points(); _qp++)
     366             :         {
     367    22045627 :           ComputeValueType t = _JxW[_qp] * _coord[_qp] * test[i][_qp];
     368    22045627 :           _local_re(i) += t * computeValue();
     369   172492584 :           for (unsigned int j = 0; j < test.size(); j++)
     370   150446960 :             _local_ke(i, j) += t * test[j][_qp];
     371             :         }
     372             :       // mass matrix is always SPD but in case of boundary restricted, it will be rank deficient
     373      567674 :       _local_sol.resize(_n_local_dofs);
     374      567674 :       if (_bnd)
     375        4854 :         _local_ke.svd_solve(_local_re, _local_sol);
     376             :       else
     377      562820 :         _local_ke.cholesky_solve(_local_re, _local_sol);
     378             : 
     379      567674 :       _coincident_lower_d_calc ? _var.setLowerDofValues(_local_sol) : _var.setDofValues(_local_sol);
     380             :     }
     381             :   }
     382    45960431 : }
     383             : 
     384             : template <>
     385             : void
     386      575344 : AuxKernelTempl<RealEigenVector>::compute()
     387             : {
     388      575344 :   precalculateValue();
     389             : 
     390      575344 :   if (isNodal()) /* nodal variables */
     391             :   {
     392      570872 :     if (_var.isNodalDefined())
     393             :     {
     394      558072 :       _qp = 0;
     395      558072 :       RealEigenVector value = computeValue();
     396             :       // update variable data, which is referenced by other kernels, so the value is up-to-date
     397      558072 :       _var.setNodalValue(value);
     398      558072 :     }
     399             :   }
     400             :   else /* elemental variables */
     401             :   {
     402        4472 :     _n_local_dofs = _var.numberOfDofs();
     403        4472 :     if (_n_local_dofs == 1) /* p0 */
     404             :     {
     405           0 :       RealEigenVector value = RealEigenVector::Zero(_var.count());
     406           0 :       for (_qp = 0; _qp < _qrule->n_points(); _qp++)
     407           0 :         value += _JxW[_qp] * _coord[_qp] * computeValue();
     408           0 :       value /= (_bnd ? _current_side_volume : _current_elem_volume);
     409             :       // update the variable data referenced by other kernels.
     410             :       // Note that this will update the values at the quadrature points too
     411             :       // (because this is an Elemental variable)
     412           0 :       _var.setNodalValue(value);
     413           0 :     }
     414             :     else /* high-order */
     415             :     {
     416        4472 :       _local_re.resize(_n_local_dofs);
     417      117928 :       for (unsigned int i = 0; i < _local_re.size(); ++i)
     418      113456 :         _local_re(i) = RealEigenVector::Zero(_var.count());
     419        4472 :       _local_ke.resize(_n_local_dofs, _n_local_dofs);
     420        4472 :       _local_ke.zero();
     421             : 
     422             :       // assemble the local mass matrix and the load
     423      117928 :       for (unsigned int i = 0; i < _test.size(); i++)
     424     5606416 :         for (_qp = 0; _qp < _qrule->n_points(); _qp++)
     425             :         {
     426     5492960 :           Real t = _JxW[_qp] * _coord[_qp] * _test[i][_qp];
     427     5492960 :           _local_re(i) += t * computeValue();
     428   159175072 :           for (unsigned int j = 0; j < _test.size(); j++)
     429   153682112 :             _local_ke(i, j) += t * _test[j][_qp];
     430             :         }
     431             : 
     432             :       // mass matrix is always SPD
     433        4472 :       _local_sol.resize(_n_local_dofs);
     434      117928 :       for (unsigned int i = 0; i < _local_re.size(); ++i)
     435      113456 :         _local_sol(i) = RealEigenVector::Zero(_var.count());
     436        4472 :       DenseVector<Number> re(_n_local_dofs);
     437        4472 :       DenseVector<Number> sol(_n_local_dofs);
     438       17416 :       for (unsigned int i = 0; i < _var.count(); ++i)
     439             :       {
     440      351856 :         for (unsigned int j = 0; j < _n_local_dofs; ++j)
     441      338912 :           re(j) = _local_re(j)(i);
     442             : 
     443       12944 :         if (_bnd)
     444           0 :           _local_ke.svd_solve(re, sol);
     445             :         else
     446       12944 :           _local_ke.cholesky_solve(re, sol);
     447             : 
     448      351856 :         for (unsigned int j = 0; j < _n_local_dofs; ++j)
     449      338912 :           _local_sol(j)(i) = sol(j);
     450             :       }
     451             : 
     452        4472 :       _var.setDofValues(_local_sol);
     453        4472 :     }
     454             :   }
     455      575344 : }
     456             : 
     457             : template <typename ComputeValueType>
     458             : const typename OutputTools<ComputeValueType>::VariableValue &
     459         117 : AuxKernelTempl<ComputeValueType>::uOld() const
     460             : {
     461         117 :   if (_sys.solutionStatesInitialized())
     462           0 :     mooseError("The solution states have already been initialized when calling ",
     463           0 :                type(),
     464             :                "::uOld().\n\n",
     465             :                "Make sure to call uOld() within the object constructor.");
     466             : 
     467         117 :   return _nodal ? _var.nodalValueOldArray() : _var.slnOld();
     468             : }
     469             : 
     470             : template <typename ComputeValueType>
     471             : const typename OutputTools<ComputeValueType>::VariableValue &
     472          13 : AuxKernelTempl<ComputeValueType>::uOlder() const
     473             : {
     474          13 :   if (_sys.solutionStatesInitialized())
     475           0 :     mooseError("The solution states have already been initialized when calling ",
     476           0 :                type(),
     477             :                "::uOlder().\n\n",
     478             :                "Make sure to call uOlder() within the object constructor.");
     479             : 
     480          13 :   return _nodal ? _var.nodalValueOlderArray() : _var.slnOlder();
     481             : }
     482             : 
     483             : template <typename ComputeValueType>
     484             : bool
     485       21932 : AuxKernelTempl<ComputeValueType>::isMortar()
     486             : {
     487       21932 :   return dynamic_cast<MortarNodalAuxKernelTempl<ComputeValueType> *>(this) != nullptr;
     488             : }
     489             : 
     490             : // Explicitly instantiates the three versions of the AuxKernelTempl class
     491             : template class AuxKernelTempl<Real>;
     492             : template class AuxKernelTempl<RealVectorValue>;
     493             : template class AuxKernelTempl<RealEigenVector>;

Generated by: LCOV version 1.14