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

Classes

class  CentralDifferenceLimiter
 Implements a limiter which reproduces a central-differencing scheme, defined by $(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 $(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 $(r_f) = 0$. More...
 
class  VanLeerLimiter
 The Van Leer limiter limiter function $(r_f)$ is defined as: More...
 
class  VenkatakrishnanLimiter
 The Venkatakrishnan limiter is derived from the following equations: More...
 

Enumerations

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

Functions

LimiterType limiterType (InterpMethod interp_method)
 Return the limiter type associated with the supplied interpolation method. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
template<typename T = Real>
std::pair< Real, RealinterpCoeffs (const InterpMethod m, const FaceInfo &fi, const bool one_is_elem, const T &face_flux=0.0)
 Produce the interpolation coefficients in the equation: More...
 
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. More...
 
template<typename T1 , typename T2 >
libMesh::CompareTypes< T1, T2 >::supertype harmonicInterpolation (const T1 &value1, const T2 &value2, const FaceInfo &fi, const bool one_is_elem)
 Computes the harmonic mean (1/(gc/value1+(1-gc)/value2)) of Reals, RealVectorValues and RealTensorValues while accounting for the possibility that one or both of them are AD. More...
 
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. More...
 
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). More...
 
template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value>
linearInterpolation (const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
 perform a possibly skew-corrected linear interpolation by evaluating the supplied functor with the provided functor face argument More...
 
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. More...
 
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. More...
 
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. More...
 
template<typename Scalar , typename Vector >
Scalar rF (const Scalar &phiC, const Scalar &phiD, const Vector &gradC, const RealVectorValue &dCD)
 From Moukalled 12.30. More...
 
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: More...
 
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. More...
 
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. More...
 
template<typename T >
fullLimitedInterpolation (const Limiter< T > &limiter, const T &phi_upwind, const T &phi_downwind, const VectorValue< T > *const grad_phi_upwind, const VectorValue< T > *const grad_phi_face, const Real &max_value, const Real &min_value, const FaceArg &face)
 This function performs a full limited interpolation of a variable, taking into account the values and gradients at both upwind and downwind locations, as well as geometric information and limits. More...
 
template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value, typename Enable = typename std::enable_if<ScalarTraits<T>::value>::type>
std::pair< Real, RealcomputeMinMaxValue (const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
 This function calculates the minimum and maximum values within a two-cell stencil. More...
 
template<typename T >
std::pair< Real, RealcomputeMinMaxValue (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. More...
 
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. More...
 
template<typename T , FunctorEvaluationKind FEK = FunctorEvaluationKind::Value, typename Enable = typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
interpolate (const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
 This function interpolates values at faces in a computational grid using a specified functor, face argument, and evaluation kind. More...
 
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. More...
 
template<typename T >
containerInterpolate (const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
 This function interpolates container values at faces in a computational grid using a specified functor, face argument, and limiter type. More...
 
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. More...
 
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. More...
 
const MooseEnum moose_limiter_type ("vanLeer=0 upwind=1 central_difference=2 min_mod=3 sou=4 quick=5 venkatakrishnan=6", "upwind")
 

Variables

const MooseEnum moose_limiter_type
 

Enumeration Type Documentation

◆ GradientLimiterType

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.

22  : int
23 {
25  None = -1,
27  Venkatakrishnan = 0
28 };
Venkatakrishnan limiter (smooth, multidimensional).

◆ InterpMethod

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.

◆ LimiterType

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

Definition at line 26 of file Limiter.h.

26  : int
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...
Venkatakrishnan limiter (smooth, multidimensional).

◆ LinearFVComputationMode

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.

Referenced by FVAdvection::validParams().

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 }
MooseEnum interpolationMethods()
Returns an enum with all the currently supported interpolation methods and the current default for FV...
Definition: MathFVUtils.C:61
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:54

◆ computeMinMaxValue() [1/2]

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

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

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

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

Definition at line 650 of file MathFVUtils.h.

Referenced by interpCoeffsAndAdvected(), and interpolate().

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

◆ computeMinMaxValue() [2/2]

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

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

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

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

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

Definition at line 716 of file MathFVUtils.h.

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

◆ containerInterpolate()

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

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

It handles different limiter types and performs interpolation accordingly.

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

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

Definition at line 1092 of file MathFVUtils.h.

Referenced by interpolate().

1093 {
1094  typedef typename FunctorBase<T>::GradientType ContainerGradientType;
1095  typedef typename ContainerGradientType::value_type GradientType;
1096  const GradientType * const example_gradient = nullptr;
1097 
1098  mooseAssert(face.fi, "this must be non-null");
1099  const auto limiter = Limiter<typename T::value_type>::build(face.limiter_type);
1100 
1101  const auto upwind_arg = face.elem_is_upwind ? face.makeElem() : face.makeNeighbor();
1102  const auto downwind_arg = face.elem_is_upwind ? face.makeNeighbor() : face.makeElem();
1103  const auto phi_upwind = functor(upwind_arg, time);
1104  const auto phi_downwind = functor(downwind_arg, time);
1105 
1106  // initialize in order to get proper size
1107  T ret = phi_upwind;
1108  typename T::value_type coeff_upwind, coeff_downwind;
1109 
1110  if (face.limiter_type == LimiterType::Upwind ||
1111  face.limiter_type == LimiterType::CentralDifference)
1112  {
1113  for (const auto i : index_range(ret))
1114  {
1115  const auto &component_upwind = phi_upwind[i], component_downwind = phi_downwind[i];
1116  std::tie(coeff_upwind, coeff_downwind) = interpCoeffs(*limiter,
1117  component_upwind,
1118  component_downwind,
1119  example_gradient,
1120  example_gradient,
1123  *face.fi,
1124  face.elem_is_upwind);
1125  ret[i] = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1126  }
1127  }
1128  else
1129  {
1130  const auto grad_phi_upwind = functor.gradient(upwind_arg, time);
1131  for (const auto i : index_range(ret))
1132  {
1133  const auto &component_upwind = phi_upwind[i], component_downwind = phi_downwind[i];
1134  const auto & grad = grad_phi_upwind[i];
1135  std::tie(coeff_upwind, coeff_downwind) = interpCoeffs(*limiter,
1136  component_upwind,
1137  component_downwind,
1138  &grad,
1139  example_gradient,
1142  *face.fi,
1143  face.elem_is_upwind);
1144  ret[i] = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1145  }
1146  }
1147 
1148  return ret;
1149 }
auto max(const L &left, const R &right)
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:
Definition: MathFVUtils.h:477
auto min(const L &left, const R &right)
auto index_range(const T &sizable)

◆ 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.

Referenced by MooseVariableFV< Real >::getExtrapolatedBoundaryFaceValue().

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.");
147  mooseAssert(ft == FaceInfo::VarFaceNeighbors::NEIGHBOR
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 }
const Elem & elem() const
Definition: FaceInfo.h:85
const Elem * neighborPtr() const
Definition: FaceInfo.h:88
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

◆ 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.

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

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 }

◆ fullLimitedInterpolation()

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

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

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

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

Definition at line 585 of file MathFVUtils.h.

Referenced by interpolate().

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

◆ 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.

Referenced by FVFluxKernel::gradUDotNormal().

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&#39;s elem element...
Definition: FaceInfo.h:72
const ADTemplateVariableGradient< OutputType > & adGradSln() const override
AD grad solution getter.

◆ 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.

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

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 
180  if (coord_type == Moose::CoordinateSystemType::COORD_RZ)
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)
250  mooseError(
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
522  mooseWarning(
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 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
const unsigned int invalid_uint
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
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 mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition: MooseError.h:345
MeshBase & mesh
auto raw_value(const Eigen::Map< T > &in)
Definition: EigenADReal.h:100
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:163
This data structure is used to store geometric and variable related metadata about each cell face in ...
Definition: FaceInfo.h:37
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)
A structure defining a "face" evaluation calling argument for Moose functors.
Real volume(const MeshBase &mesh, unsigned int dim=libMesh::invalid_uint)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)

◆ greenGaussGradient() [2/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 }
gc*elem+(1-gc)*neighbor
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
MeshBase & mesh
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)
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...
Definition: MathFVUtils.h:285

◆ greenGaussGradient() [3/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 }
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:163
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)
IntRange< T > make_range(T beg, T end)

◆ greenGaussGradient() [4/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 }
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:163
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)
IntRange< T > make_range(T beg, T end)

