ryujin 2.1.1 revision 8e904ddb3fa1d9e336dac21cf982add6a65e5467
Loading...
Searching...
No Matches
nasg_riemann_solver.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 <gpu.h>
11#include <newton.h>
12#include <simd.h>
13
14#include <deal.II/base/parameter_acceptor.h>
15
16#include <array>
17
18// #define DEBUG_WAVE_SPEED_ESTIMATOR
19
20namespace ryujin
21{
22 namespace EulerAEOS
23 {
32 bool covolume = true;
33
38 bool pinf = true;
39
45 bool safe_division = true;
46
53 bool variable_gamma = true;
54 };
55
56
57 template <typename Number,
59 typename MemorySpace = dealii::MemorySpace::Host>
60 class NASGRiemannSolverView;
61
62
73 template <typename ScalarNumber = double,
74 NASGRiemannSolverOptions options = NASGRiemannSolverOptions{}>
75 class NASGRiemannSolver : public dealii::ParameterAcceptor
76 {
77 public:
82
86 struct Parameters {
91
92 ScalarNumber covolume_b;
93 ScalarNumber pinf;
94
98
100
109
110 ScalarNumber gamma;
111 ScalarNumber lambda_factor;
115 ScalarNumber c_of_gamma;
116
118 };
119
121
125
129 NASGRiemannSolver(const std::string &subsection)
130 : ParameterAcceptor(subsection)
131 , parameters_("nasg_riemann_solver_parameters",
133 {
134 /* reference remains valid due to implicit_transfers_host_resident */
135 auto &parameters = *parameters_.view();
136
137 if constexpr (std::is_same<ScalarNumber, double>::value)
138 parameters.newton_tolerance = 1.e-10;
139 else
140 parameters.newton_tolerance = 1.e-4;
141 add_parameter("newton tolerance",
142 parameters.newton_tolerance,
143 "Tolerance for the quadratic newton stopping criterion");
144
145 parameters.newton_max_iterations = 0;
146 add_parameter("newton max iterations",
147 parameters.newton_max_iterations,
148 "Maximal number of quadratic newton iterations performed "
149 "during limiting");
150
151 parameters.covolume_b = ScalarNumber(0.);
152 parameters.pinf = ScalarNumber(0.);
153 parameters.compute_expensive_bounds = false;
154
155 parameters.gamma = ScalarNumber(0.);
156 parameters.lambda_factor = ScalarNumber(0.);
157 parameters.rarefaction_exponent = ScalarNumber(0.);
158 parameters.rarefaction_exponent_inverse = ScalarNumber(0.);
159 parameters.half_gamma_minus_one = ScalarNumber(0.);
160 parameters.c_of_gamma = ScalarNumber(0.);
161
162 /* invalidates view on default memory space */
163 ParameterAcceptor::parse_parameters_call_back.connect(
164 [this] { parameters_.view(); });
165 }
166
172 void set_gamma(const double gamma)
173 requires(!options.variable_gamma);
174
180 void set_equation_of_state(const double covolume_b,
181 const double pinf,
182 const bool compute_expensive_bounds);
183
191 template <typename Number,
192 typename MemorySpace = dealii::MemorySpace::Host>
193 auto view() const
194 {
196 }
197
198 private:
200
204
205 Mirrored<Parameters> parameters_;
206
207 template <typename, NASGRiemannSolverOptions, typename>
209
211 };
212
213
225 template <typename Number,
227 typename MemorySpace>
229 {
230 public:
231 static_assert(
232 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
233 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
234 "Unexpected memory space");
235
240
242
245
250 static constexpr unsigned int riemann_data_size = 5;
251
256 using primitive_type = std::array<Number, riemann_data_size>;
257
275
276 Number p_star;
277 Number u_star;
280
281 Number lambda1_minus; /* head of the 1-wave */
282 Number lambda1_plus; /* tail of the 1-wave */
283 Number lambda3_minus; /* tail of the 3-wave */
284 Number lambda3_plus; /* head of the 3-wave */
285 };
286
288
292
297 const NASGRiemannSolver<ScalarNumber, options> &riemann_solver)
298 : parameters_(riemann_solver.parameters_.template view<MemorySpace>())
299 {
300 }
301
305 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber newton_tolerance() const
306 {
307 return ScalarNumber(parameters_->newton_tolerance);
308 }
309
313 DEAL_II_HOST_DEVICE_ALWAYS_INLINE unsigned int
315 {
316 return parameters_->newton_max_iterations;
317 }
318
322 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber covolume_b() const
323 {
324 return parameters_->covolume_b;
325 }
326
330 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber pinf() const
331 {
332 return parameters_->pinf;
333 }
334
338 DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool compute_expensive_bounds() const
339 {
340 return parameters_->compute_expensive_bounds;
341 }
342
344
348
354 DEAL_II_HOST_DEVICE Number
355 compute(const primitive_type &riemann_data_i,
356 const primitive_type &riemann_data_j) const;
357
359
363
381 DEAL_II_HOST_DEVICE RiemannSolution
382 riemann_solution(const primitive_type &riemann_data_i,
383 const primitive_type &riemann_data_j,
384 const Number p_star) const;
385
392 DEAL_II_HOST_DEVICE RiemannSolution
393 solve(const primitive_type &riemann_data_i,
394 const primitive_type &riemann_data_j,
395 const unsigned int max_iterations = 100) const;
396
405 DEAL_II_HOST_DEVICE primitive_type
406 sample(const RiemannSolution &solution,
407 const Number &xi,
408 const unsigned int max_iterations = 100) const;
409
418 DEAL_II_HOST_DEVICE Number
419 rarefaction_fan_pressure(const primitive_type &riemann_data,
420 const Number &xi,
421 const ScalarNumber sign,
422 const unsigned int max_iterations) const;
423
425
429
433 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
434 one_minus_b_rho(const Number &rho) const
435 {
436 if constexpr (options.covolume)
437 return Number(1.) - covolume_b() * rho;
438 else
439 return Number(1.);
440 }
441
445 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number shift(const Number &p) const
446 {
447 if constexpr (options.pinf)
448 return p + pinf();
449 else
450 return p;
451 }
452
456 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number unshift(const Number &p) const
457 {
458 if constexpr (options.pinf)
459 return p - pinf();
460 else
461 return p;
462 }
463
468 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
469 safe_division(const Number &numerator, const Number &denominator) const
470 {
471 if constexpr (options.safe_division)
472 return ryujin::safe_division(numerator, denominator);
473 else
474 return numerator / denominator;
475 }
476
485 DEAL_II_HOST_DEVICE Number speed_of_sound(const Number &rho,
486 const Number &p,
487 const Number &gamma) const;
488
497 DEAL_II_HOST_DEVICE Number rho_star(const primitive_type &riemann_data,
498 const Number &p_star) const;
499
501
505
513 template <typename T>
514 DEAL_II_HOST_DEVICE_ALWAYS_INLINE static T c(const T &gamma_Z);
515
522 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
523 gamma_of(const primitive_type &riemann_data) const
524 {
525 if constexpr (options.variable_gamma)
526 return riemann_data[3];
527 else
528 return parameters_->gamma;
529 }
530
534 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
535 lambda_factor(const primitive_type &riemann_data) const
536 {
537 if constexpr (options.variable_gamma) {
538 const auto &gamma = riemann_data[3];
539 return ScalarNumber(0.5) * (gamma + ScalarNumber(1.)) / gamma;
540 } else
541 return parameters_->lambda_factor;
542 }
543
547 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
548 rarefaction_exponent(const primitive_type &riemann_data) const
549 {
550 if constexpr (options.variable_gamma) {
551 const auto &gamma = riemann_data[3];
552 return ScalarNumber(0.5) * (gamma - Number(1.)) / gamma;
553 } else
554 return parameters_->rarefaction_exponent;
555 }
556
560 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
562 {
563 if constexpr (options.variable_gamma) {
564 const auto &gamma = riemann_data[3];
565 return ScalarNumber(2.) * gamma / (gamma - Number(1.));
566 } else
567 return parameters_->rarefaction_exponent_inverse;
568 }
569
573 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
574 half_gamma_minus_one(const primitive_type &riemann_data) const
575 {
576 if constexpr (options.variable_gamma) {
577 const auto &gamma = riemann_data[3];
578 return ScalarNumber(0.5) * (gamma - Number(1.));
579 } else
580 return parameters_->half_gamma_minus_one;
581 }
582
586 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
587 c_of_gamma(const primitive_type &riemann_data) const
588 {
589 if constexpr (options.variable_gamma)
590 return c(riemann_data[3]);
591 else
592 return parameters_->c_of_gamma;
593 }
594
602 DEAL_II_HOST_DEVICE Number alpha(const Number &rho,
603 const Number &gamma,
604 const Number &a) const;
605
607
611
619 DEAL_II_HOST_DEVICE Number f(const primitive_type &riemann_data,
620 const Number p_star) const;
621
631 DEAL_II_HOST_DEVICE Number df(const primitive_type &riemann_data,
632 const Number &p_star) const;
633
641 DEAL_II_HOST_DEVICE Number phi(const primitive_type &riemann_data_i,
642 const primitive_type &riemann_data_j,
643 const Number p_in) const;
644
654 DEAL_II_HOST_DEVICE Number dphi(const primitive_type &riemann_data_i,
655 const primitive_type &riemann_data_j,
656 const Number &p) const;
657
664 DEAL_II_HOST_DEVICE Number
665 phi_of_p_max(const primitive_type &riemann_data_i,
666 const primitive_type &riemann_data_j) const;
667
673 DEAL_II_HOST_DEVICE Number lambda1_minus(
674 const primitive_type &riemann_data, const Number p_star) const;
675
681 DEAL_II_HOST_DEVICE Number lambda3_plus(
682 const primitive_type &riemann_data, const Number p_star) const;
683
685
689
694 DEAL_II_HOST_DEVICE Number
695 p_star_upper_bound(const primitive_type &riemann_data_i,
696 const primitive_type &riemann_data_j,
697 const Number &phi_p_max) const;
698
707 DEAL_II_HOST_DEVICE Number
708 p_star_single_gamma(const primitive_type &riemann_data_i,
709 const primitive_type &riemann_data_j,
710 const Number &phi_p_max) const;
711
721 DEAL_II_HOST_DEVICE Number
722 p_star_interpolated(const primitive_type &riemann_data_i,
723 const primitive_type &riemann_data_j) const;
724
732 DEAL_II_HOST_DEVICE Number
733 p_star_RS_full(const primitive_type &riemann_data_i,
734 const primitive_type &riemann_data_j) const;
735
743 DEAL_II_HOST_DEVICE Number
744 p_star_SS_full(const primitive_type &riemann_data_i,
745 const primitive_type &riemann_data_j) const;
746
753 DEAL_II_HOST_DEVICE Number
754 p_star_failsafe(const primitive_type &riemann_data_i,
755 const primitive_type &riemann_data_j) const;
756
765 DEAL_II_HOST_DEVICE Number
766 p_star_two_rarefaction(const primitive_type &riemann_data_i,
767 const primitive_type &riemann_data_j) const;
768
770
774
782 DEAL_II_HOST_DEVICE void newton_step(const primitive_type &riemann_data_i,
783 const primitive_type &riemann_data_j,
784 Number &p_1,
785 Number &p_2) const;
786
797 DEAL_II_HOST_DEVICE std::array<Number, 2>
798 compute_gap(const primitive_type &riemann_data_i,
799 const primitive_type &riemann_data_j,
800 const Number p_1,
801 const Number p_2) const;
802
812 DEAL_II_HOST_DEVICE Number
813 compute_lambda_max(const primitive_type &riemann_data_i,
814 const primitive_type &riemann_data_j,
815 const Number p_star) const;
816
817
818 private:
820
824
825 const Parameters *parameters_;
826
828
829 template <typename, NASGRiemannSolverOptions>
830 friend class NASGRiemannSolver;
831 };
832
833
834 /*
835 * -------------------------------------------------------------------------
836 * Inline definitions
837 * -------------------------------------------------------------------------
838 */
839
840
841 template <typename ScalarNumber, NASGRiemannSolverOptions options>
842 inline void
844 requires(!options.variable_gamma)
845 {
846 auto &parameters = *parameters_.view();
847
848 parameters.gamma = ScalarNumber(gamma);
849 parameters.lambda_factor = ScalarNumber(0.5 * (gamma + 1.) / gamma);
850 parameters.rarefaction_exponent =
851 ScalarNumber(0.5 * (gamma - 1.) / gamma);
852 parameters.rarefaction_exponent_inverse =
853 ScalarNumber(2. * gamma / (gamma - 1.));
854 parameters.half_gamma_minus_one = ScalarNumber(0.5 * (gamma - 1.));
855 parameters.c_of_gamma = ScalarNumber(
857 }
858
859
860 template <typename ScalarNumber, NASGRiemannSolverOptions options>
862 const double covolume_b,
863 const double pinf,
864 const bool compute_expensive_bounds)
865 {
866 auto &parameters = *parameters_.view();
867
868 parameters.covolume_b = ScalarNumber(covolume_b);
869 parameters.pinf = ScalarNumber(pinf);
870 parameters.compute_expensive_bounds = compute_expensive_bounds;
871 }
872
873
874 template <typename Number,
876 typename MemorySpace>
877 DEAL_II_HOST_DEVICE Number
879 const primitive_type &riemann_data_i,
880 const primitive_type &riemann_data_j) const
881 {
882 /*
883 * The NASGRiemannSolver is a guaranteed maximal wavespeed (GMS)
884 * estimate for the extended Riemann problem outlined in
885 * @cite ClaytonGuermondPopov-2022. For extensions on handling negative
886 * pressures, we follow @cite clayton2023robust (see §4.6).
887 *
888 * In contrast to the algorithm outlined in above reference the
889 * algorithm takes a couple of shortcuts to significantly decrease the
890 * computational footprint. These simplifications still guarantee that
891 * we have an upper bound on the maximal wavespeed - but the number
892 * bound might be larger. In particular:
893 *
894 * - We do not check and treat the case phi(p_min) > 0. This
895 * corresponds to two expansion waves, see §5.2 in the reference. In
896 * this case we have
897 *
898 * 0 < p_star < p_min <= p_max.
899 *
900 * And due to the fact that p_star < p_min the wavespeeds reduce to
901 * a left wavespeed v_L - a_L and right wavespeed v_R + a_R. This
902 * implies that it is sufficient to set p_2 to ANY value provided
903 * that p_2 <= p_min hold true in order to compute the correct
904 * wavespeed.
905 *
906 * If p_2 > p_min then a more pessimistic bound is computed.
907 *
908 * - The (optional) quadratic Newton iteration requires a valid bracket
909 * p_1 <= p_star <= p_2, i.e., phi(p_1) <= 0 <= phi(p_2). Both, the
910 * expensive bound and the (cheaper) interpolated bound, are upper
911 * bounds of p_star; p_1 is set to p_min or p_max depending on the
912 * sign of phi(p_max).
913 *
914 * - FIXME: Simplification in p_star_RS
915 */
916
917 const auto &[rho_i, u_i, p_i, gamma_i, a_i] = riemann_data_i;
918 const auto &[rho_j, u_j, p_j, gamma_j, a_j] = riemann_data_j;
919
920#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
921 std::cout << "rho_left: " << rho_i << std::endl;
922 std::cout << "u_left: " << u_i << std::endl;
923 std::cout << "p_left: " << p_i << std::endl;
924 std::cout << "gamma_left: " << gamma_i << std::endl;
925 std::cout << "a_left: " << a_i << std::endl;
926 std::cout << "rho_right: " << rho_j << std::endl;
927 std::cout << "u_right: " << u_j << std::endl;
928 std::cout << "p_right: " << p_j << std::endl;
929 std::cout << "gamma_right: " << gamma_j << std::endl;
930 std::cout << "a_right: " << a_j << std::endl;
931#endif
932
933 const Number phi_p_max = phi_of_p_max(riemann_data_i, riemann_data_j);
934 Number p_2 =
935 p_star_upper_bound(riemann_data_i, riemann_data_j, phi_p_max);
936
937#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
938 std::cout << " p^*_tilde = " << p_2 << "\n";
939 std::cout << " phi(p_*_t) = "
940 << phi(riemann_data_i, riemann_data_j, p_2) << std::endl;
941#endif
942
943 /*
944 * If we do no Newton iteration, cut it short:
945 */
946
947 if (newton_max_iterations() == 0) {
948 const auto lambda_max =
949 compute_lambda_max(riemann_data_i, riemann_data_j, p_2);
950
951#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
952 std::cout << "-> lambda_max = " << lambda_max << std::endl;
953#endif
954 return lambda_max;
955 }
956
957 /*
958 * Compute p_1 and ensure that p_1 < p_2. If we hit a case with two
959 * expansions we might indeed have that p_star_tilde < p_1. Set p_1 =
960 * p_2 in this case.
961 */
962
963 const Number p_min = std::min(p_i, p_j);
964 const Number p_max = std::max(p_i, p_j);
965
966 Number p_1 =
967 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
968 phi_p_max, Number(0.), p_max, p_min);
969
971 dealii::SIMDComparison::less_than_or_equal>(p_1, p_2, p_1, p_2);
972
973 /*
974 * Step 2: Perform quadratic Newton iteration.
975 *
976 * See @cite GuermondPopov2016b, p. 915f (4.8) and (4.9)
977 */
978
979 auto [gap, lambda_max] =
980 compute_gap(riemann_data_i, riemann_data_j, p_1, p_2);
981
982#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
983 std::cout << std::fixed << std::setprecision(16);
984 std::cout << "p_1: (start) " << p_1 << std::endl;
985 std::cout << "p_2: (start) " << p_2 << std::endl;
986 std::cout << "gap: (start) " << gap << std::endl;
987 std::cout << "l_m: (start) " << lambda_max << std::endl;
988#endif
989
990 for (unsigned int i = 0; i < newton_max_iterations(); ++i) {
991
992 /* We accept our current guess if we reach the tolerance... */
993 const Number tolerance(newton_tolerance());
994 if (std::max(Number(0.), gap - tolerance) == Number(0.)) {
995#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
996 std::cout << "converged after " << i << " iterations." << std::endl;
997#endif
998 break;
999 }
1000
1001 newton_step(riemann_data_i, riemann_data_j, p_1, p_2);
1002
1003 /* Update lambda_max and gap: */
1004 auto [gap_new, lambda_max_new] =
1005 compute_gap(riemann_data_i, riemann_data_j, p_1, p_2);
1006 gap = gap_new;
1007 lambda_max = lambda_max_new;
1008
1009#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
1010 std::cout << "p_1: ( " << i << " ) " << p_1 << std::endl;
1011 std::cout << "p_2: ( " << i << " ) " << p_2 << std::endl;
1012 std::cout << "gap: " << gap << std::endl;
1013 std::cout << "l_m: " << lambda_max << std::endl;
1014#endif
1015 }
1016
1017#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
1018 std::cout << "-> lambda_max = " << lambda_max << std::endl;
1019#endif
1020
1021 return lambda_max;
1022 }
1023
1024
1025 template <typename Number,
1027 typename MemorySpace>
1028 DEAL_II_HOST_DEVICE auto
1030 const primitive_type &riemann_data_i,
1031 const primitive_type &riemann_data_j,
1032 const Number p_star) const -> RiemannSolution
1033 {
1034 const auto &[rho_i, u_i, p_i, gamma_Z_i, a_i] = riemann_data_i;
1035 const auto &[rho_j, u_j, p_j, gamma_Z_j, a_j] = riemann_data_j;
1036 const auto gamm_i = gamma_of(riemann_data_i);
1037 const auto gamm_j = gamma_of(riemann_data_j);
1038
1039 /*
1040 * The velocity of the star state obtained from the left and right
1041 * wave curves, see @cite Toro2009, (4.9). Both values coincide for
1042 * the exact p_star, but differ in case of vacuum (or an approximate
1043 * p_star). In case of vacuum they are the velocities of the vacuum
1044 * fronts.
1045 */
1046
1047 const Number u_star_left = u_i - f(riemann_data_i, p_star);
1048 const Number u_star_right = u_j + f(riemann_data_j, p_star);
1049 const Number u_star = ScalarNumber(0.5) * (u_star_left + u_star_right);
1050
1051 const Number rho_star_left = rho_star(riemann_data_i, p_star);
1052 const Number rho_star_right = rho_star(riemann_data_j, p_star);
1053
1054 const Number lambda1_minus = this->lambda1_minus(riemann_data_i, p_star);
1055 const Number lambda3_plus = this->lambda3_plus(riemann_data_j, p_star);
1056
1057 /*
1058 * For a shock the tail speed coincides with the shock speed, for a
1059 * rarefaction wave it is u^\ast -+ a^\ast, see @cite Toro2009, §4.4:
1060 */
1061
1062 constexpr auto GTE = dealii::SIMDComparison::greater_than_or_equal;
1063 Number lambda1_plus =
1064 u_star_left - speed_of_sound(rho_star_left, p_star, Number(gamm_i));
1065 lambda1_plus = ryujin::compare_and_apply_mask<GTE>(
1066 p_star, p_i, lambda1_minus, lambda1_plus);
1067
1068 Number lambda3_minus =
1069 u_star_right + speed_of_sound(rho_star_right, p_star, Number(gamm_j));
1070 lambda3_minus = ryujin::compare_and_apply_mask<GTE>(
1071 p_star, p_j, lambda3_plus, lambda3_minus);
1072
1073 return RiemannSolution{
1074 .riemann_data_left = riemann_data_i,
1075 .riemann_data_right = riemann_data_j,
1076 .p_star = p_star,
1077 .u_star = u_star,
1078 .rho_star_left = rho_star_left,
1079 .rho_star_right = rho_star_right,
1080 .lambda1_minus = lambda1_minus,
1081 .lambda1_plus = lambda1_plus,
1082 .lambda3_minus = lambda3_minus,
1083 .lambda3_plus = lambda3_plus,
1084 };
1085 }
1086
1087
1088 template <typename Number,
1090 typename MemorySpace>
1091 DEAL_II_HOST_DEVICE auto
1093 const primitive_type &riemann_data_i,
1094 const primitive_type &riemann_data_j,
1095 const unsigned int max_iterations) const -> RiemannSolution
1096 {
1097 /*
1098 * First, we compute a bracket p_1 <= p_star <= p_2 with phi(p_1) <= 0
1099 * <= phi(p_2). Recall that phi is monotonically increasing.
1100 */
1101
1102 const Number &p_i = riemann_data_i[2];
1103 const Number &p_j = riemann_data_j[2];
1104
1105 const Number p_min = std::min(p_i, p_j);
1106 const Number p_max = std::max(p_i, p_j);
1107 const Number p_vacuum = unshift(Number(0.));
1108
1109 const Number phi_p_max = phi_of_p_max(riemann_data_i, riemann_data_j);
1110 const Number phi_p_min = phi(riemann_data_i, riemann_data_j, p_min);
1111 const Number phi_p_vacuum = phi(riemann_data_i, riemann_data_j, p_vacuum);
1112
1113 /*
1114 * Case phi(p_min) <= 0 <= phi(p_max) (rarefaction-shock): The bracket
1115 * is [p_min, p_max].
1116 *
1117 * Case phi(p_min) > 0 (rarefaction-rarefaction): The bracket is
1118 * [p_star_two_rarefaction(), p_min]. Note that we must not start the
1119 * iteration at -pinf: dphi is unbounded at -pinf (vacuum), which
1120 * results in NaNs in the quadratic Newton step.
1121 */
1122
1123 const Number p_lower = std::max(
1124 p_vacuum, p_star_two_rarefaction(riemann_data_i, riemann_data_j));
1125
1126 Number p_1 = ryujin::compare_and_apply_mask<
1127 dealii::SIMDComparison::less_than_or_equal>(
1128 phi_p_min, Number(0.), p_min, p_lower);
1129 Number p_2 = ryujin::compare_and_apply_mask<
1130 dealii::SIMDComparison::less_than_or_equal>(
1131 phi_p_min, Number(0.), p_max, p_min);
1132
1133 /*
1134 * Case phi(p_max) < 0 (shock-shock): The bracket is
1135 * [p_max, p_star_upper_bound()].
1136 */
1137
1138 const Number p_upper = std::max(
1139 p_max, p_star_upper_bound(riemann_data_i, riemann_data_j, phi_p_max));
1140
1141 p_1 = ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1142 phi_p_max, Number(0.), p_max, p_1);
1143 p_2 = ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1144 phi_p_max, Number(0.), p_upper, p_2);
1145
1146 /*
1147 * Case phi(-pinf) >= 0: A vacuum is formed and p_star = -pinf.
1148 */
1149
1151 dealii::SIMDComparison::greater_than_or_equal>(
1152 phi_p_vacuum, Number(0.), p_vacuum, p_1);
1154 dealii::SIMDComparison::greater_than_or_equal>(
1155 phi_p_vacuum, Number(0.), p_vacuum, p_2);
1156
1157 /*
1158 * Now, we perform quadratic Newton steps until the bracket has shrunk
1159 * to machine precision:
1160 */
1161
1162 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
1163
1164 for (unsigned int i = 0; i < max_iterations; ++i) {
1165 const Number tolerance = ScalarNumber(16. * eps) * shift(p_2);
1166 if (std::max(Number(0.), p_2 - p_1 - tolerance) == Number(0.))
1167 break;
1168
1169 newton_step(riemann_data_i, riemann_data_j, p_1, p_2);
1170 }
1171
1172 return riemann_solution(riemann_data_i, riemann_data_j, p_2);
1173 }
1174
1175
1176 template <typename Number,
1178 typename MemorySpace>
1179 DEAL_II_HOST_DEVICE auto
1181 const RiemannSolution &solution,
1182 const Number &xi,
1183 const unsigned int max_iterations) const -> primitive_type
1184 {
1185 const auto &riemann_data_left = solution.riemann_data_left;
1186 const auto &riemann_data_right = solution.riemann_data_right;
1187
1188 /*
1189 * The states inside the left and right rarefaction fans. We clip xi
1190 * to the fan so that the (masked out) values outside of the fan stay
1191 * well defined. For a shock the fan is empty:
1192 */
1193
1194 const Number xi_left =
1195 std::max(solution.lambda1_minus, std::min(xi, solution.lambda1_plus));
1196 const Number p_fan_left = rarefaction_fan_pressure(
1197 riemann_data_left, xi_left, ScalarNumber(-1.), max_iterations);
1198 const Number rho_fan_left = rho_star(riemann_data_left, p_fan_left);
1199 const Number u_fan_left =
1200 riemann_data_left[1] - f(riemann_data_left, p_fan_left);
1201
1202 const Number xi_right =
1203 std::max(solution.lambda3_minus, std::min(xi, solution.lambda3_plus));
1204 const Number p_fan_right = rarefaction_fan_pressure(
1205 riemann_data_right, xi_right, ScalarNumber(1.), max_iterations);
1206 const Number rho_fan_right = rho_star(riemann_data_right, p_fan_right);
1207 const Number u_fan_right =
1208 riemann_data_right[1] + f(riemann_data_right, p_fan_right);
1209
1210 /*
1211 * Select the region from right to left, every region overrides the
1212 * previous one. In case of vacuum the star states carry rho = 0 and
1213 * p = -pinf, so no special treatment is necessary:
1214 */
1215
1216 primitive_type result = riemann_data_right;
1217
1218 const auto select = [&](const Number &threshold,
1219 const Number &rho,
1220 const Number &u,
1221 const Number &p,
1222 const Number &gamma) {
1223 constexpr auto LT = dealii::SIMDComparison::less_than;
1224 result[0] =
1225 ryujin::compare_and_apply_mask<LT>(xi, threshold, rho, result[0]);
1226 result[1] =
1227 ryujin::compare_and_apply_mask<LT>(xi, threshold, u, result[1]);
1228 result[2] =
1229 ryujin::compare_and_apply_mask<LT>(xi, threshold, p, result[2]);
1230 result[3] =
1231 ryujin::compare_and_apply_mask<LT>(xi, threshold, gamma, result[3]);
1232 };
1233
1234 select(solution.lambda3_plus,
1235 rho_fan_right,
1236 u_fan_right,
1237 p_fan_right,
1238 riemann_data_right[3]);
1239 select(solution.lambda3_minus,
1240 solution.rho_star_right,
1241 solution.u_star,
1242 solution.p_star,
1243 riemann_data_right[3]);
1244 select(solution.u_star,
1245 solution.rho_star_left,
1246 solution.u_star,
1247 solution.p_star,
1248 riemann_data_left[3]);
1249 select(solution.lambda1_plus,
1250 rho_fan_left,
1251 u_fan_left,
1252 p_fan_left,
1253 riemann_data_left[3]);
1254 select(solution.lambda1_minus,
1255 riemann_data_left[0],
1256 riemann_data_left[1],
1257 riemann_data_left[2],
1258 riemann_data_left[3]);
1259
1260 Number gamma;
1261 if constexpr (options.variable_gamma)
1262 gamma = result[3];
1263 else
1264 gamma = Number(gamma_of(riemann_data_left));
1265
1266 result[4] = speed_of_sound(result[0], result[2], gamma);
1267
1268 return result;
1269 }
1270
1271
1272 template <typename Number,
1274 typename MemorySpace>
1275 DEAL_II_HOST_DEVICE Number
1277 rarefaction_fan_pressure(const primitive_type &riemann_data,
1278 const Number &xi,
1279 const ScalarNumber sign,
1280 const unsigned int max_iterations) const
1281 {
1282 /*
1283 * Inside the fan we have xi = u + sign a, the generalized Riemann
1284 * invariant u - sign 2 a (1 - b rho) / (gamma - 1) = const, and the
1285 * isentrope P (1 / rho - b)^gamma = const, with P = p + pinf. We
1286 * introduce
1287 *
1288 * r = (P / P_Z)^e, e = (gamma - 1) / (2 gamma),
1289 *
1290 * and note that a (1 - b rho) = a_Z (1 - b rho_Z) r. Combining all
1291 * three conditions results in the scalar equation
1292 *
1293 * g(r) = alpha_Z + d - (a_Z (1 - b rho_Z) + alpha_Z) r
1294 * - a_Z b rho_Z r^k = 0,
1295 *
1296 * with alpha_Z = 2 a_Z (1 - b rho_Z) / (gamma - 1), d = sign (xi -
1297 * u_Z), and k = (gamma + 1) / (gamma - 1). The function g is
1298 * decreasing and concave. Thus, a Newton iteration started at the
1299 * root r_0 of the linear part (which is the exact solution for b = 0,
1300 * see @cite Toro2009, (4.56)) converges monotonically from the right.
1301 */
1302
1303 const auto &[rho_Z, u_Z, p_Z, gamma_Z, a_Z] = riemann_data;
1304 const Number gamma = gamma_of(riemann_data);
1305
1306 const Number alpha_Z = alpha(rho_Z, gamma, a_Z);
1307 const Number a_tilde_Z = a_Z * one_minus_b_rho(rho_Z);
1308
1309 const Number constant = alpha_Z + sign * (xi - u_Z);
1310 const Number linear = a_tilde_Z + alpha_Z;
1311
1312 Number r = std::max(Number(0.), safe_division(constant, linear));
1313
1314 if constexpr (options.covolume) {
1315 const Number nonlinear = a_Z - a_tilde_Z; /* a_Z b rho_Z */
1316 const Number k_minus_one =
1317 safe_division(Number(2.), gamma - Number(1.));
1318 const Number k = k_minus_one + Number(1.);
1319
1320 constexpr ScalarNumber eps =
1321 std::numeric_limits<ScalarNumber>::epsilon();
1322 const Number tolerance(ScalarNumber(16.) * eps);
1323
1324 for (unsigned int i = 0; i < max_iterations; ++i) {
1325 const Number r_power = ryujin::pow(r, k_minus_one);
1326
1327 /* We approach the root from the right, thus -g(r) >= 0: */
1328 const Number minus_g =
1329 linear * r + nonlinear * r * r_power - constant;
1330 const Number minus_dg = linear + k * nonlinear * r_power;
1331 const Number delta = safe_division(minus_g, minus_dg);
1332
1333 r = std::max(Number(0.), r - delta);
1334 if (std::max(Number(0.), delta - tolerance) == Number(0.))
1335 break;
1336 }
1337 }
1338
1339 const Number P_Z = shift(p_Z);
1340 return unshift(
1341 P_Z *
1342 ryujin::pow(r, Number(rarefaction_exponent_inverse(riemann_data))));
1343 }
1344
1345
1346 template <typename Number,
1348 typename MemorySpace>
1349 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1351 const Number &rho, const Number &p, const Number &gamma) const
1352 {
1353 return std::sqrt(
1354 safe_division(gamma * shift(p), rho * one_minus_b_rho(rho)));
1355 }
1356
1357
1358 template <typename Number,
1360 typename MemorySpace>
1361 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1363 const primitive_type &riemann_data, const Number &p_star) const
1364 {
1365 /*
1366 * For p_star >= p the state is connected by a shock and we use the
1367 * Rankine-Hugoniot condition
1368 *
1369 * w^\ast = w (mu P^\ast + P) / (P^\ast + mu P),
1370 *
1371 * otherwise the state is connected by a rarefaction wave and we use
1372 * the isentrope P w^gamma = const. Here, w = 1 / rho - b,
1373 * P = p + pinf, and mu = (gamma - 1) / (gamma + 1).
1374 */
1375
1376 const auto &[rho, u, p, gamma_Z, a] = riemann_data;
1377 const auto gamma = gamma_of(riemann_data);
1378
1379 const Number one_minus_b_rho = this->one_minus_b_rho(rho);
1380 const Number b_rho = Number(1.) - one_minus_b_rho;
1381
1382 const Number P = shift(p);
1383 const Number P_star = shift(p_star);
1384
1385 /*
1386 * Shock case: Multiply w^\ast = w (mu P^\ast + P) / (P^\ast + mu P)
1387 * by (gamma + 1) and solve for rho^\ast = 1 / (b + w^\ast):
1388 */
1389
1390 const Number gamma_minus_one_P_star = (gamma - Number(1.)) * P_star;
1391 const Number gamma_minus_one_P = (gamma - Number(1.)) * P;
1392 const Number gamma_plus_one_P_star = (gamma + Number(1.)) * P_star;
1393 const Number gamma_plus_one_P = (gamma + Number(1.)) * P;
1394
1395 const Number shock_numerator = gamma_plus_one_P_star + gamma_minus_one_P;
1396 const Number shock_denominator =
1397 one_minus_b_rho * (gamma_minus_one_P_star + gamma_plus_one_P) +
1398 b_rho * shock_numerator;
1399
1400 const Number true_value =
1401 rho * safe_division(shock_numerator, shock_denominator);
1402
1403 /*
1404 * Rarefaction case: w^\ast = w r^{-1} with r = (P^\ast / P)^{1/gamma}.
1405 * We avoid the division by r so that the vacuum case P^\ast = 0
1406 * results in rho^\ast = 0:
1407 */
1408
1409 const Number r = ryujin::pow(safe_division(P_star, P),
1410 Number(ScalarNumber(1.) / gamma));
1411
1412 const Number false_value =
1413 rho * safe_division(r, one_minus_b_rho + b_rho * r);
1414
1416 dealii::SIMDComparison::greater_than_or_equal>(
1417 p_star, p, true_value, false_value);
1418 }
1419
1420
1421 template <typename Number,
1423 typename MemorySpace>
1424 template <typename T>
1425 DEAL_II_HOST_DEVICE_ALWAYS_INLINE T
1427 {
1428 /*
1429 * We implement the continuous and monotonic function c(gamma) as
1430 * defined in (A.3) on page A469 of @cite ClaytonGuermondPopov-2022.
1431 * But with a simplified quick cut-off for the case gamma > 3:
1432 *
1433 * c(gamma)^2 = 1 for gamma <= 5 / 3
1434 * c(gamma)^2 = (3 * gamma + 11) / (6 * gamma + 6) in between
1435 * c(gamma)^2 = max(1/2, 5 / 6 - slope (gamma - 3)) for gamma > 3
1436 *
1437 * Due to the fact that the function is monotonic we can simply clip
1438 * the values without checking the conditions:
1439 */
1440
1441 constexpr ScalarNumber slope =
1442 ScalarNumber(-0.34976871477801828189920753948709);
1443
1444 const T first_radicand = (ScalarNumber(3.) * gamma + T(11.)) /
1445 (ScalarNumber(6.) * gamma + T(6.));
1446
1447 const T second_radicand = T(5. / 6.) + slope * (gamma - T(3.));
1448
1449 T radicand = std::min(first_radicand, second_radicand);
1450 radicand = std::min(T(1.), radicand);
1451 radicand = std::max(T(1. / 2.), radicand);
1452
1453 return std::sqrt(radicand);
1454 }
1455
1456
1457 template <typename Number,
1459 typename MemorySpace>
1460 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1462 const Number &rho, const Number &gamma, const Number &a) const
1463 {
1464 const Number numerator = ScalarNumber(2.) * a * one_minus_b_rho(rho);
1465
1466 const Number denominator = gamma - Number(1.);
1467
1468 return safe_division(numerator, denominator);
1469 }
1470
1471
1472 template <typename Number,
1474 typename MemorySpace>
1475 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1477 const primitive_type &riemann_data, const Number p_star) const
1478 {
1479 constexpr ScalarNumber min = std::numeric_limits<ScalarNumber>::min();
1480
1481 const auto &[rho, u, p, gamma_Z, a] = riemann_data;
1482 const auto gamma = gamma_of(riemann_data);
1483
1484 const Number one_minus_b_rho = this->one_minus_b_rho(rho);
1485 const Number gamma_minus_one = gamma - Number(1.);
1486
1487 const Number Az =
1488 ScalarNumber(2.) * one_minus_b_rho / (rho * (gamma + Number(1.)));
1489
1490 const Number Bz = gamma_minus_one / (gamma + Number(1.)) * shift(p);
1491
1492 const Number radicand = safe_division(Az, shift(p_star) + Bz);
1493
1494 /* true_value is shock case */
1495 const Number true_value = (p_star - p) * std::sqrt(radicand);
1496
1497 const auto exponent = rarefaction_exponent(riemann_data);
1498
1499 const Number ratio = safe_division(shift(p_star), shift(p));
1500 const Number factor = ryujin::pow(ratio, exponent) - Number(1.);
1501
1502 /* false_value is rarefaction case */
1503 const auto false_value = ScalarNumber(2.) * a * one_minus_b_rho * factor /
1504 std::max(gamma_minus_one, Number(min));
1505
1507 dealii::SIMDComparison::greater_than_or_equal>(
1508 p_star, p, true_value, false_value);
1509 }
1510
1511
1512 template <typename Number,
1514 typename MemorySpace>
1515 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1517 const primitive_type &riemann_data, const Number &p_star) const
1518 {
1519 const auto &[rho, u, p, gamma_Z, a] = riemann_data;
1520 const auto gamma = gamma_of(riemann_data);
1521
1522 const Number one_minus_b_rho = this->one_minus_b_rho(rho);
1523
1524 const Number radicand_inverse =
1525 safe_division(ScalarNumber(0.5) * rho, one_minus_b_rho) *
1526 ((gamma + Number(1.)) * shift(p_star) +
1527 (gamma - Number(1.)) * shift(p));
1528 const Number denominator =
1529 shift(p_star) +
1530 ((gamma - Number(1.)) / (gamma + Number(1.)) * shift(p));
1531
1532 /* true_value is shock case */
1533 const Number true_value =
1534 (denominator - ScalarNumber(0.5) * (p_star - p)) /
1535 (denominator * std::sqrt(radicand_inverse));
1536
1537 const auto exponent = -lambda_factor(riemann_data);
1538
1539 const Number ratio = safe_division(shift(p_star), shift(p));
1540
1541 /*
1542 * false_value is rarefaction case. Note that the factor (gamma - 1)
1543 * of the derivative of the exponent cancels with the denominator of
1544 * alpha, so we do not have to divide by (gamma - 1):
1545 */
1546 const auto false_value =
1547 safe_division(a * one_minus_b_rho * ryujin::pow(ratio, exponent),
1548 Number(gamma * shift(p)));
1549
1551 dealii::SIMDComparison::greater_than_or_equal>(
1552 p_star, p, true_value, false_value);
1553 }
1554
1555
1556 template <typename Number,
1558 typename MemorySpace>
1559 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1561 const primitive_type &riemann_data_i,
1562 const primitive_type &riemann_data_j,
1563 const Number p_in) const
1564 {
1565 const Number &u_i = riemann_data_i[1];
1566 const Number &u_j = riemann_data_j[1];
1567
1568 return f(riemann_data_i, p_in) + f(riemann_data_j, p_in) + u_j - u_i;
1569 }
1570
1571
1572 template <typename Number,
1574 typename MemorySpace>
1575 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1577 const primitive_type &riemann_data_i,
1578 const primitive_type &riemann_data_j,
1579 const Number &p) const
1580 {
1581 return df(riemann_data_i, p) + df(riemann_data_j, p);
1582 }
1583
1584
1585 template <typename Number,
1587 typename MemorySpace>
1588 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1590 const primitive_type &riemann_data_i,
1591 const primitive_type &riemann_data_j) const
1592 {
1593 /*
1594 * The approximate Riemann solver is based on a function phi(p) that is
1595 * montone increasing in p, concave down and whose (weak) third
1596 * derivative is non-negative and locally bounded. Because we actually
1597 * do not perform any iteration for computing our wavespeed estimate we
1598 * can get away by only implementing a specialized variant of the phi
1599 * function that computes phi(p_max). It inlines the implementation of
1600 * the "f" function and eliminates all unnecessary branches in "f".
1601 */
1602
1603 const auto &[rho_i, u_i, p_i, gamma_Z_i, a_i] = riemann_data_i;
1604 const auto &[rho_j, u_j, p_j, gamma_Z_j, a_j] = riemann_data_j;
1605 const auto gamma_i = gamma_of(riemann_data_i);
1606 const auto gamma_j = gamma_of(riemann_data_j);
1607
1608 const Number p_max = std::max(p_i, p_j);
1609
1610 const Number radicand_inverse_i =
1611 safe_division(ScalarNumber(0.5) * rho_i, one_minus_b_rho(rho_i)) *
1612 ((gamma_i + Number(1.)) * shift(p_max) +
1613 (gamma_i - Number(1.)) * shift(p_i));
1614
1615 const Number value_i =
1616 safe_division(p_max - p_i, std::sqrt(radicand_inverse_i));
1617
1618 const Number radicand_inverse_j =
1619 safe_division(ScalarNumber(0.5) * rho_j, one_minus_b_rho(rho_j)) *
1620 ((gamma_j + Number(1.)) * shift(p_max) +
1621 (gamma_j - Number(1.)) * shift(p_j));
1622
1623 const Number value_j =
1624 safe_division(p_max - p_j, std::sqrt(radicand_inverse_j));
1625
1626 return value_i + value_j + u_j - u_i;
1627 }
1628
1629
1630 template <typename Number,
1632 typename MemorySpace>
1633 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1635 const primitive_type &riemann_data, const Number p_star) const
1636 {
1637 const auto &[rho, u, p, gamma, a] = riemann_data;
1638
1639 const auto factor = lambda_factor(riemann_data);
1640
1641 const Number p_inverse = safe_division(Number(1.), shift(p));
1642 const Number tmp = positive_part(p_star - p) * p_inverse;
1643
1644 return u - a * std::sqrt(Number(1.) + factor * tmp);
1645 }
1646
1647
1648 template <typename Number,
1650 typename MemorySpace>
1651 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1653 const primitive_type &riemann_data, const Number p_star) const
1654 {
1655 const auto &[rho, u, p, gamma, a] = riemann_data;
1656
1657 const auto factor = lambda_factor(riemann_data);
1658
1659 const Number p_inverse = safe_division(Number(1.), shift(p));
1660 const Number tmp = positive_part(p_star - p) * p_inverse;
1661
1662 return u + a * std::sqrt(Number(1.) + factor * tmp);
1663 }
1664
1665
1666 template <typename Number,
1668 typename MemorySpace>
1669 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1671 const primitive_type &riemann_data_i,
1672 const primitive_type &riemann_data_j,
1673 const Number &phi_p_max) const
1674 {
1675 /*
1676 * Depending on the compile time options and on
1677 * compute_expensive_bounds() we use the single gamma bound, the
1678 * interpolated bound, or the expensive bounds, each combined with
1679 * the failsafe bound or p_max.
1680 */
1681
1682 const Number &p_i = riemann_data_i[2];
1683 const Number &p_j = riemann_data_j[2];
1684
1685 const Number p_max = std::max(p_i, p_j);
1686
1687 if constexpr (!options.variable_gamma) {
1688 /*
1689 * For a single gamma the expensive bounds (5.7), (5.8), and (5.10)
1690 * reduce to a single formula of the same cost as the interpolated
1691 * bound:
1692 */
1693 const Number p_star_tilde =
1694 p_star_single_gamma(riemann_data_i, riemann_data_j, phi_p_max);
1695 const Number p_star_backup =
1696 p_star_failsafe(riemann_data_i, riemann_data_j);
1697
1699 dealii::SIMDComparison::less_than>(
1700 phi_p_max,
1701 Number(0.),
1702 std::min(p_star_tilde, p_star_backup),
1703 std::min(p_max, p_star_tilde));
1704
1705 } else if (!compute_expensive_bounds()) {
1706#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
1707 const Number p_star_RS = p_star_RS_full(riemann_data_i, riemann_data_j);
1708 const Number p_star_SS = p_star_SS_full(riemann_data_i, riemann_data_j);
1709 const Number p_strict =
1710 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1711 phi_p_max, Number(0.), p_star_SS, std::min(p_max, p_star_RS));
1712 std::cout << " p^*_strict = " << p_strict << "\n";
1713 std::cout << " phi(p_*_s) = "
1714 << phi(riemann_data_i, riemann_data_j, p_strict) << "\n";
1715 std::cout << "-> lambda_str = "
1716 << compute_lambda_max(
1717 riemann_data_i, riemann_data_j, p_strict)
1718 << std::endl;
1719#endif
1720
1721 const Number p_star_tilde =
1722 p_star_interpolated(riemann_data_i, riemann_data_j);
1723 const Number p_star_backup =
1724 p_star_failsafe(riemann_data_i, riemann_data_j);
1725
1727 dealii::SIMDComparison::less_than>(
1728 phi_p_max,
1729 Number(0.),
1730 std::min(p_star_tilde, p_star_backup),
1731 std::min(p_max, p_star_tilde));
1732
1733 } else {
1734
1735 const Number p_star_RS = p_star_RS_full(riemann_data_i, riemann_data_j);
1736 const Number p_star_SS = p_star_SS_full(riemann_data_i, riemann_data_j);
1737
1739 dealii::SIMDComparison::less_than>(
1740 phi_p_max, Number(0.), p_star_SS, std::min(p_max, p_star_RS));
1741 }
1742 }
1743
1744
1745 template <typename Number,
1747 typename MemorySpace>
1748 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1750 const primitive_type &riemann_data_i,
1751 const primitive_type &riemann_data_j,
1752 const Number &phi_p_max) const
1753 {
1754 /*
1755 * For a single gamma the expansion-shock bound (5.7)/(5.8) and the
1756 * shock-shock bound (5.10) of @cite ClaytonGuermondPopov-2022 reduce
1757 * to
1758 *
1759 * p_max * (N / D)^{1/e}, e = (gamma - 1) / (2 gamma),
1760 * N = alpha_hat_min + X - (u_j - u_i),
1761 * D = alpha_hat_min (p_min / p_max)^{-e} + X,
1762 *
1763 * with X = alpha_hat_max for phi(p_max) < 0 (5.10), and X = alpha_max
1764 * otherwise (5.7)/(5.8).
1765 */
1766
1767 const auto &[rho_i, u_i, p_i, gamma_i, a_i] = riemann_data_i;
1768 const auto &[rho_j, u_j, p_j, gamma_j, a_j] = riemann_data_j;
1769
1770 /* We have gamma_i == gamma_j: */
1771 const auto c_gamma = c_of_gamma(riemann_data_i);
1772
1773 /*
1774 * alpha_Z = 2 a_Z (1 - b rho_Z) / (gamma - 1). We drop the common
1775 * factor 2 / (gamma - 1) and rescale (u_j - u_i) accordingly:
1776 */
1777 const Number alpha_i = a_i * one_minus_b_rho(rho_i);
1778 const Number alpha_j = a_j * one_minus_b_rho(rho_j);
1779
1780 const Number p_min = shift(std::min(p_i, p_j));
1781 const Number p_max = shift(std::max(p_i, p_j));
1782
1783 const Number alpha_min =
1784 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1785 p_i, p_j, alpha_i, alpha_j);
1786
1787 const Number alpha_max = ryujin::compare_and_apply_mask<
1788 dealii::SIMDComparison::greater_than_or_equal>(
1789 p_i, p_j, alpha_i, alpha_j);
1790
1791 const Number alpha_hat_min = c_gamma * alpha_min;
1792
1793 /*
1794 * The shock-shock bound (5.10) uses alpha_hat_max, the
1795 * expansion-shock bound (5.7)/(5.8) uses alpha_max:
1796 */
1797 const Number alpha_select =
1798 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1799 phi_p_max, Number(0.), c_gamma * alpha_max, alpha_max);
1800
1801 const auto exponent = rarefaction_exponent(riemann_data_i);
1802 const auto exponent_inverse =
1803 rarefaction_exponent_inverse(riemann_data_i);
1804
1805 const Number numerator =
1806 positive_part(alpha_hat_min + alpha_select -
1807 half_gamma_minus_one(riemann_data_i) * (u_j - u_i));
1808
1809 const Number denominator =
1810 alpha_hat_min * ryujin::pow(safe_division(p_min, p_max), -exponent) +
1811 alpha_select;
1812
1813 const Number p_tilde =
1814 unshift(p_max * ryujin::pow(safe_division(numerator, denominator),
1815 exponent_inverse));
1816
1817#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
1818 std::cout << "p_star_single_gamma = " << p_tilde << std::endl;
1819#endif
1820 return p_tilde;
1821 }
1822
1823
1824 template <typename Number,
1826 typename MemorySpace>
1827 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1829 const primitive_type &riemann_data_i,
1830 const primitive_type &riemann_data_j) const
1831 {
1832 const auto &[rho_i, u_i, p_i, gamma_i, a_i] = riemann_data_i;
1833 const auto &[rho_j, u_j, p_j, gamma_j, a_j] = riemann_data_j;
1834 const auto alpha_i = alpha(rho_i, gamma_i, a_i);
1835 const auto alpha_j = alpha(rho_j, gamma_j, a_j);
1836
1837 /*
1838 * First get p_min, p_max.
1839 *
1840 * Then, we get gamma_min/max, and alpha_min/max. Note that the
1841 * *_min/max values are associated with p_min/max and are not
1842 * necessarily the minimum/maximum of *_i vs *_j.
1843 */
1844
1845 const Number p_min = shift(std::min(p_i, p_j));
1846 const Number p_max = shift(std::max(p_i, p_j));
1847
1848 const Number gamma_min =
1849 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1850 p_i, p_j, gamma_i, gamma_j);
1851
1852 const Number alpha_min =
1853 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1854 p_i, p_j, alpha_i, alpha_j);
1855
1856 const Number alpha_hat_min = c(gamma_min) * alpha_min;
1857
1858 const Number gamma_max = ryujin::compare_and_apply_mask<
1859 dealii::SIMDComparison::greater_than_or_equal>(
1860 p_i, p_j, gamma_i, gamma_j);
1861
1862 const Number alpha_max = ryujin::compare_and_apply_mask<
1863 dealii::SIMDComparison::greater_than_or_equal>(
1864 p_i, p_j, alpha_i, alpha_j);
1865
1866 const Number alpha_hat_max = c(gamma_max) * alpha_max;
1867
1868 const Number gamma_m = std::min(gamma_i, gamma_j);
1869 const Number gamma_M = std::max(gamma_i, gamma_j);
1870
1871 const Number p_ratio = safe_division(p_min, p_max);
1872
1873 /*
1874 * Here, we use a trick: The r-factor only shows up in the formula
1875 * for the case \gamma_min = \gamma_m, otherwise the r-factor
1876 * vanishes. We can accomplish this by using the following modified
1877 * exponent (where we substitute gamma_m by gamma_min):
1878 */
1879 const Number r_exponent =
1880 (gamma_M - gamma_min) / (ScalarNumber(2.) * gamma_min * gamma_M);
1881
1882 /*
1883 * Compute a simultaneous upper bound on
1884 * (5.7) second formula for \tilde p_2^\ast
1885 * (5.8) first formula for \tilde p_1^\ast
1886 * (5.11) formula for \tilde p_2^\ast
1887 */
1888
1889 const Number exponent =
1890 (gamma_m - Number(1.)) / (ScalarNumber(2.) * gamma_m);
1891 const Number exponent_inverse = Number(1.) / exponent;
1892
1893 const Number numerator =
1894 positive_part(alpha_hat_min + /*SIC!*/ alpha_max - (u_j - u_i));
1895
1896 Number denominator = alpha_hat_min * ryujin::pow(p_ratio, -exponent) +
1897 alpha_hat_max * ryujin::pow(p_ratio, r_exponent);
1898
1899 const auto temp = safe_division(numerator, denominator);
1900
1901 const Number p_tilde =
1902 unshift(p_max * ryujin::pow(temp, exponent_inverse));
1903
1904#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
1905 std::cout << "p_star_interpolated = " << p_tilde << std::endl;
1906#endif
1907 return p_tilde;
1908 }
1909
1910
1911 template <typename Number,
1913 typename MemorySpace>
1914 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1916 const primitive_type &riemann_data_i,
1917 const primitive_type &riemann_data_j) const
1918 {
1919 const auto &[rho_i, u_i, p_i, gamma_i, a_i] = riemann_data_i;
1920 const auto &[rho_j, u_j, p_j, gamma_j, a_j] = riemann_data_j;
1921 const auto alpha_i = alpha(rho_i, gamma_i, a_i);
1922 const auto alpha_j = alpha(rho_j, gamma_j, a_j);
1923
1924 /*
1925 * First get p_min, p_max.
1926 *
1927 * Then, we get gamma_min/max, and alpha_min/max. Note that the
1928 * *_min/max values are associated with p_min/max and are not
1929 * necessarily the minimum/maximum of *_i vs *_j.
1930 */
1931
1932 const Number p_min = std::min(p_i, p_j);
1933 const Number p_max = std::max(p_i, p_j);
1934
1935 const Number gamma_min =
1936 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1937 p_i, p_j, gamma_i, gamma_j);
1938
1939 const Number alpha_min =
1940 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1941 p_i, p_j, alpha_i, alpha_j);
1942
1943 const Number alpha_hat_min = c(gamma_min) * alpha_min;
1944
1945 const Number alpha_max = ryujin::compare_and_apply_mask<
1946 dealii::SIMDComparison::greater_than_or_equal>(
1947 p_i, p_j, alpha_i, alpha_j);
1948
1949 const Number gamma_m = std::min(gamma_i, gamma_j);
1950 const Number gamma_M = std::max(gamma_i, gamma_j);
1951
1952 const Number numerator =
1953 ryujin::compare_and_apply_mask<dealii::SIMDComparison::equal>(
1954 shift(p_max),
1955 Number(0.),
1956 Number(0.),
1957 positive_part(alpha_hat_min + alpha_max - (u_j - u_i)));
1958
1959 /*
1960 * The admissible set is p_min >= pinf. But numerically let's avoid
1961 * division by zero and ensure positivity:
1962 */
1963 const Number p_ratio = safe_division(shift(p_min), shift(p_max));
1964
1965 /*
1966 * Here, we use a trick: The r-factor only shows up in the formula
1967 * for the case \gamma_min = \gamma_m, otherwise the r-factor
1968 * vanishes. We can accomplish this by using the following modified
1969 * exponent (where we substitute gamma_m by gamma_min):
1970 */
1971 const Number r_exponent =
1972 (gamma_M - gamma_min) / (ScalarNumber(2.) * gamma_min * gamma_M);
1973
1974 /*
1975 * Compute (5.7) first formula for \tilde p_1^\ast and (5.8)
1976 * second formula for \tilde p_2^\ast at the same time:
1977 */
1978
1979 const Number first_exponent =
1980 (gamma_M - Number(1.)) / (ScalarNumber(2.) * gamma_M);
1981
1982 const Number first_exponent_inverse =
1983 safe_division(Number(1.), first_exponent);
1984
1985 const Number first_denom =
1986 alpha_hat_min * ryujin::pow(p_ratio, r_exponent - first_exponent) +
1987 alpha_max;
1988
1989 const Number p_1_tilde = unshift(
1990 shift(p_max) * ryujin::pow(safe_division(numerator, first_denom),
1991 first_exponent_inverse));
1992
1993 /*
1994 * Compute (5.7) second formula for \tilde p_2^\ast and (5.8) first
1995 * formula for \tilde p_1^\ast at the same time:
1996 */
1997
1998 const Number second_exponent =
1999 (gamma_m - Number(1.)) / (ScalarNumber(2.) * gamma_m);
2000
2001 const Number second_exponent_inverse =
2002 safe_division(Number(1.), second_exponent);
2003
2004 Number second_denom =
2005 alpha_hat_min * ryujin::pow(p_ratio, -second_exponent) +
2006 alpha_max * ryujin::pow(p_ratio, r_exponent);
2007
2008 const Number p_2_tilde = unshift(
2009 shift(p_max) * ryujin::pow(safe_division(numerator, second_denom),
2010 second_exponent_inverse));
2011
2012 const Number p_star = std::min(p_1_tilde, p_2_tilde);
2013
2014#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
2015 std::cout << "p_star_RS_full = " << p_star << std::endl;
2016#endif
2017 return p_star;
2018 }
2019
2020
2021 template <typename Number,
2023 typename MemorySpace>
2024 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
2026 const primitive_type &riemann_data_i,
2027 const primitive_type &riemann_data_j) const
2028 {
2029 const auto &[rho_i, u_i, p_i, gamma_i, a_i] = riemann_data_i;
2030 const auto &[rho_j, u_j, p_j, gamma_j, a_j] = riemann_data_j;
2031
2032 const Number gamma_m = std::min(gamma_i, gamma_j);
2033
2034 const Number alpha_hat_i = c(gamma_i) * alpha(rho_i, gamma_i, a_i);
2035 const Number alpha_hat_j = c(gamma_j) * alpha(rho_j, gamma_j, a_j);
2036
2037 /*
2038 * Compute (5.10) formula for \tilde p_1^\ast:
2039 *
2040 * Cost: 2x pow, 4x division, 0x sqrt
2041 */
2042
2043 const Number exponent =
2044 (gamma_m - Number(1.)) / (ScalarNumber(2.) * gamma_m);
2045 const Number exponent_inverse = Number(1.) / exponent;
2046
2047 const Number numerator =
2048 ryujin::compare_and_apply_mask<dealii::SIMDComparison::equal>(
2049 shift(p_j),
2050 Number(0.),
2051 Number(0.),
2052 positive_part(alpha_hat_i + alpha_hat_j - (u_j - u_i)));
2053
2054 const Number denominator =
2055 alpha_hat_i *
2056 ryujin::pow(safe_division(shift(p_i), shift(p_j)), -exponent) +
2057 alpha_hat_j;
2058
2059 const Number p_1_tilde = unshift(
2060 shift(p_j) *
2061 ryujin::pow(safe_division(numerator, denominator), exponent_inverse));
2062
2063 const auto p_2_tilde = p_star_failsafe(riemann_data_i, riemann_data_j);
2064
2065 const Number p_star = std::min(p_1_tilde, p_2_tilde);
2066
2067#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
2068 std::cout << "p_star_SS_full = " << p_star << std::endl;
2069#endif
2070 return p_star;
2071 }
2072
2073
2074 template <typename Number,
2076 typename MemorySpace>
2077 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
2079 const primitive_type &riemann_data_i,
2080 const primitive_type &riemann_data_j) const
2081 {
2082 const auto &[rho_i, u_i, p_i, gamma_Z_i, a_i] = riemann_data_i;
2083 const auto &[rho_j, u_j, p_j, gamma_Z_j, a_j] = riemann_data_j;
2084 const auto gamma_i = gamma_of(riemann_data_i);
2085 const auto gamma_j = gamma_of(riemann_data_j);
2086
2087 /*
2088 * Compute (5.11) formula for \tilde p_2^\ast:
2089 *
2090 * Cost: 0x pow, 3x division, 3x sqrt
2091 */
2092
2093 const Number p_max = shift(std::max(p_i, p_j));
2094
2095 const Number radicand_i =
2096 safe_division(ScalarNumber(2.) * one_minus_b_rho(rho_i) * p_max,
2097 rho_i * ((gamma_i + Number(1.)) * p_max +
2098 (gamma_i - Number(1.)) * shift(p_i)));
2099
2100 const Number x_i = std::sqrt(radicand_i);
2101
2102 const Number radicand_j =
2103 safe_division(ScalarNumber(2.) * one_minus_b_rho(rho_j) * p_max,
2104 rho_j * ((gamma_j + Number(1.)) * p_max +
2105 (gamma_j - Number(1.)) * shift(p_j)));
2106
2107 const Number x_j = std::sqrt(radicand_j);
2108
2109 const Number a = x_i + x_j;
2110 const Number b =
2111 ryujin::compare_and_apply_mask<dealii::SIMDComparison::equal>(
2112 a, Number(0.), Number(0.), u_j - u_i);
2113
2114 const Number c = -shift(p_i) * x_i - shift(p_j) * x_j;
2115
2116 const Number base = safe_division(
2117 std::abs(-b +
2118 std::sqrt(positive_part(b * b - ScalarNumber(4.) * a * c))),
2119 std::abs(ScalarNumber(2.) * a));
2120
2121 const Number p_2_tilde = unshift(base * base);
2122
2123#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
2124 std::cout << "p_star_failsafe = " << p_2_tilde << std::endl;
2125#endif
2126 return p_2_tilde;
2127 }
2128
2129
2130 template <typename Number,
2132 typename MemorySpace>
2133 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
2135 const primitive_type &riemann_data_i,
2136 const primitive_type &riemann_data_j) const
2137 {
2138 /*
2139 * With e_m = (gamma_m - 1) / (2 gamma_m), where gamma_m is the minimum
2140 * of gamma_i and gamma_j, we have (P / P_Z)^{e_Z} <= (P / P_Z)^{e_m}
2141 * for P <= P_Z. Thus, in the two rarefaction case phi is bounded from
2142 * above by a function whose root is
2143 *
2144 * P_min (N / D)^{1/e_m},
2145 * N = alpha_min + alpha_max - (u_j - u_i),
2146 * D = alpha_min + alpha_max (P_min / P_max)^{e_m}.
2147 */
2148
2149 const auto &[rho_i, u_i, p_i, gamma_Z_i, a_i] = riemann_data_i;
2150 const auto &[rho_j, u_j, p_j, gamma_Z_j, a_j] = riemann_data_j;
2151 const auto gamma_i = gamma_of(riemann_data_i);
2152 const auto gamma_j = gamma_of(riemann_data_j);
2153
2154 const Number alpha_i = alpha(rho_i, Number(gamma_i), a_i);
2155 const Number alpha_j = alpha(rho_j, Number(gamma_j), a_j);
2156
2157 const Number p_min = shift(std::min(p_i, p_j));
2158 const Number p_max = shift(std::max(p_i, p_j));
2159
2160 const Number alpha_min =
2161 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
2162 p_i, p_j, alpha_i, alpha_j);
2163
2164 const Number alpha_max = ryujin::compare_and_apply_mask<
2165 dealii::SIMDComparison::greater_than_or_equal>(
2166 p_i, p_j, alpha_i, alpha_j);
2167
2168 Number exponent;
2169 Number exponent_inverse;
2170 if constexpr (options.variable_gamma) {
2171 const Number gamma_m = std::min(gamma_i, gamma_j);
2172 exponent = (gamma_m - Number(1.)) / (ScalarNumber(2.) * gamma_m);
2173 exponent_inverse = Number(1.) / exponent;
2174 } else {
2175 exponent = rarefaction_exponent(riemann_data_i);
2176 exponent_inverse = rarefaction_exponent_inverse(riemann_data_i);
2177 }
2178
2179 const Number numerator =
2180 positive_part(alpha_min + alpha_max - (u_j - u_i));
2181
2182 const Number denominator =
2183 alpha_min +
2184 alpha_max * ryujin::pow(safe_division(p_min, p_max), exponent);
2185
2186 const Number p_tilde =
2187 unshift(p_min * ryujin::pow(safe_division(numerator, denominator),
2188 exponent_inverse));
2189
2190#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
2191 std::cout << "p_star_two_rarefaction = " << p_tilde << std::endl;
2192#endif
2193 return p_tilde;
2194 }
2195
2196
2197 template <typename Number,
2199 typename MemorySpace>
2200 DEAL_II_HOST_DEVICE_ALWAYS_INLINE void
2202 const primitive_type &riemann_data_i,
2203 const primitive_type &riemann_data_j,
2204 Number &p_1,
2205 Number &p_2) const
2206 {
2207 // FIXME: Fuse these computations:
2208 const Number phi_p_1 = phi(riemann_data_i, riemann_data_j, p_1);
2209 const Number phi_p_2 = phi(riemann_data_i, riemann_data_j, p_2);
2210 const Number dphi_p_1 = dphi(riemann_data_i, riemann_data_j, p_1);
2211 const Number dphi_p_2 = dphi(riemann_data_i, riemann_data_j, p_2);
2212
2213#ifdef DEBUG_WAVE_SPEED_ESTIMATOR
2214 std::cout << "phi_p_1: " << phi_p_1 << std::endl;
2215 std::cout << "phi_p_2: " << phi_p_2 << std::endl;
2216 std::cout << "dphi_p_1: " << dphi_p_1 << std::endl;
2217 std::cout << "dphi_p_2: " << dphi_p_2 << std::endl;
2218#endif
2219
2221 p_1, p_2, phi_p_1, phi_p_2, dphi_p_1, dphi_p_2);
2222 }
2223
2224
2225 template <typename Number,
2227 typename MemorySpace>
2228 DEAL_II_HOST_DEVICE_ALWAYS_INLINE std::array<Number, 2>
2230 const primitive_type &riemann_data_i,
2231 const primitive_type &riemann_data_j,
2232 const Number p_1,
2233 const Number p_2) const
2234 {
2235 const Number nu_11 = lambda1_minus(riemann_data_i, p_2 /*SIC!*/);
2236 const Number nu_12 = lambda1_minus(riemann_data_i, p_1 /*SIC!*/);
2237
2238 const Number nu_31 = lambda3_plus(riemann_data_j, p_1);
2239 const Number nu_32 = lambda3_plus(riemann_data_j, p_2);
2240
2241 const Number lambda_max =
2242 std::max(positive_part(nu_32), negative_part(nu_11));
2243
2244 const Number gap =
2245 std::max(std::abs(nu_32 - nu_31), std::abs(nu_12 - nu_11));
2246
2247 return {{gap, lambda_max}};
2248 }
2249
2250
2251 template <typename Number,
2253 typename MemorySpace>
2254 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
2256 const primitive_type &riemann_data_i,
2257 const primitive_type &riemann_data_j,
2258 const Number p_star) const
2259 {
2260 const Number nu_11 = lambda1_minus(riemann_data_i, p_star);
2261 const Number nu_32 = lambda3_plus(riemann_data_j, p_star);
2262
2263 return std::max(positive_part(nu_32), negative_part(nu_11));
2264 }
2265
2266 } // namespace EulerAEOS
2267} // namespace ryujin
DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto half_gamma_minus_one(const primitive_type &riemann_data) const
DEAL_II_HOST_DEVICE primitive_type sample(const RiemannSolution &solution, const Number &xi, const unsigned int max_iterations=100) const
static DEAL_II_HOST_DEVICE_ALWAYS_INLINE T c(const T &gamma_Z)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE unsigned int newton_max_iterations() const
DEAL_II_HOST_DEVICE Number p_star_single_gamma(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number &phi_p_max) const
static constexpr unsigned int riemann_data_size
DEAL_II_HOST_DEVICE RiemannSolution solve(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const unsigned int max_iterations=100) const
DEAL_II_HOST_DEVICE Number dphi(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number &p) const
DEAL_II_HOST_DEVICE Number f(const primitive_type &riemann_data, const Number p_star) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto rarefaction_exponent(const primitive_type &riemann_data) const
DEAL_II_HOST_DEVICE RiemannSolution riemann_solution(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number p_star) const
DEAL_II_HOST_DEVICE Number p_star_upper_bound(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number &phi_p_max) const
DEAL_II_HOST_DEVICE Number p_star_interpolated(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
DEAL_II_HOST_DEVICE Number compute_lambda_max(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number p_star) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool compute_expensive_bounds() const
DEAL_II_HOST_DEVICE Number df(const primitive_type &riemann_data, const Number &p_star) const
DEAL_II_HOST_DEVICE void newton_step(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, Number &p_1, Number &p_2) const
DEAL_II_HOST_DEVICE Number lambda3_plus(const primitive_type &riemann_data, const Number p_star) const
NASGRiemannSolverView(const NASGRiemannSolver< ScalarNumber, options > &riemann_solver)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number shift(const Number &p) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number unshift(const Number &p) const
DEAL_II_HOST_DEVICE Number p_star_two_rarefaction(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number one_minus_b_rho(const Number &rho) const
DEAL_II_HOST_DEVICE Number p_star_SS_full(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
std::array< Number, riemann_data_size > primitive_type
DEAL_II_HOST_DEVICE Number rarefaction_fan_pressure(const primitive_type &riemann_data, const Number &xi, const ScalarNumber sign, const unsigned int max_iterations) const
typename NASGRiemannSolver< ScalarNumber, options >::Parameters Parameters
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber newton_tolerance() const
DEAL_II_HOST_DEVICE Number compute(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
DEAL_II_HOST_DEVICE Number phi(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number p_in) const
DEAL_II_HOST_DEVICE Number p_star_failsafe(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
DEAL_II_HOST_DEVICE std::array< Number, 2 > compute_gap(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j, const Number p_1, const Number p_2) const
DEAL_II_HOST_DEVICE Number phi_of_p_max(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
DEAL_II_HOST_DEVICE Number lambda1_minus(const primitive_type &riemann_data, const Number p_star) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber pinf() const
typename get_value_type< Number >::type ScalarNumber
DEAL_II_HOST_DEVICE Number alpha(const Number &rho, const Number &gamma, const Number &a) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber covolume_b() const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto c_of_gamma(const primitive_type &riemann_data) const
DEAL_II_HOST_DEVICE Number rho_star(const primitive_type &riemann_data, const Number &p_star) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto gamma_of(const primitive_type &riemann_data) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number safe_division(const Number &numerator, const Number &denominator) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto lambda_factor(const primitive_type &riemann_data) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto rarefaction_exponent_inverse(const primitive_type &riemann_data) const
DEAL_II_HOST_DEVICE Number p_star_RS_full(const primitive_type &riemann_data_i, const primitive_type &riemann_data_j) const
DEAL_II_HOST_DEVICE Number speed_of_sound(const Number &rho, const Number &p, const Number &gamma) const
void set_equation_of_state(const double covolume_b, const double pinf, const bool compute_expensive_bounds)
NASGRiemannSolver(const std::string &subsection)
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:134
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number negative_part(const Number number)
Definition simd.h:146
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:182
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number safe_division(const Number &numerator, const Number &denominator)
Definition simd.h:164