8#include <ryujin/base/compile_time_options.h>
17 namespace ScalarConservation
20 typename Number = double,
21 typename MemorySpace = dealii::MemorySpace::Host>
29 template <
typename ScalarNumber =
double>
30 class Limiter :
public dealii::ParameterAcceptor
56 const std::string &subsection =
"/Limiter")
57 : ParameterAcceptor(subsection)
58 , parameters_(
"scalar_conservation_limiter_parameters",
60 , hyperbolic_system_(&hyperbolic_system)
63 auto ¶meters = *parameters_.view();
65 parameters.iterations = 2;
66 add_parameter(
"iterations",
67 parameters.iterations,
68 "Number of limiter iterations");
70 parameters.relaxation_factor = 1.;
71 add_parameter(
"relaxation factor",
72 parameters.relaxation_factor,
73 "Factor for scaling the relaxation window with r_i = "
74 "factor * (m_i/|Omega|)^(1.5/d).");
77 ParameterAcceptor::parse_parameters_call_back.connect(
78 [
this] { parameters_.view(); });
90 typename MemorySpace = dealii::MemorySpace::Host>
94 hyperbolic_system_->template view<dim, Number, MemorySpace>(),
113 dealii::ObserverPointer<const HyperbolicSystem> hyperbolic_system_;
115 template <
int,
typename,
typename>
130 template <
int dim,
typename Number,
typename MemorySpace>
135 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
136 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
137 "Unexpected memory space");
168 using Bounds = std::array<Number, n_bounds>;
176 , parameters_(limiter.parameters_.template view<MemorySpace>())
183 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int iterations()
const
185 return parameters_->iterations;
200 DEAL_II_HOST_DEVICE
Bounds
202 const unsigned int i,
211 const Bounds &bounds_left,
const Bounds &bounds_right)
const;
219 const Number &hd)
const;
246 const unsigned int i,
254 DEAL_II_HOST_DEVICE
void
256 const unsigned int *js,
259 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
265 DEAL_II_HOST_DEVICE
Bounds bounds(
const Number hd_i)
const;
279 DEAL_II_HOST_DEVICE std::tuple<Number, bool>
283 const Number t_min = Number(0.),
284 const Number t_max = Number(1.))
const;
301 Number u_relaxation_numerator_;
302 Number u_relaxation_denominator_;
314 template <
int dim,
typename Number,
typename MemorySpace>
315 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
321 const auto u_i = view_.state(U_i);
326 template <
int dim,
typename Number,
typename MemorySpace>
327 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
331 const auto &[u_min_l, u_max_l] = bounds_left;
332 const auto &[u_min_r, u_max_r] = bounds_right;
334 return {std::min(u_min_l, u_min_r), std::max(u_max_l, u_max_r)};
338 template <
int dim,
typename Number,
typename MemorySpace>
339 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
343 auto relaxed_bounds = bounds;
344 auto &[u_min, u_max] = relaxed_bounds;
348 Number r = std::sqrt(hd);
349 if constexpr (dim == 2)
350 r = ryujin::fixed_power<3>(std::sqrt(r));
351 else if constexpr (dim == 1)
352 r = ryujin::fixed_power<3>(r);
353 r *= relaxation_factor();
355 u_min = std::min((Number(1.) - r) * u_min, (Number(1.) + r) * u_min);
356 u_max = std::max((Number(1.) + r) * u_max, (Number(1.) - r) * u_max);
358 return relaxed_bounds;
362 template <
int dim,
typename Number,
typename MemorySpace>
363 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
375 auto &[u_min, u_max] = bounds_;
377 u_min = Number(std::numeric_limits<ScalarNumber>::max());
378 u_max = Number(std::numeric_limits<ScalarNumber>::lowest());
382 u_relaxation_numerator_ = Number(0.);
383 u_relaxation_denominator_ = Number(0.);
387 template <
int dim,
typename Number,
typename MemorySpace>
388 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
391 const unsigned int * ,
394 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
398 auto &[u_min, u_max] = bounds_;
400 const auto u_i = view_.state(U_i_);
401 const auto u_j = view_.state(U_j);
403 const auto U_ij_bar =
408 const auto u_ij_bar = view_.state(U_ij_bar);
412 u_min = std::min(u_min, u_ij_bar);
413 u_max = std::max(u_max, u_ij_bar);
418 const auto beta_ij = Number(1.);
419 u_relaxation_numerator_ += beta_ij * (u_i + u_j);
420 u_relaxation_denominator_ += std::abs(beta_ij);
424 template <
int dim,
typename Number,
typename MemorySpace>
425 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
429 const auto &[u_min, u_max] = bounds_;
431 auto relaxed_bounds = fully_relax_bounds(bounds_, hd_i);
432 auto &[u_min_relaxed, u_max_relaxed] = relaxed_bounds;
436 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
438 const Number u_relaxation =
440 std::abs(u_relaxation_numerator_) /
441 (std::abs(u_relaxation_denominator_) + Number(eps));
443 u_min_relaxed = std::max(u_min_relaxed, u_min - u_relaxation);
444 u_max_relaxed = std::min(u_max_relaxed, u_max + u_relaxation);
446 return relaxed_bounds;
450 template <
int dim,
typename Number,
typename MemorySpace>
451 DEAL_II_HOST_DEVICE_ALWAYS_INLINE std::tuple<Number, bool>
457 const Number t_max )
const
462 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
465 const auto &u_U = view_.state(U);
466 const auto &u_P = view_.state(P);
468 const auto &u_min = std::get<0>(bounds);
469 const auto &u_max = std::get<1>(bounds);
477 const auto test_max = std::max(
478 Number(0.), std::min(u_U - relax * u_max, relax * u_U - u_max));
479 const auto test_min = std::max(
480 Number(0.), std::min(u_min - relax * u_U, relax * u_min - u_U));
481 if (!(test_max == Number(0.) && test_min == Number(0.))) {
483 std::cout << std::fixed << std::setprecision(16);
484 std::cout <<
"Bounds violation: low-order state (critical)!"
485 <<
"\n\t\tu min: " << u_min
487 <<
"\n\t\tu: " << u_U
489 <<
"\n\t\tu max: " << u_max <<
"\n"
495 const auto regularization =
496 Number(100. * std::numeric_limits<ScalarNumber>::min());
498 const Number denominator =
500 std::max(regularization, std::abs(u_P) + eps * u_max);
502 t_r = ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
511 (u_max - u_U) * denominator,
514 t_r = ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
523 (u_U - u_min) * denominator,
533 t_r = std::min(t_r, t_max);
534 t_r = std::max(t_r, t_min);
536#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
542 const auto u_new = view_.state(U + t_r * P);
543 const auto test_new_max = std::max(
544 Number(0.), std::min(u_new - relax * u_max, relax * u_new - u_max));
545 const auto test_new_min = std::max(
546 Number(0.), std::min(u_min - relax * u_new, relax * u_min - u_new));
547 if (!(test_new_max == Number(0.) && test_new_min == Number(0.))) {
549 std::cout << std::fixed << std::setprecision(16);
550 std::cout <<
"Bounds violation: high-order state!"
551 <<
"\n\t\tu min: " << u_min
553 <<
"\n\t\tu: " << u_new
555 <<
"\n\t\tu max: " << u_max <<
"\n"
562 return {t_r, success};
dealii::Tensor< 1, problem_dimension, Number > state_type
flux_type flux_contribution_type
typename get_value_type< Number >::type ScalarNumber
VectorView< n_precomputed_values > PrecomputedVectorView
typename View::PrecomputedVectorView PrecomputedVectorView
DEAL_II_HOST_DEVICE void accumulate(const PrecomputedVectorView &pv, const unsigned int *js, const state_type &U_j, const flux_contribution_type &flux_j, const dealii::Tensor< 1, dim, Number > &scaled_c_ij, const state_type &affine_shift)
DEAL_II_HOST_DEVICE Bounds bounds(const Number hd_i) const
typename View::state_type state_type
DEAL_II_HOST_DEVICE Bounds fully_relax_bounds(const Bounds &bounds, const Number &hd) const
typename View::ScalarNumber ScalarNumber
DEAL_II_HOST_DEVICE Bounds projection_bounds_from_state(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i) const
static constexpr unsigned int n_bounds
std::array< Number, n_bounds > Bounds
DEAL_II_HOST_DEVICE Bounds combine_bounds(const Bounds &bounds_left, const Bounds &bounds_right) const
typename View::flux_contribution_type flux_contribution_type
DEAL_II_HOST_DEVICE_ALWAYS_INLINE unsigned int iterations() const
DEAL_II_HOST_DEVICE void reset(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i, const flux_contribution_type &flux_i)
HyperbolicSystemView< dim, Number, MemorySpace > View
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber relaxation_factor() const
LimiterView(const View &view, const Limiter< ScalarNumber > &limiter)
DEAL_II_HOST_DEVICE std::tuple< Number, bool > limit(const Bounds &bounds, const state_type &U, const state_type &P, const Number t_min=Number(0.), const Number t_max=Number(1.)) const
Limiter(const HyperbolicSystem &hyperbolic_system, const std::string &subsection="/Limiter")
@ implicit_transfers_host_resident
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number positive_part(const Number number)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number negative_part(const Number number)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor< 1, problem_dim, T > contract(const FT &flux_ij, const TT &c_ij)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE FT add(const FT &flux_left_ij, const FT &flux_right_ij)