◆ greenGaussGradient() [5/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 }
Base class template for functor objects.
Definition: MooseFunctor.h:137
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)
auto index_range(const T &sizable)

◆ greenGaussGradient() [6/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 }
Base class template for functor objects.
Definition: MooseFunctor.h:137
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)
auto index_range(const T &sizable)

◆ greenGaussGradient() [7/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
726  ArrayComponentFunctor<T, FunctorBase<std::array<T, N>>> scalar_functor(functor, i);
727  ret[i] =
728  greenGaussGradient(elem_arg, state_arg, scalar_functor, two_term_boundary_expansion, mesh);
729  }
730 
731  return ret;
732 }
Base class template for functor objects.
Definition: MooseFunctor.h:137
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)
IntRange< T > make_range(T beg, T end)

◆ greenGaussGradient() [8/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
749  ArrayComponentFunctor<T, FunctorBase<std::array<T, N>>> scalar_functor(functor, i);
750  ret[i] =
751  greenGaussGradient(face_arg, state_arg, scalar_functor, two_term_boundary_expansion, mesh);
752  }
753 
754  return ret;
755 }
Base class template for functor objects.
Definition: MooseFunctor.h:137
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)
IntRange< T > make_range(T beg, T end)

◆ harmonicInterpolation()

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

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

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

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

