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

Generated by: LCOV version 1.14