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 Real weight1, const Real weight2)
 Computes a weighted harmonic mean of Reals, RealVectorValues, and RealTensorValues while accounting for the possibility that one or both values are AD.
 
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)) using the geometric weighting of a face.
 
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>
T 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 >
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>
T 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 >
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 663 of file MathFVUtils.h.

664{
665 // Initialize max_value to 0 and min_value to a large value
666 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
667
668 // Iterate over the direct neighbors of the element associated with the face
669 for (const auto neighbor : (*face.fi).elem().neighbor_ptr_range())
670 {
671 // If not a valid neighbor, skip to the next one
672 if (neighbor == nullptr)
673 continue;
674
675 // Evaluate the functor at the neighbor and update max_value and min_value
676 const ElemArg local_cell_arg = {neighbor, false};
677 const auto value =
678 MetaPhysicL::raw_value(functor.template genericEvaluate<FEK>(local_cell_arg, time));
679 max_value = std::max(max_value, value);
680 min_value = std::min(min_value, value);
681 }
682
683 // Iterate over the neighbors of the neighbor
684 for (const auto neighbor : (*face.fi).neighbor().neighbor_ptr_range())
685 {
686 // If not a valid neighbor, skip to the next one
687 if (neighbor == nullptr)
688 continue;
689
690 // Evaluate the functor at the neighbor and update max_value and min_value
691 const ElemArg local_cell_arg = {neighbor, false};
692 const auto value =
693 MetaPhysicL::raw_value(functor.template genericEvaluate<FEK>(local_cell_arg, time));
694 max_value = std::max(max_value, value);
695 min_value = std::min(min_value, value);
696 }
697
698 // Return a pair containing the computed maximum and minimum values
699 return std::make_pair(max_value, min_value);
700}
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 729 of file MathFVUtils.h.

733{
734 // Initialize max_value to 0 and min_value to a large value
735 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
736
737 // Iterate over the direct neighbors of the element associated with the face
738 for (const auto neighbor : (*face.fi).elem().neighbor_ptr_range())
739 {
740 // If not a valid neighbor, skip to the next one
741 if (neighbor == nullptr)
742 continue;
743
744 // Evaluate the functor at the neighbor for the specified component and update max_value and
745 // min_value
746 const ElemArg local_cell_arg = {neighbor, false};
747 const auto value = MetaPhysicL::raw_value(functor(local_cell_arg, time)(component));
748 max_value = std::max(max_value, value);
749 min_value = std::min(min_value, value);
750 }
751
752 // Iterate over the neighbors of the neighbor associated with the face
753 for (const auto neighbor : (*face.fi).neighbor().neighbor_ptr_range())
754 {
755 // If not a valid neighbor, skip to the next one
756 if (neighbor == nullptr)
757 continue;
758
759 // Evaluate the functor at the neighbor for the specified component and update max_value and
760 // min_value
761 const ElemArg local_cell_arg = {neighbor, false};
762 const auto value = MetaPhysicL::raw_value(functor(local_cell_arg, time)(component));
763 max_value = std::max(max_value, value);
764 min_value = std::min(min_value, value);
765 }
766
767 // Return a pair containing the computed maximum and minimum values
768 return std::make_pair(max_value, min_value);
769}

◆ 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 1105 of file MathFVUtils.h.

1106{
1107 typedef typename FunctorBase<T>::GradientType ContainerGradientType;
1108 typedef typename ContainerGradientType::value_type GradientType;
1109 const GradientType * const example_gradient = nullptr;
1110
1111 mooseAssert(face.fi, "this must be non-null");
1112 const auto limiter = Limiter<typename T::value_type>::build(face.limiter_type);
1113
1114 const auto upwind_arg = face.elem_is_upwind ? face.makeElem() : face.makeNeighbor();
1115 const auto downwind_arg = face.elem_is_upwind ? face.makeNeighbor() : face.makeElem();
1116 const auto phi_upwind = functor(upwind_arg, time);
1117 const auto phi_downwind = functor(downwind_arg, time);
1118
1119 // initialize in order to get proper size
1120 T ret = phi_upwind;
1121 typename T::value_type coeff_upwind, coeff_downwind;
1122
1123 if (face.limiter_type == LimiterType::Upwind ||
1124 face.limiter_type == LimiterType::CentralDifference)
1125 {
1126 for (const auto i : index_range(ret))
1127 {
1128 const auto &component_upwind = phi_upwind[i], component_downwind = phi_downwind[i];
1129 std::tie(coeff_upwind, coeff_downwind) = interpCoeffs(*limiter,
1130 component_upwind,
1131 component_downwind,
1132 example_gradient,
1133 example_gradient,
1134 std::numeric_limits<Real>::max(),
1135 std::numeric_limits<Real>::min(),
1136 *face.fi,
1137 face.elem_is_upwind);
1138 ret[i] = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1139 }
1140 }
1141 else
1142 {
1143 const auto grad_phi_upwind = functor.gradient(upwind_arg, time);
1144 for (const auto i : index_range(ret))
1145 {
1146 const auto &component_upwind = phi_upwind[i], component_downwind = phi_downwind[i];
1147 const auto & grad = grad_phi_upwind[i];
1148 std::tie(coeff_upwind, coeff_downwind) = interpCoeffs(*limiter,
1149 component_upwind,
1150 component_downwind,
1151 &grad,
1152 example_gradient,
1153 std::numeric_limits<Real>::max(),
1154 std::numeric_limits<Real>::min(),
1155 *face.fi,
1156 face.elem_is_upwind);
1157 ret[i] = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1158 }
1159 }
1160
1161 return ret;
1162}
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

