ryujin 2.1.1 revision ee5cbcbf2346c1299c942d0e1f13b46449973c18
Loading...
Searching...
No Matches
limiter.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2020 - 2026 by the ryujin authors
4//
5
6#pragma once
7
8#include <compile_time_options.h>
9
10#include "hyperbolic_system.h"
11
12#include <compile_time_options.h>
13#include <deal.II/base/config.h>
14#include <gpu.h>
16#include <newton.h>
17#include <observer_pointer.h>
18#include <simd.h>
19
20// #define DEBUG_OUTPUT_LIMITER
21
22namespace ryujin
23{
24 namespace Euler
25 {
26 template <int dim,
27 typename Number = double,
28 typename MemorySpace = dealii::MemorySpace::Host>
29 class LimiterView;
30
61 template <typename ScalarNumber = double>
62 class Limiter : public dealii::ParameterAcceptor
63 {
64 public:
69
73 struct Parameters {
74 unsigned int iterations;
78 };
79
84 template <int dim,
85 typename Number = double,
86 typename MemorySpace = dealii::MemorySpace::Host>
88
90
94
98 Limiter(const HyperbolicSystem &hyperbolic_system,
99 const std::string &subsection = "/Limiter")
100 : ParameterAcceptor(subsection)
101 , parameters_("euler_limiter_parameters",
103 , hyperbolic_system_(&hyperbolic_system)
104 {
105 /*
106 * Note: We bind the parameters directly to the storage held by the
107 * Mirrored object. The corresponding memory is allocated once in
108 * the constructor and never reallocated, and the
109 * implicit_transfers_host_resident policy guarantees that the host
110 * storage is never deallocated: the addresses thus remain valid
111 * for the lifetime of this object.
112 */
113 auto &parameters = *parameters_.view();
114
115 parameters.iterations = 2;
116 add_parameter("iterations",
117 parameters.iterations,
118 "Number of limiter iterations");
119
120 if constexpr (std::is_same<ScalarNumber, double>::value)
121 parameters.newton_tolerance = 1.e-10;
122 else
123 parameters.newton_tolerance = 1.e-4;
124 add_parameter("newton tolerance",
125 parameters.newton_tolerance,
126 "Tolerance for the quadratic newton stopping criterion");
127
128 parameters.newton_max_iterations = 2;
129 add_parameter("newton max iterations",
130 parameters.newton_max_iterations,
131 "Maximal number of quadratic newton iterations performed "
132 "during limiting");
133
134 parameters.relaxation_factor = 1.;
135 add_parameter("relaxation factor",
136 parameters.relaxation_factor,
137 "Factor for scaling the relaxation window with r_i = "
138 "factor * (m_i/|Omega|)^(1.5/d).");
139
140 /*
141 * A parameter file read writes directly through the addresses
142 * bound above and bypasses the view() mechanism. Request a
143 * writable view on the host memory space to invalidate the (now
144 * stale) mirror of the parameters in the default memory space:
145 */
146 ParameterAcceptor::parse_parameters_call_back.connect(
147 [this] { parameters_.view(); });
148 }
149
157 template <int dim,
158 typename Number,
159 typename MemorySpace = dealii::MemorySpace::Host>
160 auto view() const
161 {
163 hyperbolic_system_->template view<dim, Number, MemorySpace>(),
164 *this};
165 }
166
167 private:
169
173
174 Mirrored<Parameters> parameters_;
175
177
181
182 dealii::ObserverPointer<const HyperbolicSystem> hyperbolic_system_;
183
185
186 template <int, typename, typename>
187 friend class LimiterView;
188 };
189
190
199 template <int dim, typename Number, typename MemorySpace>
201 {
202 public:
203 static_assert(
204 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
205 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
206 "Unexpected memory space");
207
212
214
216
218
219 using state_type = typename View::state_type;
220
222
224
226
228
235 static constexpr unsigned int n_bounds = 3;
236
240 using Bounds = std::array<Number, n_bounds>;
241
246 LimiterView(const View &view, const Limiter<ScalarNumber> &limiter)
247 : view_(view)
248 , parameters_(limiter.parameters_.template view<MemorySpace>())
249 {
250 }
251
255 DEAL_II_HOST_DEVICE_ALWAYS_INLINE unsigned int iterations() const
256 {
257 return parameters_->iterations;
258 }
259
263 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber newton_tolerance() const
264 {
265 return ScalarNumber(parameters_->newton_tolerance);
266 }
267
271 DEAL_II_HOST_DEVICE_ALWAYS_INLINE unsigned int
273 {
274 return parameters_->newton_max_iterations;
275 }
276
280 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber relaxation_factor() const
281 {
282 return ScalarNumber(parameters_->relaxation_factor);
283 }
284
289 DEAL_II_HOST_DEVICE Bounds
291 const unsigned int i,
292 const state_type &U_i) const;
293
299 DEAL_II_HOST_DEVICE Bounds combine_bounds(
300 const Bounds &bounds_left, const Bounds &bounds_right) const;
301
310 DEAL_II_HOST_DEVICE Bounds fully_relax_bounds(const Bounds &bounds,
311 const Number &hd) const;
312
314
333
337 DEAL_II_HOST_DEVICE void reset(const PrecomputedVectorView &pv,
338 const unsigned int i,
339 const state_type &U_i,
340 const flux_contribution_type &flux_i);
341
346 DEAL_II_HOST_DEVICE void
348 const unsigned int *js,
349 const state_type &U_j,
350 const flux_contribution_type &flux_j,
351 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
352 const state_type &affine_shift);
353
357 DEAL_II_HOST_DEVICE Bounds bounds(const Number hd_i) const;
358
360
364
380 DEAL_II_HOST_DEVICE std::tuple<Number, bool>
381 limit(const Bounds &bounds,
382 const state_type &U,
383 const state_type &P,
384 const Number t_min = Number(0.),
385 const Number t_max = Number(1.)) const;
386
387 private:
389
393
394 const View view_;
395 const Limiter<ScalarNumber>::Parameters *const parameters_;
396
397 state_type U_i_;
398
399 Bounds bounds_;
400
401 Number rho_relaxation_numerator_;
402 Number rho_relaxation_denominator_;
403 Number s_interp_max_;
404
406 };
407
408
409 /*
410 * -------------------------------------------------------------------------
411 * Inline definitions
412 * -------------------------------------------------------------------------
413 */
414
415
416 template <int dim, typename Number, typename MemorySpace>
417 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
419 const PrecomputedVectorView &pv,
420 const unsigned int i,
421 const state_type &U_i) const -> Bounds
422 {
423 const auto rho_i = view_.density(U_i);
424 const auto &[s_i, eta_i] =
425 pv.template read_tensor<Number, precomputed_type>(i);
426
427 return {/*rho_min*/ rho_i, /*rho_max*/ rho_i, /*s_min*/ s_i};
428 }
429
430
431 template <int dim, typename Number, typename MemorySpace>
432 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
434 const Bounds &bounds_left, const Bounds &bounds_right) const -> Bounds
435 {
436 const auto &[rho_min_l, rho_max_l, s_min_l] = bounds_left;
437 const auto &[rho_min_r, rho_max_r, s_min_r] = bounds_right;
438
439 return {std::min(rho_min_l, rho_min_r),
440 std::max(rho_max_l, rho_max_r),
441 std::min(s_min_l, s_min_r)};
442 }
443
444
445 template <int dim, typename Number, typename MemorySpace>
446 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
448 const Bounds &bounds, const Number &hd) const -> Bounds
449 {
450 auto relaxed_bounds = bounds;
451 auto &[rho_min, rho_max, s_min] = relaxed_bounds;
452
453 /* Use r = factor * (m_i / |Omega|) ^ (1.5 / d): */
454
455 Number r = std::sqrt(hd); // in 3D: ^ 3/6
456 if constexpr (dim == 2) //
457 r = ryujin::fixed_power<3>(std::sqrt(r)); // in 2D: ^ 3/4
458 else if constexpr (dim == 1) //
459 r = ryujin::fixed_power<3>(r); // in 1D: ^ 3/2
460 r *= relaxation_factor();
461
462 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
463 rho_min *= std::max(Number(1.) - r, Number(eps));
464 rho_max *= (Number(1.) + r);
465 s_min *= std::max(Number(1.) - r, Number(eps));
466
467 return relaxed_bounds;
468 }
469
470
471 template <int dim, typename Number, typename MemorySpace>
472 DEAL_II_HOST_DEVICE_ALWAYS_INLINE void
474 const PrecomputedVectorView & /*pv*/,
475 const unsigned int /*i*/,
476 const state_type &U_i,
477 const flux_contribution_type & /*flux_i*/)
478 {
479 U_i_ = U_i;
480
481 /* Bounds: */
482
483 auto &[rho_min, rho_max, s_min] = bounds_;
484
485 rho_min = Number(std::numeric_limits<ScalarNumber>::max());
486 rho_max = Number(0.);
487 s_min = Number(std::numeric_limits<ScalarNumber>::max());
488
489 /* Relaxation: */
490
491 rho_relaxation_numerator_ = Number(0.);
492 rho_relaxation_denominator_ = Number(0.);
493 s_interp_max_ = Number(0.);
494 }
495
496
497 template <int dim, typename Number, typename MemorySpace>
498 DEAL_II_HOST_DEVICE_ALWAYS_INLINE void
500 const PrecomputedVectorView &pv,
501 const unsigned int *js,
502 const state_type &U_j,
503 const flux_contribution_type & /*flux_j*/,
504 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
505 const state_type &affine_shift)
506 {
507 // TODO: Currently we only apply the affine_shift to U_ij_bar (which
508 // then enters all bounds), but we do not modify s_interp and
509 // rho_relaxation. When actually adding a source term to the Euler
510 // equations verify that this does the right thing.
511 Assert(std::max(affine_shift.norm(), Number(0.)) == Number(0.),
512 dealii::ExcNotImplemented());
513
514 /* Bounds: */
515 auto &[rho_min, rho_max, s_min] = bounds_;
516
517 const auto rho_i = view_.density(U_i_);
518 const auto m_i = view_.momentum(U_i_);
519 const auto rho_j = view_.density(U_j);
520 const auto m_j = view_.momentum(U_j);
521 const auto rho_affine_shift = view_.density(affine_shift);
522
523 /* bar state shifted by an affine shift: */
524 const auto rho_ij_bar =
525 ScalarNumber(0.5) * (rho_i + rho_j + (m_i - m_j) * scaled_c_ij) +
526 rho_affine_shift;
527
528 rho_min = std::min(rho_min, rho_ij_bar);
529 rho_max = std::max(rho_max, rho_ij_bar);
530
531 const auto &[s_j, eta_j] =
532 pv.template read_tensor<Number, precomputed_type>(js);
533 s_min = std::min(s_min, s_j);
534
535 /* Relaxation: */
536
537 /* Use a uniform weight. */
538 const auto beta_ij = Number(1.);
539 rho_relaxation_numerator_ += beta_ij * (rho_i + rho_j);
540 rho_relaxation_denominator_ += std::abs(beta_ij);
541
542 const Number s_interp =
543 view_.specific_entropy((U_i_ + U_j) * ScalarNumber(.5));
544 s_interp_max_ = std::max(s_interp_max_, s_interp);
545 }
546
547
548 template <int dim, typename Number, typename MemorySpace>
549 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
551 -> Bounds
552 {
553 const auto &[rho_min, rho_max, s_min] = bounds_;
554
555 auto relaxed_bounds = fully_relax_bounds(bounds_, hd_i);
556 auto &[rho_min_relaxed, rho_max_relaxed, s_min_relaxed] = relaxed_bounds;
557
558 /* Apply a stricter window: */
559
560 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
561
562 const auto rho_relaxation =
563 ScalarNumber(2. * relaxation_factor()) *
564 std::abs(rho_relaxation_numerator_) /
565 (std::abs(rho_relaxation_denominator_) + Number(eps));
566
567 const auto entropy_relaxation =
568 relaxation_factor() * (s_interp_max_ - s_min);
569
570 rho_min_relaxed = std::max(rho_min_relaxed, rho_min - rho_relaxation);
571 rho_max_relaxed = std::min(rho_max_relaxed, rho_max + rho_relaxation);
572 s_min_relaxed = std::max(s_min_relaxed, s_min - entropy_relaxation);
573
574 return relaxed_bounds;
575 }
576
577
578 template <int dim, typename Number, typename MemorySpace>
579 DEAL_II_HOST_DEVICE std::tuple<Number, bool>
581 const Bounds &bounds,
582 const state_type &U,
583 const state_type &P,
584 const Number t_min /* = Number(0.) */,
585 const Number t_max /* = Number(1.) */) const
586 {
587 bool success = true;
588 Number t_r = t_max;
589
590 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
591 const auto small = view_.vacuum_state_relaxation_small();
592 const auto large = view_.vacuum_state_relaxation_large();
593 const ScalarNumber relax_small = ScalarNumber(1. + small * eps);
594 const ScalarNumber relax = ScalarNumber(1. + large * eps);
595
596 /*
597 * First limit the density rho.
598 *
599 * See [Guermond, Nazarov, Popov, Thomas] (4.8):
600 */
601
602 {
603 const auto &rho_U = view_.density(U);
604 const auto &rho_P = view_.density(P);
605
606 const auto &rho_min = std::get<0>(bounds);
607 const auto &rho_max = std::get<1>(bounds);
608
609 /*
610 * Verify that rho_U is within bounds. This property might be
611 * violated for relative CFL numbers larger than 1.
612 */
613 const auto test_min = view_.filter_vacuum_density(
614 std::max(Number(0.), rho_U - relax * rho_max));
615 const auto test_max = view_.filter_vacuum_density(
616 std::max(Number(0.), rho_min - relax * rho_U));
617 if (!(test_min == Number(0.) && test_max == Number(0.))) {
618#ifdef DEBUG_OUTPUT
619 std::cout << std::fixed << std::setprecision(16);
620 std::cout << "Bounds violation: low-order density (critical)!"
621 << "\n\t\trho min: " << rho_min
622 << "\n\t\trho min (delta): "
623 << negative_part(rho_U - rho_min)
624 << "\n\t\trho: " << rho_U
625 << "\n\t\trho max (delta): "
626 << positive_part(rho_U - rho_max)
627 << "\n\t\trho max: " << rho_max << "\n"
628 << std::endl;
629#endif
630 success = false;
631 }
632
633 const Number denominator =
634 ScalarNumber(1.) / (std::abs(rho_P) + eps * rho_max);
635
636 constexpr auto lt = dealii::SIMDComparison::less_than;
637
638 t_r = ryujin::compare_and_apply_mask<lt>( //
639 rho_max,
640 rho_U + t_r * rho_P,
641 /*
642 * rho_P is positive.
643 *
644 * Note: Do not take an absolute value here. If we are out of
645 * bounds we have to ensure that t_r is set to t_min.
646 */
647 (rho_max - rho_U) * denominator,
648 t_r);
649
650 t_r = ryujin::compare_and_apply_mask<lt>( //
651 rho_U + t_r * rho_P,
652 rho_min,
653 /*
654 * rho_P is negative.
655 *
656 * Note: Do not take an absolute value here. If we are out of
657 * bounds we have to ensure that t_r is set to t_min.
658 */
659 (rho_U - rho_min) * denominator,
660 t_r);
661
662 /*
663 * Ensure that t_min <= t <= t_max. This might not be the case if
664 * rho_U is outside the interval [rho_min, rho_max]. Furthermore,
665 * the quotient we take above is prone to numerical cancellation in
666 * particular in the second pass of the limiter when rho_P might be
667 * small.
668 */
669 t_r = std::min(t_r, t_max);
670 t_r = std::max(t_r, t_min);
671
672#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
673 /*
674 * Verify that the new state is within bounds:
675 */
676 const auto rho_new = view_.density(U + t_r * P);
677 const auto test_new_min = view_.filter_vacuum_density(
678 std::max(Number(0.), rho_new - relax * rho_max));
679 const auto test_new_max = view_.filter_vacuum_density(
680 std::max(Number(0.), rho_min - relax * rho_new));
681 if (!(test_new_min == Number(0.) && test_new_max == Number(0.))) {
682#ifdef DEBUG_OUTPUT
683 std::cout << std::fixed << std::setprecision(16);
684 std::cout << "Bounds violation: high-order density!"
685 << "\n\t\trho min: " << rho_min
686 << "\n\t\trho min (delta): "
687 << negative_part(rho_new - rho_min)
688 << "\n\t\trho: " << rho_new
689 << "\n\t\trho max (delta): "
690 << positive_part(rho_new - rho_max)
691 << "\n\t\trho max: " << rho_max << "\n"
692 << std::endl;
693#endif
694 success = false;
695 }
696#endif
697 }
698
699 /*
700 * Then limit the specific entropy:
701 *
702 * See [Guermond, Nazarov, Popov, Thomas], Section 4.6 + Section 5.1:
703 */
704
705 Number t_l = t_min; // good state
706
707 const ScalarNumber gamma = view_.gamma();
708 const ScalarNumber gp1 = gamma + ScalarNumber(1.);
709
710 {
711 /*
712 * Prepare a quadratic Newton method:
713 *
714 * Given initial limiter values t_l and t_r with psi(t_l) > 0 and
715 * psi(t_r) < 0 we try to find t^\ast with psi(t^\ast) \approx 0.
716 *
717 * Here, psi is a 3-convex function obtained by scaling the specific
718 * entropy s:
719 *
720 * psi = \rho ^ {\gamma + 1} s
721 *
722 * (s in turn was defined as s =\varepsilon \rho ^{-\gamma}, where
723 * \varepsilon = (\rho e) is the internal energy.)
724 */
725
726 const auto &s_min = std::get<2>(bounds);
727
728#ifdef DEBUG_OUTPUT_LIMITER
729 std::cout << std::endl;
730 std::cout << std::fixed << std::setprecision(16);
731 std::cout << "t_l: (start) " << t_l << std::endl;
732 std::cout << "t_r: (start) " << t_r << std::endl;
733#endif
734
735 for (unsigned int n = 0; n < newton_max_iterations(); ++n) {
736
737 const auto U_r = U + t_r * P;
738 const auto rho_r = view_.density(U_r);
739 const auto rho_r_gamma = ryujin::pow(rho_r, gamma);
740 const auto rho_e_r = view_.internal_energy(U_r);
741
742 auto psi_r =
743 relax_small * rho_r * rho_e_r - s_min * rho_r * rho_r_gamma;
744
745#ifndef DEBUG_EXPENSIVE_BOUNDS_CHECK
746 /*
747 * If psi_r > 0 the right state is fine, force returning t_r by
748 * setting t_l = t_r:
749 */
751 dealii::SIMDComparison::greater_than>(
752 psi_r, Number(0.), t_r, t_l);
753
754 /*
755 * If we have set t_l = t_r everywhere then all states state U_r
756 * with t_r obey the specific entropy inequality and we can
757 * break.
758 *
759 * This is a very important optimization: Only for 1 in (25 to
760 * 50) cases do we actually need to limit on the specific entropy
761 * because one of the right states failed. So we can skip
762 * constructing the left state U_l, which is expensive.
763 *
764 * This implies unfortunately that we might not accurately report
765 * whether the low_order update U itself obeyed bounds because
766 * U_r = U + t_r * P pushed us back into bounds. We thus skip
767 * this shortcut if `DEBUG_EXPENSIVE_BOUNDS_CHECK` is set.
768 */
769 if (t_l == t_r) {
770#ifdef DEBUG_OUTPUT_LIMITER
771 std::cout << "shortcut: t_l == t_r" << std::endl;
772 std::cout << "psi_l: " << psi_l << std::endl;
773 std::cout << "psi_r: " << psi_r << std::endl;
774 std::cout << "t_l: ( " << n << " ) " << t_l << std::endl;
775 std::cout << "t_r: ( " << n << " ) " << t_r << std::endl;
776#endif
777 break;
778 }
779#endif
780
781 const auto U_l = U + t_l * P;
782 const auto rho_l = view_.density(U_l);
783 const auto rho_l_gamma = ryujin::pow(rho_l, gamma);
784 const auto rho_e_l = view_.internal_energy(U_l);
785
786 auto psi_l =
787 relax_small * rho_l * rho_e_l - s_min * rho_l * rho_l_gamma;
788
789 /*
790 * Verify that the left state is within bounds. This property might
791 * be violated for relative CFL numbers larger than 1.
792 */
793 const auto lower_bound =
794 (ScalarNumber(1.) - relax) * s_min * rho_l * rho_l_gamma;
795 if (n == 0 &&
796 !(std::min(Number(0.), psi_l - lower_bound) == Number(0.))) {
797#ifdef DEBUG_OUTPUT
798 std::cout << std::fixed << std::setprecision(16);
799 std::cout
800 << "Bounds violation: low-order specific entropy (critical)!\n";
801 std::cout << "\t\tPsi left: 0 <= " << psi_l << "\n" << std::endl;
802#endif
803 success = false;
804 }
805
806#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
807 /*
808 * If psi_r > 0 the right state is fine, force returning t_r by
809 * setting t_l = t_r:
810 */
812 dealii::SIMDComparison::greater_than>(
813 psi_r, Number(0.), t_r, t_l);
814#endif
815
816 /*
817 * Break if the window between t_l and t_r is within the prescribed
818 * tolerance:
819 */
820 const Number tolerance(newton_tolerance());
821 if (std::max(Number(0.), t_r - t_l - tolerance) == Number(0.)) {
822#ifdef DEBUG_OUTPUT_LIMITER
823 std::cout << "break: t_l and t_r within tolerance" << std::endl;
824 std::cout << "psi_l: " << psi_l << std::endl;
825 std::cout << "psi_r: " << psi_r << std::endl;
826 std::cout << "t_l: ( " << n << " ) " << t_l << std::endl;
827 std::cout << "t_r: ( " << n << " ) " << t_r << std::endl;
828#endif
829 break;
830 }
831
832 /* We got unlucky and have to perform a Newton step: */
833
834 const auto drho = view_.density(P);
835 const auto drho_e_l = view_.internal_energy_derivative(U_l) * P;
836 const auto drho_e_r = view_.internal_energy_derivative(U_r) * P;
837 const auto dpsi_l =
838 rho_l * drho_e_l + (rho_e_l - gp1 * s_min * rho_l_gamma) * drho;
839 const auto dpsi_r =
840 rho_r * drho_e_r + (rho_e_r - gp1 * s_min * rho_r_gamma) * drho;
841
843 t_l, t_r, psi_l, psi_r, dpsi_l, dpsi_r, Number(-1.));
844
845#ifdef DEBUG_OUTPUT_LIMITER
846 std::cout << "psi_l: " << psi_l << std::endl;
847 std::cout << "psi_r: " << psi_r << std::endl;
848 std::cout << "dpsi_l: " << dpsi_l << std::endl;
849 std::cout << "dpsi_r: " << dpsi_r << std::endl;
850 std::cout << "t_l: ( " << n << " ) " << t_l << std::endl;
851 std::cout << "t_r: ( " << n << " ) " << t_r << std::endl;
852#endif
853 }
854
855#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
856 /*
857 * Verify that the new state is within bounds:
858 */
859 {
860 const auto U_new = U + t_l * P;
861 const auto rho_new = view_.density(U_new);
862 const auto rho_new_gamma = ryujin::pow(rho_new, gamma);
863 const auto rho_e_new = view_.internal_energy(U_new);
864
865 auto psi_new = relax_small * rho_new * rho_e_new -
866 s_min * rho_new * rho_new_gamma;
867
868 const auto lower_bound =
869 (ScalarNumber(1.) - relax) * s_min * rho_new * rho_new_gamma;
870
871 const bool e_valid = std::min(Number(0.), rho_e_new) == Number(0.);
872 const bool psi_valid =
873 std::min(Number(0.), psi_new - lower_bound) == Number(0.);
874
875 if (!e_valid || !psi_valid) {
876#ifdef DEBUG_OUTPUT
877 std::cout << std::fixed << std::setprecision(16);
878 std::cout << "Bounds violation: high-order specific entropy!\n";
879 std::cout << "\t\trho e: 0 <= " << rho_e_new << "\n";
880 std::cout << "\t\tPsi: 0 <= " << psi_new << "\n" << std::endl;
881#endif
882 success = false;
883 }
884 }
885#endif
886 }
887
888 return {t_l, success};
889 }
890 } // namespace Euler
891} // namespace ryujin
Vectors::MultiComponentVectorView< ScalarNumber, n_precomputed_values, dealii::VectorizedArray< ScalarNumber >::size(), MemorySpace, false > PrecomputedVectorView
dealii::Tensor< 1, problem_dimension, Number > state_type
std::array< Number, n_precomputed_values > precomputed_type
static constexpr unsigned int problem_dimension
typename get_value_type< Number >::type ScalarNumber
static constexpr auto problem_dimension
Definition limiter.h:217
DEAL_II_HOST_DEVICE void reset(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i, const flux_contribution_type &flux_i)
Definition limiter.h:473
typename View::PrecomputedVectorView PrecomputedVectorView
Definition limiter.h:225
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)
Definition limiter.h:499
typename View::state_type state_type
Definition limiter.h:219
typename View::precomputed_type precomputed_type
Definition limiter.h:223
DEAL_II_HOST_DEVICE Bounds bounds(const Number hd_i) const
Definition limiter.h:550
DEAL_II_HOST_DEVICE Bounds combine_bounds(const Bounds &bounds_left, const Bounds &bounds_right) const
Definition limiter.h:433
LimiterView(const View &view, const Limiter< ScalarNumber > &limiter)
Definition limiter.h:246
HyperbolicSystemView< dim, Number, MemorySpace > View
Definition limiter.h:213
DEAL_II_HOST_DEVICE Bounds projection_bounds_from_state(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i) const
Definition limiter.h:418
std::array< Number, n_bounds > Bounds
Definition limiter.h:240
typename View::flux_contribution_type flux_contribution_type
Definition limiter.h:221
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber relaxation_factor() const
Definition limiter.h:280
DEAL_II_HOST_DEVICE_ALWAYS_INLINE unsigned int newton_max_iterations() const
Definition limiter.h:272
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
Definition limiter.h:580
DEAL_II_HOST_DEVICE Bounds fully_relax_bounds(const Bounds &bounds, const Number &hd) const
Definition limiter.h:447
DEAL_II_HOST_DEVICE_ALWAYS_INLINE unsigned int iterations() const
Definition limiter.h:255
static constexpr unsigned int n_bounds
Definition limiter.h:235
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber newton_tolerance() const
Definition limiter.h:263
typename View::ScalarNumber ScalarNumber
Definition limiter.h:215
auto view() const
Definition limiter.h:160
Limiter(const HyperbolicSystem &hyperbolic_system, const std::string &subsection="/Limiter")
Definition limiter.h:98
TransferPolicy
Definition gpu.h:88
DEAL_II_HOST_DEVICE_ALWAYS_INLINE void quadratic_newton_step(Number &p_1, Number &p_2, const Number phi_p_1, const Number phi_p_2, const Number dphi_p_1, const Number dphi_p_2, const Number sign=Number(1.0))
Definition newton.h:39
DEAL_II_HOST_DEVICE T pow(const T x, const T b)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number positive_part(const Number number)
Definition simd.h:149
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number negative_part(const Number number)
Definition simd.h:161
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number compare_and_apply_mask(const Number &left, const Number &right, const Number &true_value, const Number &false_value)
Definition simd.h:176