https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Classes | Enumerations | Functions | Variables
Moose::FV Namespace Reference

Classes

class  CentralDifferenceLimiter
 Implements a limiter which reproduces a central-differencing scheme, defined by $\beta(r_f) = 1$. More...
 
class  Limiter
 Base class for defining slope limiters for finite volume or potentially reconstructed Discontinuous-Galerkin applications. More...
 
struct  LimiterValueType
 
struct  LimiterValueType< ADReal >
 
struct  LimiterValueType< Real >
 
struct  LimiterValueType< T, typename std::enable_if< HasMemberType_value_type< T >::value >::type >
 
class  MinModLimiter
 The Min-Mod limiter function $\beta(r_f)$ is defined as: More...
 
class  QUICKLimiter
 The QUICK (Quadratic Upstream Interpolation for Convective Kinematics) limiter function is derived from the following equations: More...
 
class  SOULimiter
 The SOU limiter is used for reproducing the second-order-upwind scheme. More...
 
class  UpwindLimiter
 Implements a limiter which reproduces the upwind scheme, defined by $\beta(r_f) = 0$. More...
 
class  VanLeerLimiter
 The Van Leer limiter limiter function $\beta(r_f)$ is defined as: More...
 
class  VenkatakrishnanLimiter
 The Venkatakrishnan limiter is derived from the following equations: More...
 

Enumerations

enum class  GradientLimiterType : int { None = -1 , Venkatakrishnan = 0 }
 Cell-gradient limiter variants used for MUSCL-style reconstructions. More...
 
enum class  LimiterType : int {
  VanLeer = 0 , Upwind , CentralDifference , MinMod ,
  SOU , QUICK , Venkatakrishnan
}
 