Referenced by MooseVariableFV< RealEigenVector >::getDirichletBoundaryFaceValue().

◆ 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 598 of file MathFVUtils.h.

606{
607 // Compute the direction vector based on whether the current element is upwind
608 const auto dCD = face.elem_is_upwind ? face.fi->dCN() : Point(-face.fi->dCN());
609
610 // Compute the flux limiting ratio using the specified limiter
611 const auto beta = limiter(phi_upwind,
612 phi_downwind,
613 grad_phi_upwind,
614 grad_phi_face,
615 dCD,
616 max_value,
617 min_value,
618 face.fi,
619 face.elem_is_upwind);
620
621 // Determine the face centroid and the appropriate cell centroid
622 const auto & face_centroid = face.fi->faceCentroid();
623 const auto & cell_centroid =
624 face.elem_is_upwind ? face.fi->elemCentroid() : face.fi->neighborCentroid();
625
626 // Compute the delta value at the face
627 T delta_face;
628 if (face.limiter_type == LimiterType::Venkatakrishnan || face.limiter_type == LimiterType::SOU)
629 delta_face = (*grad_phi_upwind) * (face_centroid - cell_centroid);
630 else
631 delta_face = (*grad_phi_face) * (face_centroid - cell_centroid);
632
633 // Return the interpolated value
634 return phi_upwind + beta * delta_face;
635}
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:175
@ COORD_RZ
Definition MooseTypes.h:870
@ COORD_RSPHERICAL
Definition MooseTypes.h:871
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() [1/2]

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)) using the geometric weighting of a face.

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 260 of file MathFVUtils.h.

264{
265 const auto coeffs = interpCoeffs(InterpMethod::Average, fi, one_is_elem);
266 return harmonicInterpolation(value1, value2, coeffs.first, coeffs.second);
267}
libMesh::CompareTypes< T1, T2 >::supertype harmonicInterpolation(const T1 &value1, const T2 &value2, const Real weight1, const Real weight2)
Computes a weighted harmonic mean of Reals, RealVectorValues, and RealTensorValues while accounting f...

◆ harmonicInterpolation() [2/2]

template<typename T1 , typename T2 >
libMesh::CompareTypes< T1, T2 >::supertype Moose::FV::harmonicInterpolation ( const T1 &  value1,
const T2 &  value2,
const Real  weight1,
const Real  weight2 
)

Computes a weighted harmonic mean of Reals, RealVectorValues, and RealTensorValues while accounting for the possibility that one or both values are AD.

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

Parameters
value1Reference to value1 in the 1/(weight1/value1 + weight2/value2) expression
value2Reference to value2 in the 1/(weight1/value1 + weight2/value2) expression
weight1Weight corresponding to value1
weight2Weight corresponding to value2
Returns
The interpolated value

Definition at line 179 of file MathFVUtils.h.

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

Referenced by harmonicInterpolation(), and 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 490 of file MathFVUtils.h.

499{
500 // Using beta, w_f, g nomenclature from Greenshields
501 const auto beta = limiter(phi_upwind,
502 phi_downwind,
503 grad_phi_upwind,
504 grad_phi_face,
505 fi_elem_is_upwind ? fi.dCN() : Point(-fi.dCN()),
506 max_value,
507 min_value,
508 &fi,
509 fi_elem_is_upwind);
510
511 const auto w_f = fi_elem_is_upwind ? fi.gC() : (1. - fi.gC());
512
513 const auto g = beta * (1. - w_f);
514
515 return std::make_pair(1. - g, g);
516}

