ryujin 2.5.0 revision c64172211cf21344cb9b9b0f3a1266aa6400d392
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 <ryujin/base/compile_time_options.h>
10#include <ryujin/base/gpu.h>
11#include <ryujin/base/loop.h>
13#include <ryujin/base/simd.h>
19
20#include <deal.II/base/memory_space.h>
21#include <deal.II/base/parameter_acceptor.h>
22#include <deal.II/base/tensor.h>
23
24#include <array>
25#include <memory>
26#include <string>
27#include <vector>
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
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
154 std::vector<std::unique_ptr<EquationOfState>> equation_of_state_list_;
155
156 const EquationOfState *selected_equation_of_state_ = nullptr;
157
158 template <int, typename, typename>
160
162 }; /* HyperbolicSystem */
163
164
186 template <int dim, typename Number, typename MemorySpace>
188 {
189 public:
190 static_assert(
191 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
192 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
193 "Unexpected memory space");
194
199
204
208 static constexpr unsigned int problem_dimension = 2 + dim;
209
213 using state_type = dealii::Tensor<1, problem_dimension, Number>;
214
218 using flux_type =
219 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
220
225
229 static constexpr unsigned int n_precomputed_values = 4;
230
234 using precomputed_type = std::array<Number, n_precomputed_values>;
235
239 static constexpr unsigned int n_initial_precomputed_values = 0;
240
245 std::array<Number, n_initial_precomputed_values>;
246
247 template <int n_comp>
250
256
263
265
269
274 HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
275 : parameters_(
276 hyperbolic_system.parameters_.template view<MemorySpace>())
277 , equation_of_state_(hyperbolic_system.selected_equation_of_state_)
278 {
279 }
280
282
286
292 DEAL_II_ALWAYS_INLINE inline const std::string &equation_of_state() const
293 {
294 return equation_of_state_->name();
295 }
296
297 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber reference_density() const
298 {
299 return ScalarNumber(parameters_->reference_density);
300 }
301
302 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
304 {
305 return ScalarNumber(parameters_->vacuum_state_relaxation_small);
306 }
307
308 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
310 {
311 return ScalarNumber(parameters_->vacuum_state_relaxation_large);
312 }
313
314 DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool compute_strict_bounds() const
315 {
316 return parameters_->compute_strict_bounds;
317 }
318
320
330
335 DEAL_II_ALWAYS_INLINE inline Number eos_pressure(const Number &rho,
336 const Number &e) const
337 {
338 const auto &eos = equation_of_state_;
339
340 if constexpr (std::is_same_v<ScalarNumber, Number>) {
341 return ScalarNumber(eos->pressure(rho, e));
342 } else {
343 Number p;
344 for (unsigned int k = 0; k < Number::size(); ++k) {
345 p[k] = ScalarNumber(eos->pressure(rho[k], e[k]));
346 }
347 return p;
348 }
349 }
350
355 DEAL_II_ALWAYS_INLINE inline Number
356 eos_specific_internal_energy(const Number &rho, const Number &p) const
357 {
358 const auto &eos = equation_of_state_;
359
360 if constexpr (std::is_same_v<ScalarNumber, Number>) {
361 return ScalarNumber(eos->specific_internal_energy(rho, p));
362 } else {
363 Number e;
364 for (unsigned int k = 0; k < Number::size(); ++k) {
365 e[k] = ScalarNumber(eos->specific_internal_energy(rho[k], p[k]));
366 }
367 return e;
368 }
369 }
370
375 DEAL_II_ALWAYS_INLINE inline Number
376 eos_specific_entropy(const Number &rho, const Number &e) const
377 {
378 const auto &eos = equation_of_state_;
379
380 if constexpr (std::is_same_v<ScalarNumber, Number>) {
381 return ScalarNumber(eos->specific_entropy(rho, e));
382 } else {
383 Number p;
384 for (unsigned int k = 0; k < Number::size(); ++k) {
385 p[k] = ScalarNumber(eos->specific_entropy(rho[k], e[k]));
386 }
387 return p;
388 }
389 }
390
395 DEAL_II_ALWAYS_INLINE inline Number
396 eos_cold_curve_bound(const Number &rho) const
397 {
398 const auto &eos = equation_of_state_;
399
400 if constexpr (std::is_same_v<ScalarNumber, Number>) {
401 return ScalarNumber(eos->cold_curve_bound(rho));
402 } else {
403 Number p;
404 for (unsigned int k = 0; k < Number::size(); ++k) {
405 p[k] = ScalarNumber(eos->cold_curve_bound(rho[k]));
406 }
407 return p;
408 }
409 }
410
415 DEAL_II_ALWAYS_INLINE inline Number eos_temperature(const Number &rho,
416 const Number &e) const
417 {
418 const auto &eos = equation_of_state_;
419
420 if constexpr (std::is_same_v<ScalarNumber, Number>) {
421 return ScalarNumber(eos->temperature(rho, e));
422 } else {
423 Number temp;
424 for (unsigned int k = 0; k < Number::size(); ++k) {
425 temp[k] = ScalarNumber(eos->temperature(rho[k], e[k]));
426 }
427 return temp;
428 }
429 }
430
435 DEAL_II_ALWAYS_INLINE inline Number
436 eos_speed_of_sound(const Number &rho, const Number &e) const
437 {
438 const auto &eos = equation_of_state_;
439
440 if constexpr (std::is_same_v<ScalarNumber, Number>) {
441 return ScalarNumber(eos->speed_of_sound(rho, e));
442 } else {
443 Number c;
444 for (unsigned int k = 0; k < Number::size(); ++k) {
445 c[k] = ScalarNumber(eos->speed_of_sound(rho[k], e[k]));
446 }
447 return c;
448 }
449 }
450
454 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
456 {
457 return ScalarNumber(parameters_->covolume_constant);
458 }
459
463 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
465 {
466 return ScalarNumber(parameters_->interpolation_pinfty);
467 }
468
473 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber eos_interpolation_q() const
474 {
475 return ScalarNumber(parameters_->interpolation_q);
476 }
477
479
483
484 static constexpr bool have_gamma = false;
485 static constexpr bool have_covolume_constant = true;
486 static constexpr bool have_energy_equation = true;
487
489
493
498 static DEAL_II_HOST_DEVICE Number density(const state_type &U);
499
506 DEAL_II_HOST_DEVICE Number filter_vacuum_density(const Number &rho) const;
507
512 static DEAL_II_HOST_DEVICE dealii::Tensor<1, dim, Number>
513 momentum(const state_type &U);
514
519 static DEAL_II_HOST_DEVICE Number total_energy(const state_type &U);
520
525 static DEAL_II_HOST_DEVICE Number internal_energy(const state_type &U);
526
532 static DEAL_II_HOST_DEVICE state_type
534
536
542
552 DEAL_II_HOST_DEVICE Number surrogate_specific_entropy(
553 const state_type &U, const Number &gamma_min) const;
554
565 DEAL_II_HOST_DEVICE Number surrogate_harten_entropy(
566 const state_type &U, const Number &gamma_min) const;
567
578 DEAL_II_HOST_DEVICE state_type
580 const Number &eta,
581 const Number &gamma_min) const;
582
594 DEAL_II_HOST_DEVICE Number surrogate_gamma(const state_type &U,
595 const Number &p) const;
596
612 DEAL_II_HOST_DEVICE Number surrogate_pressure(const state_type &U,
613 const Number &gamma) const;
614
623 DEAL_II_HOST_DEVICE Number
624 surrogate_speed_of_sound(const state_type &U, const Number &gamma) const;
625
631 DEAL_II_HOST_DEVICE bool is_admissible(const state_type &U) const;
632
634
638
645 template <int component>
647 const state_type &U,
648 const Number &p,
649 const state_type &U_bar,
650 const Number &p_bar,
651 const dealii::Tensor<1, dim, Number> &normal) const;
652
675 template <typename Lambda>
677 apply_boundary_conditions(const dealii::types::boundary_id id,
678 const state_type &U,
679 const dealii::Tensor<1, dim, Number> &normal,
680 const Lambda &get_dirichlet_data) const;
681
683
687
698 DEAL_II_HOST_DEVICE flux_type f(const state_type &U,
699 const Number &p) const;
700
720 DEAL_II_HOST_DEVICE
724 const unsigned int i,
725 const state_type &U_i) const;
726
727 DEAL_II_HOST_DEVICE
731 const unsigned int *js,
732 const state_type &U_j) const;
733
738 DEAL_II_HOST_DEVICE
741 const flux_contribution_type &flux_j,
742 const dealii::Tensor<1, dim, Number> &c_ij) const;
743
747 static constexpr bool have_high_order_flux = false;
748
749 DEAL_II_HOST_DEVICE
751 const flux_contribution_type &flux_i,
752 const flux_contribution_type &flux_j,
753 const dealii::Tensor<1, dim, Number> &c_ij) const = delete;
754
756
760
762 static constexpr bool have_source_terms = false;
763
764 DEAL_II_HOST_DEVICE
766 const unsigned int i,
767 const state_type &U_i,
768 const ScalarNumber tau) const = delete;
769
770 DEAL_II_HOST_DEVICE
772 const unsigned int *js,
773 const state_type &U_j,
774 const ScalarNumber tau) const = delete;
775
777
781
792 template <typename ST>
793 DEAL_II_HOST_DEVICE state_type expand_state(const ST &state) const;
794
810 template <typename ST>
811 state_type from_initial_state(const ST &initial_state) const;
812
817 DEAL_II_HOST_DEVICE
818 state_type from_primitive_state(const state_type &primitive_state) const;
819
824 DEAL_II_HOST_DEVICE
826
832 template <typename Lambda>
834 const state_type &state, const Lambda &lambda) const;
835
836 private:
838
842
843 const HyperbolicSystem::Parameters *const parameters_;
844
845 /* Only valid (and dereferenced) on the host: */
846 const EquationOfState *const equation_of_state_;
847
849 }; /* HyperbolicSystemView */
850
851
852 /*
853 * -------------------------------------------------------------------------
854 * Inline definitions
855 * -------------------------------------------------------------------------
856 */
857
858
859 inline HyperbolicSystem::HyperbolicSystem(const std::string &subsection)
860 : Interface::HyperbolicSystem(
861 "Compressible Euler equations (arbitrary EOS)",
862 {{{"rho", "m", "E"},
863 {"rho", "m_1", "m_2", "E"},
864 {"rho", "m_1", "m_2", "m_3", "E"}}},
865 {{{"rho", "v", "e"},
866 {"rho", "v_1", "v_2", "e"},
867 {"rho", "v_1", "v_2", "v_3", "e"}}},
868 {{{"p",
869 "surrogate_gamma_min",
870 "surrogate_specific_entropy",
871 "surrogate_harten_entropy"},
872 {"p",
873 "surrogate_gamma_min",
874 "surrogate_specific_entropy",
875 "surrogate_harten_entropy"},
876 {"p",
877 "surrogate_gamma_min",
878 "surrogate_specific_entropy",
879 "surrogate_harten_entropy"}}},
880 {},
881 subsection)
882 , parameters_("euler_aeos_hyperbolic_system_parameters",
884 {
885 /* reference remains valid due to implicit_transfers_host_resident */
886 auto &parameters = *parameters_.view();
887
888 equation_of_state_list_ = EquationOfStateLibrary::create(subsection);
889
890 equation_of_state_ = "polytropic gas";
891 add_parameter(
892 "equation of state",
893 equation_of_state_,
894 "The equation of state. Valid names are given by any of the "
895 "subsections defined below",
896 this->prm,
897 EquationOfStateLibrary::selection(equation_of_state_list_));
898
899 parameters.compute_strict_bounds = true;
900 add_parameter(
901 "compute strict bounds",
902 parameters.compute_strict_bounds,
903 "Compute strict, but significantly more expensive bounds at various "
904 "places: (a) an expensive, but better upper wavespeed estimate in "
905 "the approximate WaveSpeedEstimator; (b) entropy "
906 "viscosity-commutator "
907 "with correct gamma_min over the stencil; (c) mathematically correct "
908 "surrogate specific entropy minimum with gamma_min over the "
909 "stencil.");
910
911 parameters.reference_density = 1.;
912 add_parameter("reference density",
913 parameters.reference_density,
914 "Problem specific density reference");
915
916 parameters.vacuum_state_relaxation_small = 1.e2;
917 add_parameter("vacuum state relaxation small",
918 parameters.vacuum_state_relaxation_small,
919 "Problem specific vacuum relaxation parameter");
920
921 parameters.vacuum_state_relaxation_large = 1.e4;
922 add_parameter("vacuum state relaxation large",
923 parameters.vacuum_state_relaxation_large,
924 "Problem specific vacuum relaxation parameter");
925
926 /*
927 * The equation of state classes update their interpolatory NASG
928 * parameters in their own parse_parameters_call_back signal, which
929 * is invoked after ours. Thus, also connect to theirs:
930 */
931 ParameterAcceptor::parse_parameters_call_back.connect(
932 [this] { update_parameters(); });
933 for (auto &it : equation_of_state_list_)
934 it->parse_parameters_call_back.connect([this] { update_parameters(); });
935
936 update_parameters();
937 }
938
939
940 inline void HyperbolicSystem::update_parameters()
941 {
942 selected_equation_of_state_ = &EquationOfStateLibrary::select(
943 equation_of_state_list_, equation_of_state_);
944 problem_name_ = "Compressible Euler equations (" +
945 selected_equation_of_state_->name() + " EOS)";
946
947 auto &parameters = *parameters_.view();
948
949 parameters.covolume_constant =
950 selected_equation_of_state_->covolume_constant();
951 parameters.interpolation_pinfty =
952 selected_equation_of_state_->interpolation_pinfty();
953 parameters.interpolation_q =
954 selected_equation_of_state_->interpolation_q();
955 }
956
957
958 template <typename MemorySpace, int dim, typename ScalarNumber>
960 const OfflineData<dim, ScalarNumber> &offline_data,
961 StateVector<ScalarNumber> &state_vector,
962 const bool skip_constrained_dofs) const
963 {
964 using HostSpace = dealii::MemorySpace::Host;
965
966 const unsigned int n_internal = offline_data.n_locally_internal();
967 const unsigned int n_owned = offline_data.n_locally_owned();
968
970
971 auto &U = state_vector.state;
972 auto &precomputed = state_vector.precomputed;
973
974 /*
975 * Compute the pressure (and an initial surrogate gamma_min) over the
976 * diagonal. This requires calling into the selected equation of
977 * state, which is only possible on the host memory space. Thus,
978 * temporarily transfer the state vector and the precomputed values
979 * to the host memory space:
980 */
981
982 constexpr bool transfer =
984 !std::is_same_v<MemorySpace, dealii::MemorySpace::Host>;
985
986 [[maybe_unused]] const bool host_resident =
987 U.template is_resident<HostSpace>();
988
989 if constexpr (transfer) {
990 U.template copy_to_memory_space<HostSpace>();
991 precomputed.template move_to_memory_space<HostSpace>();
992 }
993
994 {
995 const auto sparsity_simd_view =
996 offline_data.sparsity_pattern_simd().template view<HostSpace>();
997
998 /* We only read the hyperbolic state vector: */
999 const auto U_view =
1000 std::as_const(U)
1001 .template view<ScalarView::problem_dimension, HostSpace>();
1002 const auto precomputed_view =
1004 .template view<ScalarView::n_precomputed_values, HostSpace>();
1005
1006 const auto hyperbolic_system_views =
1007 make_select_view<dim, ScalarNumber, HostSpace>(*this);
1008
1009 const auto body = [=](auto sentinel, unsigned int i) {
1010 using T = decltype(sentinel);
1012 using precomputed_type = typename View::precomputed_type;
1013
1014 const unsigned int row_length = sparsity_simd_view.row_length(i);
1015 if (skip_constrained_dofs && row_length == 1)
1016 return;
1017
1018 const auto view = hyperbolic_system_views.template view<T>();
1019
1020 const auto U_i = U_view.template read_tensor<T>(i);
1021 const auto rho_i = view.density(U_i);
1022 const auto e_i = view.internal_energy(U_i) / rho_i;
1023
1024 /* Calls into the selected equation of state: */
1025 const auto p_i = view.eos_pressure(rho_i, e_i);
1026
1027 const auto gamma_i = view.surrogate_gamma(U_i, p_i);
1028 const precomputed_type prec_i{p_i, gamma_i, T(0.), T(0.)};
1029 precomputed_view.template write_tensor<T>(prec_i, i);
1030 };
1031
1032 loop<HostSpace, ScalarNumber>(
1033 "hyperbolic_kernel_01b", body, 0, n_internal, n_owned);
1034 }
1035
1036 if constexpr (transfer) {
1037 /* Drop the (now stale) host mirror unless it was resident before: */
1038 if (!host_resident)
1039 U.template move_to_memory_space<MemorySpace>();
1040 precomputed.template move_to_memory_space<MemorySpace>();
1041 }
1042
1043 precomputed.template view<ScalarView::n_precomputed_values, MemorySpace>()
1044 .update_ghost_values();
1045
1046 /*
1047 * Compute gamma_min over the stencil:
1048 */
1049
1050 {
1051 const auto sparsity_simd_view =
1052 offline_data.sparsity_pattern_simd().template view<MemorySpace>();
1053
1054 /* We only read the hyperbolic state vector: */
1055 const auto U_view =
1056 std::as_const(U)
1057 .template view<ScalarView::problem_dimension, MemorySpace>();
1058 const auto precomputed_view =
1060 .template view<ScalarView::n_precomputed_values, MemorySpace>();
1061
1062 const auto hyperbolic_system_views =
1063 make_select_view<dim, ScalarNumber, MemorySpace>(*this);
1064
1065 const auto body = [=](auto sentinel, unsigned int i) {
1066 using T = decltype(sentinel);
1068 using PT = typename View::precomputed_type;
1069
1070 const unsigned int row_length = sparsity_simd_view.row_length(i);
1071 if (skip_constrained_dofs && row_length == 1)
1072 return;
1073
1074 const auto view = hyperbolic_system_views.template view<T>();
1075
1076 const auto U_i = U_view.template read_tensor<T>(i);
1077 auto prec_i = precomputed_view.template read_tensor<T, PT>(i);
1078 /* Previous loop: gamma_min_i == gamma_i, s_i == 0, eta_i == 0 */
1079 auto &[p_i, gamma_min_i, s_i, eta_i] = prec_i;
1080
1081 const unsigned int stride_size = sparsity_simd_view.stride_of_row(i);
1082 const unsigned int *js = sparsity_simd_view.columns(i) + stride_size;
1083 for (unsigned int col_idx = 1; col_idx < row_length;
1084 ++col_idx, js += stride_size) {
1085
1086 const auto U_j = U_view.template read_tensor<T>(js);
1087 const auto prec_j =
1088 precomputed_view.template read_tensor<T, PT>(js);
1089 const auto p_j = std::get<0>(prec_j);
1090 const auto gamma_j = view.surrogate_gamma(U_j, p_j);
1091 gamma_min_i = std::min(gamma_min_i, gamma_j);
1092 }
1093
1094 s_i = view.surrogate_specific_entropy(U_i, gamma_min_i);
1095 eta_i = view.surrogate_harten_entropy(U_i, gamma_min_i);
1096 precomputed_view.template write_tensor<T>(prec_i, i);
1097 };
1098
1099 loop<MemorySpace, ScalarNumber>(
1100 "hyperbolic_kernel_01c", body, 0, n_internal, n_owned);
1101 }
1102 }
1103
1104
1105 template <int dim, typename Number, typename MemorySpace>
1106 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1111
1112
1113 template <int dim, typename Number, typename MemorySpace>
1114 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1116 const Number &rho) const
1117 {
1118 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
1119 const Number rho_cutoff_large =
1120 reference_density() * vacuum_state_relaxation_large() * eps;
1121
1122 return ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
1123 std::abs(rho), rho_cutoff_large, Number(0.), rho);
1124 }
1125
1126
1127 template <int dim, typename Number, typename MemorySpace>
1128 DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor<1, dim, Number>
1130 const state_type &U)
1131 {
1132 dealii::Tensor<1, dim, Number> result;
1133 for (unsigned int i = 0; i < dim; ++i)
1134 result[i] = U[1 + i];
1135 return result;
1136 }
1137
1138
1139 template <int dim, typename Number, typename MemorySpace>
1140 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1142 const state_type &U)
1143 {
1144 return U[1 + dim];
1145 }
1146
1147
1148 template <int dim, typename Number, typename MemorySpace>
1149 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1151 const state_type &U)
1152 {
1153 /*
1154 * rho e = (E - 1/2*m^2/rho)
1155 */
1156 const Number rho_inverse = ScalarNumber(1.) / density(U);
1157 const auto m = momentum(U);
1158 const Number E = total_energy(U);
1159 return E - ScalarNumber(0.5) * m.norm_square() * rho_inverse;
1160 }
1161
1162
1163 template <int dim, typename Number, typename MemorySpace>
1164 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1166 const state_type &U) -> state_type
1167 {
1168 /*
1169 * With
1170 * rho e = E - 1/2 |m|^2 / rho
1171 * we get
1172 * (rho e)' = (1/2m^2/rho^2, -m/rho , 1 )^T
1173 */
1174
1175 const Number rho_inverse = ScalarNumber(1.) / density(U);
1176 const auto u = momentum(U) * rho_inverse;
1177
1178 state_type result;
1179
1180 result[0] = ScalarNumber(0.5) * u.norm_square();
1181 for (unsigned int i = 0; i < dim; ++i) {
1182 result[1 + i] = -u[i];
1183 }
1184 result[dim + 1] = ScalarNumber(1.);
1185
1186 return result;
1187 }
1188
1189
1190 template <int dim, typename Number, typename MemorySpace>
1191 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1193 const state_type &U, const Number &gamma_min) const
1194 {
1195 const auto b = Number(eos_covolume_constant());
1196 const auto pinf = Number(eos_interpolation_pinfty());
1197 const auto q = Number(eos_interpolation_q());
1198
1199 const auto rho = density(U);
1200 const auto rho_inverse = ScalarNumber(1.) / rho;
1201
1202 const auto covolume = Number(1.) - b * rho;
1203
1204 const auto shift = internal_energy(U) - rho * q - pinf * covolume;
1205
1206 return shift * ryujin::pow(rho_inverse - b, gamma_min) / covolume;
1207 }
1208
1209
1210 template <int dim, typename Number, typename MemorySpace>
1211 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1213 const state_type &U, const Number &gamma_min) const
1214 {
1215 const auto b = Number(eos_covolume_constant());
1216 const auto pinf = Number(eos_interpolation_pinfty());
1217 const auto q = Number(eos_interpolation_q());
1218
1219 const auto rho = density(U);
1220 const auto m = momentum(U);
1221 const auto E = total_energy(U);
1222 const auto rho_rho_e_q =
1223 rho * E - ScalarNumber(0.5) * m.norm_square() - rho * rho * q;
1224
1225 const auto exponent = ScalarNumber(1.) / (gamma_min + Number(1.));
1226
1227 const auto covolume = Number(1.) - b * rho;
1228 const auto covolume_term = ryujin::pow(covolume, gamma_min - Number(1.));
1229
1230 const auto rho_pinfcov = rho * pinf * covolume;
1231
1232 return ryujin::pow(
1233 positive_part(rho_rho_e_q - rho_pinfcov) * covolume_term, exponent);
1234 }
1235
1236
1237 template <int dim, typename Number, typename MemorySpace>
1238 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1241 const Number &eta,
1242 const Number &gamma_min) const
1243 -> state_type
1244 {
1245 /*
1246 * With
1247 * eta = (shift * (1-b*rho)^{gamma-1}) ^ {1/(gamma+1)},
1248 * shift = rho * E - 1/2 |m|^2 - rho^2 * q - p_infty * rho * (1 - b rho)
1249 *
1250 * shift' = [E - 2 * rho * q - p_infty * (1 - 2 b rho), -m, rho]^T
1251 * factor = 1/(gamma+1) * (eta/(1-b rho))^-gamma / (1-b rho)^2
1252 *
1253 * we get
1254 *
1255 * eta' = factor * (1-b*rho) * shift' -
1256 * factor * shift * (gamma - 1) * b * [1, 0, 0]^T
1257 *
1258 */
1259 const auto b = Number(eos_covolume_constant());
1260 const auto pinf = Number(eos_interpolation_pinfty());
1261 const auto q = Number(eos_interpolation_q());
1262
1263 const auto rho = density(U);
1264 const auto m = momentum(U);
1265 const auto E = total_energy(U);
1266
1267 const auto covolume = Number(1.) - b * rho;
1268 const auto covolume_inverse = ScalarNumber(1.) / covolume;
1269
1270 const auto shift = rho * E - ScalarNumber(0.5) * m.norm_square() -
1271 rho * rho * q - rho * pinf * covolume;
1272
1273 constexpr auto eps = std::numeric_limits<ScalarNumber>::epsilon();
1274 const auto regularization = m.norm() * eps;
1275 const auto max_val = ryujin::pow(
1276 std::max(regularization, eta * covolume_inverse), gamma_min);
1277 auto factor = safe_division(Number(1.0), max_val);
1278 factor *= fixed_power<2>(covolume_inverse) / (gamma_min + Number(1.));
1279
1280 state_type result;
1281
1282 const auto first_term = E - ScalarNumber(2.) * rho * q -
1283 pinf * (Number(1.) - ScalarNumber(2.) * b * rho);
1284 const auto second_term = -(gamma_min - Number(1.)) * shift * b;
1285
1286 result[0] = factor * (covolume * first_term + second_term);
1287 for (unsigned int i = 0; i < dim; ++i)
1288 result[1 + i] = -factor * covolume * m[i];
1289 result[dim + 1] = factor * covolume * rho;
1290
1291 return result;
1292 }
1293
1294
1295 template <int dim, typename Number, typename MemorySpace>
1296 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
1298 const state_type &U, const Number &p) const
1299 {
1300 const auto b = Number(eos_covolume_constant());
1301 const auto pinf = Number(eos_interpolation_pinfty());
1302 const auto q = Number(eos_interpolation_q());
1303
1304 const auto rho = density(U);
1305 const auto rho_e = internal_energy(U);
1306 const auto covolume = Number(1.) - b * rho;
1307
1308 const auto numerator = (p + pinf) * covolume;
1309 const auto denominator = rho_e - rho * q - covolume * pinf;
1310 return Number(1.) + safe_division(numerator, denominator);
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 &gamma) 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 return positive_part(gamma - Number(1.)) *
1328 safe_division(rho_e - rho * q, covolume) -
1329 gamma * pinf;
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 auto radicand =
1347 (rho_e - rho * q - pinf * covolume) / (covolume * covolume * rho);
1348 radicand *= gamma * (gamma - 1.);
1349 return std::sqrt(positive_part(radicand));
1350 }
1351
1352
1353 template <int dim, typename Number, typename MemorySpace>
1354 DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool
1356 const state_type &U) const
1357 {
1358 const auto b = Number(eos_covolume_constant());
1359 const auto pinf = Number(eos_interpolation_pinfty());
1360 const auto q = Number(eos_interpolation_q());
1361
1362 const auto rho = density(U);
1363 const auto rho_e = internal_energy(U);
1364 const auto covolume = Number(1.) - b * rho;
1365
1366 const auto shift = rho_e - rho * q - pinf * covolume;
1367
1368 constexpr auto gt = dealii::SIMDComparison::greater_than;
1369 using T = Number;
1370 const auto test =
1371 ryujin::compare_and_apply_mask<gt>(rho, T(0.), T(0.), T(-1.)) + //
1372 ryujin::compare_and_apply_mask<gt>(shift, T(0.), T(0.), T(-1.));
1373
1374#ifdef DEBUG_OUTPUT
1375 if (!(test == Number(0.))) {
1376 std::cout << std::fixed << std::setprecision(16);
1377 std::cout << "Bounds violation: Negative state [rho, e] detected!\n";
1378 std::cout << "\t\trho: " << rho << "\n";
1379 std::cout << "\t\tint (shifted): " << shift << "\n";
1380 }
1381#endif
1382
1383 return (test == Number(0.));
1384 }
1385
1386
1387 template <int dim, typename Number, typename MemorySpace>
1388 template <int component>
1389 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1392 const state_type &U,
1393 const Number &p,
1394 const state_type &U_bar,
1395 const Number &p_bar,
1396 const dealii::Tensor<1, dim, Number> &normal) const -> state_type
1397 {
1398 static_assert(component == 1 || component == 2,
1399 "component has to be 1 or 2");
1400
1401 const auto b = Number(eos_covolume_constant());
1402 const auto pinf = Number(eos_interpolation_pinfty());
1403 const auto q = Number(eos_interpolation_q());
1404
1405 /*
1406 * The "four" Riemann characteristics are formed under the assumption
1407 * of a locally isentropic flow. For this, we first transform both
1408 * states into {rho, vn, vperp, gamma, a}, where we use the NASG EOS
1409 * interpolation to derive a surrogate gamma and speed of sound a.
1410 *
1411 * See, e.g., https://arxiv.org/pdf/2004.08750, "Compressible flow in
1412 * a NOble-Abel Stiffened-Gas fluid", M. I. Radulescu.
1413 */
1414
1415 const auto m = momentum(U);
1416 const auto rho = density(U);
1417 const auto vn = m * normal / rho;
1418
1419 const auto gamma = surrogate_gamma(U, p);
1420 const auto a = surrogate_speed_of_sound(U, gamma);
1421 const auto covolume = 1. - b * rho;
1422
1423 const auto m_bar = momentum(U_bar);
1424 const auto rho_bar = density(U_bar);
1425 const auto vn_bar = m_bar * normal / rho_bar;
1426
1427 const auto gamma_bar = surrogate_gamma(U_bar, p_bar);
1428 const auto a_bar = surrogate_speed_of_sound(U_bar, gamma_bar);
1429 const auto covolume_bar = 1. - b * rho_bar;
1430
1431 /*
1432 * Now compute the Riemann characteristics {R_1, R_2, vperp, s}:
1433 * R_1 = v * n - 2 / (gamma - 1) * a * (1 - b * rho)
1434 * R_2 = v * n + 2 / (gamma - 1) * a * (1 - b * rho)
1435 * vperp
1436 * S = (p + p_infty) / rho^gamma * (1 - b * rho)^gamma
1437 *
1438 * Here, we replace either R_1, or R_2 with values coming from U_bar:
1439 */
1440
1441 const auto R_1 =
1442 component == 1 ? vn_bar - 2. * a_bar / (gamma_bar - 1.) * covolume_bar
1443 : vn - 2. * a / (gamma - 1.) * covolume;
1444
1445 const auto R_2 =
1446 component == 2 ? vn_bar + 2. * a_bar / (gamma_bar - 1.) * covolume_bar
1447 : vn + 2. * a / (gamma - 1.) * covolume;
1448
1449 /*
1450 * Note that we are really hoping for the best here... We require
1451 * that R_2 >= R_1 so that we can extract a valid sound speed...
1452 */
1453
1454 Assert(
1455 R_2 >= R_1,
1456 dealii::ExcMessage("Encountered R_2 < R_1 in dynamic boundary value "
1457 "enforcement. This implies that the interpolation "
1458 "with Riemann characteristics failed."));
1459
1460 const auto vperp = m / rho - vn * normal;
1461
1462 const auto S = (p + pinf) * ryujin::pow(Number(1.) / rho - b, gamma);
1463
1464 /*
1465 * Now, we have to reconstruct the actual conserved state U from the
1466 * Riemann characteristics R_1, R_2, vperp, and s. We first set up
1467 * {vn_new, vperp_new, a_new, S} and then solve for {rho_new, p_new}
1468 * with the help of the NASG EOS surrogate formulas:
1469 *
1470 * S = (p + p_infty) / rho^gamma * (1 - b * rho)^gamma
1471 *
1472 * a^2 = gamma * (p + p_infty) / (rho * cov)
1473 *
1474 * This implies:
1475 *
1476 * a^2 / (gamma * S) = rho^{gamma - 1} / (1 - b * rho)^{1 + gamma}
1477 */
1478
1479 const auto vn_new = Number(0.5) * (R_1 + R_2);
1480
1481 /*
1482 * Technically, we would need to solve for rho subject to a number of
1483 * nonlinear relationships:
1484 *
1485 * a = (gamma - 1) * (R_2 - R_1) / (4. * (1 - b * rho))
1486 *
1487 * a^2 / (gamma * S) = rho^{gamma - 1} / (1 - b * rho)^{gamma + 1}
1488 *
1489 * This seems to be a bit expensive for the fact that our dynamic
1490 * boundary conditions are already terribly heuristic...
1491 *
1492 * So instead, we rewrite this system as:
1493 *
1494 * a * (1 - b * rho) = (gamma - 1) * (R_2 - R_1) / 4.
1495 *
1496 * a^2 / (gamma * S) (1 - b * rho)^2
1497 * = (rho / (1 - b * rho))^{gamma - 1}
1498 *
1499 * And compute the terms on the left simply with the old covolume and
1500 * solving an easier easier nonlinear equation for the density. The
1501 * resulting system reads:
1502 *
1503 * a = (gamma - 1) * (R_2 - R_1) / (4. * (1 - b * rho_old))
1504 * A = {a^2 / (gamma * S) (1 - b * rho_old)^{2 gamma}}^{1/(gamma - 1)}
1505 *
1506 * rho = A / (1 + b * A)
1507 */
1508
1509 const auto a_new_square =
1510 ryujin::fixed_power<2>((gamma - 1.) * (R_2 - R_1) / (4. * covolume));
1511
1512 auto term = ryujin::pow(a_new_square / (gamma * S), 1. / (gamma - 1.));
1513 if (b != ScalarNumber(0.)) {
1514 term *= ryujin::pow(covolume, 2. / (gamma - 1.));
1515 }
1516
1517 const auto rho_new = term / (1. + b * term);
1518
1519 const auto covolume_new = (1. - b * rho_new);
1520 const auto p_new = a_new_square / gamma * rho_new * covolume_new - pinf;
1521
1522 /*
1523 * And translate back into conserved quantities:
1524 */
1525
1526 const auto rho_e_new =
1527 rho_new * q + (p_new + gamma * pinf) * covolume_new / (gamma - 1.);
1528
1529 state_type U_new;
1530 U_new[0] = rho_new;
1531 for (unsigned int d = 0; d < dim; ++d) {
1532 U_new[1 + d] = rho_new * (vn_new * normal + vperp)[d];
1533 }
1534 U_new[1 + dim] =
1535 rho_e_new + 0.5 * rho_new * (vn_new * vn_new + vperp.norm_square());
1536
1537 return U_new;
1538 }
1539
1540
1541 template <int dim, typename Number, typename MemorySpace>
1542 template <typename Lambda>
1543 DEAL_II_ALWAYS_INLINE inline auto
1545 dealii::types::boundary_id id,
1546 const state_type &U,
1547 const dealii::Tensor<1, dim, Number> &normal,
1548 const Lambda &get_dirichlet_data) const -> state_type
1549 {
1550 state_type result = U;
1551
1552 if (id == Boundary::dirichlet) {
1553 result = get_dirichlet_data();
1554
1555 } else if (id == Boundary::dirichlet_momentum) {
1556 /*
1557 * Only enforce Dirichlet conditions on the momentum, and keep the
1558 * internal energy constant:
1559 */
1560 const auto m_dirichlet = momentum(get_dirichlet_data());
1561 const auto rho = density(result);
1562 const auto m = momentum(result);
1563
1564 for (unsigned int k = 0; k < dim; ++k)
1565 result[k + 1] = m_dirichlet[k];
1566 result[dim + 1] +=
1567 Number(0.5) / rho * (m_dirichlet.norm_square() - m.norm_square());
1568
1569 } else if (id == Boundary::dirichlet_velocity) {
1570 /*
1571 * Only enforce Dirichlet conditions on the velocity, and keep the
1572 * internal energy constant:
1573 */
1574 const auto U_dirichlet = get_dirichlet_data();
1575 const auto rho_dirichlet = density(U_dirichlet);
1576 const auto v_dirichlet = momentum(U_dirichlet) / rho_dirichlet;
1577 const auto rho = density(result);
1578 const auto v = momentum(result) / rho;
1579
1580 for (unsigned int k = 0; k < dim; ++k)
1581 result[k + 1] = rho * v_dirichlet[k];
1582 result[dim + 1] +=
1583 Number(0.5) * rho * (v_dirichlet.norm_square() - v.norm_square());
1584
1585 } else if (id == Boundary::slip) {
1586 auto m = momentum(U);
1587 m -= 1. * (m * normal) * normal;
1588 for (unsigned int k = 0; k < dim; ++k)
1589 result[k + 1] = m[k];
1590
1591 } else if (id == Boundary::no_slip) {
1592 for (unsigned int k = 0; k < dim; ++k)
1593 result[k + 1] = Number(0.);
1594
1595 } else if (id == Boundary::dynamic) {
1596 /*
1597 * On dynamic boundary conditions, we distinguish four cases:
1598 *
1599 * - supersonic inflow: prescribe full state
1600 * - subsonic inflow:
1601 * decompose into Riemann invariants and leave R_2
1602 * characteristic untouched.
1603 * - supersonic outflow: do nothing
1604 * - subsonic outflow:
1605 * decompose into Riemann invariants and prescribe incoming
1606 * R_1 characteristic.
1607 */
1608 const auto m = momentum(U);
1609 const auto rho = density(U);
1610 const auto rho_e = internal_energy(U);
1611
1612 /*
1613 * We do not have precomputed values available. Thus, simply query
1614 * the pressure oracle and compute a surrogate speed of sound from
1615 * there:
1616 */
1617 const auto p = eos_pressure(rho, rho_e / rho);
1618 const auto gamma = surrogate_gamma(U, p);
1619 const auto a = surrogate_speed_of_sound(U, gamma);
1620 const auto vn = m * normal / rho;
1621
1622 /* Supersonic inflow: */
1623 if (vn < -a) {
1624 result = get_dirichlet_data();
1625 }
1626
1627 /* Subsonic inflow: */
1628 if (vn >= -a && vn <= 0.) {
1629 const auto U_dirichlet = get_dirichlet_data();
1630 const auto rho_dirichlet = density(U_dirichlet);
1631 const auto rho_e_dirichlet = internal_energy(U_dirichlet);
1632 const auto p_dirichlet =
1633 eos_pressure(rho_dirichlet, rho_e_dirichlet / rho_dirichlet);
1634
1635 result = prescribe_riemann_characteristic<2>(
1636 U_dirichlet, p_dirichlet, U, p, normal);
1637 }
1638
1639 /* Subsonic outflow: */
1640 if (vn > 0. && vn <= a) {
1641 const auto U_dirichlet = get_dirichlet_data();
1642 const auto rho_dirichlet = density(U_dirichlet);
1643 const auto rho_e_dirichlet = internal_energy(U_dirichlet);
1644 const auto p_dirichlet =
1645 eos_pressure(rho_dirichlet, rho_e_dirichlet / rho_dirichlet);
1646
1647 result = prescribe_riemann_characteristic<1>(
1648 U, p, U_dirichlet, p_dirichlet, normal);
1649 }
1650 /* Supersonic outflow: do nothing, i.e., keep U as is */
1651
1652 } else {
1653 AssertThrow(false, dealii::ExcNotImplemented());
1654 }
1655
1656 return result;
1657 }
1658
1659
1660 template <int dim, typename Number, typename MemorySpace>
1661 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1663 const Number &p) const
1664 -> flux_type
1665 {
1666 const auto rho_inverse = ScalarNumber(1.) / density(U);
1667 const auto m = momentum(U);
1668 const auto E = total_energy(U);
1669
1670 flux_type result;
1671
1672 result[0] = m;
1673 for (unsigned int i = 0; i < dim; ++i) {
1674 result[1 + i] = m * (m[i] * rho_inverse);
1675 result[1 + i][i] += p;
1676 }
1677 result[dim + 1] = m * (rho_inverse * (E + p));
1678
1679 return result;
1680 }
1681
1682
1683 template <int dim, typename Number, typename MemorySpace>
1684 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1686 const PrecomputedVectorView &pv,
1687 const InitialPrecomputedVectorView & /*piv*/,
1688 const unsigned int i,
1689 const state_type &U_i) const -> flux_contribution_type
1690 {
1691 const auto &[p_i, gamma_min_i, s_i, eta_i] =
1692 pv.template read_tensor<Number, precomputed_type>(i);
1693 return f(U_i, p_i);
1694 }
1695
1696
1697 template <int dim, typename Number, typename MemorySpace>
1698 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1700 const PrecomputedVectorView &pv,
1701 const InitialPrecomputedVectorView & /*piv*/,
1702 const unsigned int *js,
1703 const state_type &U_j) const -> flux_contribution_type
1704 {
1705 const auto &[p_j, gamma_min_j, s_j, eta_j] =
1706 pv.template read_tensor<Number, precomputed_type>(js);
1707 return f(U_j, p_j);
1708 }
1709
1710
1711 template <int dim, typename Number, typename MemorySpace>
1712 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1714 const flux_contribution_type &flux_i,
1715 const flux_contribution_type &flux_j,
1716 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1717 {
1718 return -contract(add(flux_i, flux_j), c_ij);
1719 }
1720
1721
1722 template <int dim, typename Number, typename MemorySpace>
1723 template <typename ST>
1724 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1726 const ST &state) const -> state_type
1727 {
1728 using T = typename ST::value_type;
1729 static_assert(std::is_same_v<Number, T>, "template mismatch");
1730
1731 constexpr auto dim2 = ST::dimension - 2;
1732 static_assert(dim >= dim2,
1733 "the space dimension of the argument state must not be "
1734 "larger than the one of the target state");
1735
1736 state_type result;
1737 result[0] = state[0];
1738 result[dim + 1] = state[dim2 + 1];
1739 for (unsigned int i = 1; i < dim2 + 1; ++i)
1740 result[i] = state[i];
1741
1742 return result;
1743 }
1744
1745
1746 template <int dim, typename Number, typename MemorySpace>
1747 template <typename ST>
1748 DEAL_II_ALWAYS_INLINE inline auto
1750 const ST &initial_state) const -> state_type
1751 {
1752 auto primitive_state = expand_state(initial_state);
1753
1754 /* pressure into specific internal energy: */
1755 const auto rho = density(primitive_state);
1756 const auto p = /*SIC!*/ total_energy(primitive_state);
1757 const auto e = eos_specific_internal_energy(rho, p);
1758 primitive_state[dim + 1] = e;
1759
1760 return from_primitive_state(primitive_state);
1761 }
1762
1763
1764 template <int dim, typename Number, typename MemorySpace>
1765 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1767 const state_type &primitive_state) const -> state_type
1768 {
1769 const auto rho = density(primitive_state);
1770 /* extract velocity: */
1771 const auto u = /*SIC!*/ momentum(primitive_state);
1772 /* extract specific internal energy: */
1773 const auto &e = /*SIC!*/ total_energy(primitive_state);
1774
1775 auto state = primitive_state;
1776 /* Fix up momentum: */
1777 for (unsigned int i = 1; i < dim + 1; ++i)
1778 state[i] *= rho;
1779
1780 /* Compute total energy: */
1781 state[dim + 1] = rho * e + Number(0.5) * rho * u * u;
1782
1783 return state;
1784 }
1785
1786
1787 template <int dim, typename Number, typename MemorySpace>
1788 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1790 const state_type &state) const -> state_type
1791 {
1792 const auto rho = density(state);
1793 const auto rho_inverse = Number(1.) / rho;
1794 const auto rho_e = internal_energy(state);
1795
1796 auto primitive_state = state;
1797 /* Fix up velocity: */
1798 for (unsigned int i = 1; i < dim + 1; ++i)
1799 primitive_state[i] *= rho_inverse;
1800 /* Set specific internal energy: */
1801 primitive_state[dim + 1] = rho_e * rho_inverse;
1802
1803 return primitive_state;
1804 }
1805
1806
1807 template <int dim, typename Number, typename MemorySpace>
1808 template <typename Lambda>
1809 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1811 const state_type &state, const Lambda &lambda) const -> state_type
1812 {
1813 auto result = state;
1814 const auto M = lambda(momentum(state));
1815 for (unsigned int d = 0; d < dim; ++d)
1816 result[1 + d] = M[d];
1817 return result;
1818 }
1819 } // namespace EulerAEOS
1820} // 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
static Base & select(const std::vector< std::unique_ptr< Base > > &objects, const std::string &name)
Definition library.h:189
static std::vector< std::unique_ptr< Base > > create(Args... args)
Definition library.h:148
static dealii::Patterns::Selection selection(const std::vector< std::unique_ptr< Base > > &objects)
Definition library.h:178
constexpr bool have_separate_memory_spaces
Definition gpu.h:29
@ dirichlet_momentum
@ dirichlet_velocity
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
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)
MultiComponentVector< Number > state
MultiComponentVector< Number > precomputed