ryujin 2.1.1 revision ee5cbcbf2346c1299c942d0e1f13b46449973c18
Loading...
Searching...
No Matches
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 - 2026 by the ryujin authors
4//
5
6#pragma once
7
8#include <compile_time_options.h>
9
11
12#include <convenience_macros.h>
13#include <discretization.h>
14#include <loop.h>
16#include <patterns_conversion.h>
17#include <simd.h>
18#include <state_vector.h>
19
20#include <deal.II/base/parameter_acceptor.h>
21#include <deal.II/base/tensor.h>
22
23#include <array>
24
25namespace ryujin
26{
27 namespace EulerAEOS
28 {
29 /*
30 * For various divisions in the arbirtray equation of state module we
31 * have a mathematical guarantee that the numerator and denominator are
32 * nonnegative and the limit (of zero numerator and denominator) must
33 * converge to zero. The following function takes care of rounding
34 * issues when computing such quotients by (a) avoiding division by
35 * zero and (b) ensuring non-negativity of the result.
36 */
37 template <typename Number>
38 DEAL_II_ALWAYS_INLINE inline Number safe_division(const Number &numerator,
39 const Number &denominator)
40 {
41 using ScalarNumber = typename get_value_type<Number>::type;
42 constexpr ScalarNumber min = std::numeric_limits<ScalarNumber>::min();
43
44 return std::max(numerator, Number(0.)) /
45 std::max(denominator, Number(min));
46 }
47
48
49 template <int dim, typename Number>
51
64 class HyperbolicSystem final : public dealii::ParameterAcceptor
65 {
66 public:
70 static inline std::string problem_name =
71 "Compressible Euler equations (arbitrary EOS)";
72
76 HyperbolicSystem(const std::string &subsection = "/HyperbolicSystem");
77
82 template <int dim, typename Number = double>
84
91 template <int dim, typename Number>
92 auto view() const
93 {
94 return View<dim, Number>{*this};
95 }
96
105 template <int dim, typename ScalarNumber>
107 const OfflineData<dim, ScalarNumber> &offline_data,
109 &state_vector,
110 const bool skip_constrained_dofs = true) const;
111
112 private:
117
118 std::string equation_of_state_;
119
120 double reference_density_;
121 double vacuum_state_relaxation_small_;
122 double vacuum_state_relaxation_large_;
123
124 bool compute_strict_bounds_;
125
127
131
133 equation_of_state_list_;
134
135 using EquationOfState = EquationOfStateLibrary::EquationOfState;
136 std::shared_ptr<EquationOfState> selected_equation_of_state_;
137
138 template <int dim, typename Number>
140
142 }; /* HyperbolicSystem */
143
144
163 template <int dim, typename Number>
165 {
166 public:
171
176
180 static constexpr unsigned int problem_dimension = 2 + dim;
181
185 using state_type = dealii::Tensor<1, problem_dimension, Number>;
186
190 using flux_type =
191 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
192
197
202 static inline const auto component_names =
203 []() -> std::array<std::string, problem_dimension> {
204 if constexpr (dim == 1)
205 return {"rho", "m", "E"};
206 else if constexpr (dim == 2)
207 return {"rho", "m_1", "m_2", "E"};
208 else if constexpr (dim == 3)
209 return {"rho", "m_1", "m_2", "m_3", "E"};
210 __builtin_trap();
211 }();
212
217 static inline const auto primitive_component_names =
218 []() -> std::array<std::string, problem_dimension> {
219 if constexpr (dim == 1)
220 return {"rho", "v", "e"};
221 else if constexpr (dim == 2)
222 return {"rho", "v_1", "v_2", "e"};
223 else if constexpr (dim == 3)
224 return {"rho", "v_1", "v_2", "v_3", "e"};
225 __builtin_trap();
226 }();
227
231 static constexpr unsigned int n_precomputed_values = 4;
232
236 using precomputed_type = std::array<Number, n_precomputed_values>;
237
241 static inline const auto precomputed_names =
242 std::array<std::string, n_precomputed_values>{
243 {"p",
244 "surrogate_gamma_min",
245 "surrogate_specific_entropy",
246 "surrogate_harten_entropy"}};
247
251 static constexpr unsigned int n_initial_precomputed_values = 0;
252
257 std::array<Number, n_initial_precomputed_values>;
258
262 static inline const auto initial_precomputed_names =
263 std::array<std::string, n_initial_precomputed_values>{};
264
268 using StateVector = Vectors::
269 StateVector<ScalarNumber, problem_dimension, n_precomputed_values>;
270
276
282
290 dealii::VectorizedArray<ScalarNumber>::size(),
291 dealii::MemorySpace::Host,
292 /*writable=*/false>;
293
301
309 dealii::VectorizedArray<ScalarNumber>::size(),
310 dealii::MemorySpace::Host,
311 /*writable=*/false>;
312
314
318
323 HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
324 : hyperbolic_system_(hyperbolic_system)
325 {
326 }
327
329
333
334 DEAL_II_ALWAYS_INLINE inline const std::string &equation_of_state() const
335 {
336 return hyperbolic_system_.equation_of_state_;
337 }
338
339 DEAL_II_ALWAYS_INLINE inline ScalarNumber reference_density() const
340 {
341 return hyperbolic_system_.reference_density_;
342 }
343
344 DEAL_II_ALWAYS_INLINE inline ScalarNumber
346 {
347 return hyperbolic_system_.vacuum_state_relaxation_small_;
348 }
349
350 DEAL_II_ALWAYS_INLINE inline ScalarNumber
352 {
353 return hyperbolic_system_.vacuum_state_relaxation_large_;
354 }
355
356 DEAL_II_ALWAYS_INLINE inline bool compute_strict_bounds() const
357 {
358 return hyperbolic_system_.compute_strict_bounds_;
359 }
360
362
366
371 DEAL_II_ALWAYS_INLINE inline Number eos_pressure(const Number &rho,
372 const Number &e) const
373 {
374 const auto &eos = hyperbolic_system_.selected_equation_of_state_;
375
376 if constexpr (std::is_same_v<ScalarNumber, Number>) {
377 return ScalarNumber(eos->pressure(rho, e));
378 } else {
379 Number p;
380 for (unsigned int k = 0; k < Number::size(); ++k) {
381 p[k] = ScalarNumber(eos->pressure(rho[k], e[k]));
382 }
383 return p;
384 }
385 }
386
391 DEAL_II_ALWAYS_INLINE inline Number
392 eos_specific_internal_energy(const Number &rho, const Number &p) const
393 {
394 const auto &eos = hyperbolic_system_.selected_equation_of_state_;
395
396 if constexpr (std::is_same_v<ScalarNumber, Number>) {
397 return ScalarNumber(eos->specific_internal_energy(rho, p));
398 } else {
399 Number e;
400 for (unsigned int k = 0; k < Number::size(); ++k) {
401 e[k] = ScalarNumber(eos->specific_internal_energy(rho[k], p[k]));
402 }
403 return e;
404 }
405 }
406
411 DEAL_II_ALWAYS_INLINE inline Number
412 eos_specific_entropy(const Number &rho, const Number &e) const
413 {
414 const auto &eos = hyperbolic_system_.selected_equation_of_state_;
415
416 if constexpr (std::is_same_v<ScalarNumber, Number>) {
417 return ScalarNumber(eos->specific_entropy(rho, e));
418 } else {
419 Number p;
420 for (unsigned int k = 0; k < Number::size(); ++k) {
421 p[k] = ScalarNumber(eos->specific_entropy(rho[k], e[k]));
422 }
423 return p;
424 }
425 }
426
431 DEAL_II_ALWAYS_INLINE inline Number
432 eos_cold_curve_bound(const Number &rho) const
433 {
434 const auto &eos = hyperbolic_system_.selected_equation_of_state_;
435
436 if constexpr (std::is_same_v<ScalarNumber, Number>) {
437 return ScalarNumber(eos->cold_curve_bound(rho));
438 } else {
439 Number p;
440 for (unsigned int k = 0; k < Number::size(); ++k) {
441 p[k] = ScalarNumber(eos->cold_curve_bound(rho[k]));
442 }
443 return p;
444 }
445 }
446
451 DEAL_II_ALWAYS_INLINE inline Number eos_temperature(const Number &rho,
452 const Number &e) const
453 {
454 const auto &eos = hyperbolic_system_.selected_equation_of_state_;
455
456 if constexpr (std::is_same_v<ScalarNumber, Number>) {
457 return ScalarNumber(eos->temperature(rho, e));
458 } else {
459 Number temp;
460 for (unsigned int k = 0; k < Number::size(); ++k) {
461 temp[k] = ScalarNumber(eos->temperature(rho[k], e[k]));
462 }
463 return temp;
464 }
465 }
466
471 DEAL_II_ALWAYS_INLINE inline Number
472 eos_speed_of_sound(const Number &rho, const Number &e) const
473 {
474 const auto &eos = hyperbolic_system_.selected_equation_of_state_;
475
476 if constexpr (std::is_same_v<ScalarNumber, Number>) {
477 return ScalarNumber(eos->speed_of_sound(rho, e));
478 } else {
479 Number c;
480 for (unsigned int k = 0; k < Number::size(); ++k) {
481 c[k] = ScalarNumber(eos->speed_of_sound(rho[k], e[k]));
482 }
483 return c;
484 }
485 }
486
490 DEAL_II_ALWAYS_INLINE inline ScalarNumber eos_covolume_constant() const
491 {
492 const auto &eos = hyperbolic_system_.selected_equation_of_state_;
493 return ScalarNumber(eos->covolume_constant());
494 }
495
499 DEAL_II_ALWAYS_INLINE inline ScalarNumber eos_interpolation_pinfty() const
500 {
501 const auto &eos = hyperbolic_system_.selected_equation_of_state_;
502 return ScalarNumber(eos->interpolation_pinfty());
503 }
504
509 DEAL_II_ALWAYS_INLINE inline ScalarNumber eos_interpolation_q() const
510 {
511 const auto &eos = hyperbolic_system_.selected_equation_of_state_;
512 return ScalarNumber(eos->interpolation_q());
513 }
514
516
520
521 static constexpr bool have_gamma = false;
522 static constexpr bool have_covolume_constant = true;
523 static constexpr bool have_energy_equation = true;
524
526
530
535 static Number density(const state_type &U);
536
543 Number filter_vacuum_density(const Number &rho) const;
544
549 static dealii::Tensor<1, dim, Number> momentum(const state_type &U);
550
555 static Number total_energy(const state_type &U);
556
561 static Number internal_energy(const state_type &U);
562
569
571
577
588 const Number &gamma_min) const;
589
600 Number surrogate_harten_entropy(const state_type &U,
601 const Number &gamma_min) const;
602
615 const Number &eta,
616 const Number &gamma_min) const;
617
629 Number surrogate_gamma(const state_type &U, const Number &p) const;
630
646 Number surrogate_pressure(const state_type &U, const Number &gamma) const;
647
656 Number surrogate_speed_of_sound(const state_type &U,
657 const Number &gamma) const;
658
664 bool is_admissible(const state_type &U) const;
665
667
671
678 template <int component>
680 const state_type &U,
681 const Number &p,
682 const state_type &U_bar,
683 const Number &p_bar,
684 const dealii::Tensor<1, dim, Number> &normal) const;
685
704 template <typename Lambda>
706 apply_boundary_conditions(const dealii::types::boundary_id id,
707 const state_type &U,
708 const dealii::Tensor<1, dim, Number> &normal,
709 const Lambda &get_dirichlet_data) const;
710
712
716
727 flux_type f(const state_type &U, const Number &p) const;
728
751 const unsigned int i,
752 const state_type &U_i) const;
753
757 const unsigned int *js,
758 const state_type &U_j) const;
759
766 const flux_contribution_type &flux_j,
767 const dealii::Tensor<1, dim, Number> &c_ij) const;
768
772 static constexpr bool have_high_order_flux = false;
773
775 const flux_contribution_type &flux_i,
776 const flux_contribution_type &flux_j,
777 const dealii::Tensor<1, dim, Number> &c_ij) const = delete;
778
780
784
786 static constexpr bool have_source_terms = false;
787
789 const unsigned int i,
790 const state_type &U_i,
791 const ScalarNumber tau) const = delete;
792
794 const unsigned int *js,
795 const state_type &U_j,
796 const ScalarNumber tau) const = delete;
797
799
803
814 template <typename ST>
815 state_type expand_state(const ST &state) const;
816
829 template <typename ST>
830 state_type from_initial_state(const ST &initial_state) const;
831
836 state_type from_primitive_state(const state_type &primitive_state) const;
837
842 state_type to_primitive_state(const state_type &state) const;
843
849 template <typename Lambda>
851 const Lambda &lambda) const;
852
853 private:
855
859
860 const HyperbolicSystem &hyperbolic_system_;
861
863 }; /* HyperbolicSystemView */
864
865
866 /*
867 * -------------------------------------------------------------------------
868 * Inline definitions
869 * -------------------------------------------------------------------------
870 */
871
872
874 const std::string &subsection /*= "HyperbolicSystem"*/)
875 : ParameterAcceptor(subsection)
876 {
877 equation_of_state_ = "polytropic gas";
878 add_parameter(
879 "equation of state",
880 equation_of_state_,
881 "The equation of state. Valid names are given by any of the "
882 "subsections defined below");
883
884 compute_strict_bounds_ = true;
885 add_parameter(
886 "compute strict bounds",
887 compute_strict_bounds_,
888 "Compute strict, but significantly more expensive bounds at various "
889 "places: (a) an expensive, but better upper wavespeed estimate in "
890 "the approximate WaveSpeedEstimator; (b) entropy "
891 "viscosity-commutator "
892 "with correct gamma_min over the stencil; (c) mathematically correct "
893 "surrogate specific entropy minimum with gamma_min over the "
894 "stencil.");
895
896 reference_density_ = 1.;
897 add_parameter("reference density",
898 reference_density_,
899 "Problem specific density reference");
900
901 vacuum_state_relaxation_small_ = 1.e2;
902 add_parameter("vacuum state relaxation small",
903 vacuum_state_relaxation_small_,
904 "Problem specific vacuum relaxation parameter");
905
906 vacuum_state_relaxation_large_ = 1.e4;
907 add_parameter("vacuum state relaxation large",
908 vacuum_state_relaxation_large_,
909 "Problem specific vacuum relaxation parameter");
910
911 /*
912 * And finally populate the equation of state list with all equation of
913 * state configurations defined in the EquationOfState namespace:
914 */
916 equation_of_state_list_, subsection);
917
918 const auto populate_functions = [this]() {
919 bool initialized = false;
920 for (auto &it : equation_of_state_list_)
921
922 /* Populate EOS-specific quantities and functions */
923 if (it->name() == equation_of_state_) {
924 selected_equation_of_state_ = it;
926 "Compressible Euler equations (" + it->name() + " EOS)";
927 initialized = true;
928 break;
929 }
930
931 AssertThrow(
932 initialized,
933 dealii::ExcMessage(
934 "Could not find an equation of state description with name \"" +
935 equation_of_state_ + "\""));
936 };
937
938 ParameterAcceptor::parse_parameters_call_back.connect(populate_functions);
939 populate_functions();
940 }
941
942
943 template <int dim, typename ScalarNumber>
945 const OfflineData<dim, ScalarNumber> &offline_data,
947 &state_vector,
948 const bool skip_constrained_dofs) const
949 {
950 const unsigned int n_internal = offline_data.n_locally_internal();
951 const unsigned int n_owned = offline_data.n_locally_owned();
952 const auto sparsity_simd_view =
953 offline_data.sparsity_pattern_simd().view();
954 using VA = dealii::VectorizedArray<ScalarNumber>;
955
956 const auto U_view = std::get<0>(state_vector).view();
957 const auto precomputed_view = std::get<1>(state_vector).view();
958
959 /* Compute values over the diagonal: */
960
961 const auto body = [&](auto sentinel, unsigned int i) {
962 using T = decltype(sentinel);
964 using precomputed_type = typename View::precomputed_type;
965
966 const unsigned int row_length = sparsity_simd_view.row_length(i);
967 if (skip_constrained_dofs && row_length == 1)
968 return;
969
970 const auto U_i = U_view.template read_tensor<T>(i);
971 const auto view = this->view<dim, T>();
972 const auto rho_i = view.density(U_i);
973 const auto e_i = view.internal_energy(U_i) / rho_i;
974
975 /* Calls into the selected equation of state: */
976 const auto p_i = view.eos_pressure(rho_i, e_i);
977
978 const auto gamma_i = view.surrogate_gamma(U_i, p_i);
979 using PT = precomputed_type;
980 const PT prec_i{p_i, gamma_i, T(0.), T(0.)};
981 precomputed_view.template write_tensor<T>(prec_i, i);
982 };
983
984 cpu_simd_loop<ScalarNumber>("time_step_1", body, 0, n_internal, n_owned);
985 precomputed_view.update_ghost_values();
986
987 /* Compute gamma_min over the stencil: */
988
989 const auto body_stencil = [&](auto sentinel, unsigned int i) {
990 using T = decltype(sentinel);
992 using PT = typename View::precomputed_type;
993
994 const unsigned int row_length = sparsity_simd_view.row_length(i);
995 if (skip_constrained_dofs && row_length == 1)
996 return;
997
998 const auto U_i = U_view.template read_tensor<T>(i);
999 auto prec_i = precomputed_view.template read_tensor<T, PT>(i);
1000 /* Previous loop: gamma_min_i == gamma_i, s_i == 0, eta_i == 0 */
1001 auto &[p_i, gamma_min_i, s_i, eta_i] = prec_i;
1002
1003 const auto view = this->view<dim, T>();
1004
1005 constexpr unsigned int stride_size = get_stride_size<T>;
1006 const unsigned int *js = sparsity_simd_view.columns(i) + stride_size;
1007 for (unsigned int col_idx = 1; col_idx < row_length;
1008 ++col_idx, js += stride_size) {
1009
1010 const auto U_j = U_view.template read_tensor<T>(js);
1011 const auto prec_j = precomputed_view.template read_tensor<T, PT>(js);
1012 const auto p_j = std::get<0>(prec_j);
1013 const auto gamma_j = view.surrogate_gamma(U_j, p_j);
1014 gamma_min_i = std::min(gamma_min_i, gamma_j);
1015 }
1016
1017 s_i = view.surrogate_specific_entropy(U_i, gamma_min_i);
1018 eta_i = view.surrogate_harten_entropy(U_i, gamma_min_i);
1019 precomputed_view.template write_tensor<T>(prec_i, i);
1020 };
1021
1022 cpu_simd_loop<ScalarNumber>(
1023 "time_step_1", body_stencil, 0, n_internal, n_owned);
1024 }
1025
1026
1027 template <int dim, typename Number>
1028 DEAL_II_ALWAYS_INLINE inline Number
1030 {
1031 return U[0];
1032 }
1033
1034
1035 template <int dim, typename Number>
1036 DEAL_II_ALWAYS_INLINE inline Number
1038 const Number &rho) const
1039 {
1040 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
1041 const Number rho_cutoff_large =
1042 reference_density() * vacuum_state_relaxation_large() * eps;
1043
1044 return dealii::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1045 std::abs(rho), rho_cutoff_large, Number(0.), rho);
1046 }
1047
1048
1049 template <int dim, typename Number>
1050 DEAL_II_ALWAYS_INLINE inline dealii::Tensor<1, dim, Number>
1052 {
1053 dealii::Tensor<1, dim, Number> result;
1054 for (unsigned int i = 0; i < dim; ++i)
1055 result[i] = U[1 + i];
1056 return result;
1057 }
1058
1059
1060 template <int dim, typename Number>
1061 DEAL_II_ALWAYS_INLINE inline Number
1063 {
1064 return U[1 + dim];
1065 }
1066
1067
1068 template <int dim, typename Number>
1069 DEAL_II_ALWAYS_INLINE inline Number
1071 {
1072 /*
1073 * rho e = (E - 1/2*m^2/rho)
1074 */
1075 const Number rho_inverse = ScalarNumber(1.) / density(U);
1076 const auto m = momentum(U);
1077 const Number E = total_energy(U);
1078 return E - ScalarNumber(0.5) * m.norm_square() * rho_inverse;
1079 }
1080
1081
1082 template <int dim, typename Number>
1083 DEAL_II_ALWAYS_INLINE inline auto
1085 const state_type &U) -> state_type
1086 {
1087 /*
1088 * With
1089 * rho e = E - 1/2 |m|^2 / rho
1090 * we get
1091 * (rho e)' = (1/2m^2/rho^2, -m/rho , 1 )^T
1092 */
1093
1094 const Number rho_inverse = ScalarNumber(1.) / density(U);
1095 const auto u = momentum(U) * rho_inverse;
1096
1097 state_type result;
1098
1099 result[0] = ScalarNumber(0.5) * u.norm_square();
1100 for (unsigned int i = 0; i < dim; ++i) {
1101 result[1 + i] = -u[i];
1102 }
1103 result[dim + 1] = ScalarNumber(1.);
1104
1105 return result;
1106 }
1107
1108
1109 template <int dim, typename Number>
1110 DEAL_II_ALWAYS_INLINE inline Number
1112 const state_type &U, const Number &gamma_min) const
1113 {
1114 const auto b = Number(eos_covolume_constant());
1115 const auto pinf = Number(eos_interpolation_pinfty());
1116 const auto q = Number(eos_interpolation_q());
1117
1118 const auto rho = density(U);
1119 const auto rho_inverse = ScalarNumber(1.) / rho;
1120
1121 const auto covolume = Number(1.) - b * rho;
1122
1123 const auto shift = internal_energy(U) - rho * q - pinf * covolume;
1124
1125 return shift * ryujin::pow(rho_inverse - b, gamma_min) / covolume;
1126 }
1127
1128
1129 template <int dim, typename Number>
1130 DEAL_II_ALWAYS_INLINE inline Number
1132 const state_type &U, const Number &gamma_min) const
1133 {
1134 const auto b = Number(eos_covolume_constant());
1135 const auto pinf = Number(eos_interpolation_pinfty());
1136 const auto q = Number(eos_interpolation_q());
1137
1138 const auto rho = density(U);
1139 const auto m = momentum(U);
1140 const auto E = total_energy(U);
1141 const auto rho_rho_e_q =
1142 rho * E - ScalarNumber(0.5) * m.norm_square() - rho * rho * q;
1143
1144 const auto exponent = ScalarNumber(1.) / (gamma_min + Number(1.));
1145
1146 const auto covolume = Number(1.) - b * rho;
1147 const auto covolume_term = ryujin::pow(covolume, gamma_min - Number(1.));
1148
1149 const auto rho_pinfcov = rho * pinf * covolume;
1150
1151 return ryujin::pow(
1152 positive_part(rho_rho_e_q - rho_pinfcov) * covolume_term, exponent);
1153 }
1154
1155
1156 template <int dim, typename Number>
1157 DEAL_II_ALWAYS_INLINE inline auto
1159 const state_type &U, const Number &eta, const Number &gamma_min) const
1160 -> state_type
1161 {
1162 /*
1163 * With
1164 * eta = (shift * (1-b*rho)^{gamma-1}) ^ {1/(gamma+1)},
1165 * shift = rho * E - 1/2 |m|^2 - rho^2 * q - p_infty * rho * (1 - b rho)
1166 *
1167 * shift' = [E - 2 * rho * q - p_infty * (1 - 2 b rho), -m, rho]^T
1168 * factor = 1/(gamma+1) * (eta/(1-b rho))^-gamma / (1-b rho)^2
1169 *
1170 * we get
1171 *
1172 * eta' = factor * (1-b*rho) * shift' -
1173 * factor * shift * (gamma - 1) * b * [1, 0, 0]^T
1174 *
1175 */
1176 const auto b = Number(eos_covolume_constant());
1177 const auto pinf = Number(eos_interpolation_pinfty());
1178 const auto q = Number(eos_interpolation_q());
1179
1180 const auto rho = density(U);
1181 const auto m = momentum(U);
1182 const auto E = total_energy(U);
1183
1184 const auto covolume = Number(1.) - b * rho;
1185 const auto covolume_inverse = ScalarNumber(1.) / covolume;
1186
1187 const auto shift = rho * E - ScalarNumber(0.5) * m.norm_square() -
1188 rho * rho * q - rho * pinf * covolume;
1189
1190 constexpr auto eps = std::numeric_limits<ScalarNumber>::epsilon();
1191 const auto regularization = m.norm() * eps;
1192 const auto max_val = ryujin::pow(
1193 std::max(regularization, eta * covolume_inverse), gamma_min);
1194 auto factor = safe_division(Number(1.0), max_val);
1195 factor *= fixed_power<2>(covolume_inverse) / (gamma_min + Number(1.));
1196
1197 state_type result;
1198
1199 const auto first_term = E - ScalarNumber(2.) * rho * q -
1200 pinf * (Number(1.) - ScalarNumber(2.) * b * rho);
1201 const auto second_term = -(gamma_min - Number(1.)) * shift * b;
1202
1203 result[0] = factor * (covolume * first_term + second_term);
1204 for (unsigned int i = 0; i < dim; ++i)
1205 result[1 + i] = -factor * covolume * m[i];
1206 result[dim + 1] = factor * covolume * rho;
1207
1208 return result;
1209 }
1210
1211
1212 template <int dim, typename Number>
1213 DEAL_II_ALWAYS_INLINE inline Number
1215 const Number &p) const
1216 {
1217 const auto b = Number(eos_covolume_constant());
1218 const auto pinf = Number(eos_interpolation_pinfty());
1219 const auto q = Number(eos_interpolation_q());
1220
1221 const auto rho = density(U);
1222 const auto rho_e = internal_energy(U);
1223 const auto covolume = Number(1.) - b * rho;
1224
1225 const auto numerator = (p + pinf) * covolume;
1226 const auto denominator = rho_e - rho * q - covolume * pinf;
1227 return Number(1.) + safe_division(numerator, denominator);
1228 }
1229
1230
1231 template <int dim, typename Number>
1232 DEAL_II_ALWAYS_INLINE inline Number
1234 const state_type &U, const Number &gamma) const
1235 {
1236 const auto b = Number(eos_covolume_constant());
1237 const auto pinf = Number(eos_interpolation_pinfty());
1238 const auto q = Number(eos_interpolation_q());
1239
1240 const auto rho = density(U);
1241 const auto rho_e = internal_energy(U);
1242 const auto covolume = Number(1.) - b * rho;
1243
1244 return positive_part(gamma - Number(1.)) *
1245 safe_division(rho_e - rho * q, covolume) -
1246 gamma * pinf;
1247 }
1248
1249
1250 template <int dim, typename Number>
1251 DEAL_II_ALWAYS_INLINE inline Number
1253 const state_type &U, const Number &gamma) const
1254 {
1255 const auto b = Number(eos_covolume_constant());
1256 const auto pinf = Number(eos_interpolation_pinfty());
1257 const auto q = Number(eos_interpolation_q());
1258
1259 const auto rho = density(U);
1260 const auto rho_e = internal_energy(U);
1261 const auto covolume = Number(1.) - b * rho;
1262
1263 auto radicand =
1264 (rho_e - rho * q - pinf * covolume) / (covolume * covolume * rho);
1265 radicand *= gamma * (gamma - 1.);
1266 return std::sqrt(positive_part(radicand));
1267 }
1268
1269
1270 template <int dim, typename Number>
1271 DEAL_II_ALWAYS_INLINE inline bool
1273 {
1274 const auto b = Number(eos_covolume_constant());
1275 const auto pinf = Number(eos_interpolation_pinfty());
1276 const auto q = Number(eos_interpolation_q());
1277
1278 const auto rho = density(U);
1279 const auto rho_e = internal_energy(U);
1280 const auto covolume = Number(1.) - b * rho;
1281
1282 const auto shift = rho_e - rho * q - pinf * covolume;
1283
1284 constexpr auto gt = dealii::SIMDComparison::greater_than;
1285 using T = Number;
1286 const auto test =
1287 dealii::compare_and_apply_mask<gt>(rho, T(0.), T(0.), T(-1.)) + //
1288 dealii::compare_and_apply_mask<gt>(shift, T(0.), T(0.), T(-1.));
1289
1290#ifdef DEBUG_OUTPUT
1291 if (!(test == Number(0.))) {
1292 std::cout << std::fixed << std::setprecision(16);
1293 std::cout << "Bounds violation: Negative state [rho, e] detected!\n";
1294 std::cout << "\t\trho: " << rho << "\n";
1295 std::cout << "\t\tint (shifted): " << shift << "\n";
1296 }
1297#endif
1298
1299 return (test == Number(0.));
1300 }
1301
1302
1303 template <int dim, typename Number>
1304 template <int component>
1305 DEAL_II_ALWAYS_INLINE inline auto
1307 const state_type &U,
1308 const Number &p,
1309 const state_type &U_bar,
1310 const Number &p_bar,
1311 const dealii::Tensor<1, dim, Number> &normal) const -> state_type
1312 {
1313 static_assert(component == 1 || component == 2,
1314 "component has to be 1 or 2");
1315
1316 const auto b = Number(eos_covolume_constant());
1317 const auto pinf = Number(eos_interpolation_pinfty());
1318 const auto q = Number(eos_interpolation_q());
1319
1320 /*
1321 * The "four" Riemann characteristics are formed under the assumption
1322 * of a locally isentropic flow. For this, we first transform both
1323 * states into {rho, vn, vperp, gamma, a}, where we use the NASG EOS
1324 * interpolation to derive a surrogate gamma and speed of sound a.
1325 *
1326 * See, e.g., https://arxiv.org/pdf/2004.08750, "Compressible flow in
1327 * a NOble-Abel Stiffened-Gas fluid", M. I. Radulescu.
1328 */
1329
1330 const auto m = momentum(U);
1331 const auto rho = density(U);
1332 const auto vn = m * normal / rho;
1333
1334 const auto gamma = surrogate_gamma(U, p);
1335 const auto a = surrogate_speed_of_sound(U, gamma);
1336 const auto covolume = 1. - b * rho;
1337
1338 const auto m_bar = momentum(U_bar);
1339 const auto rho_bar = density(U_bar);
1340 const auto vn_bar = m_bar * normal / rho_bar;
1341
1342 const auto gamma_bar = surrogate_gamma(U_bar, p_bar);
1343 const auto a_bar = surrogate_speed_of_sound(U_bar, gamma_bar);
1344 const auto covolume_bar = 1. - b * rho_bar;
1345
1346 /*
1347 * Now compute the Riemann characteristics {R_1, R_2, vperp, s}:
1348 * R_1 = v * n - 2 / (gamma - 1) * a * (1 - b * rho)
1349 * R_2 = v * n + 2 / (gamma - 1) * a * (1 - b * rho)
1350 * vperp
1351 * S = (p + p_infty) / rho^gamma * (1 - b * rho)^gamma
1352 *
1353 * Here, we replace either R_1, or R_2 with values coming from U_bar:
1354 */
1355
1356 const auto R_1 =
1357 component == 1 ? vn_bar - 2. * a_bar / (gamma_bar - 1.) * covolume_bar
1358 : vn - 2. * a / (gamma - 1.) * covolume;
1359
1360 const auto R_2 =
1361 component == 2 ? vn_bar + 2. * a_bar / (gamma_bar - 1.) * covolume_bar
1362 : vn + 2. * a / (gamma - 1.) * covolume;
1363
1364 /*
1365 * Note that we are really hoping for the best here... We require
1366 * that R_2 >= R_1 so that we can extract a valid sound speed...
1367 */
1368
1369 Assert(
1370 R_2 >= R_1,
1371 dealii::ExcMessage("Encountered R_2 < R_1 in dynamic boundary value "
1372 "enforcement. This implies that the interpolation "
1373 "with Riemann characteristics failed."));
1374
1375 const auto vperp = m / rho - vn * normal;
1376
1377 const auto S = (p + pinf) * ryujin::pow(Number(1.) / rho - b, gamma);
1378
1379 /*
1380 * Now, we have to reconstruct the actual conserved state U from the
1381 * Riemann characteristics R_1, R_2, vperp, and s. We first set up
1382 * {vn_new, vperp_new, a_new, S} and then solve for {rho_new, p_new}
1383 * with the help of the NASG EOS surrogate formulas:
1384 *
1385 * S = (p + p_infty) / rho^gamma * (1 - b * rho)^gamma
1386 *
1387 * a^2 = gamma * (p + p_infty) / (rho * cov)
1388 *
1389 * This implies:
1390 *
1391 * a^2 / (gamma * S) = rho^{gamma - 1} / (1 - b * rho)^{1 + gamma}
1392 */
1393
1394 const auto vn_new = Number(0.5) * (R_1 + R_2);
1395
1396 /*
1397 * Technically, we would need to solve for rho subject to a number of
1398 * nonlinear relationships:
1399 *
1400 * a = (gamma - 1) * (R_2 - R_1) / (4. * (1 - b * rho))
1401 *
1402 * a^2 / (gamma * S) = rho^{gamma - 1} / (1 - b * rho)^{gamma + 1}
1403 *
1404 * This seems to be a bit expensive for the fact that our dynamic
1405 * boundary conditions are already terribly heuristic...
1406 *
1407 * So instead, we rewrite this system as:
1408 *
1409 * a * (1 - b * rho) = (gamma - 1) * (R_2 - R_1) / 4.
1410 *
1411 * a^2 / (gamma * S) (1 - b * rho)^2
1412 * = (rho / (1 - b * rho))^{gamma - 1}
1413 *
1414 * And compute the terms on the left simply with the old covolume and
1415 * solving an easier easier nonlinear equation for the density. The
1416 * resulting system reads:
1417 *
1418 * a = (gamma - 1) * (R_2 - R_1) / (4. * (1 - b * rho_old))
1419 * A = {a^2 / (gamma * S) (1 - b * rho_old)^{2 gamma}}^{1/(gamma - 1)}
1420 *
1421 * rho = A / (1 + b * A)
1422 */
1423
1424 const auto a_new_square =
1425 ryujin::fixed_power<2>((gamma - 1.) * (R_2 - R_1) / (4. * covolume));
1426
1427 auto term = ryujin::pow(a_new_square / (gamma * S), 1. / (gamma - 1.));
1428 if (b != ScalarNumber(0.)) {
1429 term *= std::pow(covolume, 2. / (gamma - 1.));
1430 }
1431
1432 const auto rho_new = term / (1. + b * term);
1433
1434 const auto covolume_new = (1. - b * rho_new);
1435 const auto p_new = a_new_square / gamma * rho_new * covolume_new - pinf;
1436
1437 /*
1438 * And translate back into conserved quantities:
1439 */
1440
1441 const auto rho_e_new =
1442 rho_new * q + (p_new + gamma * pinf) * covolume_new / (gamma - 1.);
1443
1444 state_type U_new;
1445 U_new[0] = rho_new;
1446 for (unsigned int d = 0; d < dim; ++d) {
1447 U_new[1 + d] = rho_new * (vn_new * normal + vperp)[d];
1448 }
1449 U_new[1 + dim] =
1450 rho_e_new + 0.5 * rho_new * (vn_new * vn_new + vperp.norm_square());
1451
1452 return U_new;
1453 }
1454
1455
1456 template <int dim, typename Number>
1457 template <typename Lambda>
1458 DEAL_II_ALWAYS_INLINE inline auto
1460 dealii::types::boundary_id id,
1461 const state_type &U,
1462 const dealii::Tensor<1, dim, Number> &normal,
1463 const Lambda &get_dirichlet_data) const -> state_type
1464 {
1465 state_type result = U;
1466
1467 if (id == Boundary::dirichlet) {
1468 result = get_dirichlet_data();
1469
1470 } else if (id == Boundary::dirichlet_momentum) {
1471 /*
1472 * Only enforce Dirichlet conditions on the momentum, and keep the
1473 * internal energy constant:
1474 */
1475 const auto m_dirichlet = momentum(get_dirichlet_data());
1476 const auto rho = density(result);
1477 const auto m = momentum(result);
1478
1479 for (unsigned int k = 0; k < dim; ++k)
1480 result[k + 1] = m_dirichlet[k];
1481 result[dim + 1] +=
1482 Number(0.5) / rho * (m_dirichlet.norm_square() - m.norm_square());
1483
1484 } else if (id == Boundary::dirichlet_velocity) {
1485 /*
1486 * Only enforce Dirichlet conditions on the velocity, and keep the
1487 * internal energy constant:
1488 */
1489 const auto U_dirichlet = get_dirichlet_data();
1490 const auto rho_dirichlet = density(U_dirichlet);
1491 const auto v_dirichlet = momentum(U_dirichlet) / rho_dirichlet;
1492 const auto rho = density(result);
1493 const auto v = momentum(result) / rho;
1494
1495 for (unsigned int k = 0; k < dim; ++k)
1496 result[k + 1] = rho * v_dirichlet[k];
1497 result[dim + 1] +=
1498 Number(0.5) * rho * (v_dirichlet.norm_square() - v.norm_square());
1499
1500 } else if (id == Boundary::slip) {
1501 auto m = momentum(U);
1502 m -= 1. * (m * normal) * normal;
1503 for (unsigned int k = 0; k < dim; ++k)
1504 result[k + 1] = m[k];
1505
1506 } else if (id == Boundary::no_slip) {
1507 for (unsigned int k = 0; k < dim; ++k)
1508 result[k + 1] = Number(0.);
1509
1510 } else if (id == Boundary::dynamic) {
1511 /*
1512 * On dynamic boundary conditions, we distinguish four cases:
1513 *
1514 * - supersonic inflow: prescribe full state
1515 * - subsonic inflow:
1516 * decompose into Riemann invariants and leave R_2
1517 * characteristic untouched.
1518 * - supersonic outflow: do nothing
1519 * - subsonic outflow:
1520 * decompose into Riemann invariants and prescribe incoming
1521 * R_1 characteristic.
1522 */
1523 const auto m = momentum(U);
1524 const auto rho = density(U);
1525 const auto rho_e = internal_energy(U);
1526
1527 /*
1528 * We do not have precomputed values available. Thus, simply query
1529 * the pressure oracle and compute a surrogate speed of sound from
1530 * there:
1531 */
1532 const auto p = eos_pressure(rho, rho_e / rho);
1533 const auto gamma = surrogate_gamma(U, p);
1534 const auto a = surrogate_speed_of_sound(U, gamma);
1535 const auto vn = m * normal / rho;
1536
1537 /* Supersonic inflow: */
1538 if (vn < -a) {
1539 result = get_dirichlet_data();
1540 }
1541
1542 /* Subsonic inflow: */
1543 if (vn >= -a && vn <= 0.) {
1544 const auto U_dirichlet = get_dirichlet_data();
1545 const auto rho_dirichlet = density(U_dirichlet);
1546 const auto rho_e_dirichlet = internal_energy(U_dirichlet);
1547 const auto p_dirichlet =
1548 eos_pressure(rho_dirichlet, rho_e_dirichlet / rho_dirichlet);
1549
1550 result = prescribe_riemann_characteristic<2>(
1551 U_dirichlet, p_dirichlet, U, p, normal);
1552 }
1553
1554 /* Subsonic outflow: */
1555 if (vn > 0. && vn <= a) {
1556 const auto U_dirichlet = get_dirichlet_data();
1557 const auto rho_dirichlet = density(U_dirichlet);
1558 const auto rho_e_dirichlet = internal_energy(U_dirichlet);
1559 const auto p_dirichlet =
1560 eos_pressure(rho_dirichlet, rho_e_dirichlet / rho_dirichlet);
1561
1562 result = prescribe_riemann_characteristic<1>(
1563 U, p, U_dirichlet, p_dirichlet, normal);
1564 }
1565 /* Supersonic outflow: do nothing, i.e., keep U as is */
1566
1567 } else {
1568 AssertThrow(false, dealii::ExcNotImplemented());
1569 }
1570
1571 return result;
1572 }
1573
1574
1575 template <int dim, typename Number>
1576 DEAL_II_ALWAYS_INLINE inline auto
1578 const Number &p) const -> flux_type
1579 {
1580 const auto rho_inverse = ScalarNumber(1.) / density(U);
1581 const auto m = momentum(U);
1582 const auto E = total_energy(U);
1583
1584 flux_type result;
1585
1586 result[0] = m;
1587 for (unsigned int i = 0; i < dim; ++i) {
1588 result[1 + i] = m * (m[i] * rho_inverse);
1589 result[1 + i][i] += p;
1590 }
1591 result[dim + 1] = m * (rho_inverse * (E + p));
1592
1593 return result;
1594 }
1595
1596
1597 template <int dim, typename Number>
1598 DEAL_II_ALWAYS_INLINE inline auto
1600 const PrecomputedVectorView &pv,
1601 const InitialPrecomputedVectorView & /*piv*/,
1602 const unsigned int i,
1603 const state_type &U_i) const -> flux_contribution_type
1604 {
1605 const auto &[p_i, gamma_min_i, s_i, eta_i] =
1606 pv.template read_tensor<Number, precomputed_type>(i);
1607 return f(U_i, p_i);
1608 }
1609
1610
1611 template <int dim, typename Number>
1612 DEAL_II_ALWAYS_INLINE inline auto
1614 const PrecomputedVectorView &pv,
1615 const InitialPrecomputedVectorView & /*piv*/,
1616 const unsigned int *js,
1617 const state_type &U_j) const -> flux_contribution_type
1618 {
1619 const auto &[p_j, gamma_min_j, s_j, eta_j] =
1620 pv.template read_tensor<Number, precomputed_type>(js);
1621 return f(U_j, p_j);
1622 }
1623
1624
1625 template <int dim, typename Number>
1626 DEAL_II_ALWAYS_INLINE inline auto
1628 const flux_contribution_type &flux_i,
1629 const flux_contribution_type &flux_j,
1630 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1631 {
1632 return -contract(add(flux_i, flux_j), c_ij);
1633 }
1634
1635
1636 template <int dim, typename Number>
1637 template <typename ST>
1639 -> state_type
1640 {
1641 using T = typename ST::value_type;
1642 static_assert(std::is_same_v<Number, T>, "template mismatch");
1643
1644 constexpr auto dim2 = ST::dimension - 2;
1645 static_assert(dim >= dim2,
1646 "the space dimension of the argument state must not be "
1647 "larger than the one of the target state");
1648
1649 state_type result;
1650 result[0] = state[0];
1651 result[dim + 1] = state[dim2 + 1];
1652 for (unsigned int i = 1; i < dim2 + 1; ++i)
1653 result[i] = state[i];
1654
1655 return result;
1656 }
1657
1658
1659 template <int dim, typename Number>
1660 template <typename ST>
1661 DEAL_II_ALWAYS_INLINE inline auto
1663 const ST &initial_state) const -> state_type
1664 {
1665 auto primitive_state = expand_state(initial_state);
1666
1667 /* pressure into specific internal energy: */
1668 const auto rho = density(primitive_state);
1669 const auto p = /*SIC!*/ total_energy(primitive_state);
1670 const auto e = eos_specific_internal_energy(rho, p);
1671 primitive_state[dim + 1] = e;
1672
1673 return from_primitive_state(primitive_state);
1674 }
1675
1676
1677 template <int dim, typename Number>
1678 DEAL_II_ALWAYS_INLINE inline auto
1680 const state_type &primitive_state) const -> state_type
1681 {
1682 const auto rho = density(primitive_state);
1683 /* extract velocity: */
1684 const auto u = /*SIC!*/ momentum(primitive_state);
1685 /* extract specific internal energy: */
1686 const auto &e = /*SIC!*/ total_energy(primitive_state);
1687
1688 auto state = primitive_state;
1689 /* Fix up momentum: */
1690 for (unsigned int i = 1; i < dim + 1; ++i)
1691 state[i] *= rho;
1692
1693 /* Compute total energy: */
1694 state[dim + 1] = rho * e + Number(0.5) * rho * u * u;
1695
1696 return state;
1697 }
1698
1699
1700 template <int dim, typename Number>
1701 DEAL_II_ALWAYS_INLINE inline auto
1703 const state_type &state) const -> state_type
1704 {
1705 const auto rho = density(state);
1706 const auto rho_inverse = Number(1.) / rho;
1707 const auto rho_e = internal_energy(state);
1708
1709 auto primitive_state = state;
1710 /* Fix up velocity: */
1711 for (unsigned int i = 1; i < dim + 1; ++i)
1712 primitive_state[i] *= rho_inverse;
1713 /* Set specific internal energy: */
1714 primitive_state[dim + 1] = rho_e * rho_inverse;
1715
1716 return primitive_state;
1717 }
1718
1719
1720 template <int dim, typename Number>
1721 template <typename Lambda>
1723 const state_type &state, const Lambda &lambda) const -> state_type
1724 {
1725 auto result = state;
1726 const auto M = lambda(momentum(state));
1727 for (unsigned int d = 0; d < dim; ++d)
1728 result[1 + d] = M[d];
1729 return result;
1730 }
1731 } // namespace EulerAEOS
1732} // namespace ryujin
dealii::Tensor< 1, problem_dimension, Number > state_type
Vectors::StateVector< ScalarNumber, problem_dimension, n_precomputed_values > StateVector
state_type from_initial_state(const ST &initial_state) const
std::array< Number, n_initial_precomputed_values > initial_precomputed_type
Number surrogate_harten_entropy(const state_type &U, const Number &gamma_min) const
static Number internal_energy(const state_type &U)
state_type to_primitive_state(const state_type &state) 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 Number eos_cold_curve_bound(const Number &rho) const
typename get_value_type< Number >::type ScalarNumber
static dealii::Tensor< 1, dim, Number > momentum(const state_type &U)
Number surrogate_pressure(const state_type &U, const Number &gamma) const
Number surrogate_speed_of_sound(const state_type &U, const Number &gamma) const
DEAL_II_ALWAYS_INLINE const std::string & equation_of_state() const
flux_contribution_type flux_contribution(const PrecomputedVectorView &pv, const InitialPrecomputedVectorView &piv, const unsigned int i, const state_type &U_i) const
state_type nodal_source(const PrecomputedVectorView &pv, const unsigned int *js, const state_type &U_j, const ScalarNumber tau) const =delete
DEAL_II_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_large() const
static constexpr unsigned int n_precomputed_values
DEAL_II_ALWAYS_INLINE ScalarNumber reference_density() const
DEAL_II_ALWAYS_INLINE ScalarNumber eos_covolume_constant() const
state_type from_primitive_state(const state_type &primitive_state) const
static state_type internal_energy_derivative(const state_type &U)
DEAL_II_ALWAYS_INLINE Number eos_temperature(const Number &rho, const Number &e) const
DEAL_II_ALWAYS_INLINE Number eos_specific_entropy(const Number &rho, const Number &e) const
DEAL_II_ALWAYS_INLINE Number eos_pressure(const Number &rho, const Number &e) const
static constexpr unsigned int problem_dimension
Number surrogate_specific_entropy(const state_type &U, const Number &gamma_min) const
DEAL_II_ALWAYS_INLINE ScalarNumber eos_interpolation_pinfty() const
static Number total_energy(const state_type &U)
bool is_admissible(const state_type &U) const
DEAL_II_ALWAYS_INLINE bool compute_strict_bounds() const
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
DEAL_II_ALWAYS_INLINE Number eos_specific_internal_energy(const Number &rho, const Number &p) const
HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
DEAL_II_ALWAYS_INLINE ScalarNumber eos_interpolation_q() const
Number filter_vacuum_density(const Number &rho) const
flux_type f(const state_type &U, const Number &p) const
state_type prescribe_riemann_characteristic(const state_type &U, const Number &p, const state_type &U_bar, const Number &p_bar, const dealii::Tensor< 1, dim, Number > &normal) const
state_type expand_state(const ST &state) const
std::array< Number, n_precomputed_values > precomputed_type
state_type surrogate_harten_entropy_derivative(const state_type &U, const Number &eta, const Number &gamma_min) const
DEAL_II_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_small() const
Number surrogate_gamma(const state_type &U, const Number &p) const
static constexpr unsigned int n_initial_precomputed_values
state_type nodal_source(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const =delete
DEAL_II_ALWAYS_INLINE Number eos_speed_of_sound(const Number &rho, const Number &e) const
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
static Number density(const state_type &U)
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 apply_galilei_transform(const state_type &state, const Lambda &lambda) const
HyperbolicSystem(const std::string &subsection="/HyperbolicSystem")
void fill_precomputed_values(const OfflineData< dim, ScalarNumber > &offline_data, typename HyperbolicSystemView< dim, ScalarNumber >::StateVector &state_vector, const bool skip_constrained_dofs=true) const
dealii::Tensor< 1, problem_dimension, Number > state_type
typename get_value_type< Number >::type ScalarNumber
const auto & n_locally_owned() const
const auto & sparsity_pattern_simd() const
const auto & n_locally_internal() const
void populate_equation_of_state_list(equation_of_state_list_type &equation_of_state_list, const std::string &subsection)
@ dirichlet_momentum
@ dirichlet_velocity
DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor< 1, problem_dim, T > contract(const FT &flux_ij, const TT &c_ij)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE FT add(const FT &flux_left_ij, const FT &flux_right_ij)
DEAL_II_HOST_DEVICE T pow(const T x, const T b)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number positive_part(const Number number)
Definition simd.h:149
std::set< std::shared_ptr< EquationOfState > > equation_of_state_list_type
DEAL_II_ALWAYS_INLINE Number safe_division(const Number &numerator, const Number &denominator)