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

Generated by: LCOV version 1.14