ryujin 2.1.1 revision b04fb4aba7bd97ddfa5994a6b4b6e8586eb15db2
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
10#include <ryujin/interface/hyperbolic_system.h>
11
13
14#include <convenience_macros.h>
15#include <discretization.h>
16#include <gpu.h>
17#include <loop.h>
19#include <patterns_conversion.h>
20#include <simd.h>
21#include <state_vector.h>
22
23#include <deal.II/base/memory_space.h>
24#include <deal.II/base/parameter_acceptor.h>
25#include <deal.II/base/tensor.h>
26
27#include <array>
28
29namespace ryujin
30{
31 namespace EulerAEOS
32 {
33 template <int dim,
34 typename Number,
35 typename MemorySpace = dealii::MemorySpace::Host>
36 class HyperbolicSystemView;
37
50 class HyperbolicSystem final : public Interface::HyperbolicSystem
51 {
52 public:
85
89 HyperbolicSystem(const std::string &subsection = "/HyperbolicSystem");
90
96 template <int dim,
97 typename Number = double,
98 typename MemorySpace = dealii::MemorySpace::Host>
100
108 template <int dim,
109 typename Number,
110 typename MemorySpace = dealii::MemorySpace::Host>
111 auto view() const
112 {
113 return View<dim, Number, MemorySpace>{*this};
114 }
115
129 template <typename MemorySpace = dealii::MemorySpace::Host,
130 int dim,
131 typename ScalarNumber>
133 const OfflineData<dim, ScalarNumber> &offline_data,
134 StateVector<ScalarNumber> &state_vector,
135 const bool skip_constrained_dofs = true) const;
136
137 private:
142
148 void update_parameters();
149
150 Mirrored<Parameters> parameters_;
151
152 std::string equation_of_state_;
153
155 equation_of_state_list_;
156
157 using EquationOfState = EquationOfStateLibrary::EquationOfState;
158 std::shared_ptr<EquationOfState> selected_equation_of_state_;
159
160 template <int, typename, typename>
162
164 }; /* HyperbolicSystem */
165
166
188 template <int dim, typename Number, typename MemorySpace>
190 {
191 public:
192 static_assert(
193 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
194 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
195 "Unexpected memory space");
196
201
206
210 static constexpr unsigned int problem_dimension = 2 + dim;
211
215 using state_type = dealii::Tensor<1, problem_dimension, Number>;
216
220 using flux_type =
221 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
222
227
231 static constexpr unsigned int n_precomputed_values = 4;
232
236 using precomputed_type = std::array<Number, n_precomputed_values>;
237
241 static constexpr unsigned int n_initial_precomputed_values = 0;
242
247 std::array<Number, n_initial_precomputed_values>;
248
249 template <int n_comp>
252
258
265
267
271
276 HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
277 : parameters_(
278 hyperbolic_system.parameters_.template view<MemorySpace>())
279 , equation_of_state_(
280 hyperbolic_system.selected_equation_of_state_.get())
281 {
282 }
283
285
289
295 DEAL_II_ALWAYS_INLINE inline const std::string &equation_of_state() const
296 {
297 return equation_of_state_->name();
298 }
299
300 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber reference_density() const
301 {
302 return ScalarNumber(parameters_->reference_density);
303 }
304
305 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
307 {
308 return ScalarNumber(parameters_->vacuum_state_relaxation_small);
309 }
310
311 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
313 {
314 return ScalarNumber(parameters_->vacuum_state_relaxation_large);
315 }
316
317 DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool compute_strict_bounds() const
318 {
319 return parameters_->compute_strict_bounds;
320 }
321
323
333
338 DEAL_II_ALWAYS_INLINE inline Number eos_pressure(const Number &rho,
339 const Number &e) const
340 {
341 const auto &eos = equation_of_state_;
342
343 if constexpr (std::is_same_v<ScalarNumber, Number>) {
344 return ScalarNumber(eos->pressure(rho, e));
345 } else {
346 Number p;
347 for (unsigned int k = 0; k < Number::size(); ++k) {
348 p[k] = ScalarNumber(eos->pressure(rho[k], e[k]));
349 }
350 return p;
351 }
352 }
353
358 DEAL_II_ALWAYS_INLINE inline Number
359 eos_specific_internal_energy(const Number &rho, const Number &p) const
360 {
361 const auto &eos = equation_of_state_;
362
363 if constexpr (std::is_same_v<ScalarNumber, Number>) {
364 return ScalarNumber(eos->specific_internal_energy(rho, p));
365 } else {
366 Number e;
367 for (unsigned int k = 0; k < Number::size(); ++k) {
368 e[k] = ScalarNumber(eos->specific_internal_energy(rho[k], p[k]));
369 }
370 return e;
371 }
372 }
373
378 DEAL_II_ALWAYS_INLINE inline Number
379 eos_specific_entropy(const Number &rho, const Number &e) const
380 {
381 const auto &eos = equation_of_state_;
382
383 if constexpr (std::is_same_v<ScalarNumber, Number>) {
384 return ScalarNumber(eos->specific_entropy(rho, e));
385 } else {
386 Number p;
387 for (unsigned int k = 0; k < Number::size(); ++k) {
388 p[k] = ScalarNumber(eos->specific_entropy(rho[k], e[k]));
389 }
390 return p;
391 }
392 }
393
398 DEAL_II_ALWAYS_INLINE inline Number
399 eos_cold_curve_bound(const Number &rho) const
400 {
401 const auto &eos = equation_of_state_;
402
403 if constexpr (std::is_same_v<ScalarNumber, Number>) {
404 return ScalarNumber(eos->cold_curve_bound(rho));
405 } else {
406 Number p;
407 for (unsigned int k = 0; k < Number::size(); ++k) {
408 p[k] = ScalarNumber(eos->cold_curve_bound(rho[k]));
409 }
410 return p;
411 }
412 }
413
418 DEAL_II_ALWAYS_INLINE inline Number eos_temperature(const Number &rho,
419 const Number &e) const
420 {
421 const auto &eos = equation_of_state_;
422
423 if constexpr (std::is_same_v<ScalarNumber, Number>) {
424 return ScalarNumber(eos->temperature(rho, e));
425 } else {
426 Number temp;
427 for (unsigned int k = 0; k < Number::size(); ++k) {
428 temp[k] = ScalarNumber(eos->temperature(rho[k], e[k]));
429 }
430 return temp;
431 }
432 }
433
438 DEAL_II_ALWAYS_INLINE inline Number
439 eos_speed_of_sound(const Number &rho, const Number &e) const
440 {
441 const auto &eos = equation_of_state_;
442
443 if constexpr (std::is_same_v<ScalarNumber, Number>) {
444 return ScalarNumber(eos->speed_of_sound(rho, e));
445 } else {
446 Number c;
447 for (unsigned int k = 0; k < Number::size(); ++k) {
448 c[k] = ScalarNumber(eos->speed_of_sound(rho[k], e[k]));
449 }
450 return c;
451 }
452 }
453
457 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
459 {
460 return ScalarNumber(parameters_->covolume_constant);
461 }
462
466 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
468 {
469 return ScalarNumber(parameters_->interpolation_pinfty);
470 }
471
476 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber eos_interpolation_q() const
477 {
478 return ScalarNumber(parameters_->interpolation_q);
479 }
480
482
486
487 static constexpr bool have_gamma = false;
488 static constexpr bool have_covolume_constant = true;
489 static constexpr bool have_energy_equation = true;
490
492
496
501 static DEAL_II_HOST_DEVICE Number density(const state_type &U);
502
509 DEAL_II_HOST_DEVICE Number filter_vacuum_density(const Number &rho) const;
510
515 static DEAL_II_HOST_DEVICE dealii::Tensor<1, dim, Number>
516 momentum(const state_type &U);
517
522 static DEAL_II_HOST_DEVICE Number total_energy(const state_type &U);
523
528 static DEAL_II_HOST_DEVICE Number internal_energy(const state_type &U);
529
535 static DEAL_II_HOST_DEVICE state_type
537
539
545
555 DEAL_II_HOST_DEVICE Number surrogate_specific_entropy(
556 const state_type &U, const Number &gamma_min) const;
557
568 DEAL_II_HOST_DEVICE Number surrogate_harten_entropy(
569 const state_type &U, const Number &gamma_min) const;
570
581 DEAL_II_HOST_DEVICE state_type
583 const Number &eta,
584 const Number &gamma_min) const;
585
597 DEAL_II_HOST_DEVICE Number surrogate_gamma(const state_type &U,
598 const Number &p) const;
599
615 DEAL_II_HOST_DEVICE Number surrogate_pressure(const state_type &U,
616 const Number &gamma) const;
617
626 DEAL_II_HOST_DEVICE Number
627 surrogate_speed_of_sound(const state_type &U, const Number &gamma) const;
628
634 DEAL_II_HOST_DEVICE bool is_admissible(const state_type &U) const;
635
637
641
648 template <int component>
650 const state_type &U,
651 const Number &p,
652 const state_type &U_bar,
653 const Number &p_bar,
654 const dealii::Tensor<1, dim, Number> &normal) const;
655
678 template <typename Lambda>
680 apply_boundary_conditions(const dealii::types::boundary_id id,
681 const state_type &U,
682 const dealii::Tensor<1, dim, Number> &normal,
683 const Lambda &get_dirichlet_data) const;
684
686
690
701 DEAL_II_HOST_DEVICE flux_type f(const state_type &U,
702 const Number &p) const;
703
723 DEAL_II_HOST_DEVICE
727 const unsigned int i,
728 const state_type &U_i) const;
729
730 DEAL_II_HOST_DEVICE
734 const unsigned int *js,
735 const state_type &U_j) const;
736
741 DEAL_II_HOST_DEVICE
744 const flux_contribution_type &flux_j,
745 const dealii::Tensor<1, dim, Number> &c_ij) const;
746
750 static constexpr bool have_high_order_flux = false;
751
752 DEAL_II_HOST_DEVICE
754 const flux_contribution_type &flux_i,
755 const flux_contribution_type &flux_j,
756 const dealii::Tensor<1, dim, Number> &c_ij) const = delete;
757
759
763
765 static constexpr bool have_source_terms = false;
766
767 DEAL_II_HOST_DEVICE
769 const unsigned int i,
770 const state_type &U_i,
771 const ScalarNumber tau) const = delete;
772
773 DEAL_II_HOST_DEVICE
775 const unsigned int *js,
776 const state_type &U_j,
777 const ScalarNumber tau) const = delete;
778
780
784
795 template <typename ST>
796 DEAL_II_HOST_DEVICE state_type expand_state(const ST &state) const;
797
813 template <typename ST>
814 state_type from_initial_state(const ST &initial_state) const;
815
820 DEAL_II_HOST_DEVICE
821 state_type from_primitive_state(const state_type &primitive_state) const;
822
827 DEAL_II_HOST_DEVICE
828 state_type to_primitive_state(const state_type &state) const;
829
835 template <typename Lambda>
837 const state_type &state, const Lambda &lambda) const;
838
839 private:
841
845
846 const HyperbolicSystem::Parameters *const parameters_;
847
848 /* Only valid (and dereferenced) on the host: */
849 const EquationOfStateLibrary::EquationOfState *const equation_of_state_;
850
852 }; /* HyperbolicSystemView */
853
854
855 /*
856 * -------------------------------------------------------------------------
857 * Inline definitions
858 * -------------------------------------------------------------------------
859 */
860
861
862 inline HyperbolicSystem::HyperbolicSystem(const std::string &subsection)
863 : Interface::HyperbolicSystem(
864 "Compressible Euler equations (arbitrary EOS)",
865 {{{"rho", "m", "E"},
866 {"rho", "m_1", "m_2", "E"},
867 {"rho", "m_1", "m_2", "m_3", "E"}}},
868 {{{"rho", "v", "e"},
869 {"rho", "v_1", "v_2", "e"},
870 {"rho", "v_1", "v_2", "v_3", "e"}}},
871 {{{"p",
872 "surrogate_gamma_min",
873 "surrogate_specific_entropy",
874 "surrogate_harten_entropy"},
875 {"p",
876 "surrogate_gamma_min",
877 "surrogate_specific_entropy",
878 "surrogate_harten_entropy"},
879 {"p",
880 "surrogate_gamma_min",
881 "surrogate_specific_entropy",
882 "surrogate_harten_entropy"}}},
883 {},
884 subsection)
885 , parameters_("euler_aeos_hyperbolic_system_parameters",
887 {
888 /* reference remains valid due to implicit_transfers_host_resident */
889 auto &parameters = *parameters_.view();
890
891 equation_of_state_ = "polytropic gas";
892 add_parameter(
893 "equation of state",
894 equation_of_state_,
895 "The equation of state. Valid names are given by any of the "
896 "subsections defined below");
897
898 parameters.compute_strict_bounds = true;
899 add_parameter(
900 "compute strict bounds",
901 parameters.compute_strict_bounds,
902 "Compute strict, but significantly more expensive bounds at various "
903 "places: (a) an expensive, but better upper wavespeed estimate in "
904 "the approximate WaveSpeedEstimator; (b) entropy "
905 "viscosity-commutator "
906 "with correct gamma_min over the stencil; (c) mathematically correct "
907 "surrogate specific entropy minimum with gamma_min over the "
908 "stencil.");
909
910 parameters.reference_density = 1.;
911 add_parameter("reference density",
912 parameters.reference_density,
913 "Problem specific density reference");
914
915 parameters.vacuum_state_relaxation_small = 1.e2;
916 add_parameter("vacuum state relaxation small",
917 parameters.vacuum_state_relaxation_small,
918 "Problem specific vacuum relaxation parameter");
919
920 parameters.vacuum_state_relaxation_large = 1.e4;
921 add_parameter("vacuum state relaxation large",
922 parameters.vacuum_state_relaxation_large,
923 "Problem specific vacuum relaxation parameter");
924
925 /*
926 * And finally populate the equation of state list with all equation of
927 * state configurations defined in the EquationOfState namespace:
928 */
930 equation_of_state_list_, subsection);
931
932 /*
933 * The equation of state classes update their interpolatory NASG
934 * parameters in their own parse_parameters_call_back signal, which
935 * is invoked after ours. Thus, also connect to theirs:
936 */
937 ParameterAcceptor::parse_parameters_call_back.connect(
938 [this] { update_parameters(); });
939 for (auto &it : equation_of_state_list_)
940 it->parse_parameters_call_back.connect([this] { update_parameters(); });
941
942 update_parameters();
943 }
944
945
946 inline void HyperbolicSystem::update_parameters()
947 {
948 bool initialized = false;
949 for (auto &it : equation_of_state_list_)
950
951 /* Populate EOS-specific quantities and functions */
952 if (it->name() == equation_of_state_) {
953 selected_equation_of_state_ = it;
954 problem_name_ =
955 "Compressible Euler equations (" + it->name() + " EOS)";
956 initialized = true;
957 break;
958 }
959
960 AssertThrow(
961 initialized,
962 dealii::ExcMessage(
963 "Could not find an equation of state description with name \"" +
964 equation_of_state_ + "\""));
965
966 auto &parameters = *parameters_.view();
967
968 parameters.covolume_constant =
969 selected_equation_of_state_->covolume_constant();
970 parameters.interpolation_pinfty =
971 selected_equation_of_state_->interpolation_pinfty();
972 parameters.interpolation_q =
973 selected_equation_of_state_->interpolation_q();
974 }
975
976
977 template <typename MemorySpace, int dim, typename ScalarNumber>
979 const OfflineData<dim, ScalarNumber> &offline_data,
980 StateVector<ScalarNumber> &state_vector,
981 const bool skip_constrained_dofs) const
982 {
983 using HostSpace = dealii::MemorySpace::Host;
984
985 const unsigned int n_internal = offline_data.n_locally_internal();
986 const unsigned int n_owned = offline_data.n_locally_owned();
987
989
990 auto &U = state_vector.U;
991 auto &precomputed = state_vector.precomputed;
992
993 /*
994 * Compute the pressure (and an initial surrogate gamma_min) over the
995 * diagonal. This requires calling into the selected equation of
996 * state, which is only possible on the host memory space. Thus,
997 * temporarily transfer the state vector and the precomputed values
998 * to the host memory space:
999 */
1000
1001 constexpr bool transfer =
1003 !std::is_same_v<MemorySpace, dealii::MemorySpace::Host>;
1004
1005 [[maybe_unused]] const bool host_resident =
1006 U.template is_resident<HostSpace>();
1007
1008 if constexpr (transfer) {
1009 U.template copy_to_memory_space<HostSpace>();
1010 precomputed.template move_to_memory_space<HostSpace>();
1011 }
1012
1013 {
1014 const auto sparsity_simd_view =
1015 offline_data.sparsity_pattern_simd().template view<HostSpace>();
1016
1017 /* We only read the hyperbolic state vector: */
1018 const auto U_view =
1019 std::as_const(U)
1020 .template view<ScalarView::problem_dimension, HostSpace>();
1021 const auto precomputed_view =
1023 .template view<ScalarView::n_precomputed_values, HostSpace>();
1024
1025 const auto hyperbolic_system_views =
1026 make_select_view<dim, ScalarNumber, HostSpace>(*this);
1027
1028 const auto body = [=](auto sentinel, unsigned int i) {
1029 using T = decltype(sentinel);
1031 using precomputed_type = typename View::precomputed_type;
1032
1033 const unsigned int row_length = sparsity_simd_view.row_length(i);
1034 if (skip_constrained_dofs && row_length == 1)
1035 return;
1036
1037 const auto view = hyperbolic_system_views.template view<T>();
1038
1039 const auto U_i = U_view.template read_tensor<T>(i);
1040 const auto rho_i = view.density(U_i);
1041 const auto e_i = view.internal_energy(U_i) / rho_i;
1042
1043 /* Calls into the selected equation of state: */
1044 const auto p_i = view.eos_pressure(rho_i, e_i);
1045
1046 const auto gamma_i = view.surrogate_gamma(U_i, p_i);
1047 const precomputed_type prec_i{p_i, gamma_i, T(0.), T(0.)};
1048 precomputed_view.template write_tensor<T>(prec_i, i);
1049 };
1050
1051 loop<HostSpace, ScalarNumber>(
1052 "hyperbolic_kernel_01b", body, 0, n_internal, n_owned);
1053 }
1054
1055 if constexpr (transfer) {
1056 /* Drop the (now stale) host mirror unless it was resident before: */
1057 if (!host_resident)
1058 U.template move_to_memory_space<MemorySpace>();
1059 precomputed.template move_to_memory_space<MemorySpace>();
1060 }
1061
1062 precomputed.template view<ScalarView::n_precomputed_values, MemorySpace>()
1063 .update_ghost_values();
1064
1065 /*
1066 * Compute gamma_min over the stencil:
1067 */
1068
1069 {
1070 const auto sparsity_simd_view =
1071 offline_data.sparsity_pattern_simd().template view<MemorySpace>();
1072
1073 /* We only read the hyperbolic state vector: */
1074 const auto U_view =
1075 std::as_const(U)
1076 .template view<ScalarView::problem_dimension, MemorySpace>();
1077 const auto precomputed_view =
1079 .template view<ScalarView::n_precomputed_values, MemorySpace>();
1080
1081 const auto hyperbolic_system_views =
1082 make_select_view<dim, ScalarNumber, MemorySpace>(*this);
1083
1084 const auto body = [=](auto sentinel, unsigned int i) {
1085 using T = decltype(sentinel);
1087 using PT = typename View::precomputed_type;
1088
1089 const unsigned int row_length = sparsity_simd_view.row_length(i);
1090 if (skip_constrained_dofs && row_length == 1)
1091 return;
1092
1093 const auto view = hyperbolic_system_views.template view<T>();
1094
1095 const auto U_i = U_view.template read_tensor<T>(i);
1096 auto prec_i = precomputed_view.template read_tensor<T, PT>(i);
1097 /* Previous loop: gamma_min_i == gamma_i, s_i == 0, eta_i == 0 */
1098 auto &[p_i, gamma_min_i, s_i, eta_i] = prec_i;
1099
1100 const unsigned int stride_size = sparsity_simd_view.stride_of_row(i);
1101 const unsigned int *js = sparsity_simd_view.columns(i) + stride_size;
1102 for (unsigned int col_idx = 1; col_idx < row_length;
1103 ++col_idx, js += stride_size) {
1104
1105 const auto U_j = U_view.template read_tensor<T>(js);
1106 const auto prec_j =
1107 precomputed_view.template read_tensor<T, PT>(js);
1108 const auto p_j = std::get<0>(prec_j);
1109 const auto gamma_j = view.surrogate_gamma(U_j, p_j);
1110 gamma_min_i = std::min(gamma_min_i, gamma_j);
1111 }
1112
1113 s_i = view.surrogate_specific_entropy(U_i, gamma_min_i);
1114 eta_i = view.surrogate_harten_entropy(U_i, gamma_min_i);
1115 precomputed_view.template write_tensor<T>(prec_i, i);
1116 };
1117
1118 loop<MemorySpace, ScalarNumber>(
1119 "hyperbolic_kernel_01c", body, 0, n_internal, n_owned);
1120 }
1121 }
1122
1123
1124 template <int dim, typename Number, typename MemorySpace>
1125 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1130
1131
1132 template <int dim, typename Number, typename MemorySpace>
1133 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1135 const Number &rho) const
1136 {
1137 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
1138 const Number rho_cutoff_large =
1139 reference_density() * vacuum_state_relaxation_large() * eps;
1140
1141 return ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1142 std::abs(rho), rho_cutoff_large, Number(0.), rho);
1143 }
1144
1145
1146 template <int dim, typename Number, typename MemorySpace>
1147 DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor<1, dim, Number>
1149 const state_type &U)
1150 {
1151 dealii::Tensor<1, dim, Number> result;
1152 for (unsigned int i = 0; i < dim; ++i)
1153 result[i] = U[1 + i];
1154 return result;
1155 }
1156
1157
1158 template <int dim, typename Number, typename MemorySpace>
1159 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1161 const state_type &U)
1162 {
1163 return U[1 + dim];
1164 }
1165
1166
1167 template <int dim, typename Number, typename MemorySpace>
1168 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1170 const state_type &U)
1171 {
1172 /*
1173 * rho e = (E - 1/2*m^2/rho)
1174 */
1175 const Number rho_inverse = ScalarNumber(1.) / density(U);
1176 const auto m = momentum(U);
1177 const Number E = total_energy(U);
1178 return E - ScalarNumber(0.5) * m.norm_square() * rho_inverse;
1179 }
1180
1181
1182 template <int dim, typename Number, typename MemorySpace>
1183 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1185 const state_type &U) -> state_type
1186 {
1187 /*
1188 * With
1189 * rho e = E - 1/2 |m|^2 / rho
1190 * we get
1191 * (rho e)' = (1/2m^2/rho^2, -m/rho , 1 )^T
1192 */
1193
1194 const Number rho_inverse = ScalarNumber(1.) / density(U);
1195 const auto u = momentum(U) * rho_inverse;
1196
1197 state_type result;
1198
1199 result[0] = ScalarNumber(0.5) * u.norm_square();
1200 for (unsigned int i = 0; i < dim; ++i) {
1201 result[1 + i] = -u[i];
1202 }
1203 result[dim + 1] = ScalarNumber(1.);
1204
1205 return result;
1206 }
1207
1208
1209 template <int dim, typename Number, typename MemorySpace>
1210 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1212 const state_type &U, const Number &gamma_min) const
1213 {
1214 const auto b = Number(eos_covolume_constant());
1215 const auto pinf = Number(eos_interpolation_pinfty());
1216 const auto q = Number(eos_interpolation_q());
1217
1218 const auto rho = density(U);
1219 const auto rho_inverse = ScalarNumber(1.) / rho;
1220
1221 const auto covolume = Number(1.) - b * rho;
1222
1223 const auto shift = internal_energy(U) - rho * q - pinf * covolume;
1224
1225 return shift * ryujin::pow(rho_inverse - b, gamma_min) / covolume;
1226 }
1227
1228
1229 template <int dim, typename Number, typename MemorySpace>
1230 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1232 const state_type &U, const Number &gamma_min) const
1233 {
1234 const auto b = Number(eos_covolume_constant());
1235 const auto pinf = Number(eos_interpolation_pinfty());
1236 const auto q = Number(eos_interpolation_q());
1237
1238 const auto rho = density(U);
1239 const auto m = momentum(U);
1240 const auto E = total_energy(U);
1241 const auto rho_rho_e_q =
1242 rho * E - ScalarNumber(0.5) * m.norm_square() - rho * rho * q;
1243
1244 const auto exponent = ScalarNumber(1.) / (gamma_min + Number(1.));
1245
1246 const auto covolume = Number(1.) - b * rho;
1247 const auto covolume_term = ryujin::pow(covolume, gamma_min - Number(1.));
1248
1249 const auto rho_pinfcov = rho * pinf * covolume;
1250
1251 return ryujin::pow(
1252 positive_part(rho_rho_e_q - rho_pinfcov) * covolume_term, exponent);
1253 }
1254
1255
1256 template <int dim, typename Number, typename MemorySpace>
1257 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1260 const Number &eta,
1261 const Number &gamma_min) const
1262 -> state_type
1263 {
1264 /*
1265 * With
1266 * eta = (shift * (1-b*rho)^{gamma-1}) ^ {1/(gamma+1)},
1267 * shift = rho * E - 1/2 |m|^2 - rho^2 * q - p_infty * rho * (1 - b rho)
1268 *
1269 * shift' = [E - 2 * rho * q - p_infty * (1 - 2 b rho), -m, rho]^T
1270 * factor = 1/(gamma+1) * (eta/(1-b rho))^-gamma / (1-b rho)^2
1271 *
1272 * we get
1273 *
1274 * eta' = factor * (1-b*rho) * shift' -
1275 * factor * shift * (gamma - 1) * b * [1, 0, 0]^T
1276 *
1277 */
1278 const auto b = Number(eos_covolume_constant());
1279 const auto pinf = Number(eos_interpolation_pinfty());
1280 const auto q = Number(eos_interpolation_q());
1281
1282 const auto rho = density(U);
1283 const auto m = momentum(U);
1284 const auto E = total_energy(U);
1285
1286 const auto covolume = Number(1.) - b * rho;
1287 const auto covolume_inverse = ScalarNumber(1.) / covolume;
1288
1289 const auto shift = rho * E - ScalarNumber(0.5) * m.norm_square() -
1290 rho * rho * q - rho * pinf * covolume;
1291
1292 constexpr auto eps = std::numeric_limits<ScalarNumber>::epsilon();
1293 const auto regularization = m.norm() * eps;
1294 const auto max_val = ryujin::pow(
1295 std::max(regularization, eta * covolume_inverse), gamma_min);
1296 auto factor = safe_division(Number(1.0), max_val);
1297 factor *= fixed_power<2>(covolume_inverse) / (gamma_min + Number(1.));
1298
1299 state_type result;
1300
1301 const auto first_term = E - ScalarNumber(2.) * rho * q -
1302 pinf * (Number(1.) - ScalarNumber(2.) * b * rho);
1303 const auto second_term = -(gamma_min - Number(1.)) * shift * b;
1304
1305 result[0] = factor * (covolume * first_term + second_term);
1306 for (unsigned int i = 0; i < dim; ++i)
1307 result[1 + i] = -factor * covolume * m[i];
1308 result[dim + 1] = factor * covolume * rho;
1309
1310 return result;
1311 }
1312
1313
1314 template <int dim, typename Number, typename MemorySpace>
1315 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1317 const state_type &U, const Number &p) const
1318 {
1319 const auto b = Number(eos_covolume_constant());
1320 const auto pinf = Number(eos_interpolation_pinfty());
1321 const auto q = Number(eos_interpolation_q());
1322
1323 const auto rho = density(U);
1324 const auto rho_e = internal_energy(U);
1325 const auto covolume = Number(1.) - b * rho;
1326
1327 const auto numerator = (p + pinf) * covolume;
1328 const auto denominator = rho_e - rho * q - covolume * pinf;
1329 return Number(1.) + safe_division(numerator, denominator);
1330 }
1331
1332
1333 template <int dim, typename Number, typename MemorySpace>
1334 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1336 const state_type &U, const Number &gamma) const
1337 {
1338 const auto b = Number(eos_covolume_constant());
1339 const auto pinf = Number(eos_interpolation_pinfty());
1340 const auto q = Number(eos_interpolation_q());
1341
1342 const auto rho = density(U);
1343 const auto rho_e = internal_energy(U);
1344 const auto covolume = Number(1.) - b * rho;
1345
1346 return positive_part(gamma - Number(1.)) *
1347 safe_division(rho_e - rho * q, covolume) -
1348 gamma * pinf;
1349 }
1350
1351
1352 template <int dim, typename Number, typename MemorySpace>
1353 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1355 const state_type &U, const Number &gamma) const
1356 {
1357 const auto b = Number(eos_covolume_constant());
1358 const auto pinf = Number(eos_interpolation_pinfty());
1359 const auto q = Number(eos_interpolation_q());
1360
1361 const auto rho = density(U);
1362 const auto rho_e = internal_energy(U);
1363 const auto covolume = Number(1.) - b * rho;
1364
1365 auto radicand =
1366 (rho_e - rho * q - pinf * covolume) / (covolume * covolume * rho);
1367 radicand *= gamma * (gamma - 1.);
1368 return std::sqrt(positive_part(radicand));
1369 }
1370
1371
1372 template <int dim, typename Number, typename MemorySpace>
1373 DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool
1375 const state_type &U) const
1376 {
1377 const auto b = Number(eos_covolume_constant());
1378 const auto pinf = Number(eos_interpolation_pinfty());
1379 const auto q = Number(eos_interpolation_q());
1380
1381 const auto rho = density(U);
1382 const auto rho_e = internal_energy(U);
1383 const auto covolume = Number(1.) - b * rho;
1384
1385 const auto shift = rho_e - rho * q - pinf * covolume;
1386
1387 constexpr auto gt = dealii::SIMDComparison::greater_than;
1388 using T = Number;
1389 const auto test =
1390 ryujin::compare_and_apply_mask<gt>(rho, T(0.), T(0.), T(-1.)) + //
1391 ryujin::compare_and_apply_mask<gt>(shift, T(0.), T(0.), T(-1.));
1392
1393#ifdef DEBUG_OUTPUT
1394 if (!(test == Number(0.))) {
1395 std::cout << std::fixed << std::setprecision(16);
1396 std::cout << "Bounds violation: Negative state [rho, e] detected!\n";
1397 std::cout << "\t\trho: " << rho << "\n";
1398 std::cout << "\t\tint (shifted): " << shift << "\n";
1399 }
1400#endif
1401
1402 return (test == Number(0.));
1403 }
1404
1405
1406 template <int dim, typename Number, typename MemorySpace>
1407 template <int component>
1408 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1411 const state_type &U,
1412 const Number &p,
1413 const state_type &U_bar,
1414 const Number &p_bar,
1415 const dealii::Tensor<1, dim, Number> &normal) const -> state_type
1416 {
1417 static_assert(component == 1 || component == 2,
1418 "component has to be 1 or 2");
1419
1420 const auto b = Number(eos_covolume_constant());
1421 const auto pinf = Number(eos_interpolation_pinfty());
1422 const auto q = Number(eos_interpolation_q());
1423
1424 /*
1425 * The "four" Riemann characteristics are formed under the assumption
1426 * of a locally isentropic flow. For this, we first transform both
1427 * states into {rho, vn, vperp, gamma, a}, where we use the NASG EOS
1428 * interpolation to derive a surrogate gamma and speed of sound a.
1429 *
1430 * See, e.g., https://arxiv.org/pdf/2004.08750, "Compressible flow in
1431 * a NOble-Abel Stiffened-Gas fluid", M. I. Radulescu.
1432 */
1433
1434 const auto m = momentum(U);
1435 const auto rho = density(U);
1436 const auto vn = m * normal / rho;
1437
1438 const auto gamma = surrogate_gamma(U, p);
1439 const auto a = surrogate_speed_of_sound(U, gamma);
1440 const auto covolume = 1. - b * rho;
1441
1442 const auto m_bar = momentum(U_bar);
1443 const auto rho_bar = density(U_bar);
1444 const auto vn_bar = m_bar * normal / rho_bar;
1445
1446 const auto gamma_bar = surrogate_gamma(U_bar, p_bar);
1447 const auto a_bar = surrogate_speed_of_sound(U_bar, gamma_bar);
1448 const auto covolume_bar = 1. - b * rho_bar;
1449
1450 /*
1451 * Now compute the Riemann characteristics {R_1, R_2, vperp, s}:
1452 * R_1 = v * n - 2 / (gamma - 1) * a * (1 - b * rho)
1453 * R_2 = v * n + 2 / (gamma - 1) * a * (1 - b * rho)
1454 * vperp
1455 * S = (p + p_infty) / rho^gamma * (1 - b * rho)^gamma
1456 *
1457 * Here, we replace either R_1, or R_2 with values coming from U_bar:
1458 */
1459
1460 const auto R_1 =
1461 component == 1 ? vn_bar - 2. * a_bar / (gamma_bar - 1.) * covolume_bar
1462 : vn - 2. * a / (gamma - 1.) * covolume;
1463
1464 const auto R_2 =
1465 component == 2 ? vn_bar + 2. * a_bar / (gamma_bar - 1.) * covolume_bar
1466 : vn + 2. * a / (gamma - 1.) * covolume;
1467
1468 /*
1469 * Note that we are really hoping for the best here... We require
1470 * that R_2 >= R_1 so that we can extract a valid sound speed...
1471 */
1472
1473 Assert(
1474 R_2 >= R_1,
1475 dealii::ExcMessage("Encountered R_2 < R_1 in dynamic boundary value "
1476 "enforcement. This implies that the interpolation "
1477 "with Riemann characteristics failed."));
1478
1479 const auto vperp = m / rho - vn * normal;
1480
1481 const auto S = (p + pinf) * ryujin::pow(Number(1.) / rho - b, gamma);
1482
1483 /*
1484 * Now, we have to reconstruct the actual conserved state U from the
1485 * Riemann characteristics R_1, R_2, vperp, and s. We first set up
1486 * {vn_new, vperp_new, a_new, S} and then solve for {rho_new, p_new}
1487 * with the help of the NASG EOS surrogate formulas:
1488 *
1489 * S = (p + p_infty) / rho^gamma * (1 - b * rho)^gamma
1490 *
1491 * a^2 = gamma * (p + p_infty) / (rho * cov)
1492 *
1493 * This implies:
1494 *
1495 * a^2 / (gamma * S) = rho^{gamma - 1} / (1 - b * rho)^{1 + gamma}
1496 */
1497
1498 const auto vn_new = Number(0.5) * (R_1 + R_2);
1499
1500 /*
1501 * Technically, we would need to solve for rho subject to a number of
1502 * nonlinear relationships:
1503 *
1504 * a = (gamma - 1) * (R_2 - R_1) / (4. * (1 - b * rho))
1505 *
1506 * a^2 / (gamma * S) = rho^{gamma - 1} / (1 - b * rho)^{gamma + 1}
1507 *
1508 * This seems to be a bit expensive for the fact that our dynamic
1509 * boundary conditions are already terribly heuristic...
1510 *
1511 * So instead, we rewrite this system as:
1512 *
1513 * a * (1 - b * rho) = (gamma - 1) * (R_2 - R_1) / 4.
1514 *
1515 * a^2 / (gamma * S) (1 - b * rho)^2
1516 * = (rho / (1 - b * rho))^{gamma - 1}
1517 *
1518 * And compute the terms on the left simply with the old covolume and
1519 * solving an easier easier nonlinear equation for the density. The
1520 * resulting system reads:
1521 *
1522 * a = (gamma - 1) * (R_2 - R_1) / (4. * (1 - b * rho_old))
1523 * A = {a^2 / (gamma * S) (1 - b * rho_old)^{2 gamma}}^{1/(gamma - 1)}
1524 *
1525 * rho = A / (1 + b * A)
1526 */
1527
1528 const auto a_new_square =
1529 ryujin::fixed_power<2>((gamma - 1.) * (R_2 - R_1) / (4. * covolume));
1530
1531 auto term = ryujin::pow(a_new_square / (gamma * S), 1. / (gamma - 1.));
1532 if (b != ScalarNumber(0.)) {
1533 term *= ryujin::pow(covolume, 2. / (gamma - 1.));
1534 }
1535
1536 const auto rho_new = term / (1. + b * term);
1537
1538 const auto covolume_new = (1. - b * rho_new);
1539 const auto p_new = a_new_square / gamma * rho_new * covolume_new - pinf;
1540
1541 /*
1542 * And translate back into conserved quantities:
1543 */
1544
1545 const auto rho_e_new =
1546 rho_new * q + (p_new + gamma * pinf) * covolume_new / (gamma - 1.);
1547
1548 state_type U_new;
1549 U_new[0] = rho_new;
1550 for (unsigned int d = 0; d < dim; ++d) {
1551 U_new[1 + d] = rho_new * (vn_new * normal + vperp)[d];
1552 }
1553 U_new[1 + dim] =
1554 rho_e_new + 0.5 * rho_new * (vn_new * vn_new + vperp.norm_square());
1555
1556 return U_new;
1557 }
1558
1559
1560 template <int dim, typename Number, typename MemorySpace>
1561 template <typename Lambda>
1562 DEAL_II_ALWAYS_INLINE inline auto
1564 dealii::types::boundary_id id,
1565 const state_type &U,
1566 const dealii::Tensor<1, dim, Number> &normal,
1567 const Lambda &get_dirichlet_data) const -> state_type
1568 {
1569 state_type result = U;
1570
1571 if (id == Boundary::dirichlet) {
1572 result = get_dirichlet_data();
1573
1574 } else if (id == Boundary::dirichlet_momentum) {
1575 /*
1576 * Only enforce Dirichlet conditions on the momentum, and keep the
1577 * internal energy constant:
1578 */
1579 const auto m_dirichlet = momentum(get_dirichlet_data());
1580 const auto rho = density(result);
1581 const auto m = momentum(result);
1582
1583 for (unsigned int k = 0; k < dim; ++k)
1584 result[k + 1] = m_dirichlet[k];
1585 result[dim + 1] +=
1586 Number(0.5) / rho * (m_dirichlet.norm_square() - m.norm_square());
1587
1588 } else if (id == Boundary::dirichlet_velocity) {
1589 /*
1590 * Only enforce Dirichlet conditions on the velocity, and keep the
1591 * internal energy constant:
1592 */
1593 const auto U_dirichlet = get_dirichlet_data();
1594 const auto rho_dirichlet = density(U_dirichlet);
1595 const auto v_dirichlet = momentum(U_dirichlet) / rho_dirichlet;
1596 const auto rho = density(result);
1597 const auto v = momentum(result) / rho;
1598
1599 for (unsigned int k = 0; k < dim; ++k)
1600 result[k + 1] = rho * v_dirichlet[k];
1601 result[dim + 1] +=
1602 Number(0.5) * rho * (v_dirichlet.norm_square() - v.norm_square());
1603
1604 } else if (id == Boundary::slip) {
1605 auto m = momentum(U);
1606 m -= 1. * (m * normal) * normal;
1607 for (unsigned int k = 0; k < dim; ++k)
1608 result[k + 1] = m[k];
1609
1610 } else if (id == Boundary::no_slip) {
1611 for (unsigned int k = 0; k < dim; ++k)
1612 result[k + 1] = Number(0.);
1613
1614 } else if (id == Boundary::dynamic) {
1615 /*
1616 * On dynamic boundary conditions, we distinguish four cases:
1617 *
1618 * - supersonic inflow: prescribe full state
1619 * - subsonic inflow:
1620 * decompose into Riemann invariants and leave R_2
1621 * characteristic untouched.
1622 * - supersonic outflow: do nothing
1623 * - subsonic outflow:
1624 * decompose into Riemann invariants and prescribe incoming
1625 * R_1 characteristic.
1626 */
1627 const auto m = momentum(U);
1628 const auto rho = density(U);
1629 const auto rho_e = internal_energy(U);
1630
1631 /*
1632 * We do not have precomputed values available. Thus, simply query
1633 * the pressure oracle and compute a surrogate speed of sound from
1634 * there:
1635 */
1636 const auto p = eos_pressure(rho, rho_e / rho);
1637 const auto gamma = surrogate_gamma(U, p);
1638 const auto a = surrogate_speed_of_sound(U, gamma);
1639 const auto vn = m * normal / rho;
1640
1641 /* Supersonic inflow: */
1642 if (vn < -a) {
1643 result = get_dirichlet_data();
1644 }
1645
1646 /* Subsonic inflow: */
1647 if (vn >= -a && vn <= 0.) {
1648 const auto U_dirichlet = get_dirichlet_data();
1649 const auto rho_dirichlet = density(U_dirichlet);
1650 const auto rho_e_dirichlet = internal_energy(U_dirichlet);
1651 const auto p_dirichlet =
1652 eos_pressure(rho_dirichlet, rho_e_dirichlet / rho_dirichlet);
1653
1654 result = prescribe_riemann_characteristic<2>(
1655 U_dirichlet, p_dirichlet, U, p, normal);
1656 }
1657
1658 /* Subsonic outflow: */
1659 if (vn > 0. && vn <= a) {
1660 const auto U_dirichlet = get_dirichlet_data();
1661 const auto rho_dirichlet = density(U_dirichlet);
1662 const auto rho_e_dirichlet = internal_energy(U_dirichlet);
1663 const auto p_dirichlet =
1664 eos_pressure(rho_dirichlet, rho_e_dirichlet / rho_dirichlet);
1665
1666 result = prescribe_riemann_characteristic<1>(
1667 U, p, U_dirichlet, p_dirichlet, normal);
1668 }
1669 /* Supersonic outflow: do nothing, i.e., keep U as is */
1670
1671 } else {
1672 AssertThrow(false, dealii::ExcNotImplemented());
1673 }
1674
1675 return result;
1676 }
1677
1678
1679 template <int dim, typename Number, typename MemorySpace>
1680 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1682 const Number &p) const
1683 -> flux_type
1684 {
1685 const auto rho_inverse = ScalarNumber(1.) / density(U);
1686 const auto m = momentum(U);
1687 const auto E = total_energy(U);
1688
1689 flux_type result;
1690
1691 result[0] = m;
1692 for (unsigned int i = 0; i < dim; ++i) {
1693 result[1 + i] = m * (m[i] * rho_inverse);
1694 result[1 + i][i] += p;
1695 }
1696 result[dim + 1] = m * (rho_inverse * (E + p));
1697
1698 return result;
1699 }
1700
1701
1702 template <int dim, typename Number, typename MemorySpace>
1703 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1705 const PrecomputedVectorView &pv,
1706 const InitialPrecomputedVectorView & /*piv*/,
1707 const unsigned int i,
1708 const state_type &U_i) const -> flux_contribution_type
1709 {
1710 const auto &[p_i, gamma_min_i, s_i, eta_i] =
1711 pv.template read_tensor<Number, precomputed_type>(i);
1712 return f(U_i, p_i);
1713 }
1714
1715
1716 template <int dim, typename Number, typename MemorySpace>
1717 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1719 const PrecomputedVectorView &pv,
1720 const InitialPrecomputedVectorView & /*piv*/,
1721 const unsigned int *js,
1722 const state_type &U_j) const -> flux_contribution_type
1723 {
1724 const auto &[p_j, gamma_min_j, s_j, eta_j] =
1725 pv.template read_tensor<Number, precomputed_type>(js);
1726 return f(U_j, p_j);
1727 }
1728
1729
1730 template <int dim, typename Number, typename MemorySpace>
1731 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1733 const flux_contribution_type &flux_i,
1734 const flux_contribution_type &flux_j,
1735 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1736 {
1737 return -contract(add(flux_i, flux_j), c_ij);
1738 }
1739
1740
1741 template <int dim, typename Number, typename MemorySpace>
1742 template <typename ST>
1743 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1745 const ST &state) const -> state_type
1746 {
1747 using T = typename ST::value_type;
1748 static_assert(std::is_same_v<Number, T>, "template mismatch");
1749
1750 constexpr auto dim2 = ST::dimension - 2;
1751 static_assert(dim >= dim2,
1752 "the space dimension of the argument state must not be "
1753 "larger than the one of the target state");
1754
1755 state_type result;
1756 result[0] = state[0];
1757 result[dim + 1] = state[dim2 + 1];
1758 for (unsigned int i = 1; i < dim2 + 1; ++i)
1759 result[i] = state[i];
1760
1761 return result;
1762 }
1763
1764
1765 template <int dim, typename Number, typename MemorySpace>
1766 template <typename ST>
1767 DEAL_II_ALWAYS_INLINE inline auto
1769 const ST &initial_state) const -> state_type
1770 {
1771 auto primitive_state = expand_state(initial_state);
1772
1773 /* pressure into specific internal energy: */
1774 const auto rho = density(primitive_state);
1775 const auto p = /*SIC!*/ total_energy(primitive_state);
1776 const auto e = eos_specific_internal_energy(rho, p);
1777 primitive_state[dim + 1] = e;
1778
1779 return from_primitive_state(primitive_state);
1780 }
1781
1782
1783 template <int dim, typename Number, typename MemorySpace>
1784 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1786 const state_type &primitive_state) const -> state_type
1787 {
1788 const auto rho = density(primitive_state);
1789 /* extract velocity: */
1790 const auto u = /*SIC!*/ momentum(primitive_state);
1791 /* extract specific internal energy: */
1792 const auto &e = /*SIC!*/ total_energy(primitive_state);
1793
1794 auto state = primitive_state;
1795 /* Fix up momentum: */
1796 for (unsigned int i = 1; i < dim + 1; ++i)
1797 state[i] *= rho;
1798
1799 /* Compute total energy: */
1800 state[dim + 1] = rho * e + Number(0.5) * rho * u * u;
1801
1802 return state;
1803 }
1804
1805
1806 template <int dim, typename Number, typename MemorySpace>
1807 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1809 const state_type &state) const -> state_type
1810 {
1811 const auto rho = density(state);
1812 const auto rho_inverse = Number(1.) / rho;
1813 const auto rho_e = internal_energy(state);
1814
1815 auto primitive_state = state;
1816 /* Fix up velocity: */
1817 for (unsigned int i = 1; i < dim + 1; ++i)
1818 primitive_state[i] *= rho_inverse;
1819 /* Set specific internal energy: */
1820 primitive_state[dim + 1] = rho_e * rho_inverse;
1821
1822 return primitive_state;
1823 }
1824
1825
1826 template <int dim, typename Number, typename MemorySpace>
1827 template <typename Lambda>
1828 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1830 const state_type &state, const Lambda &lambda) const -> state_type
1831 {
1832 auto result = state;
1833 const auto M = lambda(momentum(state));
1834 for (unsigned int d = 0; d < dim; ++d)
1835 result[1 + d] = M[d];
1836 return result;
1837 }
1838 } // namespace EulerAEOS
1839} // namespace ryujin
DEAL_II_HOST_DEVICE flux_contribution_type flux_contribution(const PrecomputedVectorView &pv, const InitialPrecomputedVectorView &piv, const unsigned int i, const state_type &U_i) const
state_type from_initial_state(const ST &initial_state) const
DEAL_II_HOST_DEVICE state_type to_primitive_state(const state_type &state) const
DEAL_II_HOST_DEVICE state_type from_primitive_state(const state_type &primitive_state) const
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
dealii::Tensor< 1, problem_dimension, Number > state_type
DEAL_II_HOST_DEVICE Number surrogate_harten_entropy(const state_type &U, const Number &gamma_min) const
static DEAL_II_HOST_DEVICE Number density(const state_type &U)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber eos_interpolation_pinfty() const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber eos_interpolation_q() const
static constexpr unsigned int n_initial_precomputed_values
static DEAL_II_HOST_DEVICE dealii::Tensor< 1, dim, Number > momentum(const state_type &U)
DEAL_II_HOST_DEVICE Number filter_vacuum_density(const Number &rho) const
DEAL_II_ALWAYS_INLINE Number eos_temperature(const Number &rho, const Number &e) const
static DEAL_II_HOST_DEVICE Number internal_energy(const state_type &U)
DEAL_II_ALWAYS_INLINE Number eos_cold_curve_bound(const Number &rho) const
typename get_value_type< Number >::type ScalarNumber
DEAL_II_HOST_DEVICE Number surrogate_speed_of_sound(const state_type &U, const Number &gamma) const
static DEAL_II_HOST_DEVICE state_type internal_energy_derivative(const state_type &U)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber reference_density() const
HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
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
DEAL_II_HOST_DEVICE Number surrogate_pressure(const state_type &U, const Number &gamma) const
std::array< Number, n_precomputed_values > precomputed_type
DEAL_II_HOST_DEVICE Number surrogate_gamma(const state_type &U, const Number &p) const
DEAL_II_HOST_DEVICE state_type apply_galilei_transform(const state_type &state, const Lambda &lambda) const
DEAL_II_ALWAYS_INLINE Number eos_specific_entropy(const Number &rho, const Number &e) const
DEAL_II_HOST_DEVICE 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_HOST_DEVICE bool is_admissible(const state_type &U) const
DEAL_II_HOST_DEVICE state_type nodal_source(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const =delete
std::array< Number, n_initial_precomputed_values > initial_precomputed_type
static DEAL_II_HOST_DEVICE Number total_energy(const state_type &U)
DEAL_II_HOST_DEVICE Number surrogate_specific_entropy(const state_type &U, const Number &gamma_min) const
DEAL_II_ALWAYS_INLINE Number eos_specific_internal_energy(const Number &rho, const Number &p) const
DEAL_II_HOST_DEVICE 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_HOST_DEVICE_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_large() const
static constexpr unsigned int problem_dimension
DEAL_II_HOST_DEVICE 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 Number eos_speed_of_sound(const Number &rho, const Number &e) const
static constexpr unsigned int n_precomputed_values
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber eos_covolume_constant() const
DEAL_II_HOST_DEVICE state_type surrogate_harten_entropy_derivative(const state_type &U, const Number &eta, const Number &gamma_min) const
DEAL_II_HOST_DEVICE state_type expand_state(const ST &state) const
DEAL_II_ALWAYS_INLINE Number eos_pressure(const Number &rho, const Number &e) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool compute_strict_bounds() const
DEAL_II_HOST_DEVICE flux_type f(const state_type &U, const Number &p) const
DEAL_II_ALWAYS_INLINE const std::string & equation_of_state() const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_small() const
DEAL_II_HOST_DEVICE 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
void fill_precomputed_values(const OfflineData< dim, ScalarNumber > &offline_data, StateVector< ScalarNumber > &state_vector, const bool skip_constrained_dofs=true) const
HyperbolicSystem(const std::string &subsection="/HyperbolicSystem")
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)
constexpr bool have_separate_memory_spaces
Definition gpu.h:29
@ 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:134
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number safe_division(const Number &numerator, const Number &denominator)
Definition simd.h:164
std::set< std::shared_ptr< EquationOfState > > equation_of_state_list_type
MultiComponentVector< Number > U
MultiComponentVector< Number > precomputed