LCOV - code coverage report
Current view: top level - include/base - MooseFunctor.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 242 335 72.2 %
Date: 2025-07-17 01:28:37 Functions: 349 969 36.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 <tuple>
      13             : 
      14             : #include "MooseFunctorForward.h"
      15             : #include "MooseFunctorArguments.h"
      16             : #include "FaceArgInterface.h"
      17             : #include "MooseMesh.h"
      18             : #include "MooseTypes.h"
      19             : #include "MooseError.h"
      20             : #include "MooseUtils.h"
      21             : 
      22             : #include "libmesh/remote_elem.h"
      23             : #include "libmesh/tensor_tools.h"
      24             : 
      25             : #include "metaphysicl/ct_types.h"
      26             : 
      27             : #include <unordered_map>
      28             : #include <functional>
      29             : 
      30             : namespace Moose
      31             : {
      32             : /**
      33             :  * An enumeration of possible functor evaluation kinds. The available options are value, gradient,
      34             :  * time derivative (dot), and gradient of time derivative (gradDot)
      35             :  */
      36             : enum class FunctorEvaluationKind
      37             : {
      38             :   Value,
      39             :   Gradient,
      40             :   Dot,
      41             :   GradDot
      42             : };
      43             : 
      44             : /**
      45             :  * A structure that defines the return type of a functor based on the type of the functor and the
      46             :  * requested evaluation kind, e.g. value, gradient, time derivative, or gradient of time derivative
      47             :  */
      48             : template <typename, FunctorEvaluationKind>
      49             : struct FunctorReturnType;
      50             : 
      51             : /**
      52             :  * The return type for a value evaluation is just the type of the functor
      53             :  */
      54             : template <typename T>
      55             : struct FunctorReturnType<T, FunctorEvaluationKind::Value>
      56             : {
      57             :   typedef T type;
      58             : };
      59             : 
      60             : /**
      61             :  * The return type of a gradient evaluation is the rank increment of a value return type. So if the
      62             :  * value type is Real, then a gradient will be a VectorValue<Real>. This also allows for containers
      63             :  * of mathematical types. So if a value type is std::vector<Real>, then the gradient type will be
      64             :  * std::vector<VectorValue<Real>>
      65             :  */
      66             : template <typename T>
      67             : struct FunctorReturnType<T, FunctorEvaluationKind::Gradient>
      68             : {
      69             :   typedef typename MetaPhysicL::ReplaceAlgebraicType<
      70             :       T,
      71             :       typename libMesh::TensorTools::IncrementRank<
      72             :           typename MetaPhysicL::ValueType<T>::type>::type>::type type;
      73             : };
      74             : 
      75             : /**
      76             :  * The return type of a time derivative evaluation is the same as the value type
      77             :  */
      78             : template <typename T>
      79             : struct FunctorReturnType<T, FunctorEvaluationKind::Dot>
      80             : {
      81             :   typedef T type;
      82             : };
      83             : 
      84             : /**
      85             :  * The return type of a gradient of time derivative evaluation is the same as the gradient type
      86             :  */
      87             : template <typename T>
      88             : struct FunctorReturnType<T, FunctorEvaluationKind::GradDot>
      89             : {
      90             :   typedef typename FunctorReturnType<T, FunctorEvaluationKind::Gradient>::type type;
      91             : };
      92             : 
      93             : /**
      94             :  * This structure takes an evaluation kind as a template argument and defines a constant expression
      95             :  * indicating the associated gradient kind
      96             :  */
      97             : template <FunctorEvaluationKind>
      98             : struct FunctorGradientEvaluationKind;
      99             : 
     100             : /**
     101             :  * The gradient kind associated with a value is simply the gradient
     102             :  */
     103             : template <>
     104             : struct FunctorGradientEvaluationKind<FunctorEvaluationKind::Value>
     105             : {
     106             :   static constexpr FunctorEvaluationKind value = FunctorEvaluationKind::Gradient;
     107             : };
     108             : 
     109             : /**
     110             :  * The gradient kind associated with a time derivative is the gradient of the time derivative
     111             :  */
     112             : template <>
     113             : struct FunctorGradientEvaluationKind<FunctorEvaluationKind::Dot>
     114             : {
     115             :   static constexpr FunctorEvaluationKind value = FunctorEvaluationKind::GradDot;
     116             : };
     117             : 
     118             : /**
     119             :  * Abstract base class that can be used to hold collections of functors
     120             :  */
     121             : class FunctorAbstract : public FaceArgInterface
     122             : {
     123             : public:
     124             :   virtual void residualSetup() = 0;
     125             :   virtual void jacobianSetup() = 0;
     126             :   virtual void timestepSetup() = 0;
     127             :   virtual void customSetup(const ExecFlagType & exec_type) = 0;
     128             : };
     129             : 
     130             : /**
     131             :  * Base class template for functor objects. This class template defines various \p operator()
     132             :  * overloads that allow a user to evaluate the functor at arbitrary geometric locations. This
     133             :  * template is meant to enable highly flexible on-the-fly variable and material property
     134             :  * evaluations
     135             :  */
     136             : template <typename T>
     137             : class FunctorBase : public FunctorAbstract
     138             : {
     139             : public:
     140             :   using FunctorType = FunctorBase<T>;
     141             :   using ValueType = T;
     142             :   /// This rigmarole makes it so that a user can create functors that return containers (std::vector,
     143             :   /// std::array). This logic will make it such that if a user requests a functor type T that is a
     144             :   /// container of algebraic types, for example Reals, then the GradientType will be a container of
     145             :   /// the gradients of those algebraic types, in this example VectorValue<Reals>. So if T is
     146             :   /// std::vector<Real>, then GradientType will be std::vector<VectorValue<Real>>. As another
     147             :   /// example: T = std::array<VectorValue<Real>, 1> -> GradientType = std::array<TensorValue<Real>,
     148             :   /// 1>
     149             :   using GradientType = typename FunctorReturnType<T, FunctorEvaluationKind::Gradient>::type;
     150             :   using DotType = ValueType;
     151             : 
     152     1123946 :   virtual ~FunctorBase() = default;
     153     1196822 :   FunctorBase(const MooseFunctorName & name,
     154             :               const std::set<ExecFlagType> & clearance_schedule = {EXEC_ALWAYS})
     155     1196822 :     : _always_evaluate(true), _functor_name(name)
     156             : 
     157             :   {
     158     1196822 :     setCacheClearanceSchedule(clearance_schedule);
     159     1196822 :   }
     160             : 
     161             :   /**
     162             :    * Perform a generic evaluation based on the supplied template argument \p FET and supplied
     163             :    * spatial and temporal arguments
     164             :    */
     165             :   template <FunctorEvaluationKind FET, typename Space, typename State>
     166             :   typename FunctorReturnType<T, FET>::type genericEvaluate(const Space & r,
     167             :                                                            const State & state) const;
     168             : 
     169             :   /// Return the functor name
     170      893729 :   const MooseFunctorName & functorName() const { return _functor_name; }
     171             : 
     172             :   ///@{
     173             :   /**
     174             :    * Same as their \p evaluate overloads with the same arguments but allows for caching
     175             :    * implementation. These are the methods a user will call in their code
     176             :    */
     177             :   ValueType operator()(const ElemArg & elem, const StateArg & state) const;
     178             :   ValueType operator()(const FaceArg & face, const StateArg & state) const;
     179             :   ValueType operator()(const ElemQpArg & qp, const StateArg & state) const;
     180             :   ValueType operator()(const ElemSideQpArg & qp, const StateArg & state) const;
     181             :   ValueType operator()(const ElemPointArg & elem_point, const StateArg & state) const;
     182             :   ValueType operator()(const NodeArg & node, const StateArg & state) const;
     183             :   ///@}
     184             : 
     185             :   ///@{
     186             :   /**
     187             :    * Same as their \p evaluateGradient overloads with the same arguments but allows for caching
     188             :    * implementation. These are the methods a user will call in their code
     189             :    */
     190             :   GradientType gradient(const ElemArg & elem, const StateArg & state) const;
     191             :   GradientType gradient(const FaceArg & face, const StateArg & state) const;
     192             :   GradientType gradient(const ElemQpArg & qp, const StateArg & state) const;
     193             :   GradientType gradient(const ElemSideQpArg & qp, const StateArg & state) const;
     194             :   GradientType gradient(const ElemPointArg & elem_point, const StateArg & state) const;
     195             :   GradientType gradient(const NodeArg & node, const StateArg & state) const;
     196             :   ///@}
     197             : 
     198             :   ///@{
     199             :   /**
     200             :    * Same as their \p evaluateDot overloads with the same arguments but allows for caching
     201             :    * implementation. These are the methods a user will call in their code
     202             :    */
     203             :   DotType dot(const ElemArg & elem, const StateArg & state) const;
     204             :   DotType dot(const FaceArg & face, const StateArg & state) const;
     205             :   DotType dot(const ElemQpArg & qp, const StateArg & state) const;
     206             :   DotType dot(const ElemSideQpArg & qp, const StateArg & state) const;
     207             :   DotType dot(const ElemPointArg & elem_point, const StateArg & state) const;
     208             :   DotType dot(const NodeArg & node, const StateArg & state) const;
     209             :   ///@}
     210             : 
     211             :   ///@{
     212             :   /**
     213             :    * Same as their \p evaluateGradDot overloads with the same arguments but allows for caching
     214             :    * implementation. These are the methods a user will call in their code
     215             :    */
     216             :   GradientType gradDot(const ElemArg & elem, const StateArg & state) const;
     217             :   GradientType gradDot(const FaceArg & face, const StateArg & state) const;
     218             :   GradientType gradDot(const ElemQpArg & qp, const StateArg & state) const;
     219             :   GradientType gradDot(const ElemSideQpArg & qp, const StateArg & state) const;
     220             :   GradientType gradDot(const ElemPointArg & elem_point, const StateArg & state) const;
     221             :   GradientType gradDot(const NodeArg & node, const StateArg & state) const;
     222             :   ///@}
     223             : 
     224             :   virtual void residualSetup() override;
     225             :   virtual void jacobianSetup() override;
     226             :   virtual void timestepSetup() override;
     227             :   virtual void customSetup(const ExecFlagType & exec_type) override;
     228             : 
     229             :   /**
     230             :    * Set how often to clear the functor evaluation cache
     231             :    */
     232             :   void setCacheClearanceSchedule(const std::set<ExecFlagType> & clearance_schedule);
     233             : 
     234             :   /**
     235             :    * Returns whether the functor is defined on this block
     236             :    */
     237           0 :   virtual bool hasBlocks(SubdomainID /* id */) const
     238             :   {
     239           0 :     mooseError("Block restriction has not been implemented for functor " + functorName());
     240             :     return false;
     241             :   }
     242             : 
     243             :   /**
     244             :    * Returns whether this (sided) face is an extrapolated boundary face for
     245             :    * this functor
     246             :    */
     247           0 :   virtual bool isExtrapolatedBoundaryFace(const FaceInfo &, const Elem *, const StateArg &) const
     248             :   {
     249           0 :     mooseError("not implemented");
     250             :   }
     251             : 
     252             :   /**
     253             :    * Returns true if the face is an internal face
     254             :    */
     255             :   bool isInternalFace(const FaceInfo &) const;
     256             : 
     257             :   /**
     258             :    * Returns true if this functor is a constant
     259             :    */
     260           0 :   virtual bool isConstant() const { return false; }
     261             : 
     262             :   virtual bool hasFaceSide(const FaceInfo & fi, const bool fi_elem_side) const override;
     263             : 
     264             :   /**
     265             :    * Examines the incoming face argument. If the face argument producer (residual object,
     266             :    * postprocessor, etc.) did not indicate a sidedness to the face, e.g. if the \p face_side member
     267             :    * of the \p FaceArg is \p nullptr, then we may "modify" the sidedness of the argument if we are
     268             :    * only defined on one side of the face. If the face argument producer \emph has indicated a
     269             :    * sidedness and we are not defined on that side, then we will error
     270             :    * @param face The face argument created by the face argument producer, likely a residual object
     271             :    * @return A face with possibly changed sidedness depending on whether we aren't defined on both
     272             :    * sides of the face
     273             :    */
     274             :   void checkFace(const Moose::FaceArg & face) const;
     275             : 
     276             :   /**
     277             :    * Whether this functor supports evaluation with FaceArg
     278             :    */
     279             :   virtual bool supportsFaceArg() const = 0;
     280             : 
     281             :   /**
     282             :    * Whether this functor supports evaluation with ElemSideQpArg
     283             :    */
     284             :   virtual bool supportsElemSideQpArg() const = 0;
     285             : 
     286             : protected:
     287             :   /** @name Functor evaluation routines
     288             :    * These methods are all for evaluating functors with different kinds of spatial arguments. Each
     289             :    * of these methods also takes a state argument. For a description of the state argument, please
     290             :    * see the \p StateArg doxygen
     291             :    */
     292             :   ///@{
     293             :   /**
     294             :    * Evaluate the functor with a given element. Some example implementations of this method
     295             :    * could compute an element-average or evaluate at the element centroid
     296             :    */
     297             :   virtual ValueType evaluate(const ElemArg & elem, const StateArg & state) const = 0;
     298             : 
     299             :   /**
     300             :    * @param face See the \p FaceArg doxygen
     301             :    * @param state See the \p StateArg doxygen
     302             :    * @return The functor evaluated at the requested state and space
     303             :    */
     304             :   virtual ValueType evaluate(const FaceArg & face, const StateArg & state) const = 0;
     305             : 
     306             :   /**
     307             :    * @param qp See the \p ElemQpArg doxygen
     308             :    * @param state See the \p StateArg doxygen
     309             :    * @return The functor evaluated at the requested state and space
     310             :    */
     311             :   virtual ValueType evaluate(const ElemQpArg & qp, const StateArg & state) const = 0;
     312             : 
     313             :   /**
     314             :    * @param side_qp See the \p ElemSideQpArg doxygen
     315             :    * @param state See the \p StateArg doxygen
     316             :    * @return The functor evaluated at the requested state and space
     317             :    */
     318             :   virtual ValueType evaluate(const ElemSideQpArg & side_qp, const StateArg & state) const = 0;
     319             : 
     320             :   /**
     321             :    * Evaluate the functor with a given element and point. Some example implementations of this
     322             :    * method could perform a two-term Taylor expansion using cell-centered value and gradient
     323             :    */
     324             :   virtual ValueType evaluate(const ElemPointArg & elem_point, const StateArg & state) const = 0;
     325             : 
     326             :   virtual ValueType evaluate(const NodeArg & node, const StateArg & state) const = 0;
     327             : 
     328             :   /**
     329             :    * Evaluate the functor gradient with a given element. Some example implementations of this
     330             :    * method could compute an element-average or evaluate at the element centroid
     331             :    */
     332           1 :   virtual GradientType evaluateGradient(const ElemArg &, const StateArg &) const
     333             :   {
     334           1 :     mooseError("Element gradient not implemented for functor " + functorName());
     335             :   }
     336             : 
     337             :   /**
     338             :    * @param face See the \p FaceArg doxygen
     339             :    * @param state See the \p StateArg doxygen
     340             :    * @return The functor gradient evaluated at the requested state and space
     341             :    */
     342           1 :   virtual GradientType evaluateGradient(const FaceArg &, const StateArg &) const
     343             :   {
     344           1 :     mooseError("Face gradient not implemented for functor " + functorName());
     345             :   }
     346             : 
     347             :   /**
     348             :    * @param qp See the \p ElemQpArg doxygen
     349             :    * @param state See the \p StateArg doxygen
     350             :    * @return The functor gradient evaluated at the requested state and space
     351             :    */
     352           1 :   virtual GradientType evaluateGradient(const ElemQpArg &, const StateArg &) const
     353             :   {
     354           1 :     mooseError("Element quadrature point gradient not implemented for functor " + functorName());
     355             :   }
     356             : 
     357             :   /**
     358             :    * @param side_qp See the \p ElemSideQpArg doxygen
     359             :    * @param state See the \p StateArg doxygen
     360             :    * @return The functor gradient evaluated at the requested state and space
     361             :    */
     362           1 :   virtual GradientType evaluateGradient(const ElemSideQpArg &, const StateArg &) const
     363             :   {
     364           1 :     mooseError("Element side quadrature point gradient not implemented for functor " +
     365           1 :                functorName());
     366             :   }
     367             : 
     368             :   /**
     369             :    * Evaluate the functor gradient with a given element and point
     370             :    */
     371           1 :   virtual GradientType evaluateGradient(const ElemPointArg &, const StateArg &) const
     372             :   {
     373           1 :     mooseError("Element-point gradient not implemented for functor " + functorName());
     374             :   }
     375             : 
     376           1 :   virtual GradientType evaluateGradient(const NodeArg &, const StateArg &) const
     377             :   {
     378           1 :     mooseError("Gradient at node not implemented for functor " + functorName());
     379             :   }
     380             : 
     381             :   /**
     382             :    * Evaluate the functor time derivative with a given element. Some example implementations of
     383             :    * this method could compute an element-average or evaluate at the element centroid
     384             :    */
     385           1 :   virtual DotType evaluateDot(const ElemArg &, const StateArg &) const
     386             :   {
     387           1 :     mooseError("Element time derivative not implemented for functor " + functorName());
     388             :   }
     389             : 
     390             :   /**
     391             :    * @param face See the \p FaceArg doxygen
     392             :    * @param state See the \p StateArg doxygen
     393             :    * @return The functor time derivative evaluated at the requested state and space
     394             :    */
     395           1 :   virtual DotType evaluateDot(const FaceArg &, const StateArg &) const
     396             :   {
     397           1 :     mooseError("Face time derivative not implemented for functor " + functorName());
     398             :   }
     399             : 
     400             :   /**
     401             :    * @param qp See the \p ElemQpArg doxygen
     402             :    * @param state See the \p StateArg doxygen
     403             :    * @return The functor time derivative evaluated at the requested state and space
     404             :    */
     405           4 :   virtual DotType evaluateDot(const ElemQpArg &, const StateArg &) const
     406             :   {
     407           4 :     mooseError("Element quadrature point time derivative not implemented for functor " +
     408           4 :                functorName());
     409             :   }
     410             : 
     411             :   /**
     412             :    * @param side_qp See the \p ElemSideQpArg doxygen
     413             :    * @param state See the \p StateArg doxygen
     414             :    * @return The functor time derivative evaluated at the requested state and space
     415             :    */
     416           1 :   virtual DotType evaluateDot(const ElemSideQpArg &, const StateArg &) const
     417             :   {
     418           1 :     mooseError("Element side quadrature point time derivative not implemented for functor " +
     419           1 :                functorName());
     420             :   }
     421             : 
     422             :   /**
     423             :    * Evaluate the functor time derivative with a given element and point
     424             :    */
     425           1 :   virtual DotType evaluateDot(const ElemPointArg &, const StateArg &) const
     426             :   {
     427           1 :     mooseError("Element-point time derivative not implemented for functor " + functorName());
     428             :   }
     429             : 
     430           1 :   virtual DotType evaluateDot(const NodeArg &, const StateArg &) const
     431             :   {
     432           1 :     mooseError("Time derivative at node not implemented for functor " + functorName());
     433             :   }
     434             : 
     435             :   /**
     436             :    * Evaluate the functor gradient-dot with a given element. Some example implementations of this
     437             :    * method could compute an element-average or evaluate at the element centroid
     438             :    */
     439           0 :   virtual GradientType evaluateGradDot(const ElemArg &, const StateArg &) const
     440             :   {
     441           0 :     mooseError("Element gradient-dot not implemented for functor " + functorName());
     442             :   }
     443             : 
     444             :   /**
     445             :    * @param face See the \p FaceArg doxygen
     446             :    * @param state See the \p StateArg doxygen
     447             :    * @return The functor gradient-dot evaluated at the requested state and space
     448             :    */
     449           0 :   virtual GradientType evaluateGradDot(const FaceArg &, const StateArg &) const
     450             :   {
     451           0 :     mooseError("Face gradient-dot not implemented for functor " + functorName());
     452             :   }
     453             : 
     454             :   /**
     455             :    * @param qp See the \p ElemQpArg doxygen
     456             :    * @param state See the \p StateArg doxygen
     457             :    * @return The functor gradient-dot evaluated at the requested state and space
     458             :    */
     459           0 :   virtual GradientType evaluateGradDot(const ElemQpArg &, const StateArg &) const
     460             :   {
     461           0 :     mooseError("Element quadrature point gradient-dot not implemented for functor " +
     462           0 :                functorName());
     463             :   }
     464             : 
     465             :   /**
     466             :    * @param side_qp See the \p ElemSideQpArg doxygen
     467             :    * @param state See the \p StateArg doxygen
     468             :    * @return The functor gradient-dot evaluated at the requested state and space
     469             :    */
     470           0 :   virtual GradientType evaluateGradDot(const ElemSideQpArg &, const StateArg &) const
     471             :   {
     472           0 :     mooseError("Element side quadrature point gradient-dot not implemented for functor " +
     473           0 :                functorName());
     474             :   }
     475             : 
     476             :   /**
     477             :    * Evaluate the functor gradient-dot with a given element and point
     478             :    */
     479           0 :   virtual GradientType evaluateGradDot(const ElemPointArg &, const StateArg &) const
     480             :   {
     481           0 :     mooseError("Element-point gradient-dot not implemented for functor " + functorName());
     482             :   }
     483             : 
     484           0 :   virtual GradientType evaluateGradDot(const NodeArg &, const StateArg &) const
     485             :   {
     486           0 :     mooseError("Gradient-dot at node not implemented for functor " + functorName());
     487             :   }
     488             :   ///@}
     489             : 
     490             : private:
     491             :   /**
     492             :    * clear cache data
     493             :    */
     494             :   void clearCacheData();
     495             : 
     496             :   /**
     497             :    * check a qp cache and if invalid then evaluate
     498             :    */
     499             :   template <typename SpaceArg, typename StateArg>
     500             :   ValueType queryQpCache(unsigned int qp,
     501             :                          const libMesh::QBase & qrule,
     502             :                          std::vector<std::pair<bool, T>> & qp_cache_data,
     503             :                          const SpaceArg & space,
     504             :                          const StateArg & state) const;
     505             : 
     506             :   /**
     507             :    * check a finite volume spatial argument cache and if invalid then evaluate
     508             :    */
     509             :   template <typename SpaceArg>
     510             :   ValueType queryFVArgCache(std::map<SpaceArg, ValueType> & cache_data,
     511             :                             const SpaceArg & space) const;
     512             : 
     513             :   /// How often to clear the material property cache
     514             :   std::set<ExecFlagType> _clearance_schedule;
     515             : 
     516             :   /// Boolean to check if we always need evaluation
     517             :   bool _always_evaluate;
     518             : 
     519             :   // Data for traditional element-quadrature point property evaluations which are useful for
     520             :   // caching implementation
     521             : 
     522             :   /// Current key for qp map cache
     523             :   mutable dof_id_type _current_qp_map_key = libMesh::DofObject::invalid_id;
     524             : 
     525             :   /// Current value for qp map cache
     526             :   mutable std::vector<std::pair<bool, ValueType>> * _current_qp_map_value = nullptr;
     527             : 
     528             :   /// Cached element quadrature point functor property evaluations. The map key is the element
     529             :   /// id. The map values should have size corresponding to the number of quadrature points on the
     530             :   /// element. The vector elements are pairs. The first member of the pair indicates whether a
     531             :   /// cached value has been computed. The second member of the pair is the (cached) value. If the
     532             :   /// boolean is false, then the value cannot be trusted
     533             :   mutable std::unordered_map<dof_id_type, std::vector<std::pair<bool, ValueType>>> _qp_to_value;
     534             : 
     535             :   // Data for traditional element-side-quadrature point property evaluations which are useful for
     536             :   // caching implementation
     537             : 
     538             :   /// Current key for side-qp map cache
     539             :   mutable dof_id_type _current_side_qp_map_key = libMesh::DofObject::invalid_id;
     540             : 
     541             :   /// Current value for side-qp map cache
     542             :   mutable std::vector<std::vector<std::pair<bool, ValueType>>> * _current_side_qp_map_value =
     543             :       nullptr;
     544             : 
     545             :   /// Cached element quadrature point functor property evaluations. The map key is the element
     546             :   /// id. The map values are a multi-dimensional vector (or vector of vectors) with the first index
     547             :   /// corresponding to the side and the second index corresponding to the quadrature point
     548             :   /// index. The elements returned after double indexing are pairs. The first member of the pair
     549             :   /// indicates whether a cached value has been computed. The second member of the pair is the
     550             :   /// (cached) value. If the boolean is false, then the value cannot be trusted
     551             :   mutable std::unordered_map<dof_id_type, std::vector<std::vector<std::pair<bool, ValueType>>>>
     552             :       _side_qp_to_value;
     553             : 
     554             :   /// Map from element arguments to their cached evaluations
     555             :   mutable std::map<ElemArg, ValueType> _elem_arg_to_value;
     556             : 
     557             :   /// Map from face arguments to their cached evaluations
     558             :   mutable std::map<FaceArg, ValueType> _face_arg_to_value;
     559             : 
     560             :   /// Map from nodal arguments to their cached evaluations
     561             :   mutable std::map<NodeArg, ValueType> _node_arg_to_value;
     562             : 
     563             :   /// name of the functor
     564             :   MooseFunctorName _functor_name;
     565             : };
     566             : 
     567             : template <typename T>
     568             : bool
     569   204495827 : FunctorBase<T>::isInternalFace(const FaceInfo & fi) const
     570             : {
     571   204495827 :   if (!fi.neighborPtr())
     572     4109443 :     return false;
     573             : 
     574   200386384 :   return hasBlocks(fi.elem().subdomain_id()) && hasBlocks(fi.neighborPtr()->subdomain_id());
     575             : }
     576             : 
     577             : template <typename T>
     578             : template <typename SpaceArg>
     579             : typename FunctorBase<T>::ValueType
     580           0 : FunctorBase<T>::queryFVArgCache(std::map<SpaceArg, ValueType> & cache_data,
     581             :                                 const SpaceArg & space) const
     582             : {
     583             :   // We don't want to evaluate if the key already exists, so instead we value initialize
     584           0 :   auto [it, inserted] = cache_data.try_emplace(space, ValueType());
     585           0 :   auto & value = it->second;
     586             : 
     587           0 :   if (inserted)
     588             :     // value not ready to go
     589             :     // this function is only called from functions that assert we are in the current time state
     590           0 :     value = evaluate(space, currentState());
     591             : 
     592           0 :   return value;
     593             : }
     594             : 
     595             : template <typename T>
     596             : typename FunctorBase<T>::ValueType
     597   273544167 : FunctorBase<T>::operator()(const ElemArg & elem, const StateArg & state) const
     598             : {
     599   273544167 :   if (_always_evaluate)
     600   273544167 :     return evaluate(elem, state);
     601             : 
     602             :   mooseAssert(state.state == 0,
     603             :               "Cached evaluations are only currently supported for the current state.");
     604             : 
     605           0 :   return queryFVArgCache(_elem_arg_to_value, elem);
     606             : }
     607             : 
     608             : template <typename T>
     609             : typename FunctorBase<T>::ValueType
     610    92015400 : FunctorBase<T>::operator()(const FaceArg & face_in, const StateArg & state) const
     611             : {
     612    92015400 :   checkFace(face_in);
     613             : 
     614    92015400 :   if (_always_evaluate)
     615    92015400 :     return evaluate(face_in, state);
     616             : 
     617             :   mooseAssert(state.state == 0,
     618             :               "Cached evaluations are only currently supported for the current state.");
     619             : 
     620           0 :   return queryFVArgCache(_face_arg_to_value, face_in);
     621             : }
     622             : 
     623             : template <typename T>
     624             : template <typename SpaceArg, typename StateArg>
     625             : typename FunctorBase<T>::ValueType
     626           0 : FunctorBase<T>::queryQpCache(const unsigned int qp,
     627             :                              const libMesh::QBase & qrule,
     628             :                              std::vector<std::pair<bool, ValueType>> & qp_cache_data,
     629             :                              const SpaceArg & space,
     630             :                              const StateArg & state) const
     631             : {
     632             :   // Check and see whether we even have sized for this quadrature point. If we haven't then we
     633             :   // must evaluate
     634           0 :   if (qp >= qp_cache_data.size())
     635             :   {
     636           0 :     qp_cache_data.resize(qrule.n_points(), std::make_pair(false, ValueType()));
     637           0 :     auto & pr = qp_cache_data[qp];
     638           0 :     pr.second = evaluate(space, state);
     639           0 :     pr.first = true;
     640           0 :     return pr.second;
     641             :   }
     642             : 
     643             :   // We've already sized for this qp, so let's see whether we have a valid cache value
     644           0 :   auto & pr = qp_cache_data[qp];
     645           0 :   if (pr.first)
     646           0 :     return pr.second;
     647             : 
     648             :   // No valid cache value so evaluate
     649           0 :   pr.second = evaluate(space, state);
     650           0 :   pr.first = true;
     651           0 :   return pr.second;
     652             : }
     653             : 
     654             : template <typename T>
     655             : typename FunctorBase<T>::ValueType
     656    32739469 : FunctorBase<T>::operator()(const ElemQpArg & elem_qp, const StateArg & state) const
     657             : {
     658    32739469 :   if (_always_evaluate)
     659    32739469 :     return evaluate(elem_qp, state);
     660             : 
     661           0 :   const auto elem_id = elem_qp.elem->id();
     662           0 :   if (elem_id != _current_qp_map_key)
     663             :   {
     664           0 :     _current_qp_map_key = elem_id;
     665           0 :     _current_qp_map_value = &_qp_to_value[elem_id];
     666             :   }
     667           0 :   auto & qp_data = *_current_qp_map_value;
     668           0 :   const auto qp = elem_qp.qp;
     669           0 :   const auto * const qrule = elem_qp.qrule;
     670             :   mooseAssert(qrule, "qrule must be non-null");
     671             : 
     672           0 :   return queryQpCache(qp, *qrule, qp_data, elem_qp, state);
     673             : }
     674             : 
     675             : template <typename T>
     676             : typename FunctorBase<T>::ValueType
     677     1890590 : FunctorBase<T>::operator()(const ElemSideQpArg & elem_side_qp, const StateArg & state) const
     678             : {
     679     1890590 :   if (_always_evaluate)
     680     1890590 :     return evaluate(elem_side_qp, state);
     681             : 
     682           0 :   const Elem * const elem = elem_side_qp.elem;
     683             :   mooseAssert(elem, "elem must be non-null");
     684           0 :   const auto elem_id = elem->id();
     685           0 :   if (elem_id != _current_side_qp_map_key)
     686             :   {
     687           0 :     _current_side_qp_map_key = elem_id;
     688           0 :     _current_side_qp_map_value = &_side_qp_to_value[elem_id];
     689             :   }
     690           0 :   auto & side_qp_data = *_current_side_qp_map_value;
     691           0 :   const auto side = elem_side_qp.side;
     692           0 :   const auto qp = elem_side_qp.qp;
     693           0 :   const auto * const qrule = elem_side_qp.qrule;
     694             :   mooseAssert(qrule, "qrule must be non-null");
     695             : 
     696             :   // Check and see whether we even have sized for this side
     697           0 :   if (side >= side_qp_data.size())
     698           0 :     side_qp_data.resize(elem->n_sides());
     699             : 
     700             :   // Ok we were sized enough for our side
     701           0 :   auto & qp_data = side_qp_data[side];
     702           0 :   return queryQpCache(qp, *qrule, qp_data, elem_side_qp, state);
     703             : }
     704             : 
     705             : template <typename T>
     706             : typename FunctorBase<T>::ValueType
     707       36605 : FunctorBase<T>::operator()(const ElemPointArg & elem_point, const StateArg & state) const
     708             : {
     709       36605 :   return evaluate(elem_point, state);
     710             : }
     711             : 
     712             : template <typename T>
     713             : void
     714     1196822 : FunctorBase<T>::setCacheClearanceSchedule(const std::set<ExecFlagType> & clearance_schedule)
     715             : {
     716     1196822 :   if (clearance_schedule.count(EXEC_ALWAYS))
     717     1196337 :     _always_evaluate = true;
     718             : 
     719     1196822 :   _clearance_schedule = clearance_schedule;
     720     1196822 : }
     721             : 
     722             : template <typename T>
     723             : typename FunctorBase<T>::ValueType
     724      777249 : FunctorBase<T>::operator()(const NodeArg & node, const StateArg & state) const
     725             : {
     726             :   mooseAssert(node.subdomain_ids, "Subdomain IDs must be supplied to the node argument");
     727      777249 :   return evaluate(node, state);
     728             : }
     729             : 
     730             : template <typename T>
     731             : void
     732    96790595 : FunctorBase<T>::checkFace(const Moose::FaceArg &
     733             : #if DEBUG
     734             :                               face
     735             : #endif
     736             : ) const
     737             : {
     738             : #if DEBUG
     739             :   const Elem * const elem = face.face_side;
     740             :   const FaceInfo * const fi = face.fi;
     741             :   mooseAssert(fi, "face info should be non-null");
     742             :   bool check_elem_def = false;
     743             :   bool check_neighbor_def = false;
     744             :   // We check if the functor is defined on both sides of the face
     745             :   if (!elem)
     746             :   {
     747             :     if (!hasFaceSide(*fi, true))
     748             :       check_neighbor_def = true;
     749             :     else if (!hasFaceSide(*fi, false))
     750             :       check_elem_def = true;
     751             :   }
     752             :   else if (elem == fi->elemPtr())
     753             :     check_elem_def = true;
     754             :   else
     755             :   {
     756             :     mooseAssert(elem == fi->neighborPtr(), "This has to match something");
     757             :     check_neighbor_def = true;
     758             :   }
     759             : 
     760             :   if (check_elem_def && !hasFaceSide(*fi, true))
     761             :   {
     762             :     std::string additional_message = "It is not defined on the neighbor side either.";
     763             :     if (hasFaceSide(*fi, false))
     764             :       additional_message = "It is however defined on the neighbor side.";
     765             :     additional_message += " Face centroid: " + Moose::stringify(fi->faceCentroid());
     766             :     mooseError(_functor_name,
     767             :                " is not defined on the element side of the face information, but a face argument "
     768             :                "producer "
     769             :                "(e.g. residual object, postprocessor, etc.) has requested evaluation there.\n",
     770             :                additional_message);
     771             :   }
     772             :   if (check_neighbor_def && !hasFaceSide(*fi, false))
     773             :   {
     774             :     std::string additional_message = "It is not defined on the element side either.";
     775             :     if (hasFaceSide(*fi, true))
     776             :       additional_message = "It is however defined on the element side.";
     777             :     additional_message += " Face centroid: " + Moose::stringify(fi->faceCentroid());
     778             :     mooseError(
     779             :         _functor_name,
     780             :         " is not defined on the neighbor side of the face information, but a face argument "
     781             :         "producer (e.g. residual object, postprocessor, etc.) has requested evaluation there.\n",
     782             :         additional_message);
     783             :   }
     784             : #endif
     785    96790595 : }
     786             : 
     787             : template <typename T>
     788             : void
     789       31945 : FunctorBase<T>::clearCacheData()
     790             : {
     791       31945 :   for (auto & map_pr : _qp_to_value)
     792           0 :     for (auto & pr : map_pr.second)
     793           0 :       pr.first = false;
     794             : 
     795       31945 :   for (auto & map_pr : _side_qp_to_value)
     796             :   {
     797           0 :     auto & side_vector = map_pr.second;
     798           0 :     for (auto & qp_vector : side_vector)
     799           0 :       for (auto & pr : qp_vector)
     800           0 :         pr.first = false;
     801             :   }
     802             : 
     803       31945 :   _current_qp_map_key = libMesh::DofObject::invalid_id;
     804       31945 :   _current_qp_map_value = nullptr;
     805       31945 :   _current_side_qp_map_key = libMesh::DofObject::invalid_id;
     806       31945 :   _current_side_qp_map_value = nullptr;
     807             : 
     808       31945 :   _elem_arg_to_value.clear();
     809       31945 :   _face_arg_to_value.clear();
     810       31945 :   _node_arg_to_value.clear();
     811       31945 : }
     812             : 
     813             : template <typename T>
     814             : void
     815     1373420 : FunctorBase<T>::timestepSetup()
     816             : {
     817     1373420 :   if (_clearance_schedule.count(EXEC_TIMESTEP_BEGIN))
     818          24 :     clearCacheData();
     819     1373420 : }
     820             : 
     821             : template <typename T>
     822             : void
     823    10128184 : FunctorBase<T>::residualSetup()
     824             : {
     825    10128184 :   if (_clearance_schedule.count(EXEC_LINEAR))
     826       30713 :     clearCacheData();
     827    10128184 : }
     828             : 
     829             : template <typename T>
     830             : void
     831     1632742 : FunctorBase<T>::jacobianSetup()
     832             : {
     833     1632742 :   if (_clearance_schedule.count(EXEC_NONLINEAR))
     834        1208 :     clearCacheData();
     835     1632742 : }
     836             : 
     837             : template <typename T>
     838             : void
     839     1481169 : FunctorBase<T>::customSetup(const ExecFlagType & exec_type)
     840             : {
     841     1481169 :   if (_clearance_schedule.count(exec_type))
     842           0 :     clearCacheData();
     843     1481169 : }
     844             : 
     845             : template <typename T>
     846             : typename FunctorBase<T>::GradientType
     847     5032908 : FunctorBase<T>::gradient(const ElemArg & elem, const StateArg & state) const
     848             : {
     849     5032908 :   return evaluateGradient(elem, state);
     850             : }
     851             : 
     852             : template <typename T>
     853             : typename FunctorBase<T>::GradientType
     854     4775174 : FunctorBase<T>::gradient(const FaceArg & face, const StateArg & state) const
     855             : {
     856     4775174 :   checkFace(face);
     857     4775174 :   return evaluateGradient(face, state);
     858             : }
     859             : 
     860             : template <typename T>
     861             : typename FunctorBase<T>::GradientType
     862    11138481 : FunctorBase<T>::gradient(const ElemQpArg & elem_qp, const StateArg & state) const
     863             : {
     864    11138481 :   return evaluateGradient(elem_qp, state);
     865             : }
     866             : 
     867             : template <typename T>
     868             : typename FunctorBase<T>::GradientType
     869          11 : FunctorBase<T>::gradient(const ElemSideQpArg & elem_side_qp, const StateArg & state) const
     870             : {
     871          11 :   return evaluateGradient(elem_side_qp, state);
     872             : }
     873             : 
     874             : template <typename T>
     875             : typename FunctorBase<T>::GradientType
     876          11 : FunctorBase<T>::gradient(const ElemPointArg & elem_point, const StateArg & state) const
     877             : {
     878          11 :   return evaluateGradient(elem_point, state);
     879             : }
     880             : 
     881             : template <typename T>
     882             : typename FunctorBase<T>::GradientType
     883          41 : FunctorBase<T>::gradient(const NodeArg & node, const StateArg & state) const
     884             : {
     885          41 :   return evaluateGradient(node, state);
     886             : }
     887             : 
     888             : template <typename T>
     889             : typename FunctorBase<T>::DotType
     890       74403 : FunctorBase<T>::dot(const ElemArg & elem, const StateArg & state) const
     891             : {
     892       74403 :   return evaluateDot(elem, state);
     893             : }
     894             : 
     895             : template <typename T>
     896             : typename FunctorBase<T>::DotType
     897          11 : FunctorBase<T>::dot(const FaceArg & face, const StateArg & state) const
     898             : {
     899          11 :   checkFace(face);
     900          11 :   return evaluateDot(face, state);
     901             : }
     902             : 
     903             : template <typename T>
     904             : typename FunctorBase<T>::DotType
     905      837847 : FunctorBase<T>::dot(const ElemQpArg & elem_qp, const StateArg & state) const
     906             : {
     907      837847 :   return evaluateDot(elem_qp, state);
     908             : }
     909             : 
     910             : template <typename T>
     911             : typename FunctorBase<T>::DotType
     912          11 : FunctorBase<T>::dot(const ElemSideQpArg & elem_side_qp, const StateArg & state) const
     913             : {
     914          11 :   return evaluateDot(elem_side_qp, state);
     915             : }
     916             : 
     917             : template <typename T>
     918             : typename FunctorBase<T>::DotType
     919          11 : FunctorBase<T>::dot(const ElemPointArg & elem_point, const StateArg & state) const
     920             : {
     921          11 :   return evaluateDot(elem_point, state);
     922             : }
     923             : 
     924             : template <typename T>
     925             : typename FunctorBase<T>::DotType
     926           9 : FunctorBase<T>::dot(const NodeArg & node, const StateArg & state) const
     927             : {
     928           9 :   return evaluateDot(node, state);
     929             : }
     930             : 
     931             : template <typename T>
     932             : typename FunctorBase<T>::GradientType
     933        1932 : FunctorBase<T>::gradDot(const ElemArg & elem, const StateArg & state) const
     934             : {
     935        1932 :   return evaluateGradDot(elem, state);
     936             : }
     937             : 
     938             : template <typename T>
     939             : typename FunctorBase<T>::GradientType
     940          10 : FunctorBase<T>::gradDot(const FaceArg & face, const StateArg & state) const
     941             : {
     942          10 :   checkFace(face);
     943          10 :   return evaluateGradDot(face, state);
     944             : }
     945             : 
     946             : template <typename T>
     947             : typename FunctorBase<T>::GradientType
     948           8 : FunctorBase<T>::gradDot(const ElemQpArg & elem_qp, const StateArg & state) const
     949             : {
     950           8 :   return evaluateGradDot(elem_qp, state);
     951             : }
     952             : 
     953             : template <typename T>
     954             : typename FunctorBase<T>::GradientType
     955           8 : FunctorBase<T>::gradDot(const ElemSideQpArg & elem_side_qp, const StateArg & state) const
     956             : {
     957           8 :   return evaluateGradDot(elem_side_qp, state);
     958             : }
     959             : 
     960             : template <typename T>
     961             : typename FunctorBase<T>::GradientType
     962           8 : FunctorBase<T>::gradDot(const ElemPointArg & elem_point, const StateArg & state) const
     963             : {
     964           8 :   return evaluateGradDot(elem_point, state);
     965             : }
     966             : 
     967             : template <typename T>
     968             : typename FunctorBase<T>::GradientType
     969           8 : FunctorBase<T>::gradDot(const NodeArg & node, const StateArg & state) const
     970             : {
     971           8 :   return evaluateGradDot(node, state);
     972             : }
     973             : 
     974             : template <typename T>
     975             : bool
     976        5966 : FunctorBase<T>::hasFaceSide(const FaceInfo & fi, const bool fi_elem_side) const
     977             : {
     978        5966 :   if (fi_elem_side)
     979        2983 :     return hasBlocks(fi.elem().subdomain_id());
     980             :   else
     981        2983 :     return fi.neighborPtr() && hasBlocks(fi.neighbor().subdomain_id());
     982             : }
     983             : 
     984             : template <typename T>
     985             : template <FunctorEvaluationKind FET, typename Space, typename State>
     986             : typename FunctorReturnType<T, FET>::type
     987   193711752 : FunctorBase<T>::genericEvaluate(const Space & r, const State & state) const
     988             : {
     989             :   if constexpr (FET == FunctorEvaluationKind::Value)
     990   184162534 :     return (*this)(r, state);
     991             :   else if constexpr (FET == FunctorEvaluationKind::Gradient)
     992     9549218 :     return gradient(r, state);
     993             :   else if constexpr (FET == FunctorEvaluationKind::Dot)
     994           0 :     return dot(r, state);
     995             :   else
     996           0 :     return gradDot(r, state);
     997             : }
     998             : 
     999             : /**
    1000             :  * A non-templated base class for functors that allow an owner object to hold
    1001             :  * different class template instantiations of \p Functor in a single container
    1002             :  */
    1003             : class FunctorEnvelopeBase
    1004             : {
    1005             : public:
    1006      599140 :   FunctorEnvelopeBase() = default;
    1007      562571 :   virtual ~FunctorEnvelopeBase() = default;
    1008             : 
    1009             :   /**
    1010             :    * @return Whether this envelope wraps a null functor
    1011             :    */
    1012             :   virtual bool wrapsNull() const = 0;
    1013             : 
    1014             :   /**
    1015             :    * @return The return type, as a string, of the functor this envelope wraps
    1016             :    */
    1017             :   virtual std::string returnType() const = 0;
    1018             : 
    1019             :   /**
    1020             :    * @return Whether this envelope wraps a constant functor
    1021             :    */
    1022             :   virtual bool isConstant() const = 0;
    1023             : 
    1024             :   /**
    1025             :    * @return Whether this envelope owns its wrapped functor. This envelope may briefly own null
    1026             :    * functors during simulation setup or it may own non-AD or AD wrappers of "true" functors, but we
    1027             :    * should never own any "true" functors, e.g. we expect memory of "true" functors to be managed by
    1028             :    * warehouses (e.g. variable, function, etc.), or by the \p SubProblem itself. With this
    1029             :    * expectation, we don't have to worry about performing setup calls
    1030             :    */
    1031             :   virtual bool ownsWrappedFunctor() const = 0;
    1032             : };
    1033             : 
    1034             : /**
    1035             :  * This is a wrapper that forwards calls to the implementation,
    1036             :  * which can be switched out at any time without disturbing references to
    1037             :  * FunctorBase. Implementation motivated by https://stackoverflow.com/a/65455485/4493669
    1038             :  */
    1039             : template <typename T>
    1040             : class FunctorEnvelope final : public FunctorBase<T>, public FunctorEnvelopeBase
    1041             : {
    1042             : public:
    1043             :   using typename Moose::FunctorBase<T>::ValueType;
    1044             :   using typename Moose::FunctorBase<T>::GradientType;
    1045             :   using typename Moose::FunctorBase<T>::DotType;
    1046             : 
    1047             :   /**
    1048             :    * @param wrapped The functor to wrap. We will *not* not own the wrapped object
    1049             :    */
    1050      294187 :   FunctorEnvelope(const FunctorBase<T> & wrapped)
    1051      588374 :     : FunctorBase<T>("wraps_" + wrapped.functorName()), FunctorEnvelopeBase(), _wrapped(&wrapped)
    1052             :   {
    1053      588374 :   }
    1054             : 
    1055             :   /**
    1056             :    * @param wrapped A unique pointer around the functor to wrap. We *will* own the wrapped object,
    1057             :    * e.g. if we are ever destructed or we are reassigned to wrap another functor, then this functor
    1058             :    * will be destructed
    1059             :    */
    1060      304953 :   FunctorEnvelope(std::unique_ptr<FunctorBase<T>> && wrapped)
    1061      304953 :     : FunctorBase<T>("wraps_" + wrapped->functorName()),
    1062             :       FunctorEnvelopeBase(),
    1063      304953 :       _owned(std::move(wrapped)),
    1064     1219812 :       _wrapped(_owned.get())
    1065             :   {
    1066      609906 :   }
    1067             : 
    1068             :   /**
    1069             :    * Prevent wrapping of a temporary object. If we are to own a functor, the unique_ptr constructor
    1070             :    * overload should be used
    1071             :    */
    1072             :   FunctorEnvelope(FunctorBase<T> &&) = delete;
    1073             : 
    1074             :   /**
    1075             :    * @param wrapped The functor to wrap. We will *not* not own the wrapped object. If we previously
    1076             :    * owned a functor, it will be destructed
    1077             :    */
    1078         138 :   void assign(const FunctorBase<T> & wrapped)
    1079             :   {
    1080         138 :     _owned.reset();
    1081         138 :     _wrapped = &wrapped;
    1082         138 :   }
    1083             : 
    1084             :   /**
    1085             :    * @param wrapped A unique pointer around the functor to wrap. We *will* own the wrapped object.
    1086             :    * If we previously owned a functor, it will be destructed
    1087             :    */
    1088         138 :   void assign(std::unique_ptr<FunctorBase<T>> && wrapped)
    1089             :   {
    1090         138 :     _owned = std::move(wrapped);
    1091         138 :     _wrapped = _owned.get();
    1092         138 :   }
    1093             : 
    1094             :   /**
    1095             :    * Prevent wrapping of a temporary object. If we are to own a functor, the unique_ptr assign
    1096             :    * overload should be used
    1097             :    */
    1098             :   void assign(FunctorBase<T> &&) = delete;
    1099             : 
    1100             :   FunctorEnvelope(const FunctorEnvelope &) = delete;
    1101             :   FunctorEnvelope(FunctorEnvelope &&) = delete;
    1102             :   FunctorEnvelope & operator=(const FunctorEnvelope &) = delete;
    1103             :   FunctorEnvelope & operator=(FunctorEnvelope &&) = delete;
    1104             : 
    1105     1125141 :   virtual ~FunctorEnvelope() = default;
    1106             : 
    1107             :   /**
    1108             :    * @return whether this object wraps a null functor
    1109             :    */
    1110      285610 :   virtual bool wrapsNull() const override { return wrapsType<NullFunctor<T>>(); }
    1111             : 
    1112             :   /**
    1113             :    * @return a string representation of the return type of this functor
    1114             :    */
    1115           0 :   virtual std::string returnType() const override { return libMesh::demangle(typeid(T).name()); }
    1116             : 
    1117      285610 :   virtual bool ownsWrappedFunctor() const override { return _owned.get(); }
    1118             : 
    1119             :   /**
    1120             :    * @return whether the wrapped object is of the requested type
    1121             :    */
    1122             :   template <typename T2>
    1123      312797 :   bool wrapsType() const
    1124             :   {
    1125      312797 :     return dynamic_cast<const T2 *>(_wrapped);
    1126             :   }
    1127             : 
    1128           0 :   virtual bool isExtrapolatedBoundaryFace(const FaceInfo & fi,
    1129             :                                           const Elem * const elem,
    1130             :                                           const StateArg & state) const override
    1131             :   {
    1132           0 :     return _wrapped->isExtrapolatedBoundaryFace(fi, elem, state);
    1133             :   }
    1134           0 :   virtual bool isConstant() const override { return _wrapped->isConstant(); }
    1135       95024 :   virtual bool hasBlocks(const SubdomainID id) const override { return _wrapped->hasBlocks(id); }
    1136         686 :   virtual bool hasFaceSide(const FaceInfo & fi, const bool fi_elem_side) const override
    1137             :   {
    1138         686 :     return _wrapped->hasFaceSide(fi, fi_elem_side);
    1139             :   }
    1140             : 
    1141        1382 :   bool supportsFaceArg() const override final { return true; }
    1142         532 :   bool supportsElemSideQpArg() const override final { return true; }
    1143             : 
    1144             : protected:
    1145             :   ///@{
    1146             :   /**
    1147             :    * Forward calls to wrapped object
    1148             :    */
    1149    31474171 :   virtual ValueType evaluate(const ElemArg & elem, const StateArg & state) const override
    1150             :   {
    1151    31474171 :     return _wrapped->operator()(elem, state);
    1152             :   }
    1153     2931047 :   virtual ValueType evaluate(const FaceArg & face, const StateArg & state) const override
    1154             :   {
    1155     2931047 :     return _wrapped->operator()(face, state);
    1156             :   }
    1157    16307263 :   virtual ValueType evaluate(const ElemQpArg & qp, const StateArg & state) const override
    1158             :   {
    1159    16307263 :     return _wrapped->operator()(qp, state);
    1160             :   }
    1161      942621 :   virtual ValueType evaluate(const ElemSideQpArg & qp, const StateArg & state) const override
    1162             :   {
    1163      942621 :     return _wrapped->operator()(qp, state);
    1164             :   }
    1165        1421 :   virtual ValueType evaluate(const ElemPointArg & elem_point, const StateArg & state) const override
    1166             :   {
    1167        1421 :     return _wrapped->operator()(elem_point, state);
    1168             :   }
    1169      274437 :   virtual ValueType evaluate(const NodeArg & node, const StateArg & state) const override
    1170             :   {
    1171      274437 :     return _wrapped->operator()(node, state);
    1172             :   }
    1173             : 
    1174       32257 :   virtual GradientType evaluateGradient(const ElemArg & elem, const StateArg & state) const override
    1175             :   {
    1176       32257 :     return _wrapped->gradient(elem, state);
    1177             :   }
    1178           1 :   virtual GradientType evaluateGradient(const FaceArg & face, const StateArg & state) const override
    1179             :   {
    1180           1 :     return _wrapped->gradient(face, state);
    1181             :   }
    1182       74801 :   virtual GradientType evaluateGradient(const ElemQpArg & qp, const StateArg & state) const override
    1183             :   {
    1184       74801 :     return _wrapped->gradient(qp, state);
    1185             :   }
    1186           1 :   virtual GradientType evaluateGradient(const ElemSideQpArg & qp,
    1187             :                                         const StateArg & state) const override
    1188             :   {
    1189           1 :     return _wrapped->gradient(qp, state);
    1190             :   }
    1191           1 :   virtual GradientType evaluateGradient(const ElemPointArg & elem_point,
    1192             :                                         const StateArg & state) const override
    1193             :   {
    1194           1 :     return _wrapped->gradient(elem_point, state);
    1195             :   }
    1196          16 :   virtual GradientType evaluateGradient(const NodeArg & node, const StateArg & state) const override
    1197             :   {
    1198          16 :     return _wrapped->gradient(node, state);
    1199             :   }
    1200             : 
    1201        9289 :   virtual DotType evaluateDot(const ElemArg & elem, const StateArg & state) const override
    1202             :   {
    1203        9289 :     return _wrapped->dot(elem, state);
    1204             :   }
    1205           1 :   virtual DotType evaluateDot(const FaceArg & face, const StateArg & state) const override
    1206             :   {
    1207           1 :     return _wrapped->dot(face, state);
    1208             :   }
    1209        2727 :   virtual DotType evaluateDot(const ElemQpArg & qp, const StateArg & state) const override
    1210             :   {
    1211        2727 :     return _wrapped->dot(qp, state);
    1212             :   }
    1213           1 :   virtual DotType evaluateDot(const ElemSideQpArg & qp, const StateArg & state) const override
    1214             :   {
    1215           1 :     return _wrapped->dot(qp, state);
    1216             :   }
    1217           1 :   virtual DotType evaluateDot(const ElemPointArg & elem_point,
    1218             :                               const StateArg & state) const override
    1219             :   {
    1220           1 :     return _wrapped->dot(elem_point, state);
    1221             :   }
    1222           0 :   virtual DotType evaluateDot(const NodeArg & node, const StateArg & state) const override
    1223             :   {
    1224           0 :     return _wrapped->dot(node, state);
    1225             :   }
    1226             : 
    1227         960 :   virtual GradientType evaluateGradDot(const ElemArg & elem, const StateArg & state) const override
    1228             :   {
    1229         960 :     return _wrapped->gradDot(elem, state);
    1230             :   }
    1231           0 :   virtual GradientType evaluateGradDot(const FaceArg & face, const StateArg & state) const override
    1232             :   {
    1233           0 :     return _wrapped->gradDot(face, state);
    1234             :   }
    1235           0 :   virtual GradientType evaluateGradDot(const ElemQpArg & qp, const StateArg & state) const override
    1236             :   {
    1237           0 :     return _wrapped->gradDot(qp, state);
    1238             :   }
    1239           0 :   virtual GradientType evaluateGradDot(const ElemSideQpArg & qp,
    1240             :                                        const StateArg & state) const override
    1241             :   {
    1242           0 :     return _wrapped->gradDot(qp, state);
    1243             :   }
    1244           0 :   virtual GradientType evaluateGradDot(const ElemPointArg & elem_point,
    1245             :                                        const StateArg & state) const override
    1246             :   {
    1247           0 :     return _wrapped->gradDot(elem_point, state);
    1248             :   }
    1249           0 :   virtual GradientType evaluateGradDot(const NodeArg & node, const StateArg & state) const override
    1250             :   {
    1251           0 :     return _wrapped->gradDot(node, state);
    1252             :   }
    1253             :   ///@}
    1254             : 
    1255             : private:
    1256             :   /// Our wrapped object
    1257             :   std::unique_ptr<FunctorBase<T>> _owned;
    1258             :   const FunctorBase<T> * _wrapped;
    1259             : 
    1260             :   friend class ::SubProblem;
    1261             : };
    1262             : 
    1263             : /**
    1264             :  * Class template for creating constant functors
    1265             :  */
    1266             : template <typename T>
    1267             : class ConstantFunctor final : public FunctorBase<T>
    1268             : {
    1269             : public:
    1270             :   using typename FunctorBase<T>::FunctorType;
    1271             :   using typename FunctorBase<T>::ValueType;
    1272             :   using typename FunctorBase<T>::GradientType;
    1273             :   using typename FunctorBase<T>::DotType;
    1274             : 
    1275        4170 :   ConstantFunctor(const ValueType & value)
    1276        8340 :     : FunctorBase<T>("constant_" + std::to_string(value)), _value(value)
    1277             :   {
    1278        8340 :   }
    1279        6322 :   ConstantFunctor(ValueType && value)
    1280       12644 :     : FunctorBase<T>("constant_" + std::to_string(MetaPhysicL::raw_value(value))), _value(value)
    1281             :   {
    1282       12644 :   }
    1283             : 
    1284           0 :   virtual bool isConstant() const override { return true; }
    1285             : 
    1286       24264 :   bool hasBlocks(SubdomainID /* id */) const override { return true; }
    1287             : 
    1288           0 :   bool supportsFaceArg() const override final { return true; }
    1289           0 :   bool supportsElemSideQpArg() const override final { return true; }
    1290             : 
    1291             : private:
    1292    22119933 :   ValueType evaluate(const ElemArg &, const StateArg &) const override { return _value; }
    1293      521622 :   ValueType evaluate(const FaceArg &, const StateArg &) const override { return _value; }
    1294     3822367 :   ValueType evaluate(const ElemQpArg &, const StateArg &) const override { return _value; }
    1295      230929 :   ValueType evaluate(const ElemSideQpArg &, const StateArg &) const override { return _value; }
    1296         191 :   ValueType evaluate(const ElemPointArg &, const StateArg &) const override { return _value; }
    1297       45729 :   ValueType evaluate(const NodeArg &, const StateArg &) const override { return _value; }
    1298             : 
    1299           5 :   GradientType evaluateGradient(const ElemArg &, const StateArg &) const override { return 0; }
    1300           5 :   GradientType evaluateGradient(const FaceArg &, const StateArg &) const override { return 0; }
    1301           5 :   GradientType evaluateGradient(const ElemQpArg &, const StateArg &) const override { return 0; }
    1302           5 :   GradientType evaluateGradient(const ElemSideQpArg &, const StateArg &) const override
    1303             :   {
    1304           5 :     return 0;
    1305             :   }
    1306           5 :   GradientType evaluateGradient(const ElemPointArg &, const StateArg &) const override { return 0; }
    1307           5 :   GradientType evaluateGradient(const NodeArg &, const StateArg &) const override { return 0; }
    1308             : 
    1309           5 :   DotType evaluateDot(const ElemArg &, const StateArg &) const override { return 0; }
    1310           5 :   DotType evaluateDot(const FaceArg &, const StateArg &) const override { return 0; }
    1311           5 :   DotType evaluateDot(const ElemQpArg &, const StateArg &) const override { return 0; }
    1312           5 :   DotType evaluateDot(const ElemSideQpArg &, const StateArg &) const override { return 0; }
    1313           5 :   DotType evaluateDot(const ElemPointArg &, const StateArg &) const override { return 0; }
    1314           5 :   DotType evaluateDot(const NodeArg &, const StateArg &) const override { return 0; }
    1315             : 
    1316           5 :   GradientType evaluateGradDot(const ElemArg &, const StateArg &) const override { return 0; }
    1317           5 :   GradientType evaluateGradDot(const FaceArg &, const StateArg &) const override { return 0; }
    1318           5 :   GradientType evaluateGradDot(const ElemQpArg &, const StateArg &) const override { return 0; }
    1319           5 :   GradientType evaluateGradDot(const ElemSideQpArg &, const StateArg &) const override { return 0; }
    1320           5 :   GradientType evaluateGradDot(const ElemPointArg &, const StateArg &) const override { return 0; }
    1321           5 :   GradientType evaluateGradDot(const NodeArg &, const StateArg &) const override { return 0; }
    1322             : 
    1323             : private:
    1324             :   ValueType _value;
    1325             : };
    1326             : 
    1327             : /**
    1328             :  * A functor that serves as a placeholder during the simulation setup phase if a functor consumer
    1329             :  * requests a functor that has not yet been constructed.
    1330             :  */
    1331             : template <typename T>
    1332             : class NullFunctor final : public FunctorBase<T>
    1333             : {
    1334             : public:
    1335             :   using typename FunctorBase<T>::FunctorType;
    1336             :   using typename FunctorBase<T>::ValueType;
    1337             :   using typename FunctorBase<T>::GradientType;
    1338             :   using typename FunctorBase<T>::DotType;
    1339             : 
    1340         554 :   NullFunctor() : FunctorBase<T>("null") {}
    1341             : 
    1342             :   // For backwards compatiblity of unit testing
    1343             :   bool hasFaceSide(const FaceInfo & fi, bool) const override;
    1344             : 
    1345           0 :   bool supportsFaceArg() const override final { return false; }
    1346           0 :   bool supportsElemSideQpArg() const override final { return false; }
    1347             : 
    1348             : private:
    1349           1 :   ValueType evaluate(const ElemArg &, const StateArg &) const override
    1350             :   {
    1351           1 :     mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
    1352             :                "they've written broken code");
    1353             :   }
    1354           1 :   ValueType evaluate(const FaceArg &, const StateArg &) const override
    1355             :   {
    1356           1 :     mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
    1357             :                "they've written broken code");
    1358             :   }
    1359           1 :   ValueType evaluate(const ElemQpArg &, const StateArg &) const override
    1360             :   {
    1361           1 :     mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
    1362             :                "they've written broken code");
    1363             :   }
    1364           1 :   ValueType evaluate(const ElemSideQpArg &, const StateArg &) const override
    1365             :   {
    1366           1 :     mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
    1367             :                "they've written broken code");
    1368             :   }
    1369           1 :   ValueType evaluate(const ElemPointArg &, const StateArg &) const override
    1370             :   {
    1371           1 :     mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
    1372             :                "they've written broken code");
    1373             :   }
    1374           1 :   ValueType evaluate(const NodeArg &, const StateArg &) const override
    1375             :   {
    1376           1 :     mooseError("We should never get here. If you have, contact a MOOSE developer and tell them "
    1377             :                "they've written broken code");
    1378             :   }
    1379             : };
    1380             : 
    1381             : template <typename T>
    1382             : bool
    1383           0 : NullFunctor<T>::hasFaceSide(const FaceInfo &, const bool) const
    1384             : {
    1385             :   // For backwards compatiblity of unit testing
    1386           0 :   return true;
    1387             : }
    1388             : }

Generated by: LCOV version 1.14