17 #include "libmesh/compare_types.h" 18 #include "libmesh/elem.h" 92 const std::string & param_name);
112 template <
typename T = Real>
113 std::pair<Real, Real>
116 const bool one_is_elem,
117 const T & face_flux = 0.0)
125 return std::make_pair(fi.
gC(), 1. - fi.
gC());
127 return std::make_pair(1. - fi.
gC(), fi.
gC());
132 if ((face_flux > 0) == one_is_elem)
133 return std::make_pair(1., 0.);
135 return std::make_pair(0., 1.);
139 mooseError(
"Unrecognized interpolation method");
148 template <
typename T,
typename T2>
153 const bool one_is_elem,
158 "The selected interpolation function only works with average or skewness-corrected " 160 const auto coeffs =
interpCoeffs(interp_method, fi, one_is_elem);
161 return coeffs.first * value1 + coeffs.second * value2;
175 template <
typename T1,
typename T2>
180 const bool one_is_elem)
184 static_assert(std::is_same<
typename MetaPhysicL::RawType<T1>::value_type,
185 typename MetaPhysicL::RawType<T2>::value_type>::
value,
186 "The input values for harmonic interpolation need to have the same raw-value!");
200 if (value1 * value2 <= 0)
203 ") must be of the same sign for harmonic interpolation");
205 return 1.0 / (coeffs.first / value1 + coeffs.second / value2);
214 if (value1(i) * value2(i) <= 0)
215 mooseWarning(
"Component " + std::to_string(i) +
" of input values (" +
218 ") must be of the same sign for harmonic interpolation");
220 result(i) = 1.0 / (coeffs.first / value1(i) + coeffs.second / value2(i));
233 if (value1(i, j) * value2(i, j) <= 0)
234 mooseWarning(
"Component (" + std::to_string(i) +
"," + std::to_string(j) +
235 ") of input values (" +
238 ") must be of the same sign for harmonic interpolation");
240 result(i, j) = 1.0 / (coeffs.first / value1(i, j) + coeffs.second / value2(i, j));
249 static_assert(Moose::always_false<T1>,
250 "Harmonic interpolation is not implemented for the used type!");
259 template <
typename T,
typename T2,
typename T3>
263 const T3 & face_gradient,
265 const bool one_is_elem)
269 auto value = (coeffs.first * value1 + coeffs.second * value2) +
280 template <
typename T,
typename T2,
typename T3>
287 const bool one_is_elem)
299 mooseError(
"unsupported interpolation method for interpolate() function");
307 template <
typename T, FunctorEvaluationKind FEK = FunctorEvaluationKind::Value>
312 "Only Value and Dot evaluations currently supported");
314 "this interpolation method is meant for linear interpolations");
317 "We must have a non-null face_info in order to prepare our ElemFromFace tuples");
321 const auto elem_arg = face.
makeElem();
324 const auto elem_eval = functor.template genericEvaluate<FEK>(elem_arg, time);
325 const auto neighbor_eval = functor.template genericEvaluate<FEK>(neighbor_arg, time);
335 const auto surface_gradient = functor.template genericEvaluate<GFEK>(new_face, time);
338 elem_eval, neighbor_eval, surface_gradient, *face.
fi,
true);
347 template <
typename T1,
356 Vector1<T1> & result,
357 const T2 & fi_elem_advected,
358 const T2 & fi_neighbor_advected,
359 const Vector2<T3> & fi_elem_advector,
360 const Vector2<T3> & fi_neighbor_advector,
367 fi_neighbor_advected * fi_neighbor_advector,
377 Real elem_coeff, neighbor_coeff;
378 if (face_advector * fi.
normal() > 0)
379 elem_coeff = 1, neighbor_coeff = 0;
381 elem_coeff = 0, neighbor_coeff = 1;
383 result = elem_coeff * fi_elem_advected * fi_elem_advector +
384 neighbor_coeff * fi_neighbor_advected * fi_neighbor_advector;
388 mooseError(
"unsupported interpolation method for FVFaceInterface::interpolate");
400 template <
typename T,
typename T2,
typename T3,
typename Vector>
406 const Vector & advector,
408 const bool one_is_elem)
411 result = coeffs.first * value1 + coeffs.second * value2;
420 bool correct_skewness =
false);
443 template <
typename Scalar,
typename Vector>
448 if ((phiD - phiC) == 0)
456 return 2. * gradC * dCD / (phiD - phiC) - 1.;
470 template <
typename T>
473 const T & phi_upwind,
474 const T & phi_downwind,
477 const Real & max_value,
478 const Real & min_value,
480 const bool fi_elem_is_upwind)
483 const auto beta = limiter(phi_upwind,
487 fi_elem_is_upwind ? fi.
dCN() : Point(-fi.
dCN()),
493 const auto w_f = fi_elem_is_upwind ? fi.
gC() : (1. - fi.
gC());
495 const auto g = beta * (1. - w_f);
497 return std::make_pair(1. - g, g);
503 template <
typename Scalar,
505 typename Enable =
typename std::enable_if<libMesh::ScalarTraits<Scalar>::value>::type>
508 const Scalar & phi_upwind,
509 const Scalar & phi_downwind,
510 const Vector *
const grad_phi_upwind,
512 const bool fi_elem_is_upwind)
524 return pr.first * phi_upwind + pr.second * phi_downwind;
530 template <
typename Limiter,
typename T,
typename Tensor>
533 const TypeVector<T> & phi_upwind,
534 const TypeVector<T> & phi_downwind,
535 const Tensor *
const grad_phi_upwind,
537 const bool fi_elem_is_upwind)
539 mooseAssert(limiter.
constant() || grad_phi_upwind,
540 "Non-null gradient only supported for constant limiters.");
544 for (
const auto i :
make_range(
unsigned(LIBMESH_DIM)))
550 interpolate(limiter, phi_upwind(i), phi_downwind(i), &gradient, fi, fi_elem_is_upwind);
554 limiter, phi_upwind(i), phi_downwind(i), gradient_example, fi, fi_elem_is_upwind);
578 template <
typename T>
581 const T & phi_upwind,
582 const T & phi_downwind,
583 const VectorValue<T> *
const grad_phi_upwind,
584 const VectorValue<T> *
const grad_phi_face,
585 const Real & max_value,
586 const Real & min_value,
593 const auto beta = limiter(phi_upwind,
605 const auto & cell_centroid =
611 delta_face = (*grad_phi_upwind) * (face_centroid - cell_centroid);
613 delta_face = (*grad_phi_face) * (face_centroid - cell_centroid);
616 return phi_upwind + beta * delta_face;
641 template <
typename T,
643 typename Enable =
typename std::enable_if<ScalarTraits<T>::value>::type>
644 std::pair<Real, Real>
651 for (
const auto neighbor : (*face.
fi).elem().neighbor_ptr_range())
654 if (neighbor ==
nullptr)
658 const ElemArg local_cell_arg = {neighbor,
false};
666 for (
const auto neighbor : (*face.
fi).neighbor().neighbor_ptr_range())
669 if (neighbor ==
nullptr)
673 const ElemArg local_cell_arg = {neighbor,
false};
681 return std::make_pair(max_value, min_value);
709 template <
typename T>
710 std::pair<Real, Real>
714 const unsigned int & component)
720 for (
const auto neighbor : (*face.
fi).elem().neighbor_ptr_range())
723 if (neighbor ==
nullptr)
728 const ElemArg local_cell_arg = {neighbor,
false};
735 for (
const auto neighbor : (*face.
fi).neighbor().neighbor_ptr_range())
738 if (neighbor ==
nullptr)
743 const ElemArg local_cell_arg = {neighbor,
false};
750 return std::make_pair(max_value, min_value);
781 template <
typename T,
783 typename Enable =
typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
784 std::pair<std::pair<T, T>, std::pair<T, T>>
789 "Only Value and Dot evaluations currently supported");
796 mooseAssert(face.
fi,
"this must be non-null");
806 auto phi_upwind = functor.template genericEvaluate<FEK>(upwind_arg, time);
807 auto phi_downwind = functor.template genericEvaluate<FEK>(downwind_arg, time);
810 std::pair<T, T> interp_coeffs;
831 time_arg = &temp_state;
841 const auto grad_phi_upwind = functor.template genericEvaluate<GFEK>(upwind_arg, *time_arg);
842 const auto grad_phi_face = functor.template genericEvaluate<GFEK>(face, *time_arg);
853 face.elem_is_upwind);
858 return std::make_pair(std::move(interp_coeffs),
859 std::make_pair(std::move(phi_upwind), std::move(phi_downwind)));
861 return std::make_pair(
862 std::make_pair(std::move(interp_coeffs.second), std::move(interp_coeffs.first)),
863 std::make_pair(std::move(phi_downwind), std::move(phi_upwind)));
889 template <
typename T,
891 typename Enable =
typename std::enable_if<libMesh::ScalarTraits<T>::value>::type>
897 "Only Value and Dot evaluations currently supported");
902 return linearInterpolation<T, FEK>(functor, face, time);
908 const auto [interp_coeffs, advected] = interpCoeffsAndAdvected<T, FEK>(functor, face, time);
910 return interp_coeffs.first * advected.first + interp_coeffs.second * advected.second;
918 const auto & limiter =
922 const auto & upwind_arg = face.elem_is_upwind ? face.makeElem() : face.makeNeighbor();
923 const auto & downwind_arg = face.elem_is_upwind ? face.makeNeighbor() : face.makeElem();
924 const auto & phi_upwind = functor.template genericEvaluate<FEK>(upwind_arg, time);
925 const auto & phi_downwind = functor.template genericEvaluate<FEK>(downwind_arg, time);
928 auto * time_arg = face.state_limiter;
932 time_arg = &temp_state;
941 const auto & grad_phi_upwind = functor.template genericEvaluate<GFEK>(upwind_arg, *time_arg);
942 const auto & grad_phi_face = functor.template genericEvaluate<GFEK>(face, *time_arg);
976 template <
typename T>
985 mooseAssert(face.
fi,
"this must be non-null");
993 auto phi_upwind = functor(upwind_arg, time);
994 auto phi_downwind = functor(downwind_arg, time);
998 T coeff_upwind, coeff_downwind;
1004 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
1006 const auto &component_upwind = phi_upwind(i), component_downwind = phi_downwind(i);
1007 std::tie(coeff_upwind, coeff_downwind) =
interpCoeffs(*limiter,
1016 ret(i) = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1026 time_arg = &temp_state;
1030 const auto & grad_phi_upwind = functor.gradient(upwind_arg, *time_arg);
1031 const auto & grad_phi_downwind = functor.gradient(downwind_arg, *time_arg);
1036 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
1038 const auto &component_upwind = phi_upwind(i), component_downwind = phi_downwind(i);
1040 grad_face = coeffs.first * grad_phi_upwind.row(i) +
1041 coeffs.second * grad_phi_downwind.row(i);
1085 template <
typename T>
1090 typedef typename ContainerGradientType::value_type
GradientType;
1093 mooseAssert(face.
fi,
"this must be non-null");
1098 const auto phi_upwind = functor(upwind_arg, time);
1099 const auto phi_downwind = functor(downwind_arg, time);
1103 typename T::value_type coeff_upwind, coeff_downwind;
1110 const auto &component_upwind = phi_upwind[i], component_downwind = phi_downwind[i];
1111 std::tie(coeff_upwind, coeff_downwind) =
interpCoeffs(*limiter,
1120 ret[i] = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1125 const auto grad_phi_upwind = functor.
gradient(upwind_arg, time);
1128 const auto &component_upwind = phi_upwind[i], component_downwind = phi_downwind[i];
1129 const auto & grad = grad_phi_upwind[i];
1130 std::tie(coeff_upwind, coeff_downwind) =
interpCoeffs(*limiter,
1139 ret[i] = coeff_upwind * component_upwind + coeff_downwind * component_downwind;
1146 template <
typename T>
1155 template <
typename T, std::
size_t N>
1167 template <
typename SubdomainRestrictable>
Base class template for functor objects.
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...
Point skewnessCorrectionVector() const
Returns the skewness-correction vector (vector between the approximate and real face centroids)...
Base class for defining slope limiters for finite volume or potentially reconstructed Discontinuous-G...
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
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:
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
1/(gc/elem+(1-gc)/neighbor)
const Point & faceCentroid() const
Returns the coordinates of the face centroid.
bool correct_skewness
Whether to perform skew correction.
Scalar rF(const Scalar &phiC, const Scalar &phiD, const Vector &gradC, const RealVectorValue &dCD)
From Moukalled 12.30.
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
const Point & neighborCentroid() const
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.
DualNumber< Real, DNDerivativeType, true > ADReal
MooseEnum interpolationMethods()
Returns an enum with all the currently supported interpolation methods and the current default for FV...
const Moose::StateArg * state_limiter
A member that can be used to define the instance in which the limiters are executed.
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...
typename FunctorReturnType< T, FunctorEvaluationKind::Gradient >::type GradientType
This rigmarole makes it so that a user can create functors that return containers (std::vector...
auto max(const L &left, const R &right)
SubdomainID elemSubdomainID() const
FunctorEvaluationKind
An enumeration of possible functor evaluation kinds.
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.
This data structure is used to store geometric and variable related metadata about each cell face in ...
virtual bool constant() const =0
const Elem * neighborPtr() const
const Point & elemCentroid() const
Returns the element centroids of the elements on the elem and neighbor sides of the face...
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
InputParameters advectedInterpolationParameter()
A structure defining a "face" evaluation calling argument for Moose functors.
Every object that can be built by the factory should be derived from this class.
const FaceInfo * fi
a face information object which defines our location in space
Real gC() const
Return the geometric weighting factor.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Moose::FV::LimiterType limiter_type
a limiter which defines how the functor evaluated on either side of the face should be interpolated t...
A structure that is used to evaluate Moose functors logically at an element/cell center.
ElemArg makeNeighbor() const
Make a ElemArg from our data using the face information neighbor.
const Point & normal() const
Returns the unit normal vector for the face oriented outward from the face's elem element...
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.
std::string stringify(const T &t)
conversion to string
This structure takes an evaluation kind as a template argument and defines a constant expression indi...
bool onBoundary(const SubdomainRestrictable &obj, const FaceInfo &fi)
Return whether the supplied face is on a boundary of the object's execution.
(gc*elem+(1-gc)*neighbor)+gradient*(rf-rf')
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...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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.
GradientType gradient(const ElemArg &elem, const StateArg &state) const
Same as their evaluateGradient overloads with the same arguments but allows for caching implementatio...
IntRange< T > make_range(T beg, T end)
SubdomainID neighborSubdomainID() const
State argument for evaluating functors.
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...
bool elem_is_upwind
a boolean which states whether the face information element is upwind of the face ...
This class provides variable solution values for other classes/objects to bind to when looping over f...
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.
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...
InterpMethod
This codifies a set of available ways to interpolate with elem+neighbor solution information to calcu...
auto min(const L &left, const R &right)
A base class interface for both producers and consumers of functor face arguments, e.g.
ElemArg makeElem() const
Make a ElemArg from our data using the face information element.
static std::unique_ptr< Limiter > build(LimiterType limiter)
auto index_range(const T &sizable)
bool setInterpolationMethod(const MooseObject &obj, Moose::FV::InterpMethod &interp_method, const std::string ¶m_name)
Sets one interpolation method.
const Point & dCN() const