Definition at line 180 of file MathFVUtils.h.

Referenced by interpolate().

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

◆ 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:

= c_1 * {F1} + c_2 * {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.

Referenced by LinearFVAnisotropicDiffusion::computeFluxRHSContribution(), LinearFVDiffusion::computeFluxRHSContribution(), containerInterpolate(), harmonicInterpolation(), interpCoeffsAndAdvected(), interpolate(), linearInterpolation(), and skewCorrectedLinearInterpolation().

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 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
Real gC() const
Return the geometric weighting factor.
Definition: FaceInfo.h:136

◆ 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:

= c_upwind * {upwind} + c_downwind * {downwind}

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

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

Definition at line 477 of file MathFVUtils.h.

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

◆ interpCoeffsAndAdvected()

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

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

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

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

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

Definition at line 790 of file MathFVUtils.h.

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

◆ interpolate() [1/9]

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

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

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

Definition at line 285 of file MathFVUtils.h.

Referenced by InterfaceDiffusiveFluxIntegralTempl< is_ad >::computeQpIntegral(), FVDiffusionInterface::computeQpResidual(), FVOneVarDiffusionInterface::computeQpResidual(), FVOrthogonalDiffusion::computeQpResidual(), FVAnisotropicDiffusion::computeQpResidual(), FVDiffusion::computeQpResidual(), PiecewiseByBlockLambdaFunctor< T >::evaluate(), MooseLinearVariableFV< Real >::evaluate(), MooseVariableFV< Real >::evaluate(), greenGaussGradient(), interpolate(), and NEML2FEInterpolation::updateInterpolations().

291 {
292  switch (m)
293  {
294  case InterpMethod::Average:
295  case InterpMethod::SkewCorrectedAverage:
296  result = linearInterpolation(value1, value2, fi, one_is_elem);
297  break;
298  case InterpMethod::HarmonicAverage:
299  result = harmonicInterpolation(value1, value2, fi, one_is_elem);
300  break;
301  default:
302  mooseError("unsupported interpolation method for interpolate() function");
303  }
304 }
libMesh::CompareTypes< T1, T2 >::supertype harmonicInterpolation(const T1 &value1, const T2 &value2, const FaceInfo &fi, const bool one_is_elem)
Computes the harmonic mean (1/(gc/value1+(1-gc)/value2)) of Reals, RealVectorValues and RealTensorVal...
Definition: MathFVUtils.h:180
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
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 pr...
Definition: MathFVUtils.h:312

◆ interpolate() [2/9]

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

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

Definition at line 356 of file MathFVUtils.h.

363 {
364  switch (m)
365  {
366  case InterpMethod::Average:
367  result = linearInterpolation(fi_elem_advected * fi_elem_advector,
368  fi_neighbor_advected * fi_neighbor_advector,
369  fi,
370  true);
371  break;
372  case InterpMethod::Upwind:
373  {
374  const auto face_advector = linearInterpolation(MetaPhysicL::raw_value(fi_elem_advector),
375  MetaPhysicL::raw_value(fi_neighbor_advector),
376  fi,
377  true);
378  Real elem_coeff, neighbor_coeff;
379  if (face_advector * fi.normal() > 0)
380  elem_coeff = 1, neighbor_coeff = 0;
381  else
382  elem_coeff = 0, neighbor_coeff = 1;
383 
384  result = elem_coeff * fi_elem_advected * fi_elem_advector +
385  neighbor_coeff * fi_neighbor_advected * fi_neighbor_advector;
386  break;
387  }
388  default:
389  mooseError("unsupported interpolation method for FVFaceInterface::interpolate");
390  }
391 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
auto raw_value(const Eigen::Map< T > &in)
Definition: EigenADReal.h:100
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 pr...
Definition: MathFVUtils.h:312
const Point & normal() const
Returns the unit normal vector for the face oriented outward from the face&#39;s elem element...
Definition: FaceInfo.h:72
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

◆ interpolate() [3/9]

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

Provides interpolation of face values for advective flux kernels.

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

Definition at line 403 of file MathFVUtils.h.

410 {
411  const auto coeffs = interpCoeffs(m, fi, one_is_elem, advector * fi.normal());
412  result = coeffs.first * value1 + coeffs.second * value2;
413 }
const Point & normal() const
Returns the unit normal vector for the face oriented outward from the face&#39;s elem element...
Definition: FaceInfo.h:72
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:
Definition: MathFVUtils.h:477

◆ interpolate() [4/9]

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

Interpolates with a limiter.

Definition at line 512 of file MathFVUtils.h.

518 {
519  auto pr =
520  interpCoeffs(limiter,
521  phi_upwind,
522  phi_downwind,
523  grad_phi_upwind,
524  /*grad_phi_face*/ static_cast<const libMesh::VectorValue<Scalar> *>(nullptr),
525  /* max_value */ std::numeric_limits<Real>::max(),
526  /* min_value */ std::numeric_limits<Real>::min(),
527  fi,
528  fi_elem_is_upwind);
529  return pr.first * phi_upwind + pr.second * phi_downwind;
530 }
auto max(const L &left, const R &right)
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:
Definition: MathFVUtils.h:477
auto min(const L &left, const R &right)

◆ interpolate() [5/9]

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

Vector overload.

Definition at line 537 of file MathFVUtils.h.

543 {
544  mooseAssert(limiter.constant() || grad_phi_upwind,
545  "Non-null gradient only supported for constant limiters.");
546 
547  const libMesh::VectorValue<T> * const gradient_example = nullptr;
549  for (const auto i : make_range(unsigned(LIBMESH_DIM)))
550  {
551  if (grad_phi_upwind)
552  {
553  const libMesh::VectorValue<T> gradient = grad_phi_upwind->row(i);
554  ret(i) =
555  interpolate(limiter, phi_upwind(i), phi_downwind(i), &gradient, fi, fi_elem_is_upwind);
556  }
557  else
558  ret(i) = interpolate(
559  limiter, phi_upwind(i), phi_downwind(i), gradient_example, fi, fi_elem_is_upwind);
560  }
561 
562  return ret;
563 }
std::array< T, N > interpolate(const FunctorBase< std::array< T, N >> &functor, const FaceArg &face, const StateArg &time)
Definition: MathFVUtils.h:1162
IntRange< T > make_range(T beg, T end)

◆ interpolate() [6/9]

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

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

It handles different limiter types and performs interpolation accordingly.

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

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

Definition at line 898 of file MathFVUtils.h.

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

◆ interpolate() [7/9]

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

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

It handles different limiter types and performs interpolation accordingly.

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

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

Definition at line 983 of file MathFVUtils.h.

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

◆ interpolate() [8/9]

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

Definition at line 1153 of file MathFVUtils.h.

1156 {
1157  return containerInterpolate(functor, face, time);
1158 }
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...
Definition: MathFVUtils.h:1092

◆ interpolate() [9/9]

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

Definition at line 1162 of file MathFVUtils.h.

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

◆ 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.

Referenced by advectedInterpolationParameter().

62 {
63  return MooseEnum("average upwind sou min_mod vanLeer quick venkatakrishnan skewness-corrected",
64  "upwind");
65 }
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54

◆ 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.

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

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 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311

◆ linearInterpolation() [1/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.

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

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 }
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:
Definition: MathFVUtils.h:477

◆ linearInterpolation() [2/2]

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

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

Definition at line 312 of file MathFVUtils.h.

313 {
314  static_assert((FEK == FunctorEvaluationKind::Value) || (FEK == FunctorEvaluationKind::Dot),
315  "Only Value and Dot evaluations currently supported");
316  mooseAssert(face.limiter_type == LimiterType::CentralDifference,
317  "this interpolation method is meant for linear interpolations");
318 
319  mooseAssert(face.fi,
320  "We must have a non-null face_info in order to prepare our ElemFromFace tuples");
321 
322  constexpr FunctorEvaluationKind GFEK = FunctorGradientEvaluationKind<FEK>::value;
323 
324  const auto elem_arg = face.makeElem();
325  const auto neighbor_arg = face.makeNeighbor();
326 
327  const auto elem_eval = functor.template genericEvaluate<FEK>(elem_arg, time);
328  const auto neighbor_eval = functor.template genericEvaluate<FEK>(neighbor_arg, time);
329 
330  if (face.correct_skewness)
331  {
332  // This condition ensures that the recursive algorithm (face_center->
333  // face_gradient -> cell_gradient -> face_center -> ...) terminates after
334  // one loop. It is hardcoded to one loop at this point since it yields
335  // 2nd order accuracy on skewed meshes with the minimum additional effort.
336  FaceArg new_face(face);
337  new_face.correct_skewness = false;
338  const auto surface_gradient = functor.template genericEvaluate<GFEK>(new_face, time);
339 
341  elem_eval, neighbor_eval, surface_gradient, *face.fi, true);
342  }
343  else
344  return linearInterpolation(elem_eval, neighbor_eval, *face.fi, true);
345 }
FunctorEvaluationKind
An enumeration of possible functor evaluation kinds.
Definition: MooseFunctor.h:36
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.
Definition: MathFVUtils.h:264
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 pr...
Definition: MathFVUtils.h:312

◆ 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.

Referenced by greenGaussGradient().

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 }
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
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.
const Elem & elem() const
Definition: FaceInfo.h:85
const Point & faceCentroid() const
Returns the coordinates of the face centroid.
Definition: FaceInfo.h:75
MeshBase & mesh
Real faceArea() const
Returns the face area of face id.
Definition: FaceInfo.h:64
This data structure is used to store geometric and variable related metadata about each cell face in ...
Definition: FaceInfo.h:37
const Elem * neighborPtr() const
Definition: FaceInfo.h:88
const Point & normal() const
Returns the unit normal vector for the face oriented outward from the face&#39;s elem element...
Definition: FaceInfo.h:72
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
const RemoteElem * remote_elem