◆ 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 803 of file MathFVUtils.h.

804{
805 // Ensure only supported FunctorEvaluationKinds are used
806 static_assert((FEK == FunctorEvaluationKind::Value) || (FEK == FunctorEvaluationKind::Dot),
807 "Only Value and Dot evaluations currently supported");
808
809 // Determine the gradient evaluation kind
811 typedef typename FunctorBase<T>::GradientType GradientType;
812 static const GradientType zero(0);
813
814 mooseAssert(face.fi, "this must be non-null");
815
816 // Construct the limiter based on the face limiter type
817 const auto limiter = Limiter<typename LimiterValueType<T>::value_type>::build(face.limiter_type);
818
819 // Determine upwind and downwind arguments based on the face element
820 const auto upwind_arg = face.elem_is_upwind ? face.makeElem() : face.makeNeighbor();
821 const auto downwind_arg = face.elem_is_upwind ? face.makeNeighbor() : face.makeElem();
822
823 // Evaluate the functor at the upwind and downwind locations
824 auto phi_upwind = functor.template genericEvaluate<FEK>(upwind_arg, time);
825 auto phi_downwind = functor.template genericEvaluate<FEK>(downwind_arg, time);
826
827 // Initialize the interpolation coefficients
828 std::pair<T, T> interp_coeffs;
829
830 // Compute interpolation coefficients for Upwind or CentralDifference limiters
831 if (face.limiter_type == LimiterType::Upwind ||
832 face.limiter_type == LimiterType::CentralDifference)
833 interp_coeffs = interpCoeffs(*limiter,
834 phi_upwind,
835 phi_downwind,
836 &zero,
837 &zero,
838 std::numeric_limits<Real>::max(),
839 std::numeric_limits<Real>::min(),
840 *face.fi,
841 face.elem_is_upwind);
842 else
843 {
844 // Determine the time argument for the limiter
845 auto * time_arg = face.state_limiter;
846 if (!time_arg)
847 {
849 time_arg = &temp_state;
850 }
851
852 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
853
854 // Compute min-max values for min-max limiters
855 if (face.limiter_type == LimiterType::Venkatakrishnan || face.limiter_type == LimiterType::SOU)
856 std::tie(max_value, min_value) = computeMinMaxValue(functor, face, *time_arg);
857
858 // Evaluate the gradient of the functor at the upwind and downwind locations
859 const auto grad_phi_upwind = functor.template genericEvaluate<GFEK>(upwind_arg, *time_arg);
860 const auto grad_phi_face = functor.template genericEvaluate<GFEK>(face, *time_arg);
861
862 // Compute the interpolation coefficients using the specified limiter
863 interp_coeffs = interpCoeffs(*limiter,
864 phi_upwind,
865 phi_downwind,
866 &grad_phi_upwind,
867 &grad_phi_face,
868 max_value,
869 min_value,
870 *face.fi,
871 face.elem_is_upwind);
872 }
873
874 // Return the interpolation coefficients and advected values
875 if (face.elem_is_upwind)
876 return std::make_pair(std::move(interp_coeffs),
877 std::make_pair(std::move(phi_upwind), std::move(phi_downwind)));
878 else
879 return std::make_pair(
880 std::make_pair(std::move(interp_coeffs.second), std::move(interp_coeffs.first)),
881 std::make_pair(std::move(phi_downwind), std::move(phi_upwind)));
882}
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 996 of file MathFVUtils.h.

