8#include <ryujin/base/compile_time_options.h>
20 namespace EulerBarotropic
23 typename Number = double,
24 typename MemorySpace = dealii::MemorySpace::Host>
32 template <
typename ScalarNumber =
double>
33 class Limiter :
public dealii::ParameterAcceptor
59 const std::string &subsection =
"/Limiter")
60 : ParameterAcceptor(subsection)
61 , parameters_(
"euler_barotropic_limiter_parameters",
63 , hyperbolic_system_(&hyperbolic_system)
66 auto ¶meters = *parameters_.view();
68 parameters.iterations = 2;
69 add_parameter(
"iterations",
70 parameters.iterations,
71 "Number of limiter iterations");
73 parameters.relaxation_factor = 1.;
74 add_parameter(
"relaxation factor",
75 parameters.relaxation_factor,
76 "Factor for scaling the relaxation window with r_i = "
77 "factor * (m_i/|Omega|)^(1.5/d).");
80 ParameterAcceptor::parse_parameters_call_back.connect(
81 [
this] { parameters_.view(); });
93 typename MemorySpace = dealii::MemorySpace::Host>
97 hyperbolic_system_->template view<dim, Number, MemorySpace>(),
116 dealii::ObserverPointer<const HyperbolicSystem> hyperbolic_system_;
118 template <
int,
typename,
typename>
133 template <
int dim,
typename Number,
typename MemorySpace>
138 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
139 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
140 "Unexpected memory space");
170 using Bounds = std::array<Number, n_bounds>;
178 , parameters_(limiter.parameters_.template view<MemorySpace>())
185 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
unsigned int iterations()
const
187 return parameters_->iterations;
202 DEAL_II_HOST_DEVICE
Bounds
204 const unsigned int i,
213 const Bounds &bounds_left,
const Bounds &bounds_right)
const;
224 const Number &hd)
const;
251 const unsigned int i,
259 DEAL_II_HOST_DEVICE
void
261 const unsigned int *js,
264 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
270 DEAL_II_HOST_DEVICE
Bounds bounds(
const Number hd_i)
const;
293 DEAL_II_HOST_DEVICE std::tuple<Number, bool>
297 const Number t_min = Number(0.),
298 const Number t_max = Number(1.))
const;
315 Number rho_relaxation_numerator_;
316 Number rho_relaxation_denominator_;
329 template <
int dim,
typename Number,
typename MemorySpace>
330 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
336 const auto rho_i = view_.density(U_i);
337 return { rho_i, rho_i};
341 template <
int dim,
typename Number,
typename MemorySpace>
342 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
346 const auto &[rho_min_l, rho_max_l] = bounds_left;
347 const auto &[rho_min_r, rho_max_r] = bounds_right;
349 return {std::min(rho_min_l, rho_min_r), std::max(rho_max_l, rho_max_r)};
353 template <
int dim,
typename Number,
typename MemorySpace>
354 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
358 auto relaxed_bounds = bounds;
359 auto &[rho_min_relaxed, rho_max_relaxed] = relaxed_bounds;
363 Number r = std::sqrt(hd);
364 if constexpr (dim == 2)
365 r = dealii::Utilities::fixed_power<3>(std::sqrt(r));
366 else if constexpr (dim == 1)
367 r = dealii::Utilities::fixed_power<3>(r);
368 r *= relaxation_factor();
370 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
371 rho_min_relaxed *= std::max(Number(1.) - r, Number(eps));
372 rho_max_relaxed *= (Number(1.) + r);
374 return relaxed_bounds;
378 template <
int dim,
typename Number,
typename MemorySpace>
379 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
391 auto &[rho_min, rho_max] = bounds_;
393 rho_min = Number(std::numeric_limits<ScalarNumber>::max());
394 rho_max = Number(0.);
398 rho_relaxation_numerator_ = Number(0.);
399 rho_relaxation_denominator_ = Number(0.);
403 template <
int dim,
typename Number,
typename MemorySpace>
404 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
void
407 const unsigned int * ,
410 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
417 Assert(std::max(affine_shift.norm(), Number(0.)) == Number(0.),
418 dealii::ExcNotImplemented());
421 auto &[rho_min, rho_max] = bounds_;
423 const auto rho_i = view_.density(U_i_);
424 const auto rho_j = view_.density(U_j);
427 const auto U_ij_bar =
432 const auto rho_ij_bar = view_.density(U_ij_bar);
436 rho_min = std::min(rho_min, rho_ij_bar);
437 rho_max = std::max(rho_max, rho_ij_bar);
442 const auto beta_ij = Number(1.);
443 rho_relaxation_numerator_ += beta_ij * (rho_i + rho_j);
444 rho_relaxation_denominator_ += std::abs(beta_ij);
448 template <
int dim,
typename Number,
typename MemorySpace>
449 DEAL_II_HOST_DEVICE_ALWAYS_INLINE
auto
453 const auto &[rho_min, rho_max] = bounds_;
455 auto relaxed_bounds = fully_relax_bounds(bounds_, hd_i);
456 auto &[rho_min_relaxed, rho_max_relaxed] = relaxed_bounds;
460 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
462 const auto rho_relaxation =
464 std::abs(rho_relaxation_numerator_) /
465 (std::abs(rho_relaxation_denominator_) + Number(eps));
467 rho_min_relaxed = std::max(rho_min_relaxed, rho_min - rho_relaxation);
468 rho_max_relaxed = std::min(rho_max_relaxed, rho_max + rho_relaxation);
470 return relaxed_bounds;
474 template <
int dim,
typename Number,
typename MemorySpace>
475 DEAL_II_HOST_DEVICE_ALWAYS_INLINE std::tuple<Number, bool>
481 const Number t_max )
const
486 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
487 const auto large = view_.vacuum_state_relaxation_large();
495 const auto &rho_U = view_.density(U);
496 const auto &rho_P = view_.density(P);
498 const auto &rho_min = std::get<0>(bounds);
499 const auto &rho_max = std::get<1>(bounds);
505 const auto test_min = view_.filter_vacuum_density(
506 std::max(Number(0.), rho_U - relax * rho_max));
507 const auto test_max = view_.filter_vacuum_density(
508 std::max(Number(0.), rho_min - relax * rho_U));
509 if (!(test_min == Number(0.) && test_max == Number(0.))) {
511 std::cout << std::fixed << std::setprecision(16);
512 std::cout <<
"Bounds violation: low-order density (critical)!"
513 <<
"\n\t\trho min: " << rho_min
514 <<
"\n\t\trho min (delta): "
516 <<
"\n\t\trho: " << rho_U
517 <<
"\n\t\trho max (delta): "
519 <<
"\n\t\trho max: " << rho_max <<
"\n"
525 const Number denominator =
528 t_r = ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
537 (rho_max - rho_U) * denominator,
540 t_r = ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
549 (rho_U - rho_min) * denominator,
559 t_r = std::min(t_r, t_max);
560 t_r = std::max(t_r, t_min);
562#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
566 const auto rho_new = view_.density(U + t_r * P);
567 const auto test_new_min = view_.filter_vacuum_density(
568 std::max(Number(0.), rho_new - relax * rho_max));
569 const auto test_new_max = view_.filter_vacuum_density(
570 std::max(Number(0.), rho_min - relax * rho_new));
571 if (!(test_new_min == Number(0.) && test_new_max == Number(0.))) {
573 std::cout << std::fixed << std::setprecision(16);
574 std::cout <<
"Bounds violation: high-order density!"
575 <<
"\n\t\trho min: " << rho_min
576 <<
"\n\t\trho min (delta): "
578 <<
"\n\t\trho: " << rho_new
579 <<
"\n\t\trho max (delta): "
581 <<
"\n\t\trho max: " << rho_max <<
"\n"
589 return {t_r, success};
VectorView< n_precomputed_values > PrecomputedVectorView
dealii::Tensor< 1, problem_dimension, Number > state_type
typename get_value_type< Number >::type ScalarNumber
flux_type flux_contribution_type
typename View::ScalarNumber ScalarNumber
static constexpr unsigned int n_bounds
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
DEAL_II_HOST_DEVICE Bounds fully_relax_bounds(const Bounds &bounds, const Number &hd) const
typename View::PrecomputedVectorView PrecomputedVectorView
typename View::flux_contribution_type flux_contribution_type
typename View::state_type state_type
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber relaxation_factor() const
HyperbolicSystemView< dim, Number, MemorySpace > View
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_ALWAYS_INLINE unsigned int iterations() const
DEAL_II_HOST_DEVICE Bounds projection_bounds_from_state(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i) const
DEAL_II_HOST_DEVICE Bounds bounds(const Number hd_i) const
LimiterView(const View &view, const Limiter< ScalarNumber > &limiter)
std::array< Number, n_bounds > Bounds
DEAL_II_HOST_DEVICE Bounds combine_bounds(const Bounds &bounds_left, const Bounds &bounds_right) 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)
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)