◆ moose_limiter_type()

const MooseEnum Moose::FV::moose_limiter_type ( )

◆ onBoundary() [1/2]

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

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

Definition at line 1174 of file MathFVUtils.h.

Referenced by FVFluxKernel::onBoundary(), ThreadedElementLoopBase< ConstElemPointerRange >::operator()(), and ThreadedFaceLoop< RangeType >::operator()().

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

◆ onBoundary() [2/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 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
const Elem & elem() const
Definition: FaceInfo.h:85
const Elem * neighborPtr() const
Definition: FaceInfo.h:88
const Elem & neighbor() const
Definition: FaceInfo.h:220

◆ rF()

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

From Moukalled 12.30.

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

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

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

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

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

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

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

Definition at line 448 of file MathFVUtils.h.

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

449 {
450  const Scalar denom = phiD - phiC;
451  const Scalar grad_dot = gradC * dCD;
452 
453  // This is an arbitrary number here, when we start seeing convergence issues we
454  // can tune this but so far this has shown okay results.
455  constexpr Real eps = 1e-10;
456  const Real denom_sign =
457  std::copysign(1.0,
458  MetaPhysicL::raw_value(denom) +
460  const Scalar safe = denom + denom_sign * eps;
461  return 2.0 * grad_dot / safe - 1.0;
462 }
int eps(unsigned int i, unsigned int j)
2D version
auto raw_value(const Eigen::Map< T > &in)
Definition: EigenADReal.h:100
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
auto min(const L &left, const R &right)

◆ selectInterpolationMethod()

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

Definition at line 81 of file MathFVUtils.C.

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

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 }
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311

◆ 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.

Referenced by FVAdvection::FVAdvection().

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:416
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:54
InterpMethod selectInterpolationMethod(const std::string &interp_method)
Definition: MathFVUtils.C:81

◆ skewCorrectedLinearInterpolation()

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

Linear interpolation with skewness correction using the face gradient.

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

Definition at line 264 of file MathFVUtils.h.

Referenced by linearInterpolation().

269 {
270  const auto coeffs = interpCoeffs(InterpMethod::SkewCorrectedAverage, fi, one_is_elem);
271 
272  auto value = (coeffs.first * value1 + coeffs.second * value2) +
273  face_gradient * fi.skewnessCorrectionVector();
274  return value;
275 }
Point skewnessCorrectionVector() const
Returns the skewness-correction vector (vector between the approximate and real face centroids)...
Definition: FaceInfo.C:74
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
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:
Definition: MathFVUtils.h:477

Variable Documentation

◆ moose_limiter_type

const MooseEnum Moose::FV::moose_limiter_type