999{
1000 // Define a zero gradient vector for initialization
1001 static const libMesh::VectorValue<T> grad_zero(0);
1002
1003 mooseAssert(face.fi, "this must be non-null");
1004
1005 // Construct the limiter based on the face limiter type
1006 const auto limiter = Limiter<typename LimiterValueType<T>::value_type>::build(face.limiter_type);
1007
1008 // Determine upwind and downwind arguments based on the face element
1009 const auto upwind_arg = face.elem_is_upwind ? face.makeElem() : face.makeNeighbor();
1010 const auto downwind_arg = face.elem_is_upwind ? face.makeNeighbor() : face.makeElem();
1011 auto phi_upwind = functor(upwind_arg, time);
1012 auto phi_downwind = functor(downwind_arg, time);
1013
1014 // Initialize the return vector value
1016 T coeff_upwind, coeff_downwind;
1017
1018 // Compute interpolation coefficients and advected values for Upwind or CentralDifference limiters
1019 if (face.limiter_type == LimiterType::Upwind ||
1020 face.limiter_type == LimiterType::CentralDifference)
1021 {
1022 for (unsigned int i = 0; i < LIBMESH_DIM; ++i)
1023 {
1024 const auto &component_upwind = phi_upwind(i), component_downwind = phi_downwind(i);
1025 std::tie(coeff_upwind, coeff_downwind) = interpCoeffs(*limiter,
1026 component_upwind,
1027 component_downwind,
1028 &grad_zero,
1029 &grad_zero,
1030 std::numeric_limits<Real>::max(),
1031 std::numeric_limits<Real>::min(),
1032 *face.fi,
1033 face.elem_is_upwind);
1034 ret(i) = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1035 }
1036 }
1037 else
1038 {
1039 // Determine the time argument for the limiter
1040 auto * time_arg = face.state_limiter;
1041 if (!time_arg)
1042 {
1044 time_arg = &temp_state;
1045 }
1046
1047 // Evaluate the gradient of the functor at the upwind and downwind locations
1048 const auto & grad_phi_upwind = functor.gradient(upwind_arg, *time_arg);
1049 const auto & grad_phi_downwind = functor.gradient(downwind_arg, *time_arg);
1050
1051 const auto coeffs = interpCoeffs(InterpMethod::Average, *face.fi, face.elem_is_upwind);
1052
1053 // Compute interpolation coefficients and advected values for each component
1054 for (unsigned int i = 0; i < LIBMESH_DIM; ++i)
1055 {
1056 const auto &component_upwind = phi_upwind(i), component_downwind = phi_downwind(i);
1057 const libMesh::VectorValue<T> &grad_upwind = grad_phi_upwind.row(i),
1058 grad_face = coeffs.first * grad_phi_upwind.row(i) +
1059 coeffs.second * grad_phi_downwind.row(i);
1060
1061 // Initialize min-max values
1062 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
1063 if (face.limiter_type == LimiterType::Venkatakrishnan ||
1064 face.limiter_type == LimiterType::SOU)
1065 std::tie(max_value, min_value) = computeMinMaxValue(functor, face, *time_arg, i);
1066
1067 // Perform full limited interpolation for the component
1068 ret(i) = fullLimitedInterpolation(*limiter,
1069 component_upwind,
1070 component_downwind,
1071 &grad_upwind,
1072 &grad_face,
1073 max_value,
1074 min_value,
1075 face);
1076 }
1077 }
1078
1079 // Return the interpolated vector value
1080 return ret;
1081}
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 1175 of file MathFVUtils.h.

1178{
1179 return containerInterpolate(functor, face, time);
1180}
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 1166 of file MathFVUtils.h.

1169{
1170 return containerInterpolate(functor, face, time);
1171}

◆ 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 911 of file MathFVUtils.h.

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

◆ 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 550 of file MathFVUtils.h.

556{
557 mooseAssert(limiter.constant() || grad_phi_upwind,
558 "Non-null gradient only supported for constant limiters.");
559
560 const libMesh::VectorValue<T> * const gradient_example = nullptr;
562 for (const auto i : make_range(unsigned(LIBMESH_DIM)))
563 {
564 if (grad_phi_upwind)
565 {
566 const libMesh::VectorValue<T> gradient = grad_phi_upwind->row(i);
567 ret(i) =
568 interpolate(limiter, phi_upwind(i), phi_downwind(i), &gradient, fi, fi_elem_is_upwind);
569 }
570 else
571 ret(i) = interpolate(
572 limiter, phi_upwind(i), phi_downwind(i), gradient_example, fi, fi_elem_is_upwind);
573 }
574
575 return ret;
576}
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 525 of file MathFVUtils.h.

531{
532 auto pr =
533 interpCoeffs(limiter,
534 phi_upwind,
535 phi_downwind,
536 grad_phi_upwind,
537 /*grad_phi_face*/ static_cast<const libMesh::VectorValue<Scalar> *>(nullptr),
538 /* max_value */ std::numeric_limits<Real>::max(),
539 /* min_value */ std::numeric_limits<Real>::min(),
540 fi,
541 fi_elem_is_upwind);
542 return pr.first * phi_upwind + pr.second * phi_downwind;
543}

◆ 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 298 of file MathFVUtils.h.

