17#include "metaphysicl/raw_type.h"
18#include "libmesh/compare_types.h"
19#include "libmesh/elem.h"
95 const std::string & param_name);
115template <
typename T = Real>
119 const bool one_is_elem,
120 const T & face_flux = 0.0)
128 return std::make_pair(fi.
gC(), 1. - fi.
gC());
130 return std::make_pair(1. - fi.
gC(), fi.
gC());
135 if ((face_flux > 0) == one_is_elem)
136 return std::make_pair(1., 0.);
138 return std::make_pair(0., 1.);
142 mooseError(
"Unrecognized interpolation method");
151template <
typename T,
typename T2>
156 const bool one_is_elem,
161 "The selected interpolation function only works with average or skewness-corrected "
163 const auto coeffs =
interpCoeffs(interp_method, fi, one_is_elem);
164 return coeffs.first * value1 + coeffs.second * value2;
178template <
typename T1,
typename T2>
183 const bool one_is_elem)
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!");
203 if (value1 * value2 <= 0)
206 ") must be of the same sign for harmonic interpolation");
208 return 1.0 / (coeffs.first / value1 + coeffs.second / value2);
217 if (value1(i) * value2(i) <= 0)
218 mooseWarning(
"Component " + std::to_string(i) +
" of input values (" +
221 ") must be of the same sign for harmonic interpolation");
223 result(i) = 1.0 / (coeffs.first / value1(i) + coeffs.second / value2(i));
236 if (value1(i, j) * value2(i, j) <= 0)
237 mooseWarning(
"Component (" + std::to_string(i) +
"," + std::to_string(j) +
238 ") of input values (" +
241 ") must be of the same sign for harmonic interpolation");
243 result(i, j) = 1.0 / (coeffs.first / value1(i, j) + coeffs.second / value2(i, j));
252 static_assert(Moose::always_false<T1>,
253 "Harmonic interpolation is not implemented for the used type!");
262template <
typename T,
typename T2,
typename T3>
266 const T3 & face_gradient,
268 const bool one_is_elem)
272 auto value = (coeffs.first * value1 + coeffs.second * value2) +
283template <
typename T,
typename T2,
typename T3>
290 const bool one_is_elem)
302 mooseError(
"unsupported interpolation method for interpolate() function");
310template <
typename T, FunctorEvaluationKind FEK = FunctorEvaluationKind::Value>
315 "Only Value and Dot evaluations currently supported");
317 "this interpolation method is meant for linear interpolations");
320 "We must have a non-null face_info in order to prepare our ElemFromFace tuples");
324 const auto elem_arg = face.
makeElem();
327 const auto elem_eval = functor.template genericEvaluate<FEK>(elem_arg, time);
328 const auto neighbor_eval = functor.template genericEvaluate<FEK>(neighbor_arg, time);
338 const auto surface_gradient = functor.template genericEvaluate<GFEK>(new_face, time);
341 elem_eval, neighbor_eval, surface_gradient, *face.
fi,
true);
350template <
typename T1,
353 template <
typename>
class Vector1,
354 template <
typename>
class Vector2>
357 Vector1<T1> & result,
358 const T2 & fi_elem_advected,
359 const T2 & fi_neighbor_advected,
360 const Vector2<T3> & fi_elem_advector,
361 const Vector2<T3> & fi_neighbor_advector,
368 fi_neighbor_advected * fi_neighbor_advector,
378 Real elem_coeff, neighbor_coeff;
379 if (face_advector * fi.
normal() > 0)
380 elem_coeff = 1, neighbor_coeff = 0;
382 elem_coeff = 0, neighbor_coeff = 1;
384 result = elem_coeff * fi_elem_advected * fi_elem_advector +
385 neighbor_coeff * fi_neighbor_advected * fi_neighbor_advector;
389 mooseError(
"unsupported interpolation method for FVFaceInterface::interpolate");
401template <
typename T,
typename T2,
typename T3,
typename Vector>
407 const Vector & advector,
409 const bool one_is_elem)
412 result = coeffs.first * value1 + coeffs.second * value2;
421 bool correct_skewness =
false);
446template <
typename Scalar,
typename Vector>
448rF(
const Scalar & phiC,
const Scalar & phiD,
const Vector & gradC,
const RealVectorValue & dCD)
450 const Scalar denom = phiD - phiC;
451 const Scalar grad_dot = gradC * dCD;
455 constexpr Real eps = 1e-10;
456 const Real denom_sign =
460 const Scalar safe = denom + denom_sign * eps;
461 return 2.0 * grad_dot / safe - 1.0;
478 const T & phi_upwind,
479 const T & phi_downwind,
482 const Real & max_value,
483 const Real & min_value,
485 const bool fi_elem_is_upwind)
488 const auto beta = limiter(phi_upwind,
492 fi_elem_is_upwind ? fi.
dCN() : Point(-fi.
dCN()),
498 const auto w_f = fi_elem_is_upwind ? fi.
gC() : (1. - fi.
gC());
500 const auto g = beta * (1. - w_f);
502 return std::make_pair(1. - g, g);
508template <
typename Scalar,
510 typename Enable =
typename std::enable_if<libMesh::ScalarTraits<Scalar>::value>::type>
513 const Scalar & phi_upwind,
514 const Scalar & phi_downwind,
515 const Vector *
const grad_phi_upwind,
517 const bool fi_elem_is_upwind)
525 std::numeric_limits<Real>::max(),
526 std::numeric_limits<Real>::min(),
529 return pr.first * phi_upwind + pr.second * phi_downwind;
535template <
typename Limiter,
typename T,
typename Tensor>
538 const TypeVector<T> & phi_upwind,
539 const TypeVector<T> & phi_downwind,
540 const Tensor *
const grad_phi_upwind,
542 const bool fi_elem_is_upwind)
544 mooseAssert(limiter.
constant() || grad_phi_upwind,
545 "Non-null gradient only supported for constant limiters.");
549 for (
const auto i : make_range(
unsigned(LIBMESH_DIM)))
555 interpolate(limiter, phi_upwind(i), phi_downwind(i), &gradient, fi, fi_elem_is_upwind);
559 limiter, phi_upwind(i), phi_downwind(i), gradient_example, fi, fi_elem_is_upwind);
586 const T & phi_upwind,
587 const T & phi_downwind,
588 const VectorValue<T> *
const grad_phi_upwind,
589 const VectorValue<T> *
const grad_phi_face,
590 const Real & max_value,
591 const Real & min_value,
598 const auto beta = limiter(phi_upwind,
610 const auto & cell_centroid =
616 delta_face = (*grad_phi_upwind) * (face_centroid - cell_centroid);
618 delta_face = (*grad_phi_face) * (face_centroid - cell_centroid);
621 return phi_upwind + beta * delta_face;
648 typename Enable =
typename std::enable_if<ScalarTraits<T>::value>::type>
653 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
656 for (
const auto neighbor : (*face.
fi).elem().neighbor_ptr_range())
659 if (neighbor ==
nullptr)
663 const ElemArg local_cell_arg = {neighbor,
false};
666 max_value = std::max(max_value, value);
667 min_value = std::min(min_value, value);
671 for (
const auto neighbor : (*face.
fi).neighbor().neighbor_ptr_range())
674 if (neighbor ==
nullptr)
678 const ElemArg local_cell_arg = {neighbor,
false};
681 max_value = std::max(max_value, value);
682 min_value = std::min(min_value, value);
686 return std::make_pair(max_value, min_value);
719 const unsigned int & component)
722 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
725 for (
const auto neighbor : (*face.
fi).elem().neighbor_ptr_range())
728 if (neighbor ==
nullptr)
733 const ElemArg local_cell_arg = {neighbor,
false};
735 max_value = std::max(max_value, value);
736 min_value = std::min(min_value, value);
740 for (
const auto neighbor : (*face.
fi).neighbor().neighbor_ptr_range())
743 if (neighbor ==
nullptr)
748 const ElemArg local_cell_arg = {neighbor,
false};
750 max_value = std::max(max_value, value);
751 min_value = std::min(min_value, value);
755 return std::make_pair(max_value, min_value);
788 typename Enable =
typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
789std::pair<std::pair<T, T>, std::pair<T, T>>
794 "Only Value and Dot evaluations currently supported");
799 static const GradientType zero(0);
801 mooseAssert(face.
fi,
"this must be non-null");
811 auto phi_upwind = functor.template genericEvaluate<FEK>(upwind_arg, time);
812 auto phi_downwind = functor.template genericEvaluate<FEK>(downwind_arg, time);
815 std::pair<T, T> interp_coeffs;
825 std::numeric_limits<Real>::max(),
826 std::numeric_limits<Real>::min(),
836 time_arg = &temp_state;
839 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
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);
863 return std::make_pair(std::move(interp_coeffs),
864 std::make_pair(std::move(phi_upwind), std::move(phi_downwind)));
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)));
896 typename Enable =
typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
902 "Only Value and Dot evaluations currently supported");
907 return linearInterpolation<T, FEK>(functor, face, time);
913 const auto [interp_coeffs, advected] = interpCoeffsAndAdvected<T, FEK>(functor, face, time);
915 return interp_coeffs.first * advected.first + interp_coeffs.second * advected.second;
922 static const GradientType zero(0);
923 const auto & limiter =
929 const auto & phi_upwind = functor.template genericEvaluate<FEK>(upwind_arg, time);
930 const auto & phi_downwind = functor.template genericEvaluate<FEK>(downwind_arg, time);
937 time_arg = &temp_state;
941 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
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);
990 mooseAssert(face.
fi,
"this must be non-null");
998 auto phi_upwind = functor(upwind_arg, time);
999 auto phi_downwind = functor(downwind_arg, time);
1003 T coeff_upwind, coeff_downwind;
1009 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
1011 const auto &component_upwind = phi_upwind(i), component_downwind = phi_downwind(i);
1012 std::tie(coeff_upwind, coeff_downwind) =
interpCoeffs(*limiter,
1017 std::numeric_limits<Real>::max(),
1018 std::numeric_limits<Real>::min(),
1021 ret(i) = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1031 time_arg = &temp_state;
1035 const auto & grad_phi_upwind = functor.gradient(upwind_arg, *time_arg);
1036 const auto & grad_phi_downwind = functor.gradient(downwind_arg, *time_arg);
1041 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
1043 const auto &component_upwind = phi_upwind(i), component_downwind = phi_downwind(i);
1045 grad_face = coeffs.first * grad_phi_upwind.row(i) +
1046 coeffs.second * grad_phi_downwind.row(i);
1049 Real max_value(std::numeric_limits<Real>::min()), min_value(std::numeric_limits<Real>::max());
1090template <
typename T>
1095 typedef typename ContainerGradientType::value_type GradientType;
1096 const GradientType *
const example_gradient =
nullptr;
1098 mooseAssert(face.
fi,
"this must be non-null");
1103 const auto phi_upwind = functor(upwind_arg, time);
1104 const auto phi_downwind = functor(downwind_arg, time);
1108 typename T::value_type coeff_upwind, coeff_downwind;
1113 for (
const auto i : index_range(ret))
1115 const auto &component_upwind = phi_upwind[i], component_downwind = phi_downwind[i];
1116 std::tie(coeff_upwind, coeff_downwind) =
interpCoeffs(*limiter,
1121 std::numeric_limits<Real>::max(),
1122 std::numeric_limits<Real>::min(),
1125 ret[i] = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1130 const auto grad_phi_upwind = functor.
gradient(upwind_arg, time);
1131 for (
const auto i : index_range(ret))
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,
1140 std::numeric_limits<Real>::max(),
1141 std::numeric_limits<Real>::min(),
1144 ret[i] = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1151template <
typename T>
1160template <
typename T, std::
size_t N>
1172template <
typename SubdomainRestrictable>
DualNumber< Real, DNDerivativeType, true > ADReal
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
A base class interface for both producers and consumers of functor face arguments,...
This data structure is used to store geometric and variable related metadata about each cell face in ...
SubdomainID neighborSubdomainID() const
Point skewnessCorrectionVector() const
Returns the skewness-correction vector (vector between the approximate and real face centroids).
const Point & normal() const
Returns the unit normal vector for the face oriented outward from the face's elem element.
const Elem * neighborPtr() const
SubdomainID elemSubdomainID() const
const Point & neighborCentroid() const
const Point & dCN() const
const Point & elemCentroid() const
Returns the element centroids of the elements on the elem and neighbor sides of the face.
Real gC() const
Return the geometric weighting factor.
const Point & faceCentroid() const
Returns the coordinates of the face centroid.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Every object that can be built by the factory should be derived from this class.
This class provides variable solution values for other classes/objects to bind to when looping over f...
Base class for defining slope limiters for finite volume or potentially reconstructed Discontinuous-G...
static std::unique_ptr< Limiter > build(LimiterType limiter)
virtual bool constant() const =0
Base class template for functor objects.
typename FunctorReturnType< T, FunctorEvaluationKind::Gradient >::type GradientType
This rigmarole makes it so that a user can create functors that return containers (std::vector,...
GradientType gradient(const ElemArg &elem, const StateArg &state) const
Same as their evaluateGradient overloads with the same arguments but allows for caching implementatio...
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...
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.
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...
Scalar rF(const Scalar &phiC, const Scalar &phiD, const Vector &gradC, const RealVectorValue &dCD)
From Moukalled 12.30.
std::pair< Real, Real > computeMinMaxValue(const FunctorBase< T > &functor, const FaceArg &face, const StateArg &time)
This function calculates the minimum and maximum values within a two-cell stencil.
bool setInterpolationMethod(const MooseObject &obj, Moose::FV::InterpMethod &interp_method, const std::string ¶m_name)
Sets one interpolation method.
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...
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.
@ Venkatakrishnan
Venkatakrishnan limiter (smooth, multidimensional).
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.
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...
InterpMethod
This codifies a set of available ways to interpolate with elem+neighbor solution information to calcu...
@ SkewCorrectedAverage
(gc*elem+(1-gc)*neighbor)+gradient*(rf-rf')
@ HarmonicAverage
1/(gc/elem+(1-gc)/neighbor)
@ Average
gc*elem+(1-gc)*neighbor
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.
MooseEnum interpolationMethods()
Returns an enum with all the currently supported interpolation methods and the current default for FV...
std::pair< Real, Real > interpCoeffs(const InterpMethod m, const FaceInfo &fi, const bool one_is_elem, const T &face_flux=0.0)
Produce the interpolation coefficients in the equation:
bool onBoundary(const SubdomainRestrictable &obj, const FaceInfo &fi)
Return whether the supplied face is on a boundary of the object's execution.
InputParameters advectedInterpolationParameter()
InterpMethod selectInterpolationMethod(const std::string &interp_method)
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
std::string stringify(const T &t)
conversion to string
FunctorEvaluationKind
An enumeration of possible functor evaluation kinds.
A structure that is used to evaluate Moose functors logically at an element/cell center.
A structure defining a "face" evaluation calling argument for Moose functors.
ElemArg makeNeighbor() const
Make a ElemArg from our data using the face information neighbor.
bool elem_is_upwind
a boolean which states whether the face information element is upwind of the face
ElemArg makeElem() const
Make a ElemArg from our data using the face information element.
bool correct_skewness
Whether to perform skew correction.
Moose::FV::LimiterType limiter_type
a limiter which defines how the functor evaluated on either side of the face should be interpolated t...
const FaceInfo * fi
a face information object which defines our location in space
const Moose::StateArg * state_limiter
A member that can be used to define the instance in which the limiters are executed.
This structure takes an evaluation kind as a template argument and defines a constant expression indi...
State argument for evaluating functors.