enum class  InterpMethod {
  Average , HarmonicAverage , SkewCorrectedAverage , Upwind ,
  RhieChow , VanLeer , MinMod , SOU ,
  QUICK , Venkatakrishnan
}
 This codifies a set of available ways to interpolate with elem+neighbor solution information to calculate values (e.g. More...
 
enum class  LinearFVComputationMode { RHS , Matrix , FullSystem }
 

Functions

LimiterType limiterType (InterpMethod interp_method)
 Return the limiter type associated with the supplied interpolation method.
 
bool elemHasFaceInfo (const Elem &elem, const Elem *const neighbor)
 This function infers based on elements if the faceinfo between them belongs to the element or not.
 
template<typename ActionFunctor >
void loopOverElemFaceInfo (const Elem &elem, const MooseMesh &mesh, ActionFunctor &act, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
 
template<typename FVVar >
std::tuple< const Elem *, const Elem *, bool > determineElemOneAndTwo (const FaceInfo &fi, const FVVar &var)
 This utility determines element one and element two given a FaceInfo fi and variable var.
 
template<typename T , typename Enable = typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
libMesh::VectorValue< T > greenGaussGradient (const ElemArg &elem_arg, const StateArg &state_arg, const FunctorBase< T > &functor, const bool two_term_boundary_expansion, const MooseMesh &mesh, const bool force_green_gauss=false)
 Compute a cell gradient using the method of Green-Gauss.
 
template<typename T , typename Enable = typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
libMesh::VectorValue< T > greenGaussGradient (const FaceArg &face_arg, const StateArg &state_arg, const FunctorBase< T > &functor, const bool two_term_boundary_expansion, const MooseMesh &mesh)
 Compute a face gradient from Green-Gauss cell gradients, with orthogonality correction On the boundaries, the boundary element value is used.
 
template<typename T >
TensorValue< T > greenGaussGradient (const ElemArg &elem_arg, const StateArg &state_arg, const Moose::FunctorBase< libMesh::VectorValue< T > > &functor, const bool two_term_boundary_expansion, const MooseMesh &mesh)
 
template<typename T >
TensorValue< T > greenGaussGradient (const FaceArg &face_arg, const StateArg &state_arg, const Moose::FunctorBase< libMesh::VectorValue< T > > &functor, const bool two_term_boundary_expansion, const MooseMesh &mesh)
 
template<typename T >
Moose::FunctorBase< std::vector< T > >::GradientType greenGaussGradient (const ElemArg &elem_arg, const StateArg &state_arg, const Moose::FunctorBase< std::vector< T > > &functor, const bool two_term_boundary_expansion, const MooseMesh &mesh)
 
template<typename T >
Moose::FunctorBase< std::vector< T > >::GradientType greenGaussGradient (const FaceArg &face_arg, const StateArg &state_arg, const Moose::FunctorBase< std::vector< T > > &functor, const bool two_term_boundary_expansion, const MooseMesh &mesh)
 
template<typename T , std::size_t N>
Moose::FunctorBase< std::array< T, N > >::GradientType greenGaussGradient (const ElemArg &elem_arg, const StateArg &state_arg, const Moose::FunctorBase< std::array< T, N > > &functor, const bool two_term_boundary_expansion, const MooseMesh &mesh)
 
template<typename T , std::size_t N>
Moose::FunctorBase< std::array< T, N > >::GradientType greenGaussGradient (const FaceArg &face_arg, const StateArg &state_arg, const Moose::FunctorBase< std::array< T, N > > &functor, const bool two_term_boundary_expansion, const MooseMesh &mesh)
 
MooseEnum interpolationMethods ()
 Returns an enum with all the currently supported interpolation methods and the current default for FV: first-order upwind.
 
InputParameters advectedInterpolationParameter ()
 
InterpMethod selectInterpolationMethod (const std::string &interp_method)
 
bool setInterpolationMethod (const MooseObject &obj, Moose::FV::InterpMethod &interp_method, const std::string &param_name)
 Sets one interpolation method.
 
template<typename T = Real>
std::pair< Real, Real > interpCoeffs (const InterpMethod m, const FaceInfo &fi, const bool one_is_elem, const T &face_flux=0.0)
 Produce the interpolation coefficients in the equation:
 
template<typename T , typename T2 >
libMesh::CompareTypes< T, T2 >::supertype linearInterpolation (const T &value1, const T2 &value2, const FaceInfo &fi, const bool one_is_elem, const InterpMethod interp_method=InterpMethod::Average)
 A simple linear interpolation of values between cell centers to a cell face.
 
template<typename T1 , typename T2 >
libMesh::CompareTypes< T1, T2 >::supertype harmonicInterpolation (const T1 &value1, const T2 &value2, const FaceInfo &fi, const bool one_is_elem)
 Computes the harmonic mean (1/(gc/value1+(1-gc)/value2)) of Reals, RealVectorValues and RealTensorValues while accounting for the possibility that one or both of them are AD.
 
template<typename T , typename T2 , typename T3 >
libMesh::CompareTypes< T, T2 >::supertype skewCorrectedLinearInterpolation (const T &value1, const T2 &value2, const T3 &face_gradient, const FaceInfo &fi, const bool one_is_elem)
 Linear interpolation with skewness correction using the face gradient.
 
template<typename T , typename T2 , typename T3 >
void interpolate (InterpMethod m, T &result, const T2 &value1, const T3 &value2, const FaceInfo &fi, const bool one_is_elem)
 Provides interpolation of face values for non-advection-specific purposes (although it can/will still be used by advective kernels sometimes).
 
template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value>
linearInterpolation (const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
 perform a possibly skew-corrected linear interpolation by evaluating the supplied functor with the provided functor face argument
 
template<typename T1 , typename T2 , typename T3 , template< typename > class Vector1, template< typename > class Vector2>
void interpolate (InterpMethod m, Vector1< T1 > &result, const T2 &fi_elem_advected, const T2 &fi_neighbor_advected, const Vector2< T3 > &fi_elem_advector, const Vector2< T3 > &fi_neighbor_advector, const FaceInfo &fi)
 Computes the product of the advected and the advector based on the given interpolation method.
 
template<typename T , typename T2 , typename T3 , typename Vector >
void interpolate (InterpMethod m, T &result, const T2 &value1, const T3 &value2, const Vector &advector, const FaceInfo &fi, const bool one_is_elem)
 Provides interpolation of face values for advective flux kernels.
 
ADReal gradUDotNormal (const FaceInfo &face_info, const MooseVariableFV< Real > &fv_var, const Moose::StateArg &time, bool correct_skewness=false)
 Calculates and returns "grad_u dot normal" on the face to be used for diffusive terms.
 
template<typename Scalar , typename Vector >
Scalar rF (const Scalar &phiC, const Scalar &phiD, const Vector &gradC, const RealVectorValue &dCD)
 From Moukalled 12.30.
 
template<typename T >
std::pair< T, T > interpCoeffs (const Limiter< T > &limiter, const T &phi_upwind, const T &phi_downwind, const libMesh::VectorValue< T > *const grad_phi_upwind, const libMesh::VectorValue< T > *const grad_phi_face, const Real &max_value, const Real &min_value, const FaceInfo &fi, const bool fi_elem_is_upwind)
 Produce the interpolation coefficients in the equation:
 
template<typename Scalar , typename Vector , typename Enable = typename std::enable_if<libMesh::ScalarTraits<Scalar>::value>::type>
Scalar interpolate (const Limiter< Scalar > &limiter, const Scalar &phi_upwind, const Scalar &phi_downwind, const Vector *const grad_phi_upwind, const FaceInfo &fi, const bool fi_elem_is_upwind)
 Interpolates with a limiter.
 
template<typename Limiter , typename T , typename Tensor >
libMesh::VectorValue< T > interpolate (const Limiter &limiter, const TypeVector< T > &phi_upwind, const TypeVector< T > &phi_downwind, const Tensor *const grad_phi_upwind, const FaceInfo &fi, const bool fi_elem_is_upwind)
 Vector overload.
 
template<typename T >
fullLimitedInterpolation (const Limiter< T > &limiter, const T &phi_upwind, const T &phi_downwind, const VectorValue< T > *const grad_phi_upwind, const VectorValue< T > *const grad_phi_face, const Real &max_value, const Real &min_value, const FaceArg &face)
 This function performs a full limited interpolation of a variable, taking into account the values and gradients at both upwind and downwind locations, as well as geometric information and limits.
 
template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value, typename Enable = typename std::enable_if<ScalarTraits<T>::value>::type>
std::pair< Real, Real > computeMinMaxValue (const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
 This function calculates the minimum and maximum values within a two-cell stencil.
 
template<typename T >
std::pair< Real, Real > computeMinMaxValue (const FunctorBase< VectorValue< T > > &functor, const FaceArg &face, const StateArg &time, const unsigned int &component)
 This function calculates the minimum and maximum values of a specified component within a two-cell stencil.
 
template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value, typename Enable = typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
std::pair< std::pair< T, T >, std::pair< T, T > > interpCoeffsAndAdvected (const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
 This function interpolates values using a specified limiter and face argument.
 
template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value, typename Enable = typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
interpolate (const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
 This function interpolates values at faces in a computational grid using a specified functor, face argument, and evaluation kind.
 
template<typename T >
libMesh::VectorValue< T > interpolate (const FunctorBase< libMesh::VectorValue< T > > &functor, const FaceArg &face, const StateArg &time)
 This function interpolates vector values at faces in a computational grid using a specified functor, face argument, and limiter type.
 
template<typename T >
containerInterpolate (const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
 This function interpolates container values at faces in a computational grid using a specified functor, face argument, and limiter type.
 
template<typename T >
std::vector< T > interpolate (const FunctorBase< std::vector< T > > &functor, const FaceArg &face, const StateArg &time)
 
template<typename T , std::size_t N>
std::array< T, N > interpolate (const FunctorBase< std::array< T, N > > &functor, const FaceArg &face, const StateArg &time)
 
template<typename SubdomainRestrictable >
bool onBoundary (const SubdomainRestrictable &obj, const FaceInfo &fi)
 Return whether the supplied face is on a boundary of the object's execution.
 
bool onBoundary (const std::set< SubdomainID > &subs, const FaceInfo &fi)
 Determine whether the passed-in face is on the boundary of an object that lives on the provided subdomains.
 

Variables

const MooseEnum moose_limiter_type
 

Enumeration Type Documentation

◆ GradientLimiterType

enum class Moose::FV::GradientLimiterType : int
strong

Cell-gradient limiter variants used for MUSCL-style reconstructions.

This is intentionally separate from face/value limiter selections. Gradient limiting typically has fewer supported options and uses different data/loops.

Enumerator
None 

No gradient limiting.

Venkatakrishnan 

Venkatakrishnan limiter (smooth, multidimensional).

Definition at line 22 of file GradientLimiterType.h.

23{
25 None = -1,
28};
@ Venkatakrishnan
Venkatakrishnan limiter (smooth, multidimensional).
@ None
No gradient limiting.

◆ InterpMethod

enum class Moose::FV::InterpMethod
strong

This codifies a set of available ways to interpolate with elem+neighbor solution information to calculate values (e.g.

solution, material properties, etc.) at the face (centroid). These methods are used in the class's interpolate functions. Some interpolation methods are only meant to be used with advective terms (e.g. upwind), others are more generically applicable.

Enumerator
Average 

gc*elem+(1-gc)*neighbor

HarmonicAverage 

1/(gc/elem+(1-gc)/neighbor)

SkewCorrectedAverage 

(gc*elem+(1-gc)*neighbor)+gradient*(rf-rf')

Upwind 

weighted

RhieChow 
VanLeer 
MinMod 
SOU 
QUICK 
Venkatakrishnan 

Definition at line 38 of file MathFVUtils.h.

39{
41 Average,
47 Upwind,
48 // Rhie-Chow
50 VanLeer,
51 MinMod,
52 SOU,
53 QUICK,
55};
@ SkewCorrectedAverage
(gc*elem+(1-gc)*neighbor)+gradient*(rf-rf')
@ HarmonicAverage
1/(gc/elem+(1-gc)/neighbor)
@ Average
gc*elem+(1-gc)*neighbor

◆ LimiterType

enum class Moose::FV::LimiterType : int
strong
Enumerator
VanLeer 
Upwind 
CentralDifference 
MinMod 
SOU 
QUICK 
Venkatakrishnan 

Definition at line 26 of file Limiter.h.

27{
28 VanLeer = 0,
29 Upwind,
31 MinMod,
32 SOU,
33 QUICK,
35};
Implements a truly explicit (no nonlinear solve) Central Difference time integration scheme.

◆ LinearFVComputationMode

Enumerator
RHS 
Matrix 
FullSystem 

Definition at line 57 of file MathFVUtils.h.

Function Documentation

◆ advectedInterpolationParameter()

InputParameters Moose::FV::advectedInterpolationParameter ( )
Returns
An input parameters object that contains the advected_interp_method parameter, e.g. the interpolation method to use for an advected quantity

Definition at line 68 of file MathFVUtils.C.

69{
70 auto params = emptyInputParameters();
71 params.addParam<MooseEnum>("advected_interp_method",
73 "The interpolation to use for the advected quantity. Options are "
74 "'upwind', 'average', 'sou' (for second-order upwind), 'min_mod', "
75 "'vanLeer', 'quick', 'venkatakrishnan', and "
76 "'skewness-corrected' with the default being 'upwind'.");
77 return params;
78}
InputParameters emptyInputParameters()
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
MooseEnum interpolationMethods()
Returns an enum with all the currently supported interpolation methods and the current default for FV...
Definition MathFVUtils.C:61

Referenced by FVAdvection::validParams().

◆ computeMinMaxValue() [1/2]

template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value, typename Enable = typename std::enable_if<ScalarTraits<T>::value>::type>
std::pair< Real, Real > Moose::FV::computeMinMaxValue ( const FunctorBase< T > &  functor,
const FaceArg face,
const StateArg time 
)

This function calculates the minimum and maximum values within a two-cell stencil.

The stencil includes the immediate neighboring elements of the face's associated element and the neighboring elements of those neighbors. It evaluates the values using a provided functor and accounts for the valid (non-null) neighbors.

Template Parameters
TThe data type for the values being computed. This is typically a scalar type.
FEKEnumeration type FunctorEvaluationKind with a default value of FunctorEvaluationKind::Value. This determines the kind of evaluation the functor will perform.
EnableA type trait used for SFINAE (Substitution Failure Is Not An Error) to ensure that T is a valid scalar type as determined by ScalarTraits<T>.
Parameters
functorAn object of a functor class derived from FunctorBase<T>. This object provides the genericEvaluate method to compute the value at a given element and time.
faceAn argument representing the face in the computational domain. The face provides access to neighboring elements via neighbor_ptr_range().
timeAn argument representing the state or time at which the evaluation is performed.
Returns
std::pair<T, T> A pair containing the minimum and maximum values computed across the two-cell stencil. The first element is the maximum value, and the second element is the minimum value.

Definition at line 650 of file MathFVUtils.h.

651{
652 // Initialize max_value to 0 and min_value to a large value
653 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
654
655 // Iterate over the direct neighbors of the element associated with the face
656 for (const auto neighbor : (*face.fi).elem().neighbor_ptr_range())
657 {
658 // If not a valid neighbor, skip to the next one
659 if (neighbor == nullptr)
660 continue;
661
662 // Evaluate the functor at the neighbor and update max_value and min_value
663 const ElemArg local_cell_arg = {neighbor, false};
664 const auto value =
665 MetaPhysicL::raw_value(functor.template genericEvaluate<FEK>(local_cell_arg, time));
666 max_value = std::max(max_value, value);
667 min_value = std::min(min_value, value);
668 }
669
670 // Iterate over the neighbors of the neighbor
671 for (const auto neighbor : (*face.fi).neighbor().neighbor_ptr_range())
672 {
673 // If not a valid neighbor, skip to the next one
674 if (neighbor == nullptr)
675 continue;
676
677 // Evaluate the functor at the neighbor and update max_value and min_value
678 const ElemArg local_cell_arg = {neighbor, false};
679 const auto value =
680 MetaPhysicL::raw_value(functor.template genericEvaluate<FEK>(local_cell_arg, time));
681 max_value = std::max(max_value, value);
682 min_value = std::min(min_value, value);
683 }
684
685 // Return a pair containing the computed maximum and minimum values
686 return std::make_pair(max_value, min_value);
687}
auto raw_value(const Eigen::Map< T > &in)
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
A structure that is used to evaluate Moose functors logically at an element/cell center.

Referenced by interpCoeffsAndAdvected(), interpolate(), and interpolate().

◆ computeMinMaxValue() [2/2]

template<typename T >
std::pair< Real, Real > Moose::FV::computeMinMaxValue ( const FunctorBase< VectorValue< T > > &  functor,
const FaceArg face,
const StateArg time,
const unsigned int component 
)

This function calculates the minimum and maximum values of a specified component within a two-cell stencil.

The stencil includes the immediate neighboring elements of the face's associated element and the neighboring elements of those neighbors. It evaluates the values using a provided functor and accounts for the valid (non-null) neighbors.

Template Parameters
TThe data type for the values being computed. This is typically a scalar type.
Parameters
functorAn object of a functor class derived from FunctorBase<VectorValue<T>>. This object provides the operator() method to compute the value at a given element and time.
faceAn argument representing the face in the computational domain. The face provides access to neighboring elements via neighbor_ptr_range().
timeAn argument representing the state or time at which the evaluation is performed.
componentAn unsigned integer representing the specific component of the vector to be evaluated.
Returns
std::pair<T, T> A pair containing the minimum and maximum values of the specified component computed across the two-cell stencil. The first element is the maximum value, and the second element is the minimum value.

Usage: This function is typically used in the finite volume methods for min-max computations over stencils (neighborhoods). It helps compute the limiting for limited second order upwind at the faces.

Definition at line 716 of file MathFVUtils.h.

720{
721 // Initialize max_value to 0 and min_value to a large value
722 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
723
724 // Iterate over the direct neighbors of the element associated with the face
725 for (const auto neighbor : (*face.fi).elem().neighbor_ptr_range())
726 {
727 // If not a valid neighbor, skip to the next one
728 if (neighbor == nullptr)
729 continue;
730
731 // Evaluate the functor at the neighbor for the specified component and update max_value and
732 // min_value
733 const ElemArg local_cell_arg = {neighbor, false};
734 const auto value = MetaPhysicL::raw_value(functor(local_cell_arg, time)(component));
735 max_value = std::max(max_value, value);
736 min_value = std::min(min_value, value);
737 }
738
739 // Iterate over the neighbors of the neighbor associated with the face
740 for (const auto neighbor : (*face.fi).neighbor().neighbor_ptr_range())
741 {
742 // If not a valid neighbor, skip to the next one
743 if (neighbor == nullptr)
744 continue;
745
746 // Evaluate the functor at the neighbor for the specified component and update max_value and
747 // min_value
748 const ElemArg local_cell_arg = {neighbor, false};
749 const auto value = MetaPhysicL::raw_value(functor(local_cell_arg, time)(component));
750 max_value = std::max(max_value, value);
751 min_value = std::min(min_value, value);
752 }
753
754 // Return a pair containing the computed maximum and minimum values
755 return std::make_pair(max_value, min_value);
756}

◆ containerInterpolate()

template<typename T >
T Moose::FV::containerInterpolate ( const FunctorBase< T > &  functor,
const FaceArg face,
const StateArg time 
)

This function interpolates container values at faces in a computational grid using a specified functor, face argument, and limiter type.

It handles different limiter types and performs interpolation accordingly.

Template Parameters
TThe data type for the container values being interpolated. This is typically a container type such as a vector or array.
Parameters
functorAn object of a functor class derived from FunctorBase<T>. This object provides the operator() method to compute the value at a given element and time.
faceAn argument representing the face in the computational domain. The face provides access to neighboring elements and limiter type.
timeAn argument representing the state or time at which the evaluation is performed.
Returns
T The interpolated container value at the face.

Usage: This function is used for interpolating container values at faces in a finite volume method, ensuring that the interpolation adheres to the constraints imposed by the limiter.

Definition at line 1092 of file MathFVUtils.h.

1093{
1094 typedef typename FunctorBase<T>::GradientType ContainerGradientType;
1095 typedef typename ContainerGradientType::value_type GradientType;
1096 const GradientType * const example_gradient = nullptr;
1097
1098 mooseAssert(face.fi, "this must be non-null");
1099 const auto limiter = Limiter<typename T::value_type>::build(face.limiter_type);
1100
1101 const auto upwind_arg = face.elem_is_upwind ? face.makeElem() : face.makeNeighbor();
1102 const auto downwind_arg = face.elem_is_upwind ? face.makeNeighbor() : face.makeElem();
1103 const auto phi_upwind = functor(upwind_arg, time);
1104 const auto phi_downwind = functor(downwind_arg, time);
1105
1106 // initialize in order to get proper size
1107 T ret = phi_upwind;
1108 typename T::value_type coeff_upwind, coeff_downwind;
1109
1110 if (face.limiter_type == LimiterType::Upwind ||
1111 face.limiter_type == LimiterType::CentralDifference)
1112 {
1113 for (const auto i : index_range(ret))
1114 {
1115 const auto &component_upwind = phi_upwind[i], component_downwind = phi_downwind[i];
1116 std::tie(coeff_upwind, coeff_downwind) = interpCoeffs(*limiter,
1117 component_upwind,
1118 component_downwind,
1119 example_gradient,
1120 example_gradient,
1121 std::numeric_limits<Real>::max(),
1122 std::numeric_limits<Real>::min(),
1123 *face.fi,
1124 face.elem_is_upwind);
1125 ret[i] = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1126 }
1127 }
1128 else
1129 {
1130 const auto grad_phi_upwind = functor.gradient(upwind_arg, time);
1131 for (const auto i : index_range(ret))
1132 {
1133 const auto &component_upwind = phi_upwind[i], component_downwind = phi_downwind[i];
1134 const auto & grad = grad_phi_upwind[i];
1135 std::tie(coeff_upwind, coeff_downwind) = interpCoeffs(*limiter,
1136 component_upwind,
1137 component_downwind,
1138 &grad,
1139 example_gradient,
1140 std::numeric_limits<Real>::max(),
1141 std::numeric_limits<Real>::min(),
1142 *face.fi,
1143 face.elem_is_upwind);
1144 ret[i] = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1145 }
1146 }
1147
1148 return ret;
1149}
Base class for defining slope limiters for finite volume or potentially reconstructed Discontinuous-G...
Definition Limiter.h:63
typename FunctorReturnType< T, FunctorEvaluationKind::Gradient >::type GradientType
This rigmarole makes it so that a user can create functors that return containers (std::vector,...
GradientType gradient(const ElemArg &elem, const StateArg &state) const
Same as their evaluateGradient overloads with the same arguments but allows for caching implementatio...
std::pair< Real, Real > interpCoeffs(const InterpMethod m, const FaceInfo &fi, const bool one_is_elem, const T &face_flux=0.0)
Produce the interpolation coefficients in the equation:
ElemArg makeNeighbor() const
Make a ElemArg from our data using the face information neighbor.
bool elem_is_upwind
a boolean which states whether the face information element is upwind of the face
ElemArg makeElem() const
Make a ElemArg from our data using the face information element.
Moose::FV::LimiterType limiter_type
a limiter which defines how the functor evaluated on either side of the face should be interpolated t...
const FaceInfo * fi
a face information object which defines our location in space

Referenced by interpolate(), and interpolate().

◆ determineElemOneAndTwo()

template<typename FVVar >
std::tuple< const Elem *, const Elem *, bool > Moose::FV::determineElemOneAndTwo ( const FaceInfo fi,
const FVVar &  var 
)

This utility determines element one and element two given a FaceInfo fi and variable var.

You may ask what in the world "element one" and "element two" means, and that would be a very good question. What it means is: a variable will always have degrees of freedom on element one. A variable may or may not have degrees of freedom on element two. So we are introducing a second terminology here. FaceInfo geometric objects have element-neighbor pairs. These element-neighbor pairs are purely geometric and have no relation to the algebraic system of variables. The elem1-elem2 notation introduced here is based on dof/algebraic information and may very well be different from variable to variable, e.g. elem1 may correspond to the FaceInfo elem for one variable (and correspondingly elem2 will be the FaceInfo neighbor), but elem1 may correspond to the FaceInfo neighbor for another variable (and correspondingly for that variable elem2 will be the FaceInfo elem).

Returns
A tuple, where the first item is elem1, the second item is elem2, and the third item is a boolean indicating whether elem1 corresponds to the FaceInfo elem

Definition at line 130 of file FVUtils.h.

131{
132 auto ft = fi.faceType(std::make_pair(var.number(), var.sys().number()));
133 mooseAssert(ft == FaceInfo::VarFaceNeighbors::BOTH
134 ? var.hasBlocks(fi.elem().subdomain_id()) && fi.neighborPtr() &&
135 var.hasBlocks(fi.neighborPtr()->subdomain_id())
136 : true,
137 "Finite volume variable " << var.name()
138 << " does not exist on both sides of the face despite "
139 "what the FaceInfo is telling us.");
140 mooseAssert(ft == FaceInfo::VarFaceNeighbors::ELEM
141 ? var.hasBlocks(fi.elem().subdomain_id()) &&
142 (!fi.neighborPtr() || !var.hasBlocks(fi.neighborPtr()->subdomain_id()))
143 : true,
144 "Finite volume variable " << var.name()
145 << " does not exist on or only on the elem side of the "
146 "face despite what the FaceInfo is telling us.");
148 ? fi.neighborPtr() && var.hasBlocks(fi.neighborPtr()->subdomain_id()) &&
149 !var.hasBlocks(fi.elem().subdomain_id())
150 : true,
151 "Finite volume variable " << var.name()
152 << " does not exist on or only on the neighbor side of the "
153 "face despite what the FaceInfo is telling us.");
154
155 const bool one_is_elem =
157 const Elem * const elem_one = one_is_elem ? &fi.elem() : fi.neighborPtr();
158 mooseAssert(elem_one, "This elem should be non-null!");
159 const Elem * const elem_two = one_is_elem ? fi.neighborPtr() : &fi.elem();
160
161 return std::make_tuple(elem_one, elem_two, one_is_elem);
162}
VarFaceNeighbors faceType(const std::pair< unsigned int, unsigned int > &var_sys) const
Returns which side(s) the given variable-system number pair is defined on for this face.
Definition FaceInfo.h:229
const Elem & elem() const
Definition FaceInfo.h:85
const Elem * neighborPtr() const
Definition FaceInfo.h:88

◆ elemHasFaceInfo()

bool Moose::FV::elemHasFaceInfo ( const Elem &  elem,
const Elem *const  neighbor 
)

This function infers based on elements if the faceinfo between them belongs to the element or not.

Parameters
elemReference to an element
neighborPointer to the neighbor of the element
Returns
If the element (first argument) is the owner of the faceinfo between the two elements

Definition at line 21 of file FVUtils.C.

22{
23 // The face info belongs to elem:
24 // * at all mesh boundaries (i.e. where there is no neighbor)
25 // * if the element faces a neighbor which is on a lower refinement level
26 // * if the element is active and it has a lower ID than its neighbor
27 if (!neighbor)
28 return true;
29 else if (elem.level() != neighbor->level())
30 return neighbor->level() < elem.level();
31 else if (!neighbor->active())
32 return false;
33 else
34 return elem.id() < neighbor->id();
35}

Referenced by MooseMesh::buildFiniteVolumeInfo(), loopOverElemFaceInfo(), and ComputeLinearFVLimitedGradientThread::operator()().

◆ fullLimitedInterpolation()

template<typename T >
T Moose::FV::fullLimitedInterpolation ( const Limiter< T > &  limiter,
const T &  phi_upwind,
const T &  phi_downwind,
const VectorValue< T > *const  grad_phi_upwind,
const VectorValue< T > *const  grad_phi_face,
const Real &  max_value,
const Real &  min_value,
const FaceArg face 
)

This function performs a full limited interpolation of a variable, taking into account the values and gradients at both upwind and downwind locations, as well as geometric information and limits.

It applies the specified limiter to ensure the interpolation adheres to the constraints imposed by the limiter.

Template Parameters
TThe data type of the scalar values and the return type.
Parameters
limiterThe limiter object used to compute the flux limiting ratio.
phi_upwindThe field value at the upwind location.
phi_downwindThe field value at the downwind location.
grad_phi_upwindPointer to the gradient at the upwind location.
grad_phi_facePointer to the gradient at the face location.
fiFaceInfo object containing geometric details such as face centroid and cell centroids.
fi_elem_is_upwindBoolean indicating if the face info element is upwind.
max_valueThe maximum allowable value.
min_valueThe minimum allowable value.
Returns
The computed limited interpolation value.

Definition at line 585 of file MathFVUtils.h.

593{
594 // Compute the direction vector based on whether the current element is upwind
595 const auto dCD = face.elem_is_upwind ? face.fi->dCN() : Point(-face.fi->dCN());
596
597 // Compute the flux limiting ratio using the specified limiter
598 const auto beta = limiter(phi_upwind,
599 phi_downwind,
600 grad_phi_upwind,
601 grad_phi_face,
602 dCD,
603 max_value,
604 min_value,
605 face.fi,
606 face.elem_is_upwind);
607
608 // Determine the face centroid and the appropriate cell centroid
609 const auto & face_centroid = face.fi->faceCentroid();
610 const auto & cell_centroid =
611 face.elem_is_upwind ? face.fi->elemCentroid() : face.fi->neighborCentroid();
612
613 // Compute the delta value at the face
614 T delta_face;
615 if (face.limiter_type == LimiterType::Venkatakrishnan || face.limiter_type == LimiterType::SOU)
616 delta_face = (*grad_phi_upwind) * (face_centroid - cell_centroid);
617 else
618 delta_face = (*grad_phi_face) * (face_centroid - cell_centroid);
619
620 // Return the interpolated value
621 return phi_upwind + beta * delta_face;
622}
const Point & neighborCentroid() const
Definition FaceInfo.h:247
const Point & dCN() const
Definition FaceInfo.h:142
const Point & elemCentroid() const
Returns the element centroids of the elements on the elem and neighbor sides of the face.
Definition FaceInfo.h:99
const Point & faceCentroid() const
Returns the coordinates of the face centroid.
Definition FaceInfo.h:75

Referenced by interpolate(), and interpolate().

◆ gradUDotNormal()

ADReal Moose::FV::gradUDotNormal ( const FaceInfo face_info,
const MooseVariableFV< Real > &  fv_var,
const Moose::StateArg time,
bool  correct_skewness = false 
)

Calculates and returns "grad_u dot normal" on the face to be used for diffusive terms.

If using any cross-diffusion corrections, etc. all those calculations should be handled appropriately by this function.

Definition at line 18 of file MathFVUtils.C.

23{
24 return fv_var.adGradSln(face_info, time, correct_skewness) * face_info.normal();
25}
const Point & normal() const
Returns the unit normal vector for the face oriented outward from the face's elem element.
Definition FaceInfo.h:72
const ADTemplateVariableGradient< OutputType > & adGradSln() const override
AD grad solution getter.

Referenced by FVFluxKernel::gradUDotNormal().

◆ greenGaussGradient() [1/8]

template<typename T , typename Enable = typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
libMesh::VectorValue< T > Moose::FV::greenGaussGradient ( const ElemArg elem_arg,
const StateArg state_arg,
const FunctorBase< T > &  functor,
const bool  two_term_boundary_expansion,
const MooseMesh mesh,
const bool  force_green_gauss = false 
)

Compute a cell gradient using the method of Green-Gauss.

Parameters
elem_argAn element argument specifying the current element and whether to perform skew corrections
state_argA state argument that indicates what temporal / solution iteration data to use when evaluating the provided functor
functorThe functor that will provide information such as cell and face value evaluations necessary to construct the cell gradient
two_term_boundary_expansionWhether to perform a two-term expansion to compute extrapolated boundary face values. If this is true, then an implicit system has to be solved. If false, then the cell center value will be used as the extrapolated boundary face value
meshThe mesh on which we are computing the gradient
Returns
The computed cell gradient

Definition at line 44 of file GreenGaussGradient.h.

50{
51 mooseAssert(elem_arg.elem, "This should be non-null");
52 const auto coord_type = mesh.getCoordSystem(elem_arg.elem->subdomain_id());
53 const auto rz_radial_coord = mesh.getAxisymmetricRadialCoord();
54
55 const T elem_value = functor(elem_arg, state_arg);
56
57 // We'll count the number of extrapolated boundary faces (ebfs)
58 unsigned int num_ebfs = 0;
59
60 // Gradient to be returned
61 VectorValue<T> grad;
62
63 if (!elem_arg.correct_skewness || force_green_gauss) // Do Green-Gauss
64 {
65 try
66 {
67 bool volume_set = false;
68 Real volume = 0;
69
70 // If we are performing a two term Taylor expansion for extrapolated boundary faces (faces on
71 // boundaries that do not have associated Dirichlet conditions), then the element gradient
72 // depends on the boundary face value and the boundary face value depends on the element
73 // gradient, so we have a system of equations to solve. Here is the system:
74 //
75 // \nabla \phi_C - \frac{1}{V} \sum_{ebf} \phi_{ebf} \vec{S_f} =
76 // \frac{1}{V} \sum_{of} \phi_{of} \vec{S_f} eqn. 1
77 //
78 // \phi_{ebf} - \vec{d_{Cf}} \cdot \nabla \phi_C = \phi_C eqn. 2
79 //
80 // where $C$ refers to the cell centroid, $ebf$ refers to an extrapolated boundary face, $of$
81 // refers to "other faces", e.g. non-ebf faces, and $f$ is a general face. $d_{Cf}$ is the
82 // vector drawn from the element centroid to the face centroid, and $\vec{S_f}$ is the surface
83 // vector, e.g. the face area times the outward facing normal
84
85 // ebf eqns: element gradient coefficients, e.g. eqn. 2, LHS term 2 coefficient
86 std::vector<libMesh::VectorValue<Real>> ebf_grad_coeffs;
87 // ebf eqns: rhs b values. These will actually correspond to the elem_value so we can use a
88 // pointer and avoid copying. This is the RHS of eqn. 2
89 std::vector<const T *> ebf_b;
90
91 // elem grad eqns: ebf coefficients, e.g. eqn. 1, LHS term 2 coefficients
92 std::vector<libMesh::VectorValue<Real>> grad_ebf_coeffs;
93 // elem grad eqns: rhs b value, e.g. eqn. 1 RHS
94 libMesh::VectorValue<T> grad_b = 0;
95
96 auto action_functor = [&volume_set,
97 &volume,
98 &elem_value,
99 &elem_arg,
100 &num_ebfs,
101 &ebf_grad_coeffs,
102 &ebf_b,
103 &grad_ebf_coeffs,
104 &grad_b,
105 &state_arg,
106 &functor,
107 two_term_boundary_expansion,
108 coord_type,
109 rz_radial_coord](const Elem & libmesh_dbg_var(functor_elem),
110 const Elem *,
111 const FaceInfo * const fi,
112 const Point & surface_vector,
113 Real coord,
114 const bool elem_has_info)
115 {
116 mooseAssert(fi, "We need a FaceInfo for this action_functor");
117 mooseAssert(
118 elem_arg.elem == &functor_elem,
119 "Just a sanity check that the element being passed in is the one we passed out.");
120
121 if (functor.isExtrapolatedBoundaryFace(*fi, elem_arg.elem, state_arg))
122 {
123 if (two_term_boundary_expansion)
124 {
125 num_ebfs += 1;
126
127 // eqn. 2
128 ebf_grad_coeffs.push_back(-1. * (elem_has_info
129 ? (fi->faceCentroid() - fi->elemCentroid())
130 : (fi->faceCentroid() - fi->neighborCentroid())));
131 ebf_b.push_back(&elem_value);
132
133 // eqn. 1
134 grad_ebf_coeffs.push_back(-surface_vector);
135 }
136 else
137 // We are doing a one-term expansion for the extrapolated boundary faces, in which case
138 // we have no eqn. 2 and we have no second term in the LHS of eqn. 1. Instead we apply
139 // the element centroid value as the face value (one-term expansion) in the RHS of eqn.
140 // 1
141 grad_b += surface_vector * elem_value;
142 }
143 else
144 grad_b +=
145 surface_vector * functor(Moose::FaceArg{fi,
147 true,
148 elem_arg.correct_skewness,
149 elem_arg.elem,
150 nullptr},
151 state_arg);
152
153 if (!volume_set)
154 {
155 // We use the FaceInfo volumes because those values have been pre-computed and cached.
156 // An explicit call to elem->volume() here would incur unnecessary expense
157 if (elem_has_info)
158 {
160 fi->elemCentroid(), coord, coord_type, rz_radial_coord);
161 volume = fi->elemVolume() * coord;
162 }
163 else
164 {
166 fi->neighborCentroid(), coord, coord_type, rz_radial_coord);
167 volume = fi->neighborVolume() * coord;
168 }
169
170 volume_set = true;
171 }
172 };
173
175 *elem_arg.elem, mesh, action_functor, coord_type, rz_radial_coord);
176
177 mooseAssert(volume_set && volume > 0, "We should have set the volume");
178 grad_b /= volume;
179
181 {
182 mooseAssert(rz_radial_coord != libMesh::invalid_uint, "rz_radial_coord must be set");
183 grad_b(rz_radial_coord) -= elem_value / elem_arg.elem->vertex_average()(rz_radial_coord);
184 }
185
186 mooseAssert(
188 "We have not yet implemented the correct translation from gradient to divergence for "
189 "spherical coordinates yet.");
190
191 // test for simple case
192 if (num_ebfs == 0)
193 grad = grad_b;
194 else
195 {
196 // We have to solve a system
197 const unsigned int sys_dim = Moose::dim + num_ebfs;
198 DenseVector<T> x(sys_dim), b(sys_dim);
199 DenseMatrix<T> A(sys_dim, sys_dim);
200
201 // Let's make i refer to Moose::dim indices, and j refer to num_ebfs indices
202
203 // eqn. 1
204 for (const auto i : make_range(Moose::dim))
205 {
206 // LHS term 1 coeffs
207 A(i, i) = 1;
208
209 // LHS term 2 coeffs
210 for (const auto j : make_range(num_ebfs))
211 A(i, Moose::dim + j) = grad_ebf_coeffs[j](i) / volume;
212
213 // RHS
214 b(i) = grad_b(i);
215 }
216
217 // eqn. 2
218 for (const auto j : make_range(num_ebfs))
219 {
220 // LHS term 1 coeffs
221 A(Moose::dim + j, Moose::dim + j) = 1;
222
223 // LHS term 2 coeffs
224 for (const auto i : make_range(unsigned(Moose::dim)))
225 A(Moose::dim + j, i) = ebf_grad_coeffs[j](i);
226
227 // RHS
228 b(Moose::dim + j) = *ebf_b[j];
229 }
230
231 A.lu_solve(b, x);
232 // libMesh is generous about what it considers nonsingular. Let's check a little more
233 // strictly
234 if (MooseUtils::absoluteFuzzyEqual(MetaPhysicL::raw_value(A(sys_dim - 1, sys_dim - 1)), 0))
235 throw libMesh::LogicError("Matrix A is singular!");
236 for (const auto i : make_range(Moose::dim))
237 grad(i) = x(i);
238 }
239 }
240 catch (std::exception & e)
241 {
242 // Don't ignore any *real* errors; we only handle matrix
243 // singularity (LogicError in older libMesh, DegenerateMap in
244 // newer) here
245 if (!strstr(e.what(), "singular"))
246 throw;
247
248 // Retry without two-term
249 if (!two_term_boundary_expansion)
251 "I believe we should only get singular systems when two-term boundary expansion is "
252 "being used. The error thrown during the computation of the gradient: ",
253 e.what());
254
255 grad = greenGaussGradient(elem_arg, state_arg, functor, false, mesh, true);
256 }
257 }
258 else // Do Least-Squares
259 {
260 try
261 {
262
263 // The least squares method aims to find the gradient at the element centroid by minimizing
264 // the difference between the estimated and actual value differences across neighboring cells.
265 // The least squares formulation is:
266 //
267 // Minimize J = \sum_{n} [ w_n ((\nabla \phi_C \cdot \delta \vec{x}_n) - \delta \phi_n) ]^2
268 //
269 // where:
270 // - \‍(\nabla \phi_C\‍) is the gradient at the element centroid C (unknown).
271 // - \‍(\delta \vec{x}_n = \vec{x}_n - \vec{x}_C\‍) is the vector from the element centroid to
272 // neighbor \‍(n\‍).
273 // - \‍(\delta \phi_n = \phi_n - \phi_C\‍) is the difference in the scalar value between
274 // neighbor \‍(n\‍) and element \‍(C\‍).
275 // - w_n = 1/||\vec{x}_n|| is a vector of weights that is used to handle large aspect ratio
276 // cells
277 //
278 // To handle extrapolated boundary faces (faces on boundaries without Dirichlet conditions),
279 // we include additional unknowns and equations in the least squares system.
280 // For ebfs, we may not know the value \‍(\phi_n\‍), so we include it as an unknown.
281 // This results in an augmented system that simultaneously solves for the gradient and the ebf
282 // values.
283
284 // Get estimated number of faces in a cell
285 const auto ptr_range = elem_arg.elem->neighbor_ptr_range();
286 const size_t num_faces = std::distance(ptr_range.begin(), ptr_range.end());
287
288 // Lists to store position differences and value differences for least squares computation
289 std::vector<Point> delta_x_list; // List of position differences between neighbor centroids
290 // and element centroid
291 delta_x_list.reserve(num_faces);
292
293 std::vector<T>
294 delta_phi_list; // List of value differences between neighbor values and element value
295 delta_phi_list.reserve(num_faces);
296
297 // Variables to handle extrapolated boundary faces (ebfs) in the least squares method
298 std::vector<Point> delta_x_ebf_list; // Position differences for ebfs
299 delta_phi_list.reserve(num_faces);
300
301 std::vector<VectorValue<Real>>
302 ebf_grad_coeffs; // Coefficients for the gradient in ebf equations
303 delta_phi_list.reserve(num_faces);
304
305 std::vector<const T *> ebf_b; // RHS values for ebf equations (pointers to avoid copying)
306 delta_phi_list.reserve(num_faces);
307
308 unsigned int num_ebfs = 0; // Number of extrapolated boundary faces
309
310 // Action functor to collect data from each face of the element
311 auto action_functor = [&elem_value,
312 &elem_arg,
313 &num_ebfs,
314 &ebf_grad_coeffs,
315 &ebf_b,
316 &delta_x_list,
317 &delta_phi_list,
318 &delta_x_ebf_list,
319 &state_arg,
320 &functor,
321 two_term_boundary_expansion](const Elem & libmesh_dbg_var(loc_elem),
322 const Elem * loc_neigh,
323 const FaceInfo * const fi,
324 const Point & /*surface_vector*/,
325 Real /*coord*/,
326 const bool elem_has_info)
327 {
328 mooseAssert(fi, "We need a FaceInfo for this action_functor");
329 mooseAssert(
330 elem_arg.elem == &loc_elem,
331 "Just a sanity check that the element being passed in is the one we passed out.");
332
333 if (functor.isExtrapolatedBoundaryFace(*fi, elem_arg.elem, state_arg))
334 {
335 // Extrapolated Boundary Face (ebf)
336 const Point delta_x = elem_has_info ? (fi->faceCentroid() - fi->elemCentroid())
337 : (fi->faceCentroid() - fi->neighborCentroid());
338 delta_x_list.push_back(delta_x);
339
340 T delta_phi;
341
342 if (two_term_boundary_expansion)
343 {
344 // Two-term expansion: include ebf values as unknowns in the augmented system
345 num_ebfs += 1;
346
347 // Coefficient for the gradient in the ebf equation
348 ebf_grad_coeffs.push_back(-delta_x);
349 // RHS value for the ebf equation
350 ebf_b.push_back(&elem_value);
351
352 delta_phi = -elem_value;
353 delta_x_ebf_list.push_back(delta_x);
354 }
355 else
356 {
357 // One-term expansion: assume zero difference across the boundary (\delta \phi = 0)
358 delta_phi = T(0);
359 }
360 delta_phi_list.push_back(delta_phi);
361 }
362 else
363 {
364 // Internal Face or Boundary Face with Dirichlet condition
365 Point delta_x;
366 T neighbor_value;
367 if (functor.isInternalFace(*fi))
368 {
369 // Internal face with a neighboring element
370 delta_x = loc_neigh->vertex_average() - elem_arg.elem->vertex_average();
371
372 const ElemArg neighbor_arg = {loc_neigh, elem_arg.correct_skewness};
373 neighbor_value = functor(neighbor_arg, state_arg);
374 }
375 else
376 {
377 // Boundary face with Dirichlet condition
378 delta_x = elem_has_info ? (fi->faceCentroid() - fi->elemCentroid())
379 : (fi->faceCentroid() - fi->neighborCentroid());
380 neighbor_value = functor(Moose::FaceArg{fi,
382 true,
383 elem_arg.correct_skewness,
384 elem_arg.elem,
385 nullptr},
386 state_arg);
387 }
388
389 delta_x_list.push_back(delta_x);
390 delta_phi_list.push_back(neighbor_value - elem_value);
391 }
392 };
393
394 // Loop over element faces and apply the action_functor
396 *elem_arg.elem, mesh, action_functor, coord_type, rz_radial_coord);
397
398 // Compute Least Squares gradient
399 const unsigned int n = delta_x_list.size();
400 mooseAssert(n >= dim, "Not enough neighbors to perform least squares");
401
402 DenseMatrix<T> ATA(dim, dim);
403 DenseVector<T> ATb(dim);
404
405 // Assemble the normal equations for the least squares method
406 // ATA = \sum_n (\delta \vec{x}_n^T * \delta \vec{x}_n)
407 // ATb = \sum_n (\delta \vec{x}_n^T * \delta \phi_n)
408 ATA.zero();
409 ATb.zero();
410
411 for (unsigned int i = 0; i < n; ++i)
412 {
413 const Point & delta_x = delta_x_list[i];
414 const T & delta_phi = delta_phi_list[i];
415
416 for (unsigned int d1 = 0; d1 < dim; ++d1)
417 {
418 const Real dx_d1 = delta_x(d1);
419 const Real dx_norm = delta_x.norm();
420 const Real dx_d1_norm = dx_d1 / dx_norm;
421
422 for (unsigned int d2 = 0; d2 < dim; ++d2)
423 {
424 const Real dx_d2_norm = delta_x(d2) / dx_norm;
425 ATA(d1, d2) += dx_d1_norm * dx_d2_norm;
426 }
427
428 ATb(d1) += dx_d1_norm * delta_phi / dx_norm;
429 }
430 }
431
432 // Add regularization to ATA to prevent singularity
433 T epsilon = 1e-12; // Small regularization parameter
434 for (unsigned int d = 0; d < dim; ++d)
435 {
436 ATA(d, d) += epsilon;
437 }
438
439 if (num_ebfs == 0)
440 {
441 // Solve and store the least squares gradient
442 DenseVector<T> grad_ls(dim);
443 ATA.lu_solve(ATb, grad_ls);
444
445 // Store the least squares gradient
446 for (unsigned int d = 0; d < dim; ++d)
447 {
448 grad(d) = grad_ls(d);
449 }
450 }
451 else
452 {
453 // We have to solve a system of equations
454 const unsigned int sys_dim = Moose::dim + num_ebfs;
455 DenseVector<T> x(sys_dim), b(sys_dim);
456 DenseMatrix<T> A(sys_dim, sys_dim);
457
458 // Let's make i refer to Moose::dim indices, and j refer to num_ebfs indices
459
460 // eqn. 1: Element gradient equations
461 for (unsigned int d1 = 0; d1 < dim; ++d1)
462 {
463 // LHS term 1 coefficients (gradient components)
464 for (unsigned int d2 = 0; d2 < dim; ++d2)
465 A(d1, d2) = ATA(d1, d2);
466
467 // RHS
468 b(d1) = ATb(d1);
469 }
470
471 // LHS term 2 coefficients (ebf contributions)
472 for (const auto i : make_range(num_ebfs))
473 {
474 const Point & delta_x = delta_x_ebf_list[i];
475 for (unsigned int d1 = 0; d1 < dim; ++d1)
476 {
477 const Real dx_d1 = delta_x(d1);
478 A(d1, Moose::dim + i) -= dx_d1 / delta_x.norm() / delta_x.norm();
479 }
480 }
481
482 // eqn. 2: Extrapolated boundary face equations
483 for (const auto j : make_range(num_ebfs))
484 {
485 // LHS term 1 coefficients (ebf values)
486 A(Moose::dim + j, Moose::dim + j) = 1;
487
488 // LHS term 2 coefficients (gradient components)
489 for (const auto i : make_range(unsigned(Moose::dim)))
490 A(Moose::dim + j, i) = ebf_grad_coeffs[j](i);
491
492 // RHS
493 b(Moose::dim + j) = *ebf_b[j];
494 }
495
496 // Solve the system
497 A.lu_solve(b, x);
498
499 // Check for singularity
500 if (MooseUtils::absoluteFuzzyEqual(MetaPhysicL::raw_value(A(sys_dim - 1, sys_dim - 1)), 0))
501 throw libMesh::LogicError("Matrix A is singular!");
502
503 // Extract the gradient components
504 for (const auto i : make_range(Moose::dim))
505 grad(i) = x(i);
506 }
507
508 mooseAssert(
510 "We have not yet implemented the correct translation from gradient to divergence for "
511 "spherical coordinates yet.");
512 }
513 catch (std::exception & e)
514 {
515 // Don't ignore any *real* errors; we only handle matrix
516 // singularity (LogicError in older libMesh, DegenerateMap in
517 // newer) here
518 if (!strstr(e.what(), "singular"))
519 throw;
520
521 // Log warning and default to simple green Gauss
523 "Singular matrix encountered in least squares gradient computation. Falling back "
524 "to Green-Gauss gradient.");
525
526 grad = greenGaussGradient(
527 elem_arg, state_arg, functor, false, mesh, /* force_green_gauss */ true);
528 }
529 }
530
531 return grad;
532
533 // Notes to future developer:
534 // Note 1:
535 // For the least squares gradient, the LS matrix could be precomputed and stored for every cell
536 // I tried doing this on October 2024, but the element lookup for these matrices is too slow
537 // and seems better to compute weights on the fly.
538 // Consider building a map from elem_id to these matrices and speed up lookup with octree
539 // Note 2:
540 // In the future one would like to have a hybrid gradient scheme, where:
541 // \nabla \phi = \beta (\nabla \phi)_{LS} + (1 - \beta) (\nabla \phi)_{GG}
542 // Then optize \beta based on mesh heuristics
543}
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition MooseError.h:345
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
unsigned int dim
This data structure is used to store geometric and variable related metadata about each cell face in ...
Definition FaceInfo.h:38
subdomain_id_type subdomain_id() const
MeshBase & mesh
void coordTransformFactor(const P &point, C &factor, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
Compute a coordinate transformation volume integration factor.
void loopOverElemFaceInfo(const Elem &elem, const MooseMesh &mesh, ActionFunctor &act, const Moose::CoordinateSystemType coord_type, const unsigned int rz_radial_coord=libMesh::invalid_uint)
Definition FVUtils.h:42
libMesh::VectorValue< T > greenGaussGradient(const ElemArg &elem_arg, const StateArg &state_arg, const FunctorBase< T > &functor, const bool two_term_boundary_expansion, const MooseMesh &mesh, const bool force_green_gauss=false)
Compute a cell gradient using the method of Green-Gauss.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition Moose.h:165
@ COORD_RZ
Definition MooseTypes.h:866
@ COORD_RSPHERICAL
Definition MooseTypes.h:867
Real volume(const MeshBase &mesh, unsigned int dim=libMesh::invalid_uint)
const unsigned int invalid_uint
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
const libMesh::Elem * elem
A structure defining a "face" evaluation calling argument for Moose functors.
bool correct_skewness
Whether to perform skew correction.

Referenced by MooseVariableFV< OutputType >::adGradSln(), PiecewiseByBlockLambdaFunctor< T >::evaluateGradient(), PiecewiseByBlockLambdaFunctor< T >::evaluateGradient(), greenGaussGradient(), greenGaussGradient(), greenGaussGradient(), greenGaussGradient(), greenGaussGradient(), greenGaussGradient(), greenGaussGradient(), and greenGaussGradient().

◆ greenGaussGradient() [2/8]

template<typename T >
TensorValue< T > Moose::FV::greenGaussGradient ( const ElemArg elem_arg,
const StateArg state_arg,
const Moose::FunctorBase< libMesh::VectorValue< T > > &  functor,
const bool  two_term_boundary_expansion,
const MooseMesh mesh 
)

Definition at line 621 of file GreenGaussGradient.h.

626{
627 TensorValue<T> ret;
628 for (const auto i : make_range(Moose::dim))
629 {
630 VectorComponentFunctor<T> scalar_functor(functor, i);
631 const auto row_gradient =
632 greenGaussGradient(elem_arg, state_arg, scalar_functor, two_term_boundary_expansion, mesh);
633 for (const auto j : make_range(unsigned(Moose::dim)))
634 ret(i, j) = row_gradient(j);
635 }
636
637 return ret;
638}
This is essentially a forwarding functor that forwards the spatial and temporal evaluation arguments ...

◆ greenGaussGradient() [3/8]

template<typename T , std::size_t N>
Moose::FunctorBase< std::array< T, N > >::GradientType Moose::FV::greenGaussGradient ( const ElemArg elem_arg,
const StateArg state_arg,
const Moose::FunctorBase< std::array< T, N > > &  functor,
const bool  two_term_boundary_expansion,
const MooseMesh mesh 
)

Definition at line 713 of file GreenGaussGradient.h.

718{
719 typedef typename Moose::FunctorBase<std::array<T, N>>::GradientType GradientType;
720 GradientType ret;
721 for (const auto i : make_range(N))
722 {
723 // Note that this can be very inefficient. Within the scalar greenGaussGradient routine we're
724 // going to do value type evaluations of the array functor from scalar_functor and we will be
725 // discarding all the value type evaluations other than the one corresponding to i
727 ret[i] =
728 greenGaussGradient(elem_arg, state_arg, scalar_functor, two_term_boundary_expansion, mesh);
729 }
730
731 return ret;
732}
This is essentially a forwarding functor that forwards the spatial and temporal evaluation arguments ...
Base class template for functor objects.

◆ greenGaussGradient() [4/8]

template<typename T >
Moose::FunctorBase< std::vector< T > >::GradientType Moose::FV::greenGaussGradient ( const ElemArg elem_arg,
const StateArg state_arg,
const Moose::FunctorBase< std::vector< T > > &  functor,
const bool  two_term_boundary_expansion,
const MooseMesh mesh 
)

Definition at line 663 of file GreenGaussGradient.h.

668{
669 // Determine the size of the container
670 const auto vals = functor(elem_arg, state_arg);
671 typedef typename Moose::FunctorBase<std::vector<T>>::GradientType GradientType;
672 GradientType ret(vals.size());
673 for (const auto i : index_range(ret))
674 {
675 // Note that this can be very inefficient. Within the scalar greenGaussGradient routine we're
676 // going to do value type evaluations of the array functor from scalar_functor and we will be
677 // discarding all the value type evaluations other than the one corresponding to i
678 ArrayComponentFunctor<T, FunctorBase<std::vector<T>>> scalar_functor(functor, i);
679 ret[i] =
680 greenGaussGradient(elem_arg, state_arg, scalar_functor, two_term_boundary_expansion, mesh);
681 }
682
683 return ret;
684}

◆ greenGaussGradient() [5/8]

template<typename T , typename Enable = typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
libMesh::VectorValue< T > Moose::FV::greenGaussGradient ( const FaceArg face_arg,
const StateArg state_arg,
const FunctorBase< T > &  functor,
const bool  two_term_boundary_expansion,
const MooseMesh mesh 
)

Compute a face gradient from Green-Gauss cell gradients, with orthogonality correction On the boundaries, the boundary element value is used.

Parameters
face_argA face argument specifying the current faceand whether to perform skew corrections
state_argA state argument that indicates what temporal / solution iteration data to use when evaluating the provided functor
functorThe functor that will provide information such as cell and face value evaluations necessary to construct the cell gradient
two_term_boundary_expansionWhether to perform a two-term expansion to compute extrapolated boundary face values. If this is true, then an implicit system has to be solved. If false, then the cell center value will be used as the extrapolated boundary face value
meshThe mesh on which we are computing the gradient
Returns
The computed cell gradient

Definition at line 563 of file GreenGaussGradient.h.

568{
569 mooseAssert(face_arg.fi, "We should have a face info to compute a face gradient");
570 const auto & fi = *(face_arg.fi);
571 const auto & elem_arg = face_arg.makeElem();
572 const auto & neighbor_arg = face_arg.makeNeighbor();
573 const bool defined_on_elem = functor.hasBlocks(fi.elemSubdomainID());
574 const bool defined_on_neighbor = fi.neighborPtr() && functor.hasBlocks(fi.neighborSubdomainID());
575
576 if (defined_on_elem && defined_on_neighbor)
577 {
578 const auto & value_elem = functor(elem_arg, state_arg);
579 const auto & value_neighbor = functor(neighbor_arg, state_arg);
580
581 // This is the component of the gradient which is parallel to the line connecting
582 // the cell centers. Therefore, we can use our second order, central difference
583 // scheme to approximate it.
584 libMesh::VectorValue<T> face_gradient = (value_neighbor - value_elem) / fi.dCNMag() * fi.eCN();
585
586 // We only need nonorthogonal correctors in 2+ dimensions
587 if (mesh.dimension() > 1)
588 {
589 // We are using an orthogonal approach for the non-orthogonal correction, for more information
590 // see Hrvoje Jasak's PhD Thesis (Imperial College, 1996)
591 libMesh::VectorValue<T> interpolated_gradient;
592
593 // Compute the gradients in the two cells on both sides of the face
594 const auto & grad_elem =
595 greenGaussGradient(elem_arg, state_arg, functor, two_term_boundary_expansion, mesh);
596 const auto & grad_neighbor =
597 greenGaussGradient(neighbor_arg, state_arg, functor, two_term_boundary_expansion, mesh);
598
600 interpolated_gradient,
601 grad_elem,
602 grad_neighbor,
603 fi,
604 true);
605
606 face_gradient += interpolated_gradient - (interpolated_gradient * fi.eCN()) * fi.eCN();
607 }
608
609 return face_gradient;
610 }
611 else if (defined_on_elem)
612 return functor.gradient(elem_arg, state_arg);
613 else if (defined_on_neighbor)
614 return functor.gradient(neighbor_arg, state_arg);
615 else
616 mooseError("The functor must be defined on one of the sides");
617}
virtual bool hasBlocks(SubdomainID) const
Returns whether the functor is defined on this block.
void interpolate(InterpMethod m, T &result, const T2 &value1, const T3 &value2, const FaceInfo &fi, const bool one_is_elem)
Provides interpolation of face values for non-advection-specific purposes (although it can/will still...

◆ greenGaussGradient() [6/8]

template<typename T >
TensorValue< T > Moose::FV::greenGaussGradient ( const FaceArg face_arg,
const StateArg state_arg,
const Moose::FunctorBase< libMesh::VectorValue< T > > &  functor,
const bool  two_term_boundary_expansion,
const MooseMesh mesh 
)

Definition at line 642 of file GreenGaussGradient.h.

647{
648 TensorValue<T> ret;
649 for (const auto i : make_range(unsigned(Moose::dim)))
650 {
651 VectorComponentFunctor<T> scalar_functor(functor, i);
652 const auto row_gradient =
653 greenGaussGradient(face_arg, state_arg, scalar_functor, two_term_boundary_expansion, mesh);
654 for (const auto j : make_range(unsigned(Moose::dim)))
655 ret(i, j) = row_gradient(j);
656 }
657
658 return ret;
659}

◆ greenGaussGradient() [7/8]

template<typename T , std::size_t N>
Moose::FunctorBase< std::array< T, N > >::GradientType Moose::FV::greenGaussGradient ( const FaceArg face_arg,
const StateArg state_arg,
const Moose::FunctorBase< std::array< T, N > > &  functor,
const bool  two_term_boundary_expansion,
const MooseMesh mesh 
)

Definition at line 736 of file GreenGaussGradient.h.

741{
742 typedef typename Moose::FunctorBase<std::array<T, N>>::GradientType GradientType;
743 GradientType ret;
744 for (const auto i : make_range(N))
745 {
746 // Note that this can be very inefficient. Within the scalar greenGaussGradient routine we're
747 // going to do value type evaluations of the array functor from scalar_functor and we will be
748 // discarding all the value type evaluations other than the one corresponding to i
750 ret[i] =
751 greenGaussGradient(face_arg, state_arg, scalar_functor, two_term_boundary_expansion, mesh);
752 }
753
754 return ret;
755}

◆ greenGaussGradient() [8/8]

template<typename T >
Moose::FunctorBase< std::vector< T > >::GradientType Moose::FV::greenGaussGradient ( const FaceArg face_arg,
const StateArg state_arg,
const Moose::FunctorBase< std::vector< T > > &  functor,
const bool  two_term_boundary_expansion,
const MooseMesh mesh 
)

Definition at line 688 of file GreenGaussGradient.h.

693{
694 // Determine the size of the container
695 const auto vals = functor(face_arg, state_arg);
696 typedef typename Moose::FunctorBase<std::vector<T>>::GradientType GradientType;
697 GradientType ret(vals.size());
698 for (const auto i : index_range(ret))
699 {
700 // Note that this can be very inefficient. Within the scalar greenGaussGradient routine we're
701 // going to do value type evaluations of the array functor from scalar_functor and we will be
702 // discarding all the value type evaluations other than the one corresponding to i
703 ArrayComponentFunctor<T, FunctorBase<std::vector<T>>> scalar_functor(functor, i);
704 ret[i] =
705 greenGaussGradient(face_arg, state_arg, scalar_functor, two_term_boundary_expansion, mesh);
706 }
707
708 return ret;
709}

◆ harmonicInterpolation()

template<typename T1 , typename T2 >
libMesh::CompareTypes< T1, T2 >::supertype Moose::FV::harmonicInterpolation ( const T1 &  value1,
const T2 &  value2,
const FaceInfo fi,
const bool  one_is_elem 
)

Computes the harmonic mean (1/(gc/value1+(1-gc)/value2)) of Reals, RealVectorValues and RealTensorValues while accounting for the possibility that one or both of them are AD.

For tensors, we use a component-wise mean instead of the matrix-inverse based option.

Parameters
value1Reference to value1 in the (1/(gc/value1+(1-gc)/value2)) expression
value2Reference to value2 in the (1/(gc/value1+(1-gc)/value2)) expression
fiReference to the FaceInfo of the face on which the interpolation is requested
one_is_elemBoolean indicating if the interpolation weight on FaceInfo belongs to the element corresponding to value1
Returns
The interpolated value

Definition at line 180 of file MathFVUtils.h.

184{
185 // We check if the base values of the given template types match, if not we throw a compile-time
186 // error
187 static_assert(std::is_same<typename MetaPhysicL::RawType<T1>::value_type,
188 typename MetaPhysicL::RawType<T2>::value_type>::value,
189 "The input values for harmonic interpolation need to have the same raw-value!");
190
191 // Fetch the interpolation coefficients, we use the exact same coefficients as for a simple
192 // weighted average
193 const auto coeffs = interpCoeffs(InterpMethod::Average, fi, one_is_elem);
194
195 // We check if the types are fit to compute the harmonic mean of. This is done compile-time
196 // using constexpr. We start with Real/ADReal which is straightforward if the input values are
197 // positive.
199 {
200 // The harmonic mean of mixed positive and negative numbers (and 0 as well) is not well-defined
201 // so we assert that the input values shall be positive.
202#ifndef NDEBUG
203 if (value1 * value2 <= 0)
204 mooseWarning("Input values (" + Moose::stringify(MetaPhysicL::raw_value(value1)) + " & " +
206 ") must be of the same sign for harmonic interpolation");
207#endif
208 return 1.0 / (coeffs.first / value1 + coeffs.second / value2);
209 }
210 // For vectors (ADRealVectorValue, VectorValue), we take the component-wise harmonic mean
211 else if constexpr (libMesh::TensorTools::TensorTraits<T1>::rank == 1)
212 {
214 for (const auto i : make_range(Moose::dim))
215 {
216#ifndef NDEBUG
217 if (value1(i) * value2(i) <= 0)
218 mooseWarning("Component " + std::to_string(i) + " of input values (" +
219 Moose::stringify(MetaPhysicL::raw_value(value1(i))) + " & " +
221 ") must be of the same sign for harmonic interpolation");
222#endif
223 result(i) = 1.0 / (coeffs.first / value1(i) + coeffs.second / value2(i));
224 }
225 return result;
226 }
227 // For tensors (ADRealTensorValue, TensorValue), similarly to the vectors,
228 // we take the component-wise harmonic mean instead of the matrix-inverse approach
229 else if constexpr (libMesh::TensorTools::TensorTraits<T1>::rank == 2)
230 {
232 for (const auto i : make_range(Moose::dim))
233 for (const auto j : make_range(Moose::dim))
234 {
235#ifndef NDEBUG
236 if (value1(i, j) * value2(i, j) <= 0)
237 mooseWarning("Component (" + std::to_string(i) + "," + std::to_string(j) +
238 ") of input values (" +
239 Moose::stringify(MetaPhysicL::raw_value(value1(i, j))) + " & " +
241 ") must be of the same sign for harmonic interpolation");
242#endif
243 result(i, j) = 1.0 / (coeffs.first / value1(i, j) + coeffs.second / value2(i, j));
244 }
245 return result;
246 }
247 // We ran out of options, harmonic mean is not supported for other types at the moment
248 else
249 // This line is supposed to throw an error when the user tries to compile this function with
250 // types that are not supported. This is the reason we needed the always_false function. Hope as
251 // C++ gets nicer, we can do this in a nicer way.
252 static_assert(Moose::always_false<T1>,
253 "Harmonic interpolation is not implemented for the used type!");
254}
for(PetscInt i=0;i< nvars;++i)
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64

Referenced by interpolate().

◆ interpCoeffs() [1/2]

template<typename T = Real>
std::pair< Real, Real > Moose::FV::interpCoeffs ( const InterpMethod  m,
const FaceInfo fi,
const bool  one_is_elem,
const T &  face_flux = 0.0 
)

Produce the interpolation coefficients in the equation:

\phi_f = c_1 * \phi_{F1} + c_2 * \phi_{F2}

A couple of examples: if we are doing an average interpolation with an orthogonal regular grid, then the pair will be (0.5, 0.5). If we are doing an upwind interpolation with the velocity facing outward from the F1 element, then the pair will be (1.0, 0.0).

The template is needed in case the face flux carries derivatives in an AD setting.

Parameters
mThe interpolation method
fiThe face information
one_is_elemWhether fi.elem() == F1
face_fluxThe advecting face flux. Not relevant for an Average interpolation
Returns
a pair where the first Real is c_1 and the second Real is c_2

Definition at line 117 of file MathFVUtils.h.

121{
122 switch (m)
123 {
124 case InterpMethod::Average:
125 case InterpMethod::SkewCorrectedAverage:
126 {
127 if (one_is_elem)
128 return std::make_pair(fi.gC(), 1. - fi.gC());
129 else
130 return std::make_pair(1. - fi.gC(), fi.gC());
131 }
132
133 case InterpMethod::Upwind:
134 {
135 if ((face_flux > 0) == one_is_elem)
136 return std::make_pair(1., 0.);
137 else
138 return std::make_pair(0., 1.);
139 }
140
141 default:
142 mooseError("Unrecognized interpolation method");
143 }
144}
Real gC() const
Return the geometric weighting factor.
Definition FaceInfo.h:136

Referenced by containerInterpolate(), harmonicInterpolation(), interpCoeffsAndAdvected(), interpolate(), interpolate(), interpolate(), linearInterpolation(), and skewCorrectedLinearInterpolation().

◆ interpCoeffs() [2/2]

template<typename T >
std::pair< T, T > Moose::FV::interpCoeffs ( const Limiter< T > &  limiter,
const T &  phi_upwind,
const T &  phi_downwind,
const libMesh::VectorValue< T > *const  grad_phi_upwind,
const libMesh::VectorValue< T > *const  grad_phi_face,
const Real &  max_value,
const Real &  min_value,
const FaceInfo fi,
const bool  fi_elem_is_upwind 
)

Produce the interpolation coefficients in the equation:

\phi_f = c_upwind * \phi_{upwind} + c_downwind * \phi_{downwind}

A couple of examples: if we are doing an average interpolation with an orthogonal regular grid, then the pair will be (0.5, 0.5). If we are doing an upwind interpolation then the pair will be (1.0, 0.0).

Returns
a pair where the first Real is c_upwind and the second Real is c_downwind

Definition at line 477 of file MathFVUtils.h.

486{
487 // Using beta, w_f, g nomenclature from Greenshields
488 const auto beta = limiter(phi_upwind,
489 phi_downwind,
490 grad_phi_upwind,
491 grad_phi_face,
492 fi_elem_is_upwind ? fi.dCN() : Point(-fi.dCN()),
493 max_value,
494 min_value,
495 &fi,
496 fi_elem_is_upwind);
497
498 const auto w_f = fi_elem_is_upwind ? fi.gC() : (1. - fi.gC());
499
500 const auto g = beta * (1. - w_f);
501
502 return std::make_pair(1. - g, g);
503}

◆ interpCoeffsAndAdvected()

template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value, typename Enable = typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
std::pair< std::pair< T, T >, std::pair< T, T > > Moose::FV::interpCoeffsAndAdvected ( const FunctorBase< T > &  functor,
const FaceArg face,
const StateArg time 
)

This function interpolates values using a specified limiter and face argument.

It evaluates the values at upwind and downwind locations and computes interpolation coefficients and advected values.

Template Parameters
TThe data type for the values being interpolated. This is typically a scalar type.
FEKEnumeration type FunctorEvaluationKind with a default value of FunctorEvaluationKind::Value. This determines the kind of evaluation the functor will perform.
EnableA type trait used for SFINAE (Substitution Failure Is Not An Error) to ensure that T is a valid scalar type as determined by ScalarTraits<T>.
Parameters
functorAn object of a functor class derived from FunctorBase<T>. This object provides the genericEvaluate method to compute the value at a given element and time.
faceAn argument representing the face in the computational domain. The face provides access to neighboring elements and limiter type.
timeAn argument representing the state or time at which the evaluation is performed.
Returns
std::pair<std::pair<T, T>, std::pair<T, T>> A pair of pairs.
  • The first pair corresponds to the interpolation coefficients, with the first value corresponding to the face information element and the second to the face information neighbor. This pair should sum to unity.
  • The second pair corresponds to the face information functor element value and neighbor value.

Usage: This function is used for interpolating values at faces in a finite volume method, ensuring that the interpolation adheres to the constraints imposed by the limiter.

Definition at line 790 of file MathFVUtils.h.

791{
792 // Ensure only supported FunctorEvaluationKinds are used
793 static_assert((FEK == FunctorEvaluationKind::Value) || (FEK == FunctorEvaluationKind::Dot),
794 "Only Value and Dot evaluations currently supported");
795
796 // Determine the gradient evaluation kind
798 typedef typename FunctorBase<T>::GradientType GradientType;
799 static const GradientType zero(0);
800
801 mooseAssert(face.fi, "this must be non-null");
802
803 // Construct the limiter based on the face limiter type
804 const auto limiter = Limiter<typename LimiterValueType<T>::value_type>::build(face.limiter_type);
805
806 // Determine upwind and downwind arguments based on the face element
807 const auto upwind_arg = face.elem_is_upwind ? face.makeElem() : face.makeNeighbor();
808 const auto downwind_arg = face.elem_is_upwind ? face.makeNeighbor() : face.makeElem();
809
810 // Evaluate the functor at the upwind and downwind locations
811 auto phi_upwind = functor.template genericEvaluate<FEK>(upwind_arg, time);
812 auto phi_downwind = functor.template genericEvaluate<FEK>(downwind_arg, time);
813
814 // Initialize the interpolation coefficients
815 std::pair<T, T> interp_coeffs;
816
817 // Compute interpolation coefficients for Upwind or CentralDifference limiters
818 if (face.limiter_type == LimiterType::Upwind ||
819 face.limiter_type == LimiterType::CentralDifference)
820 interp_coeffs = interpCoeffs(*limiter,
821 phi_upwind,
822 phi_downwind,
823 &zero,
824 &zero,
825 std::numeric_limits<Real>::max(),
826 std::numeric_limits<Real>::min(),
827 *face.fi,
828 face.elem_is_upwind);
829 else
830 {
831 // Determine the time argument for the limiter
832 auto * time_arg = face.state_limiter;
833 if (!time_arg)
834 {
836 time_arg = &temp_state;
837 }
838
839 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
840
841 // Compute min-max values for min-max limiters
842 if (face.limiter_type == LimiterType::Venkatakrishnan || face.limiter_type == LimiterType::SOU)
843 std::tie(max_value, min_value) = computeMinMaxValue(functor, face, *time_arg);
844
845 // Evaluate the gradient of the functor at the upwind and downwind locations
846 const auto grad_phi_upwind = functor.template genericEvaluate<GFEK>(upwind_arg, *time_arg);
847 const auto grad_phi_face = functor.template genericEvaluate<GFEK>(face, *time_arg);
848
849 // Compute the interpolation coefficients using the specified limiter
850 interp_coeffs = interpCoeffs(*limiter,
851 phi_upwind,
852 phi_downwind,
853 &grad_phi_upwind,
854 &grad_phi_face,
855 max_value,
856 min_value,
857 *face.fi,
858 face.elem_is_upwind);
859 }
860
861 // Return the interpolation coefficients and advected values
862 if (face.elem_is_upwind)
863 return std::make_pair(std::move(interp_coeffs),
864 std::make_pair(std::move(phi_upwind), std::move(phi_downwind)));
865 else
866 return std::make_pair(
867 std::make_pair(std::move(interp_coeffs.second), std::move(interp_coeffs.first)),
868 std::make_pair(std::move(phi_downwind), std::move(phi_upwind)));
869}
FunctorEvaluationKind
An enumeration of possible functor evaluation kinds.
const Moose::StateArg * state_limiter
A member that can be used to define the instance in which the limiters are executed.
This structure takes an evaluation kind as a template argument and defines a constant expression indi...
State argument for evaluating functors.

◆ interpolate() [1/9]

template<typename T >
libMesh::VectorValue< T > Moose::FV::interpolate ( const FunctorBase< libMesh::VectorValue< T > > &  functor,
const FaceArg face,
const StateArg time 
)

This function interpolates vector values at faces in a computational grid using a specified functor, face argument, and limiter type.

It handles different limiter types and performs interpolation accordingly.

Template Parameters
TThe data type for the vector values being interpolated. This is typically a scalar type.
Parameters
functorAn object of a functor class derived from FunctorBase<VectorValue<T>>. This object provides the operator() method to compute the value at a given element and time.
faceAn argument representing the face in the computational domain. The face provides access to neighboring elements and limiter type.
timeAn argument representing the state or time at which the evaluation is performed.
Returns
VectorValue<T> The interpolated vector value at the face.

Usage: This function is used for interpolating vector values at faces in a finite volume method, ensuring that the interpolation adheres to the constraints imposed by the limiter.

Definition at line 983 of file MathFVUtils.h.

986{
987 // Define a zero gradient vector for initialization
988 static const libMesh::VectorValue<T> grad_zero(0);
989
990 mooseAssert(face.fi, "this must be non-null");
991
992 // Construct the limiter based on the face limiter type
993 const auto limiter = Limiter<typename LimiterValueType<T>::value_type>::build(face.limiter_type);
994
995 // Determine upwind and downwind arguments based on the face element
996 const auto upwind_arg = face.elem_is_upwind ? face.makeElem() : face.makeNeighbor();
997 const auto downwind_arg = face.elem_is_upwind ? face.makeNeighbor() : face.makeElem();
998 auto phi_upwind = functor(upwind_arg, time);
999 auto phi_downwind = functor(downwind_arg, time);
1000
1001 // Initialize the return vector value
1003 T coeff_upwind, coeff_downwind;
1004
1005 // Compute interpolation coefficients and advected values for Upwind or CentralDifference limiters
1006 if (face.limiter_type == LimiterType::Upwind ||
1007 face.limiter_type == LimiterType::CentralDifference)
1008 {
1009 for (unsigned int i = 0; i < LIBMESH_DIM; ++i)
1010 {
1011 const auto &component_upwind = phi_upwind(i), component_downwind = phi_downwind(i);
1012 std::tie(coeff_upwind, coeff_downwind) = interpCoeffs(*limiter,
1013 component_upwind,
1014 component_downwind,
1015 &grad_zero,
1016 &grad_zero,
1017 std::numeric_limits<Real>::max(),
1018 std::numeric_limits<Real>::min(),
1019 *face.fi,
1020 face.elem_is_upwind);
1021 ret(i) = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1022 }
1023 }
1024 else
1025 {
1026 // Determine the time argument for the limiter
1027 auto * time_arg = face.state_limiter;
1028 if (!time_arg)
1029 {
1031 time_arg = &temp_state;
1032 }
1033
1034 // Evaluate the gradient of the functor at the upwind and downwind locations
1035 const auto & grad_phi_upwind = functor.gradient(upwind_arg, *time_arg);
1036 const auto & grad_phi_downwind = functor.gradient(downwind_arg, *time_arg);
1037
1038 const auto coeffs = interpCoeffs(InterpMethod::Average, *face.fi, face.elem_is_upwind);
1039
1040 // Compute interpolation coefficients and advected values for each component
1041 for (unsigned int i = 0; i < LIBMESH_DIM; ++i)
1042 {
1043 const auto &component_upwind = phi_upwind(i), component_downwind = phi_downwind(i);
1044 const libMesh::VectorValue<T> &grad_upwind = grad_phi_upwind.row(i),
1045 grad_face = coeffs.first * grad_phi_upwind.row(i) +
1046 coeffs.second * grad_phi_downwind.row(i);
1047
1048 // Initialize min-max values
1049 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
1050 if (face.limiter_type == LimiterType::Venkatakrishnan ||
1051 face.limiter_type == LimiterType::SOU)
1052 std::tie(max_value, min_value) = computeMinMaxValue(functor, face, *time_arg, i);
1053
1054 // Perform full limited interpolation for the component
1055 ret(i) = fullLimitedInterpolation(*limiter,
1056 component_upwind,
1057 component_downwind,
1058 &grad_upwind,
1059 &grad_face,
1060 max_value,
1061 min_value,
1062 face);
1063 }
1064 }
1065
1066 // Return the interpolated vector value
1067 return ret;
1068}
std::pair< Real, Real > computeMinMaxValue(const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
This function calculates the minimum and maximum values within a two-cell stencil.
T fullLimitedInterpolation(const Limiter< T > &limiter, const T &phi_upwind, const T &phi_downwind, const VectorValue< T > *const grad_phi_upwind, const VectorValue< T > *const grad_phi_face, const Real &max_value, const Real &min_value, const FaceArg &face)
This function performs a full limited interpolation of a variable, taking into account the values and...

◆ interpolate() [2/9]

template<typename T , std::size_t N>
std::array< T, N > Moose::FV::interpolate ( const FunctorBase< std::array< T, N > > &  functor,
const FaceArg face,
const StateArg time 
)

Definition at line 1162 of file MathFVUtils.h.

1165{
1166 return containerInterpolate(functor, face, time);
1167}
T containerInterpolate(const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
This function interpolates container values at faces in a computational grid using a specified functo...

◆ interpolate() [3/9]

template<typename T >
std::vector< T > Moose::FV::interpolate ( const FunctorBase< std::vector< T > > &  functor,
const FaceArg face,
const StateArg time 
)

Definition at line 1153 of file MathFVUtils.h.

1156{
1157 return containerInterpolate(functor, face, time);
1158}

◆ interpolate() [4/9]

template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value, typename Enable = typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
T Moose::FV::interpolate ( const FunctorBase< T > &  functor,
const FaceArg face,
const StateArg time 
)

This function interpolates values at faces in a computational grid using a specified functor, face argument, and evaluation kind.

It handles different limiter types and performs interpolation accordingly.

Template Parameters
TThe data type for the values being interpolated. This is typically a scalar type.
FEKEnumeration type FunctorEvaluationKind with a default value of FunctorEvaluationKind::Value. This determines the kind of evaluation the functor will perform.
EnableA type trait used for SFINAE (Substitution Failure Is Not An Error) to ensure that T is a valid scalar type as determined by ScalarTraits<T>.
Parameters
functorAn object of a functor class derived from FunctorBase<T>. This object provides the genericEvaluate method to compute the value at a given element and time.
faceAn argument representing the face in the computational domain. The face provides access to neighboring elements and limiter type.
timeAn argument representing the state or time at which the evaluation is performed.
Returns
T The interpolated value at the face.

Usage: This function is used for interpolating values at faces in a finite volume method, ensuring that the interpolation adheres to the constraints imposed by the limiter.

Definition at line 898 of file MathFVUtils.h.

899{
900 // Ensure only supported FunctorEvaluationKinds are used
901 static_assert((FEK == FunctorEvaluationKind::Value) || (FEK == FunctorEvaluationKind::Dot),
902 "Only Value and Dot evaluations currently supported");
903
904 // Special handling for central differencing as it is the only interpolation method which
905 // currently supports skew correction
906 if (face.limiter_type == LimiterType::CentralDifference)
907 return linearInterpolation<T, FEK>(functor, face, time);
908
909 if (face.limiter_type == LimiterType::Upwind ||
910 face.limiter_type == LimiterType::CentralDifference)
911 {
912 // Compute interpolation coefficients and advected values
913 const auto [interp_coeffs, advected] = interpCoeffsAndAdvected<T, FEK>(functor, face, time);
914 // Return the interpolated value
915 return interp_coeffs.first * advected.first + interp_coeffs.second * advected.second;
916 }
917 else
918 {
919 // Determine the gradient evaluation kind
921 typedef typename FunctorBase<T>::GradientType GradientType;
922 static const GradientType zero(0);
923 const auto & limiter =
924 Limiter<typename LimiterValueType<T>::value_type>::build(face.limiter_type);
925
926 // Determine upwind and downwind arguments based on the face element
927 const auto & upwind_arg = face.elem_is_upwind ? face.makeElem() : face.makeNeighbor();
928 const auto & downwind_arg = face.elem_is_upwind ? face.makeNeighbor() : face.makeElem();
929 const auto & phi_upwind = functor.template genericEvaluate<FEK>(upwind_arg, time);
930 const auto & phi_downwind = functor.template genericEvaluate<FEK>(downwind_arg, time);
931
932 // Determine the time argument for the limiter
933 auto * time_arg = face.state_limiter;
934 if (!time_arg)
935 {
937 time_arg = &temp_state;
938 }
939
940 // Initialize min-max values
941 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
942 if (face.limiter_type == LimiterType::Venkatakrishnan || face.limiter_type == LimiterType::SOU)
943 std::tie(max_value, min_value) = computeMinMaxValue(functor, face, *time_arg);
944
945 // Evaluate the gradient of the functor at the upwind and downwind locations
946 const auto & grad_phi_upwind = functor.template genericEvaluate<GFEK>(upwind_arg, *time_arg);
947 const auto & grad_phi_face = functor.template genericEvaluate<GFEK>(face, *time_arg);
948
949 // Perform full limited interpolation and return the interpolated value
950 return fullLimitedInterpolation(*limiter,
951 phi_upwind,
952 phi_downwind,
953 &grad_phi_upwind,
954 &grad_phi_face,
955 max_value,
956 min_value,
957 face);
958 }
959}

◆ interpolate() [5/9]

template<typename Limiter , typename T , typename Tensor >
libMesh::VectorValue< T > Moose::FV::interpolate ( const Limiter limiter,
const TypeVector< T > &  phi_upwind,
const TypeVector< T > &  phi_downwind,
const Tensor *const  grad_phi_upwind,
const FaceInfo fi,
const bool  fi_elem_is_upwind 
)

Vector overload.

Definition at line 537 of file MathFVUtils.h.

543{
544 mooseAssert(limiter.constant() || grad_phi_upwind,
545 "Non-null gradient only supported for constant limiters.");
546
547 const libMesh::VectorValue<T> * const gradient_example = nullptr;
549 for (const auto i : make_range(unsigned(LIBMESH_DIM)))
550 {
551 if (grad_phi_upwind)
552 {
553 const libMesh::VectorValue<T> gradient = grad_phi_upwind->row(i);
554 ret(i) =
555 interpolate(limiter, phi_upwind(i), phi_downwind(i), &gradient, fi, fi_elem_is_upwind);
556 }
557 else
558 ret(i) = interpolate(
559 limiter, phi_upwind(i), phi_downwind(i), gradient_example, fi, fi_elem_is_upwind);
560 }
561
562 return ret;
563}
virtual bool constant() const =0

◆ interpolate() [6/9]

template<typename Scalar , typename Vector , typename Enable = typename std::enable_if<libMesh::ScalarTraits<Scalar>::value>::type>
Scalar Moose::FV::interpolate ( const Limiter< Scalar > &  limiter,
const Scalar &  phi_upwind,
const Scalar &  phi_downwind,
const Vector *const  grad_phi_upwind,
const FaceInfo fi,
const bool  fi_elem_is_upwind 
)

Interpolates with a limiter.

Definition at line 512 of file MathFVUtils.h.

518{
519 auto pr =
520 interpCoeffs(limiter,
521 phi_upwind,
522 phi_downwind,
523 grad_phi_upwind,
524 /*grad_phi_face*/ static_cast<const libMesh::VectorValue<Scalar> *>(nullptr),
525 /* max_value */ std::numeric_limits<Real>::max(),
526 /* min_value */ std::numeric_limits<Real>::min(),
527 fi,
528 fi_elem_is_upwind);
529 return pr.first * phi_upwind + pr.second * phi_downwind;
530}

◆ interpolate() [7/9]

template<typename T , typename T2 , typename T3 >
void Moose::FV::interpolate ( InterpMethod  m,
T &  result,
const T2 &  value1,
const T3 &  value2,
const FaceInfo fi,
const bool  one_is_elem 
)

Provides interpolation of face values for non-advection-specific purposes (although it can/will still be used by advective kernels sometimes).

The interpolated value is stored in result. This should be called when a face value needs to be computed from two neighboring cells/elements. value1 and value2 represent the cell property/values from which to compute the face value. The one_is_elem parameter indicates whether value1 corresponds to the FaceInfo elem value; else it corresponds to the FaceInfo neighbor value

Definition at line 285 of file MathFVUtils.h.

291{
292 switch (m)
293 {
294 case InterpMethod::Average:
295 case InterpMethod::SkewCorrectedAverage:
296 result = linearInterpolation(value1, value2, fi, one_is_elem);
297 break;
298 case InterpMethod::HarmonicAverage:
299 result = harmonicInterpolation(value1, value2, fi, one_is_elem);
300 break;
301 default:
302 mooseError("unsupported interpolation method for interpolate() function");
303 }
304}
libMesh::CompareTypes< T1, T2 >::supertype harmonicInterpolation(const T1 &value1, const T2 &value2, const FaceInfo &fi, const bool one_is_elem)
Computes the harmonic mean (1/(gc/value1+(1-gc)/value2)) of Reals, RealVectorValues and RealTensorVal...
libMesh::CompareTypes< T, T2 >::supertype linearInterpolation(const T &value1, const T2 &value2, const FaceInfo &fi, const bool one_is_elem, const InterpMethod interp_method=InterpMethod::Average)
A simple linear interpolation of values between cell centers to a cell face.

Referenced by FVOrthogonalDiffusion::computeQpResidual(), MooseVariableFV< OutputType >::evaluate(), greenGaussGradient(), and interpolate().

◆ interpolate() [8/9]

template<typename T , typename T2 , typename T3 , typename Vector >
void Moose::FV::interpolate ( InterpMethod  m,
T &  result,
const T2 &  value1,
const T3 &  value2,
const Vector &  advector,
const FaceInfo fi,
const bool  one_is_elem 
)

Provides interpolation of face values for advective flux kernels.

This should be called by advective kernels when a face value is needed from two neighboring cells/elements. The interpolated value is stored in result. value1 and value2 represent the two neighboring advected cell property/values. advector represents the vector quantity at the face that is doing the advecting (e.g. the flow velocity at the face); this value often will have been computed using a call to the non-advective interpolate function. The one_is_elem parameter indicates whether value1 corresponds to the FaceInfo elem value; else it corresponds to the FaceInfo neighbor value

Definition at line 403 of file MathFVUtils.h.

410{
411 const auto coeffs = interpCoeffs(m, fi, one_is_elem, advector * fi.normal());
412 result = coeffs.first * value1 + coeffs.second * value2;
413}

◆ interpolate() [9/9]

template<typename T1 , typename T2 , typename T3 , template< typename > class Vector1, template< typename > class Vector2>
void Moose::FV::interpolate ( InterpMethod  m,
Vector1< T1 > &  result,
const T2 &  fi_elem_advected,
const T2 &  fi_neighbor_advected,
const Vector2< T3 > &  fi_elem_advector,
const Vector2< T3 > &  fi_neighbor_advector,
const FaceInfo fi 
)

Computes the product of the advected and the advector based on the given interpolation method.

Definition at line 356 of file MathFVUtils.h.

363{
364 switch (m)
365 {
366 case InterpMethod::Average:
367 result = linearInterpolation(fi_elem_advected * fi_elem_advector,
368 fi_neighbor_advected * fi_neighbor_advector,
369 fi,
370 true);
371 break;
372 case InterpMethod::Upwind:
373 {
374 const auto face_advector = linearInterpolation(MetaPhysicL::raw_value(fi_elem_advector),
375 MetaPhysicL::raw_value(fi_neighbor_advector),
376 fi,
377 true);
378 Real elem_coeff, neighbor_coeff;
379 if (face_advector * fi.normal() > 0)
380 elem_coeff = 1, neighbor_coeff = 0;
381 else
382 elem_coeff = 0, neighbor_coeff = 1;
383
384 result = elem_coeff * fi_elem_advected * fi_elem_advector +
385 neighbor_coeff * fi_neighbor_advected * fi_neighbor_advector;
386 break;
387 }
388 default:
389 mooseError("unsupported interpolation method for FVFaceInterface::interpolate");
390 }
391}

◆ interpolationMethods()

MooseEnum Moose::FV::interpolationMethods ( )

Returns an enum with all the currently supported interpolation methods and the current default for FV: first-order upwind.

Returns
MooseEnum with all the face interpolation methods supported

Definition at line 61 of file MathFVUtils.C.

62{
63 return MooseEnum("average upwind sou min_mod vanLeer quick venkatakrishnan skewness-corrected",
64 "upwind");
65}

Referenced by advectedInterpolationParameter().

◆ limiterType()

LimiterType Moose::FV::limiterType ( InterpMethod  interp_method)

Return the limiter type associated with the supplied interpolation method.

Definition at line 63 of file Limiter.C.

64{
65 switch (interp_method)
66 {
67 case InterpMethod::Average:
68 case InterpMethod::SkewCorrectedAverage:
69 return LimiterType::CentralDifference;
70
71 case InterpMethod::Upwind:
72 return LimiterType::Upwind;
73
74 case InterpMethod::VanLeer:
75 return LimiterType::VanLeer;
76
77 case InterpMethod::MinMod:
78 return LimiterType::MinMod;
79
80 case InterpMethod::SOU:
81 return LimiterType::SOU;
82
83 case InterpMethod::QUICK:
84 return LimiterType::QUICK;
85
86 case InterpMethod::Venkatakrishnan:
87 return LimiterType::Venkatakrishnan;
88
89 default:
90 mooseError("Unrecognized interpolation method type.");
91 }
92}

Referenced by FVAdvection::computeQpResidual(), and FVDivergence::computeQpResidual().

◆ linearInterpolation() [1/2]

template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value>
T Moose::FV::linearInterpolation ( const FunctorBase< T > &  functor,
const FaceArg face,
const StateArg time 
)

perform a possibly skew-corrected linear interpolation by evaluating the supplied functor with the provided functor face argument

Definition at line 312 of file MathFVUtils.h.

313{
314 static_assert((FEK == FunctorEvaluationKind::Value) || (FEK == FunctorEvaluationKind::Dot),
315 "Only Value and Dot evaluations currently supported");
316 mooseAssert(face.limiter_type == LimiterType::CentralDifference,
317 "this interpolation method is meant for linear interpolations");
318
319 mooseAssert(face.fi,
320 "We must have a non-null face_info in order to prepare our ElemFromFace tuples");
321
323
324 const auto elem_arg = face.makeElem();
325 const auto neighbor_arg = face.makeNeighbor();
326
327 const auto elem_eval = functor.template genericEvaluate<FEK>(elem_arg, time);
328 const auto neighbor_eval = functor.template genericEvaluate<FEK>(neighbor_arg, time);
329
330 if (face.correct_skewness)
331 {
332 // This condition ensures that the recursive algorithm (face_center->
333 // face_gradient -> cell_gradient -> face_center -> ...) terminates after
334 // one loop. It is hardcoded to one loop at this point since it yields
335 // 2nd order accuracy on skewed meshes with the minimum additional effort.
336 FaceArg new_face(face);
337 new_face.correct_skewness = false;
338 const auto surface_gradient = functor.template genericEvaluate<GFEK>(new_face, time);
339
341 elem_eval, neighbor_eval, surface_gradient, *face.fi, true);
342 }
343 else
344 return linearInterpolation(elem_eval, neighbor_eval, *face.fi, true);
345}
libMesh::CompareTypes< T, T2 >::supertype skewCorrectedLinearInterpolation(const T &value1, const T2 &value2, const T3 &face_gradient, const FaceInfo &fi, const bool one_is_elem)
Linear interpolation with skewness correction using the face gradient.

◆ linearInterpolation() [2/2]

template<typename T , typename T2 >
libMesh::CompareTypes< T, T2 >::supertype Moose::FV::linearInterpolation ( const T &  value1,
const T2 &  value2,
const FaceInfo fi,
const bool  one_is_elem,
const InterpMethod  interp_method = InterpMethod::Average 
)

A simple linear interpolation of values between cell centers to a cell face.

The one_is_elem parameter indicates whether value1 corresponds to the FaceInfo elem value; else it corresponds to the FaceInfo neighbor value

Definition at line 153 of file MathFVUtils.h.

158{
159 mooseAssert(interp_method == InterpMethod::Average ||
160 interp_method == InterpMethod::SkewCorrectedAverage,
161 "The selected interpolation function only works with average or skewness-corrected "
162 "average options!");
163 const auto coeffs = interpCoeffs(interp_method, fi, one_is_elem);
164 return coeffs.first * value1 + coeffs.second * value2;
165}

Referenced by interpolate(), interpolate(), MooseLinearVariableFV< OutputType >::limitedGradSln(), linearInterpolation(), ComputeLinearFVGreenGaussGradientFaceThread::operator()(), and MooseVariableFV< OutputType >::uncorrectedAdGradSln().

◆ loopOverElemFaceInfo()

template<typename ActionFunctor >
void Moose::FV::loopOverElemFaceInfo ( const Elem &  elem,
const MooseMesh mesh,
ActionFunctor &  act,
const Moose::CoordinateSystemType  coord_type,
const unsigned int  rz_radial_coord = libMesh::invalid_uint 
)

Definition at line 42 of file FVUtils.h.

47{
48 mooseAssert(elem.active(), "We should never call this method with an inactive element");
49
50 for (const auto side : elem.side_index_range())
51 {
52 const Elem * const candidate_neighbor = elem.neighbor_ptr(side);
53
54 bool elem_has_info = elemHasFaceInfo(elem, candidate_neighbor);
55
56 std::set<const Elem *> neighbors;
57
58 const bool inactive_neighbor_detected =
59 candidate_neighbor ? !candidate_neighbor->active() : false;
60
61 // See MooseMesh::buildFaceInfo for corresponding checks/additions of FaceInfo
62 if (inactive_neighbor_detected)
63 {
64 // We must be next to an element that has been refined
65 mooseAssert(candidate_neighbor->has_children(), "We should have children");
66
67 const auto candidate_neighbor_side = candidate_neighbor->which_neighbor_am_i(&elem);
68
69 for (const auto child_num : make_range(candidate_neighbor->n_children()))
70 if (candidate_neighbor->is_child_on_side(child_num, candidate_neighbor_side))
71 {
72 const Elem * const child = candidate_neighbor->child_ptr(child_num);
73 mooseAssert(child->level() - elem.level() == 1, "The math doesn't work out here.");
74 mooseAssert(child->has_neighbor(&elem), "Elem should be a neighbor of this child.");
75 mooseAssert(child->active(),
76 "We shouldn't have greater than a face mismatch level of one");
77 neighbors.insert(child);
78 }
79 }
80 else
81 neighbors.insert(candidate_neighbor);
82
83 for (const Elem * const neighbor : neighbors)
84 {
85 const FaceInfo * const fi =
86 elem_has_info ? mesh.faceInfo(&elem, side)
87 : mesh.faceInfo(neighbor, neighbor->which_neighbor_am_i(&elem));
88
89 mooseAssert(fi, "We should have found a FaceInfo");
90 mooseAssert(elem_has_info ? &elem == &fi->elem() : &elem == fi->neighborPtr(),
91 "Doesn't seem like we understand how this FaceInfo thing is working");
92 if (neighbor)
93 {
94 mooseAssert(neighbor != libMesh::remote_elem,
95 "Remote element detected. This indicates that you have insufficient geometric "
96 "ghosting. Please contact your application developers.");
97 mooseAssert(elem_has_info ? neighbor == fi->neighborPtr() : neighbor == &fi->elem(),
98 "Doesn't seem like we understand how this FaceInfo thing is working");
99 }
100
101 const Point elem_normal = elem_has_info ? fi->normal() : Point(-fi->normal());
102
103 Real coord;
104 MooseMeshUtils::coordTransformFactor(fi->faceCentroid(), coord, coord_type, rz_radial_coord);
105
106 const Point surface_vector = elem_normal * fi->faceArea() * coord;
107
108 act(elem, neighbor, fi, surface_vector, coord, elem_has_info);
109 }
110 }
111}
if(!dmm->_nl) SETERRQ(PETSC_COMM_WORLD
Real faceArea() const
Returns the face area of face id.
Definition FaceInfo.h:64
bool elemHasFaceInfo(const Elem &elem, const Elem *const neighbor)
This function infers based on elements if the faceinfo between them belongs to the element or not.
Definition FVUtils.C:21
const RemoteElem * remote_elem

Referenced by greenGaussGradient().

◆ onBoundary() [1/2]

bool Moose::FV::onBoundary ( const std::set< SubdomainID > &  subs,
const FaceInfo fi 
)

Determine whether the passed-in face is on the boundary of an object that lives on the provided subdomains.

Note that if the subdomain set is empty we consider that to mean that the object has no block restriction and lives on the entire mesh

Definition at line 28 of file MathFVUtils.C.

29{
30 if (!fi.neighborPtr())
31 // We're on the exterior boundary
32 return true;
33
34 if (subs.empty())
35 // The face is internal and our functor lives on all subdomains
36 return false;
37
38 const auto sub_count =
39 subs.count(fi.elem().subdomain_id()) + subs.count(fi.neighbor().subdomain_id());
40
41 switch (sub_count)
42 {
43 case 0:
44 mooseError("We should not be calling isExtrapolatedBoundaryFace on a functor that doesn't "
45 "live on either of the face information's neighboring elements");
46
47 case 1:
48 // We only live on one of the subs
49 return true;
50
51 case 2:
52 // We live on both of the subs
53 return false;
54
55 default:
56 mooseError("There should be no other sub_count options");
57 }
58}
const Elem & neighbor() const
Definition FaceInfo.h:220

◆ onBoundary() [2/2]

template<typename SubdomainRestrictable >
bool Moose::FV::onBoundary ( const SubdomainRestrictable &  obj,
const FaceInfo fi 
)

Return whether the supplied face is on a boundary of the object's execution.

Definition at line 1174 of file MathFVUtils.h.

1175{
1176 const bool internal = fi.neighborPtr() && obj.hasBlocks(fi.elemSubdomainID()) &&
1177 obj.hasBlocks(fi.neighborSubdomainID());
1178 return !internal;
1179}
SubdomainID neighborSubdomainID() const
Definition FaceInfo.h:256
SubdomainID elemSubdomainID() const
Definition FaceInfo.h:106

Referenced by FVFluxKernel::onBoundary().

◆ rF()

template<typename Scalar , typename Vector >
Scalar Moose::FV::rF ( const Scalar &  phiC,
const Scalar &  phiD,
const Vector &  gradC,
const RealVectorValue &  dCD 
)

From Moukalled 12.30.

r_f = (phiC - phiU) / (phiD - phiC)

However, this formula is only clear on grids where upwind locations can be readily determined, which is not the case for unstructured meshes. So we leverage a virtual upwind location and Moukalled 12.65

phiD - phiU = 2 * grad(phi)_C * dCD -> phiU = phiD - 2 * grad(phi)_C * dCD

Combining the two equations and performing some algebraic manipulation yields this equation for r_f:

r_f = 2 * grad(phi)_C * dCD / (phiD - phiC) - 1

This equation is clearly asymmetric considering the face between C and D because of the subscript on grad(phi). Hence this method can be thought of as constructing an r associated with the C side of the face.

This is a branchless version, avoiding if-else statements to enable vectorization.

Definition at line 448 of file MathFVUtils.h.

449{
450 const Scalar denom = phiD - phiC;
451 const Scalar grad_dot = gradC * dCD;
452
453 // This is an arbitrary number here, when we start seeing convergence issues we
454 // can tune this but so far this has shown okay results.
455 constexpr Real eps = 1e-10;
456 const Real denom_sign =
457 std::copysign(1.0,
459 std::numeric_limits<Real>::min() * MetaPhysicL::raw_value(grad_dot));
460 const Scalar safe = denom + denom_sign * eps;
461 return 2.0 * grad_dot / safe - 1.0;
462}

Referenced by FVAdvectedMinmodWeightBased::advectedInterpolate(), FVAdvectedVanLeerWeightBased::advectedInterpolate(), Moose::FV::MinModLimiter< T >::limit(), Moose::FV::QUICKLimiter< T >::limit(), and Moose::FV::VanLeerLimiter< T >::limit().

◆ selectInterpolationMethod()

InterpMethod Moose::FV::selectInterpolationMethod ( const std::string &  interp_method)

Definition at line 81 of file MathFVUtils.C.

82{
83 if (interp_method == "average")
84 return InterpMethod::Average;
85 else if (interp_method == "harmonic")
86 return InterpMethod::HarmonicAverage;
87 else if (interp_method == "skewness-corrected")
88 return InterpMethod::SkewCorrectedAverage;
89 else if (interp_method == "upwind")
90 return InterpMethod::Upwind;
91 else if (interp_method == "rc")
92 return InterpMethod::RhieChow;
93 else if (interp_method == "vanLeer")
94 return InterpMethod::VanLeer;
95 else if (interp_method == "min_mod")
96 return InterpMethod::MinMod;
97 else if (interp_method == "sou")
98 return InterpMethod::SOU;
99 else if (interp_method == "quick")
100 return InterpMethod::QUICK;
101 else if (interp_method == "venkatakrishnan")
102 return InterpMethod::Venkatakrishnan;
103 else
104 mooseError("Interpolation method ",
105 interp_method,
106 " is not currently an option in Moose::FV::selectInterpolationMethod");
107}

Referenced by setInterpolationMethod(), FVRelationshipManagerInterface::setRMParamsAdvection(), and FVRelationshipManagerInterface::setRMParamsDiffusion().

◆ setInterpolationMethod()

bool Moose::FV::setInterpolationMethod ( const MooseObject obj,
Moose::FV::InterpMethod interp_method,
const std::string &  param_name 
)

Sets one interpolation method.

Parameters
objThe MooseObject with input parameters to query
interp_methodThe interpolation method we will set
param_nameThe name of the parameter setting this interpolation method
Returns
Whether the interpolation method has indicated that we will need more than the default level of ghosting

Definition at line 110 of file MathFVUtils.C.

113{
114 bool need_more_ghosting = false;
115
116 const auto & interp_method_in = obj.getParam<MooseEnum>(param_name);
117 interp_method = selectInterpolationMethod(interp_method_in);
118
119 if (interp_method == InterpMethod::SOU || interp_method == InterpMethod::MinMod ||
120 interp_method == InterpMethod::VanLeer || interp_method == InterpMethod::QUICK ||
121 interp_method == InterpMethod::Venkatakrishnan)
122 need_more_ghosting = true;
123
124 return need_more_ghosting;
125}
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition MooseBase.h:406
InterpMethod selectInterpolationMethod(const std::string &interp_method)
Definition MathFVUtils.C:81

Referenced by FVAdvection::FVAdvection().

◆ skewCorrectedLinearInterpolation()

template<typename T , typename T2 , typename T3 >
libMesh::CompareTypes< T, T2 >::supertype Moose::FV::skewCorrectedLinearInterpolation ( const T &  value1,
const T2 &  value2,
const T3 &  face_gradient,
const FaceInfo fi,
const bool  one_is_elem 
)

Linear interpolation with skewness correction using the face gradient.

See more info in Moukalled Chapter 9. The correction involves a first order Taylor expansion around the intersection of the cell face and the line connecting the two cell centers.

Definition at line 264 of file MathFVUtils.h.

269{
270 const auto coeffs = interpCoeffs(InterpMethod::SkewCorrectedAverage, fi, one_is_elem);
271
272 auto value = (coeffs.first * value1 + coeffs.second * value2) +
273 face_gradient * fi.skewnessCorrectionVector();
274 return value;
275}
Point skewnessCorrectionVector() const
Returns the skewness-correction vector (vector between the approximate and real face centroids).
Definition FaceInfo.C:74

Referenced by linearInterpolation().

Variable Documentation

◆ moose_limiter_type

const MooseEnum Moose::FV::moose_limiter_type
extern