304{
305 switch (m)
306 {
307 case InterpMethod::Average:
308 case InterpMethod::SkewCorrectedAverage:
309 result = linearInterpolation(value1, value2, fi, one_is_elem);
310 break;
311 case InterpMethod::HarmonicAverage:
312 result = harmonicInterpolation(value1, value2, fi, one_is_elem);
313 break;
314 default:
315 mooseError("unsupported interpolation method for interpolate() function");
316 }
317}
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(), interpolate(), and FVInterfaceKernel::interpolateValue().

◆ 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 416 of file MathFVUtils.h.

423{
424 const auto coeffs = interpCoeffs(m, fi, one_is_elem, advector * fi.normal());
425 result = coeffs.first * value1 + coeffs.second * value2;
426}

◆ 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 369 of file MathFVUtils.h.

376{
377 switch (m)
378 {
379 case InterpMethod::Average:
380 result = linearInterpolation(fi_elem_advected * fi_elem_advector,
381 fi_neighbor_advected * fi_neighbor_advector,
382 fi,
383 true);
384 break;
385 case InterpMethod::Upwind:
386 {
387 const auto face_advector = linearInterpolation(MetaPhysicL::raw_value(fi_elem_advector),
388 MetaPhysicL::raw_value(fi_neighbor_advector),
389 fi,
390 true);
391 Real elem_coeff, neighbor_coeff;
392 if (face_advector * fi.normal() > 0)
393 elem_coeff = 1, neighbor_coeff = 0;
394 else
395 elem_coeff = 0, neighbor_coeff = 1;
396
397 result = elem_coeff * fi_elem_advected * fi_elem_advector +
398 neighbor_coeff * fi_neighbor_advected * fi_neighbor_advector;
399 break;
400 }
401 default:
402 mooseError("unsupported interpolation method for FVFaceInterface::interpolate");
403 }
404}

◆ 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 325 of file MathFVUtils.h.

326{
327 static_assert((FEK == FunctorEvaluationKind::Value) || (FEK == FunctorEvaluationKind::Dot),
328 "Only Value and Dot evaluations currently supported");
329 mooseAssert(face.limiter_type == LimiterType::CentralDifference,
330 "this interpolation method is meant for linear interpolations");
331
332 mooseAssert(face.fi,
333 "We must have a non-null face_info in order to prepare our ElemFromFace tuples");
334
336
337 const auto elem_arg = face.makeElem();
338 const auto neighbor_arg = face.makeNeighbor();
339
340 const auto elem_eval = functor.template genericEvaluate<FEK>(elem_arg, time);
341 const auto neighbor_eval = functor.template genericEvaluate<FEK>(neighbor_arg, time);
342
343 if (face.correct_skewness)
344 {
345 // This condition ensures that the recursive algorithm (face_center->
346 // face_gradient -> cell_gradient -> face_center -> ...) terminates after
347 // one loop. It is hardcoded to one loop at this point since it yields
348 // 2nd order accuracy on skewed meshes with the minimum additional effort.
349 FaceArg new_face(face);
350 new_face.correct_skewness = false;
351 const auto surface_gradient = functor.template genericEvaluate<GFEK>(new_face, time);
352
354 elem_eval, neighbor_eval, surface_gradient, *face.fi, true);
355 }
356 else
357 return linearInterpolation(elem_eval, neighbor_eval, *face.fi, true);
358}
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 LinearFVGradientReader::gradient(), FVGreenGaussGradient::internalFaceValues(), interpolate(), interpolate(), linearInterpolation(), 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 1187 of file MathFVUtils.h.

1188{
1189 const bool internal = fi.neighborPtr() && obj.hasBlocks(fi.elemSubdomainID()) &&
1190 obj.hasBlocks(fi.neighborSubdomainID());
1191 return !internal;
1192}
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 461 of file MathFVUtils.h.

462{
463 const Scalar denom = phiD - phiC;
464 const Scalar grad_dot = gradC * dCD;
465
466 // This is an arbitrary number here, when we start seeing convergence issues we
467 // can tune this but so far this has shown okay results.
468 constexpr Real eps = 1e-10;
469 const Real denom_sign =
470 std::copysign(1.0,
472 std::numeric_limits<Real>::min() * MetaPhysicL::raw_value(grad_dot));
473 const Scalar safe = denom + denom_sign * eps;
474 return 2.0 * grad_dot / safe - 1.0;
475}

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 277 of file MathFVUtils.h.

282{
283 const auto coeffs = interpCoeffs(InterpMethod::SkewCorrectedAverage, fi, one_is_elem);
284
285 auto value = (coeffs.first * value1 + coeffs.second * value2) +
286 face_gradient * fi.skewnessCorrectionVector();
287 return value;
288}
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