ryujin 2.1.1 revision 0348cbb53a3e4b1da2a4c037e81f88f2d21ce219
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#include <state_vector.h>
16
17#include <deal.II/base/parameter_acceptor.h>
18#include <deal.II/base/tensor.h>
19
20#include <array>
21
22namespace ryujin
23{
24 namespace Euler
25 {
26 template <int dim, typename Number>
27 class HyperbolicSystemView;
28
39 class HyperbolicSystem final : public dealii::ParameterAcceptor
40 {
41 public:
45 static inline const std::string problem_name =
46 "Compressible Euler equations (polytropic gas EOS, optimized)";
47
51 HyperbolicSystem(const std::string &subsection = "/HyperbolicSystem");
52
59 template <int dim, typename Number>
60 auto view() const
61 {
63 }
64
65 private:
70 double gamma_;
71
72 double reference_density_;
73 double vacuum_state_relaxation_small_;
74 double vacuum_state_relaxation_large_;
75
76 double gamma_inverse_;
77 double gamma_minus_one_inverse_;
78 double gamma_minus_one_over_gamma_plus_one_;
79 double gamma_plus_one_inverse_;
80
81 template <int dim, typename Number>
84 }; /* HyperbolicSystem */
85
86
103 template <int dim, typename Number>
105 {
106 public:
111 HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
112 : hyperbolic_system_(hyperbolic_system)
113 {
114 }
115
119 template <int dim2, typename Number2>
120 auto view() const
121 {
122 return HyperbolicSystemView<dim2, Number2>{hyperbolic_system_};
123 }
124
129
134
135 DEAL_II_ALWAYS_INLINE inline ScalarNumber gamma() const
136 {
137 return hyperbolic_system_.gamma_;
138 }
139
140 DEAL_II_ALWAYS_INLINE inline ScalarNumber reference_density() const
141 {
142 return hyperbolic_system_.reference_density_;
143 }
144
145 DEAL_II_ALWAYS_INLINE inline ScalarNumber
147 {
148 return hyperbolic_system_.vacuum_state_relaxation_small_;
149 }
150
151 DEAL_II_ALWAYS_INLINE inline ScalarNumber
153 {
154 return hyperbolic_system_.vacuum_state_relaxation_large_;
155 }
156
158
166
167 DEAL_II_ALWAYS_INLINE inline ScalarNumber gamma_inverse() const
168 {
169 return ScalarNumber(hyperbolic_system_.gamma_inverse_);
170 }
171
172 DEAL_II_ALWAYS_INLINE inline ScalarNumber gamma_plus_one_inverse() const
173 {
174 return ScalarNumber(hyperbolic_system_.gamma_plus_one_inverse_);
175 }
176
177 DEAL_II_ALWAYS_INLINE inline ScalarNumber gamma_minus_one_inverse() const
178 {
179 return ScalarNumber(hyperbolic_system_.gamma_minus_one_inverse_);
180 }
181
182 DEAL_II_ALWAYS_INLINE inline ScalarNumber
184 {
185 return ScalarNumber(
186 hyperbolic_system_.gamma_minus_one_over_gamma_plus_one_);
187 }
188
192 static constexpr bool have_gamma = true;
193
197 static constexpr bool have_eos_interpolation_b = false;
198
200
204
205 private:
206 const HyperbolicSystem &hyperbolic_system_;
207
208 public:
210
214
218 static constexpr unsigned int problem_dimension = 2 + dim;
219
223 using state_type = dealii::Tensor<1, problem_dimension, Number>;
224
228 using flux_type =
229 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
230
235
240 static inline const auto component_names =
241 []() -> std::array<std::string, problem_dimension> {
242 if constexpr (dim == 1)
243 return {"rho", "m", "E"};
244 else if constexpr (dim == 2)
245 return {"rho", "m_1", "m_2", "E"};
246 else if constexpr (dim == 3)
247 return {"rho", "m_1", "m_2", "m_3", "E"};
248 __builtin_trap();
249 }();
250
255 static inline const auto primitive_component_names =
256 []() -> std::array<std::string, problem_dimension> {
257 if constexpr (dim == 1)
258 return {"rho", "v", "p"};
259 else if constexpr (dim == 2)
260 return {"rho", "v_1", "v_2", "p"};
261 else if constexpr (dim == 3)
262 return {"rho", "v_1", "v_2", "v_3", "p"};
263 __builtin_trap();
264 }();
265
269 static constexpr unsigned int n_precomputed_values = 2;
270
274 using precomputed_type = std::array<Number, n_precomputed_values>;
275
279 static inline const auto precomputed_names =
280 std::array<std::string, n_precomputed_values>{"s", "eta_h"};
281
285 static constexpr unsigned int n_initial_precomputed_values = 0;
286
291 std::array<Number, n_initial_precomputed_values>;
292
296 static inline const auto initial_precomputed_names =
297 std::array<std::string, n_initial_precomputed_values>{};
298
302 using StateVector = Vectors::
303 StateVector<ScalarNumber, problem_dimension, n_precomputed_values>;
304
310
316
324
326
330
334 static constexpr unsigned int n_precomputation_cycles = 1;
335
340 template <typename DISPATCH, typename SPARSITY>
341 void precomputation_loop(unsigned int cycle,
342 const DISPATCH &dispatch_check,
343 const SPARSITY &sparsity_simd,
344 StateVector &state_vector,
345 unsigned int left,
346 unsigned int right) const;
347
349
353
358 static Number density(const state_type &U);
359
366 Number filter_vacuum_density(const Number &rho) const;
367
372 static dealii::Tensor<1, dim, Number> momentum(const state_type &U);
373
378 static Number total_energy(const state_type &U);
379
384 static Number internal_energy(const state_type &U);
385
392
403 Number pressure(const state_type &U) const;
404
412 Number speed_of_sound(const state_type &U) const;
413
421 Number specific_entropy(const state_type &U) const;
422
430 Number harten_entropy(const state_type &U) const;
431
440
445 Number mathematical_entropy(const state_type &U) const;
446
453
459 bool is_admissible(const state_type &U) const;
460
462
466
472 template <int component>
473 std::array<state_type, 2> linearized_eigenvector(
474 const state_type &U,
475 const dealii::Tensor<1, dim, Number> &normal) const;
476
483 template <int component>
485 const state_type &U,
486 const state_type &U_bar,
487 const dealii::Tensor<1, dim, Number> &normal) const;
488
507 template <typename Lambda>
509 apply_boundary_conditions(const dealii::types::boundary_id id,
510 const state_type &U,
511 const dealii::Tensor<1, dim, Number> &normal,
512 const Lambda &get_dirichlet_data) const;
513
515
519
530 flux_type f(const state_type &U) const;
531
553 const InitialPrecomputedVector &ipv,
554 const unsigned int i,
555 const state_type &U_i) const;
556
559 const InitialPrecomputedVector &ipv,
560 const unsigned int *js,
561 const state_type &U_j) const;
562
569 const flux_contribution_type &flux_j,
570 const dealii::Tensor<1, dim, Number> &c_ij) const;
571
573 static constexpr bool have_high_order_flux = false;
574
576 const flux_contribution_type &flux_i,
577 const flux_contribution_type &flux_j,
578 const dealii::Tensor<1, dim, Number> &c_ij) const = delete;
579
581
585
587 static constexpr bool have_source_terms = false;
588
590 const unsigned int i,
591 const state_type &U_i,
592 const ScalarNumber tau) const = delete;
593
595 const unsigned int *js,
596 const state_type &U_j,
597 const ScalarNumber tau) const = delete;
598
600
604
615 template <typename ST>
616 state_type expand_state(const ST &state) const;
617
631 template <typename ST>
632 state_type from_initial_state(const ST &initial_state) const;
633
638 state_type from_primitive_state(const state_type &primitive_state) const;
639
644 state_type to_primitive_state(const state_type &state) const;
645
651 template <typename Lambda>
653 const Lambda &lambda) const;
655 }; /* HyperbolicSystemView */
656
657
658 /*
659 * -------------------------------------------------------------------------
660 * Inline definitions
661 * -------------------------------------------------------------------------
662 */
663
664
665 inline HyperbolicSystem::HyperbolicSystem(const std::string &subsection)
666 : ParameterAcceptor(subsection)
667 {
668 gamma_ = 7. / 5.;
669 add_parameter("gamma", gamma_, "The ratio of specific heats");
670
671 reference_density_ = 1.;
672 add_parameter("reference density",
673 reference_density_,
674 "Problem specific density reference");
675
676 vacuum_state_relaxation_small_ = 1.e2;
677 add_parameter("vacuum state relaxation small",
678 vacuum_state_relaxation_small_,
679 "Problem specific vacuum relaxation parameter");
680
681 vacuum_state_relaxation_large_ = 1.e4;
682 add_parameter("vacuum state relaxation large",
683 vacuum_state_relaxation_large_,
684 "Problem specific vacuum relaxation parameter");
685
686 /*
687 * Precompute a number of derived gamma coefficients that contain
688 * divisions:
689 */
690 const auto compute_inverses = [this] {
691 gamma_inverse_ = 1. / gamma_;
692 gamma_plus_one_inverse_ = 1. / (gamma_ + 1.);
693 gamma_minus_one_inverse_ = 1. / (gamma_ - 1.);
694 gamma_minus_one_over_gamma_plus_one_ = (gamma_ - 1.) / (gamma_ + 1.);
695 };
696
697 compute_inverses();
698 ParameterAcceptor::parse_parameters_call_back.connect(compute_inverses);
699 }
700
701
702 template <int dim, typename Number>
703 template <typename DISPATCH, typename SPARSITY>
704 DEAL_II_ALWAYS_INLINE inline void
706 unsigned int cycle [[maybe_unused]],
707 const DISPATCH &dispatch_check,
708 const SPARSITY &sparsity_simd,
709 StateVector &state_vector,
710 unsigned int left,
711 unsigned int right) const
712 {
713 Assert(cycle == 0, dealii::ExcInternalError());
714
715 const auto &U = std::get<0>(state_vector);
716 auto &precomputed = std::get<1>(state_vector);
717
718 /* We are inside a thread parallel context */
719
720 unsigned int stride_size = get_stride_size<Number>;
721
723 for (unsigned int i = left; i < right; i += stride_size) {
724
725 /* Skip constrained degrees of freedom: */
726 const unsigned int row_length = sparsity_simd.row_length(i);
727 if (row_length == 1)
728 continue;
729
730 dispatch_check(i);
731
732 const auto U_i = U.template get_tensor<Number>(i);
733 const precomputed_type prec_i{specific_entropy(U_i),
734 harten_entropy(U_i)};
735 precomputed.template write_tensor<Number>(prec_i, i);
736 }
737 }
738
739
740 template <int dim, typename Number>
741 DEAL_II_ALWAYS_INLINE inline Number
743 {
744 return U[0];
745 }
746
747
748 template <int dim, typename Number>
749 DEAL_II_ALWAYS_INLINE inline Number
751 const Number &rho) const
752 {
753 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
754 const Number rho_cutoff_large =
755 reference_density() * vacuum_state_relaxation_large() * eps;
756
757 return dealii::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
758 std::abs(rho), rho_cutoff_large, Number(0.), rho);
759 }
760
761
762 template <int dim, typename Number>
763 DEAL_II_ALWAYS_INLINE inline dealii::Tensor<1, dim, Number>
765 {
766 dealii::Tensor<1, dim, Number> result;
767 for (unsigned int i = 0; i < dim; ++i)
768 result[i] = U[1 + i];
769 return result;
770 }
771
772
773 template <int dim, typename Number>
774 DEAL_II_ALWAYS_INLINE inline Number
776 {
777 return U[1 + dim];
778 }
779
780
781 template <int dim, typename Number>
782 DEAL_II_ALWAYS_INLINE inline Number
784 {
785 /*
786 * rho e = (E - 1/2*m^2/rho)
787 */
788 const Number rho_inverse = ScalarNumber(1.) / density(U);
789 const auto m = momentum(U);
790 const Number E = total_energy(U);
791 return E - ScalarNumber(0.5) * m.norm_square() * rho_inverse;
792 }
793
794
795 template <int dim, typename Number>
796 DEAL_II_ALWAYS_INLINE inline auto
798 const state_type &U) -> state_type
799 {
800 /*
801 * With
802 * rho e = E - 1/2 |m|^2 / rho
803 * we get
804 * (rho e)' = (1/2m^2/rho^2, -m/rho , 1 )^T
805 */
806
807 const Number rho_inverse = ScalarNumber(1.) / density(U);
808 const auto u = momentum(U) * rho_inverse;
809
810 state_type result;
811
812 result[0] = ScalarNumber(0.5) * u.norm_square();
813 for (unsigned int i = 0; i < dim; ++i) {
814 result[1 + i] = -u[i];
815 }
816 result[dim + 1] = ScalarNumber(1.);
817
818 return result;
819 }
820
821
822 template <int dim, typename Number>
823 DEAL_II_ALWAYS_INLINE inline Number
825 {
826 /* p = (gamma - 1) * (rho e) */
827 return (gamma() - ScalarNumber(1.)) * internal_energy(U);
828 }
829
830
831 template <int dim, typename Number>
832 DEAL_II_ALWAYS_INLINE inline Number
834 {
835 /* c^2 = gamma * p / rho */
836 const Number rho_inverse = ScalarNumber(1.) / density(U);
837 const Number p = pressure(U);
838 return std::sqrt(gamma() * p * rho_inverse);
839 }
840
841
842 template <int dim, typename Number>
843 DEAL_II_ALWAYS_INLINE inline Number
845 const state_type &U) const
846 {
847 /* exp((gamma - 1)s) = (rho e) / rho ^ gamma */
848 const auto rho_inverse = ScalarNumber(1.) / density(U);
849 return internal_energy(U) * ryujin::pow(rho_inverse, gamma());
850 }
851
852
853 template <int dim, typename Number>
854 DEAL_II_ALWAYS_INLINE inline Number
856 {
857 /* rho^2 e = \rho E - 1/2*m^2 */
858
859 const Number rho = density(U);
860 const auto m = momentum(U);
861 const Number E = total_energy(U);
862
863 const Number rho_rho_e = rho * E - ScalarNumber(0.5) * m.norm_square();
864 return ryujin::pow(rho_rho_e, gamma_plus_one_inverse());
865 }
866
867
868 template <int dim, typename Number>
869 DEAL_II_ALWAYS_INLINE inline auto
871 const state_type &U) const -> state_type
872 {
873 /*
874 * With
875 * eta = (rho^2 e) ^ 1/(gamma+1)
876 * rho^2 e = rho * E - 1/2 |m|^2
877 *
878 * we get
879 *
880 * eta' = 1/(gamma+1) * (rho^2 e) ^ -gamma/(gamma+1) * (E,-m,rho)^T
881 *
882 */
883
884 const Number rho = density(U);
885 const auto m = momentum(U);
886 const Number E = total_energy(U);
887
888 const Number rho_rho_e = rho * E - ScalarNumber(0.5) * m.norm_square();
889
890 const auto factor =
891 gamma_plus_one_inverse() *
892 ryujin::pow(rho_rho_e, -gamma() * gamma_plus_one_inverse());
893
894 state_type result;
895
896 result[0] = factor * E;
897 for (unsigned int i = 0; i < dim; ++i)
898 result[1 + i] = -factor * m[i];
899 result[dim + 1] = factor * rho;
900
901 return result;
902 }
903
904
905 template <int dim, typename Number>
906 DEAL_II_ALWAYS_INLINE inline Number
908 const state_type &U) const
909 {
911 const auto p = pressure(U);
912 return ryujin::pow(p, gamma_inverse());
913 }
914
915
916 template <int dim, typename Number>
917 DEAL_II_ALWAYS_INLINE inline auto
919 const state_type &U) const -> state_type
920 {
921 /*
922 * With
923 * eta = p ^ (1/gamma)
924 * p = (gamma - 1) * (rho e)
925 * rho e = E - 1/2 |m|^2 / rho
926 *
927 * we get
928 *
929 * eta' = (gamma - 1)/gamma p ^(1/gamma - 1) *
930 *
931 * (1/2m^2/rho^2 , -m/rho , 1 )^T
932 */
933 const Number rho = density(U);
934 const Number rho_inverse = ScalarNumber(1.) / rho;
935 const auto u = momentum(U) * rho_inverse;
936 const auto p = pressure(U);
937
938 const auto factor = (gamma() - ScalarNumber(1.0)) * gamma_inverse() *
939 ryujin::pow(p, gamma_inverse() - ScalarNumber(1.));
940
941 state_type result;
942
943 result[0] = factor * ScalarNumber(0.5) * u.norm_square();
944 result[dim + 1] = factor;
945 for (unsigned int i = 0; i < dim; ++i) {
946 result[1 + i] = -factor * u[i];
947 }
948
949 return result;
950 }
951
952
953 template <int dim, typename Number>
954 DEAL_II_ALWAYS_INLINE inline bool
956 {
957 const auto rho_new = density(U);
958 const auto e_new = internal_energy(U);
959 const auto s_new = specific_entropy(U);
960
961 constexpr auto gt = dealii::SIMDComparison::greater_than;
962 using T = Number;
963 const auto test =
964 dealii::compare_and_apply_mask<gt>(rho_new, T(0.), T(0.), T(-1.)) + //
965 dealii::compare_and_apply_mask<gt>(e_new, T(0.), T(0.), T(-1.)) + //
966 dealii::compare_and_apply_mask<gt>(s_new, T(0.), T(0.), T(-1.));
967
968#ifdef DEBUG_OUTPUT
969 if (!(test == Number(0.))) {
970 std::cout << std::fixed << std::setprecision(16);
971 std::cout << "Bounds violation: Negative state [rho, e, s] detected!\n";
972 std::cout << "\t\trho: " << rho_new << "\n";
973 std::cout << "\t\tint: " << e_new << "\n";
974 std::cout << "\t\tent: " << s_new << "\n" << std::endl;
975 }
976#endif
977
978 return (test == Number(0.));
979 }
980
981
982 template <int dim, typename Number>
983 template <int component>
984 DEAL_II_ALWAYS_INLINE inline auto
986 const state_type &U, const dealii::Tensor<1, dim, Number> &normal) const
987 -> std::array<state_type, 2>
988 {
989 static_assert(component == 1 || component == problem_dimension,
990 "Only first and last eigenvectors implemented");
991
992 const auto rho = density(U);
993 const auto m = momentum(U);
994 const auto v = m / rho;
995 const auto a = speed_of_sound(U);
996 const auto gamma = this->gamma();
997
998 state_type b;
999 state_type c;
1000
1001 const auto e_k = 0.5 * v.norm_square();
1002
1003 switch (component) {
1004 case 1:
1005 b[0] = (gamma - 1.) * e_k + a * v * normal;
1006 for (unsigned int i = 0; i < dim; ++i)
1007 b[1 + i] = (1. - gamma) * v[i] - a * normal[i];
1008 b[dim + 1] = gamma - 1.;
1009 b /= 2. * a * a;
1010
1011 c[0] = 1.;
1012 for (unsigned int i = 0; i < dim; ++i)
1013 c[1 + i] = v[i] - a * normal[i];
1014 c[dim + 1] = a * a / (gamma - 1) + e_k - a * (v * normal);
1015
1016 return {b, c};
1017
1018 case problem_dimension:
1019 b[0] = (gamma - 1.) * e_k - a * v * normal;
1020 for (unsigned int i = 0; i < dim; ++i)
1021 b[1 + i] = (1. - gamma) * v[i] + a * normal[i];
1022 b[dim + 1] = gamma - 1.;
1023 b /= 2. * a * a;
1024
1025 c[0] = 1.;
1026 for (unsigned int i = 0; i < dim; ++i)
1027 c[1 + i] = v[i] + a * normal[i];
1028 c[dim + 1] = a * a / (gamma - 1) + e_k + a * (v * normal);
1029
1030 return {b, c};
1031 }
1032
1033 __builtin_unreachable();
1034 }
1035
1036
1037 template <int dim, typename Number>
1038 template <int component>
1039 DEAL_II_ALWAYS_INLINE inline auto
1041 const state_type &U,
1042 const state_type &U_bar,
1043 const dealii::Tensor<1, dim, Number> &normal) const -> state_type
1044 {
1045 static_assert(component == 1 || component == 2,
1046 "component has to be 1 or 2");
1047
1048 const auto m = momentum(U);
1049 const auto rho = density(U);
1050 const auto a = speed_of_sound(U);
1051 const auto vn = m * normal / rho;
1052
1053 const auto m_bar = momentum(U_bar);
1054 const auto rho_bar = density(U_bar);
1055 const auto a_bar = speed_of_sound(U_bar);
1056 const auto vn_bar = m_bar * normal / rho_bar;
1057
1058 /* First Riemann characteristic: v* n - 2 / (gamma - 1) * a */
1059
1060 const auto R_1 = component == 1
1061 ? vn_bar - 2. * a_bar / (gamma() - ScalarNumber(1.))
1062 : vn - 2. * a / (gamma() - ScalarNumber(1.));
1063
1064 /* Second Riemann characteristic: v* n + 2 / (gamma() - 1) * a */
1065
1066 const auto R_2 = component == 2
1067 ? vn_bar + 2. * a_bar / (gamma() - ScalarNumber(1.))
1068 : vn + 2. * a / (gamma() - ScalarNumber(1.));
1069
1070 const auto p = pressure(U);
1071 const auto s = p / ryujin::pow(rho, gamma());
1072
1073 const auto vperp = m / rho - vn * normal;
1074
1075 const auto vn_new = 0.5 * (R_1 + R_2);
1076
1077 auto rho_new = 1. / (gamma() * s) *
1078 ryujin::fixed_power<2>(ScalarNumber((gamma() - 1.) / 4.) *
1079 (R_2 - R_1));
1080 rho_new = ryujin::pow(rho_new, 1. / (gamma() - 1.));
1081
1082 const auto p_new = s * std::pow(rho_new, gamma());
1083
1084 state_type U_new;
1085 U_new[0] = rho_new;
1086 for (unsigned int d = 0; d < dim; ++d) {
1087 U_new[1 + d] = rho_new * (vn_new * normal + vperp)[d];
1088 }
1089 U_new[1 + dim] = p_new / ScalarNumber(gamma() - 1.) +
1090 0.5 * rho_new * (vn_new * vn_new + vperp.norm_square());
1091
1092 return U_new;
1093 }
1094
1095
1096 template <int dim, typename Number>
1097 template <typename Lambda>
1098 DEAL_II_ALWAYS_INLINE inline auto
1100 dealii::types::boundary_id id,
1101 const state_type &U,
1102 const dealii::Tensor<1, dim, Number> &normal,
1103 const Lambda &get_dirichlet_data) const -> state_type
1104 {
1105 state_type result = U;
1106
1107 if (id == Boundary::dirichlet) {
1108 result = get_dirichlet_data();
1109
1110 } else if (id == Boundary::dirichlet_momentum) {
1111 /* Only enforce Dirichlet conditions on the momentum: */
1112 auto m_dirichlet = momentum(get_dirichlet_data());
1113 for (unsigned int k = 0; k < dim; ++k)
1114 result[k + 1] = m_dirichlet[k];
1115
1116 } else if (id == Boundary::slip) {
1117 auto m = momentum(U);
1118 m -= 1. * (m * normal) * normal;
1119 for (unsigned int k = 0; k < dim; ++k)
1120 result[k + 1] = m[k];
1121
1122 } else if (id == Boundary::no_slip) {
1123 for (unsigned int k = 0; k < dim; ++k)
1124 result[k + 1] = Number(0.);
1125
1126 } else if (id == Boundary::dynamic) {
1127 /*
1128 * On dynamic boundary conditions, we distinguish four cases:
1129 *
1130 * - supersonic inflow: prescribe full state
1131 * - subsonic inflow:
1132 * decompose into Riemann invariants and leave R_2
1133 * characteristic untouched.
1134 * - supersonic outflow: do nothing
1135 * - subsonic outflow:
1136 * decompose into Riemann invariants and prescribe incoming
1137 * R_1 characteristic.
1138 */
1139 const auto m = momentum(U);
1140 const auto rho = density(U);
1141 const auto a = speed_of_sound(U);
1142 const auto vn = m * normal / rho;
1143
1144 /* Supersonic inflow: */
1145 if (vn < -a) {
1146 result = get_dirichlet_data();
1147 }
1148
1149 /* Subsonic inflow: */
1150 if (vn >= -a && vn <= 0.) {
1151 const auto U_dirichlet = get_dirichlet_data();
1152 result = prescribe_riemann_characteristic<2>(U_dirichlet, U, normal);
1153 }
1154
1155 /* Subsonic outflow: */
1156 if (vn > 0. && vn <= a) {
1157 const auto U_dirichlet = get_dirichlet_data();
1158 result = prescribe_riemann_characteristic<1>(U, U_dirichlet, normal);
1159 }
1160
1161 /* Supersonic outflow: do nothing, i.e., keep U as is */
1162
1163 } else {
1164 AssertThrow(false, dealii::ExcNotImplemented());
1165 }
1166
1167 return result;
1168 }
1169
1170
1171 template <int dim, typename Number>
1172 DEAL_II_ALWAYS_INLINE inline auto
1174 {
1175 const auto rho_inverse = ScalarNumber(1.) / density(U);
1176 const auto m = momentum(U);
1177 const auto p = pressure(U);
1178 const auto E = total_energy(U);
1179
1180 flux_type result;
1181
1182 result[0] = m;
1183 for (unsigned int i = 0; i < dim; ++i) {
1184 result[1 + i] = m * (m[i] * rho_inverse);
1185 result[1 + i][i] += p;
1186 }
1187 result[dim + 1] = m * (rho_inverse * (E + p));
1188
1189 return result;
1190 }
1191
1192
1193 template <int dim, typename Number>
1194 DEAL_II_ALWAYS_INLINE inline auto
1196 const PrecomputedVector & /*pv*/,
1197 const InitialPrecomputedVector & /*ipv*/,
1198 const unsigned int /*i*/,
1199 const state_type &U_i) const -> flux_contribution_type
1200 {
1201 return f(U_i);
1202 }
1203
1204
1205 template <int dim, typename Number>
1206 DEAL_II_ALWAYS_INLINE inline auto
1208 const PrecomputedVector & /*pv*/,
1209 const InitialPrecomputedVector & /*ipv*/,
1210 const unsigned int * /*js*/,
1211 const state_type &U_j) const -> flux_contribution_type
1212 {
1213 return f(U_j);
1214 }
1215
1216
1217 template <int dim, typename Number>
1218 DEAL_II_ALWAYS_INLINE inline auto
1220 const flux_contribution_type &flux_i,
1221 const flux_contribution_type &flux_j,
1222 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1223 {
1224 return -contract(add(flux_i, flux_j), c_ij);
1225 }
1226
1227
1228 template <int dim, typename Number>
1229 template <typename ST>
1231 -> state_type
1232 {
1233 using T = typename ST::value_type;
1234 static_assert(std::is_same_v<Number, T>, "template mismatch");
1235
1236 constexpr auto dim2 = ST::dimension - 2;
1237 static_assert(dim >= dim2,
1238 "the space dimension of the argument state must not be "
1239 "larger than the one of the target state");
1240
1241 state_type result;
1242 result[0] = state[0];
1243 result[dim + 1] = state[dim2 + 1];
1244 for (unsigned int i = 1; i < dim2 + 1; ++i)
1245 result[i] = state[i];
1246
1247 return result;
1248 }
1249
1250
1251 template <int dim, typename Number>
1252 template <typename ST>
1253 DEAL_II_ALWAYS_INLINE inline auto
1255 const ST &initial_state) const -> state_type
1256 {
1257 const auto primitive_state = expand_state(initial_state);
1258 return from_primitive_state(primitive_state);
1259 }
1260
1261
1262 template <int dim, typename Number>
1263 DEAL_II_ALWAYS_INLINE inline auto
1265 const state_type &primitive_state) const -> state_type
1266 {
1267 const auto &rho = primitive_state[0];
1268 /* extract velocity: */
1269 const auto u = /*SIC!*/ momentum(primitive_state);
1270 const auto &p = primitive_state[dim + 1];
1271
1272 auto state = primitive_state;
1273 /* Fix up momentum: */
1274 for (unsigned int i = 1; i < dim + 1; ++i)
1275 state[i] *= rho;
1276 /* Compute total energy: */
1277 state[dim + 1] =
1278 p / (ScalarNumber(gamma() - 1.)) + Number(0.5) * rho * u * u;
1279
1280 return state;
1281 }
1282
1283
1284 template <int dim, typename Number>
1285 DEAL_II_ALWAYS_INLINE inline auto
1287 const state_type &state) const -> state_type
1288 {
1289 const auto &rho = state[0];
1290 const auto rho_inverse = Number(1.) / rho;
1291 const auto p = pressure(state);
1292
1293 auto primitive_state = state;
1294 /* Fix up velocity: */
1295 for (unsigned int i = 1; i < dim + 1; ++i)
1296 primitive_state[i] *= rho_inverse;
1297 /* Set pressure: */
1298 primitive_state[dim + 1] = p;
1299
1300 return primitive_state;
1301 }
1302
1303
1304 template <int dim, typename Number>
1305 template <typename Lambda>
1307 const state_type &state, const Lambda &lambda) const -> state_type
1308 {
1309 auto result = state;
1310 const auto M = lambda(momentum(state));
1311 for (unsigned int d = 0; d < dim; ++d)
1312 result[1 + d] = M[d];
1313 return result;
1314 }
1315
1316 } // namespace Euler
1317} // namespace ryujin
typename get_value_type< Number >::type ScalarNumber
static constexpr unsigned int n_initial_precomputed_values
static constexpr bool have_eos_interpolation_b
state_type from_initial_state(const ST &initial_state) const
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
Number harten_entropy(const state_type &U) const
flux_contribution_type flux_contribution(const PrecomputedVector &pv, const InitialPrecomputedVector &ipv, const unsigned int i, const state_type &U_i) const
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
static constexpr bool have_high_order_flux
state_type nodal_source(const PrecomputedVector &pv, const unsigned int *js, const state_type &U_j, const ScalarNumber tau) const =delete
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
void precomputation_loop(unsigned int cycle, const DISPATCH &dispatch_check, const SPARSITY &sparsity_simd, StateVector &state_vector, unsigned int left, unsigned int right) const
static constexpr unsigned int n_precomputed_values
state_type nodal_source(const PrecomputedVector &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const =delete
std::array< Number, n_precomputed_values > precomputed_type
std::array< Number, n_initial_precomputed_values > initial_precomputed_type
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)
Number filter_vacuum_density(const Number &rho) const
DEAL_II_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_large() const
Vectors::StateVector< ScalarNumber, problem_dimension, n_precomputed_values > StateVector
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
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
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
@ dirichlet_momentum
#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)