LCOV - code coverage report
Current view: top level - include/variables - MooseVariableFV.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 97 198 49.0 %
Date: 2025-07-17 01:28:37 Functions: 48 109 44.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 "MooseTypes.h"
      13             : #include "MooseVariableField.h"
      14             : #include "SubProblem.h"
      15             : #include "MooseMesh.h"
      16             : #include "MooseVariableDataFV.h"
      17             : 
      18             : #include "libmesh/numeric_vector.h"
      19             : #include "libmesh/dof_map.h"
      20             : #include "libmesh/elem.h"
      21             : #include "libmesh/quadrature.h"
      22             : #include "libmesh/dense_vector.h"
      23             : #include "libmesh/enum_fe_family.h"
      24             : 
      25             : template <typename>
      26             : class MooseVariableFV;
      27             : 
      28             : typedef MooseVariableFV<Real> MooseVariableFVReal;
      29             : class FVDirichletBCBase;
      30             : class FVFluxBC;
      31             : 
      32             : namespace libMesh
      33             : {
      34             : template <typename>
      35             : class NumericVector;
      36             : }
      37             : 
      38             : /// This class provides variable solution values for other classes/objects to
      39             : /// bind to when looping over faces or elements.  It provides both
      40             : /// elem and neighbor values when accessed in flux/face object calculations.
      41             : /// The templating is to enable support for both vector and scalar variables.
      42             : /// Gradient reconstruction (when enabled) occurs transparently within this
      43             : /// class and kernels coupling to these values will naturally "see" according
      44             : /// to the selected reconstruction methods.
      45             : ///
      46             : /// OutputType          OutputShape           OutputData
      47             : /// ----------------------------------------------------
      48             : /// Real                Real                  Real
      49             : /// RealVectorValue     RealVectorValue       Real
      50             : /// RealEigenVector      Real                  RealEigenVector
      51             : template <typename OutputType>
      52             : class MooseVariableFV : public MooseVariableField<OutputType>
      53             : {
      54             : public:
      55             :   using OutputGradient = typename MooseVariableField<OutputType>::OutputGradient;
      56             :   using OutputSecond = typename MooseVariableField<OutputType>::OutputSecond;
      57             :   using OutputDivergence = typename MooseVariableField<OutputType>::OutputDivergence;
      58             : 
      59             :   using FieldVariableValue = typename MooseVariableField<OutputType>::FieldVariableValue;
      60             :   using FieldVariableGradient = typename MooseVariableField<OutputType>::FieldVariableGradient;
      61             :   using FieldVariableSecond = typename MooseVariableField<OutputType>::FieldVariableSecond;
      62             :   using FieldVariableCurl = typename MooseVariableField<OutputType>::FieldVariableCurl;
      63             :   using FieldVariableDivergence = typename MooseVariableField<OutputType>::FieldVariableDivergence;
      64             : 
      65             :   using OutputShape = typename MooseVariableField<OutputType>::OutputShape;
      66             :   using OutputShapeGradient = typename MooseVariableField<OutputType>::OutputShapeGradient;
      67             :   using OutputShapeSecond = typename MooseVariableField<OutputType>::OutputShapeSecond;
      68             :   using OutputShapeDivergence = typename MooseVariableField<OutputType>::OutputShapeDivergence;
      69             : 
      70             :   using OutputData = typename MooseVariableField<OutputType>::OutputData;
      71             :   using DoFValue = typename MooseVariableField<OutputType>::DoFValue;
      72             : 
      73             :   using FieldVariablePhiValue = typename MooseVariableField<OutputType>::FieldVariablePhiValue;
      74             :   using FieldVariablePhiDivergence =
      75             :       typename MooseVariableField<OutputType>::FieldVariablePhiDivergence;
      76             :   using FieldVariablePhiGradient =
      77             :       typename MooseVariableField<OutputType>::FieldVariablePhiGradient;
      78             :   using FieldVariablePhiSecond = typename MooseVariableField<OutputType>::FieldVariablePhiSecond;
      79             :   using ElemQpArg = Moose::ElemQpArg;
      80             :   using ElemSideQpArg = Moose::ElemSideQpArg;
      81             :   using ElemArg = Moose::ElemArg;
      82             :   using FaceArg = Moose::FaceArg;
      83             :   using StateArg = Moose::StateArg;
      84             :   using NodeArg = Moose::NodeArg;
      85             :   using ElemPointArg = Moose::ElemPointArg;
      86             :   using typename MooseVariableField<OutputType>::ValueType;
      87             :   using typename MooseVariableField<OutputType>::DotType;
      88             :   using typename MooseVariableField<OutputType>::GradientType;
      89             : 
      90             :   static InputParameters validParams();
      91             : 
      92             :   MooseVariableFV(const InputParameters & parameters);
      93             : 
      94     9129029 :   virtual bool isFV() const override { return true; }
      95             : 
      96             :   // TODO: many of these functions are not relevant to FV variables but are
      97             :   // still called at various points from existing moose code paths.  Ideally we
      98             :   // would figure out how to remove calls to these functions and then allow
      99             :   // throwing mooseError's from them instead of silently doing nothing (e.g.
     100             :   // reinitNodes, reinitAux, prepareLowerD, etc.).
     101             : 
     102    26525501 :   virtual void prepare() override final {}
     103      152188 :   virtual void prepareNeighbor() override final {}
     104             :   virtual void prepareAux() override final;
     105      644975 :   virtual void reinitNode() override final {}
     106           0 :   virtual void reinitNodes(const std::vector<dof_id_type> & /*nodes*/) override final {}
     107           0 :   virtual void reinitNodesNeighbor(const std::vector<dof_id_type> & /*nodes*/) override final {}
     108     4357508 :   virtual void reinitAux() override final {}
     109       56646 :   virtual void reinitAuxNeighbor() override final {}
     110        8764 :   virtual void prepareLowerD() override final {}
     111             : 
     112           0 :   virtual const dof_id_type & nodalDofIndex() const override final
     113             :   {
     114           0 :     mooseError("nodalDofIndex not supported by MooseVariableFVBase");
     115             :   }
     116           0 :   virtual const dof_id_type & nodalDofIndexNeighbor() const override final
     117             :   {
     118           0 :     mooseError("nodalDofIndexNeighbor not supported by MooseVariableFVBase");
     119             :   }
     120           0 :   virtual std::size_t phiSize() const override final { return _phi.size(); }
     121           0 :   virtual std::size_t phiFaceSize() const override final { return _phi_face.size(); }
     122           0 :   virtual std::size_t phiNeighborSize() const override final { return _phi_neighbor.size(); }
     123           0 :   virtual std::size_t phiFaceNeighborSize() const override final
     124             :   {
     125           0 :     return _phi_face_neighbor.size();
     126             :   }
     127           0 :   virtual std::size_t phiLowerSize() const override final
     128             :   {
     129           0 :     mooseError("phiLowerSize not supported by MooseVariableFVBase");
     130             :   }
     131             : 
     132             :   virtual void computeElemValuesFace() override;
     133             :   virtual void computeNeighborValuesFace() override;
     134             :   virtual void computeNeighborValues() override;
     135        8764 :   virtual void computeLowerDValues() override final
     136             :   {
     137             :     // mooseError("computeLowerDValues not supported by MooseVariableFVBase");
     138        8764 :   }
     139           0 :   virtual void computeNodalNeighborValues() override final
     140             :   {
     141             :     // mooseError("computeNodalNeighborValues not supported by MooseVariableFVBase");
     142           0 :   }
     143           0 :   virtual void computeNodalValues() override final
     144             :   {
     145             :     // mooseError("computeNodalValues not supported by MooseVariableFVBase");
     146           0 :   }
     147             :   virtual const std::vector<dof_id_type> & dofIndicesLower() const override final;
     148             : 
     149      176144 :   unsigned int numberOfDofs() const override final { return _element_data->numberOfDofs(); }
     150             : 
     151           0 :   virtual unsigned int numberOfDofsNeighbor() override final
     152             :   {
     153           0 :     mooseError("numberOfDofsNeighbor not supported by MooseVariableFVBase");
     154             :   }
     155             : 
     156   272247640 :   virtual bool isNodal() const override final { return false; }
     157             : 
     158           0 :   bool hasDoFsOnNodes() const override final { return false; }
     159             : 
     160         344 :   libMesh::FEContinuity getContinuity() const override final
     161             :   {
     162         344 :     return _element_data->getContinuity();
     163             :   };
     164             : 
     165      644999 :   virtual bool isNodalDefined() const override final { return false; }
     166             : 
     167             :   virtual void setNodalValue(const OutputType & value, unsigned int idx = 0) override;
     168             : 
     169             :   virtual void setDofValue(const OutputData & value, unsigned int index) override;
     170             : 
     171             :   void clearDofIndices() override;
     172             : 
     173             :   virtual void prepareIC() override;
     174             : 
     175         992 :   virtual const Elem * const & currentElem() const override { return _element_data->currentElem(); }
     176             : 
     177           0 :   virtual void getDofIndices(const Elem * elem,
     178             :                              std::vector<dof_id_type> & dof_indices) const override
     179             :   {
     180           0 :     return _element_data->getDofIndices(elem, dof_indices);
     181             :   }
     182             : 
     183   680800369 :   virtual const std::vector<dof_id_type> & dofIndices() const final
     184             :   {
     185   680800369 :     return _element_data->dofIndices();
     186             :   }
     187   543294075 :   virtual const std::vector<dof_id_type> & dofIndicesNeighbor() const final
     188             :   {
     189   543294075 :     return _neighbor_data->dofIndices();
     190             :   }
     191             : 
     192           0 :   Moose::FV::InterpMethod faceInterpolationMethod() const { return _face_interp_method; }
     193             : 
     194             :   void clearAllDofIndices() final;
     195             : 
     196           0 :   const DoFValue & nodalVectorTagValue(TagID) const override
     197             :   {
     198           0 :     mooseError("nodalVectorTagValue not implemented for finite volume variables.");
     199             :   }
     200           0 :   const DoFValue & nodalMatrixTagValue(TagID) const override
     201             :   {
     202           0 :     mooseError("nodalMatrixTagValue not implemented for finite volume variables.");
     203             :   }
     204             : 
     205          52 :   const FieldVariableValue & vectorTagValue(TagID tag) const override
     206             :   {
     207          52 :     return _element_data->vectorTagValue(tag);
     208             :   }
     209          52 :   const DoFValue & vectorTagDofValue(TagID tag) const override
     210             :   {
     211          52 :     return _element_data->vectorTagDofValue(tag);
     212             :   }
     213          13 :   const FieldVariableValue & matrixTagValue(TagID tag) const override
     214             :   {
     215          13 :     return _element_data->matrixTagValue(tag);
     216             :   }
     217           0 :   const FieldVariableValue & vectorTagValueNeighbor(TagID tag)
     218             :   {
     219           0 :     return _neighbor_data->vectorTagValue(tag);
     220             :   }
     221           0 :   const FieldVariableValue & matrixTagValueNeighbor(TagID tag)
     222             :   {
     223           0 :     return _neighbor_data->matrixTagValue(tag);
     224             :   }
     225             : 
     226           0 :   const FieldVariableValue & uDot() const { return _element_data->uDot(); }
     227        7120 :   const FieldVariableValue & sln() const override { return _element_data->sln(Moose::Current); }
     228           0 :   const FieldVariableValue & slnOld() const override { return _element_data->sln(Moose::Old); }
     229           0 :   const FieldVariableValue & slnOlder() const override { return _element_data->sln(Moose::Older); }
     230        2800 :   const FieldVariableGradient & gradSln() const override
     231             :   {
     232        2800 :     return _element_data->gradSln(Moose::Current);
     233             :   }
     234           0 :   const FieldVariableGradient & gradSlnOld() const override
     235             :   {
     236           0 :     return _element_data->gradSln(Moose::Old);
     237             :   }
     238           0 :   const FieldVariableValue & uDotNeighbor() const { return _neighbor_data->uDot(); }
     239          78 :   const FieldVariableValue & slnNeighbor() const override
     240             :   {
     241          78 :     return _neighbor_data->sln(Moose::Current);
     242             :   }
     243           0 :   const FieldVariableValue & slnOldNeighbor() const override
     244             :   {
     245           0 :     return _neighbor_data->sln(Moose::Old);
     246             :   }
     247          26 :   const FieldVariableGradient & gradSlnNeighbor() const override
     248             :   {
     249          26 :     return _neighbor_data->gradSln(Moose::Current);
     250             :   }
     251           0 :   const FieldVariableGradient & gradSlnOldNeighbor() const override
     252             :   {
     253           0 :     return _neighbor_data->gradSln(Moose::Old);
     254             :   }
     255             : 
     256           0 :   const VariableValue & duDotDu() const { return _element_data->duDotDu(); }
     257           0 :   const VariableValue & duDotDotDu() const { return _element_data->duDotDotDu(); }
     258           0 :   const VariableValue & duDotDuNeighbor() const { return _neighbor_data->duDotDu(); }
     259           0 :   const VariableValue & duDotDotDuNeighbor() const { return _neighbor_data->duDotDotDu(); }
     260             : 
     261             :   /// AD
     262       11104 :   const ADTemplateVariableValue<OutputType> & adSln() const override
     263             :   {
     264       11104 :     return _element_data->adSln();
     265             :   }
     266         668 :   const ADTemplateVariableGradient<OutputType> & adGradSln() const override
     267             :   {
     268         668 :     return _element_data->adGradSln();
     269             :   }
     270             : 
     271             :   /**
     272             :    * Retrieve (or potentially compute) the gradient on the provided element. Overriders of this
     273             :    * method *cannot* call \p getBoundaryFaceValue because that method itself may lead to a call to
     274             :    * \p adGradSln(const Elem * const) resulting in infinite recursion
     275             :    * @param elem The element for which to retrieve the gradient
     276             :    * @param state State argument which describes at what time / solution iteration  state we want to
     277             :    * evaluate the variable
     278             :    * @param correct_skewness Whether to perform skew corrections
     279             :    * @return The gradient at the element centroid
     280             :    */
     281             :   virtual const VectorValue<ADReal> & adGradSln(const Elem * const elem,
     282             :                                                 const StateArg & state,
     283             :                                                 const bool correct_skewness = false) const;
     284             : 
     285             :   /**
     286             :    * Retrieve (or potentially compute) a cross-diffusion-corrected gradient on the provided face.
     287             :    * "Correcting" the face gradient involves weighting the gradient stencil more heavily on the
     288             :    * solution values on the face-neighbor cells than a linear interpolation between cell center
     289             :    * gradients does
     290             :    * @param face The face for which to retrieve the gradient.
     291             :    * @param state State argument which describes at what time / solution iteration  state we want to
     292             :    * evaluate the variable
     293             :    * @param correct_skewness Whether to perform skew corrections
     294             :    */
     295             :   virtual VectorValue<ADReal>
     296             :   adGradSln(const FaceInfo & fi, const StateArg & state, const bool correct_skewness = false) const;
     297             : 
     298             :   /**
     299             :    * Retrieve (or potentially compute) the uncorrected gradient on the provided face. This
     300             :    * uncorrected gradient is a simple linear interpolation between cell gradients computed at the
     301             :    * centers of the two neighboring cells. "Correcting" the face gradient involves weighting the
     302             :    * gradient stencil more heavily on the solution values on the face-neighbor cells than the linear
     303             :    * interpolation process does. This is commonly known as a cross-diffusion correction. Correction
     304             :    * is done in \p adGradSln(const FaceInfo & fi)
     305             :    * @param face The face for which to retrieve the gradient
     306             :    * @param state State argument which describes at what time / solution iteration  state we want to
     307             :    * evaluate the variable
     308             :    * @param correct_skewness Whether to perform skew corrections
     309             :    */
     310             :   virtual VectorValue<ADReal> uncorrectedAdGradSln(const FaceInfo & fi,
     311             :                                                    const StateArg & state,
     312             :                                                    const bool correct_skewness = false) const;
     313             : 
     314             :   /**
     315             :    * Retrieve the solution value at a boundary face. If we're using a one term Taylor series
     316             :    * expansion we'll simply return the ajacent element centroid value. If we're doing two terms,
     317             :    * then we will compute the gradient if necessary to help us interpolate from the element centroid
     318             :    * value to the face
     319             :    */
     320             :   ADReal getBoundaryFaceValue(const FaceInfo & fi,
     321             :                               const StateArg & state,
     322             :                               bool correct_skewness = false) const;
     323             : 
     324           0 :   const ADTemplateVariableSecond<OutputType> & adSecondSln() const override
     325             :   {
     326           0 :     return _element_data->adSecondSln();
     327             :   }
     328         367 :   const ADTemplateVariableValue<OutputType> & adUDot() const override
     329             :   {
     330         367 :     return _element_data->adUDot();
     331             :   }
     332          13 :   const ADTemplateVariableValue<OutputType> & adUDotDot() const override
     333             :   {
     334          13 :     return _element_data->adUDotDot();
     335             :   }
     336           0 :   const ADTemplateVariableGradient<OutputType> & adGradSlnDot() const override
     337             :   {
     338           0 :     return _element_data->adGradSlnDot();
     339             :   }
     340           0 :   const ADTemplateVariableCurl<OutputType> & adCurlSln() const override
     341             :   {
     342           0 :     mooseError("We don't currently implement curl for FV");
     343             :   }
     344             : 
     345             :   /// neighbor AD
     346        7266 :   const ADTemplateVariableValue<OutputType> & adSlnNeighbor() const override
     347             :   {
     348        7266 :     return _neighbor_data->adSln();
     349             :   }
     350         642 :   const ADTemplateVariableGradient<OutputType> & adGradSlnNeighbor() const override
     351             :   {
     352         642 :     return _neighbor_data->adGradSln();
     353             :   }
     354           0 :   const ADTemplateVariableSecond<OutputType> & adSecondSlnNeighbor() const override
     355             :   {
     356           0 :     return _neighbor_data->adSecondSln();
     357             :   }
     358           0 :   const ADTemplateVariableValue<OutputType> & adUDotNeighbor() const override
     359             :   {
     360           0 :     return _neighbor_data->adUDot();
     361             :   }
     362           0 :   const ADTemplateVariableValue<OutputType> & adUDotDotNeighbor() const override
     363             :   {
     364           0 :     return _neighbor_data->adUDotDot();
     365             :   }
     366           0 :   const ADTemplateVariableGradient<OutputType> & adGradSlnNeighborDot() const override
     367             :   {
     368           0 :     return _neighbor_data->adGradSlnDot();
     369             :   }
     370           0 :   const ADTemplateVariableCurl<OutputType> & adCurlSlnNeighbor() const override
     371             :   {
     372           0 :     mooseError("We don't currently implement curl for FV");
     373             :   }
     374             : 
     375             :   /// Initializes/computes variable values from the solution vectors for the
     376             :   /// current element being operated on in assembly. This
     377             :   /// must be called every time the current element (as defined by the assembly
     378             :   /// data structure changes in order for objects that bind to sln, adSln,
     379             :   /// uDot, etc. to be updated/correct.
     380             :   virtual void computeElemValues() override;
     381             :   /// Initializes/computes variable values from the solution vectors for the
     382             :   /// face represented by fi.  This includes initializing data for elements on
     383             :   /// both sides of the face (elem and neighbor) and handles the case where
     384             :   /// there is no element on one side of the face gracefully - i.e. you call
     385             :   /// this uniformly for every face regardless of whether you are on a boundary
     386             :   /// or not - or whether the variable is only defined on one side of the face
     387             :   /// or not.
     388             :   virtual void computeFaceValues(const FaceInfo & fi) override;
     389             : 
     390             :   /**
     391             :    * Set local DOF values and evaluate the values on quadrature points
     392             :    */
     393             :   virtual void setDofValues(const DenseVector<OutputData> & values) override;
     394             :   virtual void setLowerDofValues(const DenseVector<OutputData> & values) override;
     395             : 
     396             :   /// Get the current value of this variable on an element
     397             :   /// @param[in] elem   Element at which to get value
     398             :   /// @param[in] idx    Local index of this variable's element DoFs
     399             :   /// @return Variable value
     400             :   OutputData getElementalValue(const Elem * elem, unsigned int idx = 0) const;
     401             :   /// Get the old value of this variable on an element
     402             :   /// @param[in] elem   Element at which to get value
     403             :   /// @param[in] idx    Local index of this variable's element DoFs
     404             :   /// @return Variable value
     405             :   OutputData getElementalValueOld(const Elem * elem, unsigned int idx = 0) const;
     406             :   /// Get the older value of this variable on an element
     407             :   /// @param[in] elem   Element at which to get value
     408             :   /// @param[in] idx    Local index of this variable's element DoFs
     409             :   /// @return Variable value
     410             :   OutputData getElementalValueOlder(const Elem * elem, unsigned int idx = 0) const;
     411             : 
     412             :   virtual void insert(libMesh::NumericVector<libMesh::Number> & vector) override;
     413             :   virtual void insertLower(libMesh::NumericVector<libMesh::Number> & vector) override;
     414             :   virtual void add(libMesh::NumericVector<libMesh::Number> & vector) override;
     415             : 
     416             :   const DoFValue & dofValues() const override;
     417             :   const DoFValue & dofValuesOld() const override;
     418             :   const DoFValue & dofValuesOlder() const override;
     419             :   const DoFValue & dofValuesPreviousNL() const override;
     420             :   const DoFValue & dofValuesNeighbor() const override;
     421             :   const DoFValue & dofValuesOldNeighbor() const override;
     422             :   const DoFValue & dofValuesOlderNeighbor() const override;
     423             :   const DoFValue & dofValuesPreviousNLNeighbor() const override;
     424             :   const DoFValue & dofValuesDot() const override;
     425             :   const DoFValue & dofValuesDotNeighbor() const override;
     426             :   const DoFValue & dofValuesDotOld() const override;
     427             :   const DoFValue & dofValuesDotOldNeighbor() const override;
     428             :   const DoFValue & dofValuesDotDot() const override;
     429             :   const DoFValue & dofValuesDotDotNeighbor() const override;
     430             :   const DoFValue & dofValuesDotDotOld() const override;
     431             :   const DoFValue & dofValuesDotDotOldNeighbor() const override;
     432             :   const MooseArray<libMesh::Number> & dofValuesDuDotDu() const override;
     433             :   const MooseArray<libMesh::Number> & dofValuesDuDotDuNeighbor() const override;
     434             :   const MooseArray<libMesh::Number> & dofValuesDuDotDotDu() const override;
     435             :   const MooseArray<libMesh::Number> & dofValuesDuDotDotDuNeighbor() const override;
     436             : 
     437             :   const MooseArray<ADReal> & adDofValues() const override;
     438             :   const MooseArray<ADReal> & adDofValuesNeighbor() const override;
     439             :   const MooseArray<ADReal> & adDofValuesDot() const override;
     440             : 
     441             :   /// Note: const monomial is always the case - higher order solns are
     442             :   /// reconstructed - so this is simpler func than FE equivalent.
     443             :   OutputType getValue(const Elem * elem) const;
     444             : 
     445             :   /// Compute the variable gradient value at a point on an element
     446             :   /// @param elem The element we are computing on
     447             :   /// @param phi Evaluated shape functions at a point
     448             :   /// @return The variable gradient value
     449             :   typename OutputTools<OutputType>::OutputGradient getGradient(const Elem * elem) const;
     450             : 
     451             :   /// Returns true if a Dirichlet BC exists on the current face.  This only
     452             :   /// works if the variable has been initialized on a face with
     453             :   /// computeFaceValues.  Its return value is nonsense if initialized on a
     454             :   /// single element via computeElemValues.
     455           0 :   bool hasDirichletBC() const
     456             :   {
     457           0 :     return _element_data->hasDirichletBC() || _neighbor_data->hasDirichletBC();
     458             :   }
     459             : 
     460             :   std::pair<bool, const FVDirichletBCBase *> getDirichletBC(const FaceInfo & fi) const;
     461             : 
     462             :   std::pair<bool, std::vector<const FVFluxBC *>> getFluxBCs(const FaceInfo & fi) const;
     463             : 
     464             :   virtual void residualSetup() override;
     465             :   virtual void initialSetup() override;
     466             :   virtual void jacobianSetup() override;
     467             :   virtual void timestepSetup() override;
     468             :   virtual void meshChanged() override;
     469             : 
     470             :   /**
     471             :    * Get the solution value for the provided element and seed the derivative for the corresponding
     472             :    * dof index
     473             :    * @param elem The element to retrieive the solution value for
     474             :    * @param state State argument which describes at what time / solution iteration  state we want to
     475             :    * evaluate the variable
     476             :    */
     477             :   ADReal getElemValue(const Elem * elem, const StateArg & state) const;
     478             : 
     479             :   void setActiveTags(const std::set<TagID> & vtags) override;
     480             : 
     481             :   /**
     482             :    * Request that quadrature point data be (pre)computed. Quadrature point data is (pre)computed by
     483             :    * default for this base class but derived variable classes may choose not to unless this API is
     484             :    * called
     485             :    */
     486       11414 :   virtual void requireQpComputations() const {}
     487             : 
     488             :   /**
     489             :    * Determine whether a specified face side is a Dirichlet boundary face. In the base
     490             :    * implementation we only inspect the face information object for whether there are Dirichlet
     491             :    * conditions. However, derived classes may allow discontinuities between + and - side face
     492             :    * values, e.g. one side may have a Dirichlet condition and the other side may perform
     493             :    * extrapolation to determine its value
     494             :    * @param fi The face information object
     495             :    * @param elem An element that can be used to indicate sidedness of the face
     496             :    * @param state The state at which to determine whether the face is a Dirichlet face or not
     497             :    * @return Whether the potentially sided (as indicated by \p elem) \p fi is a Dirichlet boundary
     498             :    * face for this variable
     499             :    */
     500             :   virtual bool isDirichletBoundaryFace(const FaceInfo & fi,
     501             :                                        const Elem * elem,
     502             :                                        const Moose::StateArg & state) const;
     503             : 
     504           0 :   bool supportsFaceArg() const override final { return true; }
     505           0 :   bool supportsElemSideQpArg() const override final { return true; }
     506             : 
     507             : protected:
     508             :   /**
     509             :    * Retrieves a Dirichlet boundary value for the provided face. Callers of this method should be
     510             :    * sure that \p isDirichletBoundaryFace returns true. In the base implementation we only inspect
     511             :    * the face information object for the Dirichlet value. However, derived
     512             :    * classes may allow discontinuities between + and - side face values, e.g. one side may have a
     513             :    * Dirichlet condition and the other side may perform extrapolation to determine its value. This
     514             :    * is the reason for the existence of the \p elem parameter, to indicate sidedness
     515             :    * @param fi The face information object
     516             :    * @param elem An element that can be used to indicate sidedness of the face
     517             :    * @param state State argument which describes at what time / solution iteration  state we want to
     518             :    * evaluate the variable
     519             :    * @return The Dirichlet value on the boundary face associated with \p fi (and potentially \p
     520             :    * elem)
     521             :    */
     522             :   virtual ADReal getDirichletBoundaryFaceValue(const FaceInfo & fi,
     523             :                                                const Elem * elem,
     524             :                                                const Moose::StateArg & state) const;
     525             : 
     526             :   /**
     527             :    * Returns whether this is an extrapolated boundary face. An extrapolated boundary face is
     528             :    * boundary face for which is not a corresponding Dirichlet condition, e.g. we need to compute
     529             :    * some approximation for the boundary face value using the adjacent cell centroid information. In
     530             :    * the base implementation we only inspect the face information object for whether we should
     531             :    * perform extrapolation. However, derived classes may allow discontinuities between + and - side
     532             :    * face values, e.g. one side may have a Dirichlet condition and the other side may perform
     533             :    * extrapolation to determine its value
     534             :    * @param fi The face information object
     535             :    * @param elem An element that can be used to indicate sidedness of the face
     536             :    * @param state The state at which to determine whether the face is extrapolated or not
     537             :    * @return Whether the potentially sided (as indicated by \p elem) \p fi is an extrapolated
     538             :    * boundary face for this variable
     539             :    */
     540             :   bool isExtrapolatedBoundaryFace(const FaceInfo & fi,
     541             :                                   const Elem * elem,
     542             :                                   const Moose::StateArg & state) const override;
     543             : 
     544             : private:
     545             :   using MooseVariableField<OutputType>::evaluate;
     546             :   using MooseVariableField<OutputType>::evaluateGradient;
     547             :   using MooseVariableField<OutputType>::evaluateDot;
     548             : 
     549             :   ValueType evaluate(const ElemArg & elem, const StateArg &) const override final;
     550             :   ValueType evaluate(const FaceArg & face, const StateArg &) const override final;
     551             :   ValueType evaluate(const NodeArg & node, const StateArg &) const override final;
     552             :   ValueType evaluate(const ElemPointArg & elem_point, const StateArg & state) const override final;
     553             :   ValueType evaluate(const ElemQpArg & elem_qp, const StateArg & state) const override final;
     554             :   ValueType evaluate(const ElemSideQpArg & elem_side_qp,
     555             :                      const StateArg & state) const override final;
     556             :   GradientType evaluateGradient(const ElemQpArg & qp_arg, const StateArg &) const override final;
     557             :   GradientType evaluateGradient(const ElemArg & elem_arg, const StateArg &) const override final;
     558             :   GradientType evaluateGradient(const FaceArg & face, const StateArg &) const override final;
     559             :   DotType evaluateDot(const ElemArg & elem, const StateArg &) const override final;
     560             :   DotType evaluateDot(const FaceArg & face, const StateArg &) const override final;
     561             :   DotType evaluateDot(const ElemQpArg & elem_qp, const StateArg &) const override final;
     562             : 
     563             :   /**
     564             :    * Setup the boundary to Dirichlet BC map
     565             :    */
     566             :   void determineBoundaryToDirichletBCMap();
     567             : 
     568             :   /// Whether the boundary to Dirichlet cache map has been setup yet
     569             :   bool _dirichlet_map_setup = false;
     570             : 
     571             :   /**
     572             :    * Setup the boundary to Flux BC map
     573             :    */
     574             :   void determineBoundaryToFluxBCMap();
     575             : 
     576             :   /// Whether the boundary to fluxBC cache map has been setup yet
     577             :   bool _flux_map_setup = false;
     578             : 
     579             : public:
     580           0 :   const MooseArray<OutputType> & nodalValueArray() const override
     581             :   {
     582           0 :     mooseError("Finite volume variables do not have defined values at nodes.");
     583             :   }
     584           0 :   const MooseArray<OutputType> & nodalValueOldArray() const override
     585             :   {
     586           0 :     mooseError("Finite volume variables do not have defined values at nodes.");
     587             :   }
     588           0 :   const MooseArray<OutputType> & nodalValueOlderArray() const override
     589             :   {
     590           0 :     mooseError("Finite volume variables do not have defined values at nodes.");
     591             :   }
     592             : 
     593       46396 :   bool computingSecond() const override final { return false; }
     594           0 :   bool computingCurl() const override final { return false; }
     595           0 :   bool computingDiv() const override final { return false; }
     596           0 :   bool usesSecondPhiNeighbor() const override final { return false; }
     597             : 
     598       47254 :   const FieldVariablePhiValue & phi() const override final { return _phi; }
     599       46422 :   const FieldVariablePhiGradient & gradPhi() const override final { return _grad_phi; }
     600           0 :   const FieldVariablePhiSecond & secondPhi() const override final
     601             :   {
     602           0 :     mooseError("We don't currently implement second derivatives for FV");
     603             :   }
     604           0 :   const FieldVariablePhiValue & curlPhi() const override final
     605             :   {
     606           0 :     mooseError("We don't currently implement curl for FV");
     607             :   }
     608           0 :   const FieldVariablePhiDivergence & divPhi() const override final
     609             :   {
     610           0 :     mooseError("We don't currently implement divergence for FV");
     611             :   }
     612             : 
     613          88 :   const FieldVariablePhiValue & phiFace() const override final { return _phi_face; }
     614          84 :   const FieldVariablePhiGradient & gradPhiFace() const override final { return _grad_phi_face; }
     615           0 :   const FieldVariablePhiSecond & secondPhiFace() const override final
     616             :   {
     617           0 :     mooseError("We don't currently implement second derivatives for FV");
     618             :   }
     619             : 
     620          84 :   const FieldVariablePhiValue & phiFaceNeighbor() const override final
     621             :   {
     622          84 :     return _phi_face_neighbor;
     623             :   }
     624          84 :   const FieldVariablePhiGradient & gradPhiFaceNeighbor() const override final
     625             :   {
     626          84 :     return _grad_phi_face_neighbor;
     627             :   }
     628           0 :   const FieldVariablePhiSecond & secondPhiFaceNeighbor() const override final
     629             :   {
     630           0 :     mooseError("We don't currently implement second derivatives for FV");
     631             :   }
     632             : 
     633           0 :   const FieldVariablePhiValue & phiNeighbor() const override final { return _phi_neighbor; }
     634           0 :   const FieldVariablePhiGradient & gradPhiNeighbor() const override final
     635             :   {
     636           0 :     return _grad_phi_neighbor;
     637             :   }
     638           0 :   const FieldVariablePhiSecond & secondPhiNeighbor() const override final
     639             :   {
     640           0 :     mooseError("We don't currently implement second derivatives for FV");
     641             :   }
     642             : 
     643             :   virtual const FieldVariablePhiValue & phiLower() const override;
     644             : 
     645             :   unsigned int oldestSolutionStateRequested() const override final;
     646             : 
     647             :   /**
     648             :    * Retrieves an extrapolated boundary value for the provided face. Callers of this method should
     649             :    * be sure that \p isExtrapolatedBoundaryFace returns true. In the base implementation we only
     650             :    * inspect the face information object for the extrapolated value. However, derived classes may
     651             :    * allow discontinuities between + and - side face values, e.g. one side may have a Dirichlet
     652             :    * condition and the other side may perform extrapolation to determine its value. This is the
     653             :    * reason for the existence of the \p elem parameter, to indicate sidedness
     654             :    * @param fi The face information object
     655             :    * @param two_term_expansion Whether to use the cell gradient in addition to the cell center value
     656             :    * to compute the extrapolated boundary face value. If this is false, then the cell center value
     657             :    * will be used
     658             :    * @param correct_skewness Whether to perform skew corrections. This is relevant when performing
     659             :    * two term expansions as the gradient evaluation may involve evaluating face values on internal
     660             :    * skewed faces
     661             :    * @param elem_side_to_extrapolate_from An element that can be used to indicate sidedness of the
     662             :    * face
     663             :    * @param state State argument which describes at what time / solution iteration  state we want to
     664             :    * evaluate the variable
     665             :    * @return The extrapolated value on the boundary face associated with \p fi (and potentially \p
     666             :    * elem_side_to_extrapolate_from)
     667             :    */
     668             :   virtual ADReal getExtrapolatedBoundaryFaceValue(const FaceInfo & fi,
     669             :                                                   bool two_term_expansion,
     670             :                                                   bool correct_skewness,
     671             :                                                   const Elem * elem_side_to_extrapolate_from,
     672             :                                                   const StateArg & state) const;
     673             : 
     674             :   /// Function to get wether two term boundary expansion is used for the variable
     675           0 :   const bool & getTwoTermBoundaryExpansion() const { return _two_term_boundary_expansion; }
     676             : 
     677             : protected:
     678             :   /**
     679             :    * clear finite volume caches
     680             :    */
     681             :   void clearCaches();
     682             : 
     683             :   usingMooseVariableFieldMembers;
     684             : 
     685             :   /// Holder for all the data associated with the "main" element
     686             :   std::unique_ptr<MooseVariableDataFV<OutputType>> _element_data;
     687             : 
     688             :   /// Holder for all the data associated with the neighbor element
     689             :   std::unique_ptr<MooseVariableDataFV<OutputType>> _neighbor_data;
     690             : 
     691             : private:
     692             :   /// The current (ghosted) solution. Note that this needs to be stored as a reference to a pointer
     693             :   /// because the solution might not exist at the time that this variable is constructed, so we
     694             :   /// cannot safely dereference at that time
     695             :   const libMesh::NumericVector<libMesh::Number> * const & _solution;
     696             : 
     697             :   /// Shape functions
     698             :   const FieldVariablePhiValue & _phi;
     699             :   const FieldVariablePhiGradient & _grad_phi;
     700             :   const FieldVariablePhiValue & _phi_face;
     701             :   const FieldVariablePhiGradient & _grad_phi_face;
     702             :   const FieldVariablePhiValue & _phi_face_neighbor;
     703             :   const FieldVariablePhiGradient & _grad_phi_face_neighbor;
     704             :   const FieldVariablePhiValue & _phi_neighbor;
     705             :   const FieldVariablePhiGradient & _grad_phi_neighbor;
     706             : 
     707             :   /// A member used to help determine when we can return cached data as opposed to computing new
     708             :   /// data
     709             :   mutable const Elem * _prev_elem;
     710             : 
     711             :   /// Map from boundary ID to Dirichlet boundary conditions. Added to speed up Dirichlet BC lookups
     712             :   /// in \p getDirichletBC
     713             :   std::unordered_map<BoundaryID, const FVDirichletBCBase *> _boundary_id_to_dirichlet_bc;
     714             : 
     715             :   /// Map from boundary ID to flux boundary conditions. Added to enable internal separator
     716             :   /// boundaries.
     717             :   std::unordered_map<BoundaryID, std::vector<const FVFluxBC *>> _boundary_id_to_flux_bc;
     718             : 
     719             :   /**
     720             :    * Emit an error message for unsupported lower-d ops
     721             :    */
     722             :   [[noreturn]] void lowerDError() const;
     723             : 
     724             : protected:
     725             :   /// A cache for storing gradients on elements
     726             :   mutable std::unordered_map<const Elem *, VectorValue<ADReal>> _elem_to_grad;
     727             : 
     728             :   /// Whether to use a two term expansion for computing boundary face values
     729             :   bool _two_term_boundary_expansion;
     730             : 
     731             :   /// A member to hold the cell gradient when not caching, used to return a reference (due to
     732             :   /// expensive ADReal copy)
     733             :   mutable VectorValue<ADReal> _temp_cell_gradient;
     734             : 
     735             :   /// Whether to cache cell gradients
     736             :   const bool _cache_cell_gradients;
     737             : 
     738             :   /// Decides if an average or skewed corrected average is used for the
     739             :   /// face interpolation. Other options are not taken into account here,
     740             :   /// but at higher, kernel-based levels.
     741             :   Moose::FV::InterpMethod _face_interp_method;
     742             : 
     743             :   friend void Moose::initDofIndices<>(MooseVariableFV<OutputType> &, const Elem &);
     744             : };
     745             : 
     746             : template <typename OutputType>
     747             : inline const MooseArray<ADReal> &
     748           0 : MooseVariableFV<OutputType>::adDofValues() const
     749             : {
     750           0 :   return _element_data->adDofValues();
     751             : }
     752             : 
     753             : template <typename OutputType>
     754             : inline const MooseArray<ADReal> &
     755           0 : MooseVariableFV<OutputType>::adDofValuesNeighbor() const
     756             : {
     757           0 :   return _neighbor_data->adDofValues();
     758             : }
     759             : 
     760             : template <typename OutputType>
     761             : inline const MooseArray<ADReal> &
     762           0 : MooseVariableFV<OutputType>::adDofValuesDot() const
     763             : {
     764           0 :   return _element_data->adDofValuesDot();
     765             : }
     766             : 
     767             : template <typename OutputType>
     768             : typename MooseVariableFV<OutputType>::ValueType
     769   211751369 : MooseVariableFV<OutputType>::evaluate(const ElemArg & elem_arg, const StateArg & state) const
     770             : {
     771   211751369 :   return getElemValue(elem_arg.elem, state);
     772             : }
     773             : 
     774             : template <typename OutputType>
     775             : typename MooseVariableFV<OutputType>::ValueType
     776       33238 : MooseVariableFV<OutputType>::evaluate(const ElemPointArg & elem_point, const StateArg & state) const
     777             : {
     778           0 :   return (*this)(elem_point.makeElem(), state) +
     779       33238 :          (elem_point.point - elem_point.elem->vertex_average()) *
     780       66476 :              this->gradient(elem_point.makeElem(), state);
     781             : }
     782             : 
     783             : template <typename OutputType>
     784             : typename MooseVariableFV<OutputType>::ValueType
     785       23378 : MooseVariableFV<OutputType>::evaluate(const ElemQpArg & elem_qp, const StateArg & state) const
     786             : {
     787       23378 :   return (*this)(ElemPointArg{elem_qp.elem,
     788             :                               elem_qp.point,
     789       23378 :                               _face_interp_method == Moose::FV::InterpMethod::SkewCorrectedAverage},
     790       23378 :                  state);
     791             : }
     792             : 
     793             : template <typename OutputType>
     794             : typename MooseVariableFV<OutputType>::ValueType
     795        1072 : MooseVariableFV<OutputType>::evaluate(const ElemSideQpArg & elem_side_qp,
     796             :                                       const StateArg & state) const
     797             : {
     798        1072 :   return (*this)(ElemPointArg{elem_side_qp.elem,
     799             :                               elem_side_qp.point,
     800        1072 :                               _face_interp_method == Moose::FV::InterpMethod::SkewCorrectedAverage},
     801        1072 :                  state);
     802             : }
     803             : 
     804             : template <typename OutputType>
     805             : typename MooseVariableFV<OutputType>::GradientType
     806        6470 : MooseVariableFV<OutputType>::evaluateGradient(const ElemQpArg & qp_arg,
     807             :                                               const StateArg & state) const
     808             : {
     809        6470 :   return adGradSln(
     810        6470 :       qp_arg.elem, state, _face_interp_method == Moose::FV::InterpMethod::SkewCorrectedAverage);
     811             : }
     812             : 
     813             : template <typename OutputType>
     814             : typename MooseVariableFV<OutputType>::GradientType
     815     4993085 : MooseVariableFV<OutputType>::evaluateGradient(const ElemArg & elem_arg,
     816             :                                               const StateArg & state) const
     817             : {
     818     4993085 :   return adGradSln(elem_arg.elem, state, elem_arg.correct_skewness);
     819             : }
     820             : 
     821             : template <typename OutputType>
     822             : typename MooseVariableFV<OutputType>::GradientType
     823     4774929 : MooseVariableFV<OutputType>::evaluateGradient(const FaceArg & face, const StateArg & state) const
     824             : {
     825             :   mooseAssert(face.fi, "We must have a non-null face information");
     826     4774929 :   return adGradSln(*face.fi, state, face.correct_skewness);
     827             : }
     828             : 
     829             : template <typename OutputType>
     830             : void
     831      455411 : MooseVariableFV<OutputType>::setActiveTags(const std::set<TagID> & vtags)
     832             : {
     833      455411 :   _element_data->setActiveTags(vtags);
     834      455411 :   _neighbor_data->setActiveTags(vtags);
     835      455411 : }
     836             : 
     837             : template <typename OutputType>
     838             : const std::vector<dof_id_type> &
     839      238392 : MooseVariableFV<OutputType>::dofIndicesLower() const
     840             : {
     841      238392 :   static const std::vector<dof_id_type> empty;
     842      238392 :   return empty;
     843             : }
     844             : 
     845             : template <typename OutputType>
     846             : void
     847        6154 : MooseVariableFV<OutputType>::initialSetup()
     848             : {
     849        6154 :   determineBoundaryToDirichletBCMap();
     850        6154 :   determineBoundaryToFluxBCMap();
     851        6154 :   MooseVariableField<OutputType>::initialSetup();
     852        6154 : }
     853             : 
     854             : template <typename OutputType>
     855             : void
     856         624 : MooseVariableFV<OutputType>::meshChanged()
     857             : {
     858         624 :   _prev_elem = nullptr;
     859         624 :   _dirichlet_map_setup = false;
     860         624 :   _flux_map_setup = false;
     861         624 :   MooseVariableField<OutputType>::meshChanged();
     862         624 : }
     863             : 
     864             : template <typename OutputType>
     865             : void
     866       22003 : MooseVariableFV<OutputType>::timestepSetup()
     867             : {
     868       22003 :   _dirichlet_map_setup = false;
     869       22003 :   _flux_map_setup = false;
     870       22003 :   MooseVariableField<OutputType>::timestepSetup();
     871       22003 : }
     872             : 
     873             : template <typename OutputType>
     874             : const typename MooseVariableFV<OutputType>::FieldVariablePhiValue &
     875           0 : MooseVariableFV<OutputType>::phiLower() const
     876             : {
     877           0 :   lowerDError();
     878             : }
     879             : 
     880             : template <typename OutputType>
     881             : void
     882           0 : MooseVariableFV<OutputType>::lowerDError() const
     883             : {
     884           0 :   mooseError("Lower dimensional element support not implemented for finite volume variables");
     885             : }
     886             : 
     887             : // Declare all the specializations, as the template specialization declaration below must know
     888             : template <>
     889             : ADReal MooseVariableFV<Real>::evaluateDot(const ElemArg & elem, const StateArg & state) const;
     890             : template <>
     891             : ADReal MooseVariableFV<Real>::evaluateDot(const FaceArg & elem_arg, const StateArg & state) const;
     892             : template <>
     893             : ADReal MooseVariableFV<Real>::evaluateDot(const ElemQpArg & elem_arg, const StateArg & state) const;
     894             : 
     895             : // Prevent implicit instantiation in other translation units where these classes are used
     896             : extern template class MooseVariableFV<Real>;

Generated by: LCOV version 1.14