ryujin 2.1.1 revision d0a94ad2ccc0c4c2e8c2485c52b06b90e2fc9853
hyperbolic_system.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3// Copyright (C) 2020 - 2024 by the ryujin authors
4//
5
6#pragma once
7
8#include <compile_time_options.h>
10#include <discretization.h>
12#include <openmp.h>
13#include <patterns_conversion.h>
14#include <simd.h>
15
16#include <deal.II/base/parameter_acceptor.h>
17#include <deal.II/base/tensor.h>
18
19#include <array>
20
21namespace ryujin
22{
23 namespace Euler
24 {
25 template <int dim, typename Number>
26 class HyperbolicSystemView;
27
38 class HyperbolicSystem final : public dealii::ParameterAcceptor
39 {
40 public:
44 static inline const std::string problem_name =
45 "Compressible Euler equations (polytropic gas EOS, optimized)";
46
50 HyperbolicSystem(const std::string &subsection = "/HyperbolicSystem");
51
58 template <int dim, typename Number>
59 auto view() const
60 {
62 }
63
64 private:
69 double gamma_;
70
71 double reference_density_;
72 double vacuum_state_relaxation_small_;
73 double vacuum_state_relaxation_large_;
74
75 double gamma_inverse_;
76 double gamma_minus_one_inverse_;
77 double gamma_minus_one_over_gamma_plus_one_;
78 double gamma_plus_one_inverse_;
79
80 template <int dim, typename Number>
83 }; /* HyperbolicSystem */
84
85
102 template <int dim, typename Number>
104 {
105 public:
110 HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
111 : hyperbolic_system_(hyperbolic_system)
112 {
113 }
114
118 template <int dim2, typename Number2>
119 auto view() const
120 {
121 return HyperbolicSystemView<dim2, Number2>{hyperbolic_system_};
122 }
123
128
133
134 DEAL_II_ALWAYS_INLINE inline ScalarNumber gamma() const
135 {
136 return hyperbolic_system_.gamma_;
137 }
138
139 DEAL_II_ALWAYS_INLINE inline ScalarNumber reference_density() const
140 {
141 return hyperbolic_system_.reference_density_;
142 }
143
144 DEAL_II_ALWAYS_INLINE inline ScalarNumber
146 {
147 return hyperbolic_system_.vacuum_state_relaxation_small_;
148 }
149
150 DEAL_II_ALWAYS_INLINE inline ScalarNumber
152 {
153 return hyperbolic_system_.vacuum_state_relaxation_large_;
154 }
155
157
165
166 DEAL_II_ALWAYS_INLINE inline ScalarNumber gamma_inverse() const
167 {
168 return ScalarNumber(hyperbolic_system_.gamma_inverse_);
169 }
170
171 DEAL_II_ALWAYS_INLINE inline ScalarNumber gamma_plus_one_inverse() const
172 {
173 return ScalarNumber(hyperbolic_system_.gamma_plus_one_inverse_);
174 }
175
176 DEAL_II_ALWAYS_INLINE inline ScalarNumber gamma_minus_one_inverse() const
177 {
178 return ScalarNumber(hyperbolic_system_.gamma_minus_one_inverse_);
179 }
180
181 DEAL_II_ALWAYS_INLINE inline ScalarNumber
183 {
184 return ScalarNumber(
185 hyperbolic_system_.gamma_minus_one_over_gamma_plus_one_);
186 }
187
191 static constexpr bool have_gamma = true;
192
196 static constexpr bool have_eos_interpolation_b = false;
197
199
203
204 private:
205 const HyperbolicSystem &hyperbolic_system_;
206
207 public:
209
213
217 static constexpr unsigned int problem_dimension = 2 + dim;
218
222 using state_type = dealii::Tensor<1, problem_dimension, Number>;
223
228
233 static inline const auto component_names =
234 []() -> std::array<std::string, problem_dimension> {
235 if constexpr (dim == 1)
236 return {"rho", "m", "E"};
237 else if constexpr (dim == 2)
238 return {"rho", "m_1", "m_2", "E"};
239 else if constexpr (dim == 3)
240 return {"rho", "m_1", "m_2", "m_3", "E"};
241 __builtin_trap();
242 }();
243
248 static inline const auto primitive_component_names =
249 []() -> std::array<std::string, problem_dimension> {
250 if constexpr (dim == 1)
251 return {"rho", "v", "p"};
252 else if constexpr (dim == 2)
253 return {"rho", "v_1", "v_2", "p"};
254 else if constexpr (dim == 3)
255 return {"rho", "v_1", "v_2", "v_3", "p"};
256 __builtin_trap();
257 }();
258
262 using flux_type =
263 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
264
269
271
275
279 static constexpr unsigned int n_precomputed_initial_values = 0;
280
285 std::array<Number, n_precomputed_initial_values>;
286
293
297 static inline const auto precomputed_initial_names =
298 std::array<std::string, n_precomputed_initial_values>{};
299
303 static constexpr unsigned int n_precomputed_values = 2;
304
308 using precomputed_state_type = std::array<Number, n_precomputed_values>;
309
315
319 static inline const auto precomputed_names =
320 std::array<std::string, n_precomputed_values>{"s", "eta_h"};
321
325 static constexpr unsigned int n_precomputation_cycles = 1;
326
331 template <typename DISPATCH, typename SPARSITY>
332 void precomputation_loop(unsigned int cycle,
333 const DISPATCH &dispatch_check,
334 precomputed_vector_type &precomputed_values,
335 const SPARSITY &sparsity_simd,
336 const vector_type &U,
337 unsigned int left,
338 unsigned int right) const;
339
341
345
350 static Number density(const state_type &U);
351
358 Number filter_vacuum_density(const Number &rho) const;
359
364 static dealii::Tensor<1, dim, Number> momentum(const state_type &U);
365
370 static Number total_energy(const state_type &U);
371
376 static Number internal_energy(const state_type &U);
377
384
395 Number pressure(const state_type &U) const;
396
404 Number speed_of_sound(const state_type &U) const;
405
413 Number specific_entropy(const state_type &U) const;
414
422 Number harten_entropy(const state_type &U) const;
423
432
437 Number mathematical_entropy(const state_type &U) const;
438
445
451 bool is_admissible(const state_type &U) const;
452
454
458
464 template <int component>
465 std::array<state_type, 2> linearized_eigenvector(
466 const state_type &U,
467 const dealii::Tensor<1, dim, Number> &normal) const;
468
475 template <int component>
477 const state_type &U,
478 const state_type &U_bar,
479 const dealii::Tensor<1, dim, Number> &normal) const;
480
499 template <typename Lambda>
501 apply_boundary_conditions(const dealii::types::boundary_id id,
502 const state_type &U,
503 const dealii::Tensor<1, dim, Number> &normal,
504 const Lambda &get_dirichlet_data) const;
505
507
511
522 flux_type f(const state_type &U) const;
523
546 const unsigned int i,
547 const state_type &U_i) const;
548
552 const unsigned int *js,
553 const state_type &U_j) const;
554
561 const flux_contribution_type &flux_j,
562 const dealii::Tensor<1, dim, Number> &c_ij) const;
563
565 static constexpr bool have_high_order_flux = false;
566
568 const flux_contribution_type &flux_i,
569 const flux_contribution_type &flux_j,
570 const dealii::Tensor<1, dim, Number> &c_ij) const = delete;
571
573
577
579 static constexpr bool have_source_terms = false;
580
582 const unsigned int i,
583 const state_type &U_i,
584 const ScalarNumber tau) const = delete;
585
587 const unsigned int *js,
588 const state_type &U_j,
589 const ScalarNumber tau) const = delete;
590
592
596
607 template <typename ST>
608 state_type expand_state(const ST &state) const;
609
623 template <typename ST>
624 state_type from_initial_state(const ST &initial_state) const;
625
630 state_type from_primitive_state(const state_type &primitive_state) const;
631
636 state_type to_primitive_state(const state_type &state) const;
637
643 template <typename Lambda>
645 const Lambda &lambda) const;
647 }; /* HyperbolicSystemView */
648
649
650 /*
651 * -------------------------------------------------------------------------
652 * Inline definitions
653 * -------------------------------------------------------------------------
654 */
655
656
657 inline HyperbolicSystem::HyperbolicSystem(const std::string &subsection)
658 : ParameterAcceptor(subsection)
659 {
660 gamma_ = 7. / 5.;
661 add_parameter("gamma", gamma_, "The ratio of specific heats");
662
663 reference_density_ = 1.;
664 add_parameter("reference density",
665 reference_density_,
666 "Problem specific density reference");
667
668 vacuum_state_relaxation_small_ = 1.e2;
669 add_parameter("vacuum state relaxation small",
670 vacuum_state_relaxation_small_,
671 "Problem specific vacuum relaxation parameter");
672
673 vacuum_state_relaxation_large_ = 1.e4;
674 add_parameter("vacuum state relaxation large",
675 vacuum_state_relaxation_large_,
676 "Problem specific vacuum relaxation parameter");
677
678 /*
679 * Precompute a number of derived gamma coefficients that contain
680 * divisions:
681 */
682 const auto compute_inverses = [this] {
683 gamma_inverse_ = 1. / gamma_;
684 gamma_plus_one_inverse_ = 1. / (gamma_ + 1.);
685 gamma_minus_one_inverse_ = 1. / (gamma_ - 1.);
686 gamma_minus_one_over_gamma_plus_one_ = (gamma_ - 1.) / (gamma_ + 1.);
687 };
688
689 compute_inverses();
690 ParameterAcceptor::parse_parameters_call_back.connect(compute_inverses);
691 }
692
693
694 template <int dim, typename Number>
695 template <typename DISPATCH, typename SPARSITY>
696 DEAL_II_ALWAYS_INLINE inline void
698 unsigned int cycle [[maybe_unused]],
699 const DISPATCH &dispatch_check,
700 precomputed_vector_type &precomputed_values,
701 const SPARSITY &sparsity_simd,
702 const vector_type &U,
703 unsigned int left,
704 unsigned int right) const
705 {
706 Assert(cycle == 0, dealii::ExcInternalError());
707
708 /* We are inside a thread parallel context */
709
710 unsigned int stride_size = get_stride_size<Number>;
711
713 for (unsigned int i = left; i < right; i += stride_size) {
714
715 /* Skip constrained degrees of freedom: */
716 const unsigned int row_length = sparsity_simd.row_length(i);
717 if (row_length == 1)
718 continue;
719
720 dispatch_check(i);
721
722 const auto U_i = U.template get_tensor<Number>(i);
723 const precomputed_state_type prec_i{specific_entropy(U_i),
724 harten_entropy(U_i)};
725 precomputed_values.template write_tensor<Number>(prec_i, i);
726 }
727 }
728
729
730 template <int dim, typename Number>
731 DEAL_II_ALWAYS_INLINE inline Number
733 {
734 return U[0];
735 }
736
737
738 template <int dim, typename Number>
739 DEAL_II_ALWAYS_INLINE inline Number
741 const Number &rho) const
742 {
743 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
744 const Number rho_cutoff_large =
745 reference_density() * vacuum_state_relaxation_large() * eps;
746
747 return dealii::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
748 std::abs(rho), rho_cutoff_large, Number(0.), rho);
749 }
750
751
752 template <int dim, typename Number>
753 DEAL_II_ALWAYS_INLINE inline dealii::Tensor<1, dim, Number>
755 {
756 dealii::Tensor<1, dim, Number> result;
757 for (unsigned int i = 0; i < dim; ++i)
758 result[i] = U[1 + i];
759 return result;
760 }
761
762
763 template <int dim, typename Number>
764 DEAL_II_ALWAYS_INLINE inline Number
766 {
767 return U[1 + dim];
768 }
769
770
771 template <int dim, typename Number>
772 DEAL_II_ALWAYS_INLINE inline Number
774 {
775 /*
776 * rho e = (E - 1/2*m^2/rho)
777 */
778 const Number rho_inverse = ScalarNumber(1.) / density(U);
779 const auto m = momentum(U);
780 const Number E = total_energy(U);
781 return E - ScalarNumber(0.5) * m.norm_square() * rho_inverse;
782 }
783
784
785 template <int dim, typename Number>
786 DEAL_II_ALWAYS_INLINE inline auto
788 const state_type &U) -> state_type
789 {
790 /*
791 * With
792 * rho e = E - 1/2 |m|^2 / rho
793 * we get
794 * (rho e)' = (1/2m^2/rho^2, -m/rho , 1 )^T
795 */
796
797 const Number rho_inverse = ScalarNumber(1.) / density(U);
798 const auto u = momentum(U) * rho_inverse;
799
800 state_type result;
801
802 result[0] = ScalarNumber(0.5) * u.norm_square();
803 for (unsigned int i = 0; i < dim; ++i) {
804 result[1 + i] = -u[i];
805 }
806 result[dim + 1] = ScalarNumber(1.);
807
808 return result;
809 }
810
811
812 template <int dim, typename Number>
813 DEAL_II_ALWAYS_INLINE inline Number
815 {
816 /* p = (gamma - 1) * (rho e) */
817 return (gamma() - ScalarNumber(1.)) * internal_energy(U);
818 }
819
820
821 template <int dim, typename Number>
822 DEAL_II_ALWAYS_INLINE inline Number
824 {
825 /* c^2 = gamma * p / rho */
826 const Number rho_inverse = ScalarNumber(1.) / density(U);
827 const Number p = pressure(U);
828 return std::sqrt(gamma() * p * rho_inverse);
829 }
830
831
832 template <int dim, typename Number>
833 DEAL_II_ALWAYS_INLINE inline Number
835 const state_type &U) const
836 {
837 /* exp((gamma - 1)s) = (rho e) / rho ^ gamma */
838 const auto rho_inverse = ScalarNumber(1.) / density(U);
839 return internal_energy(U) * ryujin::pow(rho_inverse, gamma());
840 }
841
842
843 template <int dim, typename Number>
844 DEAL_II_ALWAYS_INLINE inline Number
846 {
847 /* rho^2 e = \rho E - 1/2*m^2 */
848
849 const Number rho = density(U);
850 const auto m = momentum(U);
851 const Number E = total_energy(U);
852
853 const Number rho_rho_e = rho * E - ScalarNumber(0.5) * m.norm_square();
854 return ryujin::pow(rho_rho_e, gamma_plus_one_inverse());
855 }
856
857
858 template <int dim, typename Number>
859 DEAL_II_ALWAYS_INLINE inline auto
861 const state_type &U) const -> state_type
862 {
863 /*
864 * With
865 * eta = (rho^2 e) ^ 1/(gamma+1)
866 * rho^2 e = rho * E - 1/2 |m|^2
867 *
868 * we get
869 *
870 * eta' = 1/(gamma+1) * (rho^2 e) ^ -gamma/(gamma+1) * (E,-m,rho)^T
871 *
872 */
873
874 const Number rho = density(U);
875 const auto m = momentum(U);
876 const Number E = total_energy(U);
877
878 const Number rho_rho_e = rho * E - ScalarNumber(0.5) * m.norm_square();
879
880 const auto factor =
881 gamma_plus_one_inverse() *
882 ryujin::pow(rho_rho_e, -gamma() * gamma_plus_one_inverse());
883
884 state_type result;
885
886 result[0] = factor * E;
887 for (unsigned int i = 0; i < dim; ++i)
888 result[1 + i] = -factor * m[i];
889 result[dim + 1] = factor * rho;
890
891 return result;
892 }
893
894
895 template <int dim, typename Number>
896 DEAL_II_ALWAYS_INLINE inline Number
898 const state_type &U) const
899 {
901 const auto p = pressure(U);
902 return ryujin::pow(p, gamma_inverse());
903 }
904
905
906 template <int dim, typename Number>
907 DEAL_II_ALWAYS_INLINE inline auto
909 const state_type &U) const -> state_type
910 {
911 /*
912 * With
913 * eta = p ^ (1/gamma)
914 * p = (gamma - 1) * (rho e)
915 * rho e = E - 1/2 |m|^2 / rho
916 *
917 * we get
918 *
919 * eta' = (gamma - 1)/gamma p ^(1/gamma - 1) *
920 *
921 * (1/2m^2/rho^2 , -m/rho , 1 )^T
922 */
923 const Number rho = density(U);
924 const Number rho_inverse = ScalarNumber(1.) / rho;
925 const auto u = momentum(U) * rho_inverse;
926 const auto p = pressure(U);
927
928 const auto factor = (gamma() - ScalarNumber(1.0)) * gamma_inverse() *
929 ryujin::pow(p, gamma_inverse() - ScalarNumber(1.));
930
931 state_type result;
932
933 result[0] = factor * ScalarNumber(0.5) * u.norm_square();
934 result[dim + 1] = factor;
935 for (unsigned int i = 0; i < dim; ++i) {
936 result[1 + i] = -factor * u[i];
937 }
938
939 return result;
940 }
941
942
943 template <int dim, typename Number>
944 DEAL_II_ALWAYS_INLINE inline bool
946 {
947 const auto rho_new = density(U);
948 const auto e_new = internal_energy(U);
949 const auto s_new = specific_entropy(U);
950
951 constexpr auto gt = dealii::SIMDComparison::greater_than;
952 using T = Number;
953 const auto test =
954 dealii::compare_and_apply_mask<gt>(rho_new, T(0.), T(0.), T(-1.)) + //
955 dealii::compare_and_apply_mask<gt>(e_new, T(0.), T(0.), T(-1.)) + //
956 dealii::compare_and_apply_mask<gt>(s_new, T(0.), T(0.), T(-1.));
957
958#ifdef DEBUG_OUTPUT
959 if (!(test == Number(0.))) {
960 std::cout << std::fixed << std::setprecision(16);
961 std::cout << "Bounds violation: Negative state [rho, e, s] detected!\n";
962 std::cout << "\t\trho: " << rho_new << "\n";
963 std::cout << "\t\tint: " << e_new << "\n";
964 std::cout << "\t\tent: " << s_new << "\n" << std::endl;
965 }
966#endif
967
968 return (test == Number(0.));
969 }
970
971
972 template <int dim, typename Number>
973 template <int component>
974 DEAL_II_ALWAYS_INLINE inline auto
976 const state_type &U, const dealii::Tensor<1, dim, Number> &normal) const
977 -> std::array<state_type, 2>
978 {
979 static_assert(component == 1 || component == problem_dimension,
980 "Only first and last eigenvectors implemented");
981
982 const auto rho = density(U);
983 const auto m = momentum(U);
984 const auto v = m / rho;
985 const auto a = speed_of_sound(U);
986 const auto gamma = this->gamma();
987
988 state_type b;
989 state_type c;
990
991 const auto e_k = 0.5 * v.norm_square();
992
993 switch (component) {
994 case 1:
995 b[0] = (gamma - 1.) * e_k + a * v * normal;
996 for (unsigned int i = 0; i < dim; ++i)
997 b[1 + i] = (1. - gamma) * v[i] - a * normal[i];
998 b[dim + 1] = gamma - 1.;
999 b /= 2. * a * a;
1000
1001 c[0] = 1.;
1002 for (unsigned int i = 0; i < dim; ++i)
1003 c[1 + i] = v[i] - a * normal[i];
1004 c[dim + 1] = a * a / (gamma - 1) + e_k - a * (v * normal);
1005
1006 return {b, c};
1007
1008 case problem_dimension:
1009 b[0] = (gamma - 1.) * e_k - a * v * normal;
1010 for (unsigned int i = 0; i < dim; ++i)
1011 b[1 + i] = (1. - gamma) * v[i] + a * normal[i];
1012 b[dim + 1] = gamma - 1.;
1013 b /= 2. * a * a;
1014
1015 c[0] = 1.;
1016 for (unsigned int i = 0; i < dim; ++i)
1017 c[1 + i] = v[i] + a * normal[i];
1018 c[dim + 1] = a * a / (gamma - 1) + e_k + a * (v * normal);
1019
1020 return {b, c};
1021 }
1022
1023 __builtin_unreachable();
1024 }
1025
1026
1027 template <int dim, typename Number>
1028 template <int component>
1029 DEAL_II_ALWAYS_INLINE inline auto
1031 const state_type &U,
1032 const state_type &U_bar,
1033 const dealii::Tensor<1, dim, Number> &normal) const -> state_type
1034 {
1035 static_assert(component == 1 || component == 2,
1036 "component has to be 1 or 2");
1037
1038 const auto m = momentum(U);
1039 const auto rho = density(U);
1040 const auto a = speed_of_sound(U);
1041 const auto vn = m * normal / rho;
1042
1043 const auto m_bar = momentum(U_bar);
1044 const auto rho_bar = density(U_bar);
1045 const auto a_bar = speed_of_sound(U_bar);
1046 const auto vn_bar = m_bar * normal / rho_bar;
1047
1048 /* First Riemann characteristic: v* n - 2 / (gamma - 1) * a */
1049
1050 const auto R_1 = component == 1
1051 ? vn_bar - 2. * a_bar / (gamma() - ScalarNumber(1.))
1052 : vn - 2. * a / (gamma() - ScalarNumber(1.));
1053
1054 /* Second Riemann characteristic: v* n + 2 / (gamma() - 1) * a */
1055
1056 const auto R_2 = component == 2
1057 ? vn_bar + 2. * a_bar / (gamma() - ScalarNumber(1.))
1058 : vn + 2. * a / (gamma() - ScalarNumber(1.));
1059
1060 const auto p = pressure(U);
1061 const auto s = p / ryujin::pow(rho, gamma());
1062
1063 const auto vperp = m / rho - vn * normal;
1064
1065 const auto vn_new = 0.5 * (R_1 + R_2);
1066
1067 auto rho_new = 1. / (gamma() * s) *
1068 ryujin::fixed_power<2>(ScalarNumber((gamma() - 1.) / 4.) *
1069 (R_2 - R_1));
1070 rho_new = ryujin::pow(rho_new, 1. / (gamma() - 1.));
1071
1072 const auto p_new = s * std::pow(rho_new, gamma());
1073
1074 state_type U_new;
1075 U_new[0] = rho_new;
1076 for (unsigned int d = 0; d < dim; ++d) {
1077 U_new[1 + d] = rho_new * (vn_new * normal + vperp)[d];
1078 }
1079 U_new[1 + dim] = p_new / ScalarNumber(gamma() - 1.) +
1080 0.5 * rho_new * (vn_new * vn_new + vperp.norm_square());
1081
1082 return U_new;
1083 }
1084
1085
1086 template <int dim, typename Number>
1087 template <typename Lambda>
1088 DEAL_II_ALWAYS_INLINE inline auto
1090 dealii::types::boundary_id id,
1091 const state_type &U,
1092 const dealii::Tensor<1, dim, Number> &normal,
1093 const Lambda &get_dirichlet_data) const -> state_type
1094 {
1095 state_type result = U;
1096
1097 if (id == Boundary::dirichlet) {
1098 result = get_dirichlet_data();
1099
1100 } else if (id == Boundary::slip) {
1101 auto m = momentum(U);
1102 m -= 1. * (m * normal) * normal;
1103 for (unsigned int k = 0; k < dim; ++k)
1104 result[k + 1] = m[k];
1105
1106 } else if (id == Boundary::no_slip) {
1107 for (unsigned int k = 0; k < dim; ++k)
1108 result[k + 1] = Number(0.);
1109
1110 } else if (id == Boundary::dynamic) {
1111 /*
1112 * On dynamic boundary conditions, we distinguish four cases:
1113 *
1114 * - supersonic inflow: prescribe full state
1115 * - subsonic inflow:
1116 * decompose into Riemann invariants and leave R_2
1117 * characteristic untouched.
1118 * - supersonic outflow: do nothing
1119 * - subsonic outflow:
1120 * decompose into Riemann invariants and prescribe incoming
1121 * R_1 characteristic.
1122 */
1123 const auto m = momentum(U);
1124 const auto rho = density(U);
1125 const auto a = speed_of_sound(U);
1126 const auto vn = m * normal / rho;
1127
1128 /* Supersonic inflow: */
1129 if (vn < -a) {
1130 result = get_dirichlet_data();
1131 }
1132
1133 /* Subsonic inflow: */
1134 if (vn >= -a && vn <= 0.) {
1135 const auto U_dirichlet = get_dirichlet_data();
1136 result = prescribe_riemann_characteristic<2>(U_dirichlet, U, normal);
1137 }
1138
1139 /* Subsonic outflow: */
1140 if (vn > 0. && vn <= a) {
1141 const auto U_dirichlet = get_dirichlet_data();
1142 result = prescribe_riemann_characteristic<1>(U, U_dirichlet, normal);
1143 }
1144
1145 /* Supersonic outflow: do nothing, i.e., keep U as is */
1146 }
1147
1148 return result;
1149 }
1150
1151
1152 template <int dim, typename Number>
1153 DEAL_II_ALWAYS_INLINE inline auto
1155 {
1156 const auto rho_inverse = ScalarNumber(1.) / density(U);
1157 const auto m = momentum(U);
1158 const auto p = pressure(U);
1159 const auto E = total_energy(U);
1160
1161 flux_type result;
1162
1163 result[0] = m;
1164 for (unsigned int i = 0; i < dim; ++i) {
1165 result[1 + i] = m * (m[i] * rho_inverse);
1166 result[1 + i][i] += p;
1167 }
1168 result[dim + 1] = m * (rho_inverse * (E + p));
1169
1170 return result;
1171 }
1172
1173
1174 template <int dim, typename Number>
1175 DEAL_II_ALWAYS_INLINE inline auto
1177 const precomputed_vector_type & /*pv*/,
1178 const precomputed_initial_vector_type & /*piv*/,
1179 const unsigned int /*i*/,
1180 const state_type &U_i) const -> flux_contribution_type
1181 {
1182 return f(U_i);
1183 }
1184
1185
1186 template <int dim, typename Number>
1187 DEAL_II_ALWAYS_INLINE inline auto
1189 const precomputed_vector_type & /*pv*/,
1190 const precomputed_initial_vector_type & /*piv*/,
1191 const unsigned int * /*js*/,
1192 const state_type &U_j) const -> flux_contribution_type
1193 {
1194 return f(U_j);
1195 }
1196
1197
1198 template <int dim, typename Number>
1199 DEAL_II_ALWAYS_INLINE inline auto
1201 const flux_contribution_type &flux_i,
1202 const flux_contribution_type &flux_j,
1203 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1204 {
1205 return -contract(add(flux_i, flux_j), c_ij);
1206 }
1207
1208
1209 template <int dim, typename Number>
1210 template <typename ST>
1212 -> state_type
1213 {
1214 using T = typename ST::value_type;
1215 static_assert(std::is_same_v<Number, T>, "template mismatch");
1216
1217 constexpr auto dim2 = ST::dimension - 2;
1218 static_assert(dim >= dim2,
1219 "the space dimension of the argument state must not be "
1220 "larger than the one of the target state");
1221
1222 state_type result;
1223 result[0] = state[0];
1224 result[dim + 1] = state[dim2 + 1];
1225 for (unsigned int i = 1; i < dim2 + 1; ++i)
1226 result[i] = state[i];
1227
1228 return result;
1229 }
1230
1231
1232 template <int dim, typename Number>
1233 template <typename ST>
1234 DEAL_II_ALWAYS_INLINE inline auto
1236 const ST &initial_state) const -> state_type
1237 {
1238 const auto primitive_state = expand_state(initial_state);
1239 return from_primitive_state(primitive_state);
1240 }
1241
1242
1243 template <int dim, typename Number>
1244 DEAL_II_ALWAYS_INLINE inline auto
1246 const state_type &primitive_state) const -> state_type
1247 {
1248 const auto &rho = primitive_state[0];
1249 /* extract velocity: */
1250 const auto u = /*SIC!*/ momentum(primitive_state);
1251 const auto &p = primitive_state[dim + 1];
1252
1253 auto state = primitive_state;
1254 /* Fix up momentum: */
1255 for (unsigned int i = 1; i < dim + 1; ++i)
1256 state[i] *= rho;
1257 /* Compute total energy: */
1258 state[dim + 1] =
1259 p / (ScalarNumber(gamma() - 1.)) + Number(0.5) * rho * u * u;
1260
1261 return state;
1262 }
1263
1264
1265 template <int dim, typename Number>
1266 DEAL_II_ALWAYS_INLINE inline auto
1268 const state_type &state) const -> state_type
1269 {
1270 const auto &rho = state[0];
1271 const auto rho_inverse = Number(1.) / rho;
1272 const auto p = pressure(state);
1273
1274 auto primitive_state = state;
1275 /* Fix up velocity: */
1276 for (unsigned int i = 1; i < dim + 1; ++i)
1277 primitive_state[i] *= rho_inverse;
1278 /* Set pressure: */
1279 primitive_state[dim + 1] = p;
1280
1281 return primitive_state;
1282 }
1283
1284
1285 template <int dim, typename Number>
1286 template <typename Lambda>
1288 const state_type &state, const Lambda &lambda) const -> state_type
1289 {
1290 auto result = state;
1291 const auto M = lambda(momentum(state));
1292 for (unsigned int d = 0; d < dim; ++d)
1293 result[1 + d] = M[d];
1294 return result;
1295 }
1296
1297 } // namespace Euler
1298} // namespace ryujin
typename get_value_type< Number >::type ScalarNumber
static constexpr bool have_eos_interpolation_b
state_type from_initial_state(const ST &initial_state) const
std::array< Number, n_precomputed_initial_values > precomputed_initial_state_type
static Number internal_energy(const state_type &U)
state_type from_primitive_state(const state_type &primitive_state) const
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
static constexpr unsigned int n_precomputed_initial_values
Number harten_entropy(const state_type &U) const
std::array< Number, n_precomputed_values > precomputed_state_type
state_type high_order_flux_divergence(const flux_contribution_type &flux_i, const flux_contribution_type &flux_j, const dealii::Tensor< 1, dim, Number > &c_ij) const =delete
DEAL_II_ALWAYS_INLINE ScalarNumber reference_density() const
state_type harten_entropy_derivative(const state_type &U) const
static constexpr unsigned int n_precomputation_cycles
flux_contribution_type flux_contribution(const precomputed_vector_type &pv, const precomputed_initial_vector_type &piv, const unsigned int i, const state_type &U_i) const
static constexpr bool have_high_order_flux
state_type expand_state(const ST &state) const
HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
static constexpr unsigned int problem_dimension
dealii::Tensor< 1, problem_dimension, Number > state_type
flux_type f(const state_type &U) const
static constexpr unsigned int n_precomputed_values
state_type prescribe_riemann_characteristic(const state_type &U, const state_type &U_bar, const dealii::Tensor< 1, dim, Number > &normal) const
Number pressure(const state_type &U) const
state_type apply_galilei_transform(const state_type &state, const Lambda &lambda) const
Number mathematical_entropy(const state_type &U) const
DEAL_II_ALWAYS_INLINE ScalarNumber gamma_inverse() const
DEAL_II_ALWAYS_INLINE ScalarNumber gamma() const
static Number total_energy(const state_type &U)
DEAL_II_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_small() const
DEAL_II_ALWAYS_INLINE ScalarNumber gamma_minus_one_inverse() const
DEAL_II_ALWAYS_INLINE ScalarNumber gamma_plus_one_inverse() const
static Number density(const state_type &U)
state_type nodal_source(const precomputed_vector_type &pv, const unsigned int *js, const state_type &U_j, const ScalarNumber tau) const =delete
Number filter_vacuum_density(const Number &rho) const
DEAL_II_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_large() const
static state_type internal_energy_derivative(const state_type &U)
state_type flux_divergence(const flux_contribution_type &flux_i, const flux_contribution_type &flux_j, const dealii::Tensor< 1, dim, Number > &c_ij) const
std::array< state_type, 2 > linearized_eigenvector(const state_type &U, const dealii::Tensor< 1, dim, Number > &normal) const
state_type nodal_source(const precomputed_vector_type &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const =delete
DEAL_II_ALWAYS_INLINE ScalarNumber gamma_minus_one_over_gamma_plus_one() const
state_type mathematical_entropy_derivative(const state_type &U) const
state_type apply_boundary_conditions(const dealii::types::boundary_id id, const state_type &U, const dealii::Tensor< 1, dim, Number > &normal, const Lambda &get_dirichlet_data) const
state_type to_primitive_state(const state_type &state) const
void precomputation_loop(unsigned int cycle, const DISPATCH &dispatch_check, precomputed_vector_type &precomputed_values, const SPARSITY &sparsity_simd, const vector_type &U, unsigned int left, unsigned int right) const
static dealii::Tensor< 1, dim, Number > momentum(const state_type &U)
Number speed_of_sound(const state_type &U) const
bool is_admissible(const state_type &U) const
Number specific_entropy(const state_type &U) const
HyperbolicSystem(const std::string &subsection="/HyperbolicSystem")
static const std::string problem_name
#define RYUJIN_OMP_FOR
Definition: openmp.h:70
T pow(const T x, const T b)
DEAL_II_ALWAYS_INLINE FT add(const FT &flux_left_ij, const FT &flux_right_ij)
DEAL_II_ALWAYS_INLINE dealii::Tensor< 1, problem_dim, T > contract(const FT &flux_ij, const TT &c_ij)