LCOV - code coverage report
Current view: top level - include/problems - SubProblem.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 8601ad Lines: 121 133 91.0 %
Date: 2025-07-18 13:27:08 Functions: 89 100 89.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : #include "Problem.h"
      13             : #include "DiracKernelInfo.h"
      14             : #include "GeometricSearchData.h"
      15             : #include "MooseTypes.h"
      16             : #include "VectorTag.h"
      17             : #include "MooseError.h"
      18             : #include "FunctorMaterialProperty.h"
      19             : #include "RawValueFunctor.h"
      20             : #include "ADWrapperFunctor.h"
      21             : 
      22             : #include "libmesh/coupling_matrix.h"
      23             : #include "libmesh/parameters.h"
      24             : 
      25             : #include <memory>
      26             : #include <unordered_map>
      27             : #include <map>
      28             : #include <vector>
      29             : 
      30             : namespace libMesh
      31             : {
      32             : template <typename>
      33             : class VectorValue;
      34             : typedef VectorValue<Real> RealVectorValue;
      35             : class GhostingFunctor;
      36             : }
      37             : 
      38             : class MooseMesh;
      39             : class Factory;
      40             : class Assembly;
      41             : class MooseVariableFieldBase;
      42             : class MooseVariableScalar;
      43             : template <typename>
      44             : class MooseVariableFE;
      45             : typedef MooseVariableFE<Real> MooseVariable;
      46             : typedef MooseVariableFE<RealVectorValue> VectorMooseVariable;
      47             : typedef MooseVariableFE<RealEigenVector> ArrayMooseVariable;
      48             : class RestartableDataValue;
      49             : class SystemBase;
      50             : class LineSearch;
      51             : class FaceInfo;
      52             : class MooseObjectName;
      53             : namespace Moose
      54             : {
      55             : class FunctorEnvelopeBase;
      56             : }
      57             : 
      58             : // libMesh forward declarations
      59             : namespace libMesh
      60             : {
      61             : class EquationSystems;
      62             : class DofMap;
      63             : class CouplingMatrix;
      64             : template <typename T>
      65             : class SparseMatrix;
      66             : template <typename T>
      67             : class NumericVector;
      68             : class System;
      69             : } // namespace libMesh
      70             : 
      71             : using libMesh::CouplingMatrix;
      72             : using libMesh::EquationSystems;
      73             : 
      74             : /**
      75             :  * Generic class for solving transient nonlinear problems
      76             :  *
      77             :  */
      78             : class SubProblem : public Problem
      79             : {
      80             : public:
      81             :   static InputParameters validParams();
      82             : 
      83             :   SubProblem(const InputParameters & parameters);
      84             :   virtual ~SubProblem();
      85             : 
      86             :   virtual libMesh::EquationSystems & es() = 0;
      87             :   virtual MooseMesh & mesh() = 0;
      88             :   virtual const MooseMesh & mesh() const = 0;
      89             :   virtual const MooseMesh & mesh(bool use_displaced) const = 0;
      90             : 
      91             :   /**
      92             :    * @returns whether there will be nonlocal coupling at any point in the simulation, e.g. whether
      93             :    * there are any active \emph or inactive nonlocal kernels or boundary conditions
      94             :    */
      95             :   virtual bool checkNonlocalCouplingRequirement() const = 0;
      96             : 
      97             :   /**
      98             :    * @return whether the given solver system \p sys_num is converged
      99             :    */
     100           0 :   virtual bool solverSystemConverged(const unsigned int sys_num) { return converged(sys_num); }
     101             : 
     102             :   /**
     103             :    * @return whether the given nonlinear system \p nl_sys_num is converged.
     104             :    */
     105             :   virtual bool nlConverged(const unsigned int nl_sys_num);
     106             : 
     107             :   /**
     108             :    * Eventually we want to convert this virtual over to taking a solver system number argument.
     109             :    * We will have to first convert apps to use solverSystemConverged, and then once that is done, we
     110             :    * can change this signature. Then we can go through the apps again and convert back to this
     111             :    * changed API
     112             :    */
     113      310072 :   virtual bool converged(const unsigned int sys_num) { return solverSystemConverged(sys_num); }
     114             : 
     115             :   /**
     116             :    * @return the nonlinear system number corresponding to the provided \p nl_sys_name
     117             :    */
     118             :   virtual unsigned int nlSysNum(const NonlinearSystemName & nl_sys_name) const = 0;
     119             : 
     120             :   /**
     121             :    * @return the linear system number corresponding to the provided \p linear_sys_name
     122             :    */
     123             :   virtual unsigned int linearSysNum(const LinearSystemName & linear_sys_name) const = 0;
     124             : 
     125             :   /**
     126             :    * @return the solver system number corresponding to the provided \p solver_sys_name
     127             :    */
     128             :   virtual unsigned int solverSysNum(const SolverSystemName & solver_sys_name) const = 0;
     129             : 
     130             :   virtual void onTimestepBegin() = 0;
     131             :   virtual void onTimestepEnd() = 0;
     132             : 
     133             :   virtual bool isTransient() const = 0;
     134             : 
     135             :   /// marks this problem as including/needing finite volume functionality.
     136             :   virtual void needFV() = 0;
     137             : 
     138             :   /// returns true if this problem includes/needs finite volume functionality.
     139             :   virtual bool haveFV() const = 0;
     140             : 
     141             :   /**
     142             :    * Whether or not the user has requested default ghosting ot be on.
     143             :    */
     144      121478 :   bool defaultGhosting() { return _default_ghosting; }
     145             : 
     146             :   /**
     147             :    * Create a Tag.  Tags can be associated with Vectors and Matrices and allow objects
     148             :    * (such as Kernels) to arbitrarily contribute values to any set of vectors/matrics
     149             :    *
     150             :    * Note: If the tag is already present then this will simply return the TagID of that Tag, but the
     151             :    * type must be the same.
     152             :    *
     153             :    * @param tag_name The name of the tag to create, the TagID will get automatically generated
     154             :    * @param type The type of the tag
     155             :    */
     156             :   virtual TagID addVectorTag(const TagName & tag_name,
     157             :                              const Moose::VectorTagType type = Moose::VECTOR_TAG_RESIDUAL);
     158             : 
     159             :   /**
     160             :    * Adds a vector tag to the list of vectors that will not be zeroed
     161             :    * when other tagged vectors are
     162             :    * @param tag the TagID of the vector that will be manually managed
     163             :    */
     164             :   void addNotZeroedVectorTag(const TagID tag);
     165             : 
     166             :   /**
     167             :    * Checks if a vector tag is in the list of vectors that will not be zeroed
     168             :    * when other tagged vectors are
     169             :    * @param tag the TagID of the vector that is currently being checked
     170             :    * @returns false if the tag is not within the set of vectors that are
     171             :    *          intended to not be zero or if the set is empty. returns true otherwise
     172             :    */
     173             :   bool vectorTagNotZeroed(const TagID tag) const;
     174             : 
     175             :   /**
     176             :    * Get a VectorTag from a TagID.
     177             :    */
     178             :   virtual const VectorTag & getVectorTag(const TagID tag_id) const;
     179             :   std::vector<VectorTag> getVectorTags(const std::set<TagID> & tag_ids) const;
     180             : 
     181             :   /**
     182             :    * Get a TagID from a TagName.
     183             :    */
     184             :   virtual TagID getVectorTagID(const TagName & tag_name) const;
     185             : 
     186             :   /**
     187             :    * Retrieve the name associated with a TagID
     188             :    */
     189             :   virtual TagName vectorTagName(const TagID tag) const;
     190             : 
     191             :   /**
     192             :    * Return all vector tags, where a tag is represented by a map from name to ID. Can optionally be
     193             :    * limited to a vector tag type.
     194             :    */
     195             :   virtual const std::vector<VectorTag> &
     196             :   getVectorTags(const Moose::VectorTagType type = Moose::VECTOR_TAG_ANY) const;
     197             : 
     198             :   /**
     199             :    * Check to see if a particular Tag exists
     200             :    */
     201  3146819739 :   virtual bool vectorTagExists(const TagID tag_id) const { return tag_id < _vector_tags.size(); }
     202             : 
     203             :   /**
     204             :    * Check to see if a particular Tag exists by using Tag name
     205             :    */
     206             :   virtual bool vectorTagExists(const TagName & tag_name) const;
     207             : 
     208             :   /**
     209             :    * The total number of tags, which can be limited to the tag type
     210             :    */
     211             :   virtual unsigned int numVectorTags(const Moose::VectorTagType type = Moose::VECTOR_TAG_ANY) const;
     212             : 
     213             :   virtual Moose::VectorTagType vectorTagType(const TagID tag_id) const;
     214             : 
     215             :   /**
     216             :    * Create a Tag.  Tags can be associated with Vectors and Matrices and allow objects
     217             :    * (such as Kernels) to arbitrarily contribute values to any set of vectors/matrics
     218             :    *
     219             :    * Note: If the tag is already present then this will simply return the TagID of that Tag
     220             :    *
     221             :    * @param tag_name The name of the tag to create, the TagID will get automatically generated
     222             :    */
     223             :   virtual TagID addMatrixTag(TagName tag_name);
     224             : 
     225             :   /**
     226             :    * Get a TagID from a TagName.
     227             :    */
     228             :   virtual TagID getMatrixTagID(const TagName & tag_name) const;
     229             : 
     230             :   /**
     231             :    * Retrieve the name associated with a TagID
     232             :    */
     233             :   virtual TagName matrixTagName(TagID tag);
     234             : 
     235             :   /**
     236             :    * Check to see if a particular Tag exists
     237             :    */
     238             :   virtual bool matrixTagExists(const TagName & tag_name) const;
     239             : 
     240             :   /**
     241             :    * Check to see if a particular Tag exists
     242             :    */
     243             :   virtual bool matrixTagExists(TagID tag_id) const;
     244             : 
     245             :   /**
     246             :    * The total number of tags
     247             :    */
     248     9032361 :   virtual unsigned int numMatrixTags() const { return _matrix_tag_name_to_tag_id.size(); }
     249             : 
     250             :   /**
     251             :    * Return all matrix tags in the system, where a tag is represented by a map from name to ID
     252             :    */
     253      487556 :   virtual std::map<TagName, TagID> & getMatrixTags() { return _matrix_tag_name_to_tag_id; }
     254             : 
     255             :   /// Whether or not this problem has the variable
     256             :   virtual bool hasVariable(const std::string & var_name) const = 0;
     257             : 
     258             :   /// Whether or not this problem has this linear variable
     259             :   virtual bool hasLinearVariable(const std::string & var_name) const;
     260             : 
     261             :   /// Whether or not this problem has this auxiliary variable
     262             :   virtual bool hasAuxiliaryVariable(const std::string & var_name) const;
     263             : 
     264             :   /**
     265             :    * Returns the variable reference for requested variable which must
     266             :    * be of the expected_var_type (Nonlinear vs. Auxiliary) and
     267             :    * expected_var_field_type (standard, scalar, vector). The default
     268             :    * values of VAR_ANY and VAR_FIELD_ANY should be used when "any"
     269             :    * type of variable is acceptable.  Throws an error if the variable
     270             :    * in question is not in the expected System or of the expected
     271             :    * type.
     272             :    */
     273             :   virtual const MooseVariableFieldBase & getVariable(
     274             :       const THREAD_ID tid,
     275             :       const std::string & var_name,
     276             :       Moose::VarKindType expected_var_type = Moose::VarKindType::VAR_ANY,
     277             :       Moose::VarFieldType expected_var_field_type = Moose::VarFieldType::VAR_FIELD_ANY) const = 0;
     278             :   virtual MooseVariableFieldBase &
     279     4322272 :   getVariable(const THREAD_ID tid,
     280             :               const std::string & var_name,
     281             :               Moose::VarKindType expected_var_type = Moose::VarKindType::VAR_ANY,
     282             :               Moose::VarFieldType expected_var_field_type = Moose::VarFieldType::VAR_FIELD_ANY)
     283             :   {
     284     4322272 :     return const_cast<MooseVariableFieldBase &>(const_cast<const SubProblem *>(this)->getVariable(
     285     4322264 :         tid, var_name, expected_var_type, expected_var_field_type));
     286             :   }
     287             : 
     288             :   /// Returns the variable reference for requested MooseVariable which may be in any system
     289             :   virtual MooseVariable & getStandardVariable(const THREAD_ID tid,
     290             :                                               const std::string & var_name) = 0;
     291             : 
     292             :   /// Returns the variable reference for requested MooseVariableField which may be in any system
     293             :   virtual MooseVariableFieldBase & getActualFieldVariable(const THREAD_ID tid,
     294             :                                                           const std::string & var_name) = 0;
     295             : 
     296             :   /// Returns the variable reference for requested VectorMooseVariable which may be in any system
     297             :   virtual VectorMooseVariable & getVectorVariable(const THREAD_ID tid,
     298             :                                                   const std::string & var_name) = 0;
     299             : 
     300             :   /// Returns the variable reference for requested ArrayMooseVariable which may be in any system
     301             :   virtual ArrayMooseVariable & getArrayVariable(const THREAD_ID tid,
     302             :                                                 const std::string & var_name) = 0;
     303             : 
     304             :   /// Returns a Boolean indicating whether any system contains a variable with the name provided
     305             :   virtual bool hasScalarVariable(const std::string & var_name) const = 0;
     306             : 
     307             :   /// Returns the scalar variable reference from whichever system contains it
     308             :   virtual MooseVariableScalar & getScalarVariable(const THREAD_ID tid,
     309             :                                                   const std::string & var_name) = 0;
     310             : 
     311             :   /// Returns the equation system containing the variable provided
     312             :   virtual libMesh::System & getSystem(const std::string & var_name) = 0;
     313             : 
     314             :   /**
     315             :    * Set the MOOSE variables to be reinited on each element.
     316             :    * @param moose_vars A set of variables that need to be reinited each time reinit() is called.
     317             :    *
     318             :    * @param tid The thread id
     319             :    */
     320             :   virtual void
     321             :   setActiveElementalMooseVariables(const std::set<MooseVariableFieldBase *> & moose_vars,
     322             :                                    const THREAD_ID tid);
     323             : 
     324             :   /**
     325             :    * Get the MOOSE variables to be reinited on each element.
     326             :    *
     327             :    * @param tid The thread id
     328             :    */
     329             :   virtual const std::set<MooseVariableFieldBase *> &
     330             :   getActiveElementalMooseVariables(const THREAD_ID tid) const;
     331             : 
     332             :   /**
     333             :    * Whether or not a list of active elemental moose variables has been set.
     334             :    *
     335             :    * @return True if there has been a list of active elemental moose variables set, False otherwise
     336             :    */
     337             :   virtual bool hasActiveElementalMooseVariables(const THREAD_ID tid) const;
     338             : 
     339             :   /**
     340             :    * Clear the active elemental MooseVariableFieldBase.  If there are no active variables then they
     341             :    * will all be reinited. Call this after finishing the computation that was using a restricted set
     342             :    * of MooseVariableFieldBase
     343             :    *
     344             :    * @param tid The thread id
     345             :    */
     346             :   virtual void clearActiveElementalMooseVariables(const THREAD_ID tid);
     347             : 
     348             :   virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) = 0;
     349             :   virtual const Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) const = 0;
     350             : 
     351             :   /**
     352             :    * Return the nonlinear system object as a base class reference given the system number
     353             :    */
     354             :   virtual const SystemBase & systemBaseNonlinear(const unsigned int sys_num) const = 0;
     355             :   virtual SystemBase & systemBaseNonlinear(const unsigned int sys_num) = 0;
     356             :   /**
     357             :    * Return the linear system object as a base class reference given the system number
     358             :    */
     359             :   virtual const SystemBase & systemBaseLinear(const unsigned int sys_num) const = 0;
     360             :   virtual SystemBase & systemBaseLinear(const unsigned int sys_num) = 0;
     361             :   /**
     362             :    * Return the solver system object as a base class reference given the system number
     363             :    */
     364             :   virtual const SystemBase & systemBaseSolver(const unsigned int sys_num) const = 0;
     365             :   virtual SystemBase & systemBaseSolver(const unsigned int sys_num) = 0;
     366             :   /**
     367             :    * Return the auxiliary system object as a base class reference
     368             :    */
     369             :   virtual const SystemBase & systemBaseAuxiliary() const = 0;
     370             :   virtual SystemBase & systemBaseAuxiliary() = 0;
     371             : 
     372             :   virtual void prepareShapes(unsigned int var, const THREAD_ID tid) = 0;
     373             :   virtual void prepareFaceShapes(unsigned int var, const THREAD_ID tid) = 0;
     374             :   virtual void prepareNeighborShapes(unsigned int var, const THREAD_ID tid) = 0;
     375             :   Moose::CoordinateSystemType getCoordSystem(SubdomainID sid) const;
     376             : 
     377             :   /**
     378             :    * Returns the desired radial direction for RZ coordinate transformation
     379             :    * @return The coordinate direction for the radial direction
     380             :    */
     381             :   unsigned int getAxisymmetricRadialCoord() const;
     382             : 
     383             :   virtual DiracKernelInfo & diracKernelInfo();
     384             :   virtual Real finalNonlinearResidual(const unsigned int nl_sys_num) const;
     385             :   virtual unsigned int nNonlinearIterations(const unsigned int nl_sys_num) const;
     386             :   virtual unsigned int nLinearIterations(const unsigned int nl_sys_num) const;
     387             : 
     388             :   virtual void addResidual(const THREAD_ID tid) = 0;
     389             :   virtual void addResidualNeighbor(const THREAD_ID tid) = 0;
     390             :   virtual void addResidualLower(const THREAD_ID tid) = 0;
     391             : 
     392             :   virtual void cacheResidual(const THREAD_ID tid);
     393             :   virtual void cacheResidualNeighbor(const THREAD_ID tid);
     394             :   virtual void addCachedResidual(const THREAD_ID tid);
     395             : 
     396             :   virtual void setResidual(libMesh::NumericVector<libMesh::Number> & residual,
     397             :                            const THREAD_ID tid) = 0;
     398             :   virtual void setResidualNeighbor(libMesh::NumericVector<libMesh::Number> & residual,
     399             :                                    const THREAD_ID tid) = 0;
     400             : 
     401             :   virtual void addJacobian(const THREAD_ID tid) = 0;
     402             :   virtual void addJacobianNeighbor(const THREAD_ID tid) = 0;
     403             :   virtual void addJacobianNeighborLowerD(const THREAD_ID tid) = 0;
     404             :   virtual void addJacobianLowerD(const THREAD_ID tid) = 0;
     405             :   virtual void addJacobianNeighbor(libMesh::SparseMatrix<libMesh::Number> & jacobian,
     406             :                                    unsigned int ivar,
     407             :                                    unsigned int jvar,
     408             :                                    const libMesh::DofMap & dof_map,
     409             :                                    std::vector<dof_id_type> & dof_indices,
     410             :                                    std::vector<dof_id_type> & neighbor_dof_indices,
     411             :                                    const std::set<TagID> & tags,
     412             :                                    const THREAD_ID tid) = 0;
     413             : 
     414             :   virtual void cacheJacobian(const THREAD_ID tid);
     415             :   virtual void cacheJacobianNeighbor(const THREAD_ID tid);
     416             :   virtual void addCachedJacobian(const THREAD_ID tid);
     417             : 
     418             :   virtual void prepare(const Elem * elem, const THREAD_ID tid) = 0;
     419             :   virtual void prepareFace(const Elem * elem, const THREAD_ID tid) = 0;
     420             :   virtual void prepare(const Elem * elem,
     421             :                        unsigned int ivar,
     422             :                        unsigned int jvar,
     423             :                        const std::vector<dof_id_type> & dof_indices,
     424             :                        const THREAD_ID tid) = 0;
     425             :   virtual void setCurrentSubdomainID(const Elem * elem, const THREAD_ID tid) = 0;
     426             :   virtual void
     427             :   setNeighborSubdomainID(const Elem * elem, unsigned int side, const THREAD_ID tid) = 0;
     428             :   virtual void prepareAssembly(const THREAD_ID tid) = 0;
     429             : 
     430             :   virtual void reinitElem(const Elem * elem, const THREAD_ID tid) = 0;
     431             :   virtual void reinitElemPhys(const Elem * elem,
     432             :                               const std::vector<Point> & phys_points_in_elem,
     433             :                               const THREAD_ID tid) = 0;
     434             :   virtual void reinitElemFace(const Elem * elem, unsigned int side, const THREAD_ID tid) = 0;
     435             :   virtual void reinitLowerDElem(const Elem * lower_d_elem,
     436             :                                 const THREAD_ID tid,
     437             :                                 const std::vector<Point> * const pts = nullptr,
     438             :                                 const std::vector<Real> * const weights = nullptr);
     439             :   virtual void reinitNode(const Node * node, const THREAD_ID tid) = 0;
     440             :   virtual void reinitNodeFace(const Node * node, BoundaryID bnd_id, const THREAD_ID tid) = 0;
     441             :   virtual void reinitNodes(const std::vector<dof_id_type> & nodes, const THREAD_ID tid) = 0;
     442             :   virtual void reinitNodesNeighbor(const std::vector<dof_id_type> & nodes, const THREAD_ID tid) = 0;
     443             :   virtual void reinitNeighbor(const Elem * elem, unsigned int side, const THREAD_ID tid) = 0;
     444             :   virtual void reinitNeighborPhys(const Elem * neighbor,
     445             :                                   unsigned int neighbor_side,
     446             :                                   const std::vector<Point> & physical_points,
     447             :                                   const THREAD_ID tid) = 0;
     448             :   virtual void reinitNeighborPhys(const Elem * neighbor,
     449             :                                   const std::vector<Point> & physical_points,
     450             :                                   const THREAD_ID tid) = 0;
     451             :   virtual void
     452             :   reinitElemNeighborAndLowerD(const Elem * elem, unsigned int side, const THREAD_ID tid) = 0;
     453             :   /**
     454             :    * fills the VariableValue arrays for scalar variables from the solution vector
     455             :    * @param tid The thread id
     456             :    * @param reinit_for_derivative_reordering A flag indicating whether we are reinitializing for the
     457             :    *        purpose of re-ordering derivative information for ADNodalBCs
     458             :    */
     459             :   virtual void reinitScalars(const THREAD_ID tid,
     460             :                              bool reinit_for_derivative_reordering = false) = 0;
     461             :   virtual void reinitOffDiagScalars(const THREAD_ID tid) = 0;
     462             : 
     463             :   /// sets the current boundary ID in assembly
     464             :   virtual void setCurrentBoundaryID(BoundaryID bid, const THREAD_ID tid);
     465             : 
     466             :   /**
     467             :    * reinitialize FE objects on a given element on a given side at a given set of reference
     468             :    * points and then compute variable data. Note that this method makes no assumptions about what's
     469             :    * been called beforehand, e.g. you don't have to call some prepare method before this one. This
     470             :    * is an all-in-one reinit
     471             :    */
     472             :   virtual void reinitElemFaceRef(const Elem * elem,
     473             :                                  unsigned int side,
     474             :                                  Real tolerance,
     475             :                                  const std::vector<Point> * const pts,
     476             :                                  const std::vector<Real> * const weights = nullptr,
     477             :                                  const THREAD_ID tid = 0);
     478             : 
     479             :   /**
     480             :    * reinitialize FE objects on a given neighbor element on a given side at a given set of reference
     481             :    * points and then compute variable data. Note that this method makes no assumptions about what's
     482             :    * been called beforehand, e.g. you don't have to call some prepare method before this one. This
     483             :    * is an all-in-one reinit
     484             :    */
     485             :   virtual void reinitNeighborFaceRef(const Elem * neighbor_elem,
     486             :                                      unsigned int neighbor_side,
     487             :                                      Real tolerance,
     488             :                                      const std::vector<Point> * const pts,
     489             :                                      const std::vector<Real> * const weights = nullptr,
     490             :                                      const THREAD_ID tid = 0);
     491             : 
     492             :   /**
     493             :    * reinitialize a neighboring lower dimensional element
     494             :    */
     495             :   void reinitNeighborLowerDElem(const Elem * elem, const THREAD_ID tid = 0);
     496             : 
     497             :   /**
     498             :    * Reinit a mortar element to obtain a valid JxW
     499             :    */
     500             :   void reinitMortarElem(const Elem * elem, const THREAD_ID tid = 0);
     501             : 
     502             :   /**
     503             :    * Returns true if the Problem has Dirac kernels it needs to compute on elem.
     504             :    */
     505             :   virtual bool reinitDirac(const Elem * elem, const THREAD_ID tid) = 0;
     506             :   /**
     507             :    * Fills "elems" with the elements that should be looped over for Dirac Kernels
     508             :    */
     509             :   virtual void getDiracElements(std::set<const Elem *> & elems) = 0;
     510             :   /**
     511             :    * Gets called before Dirac Kernels are asked to add the points they are supposed to be evaluated
     512             :    * in
     513             :    */
     514             :   virtual void clearDiracInfo() = 0;
     515             : 
     516             :   // Geom Search
     517             :   virtual void
     518             :   updateGeomSearch(GeometricSearchData::GeometricSearchType type = GeometricSearchData::ALL) = 0;
     519             : 
     520             :   virtual GeometricSearchData & geomSearchData() = 0;
     521             : 
     522             :   /**
     523             :    * Adds the given material property to a storage map based on block ids
     524             :    *
     525             :    * This is method is called from within the Material class when the property
     526             :    * is first registered.
     527             :    * @param block_id The block id for the MaterialProperty
     528             :    * @param name The name of the property
     529             :    */
     530             :   virtual void storeSubdomainMatPropName(SubdomainID block_id, const std::string & name);
     531             : 
     532             :   /**
     533             :    * Adds the given material property to a storage map based on boundary ids
     534             :    *
     535             :    * This is method is called from within the Material class when the property
     536             :    * is first registered.
     537             :    * @param boundary_id The block id for the MaterialProperty
     538             :    * @param name The name of the property
     539             :    */
     540             :   virtual void storeBoundaryMatPropName(BoundaryID boundary_id, const std::string & name);
     541             : 
     542             :   /**
     543             :    * Adds to a map based on block ids of material properties for which a zero
     544             :    * value can be returned. Thes properties are optional and will not trigger a
     545             :    * missing material property error.
     546             :    *
     547             :    * @param block_id The block id for the MaterialProperty
     548             :    * @param name The name of the property
     549             :    */
     550             :   virtual void storeSubdomainZeroMatProp(SubdomainID block_id, const MaterialPropertyName & name);
     551             : 
     552             :   /**
     553             :    * Adds to a map based on boundary ids of material properties for which a zero
     554             :    * value can be returned. Thes properties are optional and will not trigger a
     555             :    * missing material property error.
     556             :    *
     557             :    * @param boundary_id The block id for the MaterialProperty
     558             :    * @param name The name of the property
     559             :    */
     560             :   virtual void storeBoundaryZeroMatProp(BoundaryID boundary_id, const MaterialPropertyName & name);
     561             : 
     562             :   /**
     563             :    * Adds to a map based on block ids of material properties to validate
     564             :    *
     565             :    * @param block_id The block id for the MaterialProperty
     566             :    * @param name The name of the property
     567             :    */
     568             :   virtual void storeSubdomainDelayedCheckMatProp(const std::string & requestor,
     569             :                                                  SubdomainID block_id,
     570             :                                                  const std::string & name);
     571             : 
     572             :   /**
     573             :    * Adds to a map based on boundary ids of material properties to validate
     574             :    *
     575             :    * @param requestor The MOOSE object name requesting the material property
     576             :    * @param boundary_id The block id for the MaterialProperty
     577             :    * @param name The name of the property
     578             :    */
     579             :   virtual void storeBoundaryDelayedCheckMatProp(const std::string & requestor,
     580             :                                                 BoundaryID boundary_id,
     581             :                                                 const std::string & name);
     582             : 
     583             :   /**
     584             :    * Checks block material properties integrity
     585             :    *
     586             :    * \see FEProblemBase::checkProblemIntegrity
     587             :    */
     588             :   virtual void checkBlockMatProps();
     589             : 
     590             :   /**
     591             :    * Checks boundary material properties integrity
     592             :    *
     593             :    * \see FEProblemBase::checkProblemIntegrity
     594             :    */
     595             :   virtual void checkBoundaryMatProps();
     596             : 
     597             :   /**
     598             :    * Helper method for adding a material property name to the _material_property_requested set
     599             :    */
     600             :   virtual void markMatPropRequested(const std::string &);
     601             : 
     602             :   /**
     603             :    * Find out if a material property has been requested by any object
     604             :    */
     605             :   virtual bool isMatPropRequested(const std::string & prop_name) const;
     606             : 
     607             :   /**
     608             :    * Helper for tracking the object that is consuming a property for MaterialPropertyDebugOutput
     609             :    */
     610             :   void addConsumedPropertyName(const MooseObjectName & obj_name, const std::string & prop_name);
     611             : 
     612             :   /**
     613             :    * Return the map that tracks the object with consumed material properties
     614             :    */
     615             :   const std::map<MooseObjectName, std::set<std::string>> & getConsumedPropertyMap() const;
     616             : 
     617             :   /**
     618             :    * Will make sure that all dofs connected to elem_id are ghosted to this processor
     619             :    */
     620             :   virtual void addGhostedElem(dof_id_type elem_id) = 0;
     621             : 
     622             :   /**
     623             :    * Will make sure that all necessary elements from boundary_id are ghosted to this processor
     624             :    */
     625             :   virtual void addGhostedBoundary(BoundaryID boundary_id) = 0;
     626             : 
     627             :   /**
     628             :    * Causes the boundaries added using addGhostedBoundary to actually be ghosted.
     629             :    */
     630             :   virtual void ghostGhostedBoundaries() = 0;
     631             : 
     632             :   /**
     633             :    * Get a vector containing the block ids the material property is defined on.
     634             :    */
     635             :   virtual std::set<SubdomainID> getMaterialPropertyBlocks(const std::string & prop_name);
     636             : 
     637             :   /**
     638             :    * Get a vector of block id equivalences that the material property is defined on.
     639             :    */
     640             :   virtual std::vector<SubdomainName> getMaterialPropertyBlockNames(const std::string & prop_name);
     641             : 
     642             :   /**
     643             :    * Check if a material property is defined on a block.
     644             :    */
     645             :   virtual bool hasBlockMaterialProperty(SubdomainID block_id, const std::string & prop_name);
     646             : 
     647             :   /**
     648             :    * Get a vector containing the block ids the material property is defined on.
     649             :    */
     650             :   virtual std::set<BoundaryID> getMaterialPropertyBoundaryIDs(const std::string & prop_name);
     651             : 
     652             :   /**
     653             :    * Get a vector of block id equivalences that the material property is defined on.
     654             :    */
     655             :   virtual std::vector<BoundaryName> getMaterialPropertyBoundaryNames(const std::string & prop_name);
     656             : 
     657             :   /**
     658             :    * Check if a material property is defined on a block.
     659             :    */
     660             :   virtual bool hasBoundaryMaterialProperty(BoundaryID boundary_id, const std::string & prop_name);
     661             : 
     662             :   /**
     663             :    * Returns true if the problem is in the process of computing it's initial residual.
     664             :    * @return Whether or not the problem is currently computing the initial residual.
     665             :    */
     666             :   virtual bool computingPreSMOResidual(const unsigned int nl_sys_num) const = 0;
     667             : 
     668             :   /**
     669             :    * Return the list of elements that should have their DoFs ghosted to this processor.
     670             :    * @return The list
     671             :    */
     672       71184 :   virtual std::set<dof_id_type> & ghostedElems() { return _ghosted_elems; }
     673             : 
     674             :   std::map<std::string, std::vector<dof_id_type>> _var_dof_map;
     675             : 
     676             :   /**
     677             :    * @return the nonlocal coupling matrix for the i'th nonlinear system
     678             :    */
     679             :   virtual const libMesh::CouplingMatrix & nonlocalCouplingMatrix(const unsigned i) const = 0;
     680             : 
     681             :   /**
     682             :    * Returns true if the problem is in the process of computing the Jacobian
     683             :    */
     684   402381613 :   const bool & currentlyComputingJacobian() const { return _currently_computing_jacobian; };
     685             : 
     686             :   /**
     687             :    * Set whether or not the problem is in the process of computing the Jacobian
     688             :    */
     689     3704828 :   void setCurrentlyComputingJacobian(const bool currently_computing_jacobian)
     690             :   {
     691     3704828 :     _currently_computing_jacobian = currently_computing_jacobian;
     692     3704828 :   }
     693             : 
     694             :   /**
     695             :    * Returns true if the problem is in the process of computing the residual and the Jacobian
     696             :    */
     697             :   const bool & currentlyComputingResidualAndJacobian() const;
     698             : 
     699             :   /**
     700             :    * Set whether or not the problem is in the process of computing the Jacobian
     701             :    */
     702             :   void setCurrentlyComputingResidualAndJacobian(bool currently_computing_residual_and_jacobian);
     703             : 
     704             :   /**
     705             :    * Returns true if the problem is in the process of computing the nonlinear residual
     706             :    */
     707       21781 :   bool computingNonlinearResid() const { return _computing_nonlinear_residual; }
     708             : 
     709             :   /**
     710             :    * Set whether or not the problem is in the process of computing the nonlinear residual
     711             :    */
     712      197082 :   virtual void computingNonlinearResid(const bool computing_nonlinear_residual)
     713             :   {
     714      197082 :     _computing_nonlinear_residual = computing_nonlinear_residual;
     715      197082 :   }
     716             : 
     717             :   /**
     718             :    * Returns true if the problem is in the process of computing the residual
     719             :    */
     720       66739 :   const bool & currentlyComputingResidual() const { return _currently_computing_residual; }
     721             : 
     722             :   /**
     723             :    * Set whether or not the problem is in the process of computing the residual
     724             :    */
     725      548912 :   virtual void setCurrentlyComputingResidual(const bool currently_computing_residual)
     726             :   {
     727      548912 :     _currently_computing_residual = currently_computing_residual;
     728      548912 :   }
     729             : 
     730             :   /// Is it safe to access the tagged  matrices
     731  1111507935 :   virtual bool safeAccessTaggedMatrices() const { return _safe_access_tagged_matrices; }
     732             : 
     733             :   /// Is it safe to access the tagged vectors
     734      588273 :   virtual bool safeAccessTaggedVectors() const { return _safe_access_tagged_vectors; }
     735             : 
     736             :   virtual void clearActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid);
     737             : 
     738             :   virtual void clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid);
     739             : 
     740             :   virtual void setActiveFEVariableCoupleableVectorTags(std::set<TagID> & vtags,
     741             :                                                        const THREAD_ID tid);
     742             : 
     743             :   virtual void setActiveFEVariableCoupleableMatrixTags(std::set<TagID> & mtags,
     744             :                                                        const THREAD_ID tid);
     745             : 
     746             :   virtual void clearActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid);
     747             : 
     748             :   virtual void clearActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid);
     749             : 
     750             :   virtual void setActiveScalarVariableCoupleableVectorTags(std::set<TagID> & vtags,
     751             :                                                            const THREAD_ID tid);
     752             : 
     753             :   virtual void setActiveScalarVariableCoupleableMatrixTags(std::set<TagID> & mtags,
     754             :                                                            const THREAD_ID tid);
     755             : 
     756             :   const std::set<TagID> & getActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid) const;
     757             : 
     758             :   const std::set<TagID> & getActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid) const;
     759             : 
     760             :   const std::set<TagID> & getActiveFEVariableCoupleableVectorTags(const THREAD_ID tid) const;
     761             : 
     762             :   const std::set<TagID> & getActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid) const;
     763             : 
     764             :   /**
     765             :    * Method for setting whether we have any ad objects
     766             :    */
     767         522 :   virtual void haveADObjects(bool have_ad_objects) { _have_ad_objects = have_ad_objects; }
     768             :   /**
     769             :    * Method for reading wehther we have any ad objects
     770             :    */
     771   407560380 :   bool haveADObjects() const { return _have_ad_objects; }
     772             : 
     773             :   virtual LineSearch * getLineSearch() = 0;
     774             : 
     775             :   /**
     776             :    * The coupling matrix defining what blocks exist in the preconditioning matrix
     777             :    */
     778             :   virtual const libMesh::CouplingMatrix * couplingMatrix(const unsigned int nl_sys_num) const = 0;
     779             : 
     780             : private:
     781             :   /**
     782             :    * Creates (n_sys - 1) clones of the provided algebraic ghosting functor (corresponding to the
     783             :    * nonlinear system algebraic ghosting functor), initializes the clone with the appropriate
     784             :    * DofMap, and then adds the clone to said DofMap
     785             :    * @param algebraic_gf the (nonlinear system's) algebraic ghosting functor to clone
     786             :    * @param to_mesh whether the clone should be added to the corresponding DofMap's underlying
     787             :    * MeshBase (the underlying MeshBase will be the same for every system held by this object's
     788             :    * EquationSystems object)
     789             :    */
     790             :   void cloneAlgebraicGhostingFunctor(libMesh::GhostingFunctor & algebraic_gf, bool to_mesh = true);
     791             : 
     792             :   /**
     793             :    * Creates (n_sys - 1) clones of the provided coupling ghosting functor (corresponding to the
     794             :    * nonlinear system coupling ghosting functor), initializes the clone with the appropriate
     795             :    * DofMap, and then adds the clone to said DofMap
     796             :    * @param coupling_gf the (nonlinear system's) coupling ghosting functor to clone
     797             :    * @param to_mesh whether the clone should be added to the corresponding DofMap's underlying
     798             :    * MeshBase (the underlying MeshBase will be the same for every system held by this object's
     799             :    * EquationSystems object)
     800             :    */
     801             :   void cloneCouplingGhostingFunctor(libMesh::GhostingFunctor & coupling_gf, bool to_mesh = true);
     802             : 
     803             : public:
     804             :   /**
     805             :    * Add an algebraic ghosting functor to this problem's DofMaps
     806             :    */
     807             :   void addAlgebraicGhostingFunctor(libMesh::GhostingFunctor & algebraic_gf, bool to_mesh = true);
     808             : 
     809             :   /**
     810             :    * Add a coupling functor to this problem's DofMaps
     811             :    */
     812             :   void addCouplingGhostingFunctor(libMesh::GhostingFunctor & coupling_gf, bool to_mesh = true);
     813             : 
     814             :   /**
     815             :    * Remove an algebraic ghosting functor from this problem's DofMaps
     816             :    */
     817             :   void removeAlgebraicGhostingFunctor(libMesh::GhostingFunctor & algebraic_gf);
     818             : 
     819             :   /**
     820             :    * Remove a coupling ghosting functor from this problem's DofMaps
     821             :    */
     822             :   void removeCouplingGhostingFunctor(libMesh::GhostingFunctor & coupling_gf);
     823             : 
     824             :   /**
     825             :    * Automatic scaling setter
     826             :    * @param automatic_scaling A boolean representing whether we are performing automatic scaling
     827             :    */
     828             :   virtual void automaticScaling(bool automatic_scaling);
     829             : 
     830             :   /**
     831             :    * Automatic scaling getter
     832             :    * @return A boolean representing whether we are performing automatic scaling
     833             :    */
     834             :   bool automaticScaling() const;
     835             : 
     836             :   /**
     837             :    * Tells this problem that the assembly associated with the given nonlinear system number involves
     838             :    * a scaling vector
     839             :    */
     840             :   void hasScalingVector(const unsigned int nl_sys_num);
     841             : 
     842             :   /**
     843             :    * Whether we have a displaced problem in our simulation
     844             :    */
     845             :   virtual bool haveDisplaced() const = 0;
     846             : 
     847             :   /**
     848             :    * Getter for whether we're computing the scaling jacobian
     849             :    */
     850             :   virtual bool computingScalingJacobian() const = 0;
     851             : 
     852             :   /**
     853             :    * Getter for whether we're computing the scaling residual
     854             :    */
     855             :   virtual bool computingScalingResidual() const = 0;
     856             : 
     857             :   /**
     858             :    * Clear dof indices from variables in nl and aux systems
     859             :    */
     860             :   void clearAllDofIndices();
     861             : 
     862             :   /**
     863             :    * @tparam T The type that the functor will return when evaluated, e.g. \p
     864             :                ADReal or \p Real
     865             :    * @param name The name of the functor to retrieve
     866             :    * @param tid The thread ID that we are retrieving the functor property for
     867             :    * @param requestor_name The name of the object that is requesting this functor property
     868             :    * @param requestor_is_ad Whether the requesting object is an AD object
     869             :    * @return a constant reference to the functor
     870             :    */
     871             :   template <typename T>
     872             :   const Moose::Functor<T> & getFunctor(const std::string & name,
     873             :                                        const THREAD_ID tid,
     874             :                                        const std::string & requestor_name,
     875             :                                        bool requestor_is_ad);
     876             : 
     877             :   /**
     878             :    * checks whether we have a functor corresponding to \p name on the thread id \p tid
     879             :    */
     880             :   bool hasFunctor(const std::string & name, const THREAD_ID tid) const;
     881             : 
     882             :   /**
     883             :    * checks whether we have a functor of type T corresponding to \p name on the thread id \p tid
     884             :    */
     885             :   template <typename T>
     886             :   bool hasFunctorWithType(const std::string & name, const THREAD_ID tid) const;
     887             : 
     888             :   /**
     889             :    * add a functor to the problem functor container
     890             :    */
     891             :   template <typename T>
     892             :   void
     893             :   addFunctor(const std::string & name, const Moose::FunctorBase<T> & functor, const THREAD_ID tid);
     894             : 
     895             :   /**
     896             :    * Add a functor that has block-wise lambda definitions, e.g. the evaluations of the functor are
     897             :    * based on a user-provided lambda expression.
     898             :    * @param name The name of the functor to add
     899             :    * @param my_lammy The lambda expression that will be called when the functor is evaluated
     900             :    * @param clearance_schedule How often to clear functor evaluations. The default value is always,
     901             :    * which means that the functor will be re-evaluated every time it is called. If it is something
     902             :    * other than always, than cached values may be returned
     903             :    * @param mesh The mesh on which this functor operates
     904             :    * @param block_ids The blocks on which the lambda expression is defined
     905             :    * @param tid The thread on which the functor we are adding will run
     906             :    * @return The added functor
     907             :    */
     908             :   template <typename T, typename PolymorphicLambda>
     909             :   const Moose::FunctorBase<T> &
     910             :   addPiecewiseByBlockLambdaFunctor(const std::string & name,
     911             :                                    PolymorphicLambda my_lammy,
     912             :                                    const std::set<ExecFlagType> & clearance_schedule,
     913             :                                    const MooseMesh & mesh,
     914             :                                    const std::set<SubdomainID> & block_ids,
     915             :                                    const THREAD_ID tid);
     916             : 
     917             :   virtual void initialSetup();
     918             :   virtual void timestepSetup();
     919             :   virtual void customSetup(const ExecFlagType & exec_type);
     920             :   virtual void residualSetup();
     921             :   virtual void jacobianSetup();
     922             : 
     923             :   /// Setter for debug functor output
     924          34 :   void setFunctorOutput(bool set_output) { _output_functors = set_output; }
     925             : 
     926             :   /**
     927             :    * @return the number of nonlinear systems in the problem
     928             :    */
     929             :   virtual std::size_t numNonlinearSystems() const = 0;
     930             : 
     931             :   /**
     932             :    * @return the current nonlinear system number
     933             :    */
     934             :   virtual unsigned int currentNlSysNum() const = 0;
     935             : 
     936             :   /**
     937             :    * @return the number of linear systems in the problem
     938             :    */
     939             :   virtual std::size_t numLinearSystems() const = 0;
     940             : 
     941             :   /**
     942             :    * @return the number of solver systems in the problem
     943             :    */
     944             :   virtual std::size_t numSolverSystems() const = 0;
     945             : 
     946             :   /**
     947             :    * @return the current linear system number
     948             :    */
     949             :   virtual unsigned int currentLinearSysNum() const = 0;
     950             : 
     951             :   /**
     952             :    * Register an unfulfilled functor request
     953             :    */
     954             :   template <typename T>
     955             :   void registerUnfilledFunctorRequest(T * functor_interface,
     956             :                                       const std::string & functor_name,
     957             :                                       const THREAD_ID tid);
     958             : 
     959             :   /**
     960             :    * Return the residual vector tags we are currently computing
     961             :    */
     962             :   virtual const std::vector<VectorTag> & currentResidualVectorTags() const = 0;
     963             : 
     964             :   /**
     965             :    * Select the vector tags which belong to a specific system
     966             :    * @param system Reference to the system
     967             :    * @param input_vector_tags A vector of vector tags
     968             :    * @param selected_tags A set which gets populated by the tag-ids that belong to the system
     969             :    */
     970             :   static void selectVectorTagsFromSystem(const SystemBase & system,
     971             :                                          const std::vector<VectorTag> & input_vector_tags,
     972             :                                          std::set<TagID> & selected_tags);
     973             : 
     974             :   /**
     975             :    * Select the matrix tags which belong to a specific system
     976             :    * @param system Reference to the system
     977             :    * @param input_matrix_tags A map of matrix tags
     978             :    * @param selected_tags A set which gets populated by the tag-ids that belong to the system
     979             :    */
     980             :   static void selectMatrixTagsFromSystem(const SystemBase & system,
     981             :                                          const std::map<TagName, TagID> & input_matrix_tags,
     982             :                                          std::set<TagID> & selected_tags);
     983             : 
     984             :   /**
     985             :    * reinitialize the finite volume assembly data for the provided face and thread
     986             :    */
     987             :   void reinitFVFace(const THREAD_ID tid, const FaceInfo & fi);
     988             : 
     989             :   /**
     990             :    * Whether the simulation has active nonlocal coupling which should be accounted for in the
     991             :    * Jacobian. For this to return true, there must be at least one active nonlocal kernel or
     992             :    * boundary condition
     993             :    */
     994             :   virtual bool hasNonlocalCoupling() const = 0;
     995             : 
     996             :   /**
     997             :    * Prepare \p DofMap and \p Assembly classes with our p-refinement information
     998             :    */
     999             :   void preparePRefinement();
    1000             : 
    1001             :   /**
    1002             :    * @returns whether we're doing p-refinement
    1003             :    */
    1004             :   [[nodiscard]] bool doingPRefinement() const;
    1005             : 
    1006             :   /**
    1007             :    * Query whether p-refinement has been requested at any point during the simulation
    1008             :    */
    1009      272744 :   [[nodiscard]] bool havePRefinement() const { return _have_p_refinement; }
    1010             : 
    1011             :   /**
    1012             :    * Set the current lower dimensional element. This can be null
    1013             :    */
    1014             :   virtual void setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid);
    1015             : 
    1016             : protected:
    1017             :   /**
    1018             :    * Helper function called by getVariable that handles the logic for
    1019             :    * checking whether Variables of the requested type are available.
    1020             :    */
    1021             :   template <typename T>
    1022             :   MooseVariableFieldBase & getVariableHelper(const THREAD_ID tid,
    1023             :                                              const std::string & var_name,
    1024             :                                              Moose::VarKindType expected_var_type,
    1025             :                                              Moose::VarFieldType expected_var_field_type,
    1026             :                                              const std::vector<T> & nls,
    1027             :                                              const SystemBase & aux) const;
    1028             : 
    1029             :   /**
    1030             :    * Verify the integrity of _vector_tags and _typed_vector_tags
    1031             :    */
    1032             :   bool verifyVectorTags() const;
    1033             : 
    1034             :   /**
    1035             :    * Mark a variable family for either disabling or enabling p-refinement with valid parameters of a
    1036             :    * variable
    1037             :    */
    1038             :   void markFamilyPRefinement(const InputParameters & params);
    1039             : 
    1040             :   /// The currently declared tags
    1041             :   std::map<TagName, TagID> _matrix_tag_name_to_tag_id;
    1042             : 
    1043             :   /// Reverse map
    1044             :   std::map<TagID, TagName> _matrix_tag_id_to_tag_name;
    1045             : 
    1046             :   /// The Factory for building objects
    1047             :   Factory & _factory;
    1048             : 
    1049             :   DiracKernelInfo _dirac_kernel_info;
    1050             : 
    1051             :   /// Map of material properties (block_id -> list of properties)
    1052             :   std::map<SubdomainID, std::set<std::string>> _map_block_material_props;
    1053             : 
    1054             :   /// Map for boundary material properties (boundary_id -> list of properties)
    1055             :   std::map<BoundaryID, std::set<std::string>> _map_boundary_material_props;
    1056             : 
    1057             :   /// Set of properties returned as zero properties
    1058             :   std::map<SubdomainID, std::set<MaterialPropertyName>> _zero_block_material_props;
    1059             :   std::map<BoundaryID, std::set<MaterialPropertyName>> _zero_boundary_material_props;
    1060             : 
    1061             :   /// set containing all material property names that have been requested by getMaterialProperty*
    1062             :   std::set<std::string> _material_property_requested;
    1063             : 
    1064             :   ///@{
    1065             :   /**
    1066             :    * Data structures of the requested material properties.  We store them in a map
    1067             :    * from boundary/block id to multimap.  Each of the multimaps is a list of
    1068             :    * requestor object names to material property names.
    1069             :    */
    1070             :   std::map<SubdomainID, std::multimap<std::string, std::string>> _map_block_material_props_check;
    1071             :   std::map<BoundaryID, std::multimap<std::string, std::string>> _map_boundary_material_props_check;
    1072             :   ///@}
    1073             : 
    1074             :   /// This is the set of MooseVariableFieldBase that will actually get reinited by a call to reinit(elem)
    1075             :   std::vector<std::set<MooseVariableFieldBase *>> _active_elemental_moose_variables;
    1076             : 
    1077             :   /// Whether or not there is currently a list of active elemental moose variables
    1078             :   /* This needs to remain <unsigned int> for threading purposes */
    1079             :   std::vector<unsigned int> _has_active_elemental_moose_variables;
    1080             : 
    1081             :   std::vector<std::set<TagID>> _active_fe_var_coupleable_matrix_tags;
    1082             : 
    1083             :   std::vector<std::set<TagID>> _active_fe_var_coupleable_vector_tags;
    1084             : 
    1085             :   std::vector<std::set<TagID>> _active_sc_var_coupleable_matrix_tags;
    1086             : 
    1087             :   std::vector<std::set<TagID>> _active_sc_var_coupleable_vector_tags;
    1088             : 
    1089             :   /// Whether or not to use default libMesh coupling
    1090             :   bool _default_ghosting;
    1091             : 
    1092             :   /// Elements that should have Dofs ghosted to the local processor
    1093             :   std::set<dof_id_type> _ghosted_elems;
    1094             : 
    1095             :   /// Flag to determine whether the problem is currently computing Jacobian
    1096             :   bool _currently_computing_jacobian;
    1097             : 
    1098             :   /// Flag to determine whether the problem is currently computing the residual and Jacobian
    1099             :   bool _currently_computing_residual_and_jacobian;
    1100             : 
    1101             :   /// Whether the non-linear residual is being evaluated
    1102             :   bool _computing_nonlinear_residual;
    1103             : 
    1104             :   /// Whether the residual is being evaluated
    1105             :   bool _currently_computing_residual;
    1106             : 
    1107             :   /// Is it safe to retrieve data from tagged matrices
    1108             :   bool _safe_access_tagged_matrices;
    1109             : 
    1110             :   /// Is it safe to retrieve data from tagged vectors
    1111             :   bool _safe_access_tagged_vectors;
    1112             : 
    1113             :   /// AD flag indicating whether **any** AD objects have been added
    1114             :   bool _have_ad_objects;
    1115             : 
    1116             :   /// the list of vector tags that will not be zeroed when all other tags are
    1117             :   std::unordered_set<TagID> _not_zeroed_tagged_vectors;
    1118             : 
    1119             : private:
    1120             :   /**
    1121             :    * @return whether a given variable name is in the solver systems (reflected by the first
    1122             :    * member of the returned pair which is a boolean) and if so, what solver system number it is
    1123             :    * in (the second member of the returned pair; if the variable is not in the solver systems,
    1124             :    * then this will be an invalid unsigned integer)
    1125             :    */
    1126             :   virtual std::pair<bool, unsigned int>
    1127             :   determineSolverSystem(const std::string & var_name, bool error_if_not_found = false) const = 0;
    1128             : 
    1129             :   enum class TrueFunctorIs
    1130             :   {
    1131             :     UNSET,
    1132             :     NONAD,
    1133             :     AD
    1134             :   };
    1135             : 
    1136             :   /// A container holding pointers to all the functors in our problem. We hold a tuple where the
    1137             :   /// zeroth item in the tuple is an enumerator that describes what type of functor the "true"
    1138             :   /// functor is (either NONAD or AD), the first item in the tuple is the non-AD version of the
    1139             :   /// functor, and the second item in the tuple is the AD version of the functor
    1140             :   std::vector<std::multimap<std::string,
    1141             :                             std::tuple<TrueFunctorIs,
    1142             :                                        std::unique_ptr<Moose::FunctorEnvelopeBase>,
    1143             :                                        std::unique_ptr<Moose::FunctorEnvelopeBase>>>>
    1144             :       _functors;
    1145             : 
    1146             :   /// Container to hold PiecewiseByBlockLambdaFunctors
    1147             :   std::vector<std::map<std::string, std::unique_ptr<Moose::FunctorAbstract>>> _pbblf_functors;
    1148             : 
    1149             :   /// Lists all functors in the problem
    1150             :   void showFunctors() const;
    1151             : 
    1152             :   /// Lists all functors and all the objects that requested them
    1153             :   void showFunctorRequestors() const;
    1154             : 
    1155             :   /// The requestors of functors where the key is the prop name and the value is a set of names of
    1156             :   /// requestors
    1157             :   std::map<std::string, std::set<std::string>> _functor_to_requestors;
    1158             : 
    1159             :   /// A multimap (for each thread) from unfilled functor requests to whether the requests were for
    1160             :   ///  AD functors and whether the requestor was an AD object
    1161             :   std::vector<std::multimap<std::string, std::pair<bool, bool>>> _functor_to_request_info;
    1162             : 
    1163             :   /// Whether to output a list of the functors used and requested (currently only at initialSetup)
    1164             :   bool _output_functors;
    1165             : 
    1166             :   /// The declared vector tags
    1167             :   std::vector<VectorTag> _vector_tags;
    1168             : 
    1169             :   /**
    1170             :    * The vector tags associated with each VectorTagType
    1171             :    * This is kept separate from _vector_tags for quick access into typed vector tags in places where
    1172             :    * we don't want to build a new vector every call (like in residual evaluation)
    1173             :    */
    1174             :   std::vector<std::vector<VectorTag>> _typed_vector_tags;
    1175             : 
    1176             :   /// Map of vector tag TagName to TagID
    1177             :   std::map<TagName, TagID> _vector_tags_name_map;
    1178             : 
    1179             :   ///@{ Helper functions for checking MaterialProperties
    1180             :   std::string restrictionSubdomainCheckName(SubdomainID check_id);
    1181             :   std::string restrictionBoundaryCheckName(BoundaryID check_id);
    1182             :   ///@}
    1183             : 
    1184             :   // Contains properties consumed by objects, see addConsumedPropertyName
    1185             :   std::map<MooseObjectName, std::set<std::string>> _consumed_material_properties;
    1186             : 
    1187             :   /// A map from a root algebraic ghosting functor, e.g. the ghosting functor passed into \p
    1188             :   /// removeAlgebraicGhostingFunctor, to its clones in other systems, e.g. systems other than system
    1189             :   /// 0
    1190             :   std::unordered_map<libMesh::GhostingFunctor *,
    1191             :                      std::vector<std::shared_ptr<libMesh::GhostingFunctor>>>
    1192             :       _root_alg_gf_to_sys_clones;
    1193             : 
    1194             :   /// A map from a root coupling ghosting functor, e.g. the ghosting functor passed into \p
    1195             :   /// removeCouplingGhostingFunctor, to its clones in other systems, e.g. systems other than system
    1196             :   /// 0
    1197             :   std::unordered_map<libMesh::GhostingFunctor *,
    1198             :                      std::vector<std::shared_ptr<libMesh::GhostingFunctor>>>
    1199             :       _root_coupling_gf_to_sys_clones;
    1200             : 
    1201             :   /// Whether p-refinement has been requested at any point during the simulation
    1202             :   bool _have_p_refinement;
    1203             : 
    1204             :   /// Indicate whether a family is disabled for p-refinement
    1205             :   std::unordered_map<FEFamily, bool> _family_for_p_refinement;
    1206             :   /// The set of variable families by default disable p-refinement
    1207             :   static const std::unordered_set<FEFamily> _default_families_without_p_refinement;
    1208             : 
    1209             :   friend class Restartable;
    1210             : };
    1211             : 
    1212             : template <typename T>
    1213             : const Moose::Functor<T> &
    1214       21844 : SubProblem::getFunctor(const std::string & name,
    1215             :                        const THREAD_ID tid,
    1216             :                        const std::string & requestor_name,
    1217             :                        const bool requestor_is_ad)
    1218             : {
    1219             :   mooseAssert(tid < _functors.size(), "Too large a thread ID");
    1220             : 
    1221             :   // Log the requestor
    1222       21844 :   _functor_to_requestors["wraps_" + name].insert(requestor_name);
    1223             : 
    1224       21844 :   constexpr bool requested_functor_is_ad =
    1225             :       !std::is_same<T, typename MetaPhysicL::RawType<T>::value_type>::value;
    1226             : 
    1227       21844 :   auto & functor_to_request_info = _functor_to_request_info[tid];
    1228             : 
    1229             :   // Get the requested functor if we already have it
    1230       21844 :   auto & functors = _functors[tid];
    1231       21844 :   if (auto find_ret = functors.find("wraps_" + name); find_ret != functors.end())
    1232             :   {
    1233       21706 :     if (functors.count("wraps_" + name) > 1)
    1234           0 :       mooseError("Attempted to get a functor with the name '",
    1235             :                  name,
    1236             :                  "' but multiple (" + std::to_string(functors.count("wraps_" + name)) +
    1237             :                      ") functors match. Make sure that you do not have functor material "
    1238             :                      "properties, functions, postprocessors or variables with the same names.");
    1239             : 
    1240       21706 :     auto & [true_functor_is, non_ad_functor, ad_functor] = find_ret->second;
    1241       21706 :     auto & functor_wrapper = requested_functor_is_ad ? *ad_functor : *non_ad_functor;
    1242             : 
    1243       21706 :     auto * const functor = dynamic_cast<Moose::Functor<T> *>(&functor_wrapper);
    1244       21706 :     if (!functor)
    1245           0 :       mooseError("A call to SubProblem::getFunctor requested a functor named '",
    1246             :                  name,
    1247             :                  "' that returns the type: '",
    1248             :                  libMesh::demangle(typeid(T).name()),
    1249             :                  "'. However, that functor already exists and returns a different type: '",
    1250           0 :                  functor_wrapper.returnType(),
    1251             :                  "'");
    1252             : 
    1253       21706 :     if (functor->template wrapsType<Moose::NullFunctor<T>>())
    1254             :       // Store for future checking when the actual functor gets added
    1255         247 :       functor_to_request_info.emplace(name,
    1256         494 :                                       std::make_pair(requested_functor_is_ad, requestor_is_ad));
    1257             :     else
    1258             :     {
    1259             :       // We already have the actual functor
    1260       21459 :       if (true_functor_is == SubProblem::TrueFunctorIs::UNSET)
    1261           0 :         mooseError("We already have the functor; it should not be unset");
    1262             : 
    1263             :       // Check for whether this is a valid request
    1264             :       // We allow auxiliary variables and linear variables to be retrieved as non AD
    1265       18958 :       if (!requested_functor_is_ad && requestor_is_ad &&
    1266        8861 :           true_functor_is == SubProblem::TrueFunctorIs::AD &&
    1267           4 :           !(hasAuxiliaryVariable(name) || hasLinearVariable(name)))
    1268           4 :         mooseError("The AD object '",
    1269             :                    requestor_name,
    1270             :                    "' is requesting the functor '",
    1271             :                    name,
    1272             :                    "' as a non-AD functor even though it is truly an AD functor, which is not "
    1273             :                    "allowed, since this may unintentionally drop derivatives.");
    1274             :     }
    1275             : 
    1276       21702 :     return *functor;
    1277             :   }
    1278             : 
    1279             :   // We don't have the functor yet but we could have it in the future. We'll create null functors
    1280             :   // for now
    1281         138 :   functor_to_request_info.emplace(name, std::make_pair(requested_functor_is_ad, requestor_is_ad));
    1282             :   if constexpr (requested_functor_is_ad)
    1283             :   {
    1284             :     typedef typename MetaPhysicL::RawType<T>::value_type NonADType;
    1285             :     typedef T ADType;
    1286             : 
    1287             :     auto emplace_ret =
    1288         132 :         functors.emplace("wraps_" + name,
    1289          88 :                          std::make_tuple(SubProblem::TrueFunctorIs::UNSET,
    1290             :                                          std::make_unique<Moose::Functor<NonADType>>(
    1291             :                                              std::make_unique<Moose::NullFunctor<NonADType>>()),
    1292             :                                          std::make_unique<Moose::Functor<ADType>>(
    1293             :                                              std::make_unique<Moose::NullFunctor<ADType>>())));
    1294             : 
    1295          44 :     return static_cast<Moose::Functor<T> &>(*(requested_functor_is_ad
    1296          44 :                                                   ? std::get<2>(emplace_ret->second)
    1297          44 :                                                   : std::get<1>(emplace_ret->second)));
    1298             :   }
    1299             :   else
    1300             :   {
    1301             :     typedef T NonADType;
    1302             :     typedef typename Moose::ADType<T>::type ADType;
    1303             : 
    1304             :     auto emplace_ret =
    1305         282 :         functors.emplace("wraps_" + name,
    1306         188 :                          std::make_tuple(SubProblem::TrueFunctorIs::UNSET,
    1307             :                                          std::make_unique<Moose::Functor<NonADType>>(
    1308             :                                              std::make_unique<Moose::NullFunctor<NonADType>>()),
    1309             :                                          std::make_unique<Moose::Functor<ADType>>(
    1310             :                                              std::make_unique<Moose::NullFunctor<ADType>>())));
    1311             : 
    1312          94 :     return static_cast<Moose::Functor<T> &>(*(requested_functor_is_ad
    1313             :                                                   ? std::get<2>(emplace_ret->second)
    1314         188 :                                                   : std::get<1>(emplace_ret->second)));
    1315             :   }
    1316             : }
    1317             : 
    1318             : template <typename T>
    1319             : bool
    1320         432 : SubProblem::hasFunctorWithType(const std::string & name, const THREAD_ID tid) const
    1321             : {
    1322             :   mooseAssert(tid < _functors.size(), "Too large a thread ID");
    1323         432 :   auto & functors = _functors[tid];
    1324             : 
    1325         432 :   const auto & it = functors.find("wraps_" + name);
    1326         432 :   constexpr bool requested_functor_is_ad =
    1327             :       !std::is_same<T, typename MetaPhysicL::RawType<T>::value_type>::value;
    1328             : 
    1329         432 :   if (it == functors.end())
    1330         240 :     return false;
    1331             :   else
    1332         192 :     return dynamic_cast<Moose::Functor<T> *>(
    1333         384 :         requested_functor_is_ad ? std::get<2>(it->second).get() : std::get<1>(it->second).get());
    1334             : }
    1335             : 
    1336             : template <typename T, typename PolymorphicLambda>
    1337             : const Moose::FunctorBase<T> &
    1338        8432 : SubProblem::addPiecewiseByBlockLambdaFunctor(const std::string & name,
    1339             :                                              PolymorphicLambda my_lammy,
    1340             :                                              const std::set<ExecFlagType> & clearance_schedule,
    1341             :                                              const MooseMesh & mesh,
    1342             :                                              const std::set<SubdomainID> & block_ids,
    1343             :                                              const THREAD_ID tid)
    1344             : {
    1345        8432 :   auto & pbblf_functors = _pbblf_functors[tid];
    1346             : 
    1347        8432 :   auto [it, first_time_added] =
    1348        8432 :       pbblf_functors.emplace(name,
    1349             :                              std::make_unique<PiecewiseByBlockLambdaFunctor<T>>(
    1350             :                                  name, my_lammy, clearance_schedule, mesh, block_ids));
    1351             : 
    1352        8432 :   auto * functor = dynamic_cast<PiecewiseByBlockLambdaFunctor<T> *>(it->second.get());
    1353        8432 :   if (!functor)
    1354             :   {
    1355           0 :     if (first_time_added)
    1356           0 :       mooseError("This should be impossible. If this was the first time we added the functor, then "
    1357             :                  "the dynamic cast absolutely should have succeeded");
    1358             :     else
    1359           0 :       mooseError("Attempted to add a lambda functor with the name '",
    1360             :                  name,
    1361             :                  "' but another lambda functor of that name returns a different type");
    1362             :   }
    1363             : 
    1364        8432 :   if (first_time_added)
    1365        7443 :     addFunctor(name, *functor, tid);
    1366             :   else
    1367             :     // The functor already exists
    1368         989 :     functor->setFunctor(mesh, block_ids, my_lammy);
    1369             : 
    1370        8428 :   return *functor;
    1371             : }
    1372             : 
    1373             : template <typename T>
    1374             : void
    1375      295276 : SubProblem::addFunctor(const std::string & name,
    1376             :                        const Moose::FunctorBase<T> & functor,
    1377             :                        const THREAD_ID tid)
    1378             : {
    1379      295276 :   constexpr bool added_functor_is_ad =
    1380             :       !std::is_same<T, typename MetaPhysicL::RawType<T>::value_type>::value;
    1381             : 
    1382             :   mooseAssert(tid < _functors.size(), "Too large a thread ID");
    1383             : 
    1384      295276 :   auto & functor_to_request_info = _functor_to_request_info[tid];
    1385      295276 :   auto & functors = _functors[tid];
    1386      295276 :   auto it = functors.find("wraps_" + name);
    1387      295276 :   if (it != functors.end())
    1388             :   {
    1389             :     // We have this functor already. If it's a null functor, we want to replace it with the valid
    1390             :     // functor we have now. If it's not then we'll add a new entry into the multimap and then we'll
    1391             :     // error later if a user requests a functor because their request is ambiguous. This is the
    1392             :     // reason that the functors container is a multimap: for nice error messages
    1393             :     auto * const existing_wrapper_base =
    1394        6265 :         added_functor_is_ad ? std::get<2>(it->second).get() : std::get<1>(it->second).get();
    1395        6265 :     auto * const existing_wrapper = dynamic_cast<Moose::Functor<T> *>(existing_wrapper_base);
    1396        6265 :     if (existing_wrapper && existing_wrapper->template wrapsType<Moose::NullFunctor<T>>())
    1397             :     {
    1398             :       // Sanity check
    1399         138 :       auto [request_info_it, request_info_end_it] = functor_to_request_info.equal_range(name);
    1400         138 :       if (request_info_it == request_info_end_it)
    1401           0 :         mooseError("We are wrapping a NullFunctor but we don't have any unfilled functor request "
    1402             :                    "info. This doesn't make sense.");
    1403             : 
    1404             :       // Check for valid requests
    1405         523 :       while (request_info_it != request_info_end_it)
    1406             :       {
    1407         385 :         auto & [requested_functor_is_ad, requestor_is_ad] = request_info_it->second;
    1408           5 :         if (!requested_functor_is_ad && requestor_is_ad && added_functor_is_ad)
    1409           0 :           mooseError("We are requesting a non-AD functor '" + name +
    1410             :                      "' from an AD object, but the true functor is AD. This means we could be "
    1411             :                      "dropping important derivatives. We will not allow this");
    1412             :         // We're going to eventually check whether we've fulfilled all functor requests and our
    1413             :         // check will be that the multimap is empty. This request is fulfilled, so erase it from the
    1414             :         // map now
    1415         385 :         request_info_it = functor_to_request_info.erase(request_info_it);
    1416             :       }
    1417             : 
    1418             :       // Ok we didn't have the functor before, so we will add it now
    1419         138 :       std::get<0>(it->second) =
    1420             :           added_functor_is_ad ? SubProblem::TrueFunctorIs::AD : SubProblem::TrueFunctorIs::NONAD;
    1421         138 :       existing_wrapper->assign(functor);
    1422             :       // Finally we create the non-AD or AD complement of the just added functor
    1423             :       if constexpr (added_functor_is_ad)
    1424             :       {
    1425             :         typedef typename MetaPhysicL::RawType<T>::value_type NonADType;
    1426           5 :         auto * const existing_non_ad_wrapper_base = std::get<1>(it->second).get();
    1427           5 :         auto * const existing_non_ad_wrapper =
    1428           5 :             dynamic_cast<Moose::Functor<NonADType> *>(existing_non_ad_wrapper_base);
    1429             :         mooseAssert(existing_non_ad_wrapper->template wrapsType<Moose::NullFunctor<NonADType>>(),
    1430             :                     "Both members of pair should have been wrapping a NullFunctor");
    1431           5 :         existing_non_ad_wrapper->assign(
    1432             :             std::make_unique<Moose::RawValueFunctor<NonADType>>(functor));
    1433             :       }
    1434             :       else
    1435             :       {
    1436             :         typedef typename Moose::ADType<T>::type ADType;
    1437         133 :         auto * const existing_ad_wrapper_base = std::get<2>(it->second).get();
    1438         133 :         auto * const existing_ad_wrapper =
    1439         133 :             dynamic_cast<Moose::Functor<ADType> *>(existing_ad_wrapper_base);
    1440             :         mooseAssert(existing_ad_wrapper->template wrapsType<Moose::NullFunctor<ADType>>(),
    1441             :                     "Both members of pair should have been wrapping a NullFunctor");
    1442         133 :         existing_ad_wrapper->assign(std::make_unique<Moose::ADWrapperFunctor<ADType>>(functor));
    1443             :       }
    1444         138 :       return;
    1445             :     }
    1446        6127 :     else if (!existing_wrapper)
    1447             :     {
    1448             :       // Functor was emplaced but the cast failed. This could be a double definition with
    1449             :       // different types, or it could be a request with one type then a definition with another
    1450             :       // type. Either way it is going to error later, but it is cleaner to catch it now
    1451           0 :       mooseError("Functor '",
    1452             :                  name,
    1453             :                  "' is being added with return type '",
    1454             :                  MooseUtils::prettyCppType<T>(),
    1455             :                  "' but it has already been defined or requested with return type '",
    1456           0 :                  existing_wrapper_base->returnType(),
    1457             :                  "'.");
    1458             :     }
    1459             :   }
    1460             : 
    1461             :   // We are a new functor, create the opposite ADType one and store it with other functors
    1462             :   if constexpr (added_functor_is_ad)
    1463             :   {
    1464             :     typedef typename MetaPhysicL::RawType<T>::value_type NonADType;
    1465      176474 :     auto new_non_ad_wrapper = std::make_unique<Moose::Functor<NonADType>>(
    1466             :         std::make_unique<Moose::RawValueFunctor<NonADType>>(functor));
    1467      176474 :     auto new_ad_wrapper = std::make_unique<Moose::Functor<T>>(functor);
    1468      352948 :     _functors[tid].emplace("wraps_" + name,
    1469      176474 :                            std::make_tuple(SubProblem::TrueFunctorIs::AD,
    1470      176474 :                                            std::move(new_non_ad_wrapper),
    1471      176474 :                                            std::move(new_ad_wrapper)));
    1472      176474 :   }
    1473             :   else
    1474             :   {
    1475             :     typedef typename Moose::ADType<T>::type ADType;
    1476      118664 :     auto new_non_ad_wrapper = std::make_unique<Moose::Functor<T>>((functor));
    1477      118664 :     auto new_ad_wrapper = std::make_unique<Moose::Functor<ADType>>(
    1478             :         std::make_unique<Moose::ADWrapperFunctor<ADType>>(functor));
    1479      237328 :     _functors[tid].emplace("wraps_" + name,
    1480      118664 :                            std::make_tuple(SubProblem::TrueFunctorIs::NONAD,
    1481      118664 :                                            std::move(new_non_ad_wrapper),
    1482      118664 :                                            std::move(new_ad_wrapper)));
    1483      118664 :   }
    1484             : }
    1485             : 
    1486             : inline const bool &
    1487      294699 : SubProblem::currentlyComputingResidualAndJacobian() const
    1488             : {
    1489      294699 :   return _currently_computing_residual_and_jacobian;
    1490             : }
    1491             : 
    1492             : inline void
    1493     3683624 : SubProblem::setCurrentlyComputingResidualAndJacobian(
    1494             :     const bool currently_computing_residual_and_jacobian)
    1495             : {
    1496     3683624 :   _currently_computing_residual_and_jacobian = currently_computing_residual_and_jacobian;
    1497     3683624 : }
    1498             : 
    1499             : namespace Moose
    1500             : {
    1501             : void initial_condition(libMesh::EquationSystems & es, const std::string & system_name);
    1502             : } // namespace Moose

Generated by: LCOV version 1.14