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

Generated by: LCOV version 1.14