LCOV - code coverage report
Current view: top level - include/base - Assembly.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 863ef6 Lines: 344 394 87.3 %
Date: 2025-10-15 18:16:15 Functions: 175 198 88.4 %
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             : #pragma once
      11             : 
      12             : #include "DenseMatrix.h"
      13             : #include "MooseArray.h"
      14             : #include "MooseTypes.h"
      15             : #include "MooseVariableFE.h"
      16             : #include "MoosePassKey.h"
      17             : #include "ArbitraryQuadrature.h"
      18             : 
      19             : #include "libmesh/dense_vector.h"
      20             : #include "libmesh/enum_quadrature_type.h"
      21             : #include "libmesh/fe_type.h"
      22             : #include "libmesh/point.h"
      23             : #include "libmesh/fe_base.h"
      24             : #include "libmesh/numeric_vector.h"
      25             : #include "libmesh/elem_side_builder.h"
      26             : 
      27             : #include <unordered_map>
      28             : 
      29             : // libMesh forward declarations
      30             : namespace libMesh
      31             : {
      32             : class DofMap;
      33             : class CouplingMatrix;
      34             : class Elem;
      35             : template <typename>
      36             : class VectorValue;
      37             : typedef VectorValue<Real> RealVectorValue;
      38             : template <typename T>
      39             : class FEGenericBase;
      40             : typedef FEGenericBase<Real> FEBase;
      41             : typedef FEGenericBase<VectorValue<Real>> FEVectorBase;
      42             : class Node;
      43             : template <typename T>
      44             : class NumericVector;
      45             : template <typename T>
      46             : class SparseMatrix;
      47             : class StaticCondensation;
      48             : }
      49             : 
      50             : // MOOSE Forward Declares
      51             : class FaceInfo;
      52             : class MooseMesh;
      53             : class ArbitraryQuadrature;
      54             : class SystemBase;
      55             : class MooseVariableFieldBase;
      56             : class MooseVariableBase;
      57             : template <typename>
      58             : class MooseVariableFE;
      59             : class MooseVariableScalar;
      60             : typedef MooseVariableFE<Real> MooseVariable;
      61             : typedef MooseVariableFE<RealVectorValue> VectorMooseVariable;
      62             : typedef MooseVariableFE<RealEigenVector> ArrayMooseVariable;
      63             : class XFEMInterface;
      64             : class SubProblem;
      65             : class NodeFaceConstraint;
      66             : 
      67             : #ifdef MOOSE_KOKKOS_ENABLED
      68             : namespace Moose::Kokkos
      69             : {
      70             : class Assembly;
      71             : }
      72             : #endif
      73             : 
      74             : // Assembly.h does not import Moose.h nor libMeshReducedNamespace.h
      75             : using libMesh::FEBase;
      76             : using libMesh::FEFamily;
      77             : using libMesh::FEType;
      78             : using libMesh::FEVectorBase;
      79             : using libMesh::LAGRANGE_VEC;
      80             : using libMesh::Order;
      81             : using libMesh::QuadratureType;
      82             : 
      83             : /// Computes a conversion multiplier for use when computing integraals for the
      84             : /// current coordinate system type.  This allows us to handle cases where we use RZ,
      85             : /// spherical, or other non-cartesian coordinate systems. The factor returned
      86             : /// by this function should generally be multiplied against all integration
      87             : /// terms.  Note that the computed factor is particular to a specific point on
      88             : /// the mesh.  The result is stored in the factor argument.  point is the point
      89             : /// at which to compute the factor.  point and factor can be either Point and
      90             : /// Real or ADPoint and ADReal.
      91             : template <typename P, typename C>
      92             : void coordTransformFactor(const SubProblem & s,
      93             :                           SubdomainID sub_id,
      94             :                           const P & point,
      95             :                           C & factor,
      96             :                           SubdomainID neighbor_sub_id = libMesh::Elem::invalid_subdomain_id);
      97             : 
      98             : template <typename P, typename C>
      99             : void coordTransformFactor(const MooseMesh & mesh,
     100             :                           SubdomainID sub_id,
     101             :                           const P & point,
     102             :                           C & factor,
     103             :                           SubdomainID neighbor_sub_id = libMesh::Elem::invalid_subdomain_id);
     104             : 
     105             : /**
     106             :  * Keeps track of stuff related to assembling
     107             :  *
     108             :  */
     109             : class Assembly
     110             : {
     111             : public:
     112             :   Assembly(SystemBase & sys, THREAD_ID tid);
     113             :   virtual ~Assembly();
     114             : 
     115             :   /**
     116             :    * Workaround for C++ compilers thinking they can't just cast a
     117             :    * const-reference-to-pointer to const-reference-to-const-pointer
     118             :    */
     119             :   template <typename T>
     120   115799544 :   static const T * const & constify_ref(T * const & inref)
     121             :   {
     122   115799544 :     const T * const * ptr = &inref;
     123   115799544 :     return *ptr;
     124             :   }
     125             : 
     126             :   /**
     127             :    * Get a reference to a pointer that will contain the current volume FE.
     128             :    * @param type The type of FE
     129             :    * @param dim The dimension of the current volume
     130             :    * @return A _reference_ to the pointer.  Make sure to store this as a reference!
     131             :    */
     132        4790 :   const FEBase * const & getFE(FEType type, unsigned int dim) const
     133             :   {
     134        4790 :     buildFE(type);
     135        4790 :     return constify_ref(_fe[dim][type]);
     136             :   }
     137             : 
     138             :   /**
     139             :    * Get a reference to a pointer that will contain the current 'neighbor' FE.
     140             :    * @param type The type of FE
     141             :    * @param dim The dimension of the current volume
     142             :    * @return A _reference_ to the pointer.  Make sure to store this as a reference!
     143             :    */
     144             :   const FEBase * const & getFENeighbor(FEType type, unsigned int dim) const
     145             :   {
     146             :     buildNeighborFE(type);
     147             :     return constify_ref(_fe_neighbor[dim][type]);
     148             :   }
     149             : 
     150             :   /**
     151             :    * Get a reference to a pointer that will contain the current "face" FE.
     152             :    * @param type The type of FE
     153             :    * @param dim The dimension of the current face
     154             :    * @return A _reference_ to the pointer.  Make sure to store this as a reference!
     155             :    */
     156             :   const FEBase * const & getFEFace(FEType type, unsigned int dim) const
     157             :   {
     158             :     buildFaceFE(type);
     159             :     return constify_ref(_fe_face[dim][type]);
     160             :   }
     161             : 
     162             :   /**
     163             :    * Get a reference to a pointer that will contain the current "neighbor" FE.
     164             :    * @param type The type of FE
     165             :    * @param dim The dimension of the neighbor face
     166             :    * @return A _reference_ to the pointer.  Make sure to store this as a reference!
     167             :    */
     168             :   const FEBase * const & getFEFaceNeighbor(FEType type, unsigned int dim) const
     169             :   {
     170             :     buildFaceNeighborFE(type);
     171             :     return constify_ref(_fe_face_neighbor[dim][type]);
     172             :   }
     173             : 
     174             :   /**
     175             :    * Get a reference to a pointer that will contain the current volume FEVector.
     176             :    * @param type The type of FEVector
     177             :    * @param dim The dimension of the current volume
     178             :    * @return A _reference_ to the pointer.  Make sure to store this as a reference!
     179             :    */
     180             :   const FEVectorBase * const & getVectorFE(FEType type, unsigned int dim) const
     181             :   {
     182             :     buildVectorFE(type);
     183             :     return constify_ref(_vector_fe[dim][type]);
     184             :   }
     185             : 
     186             :   /**
     187             :    * GetVector a reference to a pointer that will contain the current 'neighbor' FE.
     188             :    * @param type The type of FE
     189             :    * @param dim The dimension of the current volume
     190             :    * @return A _reference_ to the pointer.  Make sure to store this as a reference!
     191             :    */
     192             :   const FEVectorBase * const & getVectorFENeighbor(FEType type, unsigned int dim) const
     193             :   {
     194             :     buildVectorNeighborFE(type);
     195             :     return constify_ref(_vector_fe_neighbor[dim][type]);
     196             :   }
     197             : 
     198             :   /**
     199             :    * GetVector a reference to a pointer that will contain the current "face" FE.
     200             :    * @param type The type of FE
     201             :    * @param dim The dimension of the current face
     202             :    * @return A _reference_ to the pointer.  Make sure to store this as a reference!
     203             :    */
     204             :   const FEVectorBase * const & getVectorFEFace(FEType type, unsigned int dim) const
     205             :   {
     206             :     buildVectorFaceFE(type);
     207             :     return constify_ref(_vector_fe_face[dim][type]);
     208             :   }
     209             : 
     210             :   /**
     211             :    * GetVector a reference to a pointer that will contain the current "neighbor" FE.
     212             :    * @param type The type of FE
     213             :    * @param dim The dimension of the neighbor face
     214             :    * @return A _reference_ to the pointer.  Make sure to store this as a reference!
     215             :    */
     216             :   const FEVectorBase * const & getVectorFEFaceNeighbor(FEType type, unsigned int dim) const
     217             :   {
     218             :     buildVectorFaceNeighborFE(type);
     219             :     return constify_ref(_vector_fe_face_neighbor[dim][type]);
     220             :   }
     221             : 
     222             : #ifdef MOOSE_KOKKOS_ENABLED
     223             :   /**
     224             :    * Key structure for APIs manipulating internal shape and quadrature data. Developers in blessed
     225             :    * classes may create keys using simple curly braces \p {} or may be more explicit and use \p
     226             :    * Assembly::InternalDataKey{}
     227             :    */
     228             :   using InternalDataKey = Moose::PassKey<Moose::Kokkos::Assembly>;
     229             : #endif
     230             : 
     231             :   /**
     232             :    * Returns the reference to the current quadrature being used
     233             :    * @return A _reference_ to the pointer.  Make sure to store this as a reference!
     234             :    */
     235    51463170 :   const libMesh::QBase * const & qRule() const { return constify_ref(_current_qrule); }
     236             : 
     237             :   /**
     238             :    * Returns the reference to the current quadrature being used
     239             :    * @return A _reference_ to the pointer.  Make sure to store this as a reference!
     240             :    */
     241       82855 :   libMesh::QBase * const & writeableQRule() { return _current_qrule; }
     242             : 
     243             : #ifdef MOOSE_KOKKOS_ENABLED
     244             :   /**
     245             :    * Returns the pointer to the quadrature of specified block and dimension
     246             :    * @return A pointer.
     247             :    */
     248        1486 :   libMesh::QBase * writeableQRule(unsigned int dim, SubdomainID block, InternalDataKey)
     249             :   {
     250        1486 :     return qrules(dim, block).vol.get();
     251             :   }
     252             : #endif
     253             : 
     254             :   /**
     255             :    * Returns the reference to the quadrature points
     256             :    * @return A _reference_.  Make sure to store this as a reference!
     257             :    */
     258      213116 :   const MooseArray<Point> & qPoints() const { return _current_q_points; }
     259             : 
     260             :   /**
     261             :    * Returns the reference to the mortar segment element quadrature points
     262             :    * @return A _reference_.  Make sure to store this as a reference!
     263             :    */
     264        1338 :   const std::vector<Point> & qPointsMortar() const { return _fe_msm->get_xyz(); }
     265             : 
     266             :   /**
     267             :    * The current points in physical space where we have reinited through reinitAtPhysical()
     268             :    * @return A _reference_.  Make sure to store this as a reference!
     269             :    */
     270         999 :   const MooseArray<Point> & physicalPoints() const { return _current_physical_points; }
     271             : 
     272             :   /**
     273             :    * Returns the reference to the transformed jacobian weights
     274             :    * @return A _reference_.  Make sure to store this as a reference!
     275             :    */
     276      208931 :   const MooseArray<Real> & JxW() const { return _current_JxW; }
     277             : 
     278        5164 :   const MooseArray<ADReal> & adJxW() const { return _ad_JxW; }
     279             : 
     280        2076 :   const MooseArray<ADReal> & adJxWFace() const { return _ad_JxW_face; }
     281             : 
     282             :   const MooseArray<ADReal> & adCurvatures() const;
     283             : 
     284             :   /**
     285             :    * Returns the reference to the coordinate transformation coefficients
     286             :    * @return A _reference_.  Make sure to store this as a reference!
     287             :    */
     288      266395 :   const MooseArray<Real> & coordTransformation() const { return _coord; }
     289             : 
     290             :   /**
     291             :    * Returns the reference to the coordinate transformation coefficients on the mortar segment mesh
     292             :    * @return A _reference_.  Make sure to store this as a reference!
     293             :    */
     294        1448 :   const MooseArray<Real> & mortarCoordTransformation() const { return _coord_msm; }
     295             : 
     296             :   /**
     297             :    * Returns the reference to the AD version of the coordinate transformation coefficients
     298             :    * @return A _reference_.  Make sure to store this as a reference!
     299             :    */
     300        7240 :   const MooseArray<ADReal> & adCoordTransformation() const
     301             :   {
     302             :     // Coord values for non-cartesian coordinate systems are functions of the locations of the
     303             :     // quadrature points in physical space. We also have no way of knowing whether this was called
     304             :     // from a volumetric or face object so we should set both volumetric and face xyz to true
     305        7240 :     _calculate_xyz = true;
     306        7240 :     _calculate_face_xyz = true;
     307             : 
     308        7240 :     _calculate_ad_coord = true;
     309        7240 :     return _ad_coord;
     310             :   }
     311             : 
     312             :   /**
     313             :    * Get the coordinate system type
     314             :    * @return A reference to the coordinate system type
     315             :    */
     316      161616 :   const Moose::CoordinateSystemType & coordSystem() const { return _coord_type; }
     317             : 
     318             :   /**
     319             :    * Returns the reference to the current quadrature being used on a current face
     320             :    * @return A _reference_.  Make sure to store this as a reference!
     321             :    */
     322    62778223 :   const libMesh::QBase * const & qRuleFace() const { return constify_ref(_current_qrule_face); }
     323             : 
     324             :   /**
     325             :    * Returns the reference to the current quadrature being used on a current face
     326             :    * @return A _reference_.  Make sure to store this as a reference!
     327             :    */
     328         146 :   libMesh::QBase * const & writeableQRuleFace() { return _current_qrule_face; }
     329             : 
     330             : #ifdef MOOSE_KOKKOS_ENABLED
     331             :   /**
     332             :    * Returns the pointer to the quadrature used on a face of specified block and dimension
     333             :    * @return A pointer.
     334             :    */
     335        1486 :   libMesh::QBase * writeableQRuleFace(unsigned int dim, SubdomainID block, InternalDataKey)
     336             :   {
     337        1486 :     return qrules(dim, block).face.get();
     338             :   }
     339             : #endif
     340             : 
     341             :   /**
     342             :    * Returns the reference to the current quadrature being used
     343             :    * @return A _reference_.  Make sure to store this as a reference!
     344             :    */
     345       73621 :   const MooseArray<Point> & qPointsFace() const { return _current_q_points_face; }
     346             : 
     347             :   /**
     348             :    * Returns the reference to the transformed jacobian weights on a current face
     349             :    * @return A _reference_.  Make sure to store this as a reference!
     350             :    */
     351       61679 :   const MooseArray<Real> & JxWFace() const { return _current_JxW_face; }
     352             : 
     353             :   /**
     354             :    * Returns the array of normals for quadrature points on a current side
     355             :    * @return A _reference_.  Make sure to store this as a reference!
     356             :    */
     357       60960 :   const MooseArray<Point> & normals() const { return _current_normals; }
     358             : 
     359             :   /***
     360             :    * Returns the array of normals for quadrature points on a current side
     361             :    */
     362         195 :   const std::vector<Eigen::Map<RealDIMValue>> & mappedNormals() const { return _mapped_normals; }
     363             : 
     364             :   /**
     365             :    * Returns the array of tangents for quadrature points on a current side
     366             :    * @return A _reference_.  Make sure to store this as a reference!
     367             :    */
     368        1338 :   const MooseArray<std::vector<Point>> & tangents() const { return _current_tangents; }
     369             : 
     370             :   /**
     371             :    * Number of extra element integers Assembly tracked
     372             :    */
     373   460368433 :   unsigned int numExtraElemIntegers() const { return _extra_elem_ids.size() - 1; }
     374             : 
     375             :   /**
     376             :    * Returns an integer ID of the current element given the index associated with the integer
     377             :    */
     378         457 :   const dof_id_type & extraElemID(unsigned int id) const
     379             :   {
     380             :     mooseAssert(id < _extra_elem_ids.size(), "An invalid extra element integer id");
     381         457 :     return _extra_elem_ids[id];
     382             :   }
     383             : 
     384             :   /**
     385             :    * Returns an integer ID of the current element given the index associated with the integer
     386             :    */
     387          56 :   const dof_id_type & extraElemIDNeighbor(unsigned int id) const
     388             :   {
     389             :     mooseAssert(id < _neighbor_extra_elem_ids.size(), "An invalid extra element integer id");
     390          56 :     return _neighbor_extra_elem_ids[id];
     391             :   }
     392             : 
     393        1945 :   const MooseArray<ADPoint> & adNormals() const { return _ad_normals; }
     394             : 
     395        5287 :   const MooseArray<ADPoint> & adQPoints() const
     396             :   {
     397        5287 :     _calculate_xyz = true;
     398        5287 :     return _ad_q_points;
     399             :   }
     400             : 
     401        1945 :   const MooseArray<ADPoint> & adQPointsFace() const
     402             :   {
     403        1945 :     _calculate_face_xyz = true;
     404        1945 :     return _ad_q_points_face;
     405             :   }
     406             : 
     407             :   template <bool is_ad>
     408             :   const MooseArray<Moose::GenericType<Point, is_ad>> & genericQPoints() const;
     409             : 
     410             :   /**
     411             :    * Return the current element
     412             :    * @return A _reference_.  Make sure to store this as a reference!
     413             :    */
     414   459463178 :   const Elem * const & elem() const { return _current_elem; }
     415             : 
     416             :   /**
     417             :    * Return the current subdomain ID
     418             :    */
     419       63825 :   const SubdomainID & currentSubdomainID() const { return _current_subdomain_id; }
     420             : 
     421             :   /**
     422             :    * set the current subdomain ID
     423             :    */
     424   484681781 :   void setCurrentSubdomainID(SubdomainID i) { _current_subdomain_id = i; }
     425             : 
     426             :   /**
     427             :    * Return the current boundary ID
     428             :    */
     429       90401 :   const BoundaryID & currentBoundaryID() const { return _current_boundary_id; }
     430             : 
     431             :   /**
     432             :    * set the current boundary ID
     433             :    */
     434   147214289 :   void setCurrentBoundaryID(BoundaryID i) { _current_boundary_id = i; }
     435             : 
     436             :   /**
     437             :    * Returns the reference to the current element volume
     438             :    * @return A _reference_.  Make sure to store this as a reference!
     439             :    */
     440    20341122 :   const Real & elemVolume() const { return _current_elem_volume; }
     441             : 
     442             :   /**
     443             :    * Returns the current side
     444             :    * @return A _reference_.  Make sure to store this as a reference!
     445             :    */
     446    17149886 :   const unsigned int & side() const { return _current_side; }
     447             : 
     448             :   /**
     449             :    * Returns the current neighboring side
     450             :    * @return A _reference_.  Make sure to store this as a reference!
     451             :    */
     452     2505506 :   const unsigned int & neighborSide() const { return _current_neighbor_side; }
     453             : 
     454             :   /**
     455             :    * Returns the side element
     456             :    * @return A _reference_.  Make sure to store this as a reference!
     457             :    */
     458       20314 :   const Elem *& sideElem() { return _current_side_elem; }
     459             : 
     460             :   /**
     461             :    * Returns the reference to the volume of current side element
     462             :    * @return A _reference_.  Make sure to store this as a reference!
     463             :    */
     464       95596 :   const Real & sideElemVolume() const { return _current_side_volume; }
     465             : 
     466             :   /**
     467             :    * Return the neighbor element
     468             :    * @return A _reference_.  Make sure to store this as a reference!
     469             :    */
     470     8006445 :   const Elem * const & neighbor() const { return _current_neighbor_elem; }
     471             : 
     472             :   /**
     473             :    * Return the lower dimensional element
     474             :    * @return A _reference_.  Make sure to store this as a reference!
     475             :    */
     476      256448 :   const Elem * const & lowerDElem() const { return _current_lower_d_elem; }
     477             : 
     478             :   /**
     479             :    * Return the neighboring lower dimensional element
     480             :    * @return A _reference_.  Make sure to store this as a reference!
     481             :    */
     482        1448 :   const Elem * const & neighborLowerDElem() const { return _current_neighbor_lower_d_elem; }
     483             : 
     484             :   /*
     485             :    * @return The current lower-dimensional element volume
     486             :    */
     487             :   const Real & lowerDElemVolume() const;
     488             : 
     489             :   /*
     490             :    * @return The current neighbor lower-dimensional element volume
     491             :    */
     492             :   const Real & neighborLowerDElemVolume() const;
     493             : 
     494             :   /**
     495             :    * Return the current subdomain ID
     496             :    */
     497       11419 :   const SubdomainID & currentNeighborSubdomainID() const { return _current_neighbor_subdomain_id; }
     498             : 
     499             :   /**
     500             :    * set the current subdomain ID
     501             :    */
     502  1722726165 :   void setCurrentNeighborSubdomainID(SubdomainID i) { _current_neighbor_subdomain_id = i; }
     503             : 
     504             :   /**
     505             :    * Returns the reference to the current neighbor volume
     506             :    * @return A _reference_.  Make sure to store this as a reference!
     507             :    */
     508        4002 :   const Real & neighborVolume()
     509             :   {
     510        4002 :     _need_neighbor_elem_volume = true;
     511        4002 :     return _current_neighbor_volume;
     512             :   }
     513             : 
     514             :   /**
     515             :    * Returns the reference to the current quadrature being used on a current neighbor
     516             :    * @return A _reference_.  Make sure to store this as a reference!
     517             :    */
     518     1537407 :   const libMesh::QBase * const & qRuleNeighbor() const
     519             :   {
     520     1537407 :     return constify_ref(_current_qrule_neighbor);
     521             :   }
     522             : 
     523             :   /**
     524             :    * Returns the reference to the current quadrature being used on a current neighbor
     525             :    * @return A _reference_.  Make sure to store this as a reference!
     526             :    */
     527             :   libMesh::QBase * const & writeableQRuleNeighbor() { return _current_qrule_neighbor; }
     528             : 
     529             :   /**
     530             :    * Returns the reference to the transformed jacobian weights on a current face
     531             :    * @return A _reference_.  Make sure to store this as a reference!
     532             :    */
     533             :   const MooseArray<Real> & JxWNeighbor() const;
     534             : 
     535             :   /**
     536             :    * Returns the reference to the current quadrature points being used on the neighbor face
     537             :    * @return A _reference_.  Make sure to store this as a reference!
     538             :    */
     539       12867 :   const MooseArray<Point> & qPointsFaceNeighbor() const { return _current_q_points_face_neighbor; }
     540             : 
     541             :   /**
     542             :    * Returns the reference to the node
     543             :    * @return A _reference_.  Make sure to store this as a reference!
     544             :    */
     545      792553 :   const Node * const & node() const { return _current_node; }
     546             : 
     547             :   /**
     548             :    * Returns the reference to the neighboring node
     549             :    * @return A _reference_.  Make sure to store this as a reference!
     550             :    */
     551      180632 :   const Node * const & nodeNeighbor() const { return _current_neighbor_node; }
     552             : 
     553             :   /**
     554             :    * Creates block-specific volume, face and arbitrary qrules based on the
     555             :    * orders and the flag of whether or not to allow negative qweights passed in.
     556             :    * Any quadrature rules specified using this function override those created
     557             :    * via in the non-block-specific/global createQRules function. order is used
     558             :    * for arbitrary volume quadrature rules, while volume_order and face_order
     559             :    * are for elem and face quadrature respectively.
     560             :    */
     561             :   void createQRules(QuadratureType type,
     562             :                     Order order,
     563             :                     Order volume_order,
     564             :                     Order face_order,
     565             :                     SubdomainID block,
     566             :                     bool allow_negative_qweights = true);
     567             : 
     568             :   /**
     569             :    * Increases the element/volume quadrature order for the specified mesh
     570             :    * block if and only if the current volume quadrature order is lower.  This
     571             :    * works exactly like the bumpAllQRuleOrder function, except it only
     572             :    * affects the volume quadrature rule (not face quadrature).
     573             :    */
     574             :   void bumpVolumeQRuleOrder(Order volume_order, SubdomainID block);
     575             : 
     576             :   /**
     577             :    * Increases the element/volume and face/area quadrature orders for the specified mesh
     578             :    * block if and only if the current volume or face quadrature order is lower.  This
     579             :    * can only cause the quadrature level to increase.  If order is
     580             :    * lower than or equal to the current volume+face quadrature rule order,
     581             :    * then nothing is done (i.e. this function is idempotent).
     582             :    */
     583             :   void bumpAllQRuleOrder(Order order, SubdomainID block);
     584             : 
     585             :   /**
     586             :    * Set the qrule to be used for volume integration.
     587             :    *
     588             :    * Note: This is normally set internally, only use if you know what you are doing!
     589             :    *
     590             :    * @param qrule The qrule you want to set
     591             :    * @param dim The spatial dimension of the qrule
     592             :    */
     593             :   void setVolumeQRule(libMesh::QBase * qrule, unsigned int dim);
     594             : 
     595             :   /**
     596             :    * Set the qrule to be used for face integration.
     597             :    *
     598             :    * Note: This is normally set internally, only use if you know what you are doing!
     599             :    *
     600             :    * @param qrule The qrule you want to set
     601             :    * @param dim The spatial dimension of the qrule
     602             :    */
     603             :   void setFaceQRule(libMesh::QBase * qrule, unsigned int dim);
     604             : 
     605             :   /**
     606             :    * Specifies a custom qrule for integration on mortar segment mesh
     607             :    *
     608             :    * Used to properly integrate QUAD face elements using quadrature on TRI mortar segment elements.
     609             :    * For example, to exactly integrate a FIRST order QUAD element, SECOND order quadrature on TRI
     610             :    * mortar segments is needed.
     611             :    */
     612             :   void setMortarQRule(Order order);
     613             : 
     614             :   /**
     615             :    * Indicates that dual shape functions are used for mortar constraint
     616             :    */
     617         135 :   void activateDual() { _need_dual = true; }
     618             : 
     619             :   /**
     620             :    * Indicates whether dual shape functions are used (computation is now repeated on each element
     621             :    * so expense of computing dual shape functions is no longer trivial)
     622             :    */
     623      355146 :   bool needDual() const { return _need_dual; }
     624             : 
     625             :   /**
     626             :    * Set the cached quadrature rules to nullptr
     627             :    */
     628             :   void clearCachedQRules();
     629             : 
     630             : private:
     631             :   /**
     632             :    * Set the qrule to be used for lower dimensional integration.
     633             :    *
     634             :    * @param qrule The qrule you want to set
     635             :    * @param dim The spatial dimension of the qrule
     636             :    */
     637             :   void setLowerQRule(libMesh::QBase * qrule, unsigned int dim);
     638             : 
     639             : public:
     640             :   /**
     641             :    * Set the qrule to be used for neighbor integration.
     642             :    *
     643             :    * Note: This is normally set internally, only use if you know what you are doing!
     644             :    *
     645             :    * @param qrule The qrule you want to set
     646             :    * @param dim The spatial dimension of the qrule
     647             :    */
     648             :   void setNeighborQRule(libMesh::QBase * qrule, unsigned int dim);
     649             : 
     650             :   /**
     651             :    * Reinitialize objects (JxW, q_points, ...) for an elements
     652             :    *
     653             :    * @param elem The element we want to reinitialize on
     654             :    */
     655             :   void reinit(const Elem * elem);
     656             : 
     657             :   /**
     658             :    * Set the volumetric quadrature rule based on the provided element
     659             :    */
     660             :   void setVolumeQRule(const Elem * elem);
     661             : 
     662             :   /**
     663             :    * Reinitialize FE data for the given element on the given side, optionally
     664             :    * with a given set of reference points
     665             :    */
     666             :   void reinitElemFaceRef(const Elem * elem,
     667             :                          unsigned int elem_side,
     668             :                          Real tolerance,
     669             :                          const std::vector<Point> * const pts = nullptr,
     670             :                          const std::vector<Real> * const weights = nullptr);
     671             : 
     672             :   /**
     673             :    * Reinitialize FE data for the given neighbor_element on the given side with a given set of
     674             :    * reference points
     675             :    */
     676             :   void reinitNeighborFaceRef(const Elem * neighbor_elem,
     677             :                              unsigned int neighbor_side,
     678             :                              Real tolerance,
     679             :                              const std::vector<Point> * const pts,
     680             :                              const std::vector<Real> * const weights = nullptr);
     681             : 
     682             :   /**
     683             :    * Reintialize dual basis coefficients based on a customized quadrature rule
     684             :    */
     685             :   void reinitDual(const Elem * elem, const std::vector<Point> & pts, const std::vector<Real> & JxW);
     686             : 
     687             :   /**
     688             :    * Reinitialize FE data for a lower dimenesional element with a given set of reference points
     689             :    */
     690             :   void reinitLowerDElem(const Elem * elem,
     691             :                         const std::vector<Point> * const pts = nullptr,
     692             :                         const std::vector<Real> * const weights = nullptr);
     693             : 
     694             :   /**
     695             :    * reinitialize a neighboring lower dimensional element
     696             :    */
     697             :   void reinitNeighborLowerDElem(const Elem * elem);
     698             : 
     699             :   /**
     700             :    * reinitialize a mortar segment mesh element in order to get a proper JxW
     701             :    */
     702             :   void reinitMortarElem(const Elem * elem);
     703             : 
     704             :   /**
     705             :    * Returns a reference to JxW for mortar segment elements
     706             :    */
     707       15954 :   const std::vector<Real> & jxWMortar() const { return *_JxW_msm; }
     708             : 
     709             :   /**
     710             :    * Returns a reference to the quadrature rule for the mortar segments
     711             :    */
     712       15954 :   const libMesh::QBase * const & qRuleMortar() const { return constify_ref(_qrule_msm); }
     713             : 
     714             : private:
     715             :   /**
     716             :    * compute AD things on an element face
     717             :    */
     718             :   void computeADFace(const Elem & elem, const unsigned int side);
     719             : 
     720             : public:
     721             :   /**
     722             :    * Reinitialize the assembly data at specific physical point in the given element.
     723             :    */
     724             :   void reinitAtPhysical(const Elem * elem, const std::vector<Point> & physical_points);
     725             : 
     726             :   /**
     727             :    * Reinitialize the assembly data at specific points in the reference element.
     728             :    */
     729             :   void reinit(const Elem * elem, const std::vector<Point> & reference_points);
     730             : 
     731             :   /**
     732             :    * Set the face quadrature rule based on the provided element and side
     733             :    */
     734             :   void setFaceQRule(const Elem * const elem, const unsigned int side);
     735             : 
     736             :   /**
     737             :    * Reinitialize the assembly data on an side of an element
     738             :    */
     739             :   void reinit(const Elem * elem, unsigned int side);
     740             : 
     741             :   /**
     742             :    * Reinitialize the assembly data on the side of a element at the custom reference points
     743             :    */
     744             :   void reinit(const Elem * elem, unsigned int side, const std::vector<Point> & reference_points);
     745             : 
     746             :   void reinitFVFace(const FaceInfo & fi);
     747             : 
     748             :   /**
     749             :    * Reinitialize an element and its neighbor along a particular side.
     750             :    *
     751             :    * @param elem Element being reinitialized
     752             :    * @param side Side of the element
     753             :    * @param neighbor Neighbor facing the element on the side 'side'
     754             :    * @param neighbor_side The side id on the neighboring element.
     755             :    * @param neighbor_reference_points Optional argument specifying the neighbor reference points. If
     756             :    * not passed, then neighbor reference points will be determined by doing an inverse map based on
     757             :    * the physical location of the \p elem quadrature points
     758             :    */
     759             :   void reinitElemAndNeighbor(const Elem * elem,
     760             :                              unsigned int side,
     761             :                              const Elem * neighbor,
     762             :                              unsigned int neighbor_side,
     763             :                              const std::vector<Point> * neighbor_reference_points = nullptr);
     764             : 
     765             :   /**
     766             :    * Reinitializes the neighbor at the physical coordinates on neighbor side given.
     767             :    */
     768             :   void reinitNeighborAtPhysical(const Elem * neighbor,
     769             :                                 unsigned int neighbor_side,
     770             :                                 const std::vector<Point> & physical_points);
     771             : 
     772             :   /**
     773             :    * Reinitializes the neighbor at the physical coordinates within element given.
     774             :    */
     775             :   void reinitNeighborAtPhysical(const Elem * neighbor, const std::vector<Point> & physical_points);
     776             : 
     777             :   /**
     778             :    * Reinitializes the neighbor side using reference coordinates.
     779             :    */
     780             :   void reinitNeighbor(const Elem * neighbor, const std::vector<Point> & reference_points);
     781             : 
     782             :   /**
     783             :    * Reinitialize assembly data for a node
     784             :    */
     785             :   void reinit(const Node * node);
     786             : 
     787             :   /**
     788             :    * Initialize the Assembly object and set the CouplingMatrix for use throughout.
     789             :    */
     790             :   void init(const libMesh::CouplingMatrix * cm);
     791             : 
     792             :   /// Create pair of variables requiring nonlocal jacobian contributions
     793             :   void initNonlocalCoupling();
     794             : 
     795             :   /// Sizes and zeroes the Jacobian blocks used for the current element
     796             :   void prepareJacobianBlock();
     797             : 
     798             :   /// Sizes and zeroes the residual for the current element
     799             :   void prepareResidual();
     800             : 
     801             :   void prepare();
     802             :   void prepareNonlocal();
     803             : 
     804             :   /**
     805             :    * Used for preparing the dense residual and jacobian blocks for one particular variable.
     806             :    *
     807             :    * @param var The variable that needs to have its datastructures prepared
     808             :    */
     809             :   void prepareVariable(MooseVariableFieldBase * var);
     810             :   void prepareVariableNonlocal(MooseVariableFieldBase * var);
     811             :   void prepareNeighbor();
     812             : 
     813             :   /**
     814             :    * Prepare the Jacobians and residuals for a lower dimensional element. This method may be called
     815             :    * when performing mortar finite element simulations
     816             :    */
     817             :   void prepareLowerD();
     818             : 
     819             :   void prepareBlock(unsigned int ivar, unsigned jvar, const std::vector<dof_id_type> & dof_indices);
     820             :   void prepareBlockNonlocal(unsigned int ivar,
     821             :                             unsigned jvar,
     822             :                             const std::vector<dof_id_type> & idof_indices,
     823             :                             const std::vector<dof_id_type> & jdof_indices);
     824             :   void prepareScalar();
     825             :   void prepareOffDiagScalar();
     826             : 
     827             :   template <typename T>
     828             :   void copyShapes(MooseVariableField<T> & v);
     829             :   void copyShapes(unsigned int var);
     830             : 
     831             :   template <typename T>
     832             :   void copyFaceShapes(MooseVariableField<T> & v);
     833             :   void copyFaceShapes(unsigned int var);
     834             : 
     835             :   template <typename T>
     836             :   void copyNeighborShapes(MooseVariableField<T> & v);
     837             :   void copyNeighborShapes(unsigned int var);
     838             : 
     839             :   /**
     840             :    * Key structure for APIs manipulating global vectors/matrices. Developers in blessed classes may
     841             :    * create keys using simple curly braces \p {} or may be more explicit and use \p
     842             :    * Assembly::GlobalDataKey{}
     843             :    */
     844             :   class GlobalDataKey
     845             :   {
     846             :     // Blessed classes
     847             :     friend class Assembly;
     848             :     friend class SubProblem;
     849             :     friend class FEProblemBase;
     850             :     friend class DisplacedProblem;
     851             :     friend class ComputeMortarFunctor;
     852             :     friend class NonlinearSystemBase;
     853   692776912 :     GlobalDataKey() {}
     854             :     GlobalDataKey(const GlobalDataKey &) {}
     855             :   };
     856             : 
     857             :   /**
     858             :    * Key structure for APIs adding/caching local element residuals/Jacobians. Developers in blessed
     859             :    * classes may create keys using simple curly braces \p {} or may be more explicit and use \p
     860             :    * Assembly::LocalDataKey{}
     861             :    */
     862             :   class LocalDataKey
     863             :   {
     864             :     // Blessed classes
     865             :     friend class Assembly;
     866             :     friend class TaggingInterface;
     867  2352168479 :     LocalDataKey() {}
     868             :     LocalDataKey(const LocalDataKey &) {}
     869             :   };
     870             : 
     871             :   /**
     872             :    * Add local residuals of all field variables for a set of tags onto the global residual vectors
     873             :    * associated with the tags.
     874             :    */
     875             :   void addResidual(GlobalDataKey, const std::vector<VectorTag> & vector_tags);
     876             :   /**
     877             :    * Add local neighbor residuals of all field variables for a set of tags onto the global residual
     878             :    * vectors associated with the tags.
     879             :    */
     880             :   void addResidualNeighbor(GlobalDataKey, const std::vector<VectorTag> & vector_tags);
     881             :   /**
     882             :    * Add local neighbor residuals of all field variables for a set of tags onto the global residual
     883             :    * vectors associated with the tags.
     884             :    */
     885             :   void addResidualLower(GlobalDataKey, const std::vector<VectorTag> & vector_tags);
     886             : 
     887             :   /**
     888             :    * Add residuals of all scalar variables for a set of tags onto the global residual vectors
     889             :    * associated with the tags.
     890             :    */
     891             :   void addResidualScalar(GlobalDataKey, const std::vector<VectorTag> & vector_tags);
     892             : 
     893             :   /**
     894             :    * Takes the values that are currently in _sub_Re of all field variables and appends them to
     895             :    * the cached values.
     896             :    */
     897             :   void cacheResidual(GlobalDataKey, const std::vector<VectorTag> & tags);
     898             : 
     899             :   /**
     900             :    * Takes the values that are currently in _sub_Rn of all field variables and appends them to
     901             :    * the cached values.
     902             :    */
     903             :   void cacheResidualNeighbor(GlobalDataKey, const std::vector<VectorTag> & tags);
     904             : 
     905             :   /**
     906             :    * Takes the values that are currently in _sub_Rl and appends them to the cached values.
     907             :    */
     908             :   void cacheResidualLower(GlobalDataKey, const std::vector<VectorTag> & tags);
     909             : 
     910             :   /**
     911             :    * Pushes all cached residuals to the global residual vectors associated with each tag.
     912             :    *
     913             :    * Note that this will also clear the cache.
     914             :    */
     915             :   void addCachedResiduals(GlobalDataKey, const std::vector<VectorTag> & tags);
     916             : 
     917             :   /**
     918             :    * Clears all of the residuals in _cached_residual_rows and _cached_residual_values
     919             :    *
     920             :    * This method is designed specifically for use after calling
     921             :    * FEProblemBase::addCachedResidualDirectly() and DisplacedProblem::addCachedResidualDirectly() to
     922             :    * ensure that we don't have any extra residuals hanging around that we didn't have the vectors
     923             :    * for
     924             :    */
     925             :   void clearCachedResiduals(GlobalDataKey);
     926             : 
     927             :   /**
     928             :    * Adds the values that have been cached by calling cacheResidual(), cacheResidualNeighbor(),
     929             :    * and/or cacheResidualLower() to a user-defined residual (that is, not necessarily the vector
     930             :    * that vector_tag points to)
     931             :    *
     932             :    * Note that this will also clear the cache.
     933             :    */
     934             :   void addCachedResidualDirectly(NumericVector<Number> & residual,
     935             :                                  GlobalDataKey,
     936             :                                  const VectorTag & vector_tag);
     937             : 
     938             :   /**
     939             :    * Sets local residuals of all field variables to the global residual vector for a tag.
     940             :    */
     941             :   void setResidual(NumericVector<Number> & residual, GlobalDataKey, const VectorTag & vector_tag);
     942             : 
     943             :   /**
     944             :    * Sets local neighbor residuals of all field variables to the global residual vector for a tag.
     945             :    */
     946             :   void setResidualNeighbor(NumericVector<Number> & residual,
     947             :                            GlobalDataKey,
     948             :                            const VectorTag & vector_tag);
     949             : 
     950             :   /**
     951             :    * Adds all local Jacobian to the global Jacobian matrices.
     952             :    */
     953             :   void addJacobian(GlobalDataKey);
     954             : 
     955             :   /**
     956             :    * Adds non-local Jacobian to the global Jacobian matrices.
     957             :    */
     958             :   void addJacobianNonlocal(GlobalDataKey);
     959             : 
     960             :   /**
     961             :    * Add ElementNeighbor, NeighborElement, and NeighborNeighbor portions of the Jacobian for compute
     962             :    * objects like DGKernels
     963             :    */
     964             :   void addJacobianNeighbor(GlobalDataKey);
     965             : 
     966             :   /**
     967             :    * Add Jacobians for pairs of scalar variables into the global Jacobian matrices.
     968             :    */
     969             :   void addJacobianScalar(GlobalDataKey);
     970             : 
     971             :   /**
     972             :    * Add Jacobians for a scalar variables with all other field variables into the global Jacobian
     973             :    * matrices.
     974             :    */
     975             :   void addJacobianOffDiagScalar(unsigned int ivar, GlobalDataKey);
     976             : 
     977             :   /**
     978             :    * Adds element matrix for ivar rows and jvar columns to the global Jacobian matrix.
     979             :    */
     980             :   void addJacobianBlock(libMesh::SparseMatrix<Number> & jacobian,
     981             :                         unsigned int ivar,
     982             :                         unsigned int jvar,
     983             :                         const libMesh::DofMap & dof_map,
     984             :                         std::vector<dof_id_type> & dof_indices,
     985             :                         GlobalDataKey,
     986             :                         TagID tag);
     987             : 
     988             :   /**
     989             :    * Add element matrix for ivar rows and jvar columns to the global Jacobian matrix for given
     990             :    * tags.
     991             :    */
     992             :   void addJacobianBlockTags(libMesh::SparseMatrix<Number> & jacobian,
     993             :                             unsigned int ivar,
     994             :                             unsigned int jvar,
     995             :                             const libMesh::DofMap & dof_map,
     996             :                             std::vector<dof_id_type> & dof_indices,
     997             :                             GlobalDataKey,
     998             :                             const std::set<TagID> & tags);
     999             : 
    1000             :   /**
    1001             :    * Adds non-local element matrix for ivar rows and jvar columns to the global Jacobian matrix.
    1002             :    */
    1003             :   void addJacobianBlockNonlocal(libMesh::SparseMatrix<Number> & jacobian,
    1004             :                                 unsigned int ivar,
    1005             :                                 unsigned int jvar,
    1006             :                                 const libMesh::DofMap & dof_map,
    1007             :                                 const std::vector<dof_id_type> & idof_indices,
    1008             :                                 const std::vector<dof_id_type> & jdof_indices,
    1009             :                                 GlobalDataKey,
    1010             :                                 TagID tag);
    1011             : 
    1012             :   /**
    1013             :    * Adds non-local element matrix for ivar rows and jvar columns to the global Jacobian matrix.
    1014             :    */
    1015             :   void addJacobianBlockNonlocalTags(libMesh::SparseMatrix<Number> & jacobian,
    1016             :                                     unsigned int ivar,
    1017             :                                     unsigned int jvar,
    1018             :                                     const libMesh::DofMap & dof_map,
    1019             :                                     const std::vector<dof_id_type> & idof_indices,
    1020             :                                     const std::vector<dof_id_type> & jdof_indices,
    1021             :                                     GlobalDataKey,
    1022             :                                     const std::set<TagID> & tags);
    1023             : 
    1024             :   /**
    1025             :    * Add *all* portions of the Jacobian except PrimaryPrimary, e.g. LowerLower, LowerSecondary,
    1026             :    * LowerPrimary, SecondaryLower, SecondarySecondary, SecondaryPrimary, PrimaryLower,
    1027             :    * PrimarySecondary, for mortar-like objects. Primary indicates the interior parent element on the
    1028             :    * primary side of the mortar interface. Secondary indicates the neighbor of the interior parent
    1029             :    * element. Lower denotes the lower-dimensional element living on the primary side of the mortar
    1030             :    * interface.
    1031             :    */
    1032             :   void addJacobianNeighborLowerD(GlobalDataKey);
    1033             : 
    1034             :   /**
    1035             :    * Add portions of the Jacobian of LowerLower, LowerSecondary, and SecondaryLower for
    1036             :    * boundary conditions. Secondary indicates the boundary element. Lower denotes the
    1037             :    * lower-dimensional element living on the boundary side.
    1038             :    */
    1039             :   void addJacobianLowerD(GlobalDataKey);
    1040             : 
    1041             :   /**
    1042             :    * Cache *all* portions of the Jacobian, e.g. LowerLower, LowerSecondary, LowerPrimary,
    1043             :    * SecondaryLower, SecondarySecondary, SecondaryPrimary, PrimaryLower, PrimarySecondary,
    1044             :    * PrimaryPrimary for mortar-like objects. Primary indicates the interior parent element on the
    1045             :    * primary side of the mortar interface. Secondary indicates the interior parent element on the
    1046             :    * secondary side of the interface. Lower denotes the lower-dimensional element living on the
    1047             :    * secondary side of the mortar interface; it's the boundary face of the \p Secondary element.
    1048             :    */
    1049             :   void cacheJacobianMortar(GlobalDataKey);
    1050             : 
    1051             :   /**
    1052             :    * Adds three neighboring element matrices for ivar rows and jvar columns to the global Jacobian
    1053             :    * matrix.
    1054             :    */
    1055             :   void addJacobianNeighbor(libMesh::SparseMatrix<Number> & jacobian,
    1056             :                            unsigned int ivar,
    1057             :                            unsigned int jvar,
    1058             :                            const libMesh::DofMap & dof_map,
    1059             :                            std::vector<dof_id_type> & dof_indices,
    1060             :                            std::vector<dof_id_type> & neighbor_dof_indices,
    1061             :                            GlobalDataKey,
    1062             :                            TagID tag);
    1063             : 
    1064             :   /**
    1065             :    * Adds three neighboring element matrices for ivar rows and jvar columns to the global Jacobian
    1066             :    * matrix.
    1067             :    */
    1068             :   void addJacobianNeighborTags(libMesh::SparseMatrix<Number> & jacobian,
    1069             :                                unsigned int ivar,
    1070             :                                unsigned int jvar,
    1071             :                                const libMesh::DofMap & dof_map,
    1072             :                                std::vector<dof_id_type> & dof_indices,
    1073             :                                std::vector<dof_id_type> & neighbor_dof_indices,
    1074             :                                GlobalDataKey,
    1075             :                                const std::set<TagID> & tags);
    1076             : 
    1077             :   /**
    1078             :    * Takes the values that are currently in _sub_Kee and appends them to the cached values.
    1079             :    */
    1080             :   void cacheJacobian(GlobalDataKey);
    1081             : 
    1082             :   /**
    1083             :    * Takes the values that are currently in _sub_Keg and appends them to the cached values.
    1084             :    */
    1085             :   void cacheJacobianNonlocal(GlobalDataKey);
    1086             : 
    1087             :   /**
    1088             :    * Takes the values that are currently in the neighbor Dense Matrices and appends them to the
    1089             :    * cached values.
    1090             :    */
    1091             :   void cacheJacobianNeighbor(GlobalDataKey);
    1092             : 
    1093             :   /**
    1094             :    * Adds the values that have been cached by calling cacheJacobian() and or cacheJacobianNeighbor()
    1095             :    * to the jacobian matrix.
    1096             :    *
    1097             :    * Note that this will also clear the cache.
    1098             :    */
    1099             :   void addCachedJacobian(GlobalDataKey);
    1100             : 
    1101             :   /**
    1102             :    * Sets previously-cached Jacobian values via SparseMatrix::set() calls.
    1103             :    */
    1104             :   void setCachedJacobian(GlobalDataKey);
    1105             : 
    1106             :   /**
    1107             :    * Zero out previously-cached Jacobian rows.
    1108             :    */
    1109             :   void zeroCachedJacobian(GlobalDataKey);
    1110             : 
    1111             :   /**
    1112             :    * Get local residual block for a variable and a tag. Only blessed framework classes may call this
    1113             :    * API by creating the requisiste \p LocalDataKey class
    1114             :    */
    1115   770873815 :   DenseVector<Number> & residualBlock(unsigned int var_num, LocalDataKey, TagID tag_id)
    1116             :   {
    1117   770873815 :     return _sub_Re[tag_id][var_num];
    1118             :   }
    1119             : 
    1120             :   /**
    1121             :    * Get local neighbor residual block for a variable and a tag. Only blessed framework classes may
    1122             :    * call this API by creating the requisiste \p LocalDataKey class
    1123             :    */
    1124    25996212 :   DenseVector<Number> & residualBlockNeighbor(unsigned int var_num, LocalDataKey, TagID tag_id)
    1125             :   {
    1126    25996212 :     return _sub_Rn[tag_id][var_num];
    1127             :   }
    1128             : 
    1129             :   /**
    1130             :    * Get residual block for lower. Only blessed framework classes may call this API by creating the
    1131             :    * requisiste \p LocalDataKey class
    1132             :    */
    1133      110592 :   DenseVector<Number> & residualBlockLower(unsigned int var_num, LocalDataKey, TagID tag_id)
    1134             :   {
    1135      110592 :     return _sub_Rl[tag_id][var_num];
    1136             :   }
    1137             : 
    1138             :   /**
    1139             :    * Get local Jacobian block for a pair of variables and a tag. Only blessed framework classes may
    1140             :    * call this API by creating the requisiste \p LocalDataKey class
    1141             :    */
    1142   559066961 :   DenseMatrix<Number> & jacobianBlock(unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag)
    1143             :   {
    1144   559066961 :     jacobianBlockUsed(tag, ivar, jvar, true);
    1145   559066961 :     return _sub_Kee[tag][ivar][_block_diagonal_matrix ? 0 : jvar];
    1146             :   }
    1147             : 
    1148             :   /**
    1149             :    * Get local Jacobian block from non-local contribution for a pair of variables and a tag. Only
    1150             :    * blessed framework classes may call this API by creating the requisiste \p LocalDataKey class
    1151             :    */
    1152             :   DenseMatrix<Number> &
    1153       25876 :   jacobianBlockNonlocal(unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag)
    1154             :   {
    1155       25876 :     jacobianBlockNonlocalUsed(tag, ivar, jvar, true);
    1156       25876 :     return _sub_Keg[tag][ivar][_block_diagonal_matrix ? 0 : jvar];
    1157             :   }
    1158             : 
    1159             :   /**
    1160             :    * Get local Jacobian block of a DG Jacobian type for a pair of variables and a tag. Only blessed
    1161             :    * framework classes may call this API by creating the requisiste \p LocalDataKey class
    1162             :    */
    1163             :   DenseMatrix<Number> & jacobianBlockNeighbor(
    1164             :       Moose::DGJacobianType type, unsigned int ivar, unsigned int jvar, LocalDataKey, TagID tag);
    1165             : 
    1166             :   /**
    1167             :    * Returns the jacobian block for the given mortar Jacobian type. This jacobian block can involve
    1168             :    * degrees of freedom from the secondary side interior parent, the primary side
    1169             :    * interior parent, or the lower-dimensional element (located on the secondary
    1170             :    * side). Only blessed framework classes may call this API by creating the requisiste \p
    1171             :    * LocalDataKey class
    1172             :    */
    1173             :   DenseMatrix<Number> & jacobianBlockMortar(Moose::ConstraintJacobianType type,
    1174             :                                             unsigned int ivar,
    1175             :                                             unsigned int jvar,
    1176             :                                             LocalDataKey,
    1177             :                                             TagID tag);
    1178             : 
    1179             :   /**
    1180             :    * Lets an external class cache residual at a set of nodes. Only blessed framework classes may
    1181             :    * call this API by creating the requisiste \p LocalDataKey class
    1182             :    */
    1183             :   void cacheResidualNodes(const DenseVector<Number> & res,
    1184             :                           const std::vector<dof_id_type> & dof_index,
    1185             :                           LocalDataKey,
    1186             :                           TagID tag);
    1187             : 
    1188             :   /**
    1189             :    * Caches the Jacobian entry 'value', to eventually be
    1190             :    * added/set in the (i,j) location of the matrix.
    1191             :    *
    1192             :    * We use numeric_index_type for the index arrays (rather than
    1193             :    * dof_id_type) since that is what the SparseMatrix interface uses,
    1194             :    * but at the time of this writing, those two types are equivalent.
    1195             :    *
    1196             :    * Only blessed framework classes may call this API by creating the requisiste \p LocalDataKey
    1197             :    * class
    1198             :    */
    1199             :   void
    1200             :   cacheJacobian(numeric_index_type i, numeric_index_type j, Real value, LocalDataKey, TagID tag);
    1201             : 
    1202             :   /**
    1203             :    * Caches the Jacobian entry 'value', to eventually be
    1204             :    * added/set in the (i,j) location of the matrices in corresponding to \p tags.
    1205             :    *
    1206             :    * We use numeric_index_type for the index arrays (rather than
    1207             :    * dof_id_type) since that is what the SparseMatrix interface uses,
    1208             :    * but at the time of this writing, those two types are equivalent.
    1209             :    *
    1210             :    * Only blessed framework classes may call this API by creating the requisiste \p LocalDataKey
    1211             :    * class
    1212             :    */
    1213             :   void cacheJacobian(numeric_index_type i,
    1214             :                      numeric_index_type j,
    1215             :                      Real value,
    1216             :                      LocalDataKey,
    1217             :                      const std::set<TagID> & tags);
    1218             : 
    1219             :   /**
    1220             :    * Cache a local Jacobian block with the provided rows (\p idof_indices) and columns (\p
    1221             :    * jdof_indices) for eventual accumulation into the global matrix specified by \p tag. The \p
    1222             :    * scaling_factor will be applied before caching. Only blessed framework classes may call this API
    1223             :    * by creating the requisiste \p LocalDataKey class
    1224             :    */
    1225             :   void cacheJacobianBlock(DenseMatrix<Number> & jac_block,
    1226             :                           const std::vector<dof_id_type> & idof_indices,
    1227             :                           const std::vector<dof_id_type> & jdof_indices,
    1228             :                           Real scaling_factor,
    1229             :                           LocalDataKey,
    1230             :                           TagID tag);
    1231             : 
    1232             :   /**
    1233             :    * Process the supplied residual values. This is a mirror of of the non-templated version of \p
    1234             :    * addResiduals except that it's meant for \emph only processing residuals (and not their
    1235             :    * derivatives/Jacobian). We supply this API such that residual objects that leverage the AD
    1236             :    * version of this method when computing the Jacobian (or residual + Jacobian) can mirror the same
    1237             :    * behavior when doing pure residual evaluations, such as when evaluating linear residuals during
    1238             :    * (P)JFNK. This method will call \p constrain_element_vector on the supplied residuals. Only
    1239             :    * blessed framework classes may call this API by creating the requisiste \p LocalDataKey class
    1240             :    */
    1241             :   template <typename Residuals, typename Indices>
    1242             :   void cacheResiduals(const Residuals & residuals,
    1243             :                       const Indices & row_indices,
    1244             :                       Real scaling_factor,
    1245             :                       LocalDataKey,
    1246             :                       const std::set<TagID> & vector_tags);
    1247             : 
    1248             :   /**
    1249             :    * Process the \p derivatives() data of a vector of \p ADReals. This
    1250             :    * method simply caches the derivative values for the corresponding column indices for the
    1251             :    * provided \p matrix_tags. Note that this overload will call \p DofMap::constrain_element_matrix.
    1252             :    * Only blessed framework classes may call this API by creating the requisiste \p LocalDataKey
    1253             :    * class
    1254             :    */
    1255             :   template <typename Residuals, typename Indices>
    1256             :   void cacheJacobian(const Residuals & residuals,
    1257             :                      const Indices & row_indices,
    1258             :                      Real scaling_factor,
    1259             :                      LocalDataKey,
    1260             :                      const std::set<TagID> & matrix_tags);
    1261             : 
    1262             :   /**
    1263             :    * Process the supplied residual values. This is a mirror of of the non-templated version of \p
    1264             :    * addResiduals except that it's meant for \emph only processing residuals (and not their
    1265             :    * derivatives/Jacobian). We supply this API such that residual objects that leverage the AD
    1266             :    * version of this method when computing the Jacobian (or residual + Jacobian) can mirror the same
    1267             :    * behavior when doing pure residual evaluations, such as when evaluating linear residuals during
    1268             :    * (P)JFNK. This method will \emph not call \p constrain_element_vector on the supplied residuals.
    1269             :    * Only blessed framework classes may call this API by creating the requisiste \p LocalDataKey
    1270             :    * class
    1271             :    */
    1272             :   template <typename Residuals, typename Indices>
    1273             :   void cacheResidualsWithoutConstraints(const Residuals & residuals,
    1274             :                                         const Indices & row_indices,
    1275             :                                         Real scaling_factor,
    1276             :                                         LocalDataKey,
    1277             :                                         const std::set<TagID> & vector_tags);
    1278             : 
    1279             :   /**
    1280             :    * Process the \p derivatives() data of a vector of \p ADReals. This
    1281             :    * method simply caches the derivative values for the corresponding column indices for the
    1282             :    * provided \p matrix_tags. Note that this overload will \emph not call \p
    1283             :    * DofMap::constrain_element_matrix. Only blessed framework classes may call this API by creating
    1284             :    * the requisiste \p LocalDataKey class
    1285             :    */
    1286             :   template <typename Residuals, typename Indices>
    1287             :   void cacheJacobianWithoutConstraints(const Residuals & residuals,
    1288             :                                        const Indices & row_indices,
    1289             :                                        Real scaling_factor,
    1290             :                                        LocalDataKey,
    1291             :                                        const std::set<TagID> & matrix_tags);
    1292             : 
    1293    19110376 :   std::vector<std::pair<MooseVariableFieldBase *, MooseVariableFieldBase *>> & couplingEntries()
    1294             :   {
    1295    19110376 :     return _cm_ff_entry;
    1296             :   }
    1297             :   const std::vector<std::pair<MooseVariableFieldBase *, MooseVariableFieldBase *>> &
    1298       42235 :   couplingEntries() const
    1299             :   {
    1300       42235 :     return _cm_ff_entry;
    1301             :   }
    1302             :   std::vector<std::pair<MooseVariableFieldBase *, MooseVariableFieldBase *>> &
    1303        5558 :   nonlocalCouplingEntries()
    1304             :   {
    1305        5558 :     return _cm_nonlocal_entry;
    1306             :   }
    1307             :   const std::vector<std::pair<MooseVariableFieldBase *, MooseVariableScalar *>> &
    1308             :   fieldScalarCouplingEntries() const
    1309             :   {
    1310             :     return _cm_fs_entry;
    1311             :   }
    1312             :   const std::vector<std::pair<MooseVariableScalar *, MooseVariableFieldBase *>> &
    1313        3180 :   scalarFieldCouplingEntries() const
    1314             :   {
    1315        3180 :     return _cm_sf_entry;
    1316             :   }
    1317             : 
    1318             :   // Read-only references
    1319          56 :   const VariablePhiValue & phi() const { return _phi; }
    1320             :   template <typename T>
    1321        4928 :   const ADTemplateVariablePhiGradient<T> & adGradPhi(const MooseVariableFE<T> & v) const
    1322             :   {
    1323        4928 :     return _ad_grad_phi_data.at(v.feType());
    1324             :   }
    1325             :   const VariablePhiValue & phi(const MooseVariableField<Real> &) const { return _phi; }
    1326          56 :   const VariablePhiGradient & gradPhi() const { return _grad_phi; }
    1327             :   const VariablePhiGradient & gradPhi(const MooseVariableField<Real> &) const { return _grad_phi; }
    1328             :   const VariablePhiSecond & secondPhi() const { return _second_phi; }
    1329             :   const VariablePhiSecond & secondPhi(const MooseVariableField<Real> &) const
    1330             :   {
    1331             :     return _second_phi;
    1332             :   }
    1333             : 
    1334          72 :   const VariablePhiValue & phiFace() const { return _phi_face; }
    1335             :   const VariablePhiValue & phiFace(const MooseVariableField<Real> &) const { return _phi_face; }
    1336          72 :   const VariablePhiGradient & gradPhiFace() const { return _grad_phi_face; }
    1337             :   const VariablePhiGradient & gradPhiFace(const MooseVariableField<Real> &) const
    1338             :   {
    1339             :     return _grad_phi_face;
    1340             :   }
    1341             :   const VariablePhiSecond & secondPhiFace(const MooseVariableField<Real> &) const
    1342             :   {
    1343             :     return _second_phi_face;
    1344             :   }
    1345             : 
    1346             :   const VariablePhiValue & phiNeighbor(const MooseVariableField<Real> &) const
    1347             :   {
    1348             :     return _phi_neighbor;
    1349             :   }
    1350             :   const VariablePhiGradient & gradPhiNeighbor(const MooseVariableField<Real> &) const
    1351             :   {
    1352             :     return _grad_phi_neighbor;
    1353             :   }
    1354             :   const VariablePhiSecond & secondPhiNeighbor(const MooseVariableField<Real> &) const
    1355             :   {
    1356             :     return _second_phi_neighbor;
    1357             :   }
    1358             : 
    1359             :   const VariablePhiValue & phiFaceNeighbor(const MooseVariableField<Real> &) const
    1360             :   {
    1361             :     return _phi_face_neighbor;
    1362             :   }
    1363             :   const VariablePhiGradient & gradPhiFaceNeighbor(const MooseVariableField<Real> &) const
    1364             :   {
    1365             :     return _grad_phi_face_neighbor;
    1366             :   }
    1367             :   const VariablePhiSecond & secondPhiFaceNeighbor(const MooseVariableField<Real> &) const
    1368             :   {
    1369             :     return _second_phi_face_neighbor;
    1370             :   }
    1371             : 
    1372             :   const VectorVariablePhiValue & phi(const MooseVariableField<RealVectorValue> &) const
    1373             :   {
    1374             :     return _vector_phi;
    1375             :   }
    1376             :   const VectorVariablePhiGradient & gradPhi(const MooseVariableField<RealVectorValue> &) const
    1377             :   {
    1378             :     return _vector_grad_phi;
    1379             :   }
    1380             :   const VectorVariablePhiSecond & secondPhi(const MooseVariableField<RealVectorValue> &) const
    1381             :   {
    1382             :     return _vector_second_phi;
    1383             :   }
    1384             :   const VectorVariablePhiCurl & curlPhi(const MooseVariableField<RealVectorValue> &) const
    1385             :   {
    1386             :     return _vector_curl_phi;
    1387             :   }
    1388             :   const VectorVariablePhiDivergence & divPhi(const MooseVariableField<RealVectorValue> &) const
    1389             :   {
    1390             :     return _vector_div_phi;
    1391             :   }
    1392             : 
    1393             :   const VectorVariablePhiValue & phiFace(const MooseVariableField<RealVectorValue> &) const
    1394             :   {
    1395             :     return _vector_phi_face;
    1396             :   }
    1397             :   const VectorVariablePhiGradient & gradPhiFace(const MooseVariableField<RealVectorValue> &) const
    1398             :   {
    1399             :     return _vector_grad_phi_face;
    1400             :   }
    1401             :   const VectorVariablePhiSecond & secondPhiFace(const MooseVariableField<RealVectorValue> &) const
    1402             :   {
    1403             :     return _vector_second_phi_face;
    1404             :   }
    1405             :   const VectorVariablePhiCurl & curlPhiFace(const MooseVariableField<RealVectorValue> &) const
    1406             :   {
    1407             :     return _vector_curl_phi_face;
    1408             :   }
    1409             :   const VectorVariablePhiDivergence & divPhiFace(const MooseVariableField<RealVectorValue> &) const
    1410             :   {
    1411             :     return _vector_div_phi_face;
    1412             :   }
    1413             : 
    1414             :   const VectorVariablePhiValue & phiNeighbor(const MooseVariableField<RealVectorValue> &) const
    1415             :   {
    1416             :     return _vector_phi_neighbor;
    1417             :   }
    1418             :   const VectorVariablePhiGradient &
    1419             :   gradPhiNeighbor(const MooseVariableField<RealVectorValue> &) const
    1420             :   {
    1421             :     return _vector_grad_phi_neighbor;
    1422             :   }
    1423             :   const VectorVariablePhiSecond &
    1424             :   secondPhiNeighbor(const MooseVariableField<RealVectorValue> &) const
    1425             :   {
    1426             :     return _vector_second_phi_neighbor;
    1427             :   }
    1428             :   const VectorVariablePhiCurl & curlPhiNeighbor(const MooseVariableField<RealVectorValue> &) const
    1429             :   {
    1430             :     return _vector_curl_phi_neighbor;
    1431             :   }
    1432             :   const VectorVariablePhiDivergence &
    1433             :   divPhiNeighbor(const MooseVariableField<RealVectorValue> &) const
    1434             :   {
    1435             :     return _vector_div_phi_neighbor;
    1436             :   }
    1437             : 
    1438             :   const VectorVariablePhiValue & phiFaceNeighbor(const MooseVariableField<RealVectorValue> &) const
    1439             :   {
    1440             :     return _vector_phi_face_neighbor;
    1441             :   }
    1442             :   const VectorVariablePhiGradient &
    1443             :   gradPhiFaceNeighbor(const MooseVariableField<RealVectorValue> &) const
    1444             :   {
    1445             :     return _vector_grad_phi_face_neighbor;
    1446             :   }
    1447             :   const VectorVariablePhiSecond &
    1448             :   secondPhiFaceNeighbor(const MooseVariableField<RealVectorValue> &) const
    1449             :   {
    1450             :     return _vector_second_phi_face_neighbor;
    1451             :   }
    1452             :   const VectorVariablePhiCurl &
    1453             :   curlPhiFaceNeighbor(const MooseVariableField<RealVectorValue> &) const
    1454             :   {
    1455             :     return _vector_curl_phi_face_neighbor;
    1456             :   }
    1457             :   const VectorVariablePhiDivergence &
    1458             :   divPhiFaceNeighbor(const MooseVariableField<RealVectorValue> &) const
    1459             :   {
    1460             :     return _vector_div_phi_face_neighbor;
    1461             :   }
    1462             : 
    1463             :   // Writeable references
    1464   143573707 :   VariablePhiValue & phi(const MooseVariableField<Real> &) { return _phi; }
    1465   143571680 :   VariablePhiGradient & gradPhi(const MooseVariableField<Real> &) { return _grad_phi; }
    1466       29031 :   VariablePhiSecond & secondPhi(const MooseVariableField<Real> &) { return _second_phi; }
    1467             : 
    1468      659224 :   VariablePhiValue & phiFace(const MooseVariableField<Real> &) { return _phi_face; }
    1469      659118 :   VariablePhiGradient & gradPhiFace(const MooseVariableField<Real> &) { return _grad_phi_face; }
    1470        6089 :   VariablePhiSecond & secondPhiFace(const MooseVariableField<Real> &) { return _second_phi_face; }
    1471             : 
    1472      217581 :   VariablePhiValue & phiNeighbor(const MooseVariableField<Real> &) { return _phi_neighbor; }
    1473      217489 :   VariablePhiGradient & gradPhiNeighbor(const MooseVariableField<Real> &)
    1474             :   {
    1475      217489 :     return _grad_phi_neighbor;
    1476             :   }
    1477           0 :   VariablePhiSecond & secondPhiNeighbor(const MooseVariableField<Real> &)
    1478             :   {
    1479           0 :     return _second_phi_neighbor;
    1480             :   }
    1481             : 
    1482      219817 :   VariablePhiValue & phiFaceNeighbor(const MooseVariableField<Real> &)
    1483             :   {
    1484      219817 :     return _phi_face_neighbor;
    1485             :   }
    1486      219672 :   VariablePhiGradient & gradPhiFaceNeighbor(const MooseVariableField<Real> &)
    1487             :   {
    1488      219672 :     return _grad_phi_face_neighbor;
    1489             :   }
    1490           0 :   VariablePhiSecond & secondPhiFaceNeighbor(const MooseVariableField<Real> &)
    1491             :   {
    1492           0 :     return _second_phi_face_neighbor;
    1493             :   }
    1494             : 
    1495             :   // Writeable references with vector variable
    1496     2114801 :   VectorVariablePhiValue & phi(const MooseVariableField<RealVectorValue> &) { return _vector_phi; }
    1497     2114715 :   VectorVariablePhiGradient & gradPhi(const MooseVariableField<RealVectorValue> &)
    1498             :   {
    1499     2114715 :     return _vector_grad_phi;
    1500             :   }
    1501           0 :   VectorVariablePhiSecond & secondPhi(const MooseVariableField<RealVectorValue> &)
    1502             :   {
    1503           0 :     return _vector_second_phi;
    1504             :   }
    1505       56978 :   VectorVariablePhiCurl & curlPhi(const MooseVariableField<RealVectorValue> &)
    1506             :   {
    1507       56978 :     return _vector_curl_phi;
    1508             :   }
    1509      505608 :   VectorVariablePhiDivergence & divPhi(const MooseVariableField<RealVectorValue> &)
    1510             :   {
    1511      505608 :     return _vector_div_phi;
    1512             :   }
    1513             : 
    1514       66880 :   VectorVariablePhiValue & phiFace(const MooseVariableField<RealVectorValue> &)
    1515             :   {
    1516       66880 :     return _vector_phi_face;
    1517             :   }
    1518       66550 :   VectorVariablePhiGradient & gradPhiFace(const MooseVariableField<RealVectorValue> &)
    1519             :   {
    1520       66550 :     return _vector_grad_phi_face;
    1521             :   }
    1522           0 :   VectorVariablePhiSecond & secondPhiFace(const MooseVariableField<RealVectorValue> &)
    1523             :   {
    1524           0 :     return _vector_second_phi_face;
    1525             :   }
    1526             :   VectorVariablePhiCurl & curlPhiFace(const MooseVariableField<RealVectorValue> &)
    1527             :   {
    1528             :     return _vector_curl_phi_face;
    1529             :   }
    1530             :   VectorVariablePhiDivergence & divPhiFace(const MooseVariableField<RealVectorValue> &)
    1531             :   {
    1532             :     return _vector_div_phi_face;
    1533             :   }
    1534             : 
    1535         304 :   VectorVariablePhiValue & phiNeighbor(const MooseVariableField<RealVectorValue> &)
    1536             :   {
    1537         304 :     return _vector_phi_neighbor;
    1538             :   }
    1539         304 :   VectorVariablePhiGradient & gradPhiNeighbor(const MooseVariableField<RealVectorValue> &)
    1540             :   {
    1541         304 :     return _vector_grad_phi_neighbor;
    1542             :   }
    1543           0 :   VectorVariablePhiSecond & secondPhiNeighbor(const MooseVariableField<RealVectorValue> &)
    1544             :   {
    1545           0 :     return _vector_second_phi_neighbor;
    1546             :   }
    1547             :   VectorVariablePhiCurl & curlPhiNeighbor(const MooseVariableField<RealVectorValue> &)
    1548             :   {
    1549             :     return _vector_curl_phi_neighbor;
    1550             :   }
    1551             :   VectorVariablePhiDivergence & divPhiNeighbor(const MooseVariableField<RealVectorValue> &)
    1552             :   {
    1553             :     return _vector_div_phi_neighbor;
    1554             :   }
    1555         353 :   VectorVariablePhiValue & phiFaceNeighbor(const MooseVariableField<RealVectorValue> &)
    1556             :   {
    1557         353 :     return _vector_phi_face_neighbor;
    1558             :   }
    1559         328 :   VectorVariablePhiGradient & gradPhiFaceNeighbor(const MooseVariableField<RealVectorValue> &)
    1560             :   {
    1561         328 :     return _vector_grad_phi_face_neighbor;
    1562             :   }
    1563           0 :   VectorVariablePhiSecond & secondPhiFaceNeighbor(const MooseVariableField<RealVectorValue> &)
    1564             :   {
    1565           0 :     return _vector_second_phi_face_neighbor;
    1566             :   }
    1567             :   VectorVariablePhiCurl & curlPhiFaceNeighbor(const MooseVariableField<RealVectorValue> &)
    1568             :   {
    1569             :     return _vector_curl_phi_face_neighbor;
    1570             :   }
    1571             :   VectorVariablePhiDivergence & divPhiFaceNeighbor(const MooseVariableField<RealVectorValue> &)
    1572             :   {
    1573             :     return _vector_div_phi_face_neighbor;
    1574             :   }
    1575             : 
    1576             :   // Writeable references with array variable
    1577     1274722 :   VariablePhiValue & phi(const MooseVariableField<RealEigenVector> &) { return _phi; }
    1578     1274722 :   VariablePhiGradient & gradPhi(const MooseVariableField<RealEigenVector> &) { return _grad_phi; }
    1579           0 :   VariablePhiSecond & secondPhi(const MooseVariableField<RealEigenVector> &) { return _second_phi; }
    1580             : 
    1581       14871 :   VariablePhiValue & phiFace(const MooseVariableField<RealEigenVector> &) { return _phi_face; }
    1582       14570 :   VariablePhiGradient & gradPhiFace(const MooseVariableField<RealEigenVector> &)
    1583             :   {
    1584       14570 :     return _grad_phi_face;
    1585             :   }
    1586           0 :   VariablePhiSecond & secondPhiFace(const MooseVariableField<RealEigenVector> &)
    1587             :   {
    1588           0 :     return _second_phi_face;
    1589             :   }
    1590             : 
    1591        4008 :   VariablePhiValue & phiNeighbor(const MooseVariableField<RealEigenVector> &)
    1592             :   {
    1593        4008 :     return _phi_neighbor;
    1594             :   }
    1595        4008 :   VariablePhiGradient & gradPhiNeighbor(const MooseVariableField<RealEigenVector> &)
    1596             :   {
    1597        4008 :     return _grad_phi_neighbor;
    1598             :   }
    1599           0 :   VariablePhiSecond & secondPhiNeighbor(const MooseVariableField<RealEigenVector> &)
    1600             :   {
    1601           0 :     return _second_phi_neighbor;
    1602             :   }
    1603             : 
    1604        4008 :   VariablePhiValue & phiFaceNeighbor(const MooseVariableField<RealEigenVector> &)
    1605             :   {
    1606        4008 :     return _phi_face_neighbor;
    1607             :   }
    1608        4008 :   VariablePhiGradient & gradPhiFaceNeighbor(const MooseVariableField<RealEigenVector> &)
    1609             :   {
    1610        4008 :     return _grad_phi_face_neighbor;
    1611             :   }
    1612           0 :   VariablePhiSecond & secondPhiFaceNeighbor(const MooseVariableField<RealEigenVector> &)
    1613             :   {
    1614           0 :     return _second_phi_face_neighbor;
    1615             :   }
    1616             : 
    1617             :   template <typename OutputType>
    1618      187296 :   const typename OutputTools<OutputType>::VariablePhiValue & fePhi(FEType type) const
    1619             :   {
    1620      187296 :     buildFE(type);
    1621      187296 :     return _fe_shape_data[type]->_phi;
    1622             :   }
    1623             : 
    1624             :   template <typename OutputType>
    1625      187506 :   const typename OutputTools<OutputType>::VariablePhiGradient & feGradPhi(FEType type) const
    1626             :   {
    1627      187506 :     buildFE(type);
    1628      187506 :     return _fe_shape_data[type]->_grad_phi;
    1629             :   }
    1630             : 
    1631             :   template <typename OutputType>
    1632      178966 :   const ADTemplateVariablePhiGradient<OutputType> & feADGradPhi(FEType type) const
    1633             :   {
    1634      178966 :     return _ad_grad_phi_data[type];
    1635             :   }
    1636             : 
    1637             :   template <typename OutputType>
    1638       29246 :   const typename OutputTools<OutputType>::VariablePhiSecond & feSecondPhi(FEType type) const
    1639             :   {
    1640       29246 :     _need_second_derivative.insert(type);
    1641       29246 :     buildFE(type);
    1642       29246 :     return _fe_shape_data[type]->_second_phi;
    1643             :   }
    1644             : 
    1645             :   template <typename OutputType>
    1646             :   const typename OutputTools<OutputType>::VariablePhiValue & fePhiLower(FEType type) const;
    1647             : 
    1648             :   template <typename OutputType>
    1649             :   const typename OutputTools<OutputType>::VariablePhiValue & feDualPhiLower(FEType type) const;
    1650             : 
    1651             :   template <typename OutputType>
    1652             :   const typename OutputTools<OutputType>::VariablePhiGradient & feGradPhiLower(FEType type) const;
    1653             : 
    1654             :   template <typename OutputType>
    1655             :   const typename OutputTools<OutputType>::VariablePhiGradient &
    1656             :   feGradDualPhiLower(FEType type) const;
    1657             : 
    1658             :   template <typename OutputType>
    1659      187296 :   const typename OutputTools<OutputType>::VariablePhiValue & fePhiFace(FEType type) const
    1660             :   {
    1661      187296 :     buildFaceFE(type);
    1662      187296 :     return _fe_shape_data_face[type]->_phi;
    1663             :   }
    1664             : 
    1665             :   template <typename OutputType>
    1666      187296 :   const typename OutputTools<OutputType>::VariablePhiGradient & feGradPhiFace(FEType type) const
    1667             :   {
    1668      187296 :     buildFaceFE(type);
    1669      187296 :     return _fe_shape_data_face[type]->_grad_phi;
    1670             :   }
    1671             : 
    1672             :   template <typename OutputType>
    1673      178966 :   const ADTemplateVariablePhiGradient<OutputType> & feADGradPhiFace(FEType type) const
    1674             :   {
    1675      178966 :     return _ad_grad_phi_data_face[type];
    1676             :   }
    1677             : 
    1678             :   template <typename OutputType>
    1679        6290 :   const typename OutputTools<OutputType>::VariablePhiSecond & feSecondPhiFace(FEType type) const
    1680             :   {
    1681        6290 :     _need_second_derivative.insert(type);
    1682        6290 :     buildFaceFE(type);
    1683        6290 :     return _fe_shape_data_face[type]->_second_phi;
    1684             :   }
    1685             : 
    1686             :   template <typename OutputType>
    1687      187296 :   const typename OutputTools<OutputType>::VariablePhiValue & fePhiNeighbor(FEType type) const
    1688             :   {
    1689      187296 :     buildNeighborFE(type);
    1690      187296 :     return _fe_shape_data_neighbor[type]->_phi;
    1691             :   }
    1692             : 
    1693             :   template <typename OutputType>
    1694      187296 :   const typename OutputTools<OutputType>::VariablePhiGradient & feGradPhiNeighbor(FEType type) const
    1695             :   {
    1696      187296 :     buildNeighborFE(type);
    1697      187296 :     return _fe_shape_data_neighbor[type]->_grad_phi;
    1698             :   }
    1699             : 
    1700             :   template <typename OutputType>
    1701          42 :   const typename OutputTools<OutputType>::VariablePhiSecond & feSecondPhiNeighbor(FEType type) const
    1702             :   {
    1703          42 :     _need_second_derivative_neighbor.insert(type);
    1704          42 :     buildNeighborFE(type);
    1705          42 :     return _fe_shape_data_neighbor[type]->_second_phi;
    1706             :   }
    1707             : 
    1708             :   template <typename OutputType>
    1709      187296 :   const typename OutputTools<OutputType>::VariablePhiValue & fePhiFaceNeighbor(FEType type) const
    1710             :   {
    1711      187296 :     buildFaceNeighborFE(type);
    1712      187296 :     return _fe_shape_data_face_neighbor[type]->_phi;
    1713             :   }
    1714             : 
    1715             :   template <typename OutputType>
    1716             :   const typename OutputTools<OutputType>::VariablePhiGradient &
    1717      187296 :   feGradPhiFaceNeighbor(FEType type) const
    1718             :   {
    1719      187296 :     buildFaceNeighborFE(type);
    1720      187296 :     return _fe_shape_data_face_neighbor[type]->_grad_phi;
    1721             :   }
    1722             : 
    1723             :   template <typename OutputType>
    1724             :   const typename OutputTools<OutputType>::VariablePhiSecond &
    1725          42 :   feSecondPhiFaceNeighbor(FEType type) const
    1726             :   {
    1727          42 :     _need_second_derivative_neighbor.insert(type);
    1728          42 :     buildFaceNeighborFE(type);
    1729          42 :     return _fe_shape_data_face_neighbor[type]->_second_phi;
    1730             :   }
    1731             : 
    1732             :   template <typename OutputType>
    1733           0 :   const typename OutputTools<OutputType>::VariablePhiCurl & feCurlPhi(FEType type) const
    1734             :   {
    1735           0 :     _need_curl.insert(type);
    1736           0 :     buildFE(type);
    1737           0 :     return _fe_shape_data[type]->_curl_phi;
    1738             :   }
    1739             : 
    1740             :   template <typename OutputType>
    1741           0 :   const typename OutputTools<OutputType>::VariablePhiCurl & feCurlPhiFace(FEType type) const
    1742             :   {
    1743           0 :     _need_curl.insert(type);
    1744           0 :     buildFaceFE(type);
    1745           0 :     return _fe_shape_data_face[type]->_curl_phi;
    1746             :   }
    1747             : 
    1748             :   template <typename OutputType>
    1749           0 :   const typename OutputTools<OutputType>::VariablePhiCurl & feCurlPhiNeighbor(FEType type) const
    1750             :   {
    1751           0 :     _need_curl.insert(type);
    1752           0 :     buildNeighborFE(type);
    1753           0 :     return _fe_shape_data_neighbor[type]->_curl_phi;
    1754             :   }
    1755             : 
    1756             :   template <typename OutputType>
    1757           0 :   const typename OutputTools<OutputType>::VariablePhiCurl & feCurlPhiFaceNeighbor(FEType type) const
    1758             :   {
    1759           0 :     _need_curl.insert(type);
    1760           0 :     buildFaceNeighborFE(type);
    1761           0 :     return _fe_shape_data_face_neighbor[type]->_curl_phi;
    1762             :   }
    1763             : 
    1764             :   template <typename OutputType>
    1765           0 :   const typename OutputTools<OutputType>::VariablePhiDivergence & feDivPhi(FEType type) const
    1766             :   {
    1767           0 :     buildFE(type);
    1768           0 :     return _fe_shape_data[type]->_div_phi;
    1769             :   }
    1770             : 
    1771             :   template <typename OutputType>
    1772           0 :   const typename OutputTools<OutputType>::VariablePhiDivergence & feDivPhiFace(FEType type) const
    1773             :   {
    1774           0 :     buildFaceFE(type);
    1775           0 :     return _fe_shape_data_face[type]->_div_phi;
    1776             :   }
    1777             : 
    1778             :   template <typename OutputType>
    1779             :   const typename OutputTools<OutputType>::VariablePhiDivergence &
    1780           0 :   feDivPhiNeighbor(FEType type) const
    1781             :   {
    1782           0 :     buildNeighborFE(type);
    1783           0 :     return _fe_shape_data_neighbor[type]->_div_phi;
    1784             :   }
    1785             : 
    1786             :   template <typename OutputType>
    1787             :   const typename OutputTools<OutputType>::VariablePhiDivergence &
    1788           0 :   feDivPhiFaceNeighbor(FEType type) const
    1789             :   {
    1790           0 :     buildFaceNeighborFE(type);
    1791           0 :     return _fe_shape_data_face_neighbor[type]->_div_phi;
    1792             :   }
    1793             : 
    1794             :   /// On-demand computation of volume element accounting for RZ/RSpherical
    1795             :   Real elementVolume(const Elem * elem) const;
    1796             : 
    1797             :   /**
    1798             :    * Set the pointer to the XFEM controller object
    1799             :    */
    1800           0 :   void setXFEM(std::shared_ptr<XFEMInterface> xfem) { _xfem = xfem; }
    1801             : 
    1802             :   /**
    1803             :    * Assign the displacement numbers and directions
    1804             :    */
    1805             :   void assignDisplacements(
    1806             :       std::vector<std::pair<unsigned int, unsigned short>> && disp_numbers_and_directions);
    1807             : 
    1808             :   /**
    1809             :    * Helper function for assembling residual contriubutions on local
    1810             :    * quadrature points for an array kernel, bc, etc.
    1811             :    * @param re The local residual
    1812             :    * @param i The local test function index
    1813             :    * @param ntest The number of test functions
    1814             :    * @param v The residual contribution on the current qp
    1815             :    */
    1816   120492764 :   void saveLocalArrayResidual(DenseVector<Number> & re,
    1817             :                               unsigned int i,
    1818             :                               unsigned int ntest,
    1819             :                               const RealEigenVector & v) const
    1820             :   {
    1821   400909884 :     for (unsigned int j = 0; j < v.size(); ++j, i += ntest)
    1822   280417120 :       re(i) += v(j);
    1823   120492764 :   }
    1824             : 
    1825             :   /**
    1826             :    * Helper function for assembling diagonal Jacobian contriubutions on local
    1827             :    * quadrature points for an array kernel, bc, etc.
    1828             :    * @param ke The local Jacobian
    1829             :    * @param i The local test function index
    1830             :    * @param ntest The number of test functions
    1831             :    * @param j The local shape function index
    1832             :    * @param nphi The number of shape functions
    1833             :    * @param v The diagonal Jacobian contribution on the current qp
    1834             :    */
    1835    35087136 :   void saveDiagLocalArrayJacobian(DenseMatrix<Number> & ke,
    1836             :                                   unsigned int i,
    1837             :                                   unsigned int ntest,
    1838             :                                   unsigned int j,
    1839             :                                   unsigned int nphi,
    1840             :                                   unsigned int ivar,
    1841             :                                   const RealEigenVector & v) const
    1842             :   {
    1843    35087136 :     unsigned int pace = (_component_block_diagonal[ivar] ? 0 : nphi);
    1844   109454688 :     for (unsigned int k = 0; k < v.size(); ++k, i += ntest, j += pace)
    1845    74367552 :       ke(i, j) += v(k);
    1846    35087136 :   }
    1847             : 
    1848             :   /**
    1849             :    * Helper function for assembling full Jacobian contriubutions on local
    1850             :    * quadrature points for an array kernel, bc, etc.
    1851             :    * @param ke The local Jacobian
    1852             :    * @param i The local test function index
    1853             :    * @param ntest The number of test functions
    1854             :    * @param j The local shape function index
    1855             :    * @param nphi The number of shape functions
    1856             :    * @param ivar The array variable index
    1857             :    * @param jvar The contributing variable index
    1858             :    * @param v The full Jacobian contribution from a variable on the current qp
    1859             :    */
    1860    56415506 :   void saveFullLocalArrayJacobian(DenseMatrix<Number> & ke,
    1861             :                                   unsigned int i,
    1862             :                                   unsigned int ntest,
    1863             :                                   unsigned int j,
    1864             :                                   unsigned int nphi,
    1865             :                                   unsigned int ivar,
    1866             :                                   unsigned int jvar,
    1867             :                                   const RealEigenMatrix & v) const
    1868             :   {
    1869    56415506 :     if (ivar == jvar && _component_block_diagonal[ivar])
    1870             :     {
    1871      247176 :       for (unsigned int k = 0; k < v.rows(); ++k, i += ntest)
    1872      161220 :         ke(i, j) += v(k, k);
    1873             :     }
    1874             :     else
    1875             :     {
    1876    56329550 :       const unsigned int saved_j = j;
    1877   257308650 :       for (unsigned int k = 0; k < v.rows(); ++k, i += ntest)
    1878             :       {
    1879   200979100 :         j = saved_j;
    1880   955885524 :         for (unsigned int l = 0; l < v.cols(); ++l, j += nphi)
    1881   754906424 :           ke(i, j) += v(k, l);
    1882             :       }
    1883             :     }
    1884    56415506 :   }
    1885             : 
    1886        2690 :   DenseVector<Real> getJacobianDiagonal(DenseMatrix<Number> & ke)
    1887             :   {
    1888        2690 :     unsigned int rows = ke.m();
    1889        2690 :     unsigned int cols = ke.n();
    1890        2690 :     DenseVector<Real> diag(rows);
    1891       18346 :     for (unsigned int i = 0; i < rows; i++)
    1892             :       // % operation is needed to account for cases of no component coupling of array variables
    1893       15656 :       diag(i) = ke(i, i % cols);
    1894        2690 :     return diag;
    1895             :   }
    1896             : 
    1897             :   /**
    1898             :    * Attaches the current elem/volume quadrature rule to the given fe.  The
    1899             :    * current subdomain (as set via setCurrentSubdomainID is used to determine
    1900             :    * the correct rule.  The attached quadrature rule is also returned.
    1901             :    */
    1902             :   inline const libMesh::QBase * attachQRuleElem(unsigned int dim, FEBase & fe)
    1903             :   {
    1904             :     auto qrule = qrules(dim).vol.get();
    1905             :     fe.attach_quadrature_rule(qrule);
    1906             :     return qrule;
    1907             :   }
    1908             : 
    1909             :   /**
    1910             :    * Attaches the current face/area quadrature rule to the given fe.  The
    1911             :    * current subdomain (as set via setCurrentSubdomainID is used to determine
    1912             :    * the correct rule.  The attached quadrature rule is also returned.
    1913             :    */
    1914             :   inline const libMesh::QBase * attachQRuleFace(unsigned int dim, FEBase & fe)
    1915             :   {
    1916             :     auto qrule = qrules(dim).face.get();
    1917             :     fe.attach_quadrature_rule(qrule);
    1918             :     return qrule;
    1919             :   }
    1920             : 
    1921             :   /**
    1922             :    * signals this object that a vector containing variable scaling factors should be used when
    1923             :    * doing residual and matrix assembly
    1924             :    */
    1925             :   void hasScalingVector();
    1926             : 
    1927             :   /**
    1928             :    * Modify the weights when using the arbitrary quadrature rule. The intention is to use this when
    1929             :    * you wish to supply your own quadrature after calling reinit at physical points.
    1930             :    *
    1931             :    * You should only use this if the arbitrary quadrature is the current quadrature rule!
    1932             :    *
    1933             :    * @param weights The weights to fill into _current_JxW
    1934             :    */
    1935             :   void modifyArbitraryWeights(const std::vector<Real> & weights);
    1936             : 
    1937             :   /**
    1938             :    * @return whether we are computing a residual
    1939             :    */
    1940    47400051 :   bool computingResidual() const { return _computing_residual; }
    1941             : 
    1942             :   /**
    1943             :    * @return whether we are computing a Jacobian
    1944             :    */
    1945    46136451 :   bool computingJacobian() const { return _computing_jacobian; }
    1946             : 
    1947             :   /**
    1948             :    * @return whether we are computing a residual and a Jacobian simultaneously
    1949             :    */
    1950             :   bool computingResidualAndJacobian() const { return _computing_residual_and_jacobian; }
    1951             : 
    1952             :   /**
    1953             :    * @return The current mortar segment element
    1954             :    */
    1955        1448 :   const Elem * const & msmElem() const { return _msm_elem; }
    1956             : 
    1957             :   /**
    1958             :    * Indicate that we have p-refinement. This method will perform the following tasks:
    1959             :    * - Disable p-refinement as requested by the user with \p disable_p_refinement_for_families
    1960             :    * -.Disable p-refinement of Lagrange helper types that we use for getting things like the
    1961             :    *   physical locations of quadrature points and JxW. (Don't worry, we still use the element
    1962             :    *   p-level when initializing the quadrature rule attached to the Lagrange helper so the number
    1963             :    *   of quadrature points reflects the element p-level)
    1964             :    * @param disable_p_refinement_for_families Families that we should disable p-refinement for
    1965             :    */
    1966             :   void havePRefinement(const std::unordered_set<FEFamily> & disable_p_refinement_for_families);
    1967             : 
    1968             :   /**
    1969             :    * Set the current lower dimensional element. This may be null
    1970             :    */
    1971             :   void setCurrentLowerDElem(const Elem * const lower_d_elem);
    1972             : 
    1973             : private:
    1974             :   /**
    1975             :    * Just an internal helper function to reinit the volume FE objects.
    1976             :    *
    1977             :    * @param elem The element we are using to reinit
    1978             :    */
    1979             :   void reinitFE(const Elem * elem);
    1980             : 
    1981             :   /**
    1982             :    * Just an internal helper function to reinit the face FE objects.
    1983             :    *
    1984             :    * @param elem The element we are using to reinit
    1985             :    * @param side The side of the element we are reiniting on
    1986             :    */
    1987             :   void reinitFEFace(const Elem * elem, unsigned int side);
    1988             : 
    1989             :   void computeFaceMap(const Elem & elem, const unsigned int side, const std::vector<Real> & qw);
    1990             : 
    1991             :   void reinitFEFaceNeighbor(const Elem * neighbor, const std::vector<Point> & reference_points);
    1992             : 
    1993             :   void reinitFENeighbor(const Elem * neighbor, const std::vector<Point> & reference_points);
    1994             : 
    1995             :   template <typename Points, typename Coords>
    1996             :   void setCoordinateTransformation(const libMesh::QBase * qrule,
    1997             :                                    const Points & q_points,
    1998             :                                    Coords & coord,
    1999             :                                    SubdomainID sub_id);
    2000             : 
    2001             :   void computeCurrentElemVolume();
    2002             : 
    2003             :   void computeCurrentFaceVolume();
    2004             : 
    2005             :   void computeCurrentNeighborVolume();
    2006             : 
    2007             :   /**
    2008             :    * Update the integration weights for XFEM partial elements.
    2009             :    * This only affects the weights if XFEM is used and if the element is cut.
    2010             :    * @param elem The element for which the weights are adjusted
    2011             :    */
    2012             :   void modifyWeightsDueToXFEM(const Elem * elem);
    2013             : 
    2014             :   /**
    2015             :    * Update the face integration weights for XFEM partial elements.
    2016             :    * This only affects the weights if XFEM is used and if the element is cut.
    2017             :    * @param elem The element for which the weights are adjusted
    2018             :    * @param side The side of element for which the weights are adjusted
    2019             :    */
    2020             :   void modifyFaceWeightsDueToXFEM(const Elem * elem, unsigned int side = 0);
    2021             : 
    2022             :   /**
    2023             :    * compute gradient of phi possibly with derivative information with respect to nonlinear
    2024             :    * displacement variables
    2025             :    */
    2026             :   template <typename OutputType>
    2027             :   void computeGradPhiAD(const Elem * elem,
    2028             :                         unsigned int n_qp,
    2029             :                         ADTemplateVariablePhiGradient<OutputType> & grad_phi,
    2030             :                         libMesh::FEGenericBase<OutputType> * fe);
    2031             : 
    2032             :   /**
    2033             :    * resize any objects that contribute to automatic differentiation-related mapping calculations
    2034             :    */
    2035             :   void resizeADMappingObjects(unsigned int n_qp, unsigned int dim);
    2036             : 
    2037             :   /**
    2038             :    * compute the finite element reference-physical mapping quantities (such as JxW) with possible
    2039             :    * dependence on nonlinear displacement variables at a single quadrature point
    2040             :    */
    2041             :   void
    2042             :   computeSinglePointMapAD(const Elem * elem, const std::vector<Real> & qw, unsigned p, FEBase * fe);
    2043             : 
    2044             :   /**
    2045             :    * Add local residuals of all field variables for a tag onto the tag's residual vector
    2046             :    */
    2047             :   void addResidual(const VectorTag & vector_tag);
    2048             :   /**
    2049             :    * Add local neighbor residuals of all field variables for a tag onto the tag's residual vector
    2050             :    */
    2051             :   void addResidualNeighbor(const VectorTag & vector_tag);
    2052             :   /**
    2053             :    * Add local lower-dimensional block residuals of all field variables for a tag onto the tag's
    2054             :    * residual vector
    2055             :    */
    2056             :   void addResidualLower(const VectorTag & vector_tag);
    2057             :   /**
    2058             :    * Add residuals of all scalar variables for a tag onto the tag's residual vector
    2059             :    */
    2060             :   void addResidualScalar(const VectorTag & vector_tag);
    2061             : 
    2062             :   /**
    2063             :    * Clears all of the cached residuals for a specific vector tag
    2064             :    */
    2065             :   void clearCachedResiduals(const VectorTag & vector_tag);
    2066             : 
    2067             :   /**
    2068             :    * Cache individual residual contributions.  These will ultimately get added to the residual when
    2069             :    * addCachedResidual() is called.
    2070             :    *
    2071             :    * @param dof The degree of freedom to add the residual contribution to
    2072             :    * @param value The value of the residual contribution.
    2073             :    * @param TagID  the contribution should go to this tagged residual
    2074             :    */
    2075             :   void cacheResidual(dof_id_type dof, Real value, TagID tag_id);
    2076             : 
    2077             :   /**
    2078             :    * Cache individual residual contributions.  These will ultimately get added to the residual when
    2079             :    * addCachedResidual() is called.
    2080             :    *
    2081             :    * @param dof The degree of freedom to add the residual contribution to
    2082             :    * @param value The value of the residual contribution.
    2083             :    * @param tags the contribution should go to all these tags
    2084             :    */
    2085             :   void cacheResidual(dof_id_type dof, Real value, const std::set<TagID> & tags);
    2086             : 
    2087             :   /**
    2088             :    * Appling scaling, constraints to the local residual block and populate the full DoF indices
    2089             :    * for array variable.
    2090             :    */
    2091             :   void processLocalResidual(DenseVector<Number> & res_block,
    2092             :                             std::vector<dof_id_type> & dof_indices,
    2093             :                             const std::vector<Real> & scaling_factor,
    2094             :                             bool is_nodal);
    2095             : 
    2096             :   /**
    2097             :    * Add a local residual block to a global residual vector with proper scaling.
    2098             :    */
    2099             :   void addResidualBlock(NumericVector<Number> & residual,
    2100             :                         DenseVector<Number> & res_block,
    2101             :                         const std::vector<dof_id_type> & dof_indices,
    2102             :                         const std::vector<Real> & scaling_factor,
    2103             :                         bool is_nodal);
    2104             : 
    2105             :   /**
    2106             :    * Push a local residual block with proper scaling into cache.
    2107             :    */
    2108             :   void cacheResidualBlock(std::vector<Real> & cached_residual_values,
    2109             :                           std::vector<dof_id_type> & cached_residual_rows,
    2110             :                           DenseVector<Number> & res_block,
    2111             :                           const std::vector<dof_id_type> & dof_indices,
    2112             :                           const std::vector<Real> & scaling_factor,
    2113             :                           bool is_nodal);
    2114             : 
    2115             :   /**
    2116             :    * Set a local residual block to a global residual vector with proper scaling.
    2117             :    */
    2118             :   void setResidualBlock(NumericVector<Number> & residual,
    2119             :                         DenseVector<Number> & res_block,
    2120             :                         const std::vector<dof_id_type> & dof_indices,
    2121             :                         const std::vector<Real> & scaling_factor,
    2122             :                         bool is_nodal);
    2123             : 
    2124             :   /**
    2125             :    * Add a local Jacobian block to a global Jacobian with proper scaling.
    2126             :    */
    2127             :   void addJacobianBlock(libMesh::SparseMatrix<Number> & jacobian,
    2128             :                         DenseMatrix<Number> & jac_block,
    2129             :                         const MooseVariableBase & ivar,
    2130             :                         const MooseVariableBase & jvar,
    2131             :                         const std::vector<dof_id_type> & idof_indices,
    2132             :                         const std::vector<dof_id_type> & jdof_indices);
    2133             : 
    2134             :   /**
    2135             :    * Push a local Jacobian block with proper scaling into cache for a certain tag.
    2136             :    */
    2137             :   void cacheJacobianBlock(DenseMatrix<Number> & jac_block,
    2138             :                           const MooseVariableBase & ivar,
    2139             :                           const MooseVariableBase & jvar,
    2140             :                           const std::vector<dof_id_type> & idof_indices,
    2141             :                           const std::vector<dof_id_type> & jdof_indices,
    2142             :                           TagID tag);
    2143             : 
    2144             :   /**
    2145             :    * Push non-zeros of a local Jacobian block with proper scaling into cache for a certain tag.
    2146             :    */
    2147             :   void cacheJacobianBlockNonzero(DenseMatrix<Number> & jac_block,
    2148             :                                  const MooseVariableBase & ivar,
    2149             :                                  const MooseVariableBase & jvar,
    2150             :                                  const std::vector<dof_id_type> & idof_indices,
    2151             :                                  const std::vector<dof_id_type> & jdof_indices,
    2152             :                                  TagID tag);
    2153             : 
    2154             :   /**
    2155             :    * Adds element matrices for ivar rows and jvar columns to the global Jacobian matrices.
    2156             :    */
    2157             :   void addJacobianCoupledVarPair(const MooseVariableBase & ivar, const MooseVariableBase & jvar);
    2158             : 
    2159             :   /**
    2160             :    * Caches element matrix for ivar rows and jvar columns
    2161             :    */
    2162             :   void cacheJacobianCoupledVarPair(const MooseVariableBase & ivar, const MooseVariableBase & jvar);
    2163             : 
    2164             :   /**
    2165             :    * Clear any currently cached jacobians
    2166             :    *
    2167             :    * This is automatically called by setCachedJacobian
    2168             :    */
    2169             :   void clearCachedJacobian();
    2170             : 
    2171             :   /**
    2172             :    * Build FEs with a type
    2173             :    * @param type The type of FE
    2174             :    */
    2175             :   void buildFE(FEType type) const;
    2176             : 
    2177             :   /**
    2178             :    * Build FEs for a face with a type
    2179             :    * @param type The type of FE
    2180             :    */
    2181             :   void buildFaceFE(FEType type) const;
    2182             : 
    2183             :   /**
    2184             :    * Build FEs for a neighbor with a type
    2185             :    * @param type The type of FE
    2186             :    */
    2187             :   void buildNeighborFE(FEType type) const;
    2188             : 
    2189             :   /**
    2190             :    * Build FEs for a neighbor face with a type
    2191             :    * @param type The type of FE
    2192             :    */
    2193             :   void buildFaceNeighborFE(FEType type) const;
    2194             : 
    2195             :   /**
    2196             :    * Build FEs for a lower dimensional element with a type
    2197             :    * @param type The type of FE
    2198             :    */
    2199             :   void buildLowerDFE(FEType type) const;
    2200             : 
    2201             :   void buildLowerDDualFE(FEType type) const;
    2202             : 
    2203             :   /**
    2204             :    * Build Vector FEs with a type
    2205             :    * @param type The type of FE
    2206             :    */
    2207             :   void buildVectorFE(FEType type) const;
    2208             : 
    2209             :   /**
    2210             :    * Build Vector FEs for a face with a type
    2211             :    * @param type The type of FE
    2212             :    */
    2213             :   void buildVectorFaceFE(FEType type) const;
    2214             : 
    2215             :   /**
    2216             :    * Build Vector FEs for a neighbor with a type
    2217             :    * @param type The type of FE
    2218             :    */
    2219             :   void buildVectorNeighborFE(FEType type) const;
    2220             : 
    2221             :   /**
    2222             :    * Build Vector FEs for a neighbor face with a type
    2223             :    * @param type The type of FE
    2224             :    */
    2225             :   void buildVectorFaceNeighborFE(FEType type) const;
    2226             : 
    2227             :   /**
    2228             :    * Build Vector FEs for a lower dimensional element with a type
    2229             :    * @param type The type of FE
    2230             :    */
    2231             :   void buildVectorLowerDFE(FEType type) const;
    2232             :   void buildVectorDualLowerDFE(FEType type) const;
    2233             : 
    2234             :   /**
    2235             :    * Sets whether or not Jacobian coupling between \p ivar and \p jvar is used
    2236             :    * to the value \p used
    2237             :    */
    2238   860005574 :   void jacobianBlockUsed(TagID tag, unsigned int ivar, unsigned int jvar, bool used)
    2239             :   {
    2240   860005574 :     _jacobian_block_used[tag][ivar][_block_diagonal_matrix ? 0 : jvar] = used;
    2241   860005574 :   }
    2242             : 
    2243             :   /**
    2244             :    * Return a flag to indicate if a particular coupling Jacobian block
    2245             :    * between \p ivar and \p jvar is used
    2246             :    */
    2247   176534307 :   char jacobianBlockUsed(TagID tag, unsigned int ivar, unsigned int jvar) const
    2248             :   {
    2249   176534307 :     return _jacobian_block_used[tag][ivar][_block_diagonal_matrix ? 0 : jvar];
    2250             :   }
    2251             : 
    2252             :   /**
    2253             :    * Sets whether or not neighbor Jacobian coupling between \p ivar and \p jvar is used
    2254             :    * to the value \p used
    2255             :    */
    2256   503165066 :   void jacobianBlockNeighborUsed(TagID tag, unsigned int ivar, unsigned int jvar, bool used)
    2257             :   {
    2258   503165066 :     _jacobian_block_neighbor_used[tag][ivar][_block_diagonal_matrix ? 0 : jvar] = used;
    2259   503165066 :   }
    2260             : 
    2261             :   /**
    2262             :    * Return a flag to indicate if a particular coupling neighbor Jacobian block
    2263             :    * between \p ivar and \p jvar is used
    2264             :    */
    2265      539618 :   char jacobianBlockNeighborUsed(TagID tag, unsigned int ivar, unsigned int jvar) const
    2266             :   {
    2267      539618 :     return _jacobian_block_neighbor_used[tag][ivar][_block_diagonal_matrix ? 0 : jvar];
    2268             :   }
    2269             : 
    2270             :   /**
    2271             :    * Sets whether or not lower Jacobian coupling between \p ivar and \p jvar is used
    2272             :    * to the value \p used
    2273             :    */
    2274    13432811 :   void jacobianBlockLowerUsed(TagID tag, unsigned int ivar, unsigned int jvar, bool used)
    2275             :   {
    2276    13432811 :     _jacobian_block_lower_used[tag][ivar][_block_diagonal_matrix ? 0 : jvar] = used;
    2277    13432811 :   }
    2278             : 
    2279             :   /**
    2280             :    * Return a flag to indicate if a particular coupling lower Jacobian block
    2281             :    * between \p ivar and \p jvar is used
    2282             :    */
    2283     1056418 :   char jacobianBlockLowerUsed(TagID tag, unsigned int ivar, unsigned int jvar) const
    2284             :   {
    2285     1056418 :     return _jacobian_block_lower_used[tag][ivar][_block_diagonal_matrix ? 0 : jvar];
    2286             :   }
    2287             : 
    2288             :   /**
    2289             :    * Sets whether or not nonlocal Jacobian coupling between \p ivar and \p jvar is used
    2290             :    * to the value \p used
    2291             :    */
    2292       50044 :   void jacobianBlockNonlocalUsed(TagID tag, unsigned int ivar, unsigned int jvar, bool used)
    2293             :   {
    2294       50044 :     _jacobian_block_nonlocal_used[tag][ivar][_block_diagonal_matrix ? 0 : jvar] = used;
    2295       50044 :   }
    2296             : 
    2297             :   /**
    2298             :    * Return a flag to indicate if a particular coupling nonlocal Jacobian block
    2299             :    * between \p ivar and \p jvar is used
    2300             :    */
    2301       12040 :   char jacobianBlockNonlocalUsed(TagID tag, unsigned int ivar, unsigned int jvar) const
    2302             :   {
    2303       12040 :     return _jacobian_block_nonlocal_used[tag][ivar][_block_diagonal_matrix ? 0 : jvar];
    2304             :   }
    2305             : 
    2306             :   /**
    2307             :    * request phi, dphi, xyz, JxW, etc. data through the FE helper functions
    2308             :    */
    2309             :   void helpersRequestData();
    2310             : 
    2311             :   SystemBase & _sys;
    2312             :   SubProblem & _subproblem;
    2313             : 
    2314             :   const bool _displaced;
    2315             : 
    2316             :   /// Coupling matrices
    2317             :   const libMesh::CouplingMatrix * _cm;
    2318             :   const libMesh::CouplingMatrix & _nonlocal_cm;
    2319             : 
    2320             :   /// Whether we are currently computing the residual
    2321             :   const bool & _computing_residual;
    2322             : 
    2323             :   /// Whether we are currently computing the Jacobian
    2324             :   const bool & _computing_jacobian;
    2325             : 
    2326             :   /// Whether we are currently computing the residual and Jacobian
    2327             :   const bool & _computing_residual_and_jacobian;
    2328             : 
    2329             :   /// Entries in the coupling matrix for field variables
    2330             :   std::vector<std::pair<MooseVariableFieldBase *, MooseVariableFieldBase *>> _cm_ff_entry;
    2331             :   /// Entries in the coupling matrix for field variables vs scalar variables
    2332             :   std::vector<std::pair<MooseVariableFieldBase *, MooseVariableScalar *>> _cm_fs_entry;
    2333             :   /// Entries in the coupling matrix for scalar variables vs field variables
    2334             :   std::vector<std::pair<MooseVariableScalar *, MooseVariableFieldBase *>> _cm_sf_entry;
    2335             :   /// Entries in the coupling matrix for scalar variables
    2336             :   std::vector<std::pair<MooseVariableScalar *, MooseVariableScalar *>> _cm_ss_entry;
    2337             :   /// Entries in the coupling matrix for field variables for nonlocal calculations
    2338             :   std::vector<std::pair<MooseVariableFieldBase *, MooseVariableFieldBase *>> _cm_nonlocal_entry;
    2339             :   /// Flag that indicates if the jacobian block was used
    2340             :   std::vector<std::vector<std::vector<unsigned char>>> _jacobian_block_used;
    2341             :   std::vector<std::vector<std::vector<unsigned char>>> _jacobian_block_nonlocal_used;
    2342             :   /// Flag that indicates if the jacobian block for neighbor was used
    2343             :   std::vector<std::vector<std::vector<unsigned char>>> _jacobian_block_neighbor_used;
    2344             :   /// Flag that indicates if the jacobian block for the lower dimensional element was used
    2345             :   std::vector<std::vector<std::vector<unsigned char>>> _jacobian_block_lower_used;
    2346             :   /// DOF map
    2347             :   const libMesh::DofMap & _dof_map;
    2348             :   /// Thread number (id)
    2349             :   THREAD_ID _tid;
    2350             : 
    2351             :   MooseMesh & _mesh;
    2352             : 
    2353             :   unsigned int _mesh_dimension;
    2354             : 
    2355             :   /// The finite element type of the FE helper classes. The helper class gives us data like JxW, the
    2356             :   /// physical quadrature point locations, etc.
    2357             :   const FEType _helper_type;
    2358             : 
    2359             :   /// Whether user code requested a \p FEType the same as our \p _helper_type
    2360             :   mutable bool _user_added_fe_of_helper_type;
    2361             :   mutable bool _user_added_fe_face_of_helper_type;
    2362             :   mutable bool _user_added_fe_face_neighbor_of_helper_type;
    2363             :   mutable bool _user_added_fe_neighbor_of_helper_type;
    2364             :   mutable bool _user_added_fe_lower_of_helper_type;
    2365             : 
    2366             :   /// Containers for holding unique FE helper types if we are doing p-refinement. If we are not
    2367             :   /// doing p-refinement then the helper data is owned by the \p _fe data members
    2368             :   std::vector<std::unique_ptr<FEBase>> _unique_fe_helper;
    2369             :   std::vector<std::unique_ptr<FEBase>> _unique_fe_face_helper;
    2370             :   std::vector<std::unique_ptr<FEBase>> _unique_fe_face_neighbor_helper;
    2371             :   std::vector<std::unique_ptr<FEBase>> _unique_fe_neighbor_helper;
    2372             :   std::vector<std::unique_ptr<FEBase>> _unique_fe_lower_helper;
    2373             : 
    2374             :   /// Whether we are currently building the FE classes for the helpers
    2375             :   bool _building_helpers;
    2376             : 
    2377             :   /// The XFEM controller
    2378             :   std::shared_ptr<XFEMInterface> _xfem;
    2379             : 
    2380             :   /// The "volume" fe object that matches the current elem
    2381             :   std::map<FEType, FEBase *> _current_fe;
    2382             :   /// The "face" fe object that matches the current elem
    2383             :   std::map<FEType, FEBase *> _current_fe_face;
    2384             :   /// The "neighbor" fe object that matches the current elem
    2385             :   std::map<FEType, FEBase *> _current_fe_neighbor;
    2386             :   /// The "neighbor face" fe object that matches the current elem
    2387             :   std::map<FEType, FEBase *> _current_fe_face_neighbor;
    2388             : 
    2389             :   /// The "volume" vector fe object that matches the current elem
    2390             :   std::map<FEType, FEVectorBase *> _current_vector_fe;
    2391             :   /// The "face" vector fe object that matches the current elem
    2392             :   std::map<FEType, FEVectorBase *> _current_vector_fe_face;
    2393             :   /// The "neighbor" vector fe object that matches the current elem
    2394             :   std::map<FEType, FEVectorBase *> _current_vector_fe_neighbor;
    2395             :   /// The "neighbor face" vector fe object that matches the current elem
    2396             :   std::map<FEType, FEVectorBase *> _current_vector_fe_face_neighbor;
    2397             : 
    2398             :   /**** Volume Stuff ****/
    2399             : 
    2400             :   /// Each dimension's actual fe objects indexed on type
    2401             :   mutable std::map<unsigned int, std::map<FEType, FEBase *>> _fe;
    2402             :   /// Each dimension's actual vector fe objects indexed on type
    2403             :   mutable std::map<unsigned int, std::map<FEType, FEVectorBase *>> _vector_fe;
    2404             :   /// Each dimension's helper objects
    2405             :   std::map<unsigned int, FEBase *> _holder_fe_helper;
    2406             :   /// The current helper object for transforming coordinates
    2407             :   FEBase * _current_fe_helper;
    2408             :   /// The current current quadrature rule being used (could be either volumetric or arbitrary - for dirac kernels)
    2409             :   libMesh::QBase * _current_qrule;
    2410             :   /// The current volumetric quadrature for the element
    2411             :   libMesh::QBase * _current_qrule_volume;
    2412             :   /// The current arbitrary quadrature rule used within the element interior
    2413             :   ArbitraryQuadrature * _current_qrule_arbitrary;
    2414             :   /// The current arbitrary quadrature rule used on the element face
    2415             :   ArbitraryQuadrature * _current_qrule_arbitrary_face;
    2416             :   /// The current list of quadrature points
    2417             :   MooseArray<Point> _current_q_points;
    2418             :   /// The current list of transformed jacobian weights
    2419             :   MooseArray<Real> _current_JxW;
    2420             :   /// The coordinate system
    2421             :   Moose::CoordinateSystemType _coord_type;
    2422             :   /// The current coordinate transformation coefficients
    2423             :   MooseArray<Real> _coord;
    2424             :   /// The AD version of the current coordinate transformation coefficients
    2425             :   MooseArray<ADReal> _ad_coord;
    2426             : 
    2427             :   /// Data structure for tracking/grouping a set of quadrature rules for a
    2428             :   /// particular dimensionality of mesh element.
    2429             :   struct QRules
    2430             :   {
    2431      210800 :     QRules()
    2432      210800 :       : vol(nullptr),
    2433      210800 :         face(nullptr),
    2434      210800 :         arbitrary_vol(nullptr),
    2435      210800 :         arbitrary_face(nullptr),
    2436      421600 :         neighbor(nullptr)
    2437             :     {
    2438      210800 :     }
    2439             : 
    2440             :     /// volume/elem (meshdim) quadrature rule
    2441             :     std::unique_ptr<libMesh::QBase> vol;
    2442             :     /// area/face (meshdim-1) quadrature rule
    2443             :     std::unique_ptr<libMesh::QBase> face;
    2444             :     /// finite volume face/flux quadrature rule (meshdim-1)
    2445             :     std::unique_ptr<libMesh::QBase> fv_face;
    2446             :     /// volume/elem (meshdim) custom points quadrature rule
    2447             :     std::unique_ptr<ArbitraryQuadrature> arbitrary_vol;
    2448             :     /// area/face (meshdim-1) custom points quadrature rule
    2449             :     std::unique_ptr<ArbitraryQuadrature> arbitrary_face;
    2450             :     /// area/face (meshdim-1) custom points quadrature rule for DG
    2451             :     std::unique_ptr<ArbitraryQuadrature> neighbor;
    2452             :   };
    2453             : 
    2454             :   /// Holds quadrature rules for each dimension.  These are created up front
    2455             :   /// at the start of the simulation and reused/referenced for the remainder of
    2456             :   /// the sim.  This data structure should generally be read/accessed via the
    2457             :   /// qrules() function.
    2458             :   std::unordered_map<SubdomainID, std::vector<QRules>> _qrules;
    2459             : 
    2460             :   /// This is an abstraction over the internal qrules function.  This is
    2461             :   /// necessary for faces because (nodes of) faces can exists in more than one
    2462             :   /// subdomain.  When this is the case, we need to use the quadrature rule from
    2463             :   /// the subdomain that has the highest specified quadrature order.  So when
    2464             :   /// you need to access a face quadrature rule, you should retrieve it via this
    2465             :   /// function.
    2466             :   libMesh::QBase * qruleFace(const Elem * elem, unsigned int side);
    2467             :   ArbitraryQuadrature * qruleArbitraryFace(const Elem * elem, unsigned int side);
    2468             : 
    2469             :   template <typename T>
    2470    13381802 :   T * qruleFaceHelper(const Elem * elem, unsigned int side, std::function<T *(QRules &)> rule_fn)
    2471             :   {
    2472    13381802 :     auto dim = elem->dim();
    2473    13381802 :     auto neighbor = elem->neighbor_ptr(side);
    2474    13381802 :     auto q = rule_fn(qrules(dim, elem->subdomain_id()));
    2475    13381802 :     if (!neighbor)
    2476     4716863 :       return q;
    2477             : 
    2478             :     // find the maximum face quadrature order for all blocks the face is in
    2479     8664939 :     auto neighbor_block = neighbor->subdomain_id();
    2480     8664939 :     if (neighbor_block == elem->subdomain_id())
    2481     8440802 :       return q;
    2482             : 
    2483      224137 :     auto q_neighbor = rule_fn(qrules(dim, neighbor_block));
    2484      224137 :     if (q->get_order() > q_neighbor->get_order())
    2485         377 :       return q;
    2486      223760 :     return q_neighbor;
    2487             :   }
    2488             : 
    2489   472287840 :   inline QRules & qrules(unsigned int dim) { return qrules(dim, _current_subdomain_id); }
    2490             : 
    2491             :   /// This is a helper function for accessing quadrature rules for a
    2492             :   /// particular dimensionality of element.  All access to quadrature rules in
    2493             :   /// Assembly should be done via this accessor function.
    2494   515275984 :   inline QRules & qrules(unsigned int dim, SubdomainID block)
    2495             :   {
    2496   515275984 :     if (_qrules.find(block) == _qrules.end())
    2497             :     {
    2498             :       mooseAssert(_qrules.find(Moose::ANY_BLOCK_ID) != _qrules.end(),
    2499             :                   "missing quadrature rules for specified block");
    2500             :       mooseAssert(_qrules[Moose::ANY_BLOCK_ID].size() > dim,
    2501             :                   "quadrature rules not sized property for dimension");
    2502   515274114 :       return _qrules[Moose::ANY_BLOCK_ID][dim];
    2503             :     }
    2504             :     mooseAssert(_qrules.find(block) != _qrules.end(),
    2505             :                 "missing quadrature rules for specified block");
    2506             :     mooseAssert(_qrules[block].size() > dim, "quadrature rules not sized property for dimension");
    2507        1870 :     return _qrules[block][dim];
    2508             :   }
    2509             : 
    2510             :   /**** Face Stuff ****/
    2511             : 
    2512             :   /// types of finite elements
    2513             :   mutable std::map<unsigned int, std::map<FEType, FEBase *>> _fe_face;
    2514             :   /// types of vector finite elements
    2515             :   mutable std::map<unsigned int, std::map<FEType, FEVectorBase *>> _vector_fe_face;
    2516             :   /// Each dimension's helper objects
    2517             :   std::map<unsigned int, FEBase *> _holder_fe_face_helper;
    2518             :   /// helper object for transforming coordinates
    2519             :   FEBase * _current_fe_face_helper;
    2520             :   /// quadrature rule used on faces
    2521             :   libMesh::QBase * _current_qrule_face;
    2522             :   /// The current arbitrary quadrature rule used on element faces
    2523             :   ArbitraryQuadrature * _current_qface_arbitrary;
    2524             :   /// The current quadrature points on a face
    2525             :   MooseArray<Point> _current_q_points_face;
    2526             :   /// The current transformed jacobian weights on a face
    2527             :   MooseArray<Real> _current_JxW_face;
    2528             :   /// The current Normal vectors at the quadrature points.
    2529             :   MooseArray<Point> _current_normals;
    2530             :   /// Mapped normals
    2531             :   std::vector<Eigen::Map<RealDIMValue>> _mapped_normals;
    2532             :   /// The current tangent vectors at the quadrature points
    2533             :   MooseArray<std::vector<Point>> _current_tangents;
    2534             : 
    2535             :   /// Extra element IDs
    2536             :   std::vector<dof_id_type> _extra_elem_ids;
    2537             :   /// Extra element IDs of neighbor
    2538             :   std::vector<dof_id_type> _neighbor_extra_elem_ids;
    2539             :   /// Holds pointers to the dimension's normal vectors
    2540             :   std::map<unsigned int, const std::vector<Point> *> _holder_normals;
    2541             : 
    2542             :   /**** Neighbor Stuff ****/
    2543             : 
    2544             :   /// types of finite elements
    2545             :   mutable std::map<unsigned int, std::map<FEType, FEBase *>> _fe_neighbor;
    2546             :   mutable std::map<unsigned int, std::map<FEType, FEBase *>> _fe_face_neighbor;
    2547             :   mutable std::map<unsigned int, std::map<FEType, FEVectorBase *>> _vector_fe_neighbor;
    2548             :   mutable std::map<unsigned int, std::map<FEType, FEVectorBase *>> _vector_fe_face_neighbor;
    2549             : 
    2550             :   /// Each dimension's helper objects
    2551             :   std::map<unsigned int, FEBase *> _holder_fe_neighbor_helper;
    2552             :   std::map<unsigned int, FEBase *> _holder_fe_face_neighbor_helper;
    2553             : 
    2554             :   /// FE objects for lower dimensional elements
    2555             :   mutable std::map<unsigned int, std::map<FEType, FEBase *>> _fe_lower;
    2556             :   /// Vector FE objects for lower dimensional elements
    2557             :   mutable std::map<unsigned int, std::map<FEType, FEVectorBase *>> _vector_fe_lower;
    2558             :   /// helper object for transforming coordinates for lower dimensional element quadrature points
    2559             :   std::map<unsigned int, FEBase *> _holder_fe_lower_helper;
    2560             : 
    2561             :   /// quadrature rule used on neighbors
    2562             :   libMesh::QBase * _current_qrule_neighbor;
    2563             :   /// The current quadrature points on the neighbor face
    2564             :   MooseArray<Point> _current_q_points_face_neighbor;
    2565             :   /// Flag to indicate that JxW_neighbor is needed
    2566             :   mutable bool _need_JxW_neighbor;
    2567             :   /// The current transformed jacobian weights on a neighbor's face
    2568             :   MooseArray<Real> _current_JxW_neighbor;
    2569             :   /// The current coordinate transformation coefficients
    2570             :   MooseArray<Real> _coord_neighbor;
    2571             :   /// The coordinate transformation coefficients evaluated on the quadrature points of the mortar
    2572             :   /// segment mesh
    2573             :   MooseArray<Real> _coord_msm;
    2574             : 
    2575             :   /********** mortar stuff *************/
    2576             : 
    2577             :   /// A JxW for working on mortar segement elements
    2578             :   const std::vector<Real> * _JxW_msm;
    2579             :   /// A FE object for working on mortar segement elements
    2580             :   std::unique_ptr<FEBase> _fe_msm;
    2581             :   /// A qrule object for working on mortar segement elements. This needs to be a
    2582             :   /// raw pointer because we need to be able to return a reference to it because
    2583             :   /// we will be constructing other objects that need the qrule before the qrule
    2584             :   /// is actually created
    2585             :   libMesh::QBase * _qrule_msm;
    2586             :   /// Flag specifying whether a custom quadrature rule has been specified for mortar segment mesh
    2587             :   bool _custom_mortar_qrule;
    2588             : 
    2589             :   /// quadrature rule used on lower dimensional elements. This should always be
    2590             :   /// the same as the face qrule
    2591             :   libMesh::QBase * _current_qrule_lower;
    2592             : 
    2593             : protected:
    2594             :   /// The current "element" we are currently on.
    2595             :   const Elem * _current_elem;
    2596             :   /// The current subdomain ID
    2597             :   SubdomainID _current_subdomain_id;
    2598             :   /// The current boundary ID
    2599             :   BoundaryID _current_boundary_id;
    2600             :   /// Volume of the current element
    2601             :   Real _current_elem_volume;
    2602             :   /// The current side of the selected element (valid only when working with sides)
    2603             :   unsigned int _current_side;
    2604             :   /// The current "element" making up the side we are currently on.
    2605             :   const Elem * _current_side_elem;
    2606             :   /// Volume of the current side element
    2607             :   Real _current_side_volume;
    2608             :   /// The current neighbor "element"
    2609             :   const Elem * _current_neighbor_elem;
    2610             :   /// The current neighbor subdomain ID
    2611             :   SubdomainID _current_neighbor_subdomain_id;
    2612             :   /// The current side of the selected neighboring element (valid only when working with sides)
    2613             :   unsigned int _current_neighbor_side;
    2614             :   /// The current side element of the ncurrent neighbor element
    2615             :   const Elem * _current_neighbor_side_elem;
    2616             :   /// true is apps need to compute neighbor element volume
    2617             :   mutable bool _need_neighbor_elem_volume;
    2618             :   /// Volume of the current neighbor
    2619             :   Real _current_neighbor_volume;
    2620             :   /// The current node we are working with
    2621             :   const Node * _current_node;
    2622             :   /// The current neighboring node we are working with
    2623             :   const Node * _current_neighbor_node;
    2624             :   /// Boolean to indicate whether current element volumes has been computed
    2625             :   bool _current_elem_volume_computed;
    2626             :   /// Boolean to indicate whether current element side volumes has been computed
    2627             :   bool _current_side_volume_computed;
    2628             : 
    2629             :   /// The current lower dimensional element
    2630             :   const Elem * _current_lower_d_elem;
    2631             :   /// The current neighboring lower dimensional element
    2632             :   const Elem * _current_neighbor_lower_d_elem;
    2633             :   /// Whether we need to compute the lower dimensional element volume
    2634             :   mutable bool _need_lower_d_elem_volume;
    2635             :   /// The current lower dimensional element volume
    2636             :   Real _current_lower_d_elem_volume;
    2637             :   /// Whether we need to compute the neighboring lower dimensional element volume
    2638             :   mutable bool _need_neighbor_lower_d_elem_volume;
    2639             :   /// The current neighboring lower dimensional element volume
    2640             :   Real _current_neighbor_lower_d_elem_volume;
    2641             :   /// Whether dual shape functions need to be computed for mortar constraints
    2642             :   bool _need_dual;
    2643             : 
    2644             :   /// This will be filled up with the physical points passed into reinitAtPhysical() if it is called.  Invalid at all other times.
    2645             :   MooseArray<Point> _current_physical_points;
    2646             : 
    2647             :   /*
    2648             :    * Residual contributions <tag_index, ivar>
    2649             :    *
    2650             :    * tag_index is the index into _residual_vector_tags, that is, _sub_Re[0] corresponds to the tag
    2651             :    * with TagID _residual_vector_tags[0]._id
    2652             :    *
    2653             :    * When ivar corresponds to an array variable, the dense vector is in size of ndof * count,
    2654             :    * where count is the number of components of the array variable. The local residual is ordered
    2655             :    * as (r_i,j, i = 1,...,ndof; j = 1,...,count).
    2656             :    *
    2657             :    * Dense vectors for variables (ivar+i, i = 1,...,count) are empty.
    2658             :    */
    2659             :   std::vector<std::vector<DenseVector<Number>>> _sub_Re;
    2660             :   std::vector<std::vector<DenseVector<Number>>> _sub_Rn;
    2661             :   /// residual contributions for each variable from the lower dimensional element
    2662             :   std::vector<std::vector<DenseVector<Number>>> _sub_Rl;
    2663             : 
    2664             :   /// auxiliary vector for scaling residuals (optimization to avoid expensive construction/destruction)
    2665             :   DenseVector<Number> _tmp_Re;
    2666             : 
    2667             :   /*
    2668             :    * Jacobian contributions <Tag, ivar, jvar>
    2669             :    * When ivar corresponds to an array variable, the number of rows of the dense matrix is in size
    2670             :    * of indof * icount, where icount is the number of components of ivar. When jvar corresponds to
    2671             :    * an array variable, the number of columns of the dense matrix is in size of jndof * jcount,
    2672             :    * where jcount is the number of components of jvar. The local residual is ordered as
    2673             :    * (K_(i,j,k,l), k=1,...,jndof; l = 1,...,jcout; i = 1,...,indof; j = 1,...,icount).
    2674             :    *
    2675             :    * Dense matrices for variables (ivar+i, i = 1,...,icount) or (jvar+j, j = 1,...,jcount) are
    2676             :    * empty.
    2677             :    */
    2678             :   std::vector<std::vector<std::vector<DenseMatrix<Number>>>> _sub_Kee;
    2679             :   std::vector<std::vector<std::vector<DenseMatrix<Number>>>> _sub_Keg;
    2680             : 
    2681             :   /// jacobian contributions from the element and neighbor <Tag, ivar, jvar>
    2682             :   std::vector<std::vector<std::vector<DenseMatrix<Number>>>> _sub_Ken;
    2683             :   /// jacobian contributions from the neighbor and element <Tag, ivar, jvar>
    2684             :   std::vector<std::vector<std::vector<DenseMatrix<Number>>>> _sub_Kne;
    2685             :   /// jacobian contributions from the neighbor <Tag, ivar, jvar>
    2686             :   std::vector<std::vector<std::vector<DenseMatrix<Number>>>> _sub_Knn;
    2687             :   /// dlower/dlower
    2688             :   std::vector<std::vector<std::vector<DenseMatrix<Number>>>> _sub_Kll;
    2689             :   /// dlower/dsecondary (or dlower/delement)
    2690             :   std::vector<std::vector<std::vector<DenseMatrix<Number>>>> _sub_Kle;
    2691             :   /// dlower/dprimary (or dlower/dneighbor)
    2692             :   std::vector<std::vector<std::vector<DenseMatrix<Number>>>> _sub_Kln;
    2693             :   /// dsecondary/dlower (or delement/dlower)
    2694             :   std::vector<std::vector<std::vector<DenseMatrix<Number>>>> _sub_Kel;
    2695             :   /// dprimary/dlower (or dneighbor/dlower)
    2696             :   std::vector<std::vector<std::vector<DenseMatrix<Number>>>> _sub_Knl;
    2697             : 
    2698             :   /// auxiliary matrix for scaling jacobians (optimization to avoid expensive construction/destruction)
    2699             :   DenseMatrix<Number> _tmp_Ke;
    2700             : 
    2701             :   // Shape function values, gradients. second derivatives
    2702             :   VariablePhiValue _phi;
    2703             :   VariablePhiGradient _grad_phi;
    2704             :   VariablePhiSecond _second_phi;
    2705             : 
    2706             :   VariablePhiValue _phi_face;
    2707             :   VariablePhiGradient _grad_phi_face;
    2708             :   VariablePhiSecond _second_phi_face;
    2709             : 
    2710             :   VariablePhiValue _phi_neighbor;
    2711             :   VariablePhiGradient _grad_phi_neighbor;
    2712             :   VariablePhiSecond _second_phi_neighbor;
    2713             : 
    2714             :   VariablePhiValue _phi_face_neighbor;
    2715             :   VariablePhiGradient _grad_phi_face_neighbor;
    2716             :   VariablePhiSecond _second_phi_face_neighbor;
    2717             : 
    2718             :   // Shape function values, gradients, second derivatives
    2719             :   VectorVariablePhiValue _vector_phi;
    2720             :   VectorVariablePhiGradient _vector_grad_phi;
    2721             :   VectorVariablePhiSecond _vector_second_phi;
    2722             :   VectorVariablePhiCurl _vector_curl_phi;
    2723             :   VectorVariablePhiDivergence _vector_div_phi;
    2724             : 
    2725             :   VectorVariablePhiValue _vector_phi_face;
    2726             :   VectorVariablePhiGradient _vector_grad_phi_face;
    2727             :   VectorVariablePhiSecond _vector_second_phi_face;
    2728             :   VectorVariablePhiCurl _vector_curl_phi_face;
    2729             :   VectorVariablePhiDivergence _vector_div_phi_face;
    2730             : 
    2731             :   VectorVariablePhiValue _vector_phi_neighbor;
    2732             :   VectorVariablePhiGradient _vector_grad_phi_neighbor;
    2733             :   VectorVariablePhiSecond _vector_second_phi_neighbor;
    2734             :   VectorVariablePhiCurl _vector_curl_phi_neighbor;
    2735             :   VectorVariablePhiDivergence _vector_div_phi_neighbor;
    2736             : 
    2737             :   VectorVariablePhiValue _vector_phi_face_neighbor;
    2738             :   VectorVariablePhiGradient _vector_grad_phi_face_neighbor;
    2739             :   VectorVariablePhiSecond _vector_second_phi_face_neighbor;
    2740             :   VectorVariablePhiCurl _vector_curl_phi_face_neighbor;
    2741             :   VectorVariablePhiDivergence _vector_div_phi_face_neighbor;
    2742             : 
    2743             :   class FEShapeData
    2744             :   {
    2745             :   public:
    2746             :     VariablePhiValue _phi;
    2747             :     VariablePhiGradient _grad_phi;
    2748             :     VariablePhiSecond _second_phi;
    2749             :     VariablePhiCurl _curl_phi;
    2750             :     VariablePhiDivergence _div_phi;
    2751             :   };
    2752             : 
    2753             :   class VectorFEShapeData
    2754             :   {
    2755             :   public:
    2756             :     VectorVariablePhiValue _phi;
    2757             :     VectorVariablePhiGradient _grad_phi;
    2758             :     VectorVariablePhiSecond _second_phi;
    2759             :     VectorVariablePhiCurl _curl_phi;
    2760             :     VectorVariablePhiDivergence _div_phi;
    2761             :   };
    2762             : 
    2763             :   /// Shape function values, gradients, second derivatives for each FE type
    2764             :   mutable std::map<FEType, std::unique_ptr<FEShapeData>> _fe_shape_data;
    2765             :   mutable std::map<FEType, std::unique_ptr<FEShapeData>> _fe_shape_data_face;
    2766             :   mutable std::map<FEType, std::unique_ptr<FEShapeData>> _fe_shape_data_neighbor;
    2767             :   mutable std::map<FEType, std::unique_ptr<FEShapeData>> _fe_shape_data_face_neighbor;
    2768             :   mutable std::map<FEType, std::unique_ptr<FEShapeData>> _fe_shape_data_lower;
    2769             :   mutable std::map<FEType, std::unique_ptr<FEShapeData>> _fe_shape_data_dual_lower;
    2770             : 
    2771             :   /// Shape function values, gradients, second derivatives for each vector FE type
    2772             :   mutable std::map<FEType, std::unique_ptr<VectorFEShapeData>> _vector_fe_shape_data;
    2773             :   mutable std::map<FEType, std::unique_ptr<VectorFEShapeData>> _vector_fe_shape_data_face;
    2774             :   mutable std::map<FEType, std::unique_ptr<VectorFEShapeData>> _vector_fe_shape_data_neighbor;
    2775             :   mutable std::map<FEType, std::unique_ptr<VectorFEShapeData>> _vector_fe_shape_data_face_neighbor;
    2776             :   mutable std::map<FEType, std::unique_ptr<VectorFEShapeData>> _vector_fe_shape_data_lower;
    2777             :   mutable std::map<FEType, std::unique_ptr<VectorFEShapeData>> _vector_fe_shape_data_dual_lower;
    2778             : 
    2779             :   mutable std::map<FEType, ADTemplateVariablePhiGradient<Real>> _ad_grad_phi_data;
    2780             :   mutable std::map<FEType, ADTemplateVariablePhiGradient<RealVectorValue>> _ad_vector_grad_phi_data;
    2781             :   mutable std::map<FEType, ADTemplateVariablePhiGradient<Real>> _ad_grad_phi_data_face;
    2782             :   mutable std::map<FEType, ADTemplateVariablePhiGradient<RealVectorValue>>
    2783             :       _ad_vector_grad_phi_data_face;
    2784             : 
    2785             :   /**
    2786             :    * The residual vector tags that Assembly could possibly contribute to.
    2787             :    *
    2788             :    * The following variables are all indexed with this vector (i.e., index 0 in the following
    2789             :    * vectors corresponds to the tag with TagID _residual_vector_tags[0]._id):
    2790             :    * _sub_Re, _sub_Rn, _sub_Rl, _cached_residual_rows, _cached_residual_values,
    2791             :    *
    2792             :    * This index is also available in VectorTag::_type_id
    2793             :    */
    2794             :   const std::vector<VectorTag> & _residual_vector_tags;
    2795             : 
    2796             :   /// Values cached by calling cacheResidual() (the first vector is for TIME vs NONTIME)
    2797             :   std::vector<std::vector<Real>> _cached_residual_values;
    2798             : 
    2799             :   /// Where the cached values should go (the first vector is for TIME vs NONTIME)
    2800             :   std::vector<std::vector<dof_id_type>> _cached_residual_rows;
    2801             : 
    2802             :   unsigned int _max_cached_residuals;
    2803             : 
    2804             :   /// Values cached by calling cacheJacobian()
    2805             :   std::vector<std::vector<Real>> _cached_jacobian_values;
    2806             :   /// Row where the corresponding cached value should go
    2807             :   std::vector<std::vector<dof_id_type>> _cached_jacobian_rows;
    2808             :   /// Column where the corresponding cached value should go
    2809             :   std::vector<std::vector<dof_id_type>> _cached_jacobian_cols;
    2810             : 
    2811             :   unsigned int _max_cached_jacobians;
    2812             : 
    2813             :   /// Will be true if our preconditioning matrix is a block-diagonal matrix.  Which means that we can take some shortcuts.
    2814             :   bool _block_diagonal_matrix;
    2815             :   /// An flag array Indiced by variable index to show if there is no component-wise
    2816             :   /// coupling for the variable.
    2817             :   std::vector<bool> _component_block_diagonal;
    2818             : 
    2819             :   /// Temporary work vector to keep from reallocating it
    2820             :   std::vector<dof_id_type> _temp_dof_indices;
    2821             : 
    2822             :   /// Temporary work data for reinitAtPhysical()
    2823             :   std::vector<Point> _temp_reference_points;
    2824             : 
    2825             :   /// AD quantities
    2826             :   std::vector<VectorValue<ADReal>> _ad_dxyzdxi_map;
    2827             :   std::vector<VectorValue<ADReal>> _ad_dxyzdeta_map;
    2828             :   std::vector<VectorValue<ADReal>> _ad_dxyzdzeta_map;
    2829             :   std::vector<VectorValue<ADReal>> _ad_d2xyzdxi2_map;
    2830             :   std::vector<VectorValue<ADReal>> _ad_d2xyzdxideta_map;
    2831             :   std::vector<VectorValue<ADReal>> _ad_d2xyzdeta2_map;
    2832             :   std::vector<ADReal> _ad_jac;
    2833             :   MooseArray<ADReal> _ad_JxW;
    2834             :   MooseArray<VectorValue<ADReal>> _ad_q_points;
    2835             :   std::vector<ADReal> _ad_dxidx_map;
    2836             :   std::vector<ADReal> _ad_dxidy_map;
    2837             :   std::vector<ADReal> _ad_dxidz_map;
    2838             :   std::vector<ADReal> _ad_detadx_map;
    2839             :   std::vector<ADReal> _ad_detady_map;
    2840             :   std::vector<ADReal> _ad_detadz_map;
    2841             :   std::vector<ADReal> _ad_dzetadx_map;
    2842             :   std::vector<ADReal> _ad_dzetady_map;
    2843             :   std::vector<ADReal> _ad_dzetadz_map;
    2844             : 
    2845             :   MooseArray<ADReal> _ad_JxW_face;
    2846             :   MooseArray<VectorValue<ADReal>> _ad_normals;
    2847             :   MooseArray<VectorValue<ADReal>> _ad_q_points_face;
    2848             :   MooseArray<Real> _curvatures;
    2849             :   MooseArray<ADReal> _ad_curvatures;
    2850             : 
    2851             :   /**
    2852             :    * Container of displacement numbers and directions
    2853             :    */
    2854             :   std::vector<std::pair<unsigned int, unsigned short>> _disp_numbers_and_directions;
    2855             : 
    2856             :   mutable bool _calculate_xyz;
    2857             :   mutable bool _calculate_face_xyz;
    2858             :   mutable bool _calculate_curvatures;
    2859             : 
    2860             :   /// Whether to calculate coord with AD. This will only be set to \p true if a consumer calls
    2861             :   /// adCoordTransformation()
    2862             :   mutable bool _calculate_ad_coord;
    2863             : 
    2864             :   mutable std::set<FEType> _need_second_derivative;
    2865             :   mutable std::set<FEType> _need_second_derivative_neighbor;
    2866             :   mutable std::set<FEType> _need_curl;
    2867             :   mutable std::set<FEType> _need_div;
    2868             :   mutable std::set<FEType> _need_face_div;
    2869             :   mutable std::set<FEType> _need_neighbor_div;
    2870             :   mutable std::set<FEType> _need_face_neighbor_div;
    2871             : 
    2872             :   /// The map from global index to variable scaling factor
    2873             :   const NumericVector<Real> * _scaling_vector = nullptr;
    2874             : 
    2875             :   /// In place side element builder for _current_side_elem
    2876             :   libMesh::ElemSideBuilder _current_side_elem_builder;
    2877             :   /// In place side element builder for _current_neighbor_side_elem
    2878             :   libMesh::ElemSideBuilder _current_neighbor_side_elem_builder;
    2879             :   /// In place side element builder for computeFaceMap()
    2880             :   libMesh::ElemSideBuilder _compute_face_map_side_elem_builder;
    2881             : 
    2882             :   const Elem * _msm_elem = nullptr;
    2883             : 
    2884             :   /// A working vector to avoid repeated heap allocations when caching residuals that must have
    2885             :   /// libMesh-level constraints (hanging nodes, periodic bcs) applied to them. This stores local
    2886             :   /// residual values
    2887             :   DenseVector<Number> _element_vector;
    2888             : 
    2889             :   /// A working matrix to avoid repeated heap allocations when caching Jacobians that must have
    2890             :   /// libMesh-level constraints (hanging nodes, periodic bcs) applied to them. This stores local
    2891             :   /// Jacobian values
    2892             :   DenseMatrix<Number> _element_matrix;
    2893             : 
    2894             :   /// Working vectors to avoid repeated heap allocations when caching residuals/Jacobians that must
    2895             :   /// have libMesh-level constraints (hanging nodes, periodic bcs) applied to them. These are for
    2896             :   /// storing the dof indices
    2897             :   std::vector<dof_id_type> _row_indices, _column_indices;
    2898             : 
    2899             :   /// Whether we have ever conducted p-refinement
    2900             :   bool _have_p_refinement;
    2901             : 
    2902             :   /// The current reference points on the neighbor element
    2903             :   std::vector<Point> _current_neighbor_ref_points;
    2904             : };
    2905             : 
    2906             : template <typename OutputType>
    2907             : const typename OutputTools<OutputType>::VariablePhiValue &
    2908      357640 : Assembly::fePhiLower(FEType type) const
    2909             : {
    2910      357640 :   buildLowerDFE(type);
    2911      357640 :   return _fe_shape_data_lower[type]->_phi;
    2912             : }
    2913             : 
    2914             : template <typename OutputType>
    2915             : const typename OutputTools<OutputType>::VariablePhiValue &
    2916         292 : Assembly::feDualPhiLower(FEType type) const
    2917             : {
    2918         292 :   buildLowerDDualFE(type);
    2919         292 :   return _fe_shape_data_dual_lower[type]->_phi;
    2920             : }
    2921             : 
    2922             : template <typename OutputType>
    2923             : const typename OutputTools<OutputType>::VariablePhiGradient &
    2924      357640 : Assembly::feGradPhiLower(FEType type) const
    2925             : {
    2926      357640 :   buildLowerDFE(type);
    2927      357640 :   return _fe_shape_data_lower[type]->_grad_phi;
    2928             : }
    2929             : 
    2930             : template <typename OutputType>
    2931             : const typename OutputTools<OutputType>::VariablePhiGradient &
    2932         292 : Assembly::feGradDualPhiLower(FEType type) const
    2933             : {
    2934         292 :   buildLowerDDualFE(type);
    2935         292 :   return _fe_shape_data_dual_lower[type]->_grad_phi;
    2936             : }
    2937             : 
    2938             : template <>
    2939             : inline const ADTemplateVariablePhiGradient<RealVectorValue> &
    2940        1666 : Assembly::feADGradPhi<RealVectorValue>(FEType type) const
    2941             : {
    2942        1666 :   return _ad_vector_grad_phi_data[type];
    2943             : }
    2944             : 
    2945             : template <>
    2946             : inline const ADTemplateVariablePhiGradient<RealVectorValue> &
    2947        1666 : Assembly::feADGradPhiFace<RealVectorValue>(FEType type) const
    2948             : {
    2949        1666 :   return _ad_vector_grad_phi_data_face[type];
    2950             : }
    2951             : 
    2952             : template <>
    2953             : const typename OutputTools<VectorValue<Real>>::VariablePhiValue &
    2954             : Assembly::fePhi<VectorValue<Real>>(FEType type) const;
    2955             : 
    2956             : template <>
    2957             : const typename OutputTools<VectorValue<Real>>::VariablePhiGradient &
    2958             : Assembly::feGradPhi<VectorValue<Real>>(FEType type) const;
    2959             : 
    2960             : template <>
    2961             : const typename OutputTools<VectorValue<Real>>::VariablePhiSecond &
    2962             : Assembly::feSecondPhi<VectorValue<Real>>(FEType type) const;
    2963             : 
    2964             : template <>
    2965             : const typename OutputTools<VectorValue<Real>>::VariablePhiValue &
    2966             : Assembly::fePhiLower<VectorValue<Real>>(FEType type) const;
    2967             : 
    2968             : template <>
    2969             : const typename OutputTools<VectorValue<Real>>::VariablePhiValue &
    2970             : Assembly::feDualPhiLower<VectorValue<Real>>(FEType type) const;
    2971             : 
    2972             : template <>
    2973             : const typename OutputTools<VectorValue<Real>>::VariablePhiGradient &
    2974             : Assembly::feGradPhiLower<VectorValue<Real>>(FEType type) const;
    2975             : 
    2976             : template <>
    2977             : const typename OutputTools<VectorValue<Real>>::VariablePhiGradient &
    2978             : Assembly::feGradDualPhiLower<VectorValue<Real>>(FEType type) const;
    2979             : 
    2980             : template <>
    2981             : const typename OutputTools<VectorValue<Real>>::VariablePhiValue &
    2982             : Assembly::fePhiFace<VectorValue<Real>>(FEType type) const;
    2983             : 
    2984             : template <>
    2985             : const typename OutputTools<VectorValue<Real>>::VariablePhiGradient &
    2986             : Assembly::feGradPhiFace<VectorValue<Real>>(FEType type) const;
    2987             : 
    2988             : template <>
    2989             : const typename OutputTools<VectorValue<Real>>::VariablePhiSecond &
    2990             : Assembly::feSecondPhiFace<VectorValue<Real>>(FEType type) const;
    2991             : 
    2992             : template <>
    2993             : const typename OutputTools<VectorValue<Real>>::VariablePhiValue &
    2994             : Assembly::fePhiNeighbor<VectorValue<Real>>(FEType type) const;
    2995             : 
    2996             : template <>
    2997             : const typename OutputTools<VectorValue<Real>>::VariablePhiGradient &
    2998             : Assembly::feGradPhiNeighbor<VectorValue<Real>>(FEType type) const;
    2999             : 
    3000             : template <>
    3001             : const typename OutputTools<VectorValue<Real>>::VariablePhiSecond &
    3002             : Assembly::feSecondPhiNeighbor<VectorValue<Real>>(FEType type) const;
    3003             : 
    3004             : template <>
    3005             : const typename OutputTools<VectorValue<Real>>::VariablePhiValue &
    3006             : Assembly::fePhiFaceNeighbor<VectorValue<Real>>(FEType type) const;
    3007             : 
    3008             : template <>
    3009             : const typename OutputTools<VectorValue<Real>>::VariablePhiGradient &
    3010             : Assembly::feGradPhiFaceNeighbor<VectorValue<Real>>(FEType type) const;
    3011             : 
    3012             : template <>
    3013             : const typename OutputTools<VectorValue<Real>>::VariablePhiSecond &
    3014             : Assembly::feSecondPhiFaceNeighbor<VectorValue<Real>>(FEType type) const;
    3015             : 
    3016             : template <>
    3017             : const typename OutputTools<VectorValue<Real>>::VariablePhiCurl &
    3018             : Assembly::feCurlPhi<VectorValue<Real>>(FEType type) const;
    3019             : 
    3020             : template <>
    3021             : const typename OutputTools<VectorValue<Real>>::VariablePhiCurl &
    3022             : Assembly::feCurlPhiFace<VectorValue<Real>>(FEType type) const;
    3023             : 
    3024             : template <>
    3025             : const typename OutputTools<VectorValue<Real>>::VariablePhiCurl &
    3026             : Assembly::feCurlPhiNeighbor<VectorValue<Real>>(FEType type) const;
    3027             : 
    3028             : template <>
    3029             : const typename OutputTools<VectorValue<Real>>::VariablePhiCurl &
    3030             : Assembly::feCurlPhiFaceNeighbor<VectorValue<Real>>(FEType type) const;
    3031             : 
    3032             : template <>
    3033             : const typename OutputTools<VectorValue<Real>>::VariablePhiDivergence &
    3034             : Assembly::feDivPhi<VectorValue<Real>>(FEType type) const;
    3035             : 
    3036             : template <>
    3037             : const typename OutputTools<VectorValue<Real>>::VariablePhiDivergence &
    3038             : Assembly::feDivPhiFace<VectorValue<Real>>(FEType type) const;
    3039             : 
    3040             : template <>
    3041             : const typename OutputTools<VectorValue<Real>>::VariablePhiDivergence &
    3042             : Assembly::feDivPhiNeighbor<VectorValue<Real>>(FEType type) const;
    3043             : 
    3044             : template <>
    3045             : const typename OutputTools<VectorValue<Real>>::VariablePhiDivergence &
    3046             : Assembly::feDivPhiFaceNeighbor<VectorValue<Real>>(FEType type) const;
    3047             : 
    3048             : template <>
    3049             : inline const ADTemplateVariablePhiGradient<RealVectorValue> &
    3050         217 : Assembly::adGradPhi<RealVectorValue>(const MooseVariableFE<RealVectorValue> & v) const
    3051             : {
    3052         217 :   return _ad_vector_grad_phi_data.at(v.feType());
    3053             : }
    3054             : 
    3055             : template <typename Residuals, typename Indices>
    3056             : void
    3057    43511392 : Assembly::cacheResiduals(const Residuals & residuals,
    3058             :                          const Indices & input_row_indices,
    3059             :                          const Real scaling_factor,
    3060             :                          LocalDataKey,
    3061             :                          const std::set<TagID> & vector_tags)
    3062             : {
    3063             :   mooseAssert(residuals.size() == input_row_indices.size(),
    3064             :               "The number of residuals should match the number of dof indices");
    3065             :   mooseAssert(residuals.size() >= 1, "Why you calling me with no residuals?");
    3066             : 
    3067    43511392 :   if (!computingResidual() || vector_tags.empty())
    3068    14623877 :     return;
    3069             : 
    3070    28887515 :   if (residuals.size() == 1)
    3071             :   {
    3072             :     // No constraining is required. (This is likely a finite volume computation if we only have a
    3073             :     // single dof)
    3074     3699119 :     cacheResidualsWithoutConstraints(
    3075     3699119 :         residuals, input_row_indices, scaling_factor, LocalDataKey{}, vector_tags);
    3076     3699119 :     return;
    3077             :   }
    3078             : 
    3079             :   // Need to make a copy because we might modify this in constrain_element_vector
    3080    25188396 :   _row_indices.assign(input_row_indices.begin(), input_row_indices.end());
    3081             : 
    3082    25188396 :   _element_vector.resize(_row_indices.size());
    3083   145082577 :   for (const auto i : index_range(_row_indices))
    3084   119894181 :     _element_vector(i) = MetaPhysicL::raw_value(residuals[i]) * scaling_factor;
    3085             : 
    3086             :   // At time of writing, this method doesn't do anything with the asymmetric_constraint_rows
    3087             :   // argument, but we set it to false to be consistent with processLocalResidual
    3088    25188396 :   _dof_map.constrain_element_vector(
    3089    25188396 :       _element_vector, _row_indices, /*asymmetric_constraint_rows=*/false);
    3090             : 
    3091   145087137 :   for (const auto i : index_range(_row_indices))
    3092   119898741 :     cacheResidual(_row_indices[i], _element_vector(i), vector_tags);
    3093             : }
    3094             : 
    3095             : template <typename Residuals, typename Indices>
    3096             : void
    3097     3874438 : Assembly::cacheResidualsWithoutConstraints(const Residuals & residuals,
    3098             :                                            const Indices & row_indices,
    3099             :                                            const Real scaling_factor,
    3100             :                                            LocalDataKey,
    3101             :                                            const std::set<TagID> & vector_tags)
    3102             : {
    3103             :   mooseAssert(residuals.size() == row_indices.size(),
    3104             :               "The number of residuals should match the number of dof indices");
    3105             :   mooseAssert(residuals.size() >= 1, "Why you calling me with no residuals?");
    3106             : 
    3107     3874438 :   if (computingResidual() && !vector_tags.empty())
    3108     7437934 :     for (const auto i : index_range(row_indices))
    3109     3728891 :       cacheResidual(
    3110     3728891 :           row_indices[i], MetaPhysicL::raw_value(residuals[i]) * scaling_factor, vector_tags);
    3111     3874438 : }
    3112             : 
    3113             : template <typename Residuals, typename Indices>
    3114             : void
    3115    25776217 : Assembly::cacheJacobian(const Residuals & residuals,
    3116             :                         const Indices & input_row_indices,
    3117             :                         const Real scaling_factor,
    3118             :                         LocalDataKey,
    3119             :                         const std::set<TagID> & matrix_tags)
    3120             : {
    3121    25776217 :   if (!computingJacobian() || matrix_tags.empty())
    3122           0 :     return;
    3123             : 
    3124    25776217 :   if (residuals.size() == 1)
    3125             :   {
    3126             :     // No constraining is required. (This is likely a finite volume computation if we only have a
    3127             :     // single dof)
    3128    20170910 :     cacheJacobianWithoutConstraints(
    3129    20170910 :         residuals, input_row_indices, scaling_factor, LocalDataKey{}, matrix_tags);
    3130    20170910 :     return;
    3131             :   }
    3132             : 
    3133     5605307 :   const auto & compare_dofs = residuals[0].derivatives().nude_indices();
    3134             : #ifndef NDEBUG
    3135             :   auto compare_dofs_set = std::set<dof_id_type>(compare_dofs.begin(), compare_dofs.end());
    3136             : 
    3137             :   for (const auto i : make_range(decltype(residuals.size())(1), residuals.size()))
    3138             :   {
    3139             :     const auto & residual = residuals[i];
    3140             :     auto current_dofs_set = std::set<dof_id_type>(residual.derivatives().nude_indices().begin(),
    3141             :                                                   residual.derivatives().nude_indices().end());
    3142             :     mooseAssert(compare_dofs_set == current_dofs_set,
    3143             :                 "We're going to see whether the dof sets are the same. IIRC the degree of freedom "
    3144             :                 "dependence (as indicated by the dof index set held by the ADReal) has to be the "
    3145             :                 "same for every residual passed to this method otherwise constrain_element_matrix "
    3146             :                 "will not work.");
    3147             :   }
    3148             : #endif
    3149     5605307 :   _column_indices.assign(compare_dofs.begin(), compare_dofs.end());
    3150             : 
    3151             :   // If there's no derivatives then there is nothing to do. Moreover, if we pass zero size column
    3152             :   // indices to constrain_element_matrix then we will potentially get errors out of BLAS
    3153     5605307 :   if (!_column_indices.size())
    3154      540444 :     return;
    3155             : 
    3156             :   // Need to make a copy because we might modify this in constrain_element_matrix
    3157     5064863 :   _row_indices.assign(input_row_indices.begin(), input_row_indices.end());
    3158             : 
    3159     5064863 :   _element_matrix.resize(_row_indices.size(), _column_indices.size());
    3160    29073898 :   for (const auto i : index_range(_row_indices))
    3161             :   {
    3162    24009035 :     const auto & sparse_derivatives = residuals[i].derivatives();
    3163             : 
    3164   197236306 :     for (const auto j : index_range(_column_indices))
    3165   173227271 :       _element_matrix(i, j) = sparse_derivatives[_column_indices[j]] * scaling_factor;
    3166             :   }
    3167             : 
    3168     5064863 :   _dof_map.constrain_element_matrix(_element_matrix, _row_indices, _column_indices);
    3169             : 
    3170    29075136 :   for (const auto i : index_range(_row_indices))
    3171   197255166 :     for (const auto j : index_range(_column_indices))
    3172   173244893 :       cacheJacobian(_row_indices[i], _column_indices[j], _element_matrix(i, j), {}, matrix_tags);
    3173             : }
    3174             : 
    3175             : template <typename Residuals, typename Indices>
    3176             : void
    3177    20346013 : Assembly::cacheJacobianWithoutConstraints(const Residuals & residuals,
    3178             :                                           const Indices & row_indices,
    3179             :                                           const Real scaling_factor,
    3180             :                                           LocalDataKey,
    3181             :                                           const std::set<TagID> & matrix_tags)
    3182             : {
    3183             :   mooseAssert(residuals.size() == row_indices.size(),
    3184             :               "The number of residuals should match the number of dof indices");
    3185             :   mooseAssert(residuals.size() >= 1, "Why you calling me with no residuals?");
    3186             : 
    3187    20346013 :   if (!computingJacobian() || matrix_tags.empty())
    3188           0 :     return;
    3189             : 
    3190    42292617 :   for (const auto i : index_range(row_indices))
    3191             :   {
    3192    21946604 :     const auto row_index = row_indices[i];
    3193             : 
    3194    21946604 :     const auto & sparse_derivatives = residuals[i].derivatives();
    3195    21946604 :     const auto & column_indices = sparse_derivatives.nude_indices();
    3196    21946604 :     const auto & raw_derivatives = sparse_derivatives.nude_data();
    3197             : 
    3198    92112770 :     for (std::size_t j = 0; j < column_indices.size(); ++j)
    3199   140332332 :       cacheJacobian(
    3200    70166166 :           row_index, column_indices[j], raw_derivatives[j] * scaling_factor, {}, matrix_tags);
    3201             :   }
    3202             : }
    3203             : 
    3204             : inline const Real &
    3205         454 : Assembly::lowerDElemVolume() const
    3206             : {
    3207         454 :   _need_lower_d_elem_volume = true;
    3208         454 :   return _current_lower_d_elem_volume;
    3209             : }
    3210             : 
    3211             : inline const Real &
    3212         426 : Assembly::neighborLowerDElemVolume() const
    3213             : {
    3214         426 :   _need_neighbor_lower_d_elem_volume = true;
    3215         426 :   return _current_neighbor_lower_d_elem_volume;
    3216             : }
    3217             : 
    3218             : inline void
    3219        2446 : Assembly::assignDisplacements(
    3220             :     std::vector<std::pair<unsigned int, unsigned short>> && disp_numbers_and_directions)
    3221             : {
    3222        2446 :   _disp_numbers_and_directions = std::move(disp_numbers_and_directions);
    3223        2446 : }
    3224             : 
    3225             : inline void
    3226      157505 : Assembly::setCurrentLowerDElem(const Elem * const lower_d_elem)
    3227             : {
    3228      157505 :   _current_lower_d_elem = lower_d_elem;
    3229      157505 : }

Generated by: LCOV version 1.14