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
12#include <convenience_macros.h>
13#include <discretization.h>
14#include <gpu.h>
15#include <loop.h>
17#include <patterns_conversion.h>
18#include <simd.h>
19#include <state_vector.h>
20
21#include <deal.II/base/memory_space.h>
22#include <deal.II/base/parameter_acceptor.h>
23#include <deal.II/base/tensor.h>
24
25#include <array>
26
27namespace ryujin
28{
29 namespace Euler
30 {
31 template <int dim,
32 typename Number,
33 typename MemorySpace = dealii::MemorySpace::Host>
34 class HyperbolicSystemView;
35
46 class HyperbolicSystem final : public Interface::HyperbolicSystem
47 {
48 public:
84
88 HyperbolicSystem(const std::string &subsection = "/HyperbolicSystem");
89
95 template <int dim,
96 typename Number = double,
97 typename MemorySpace = dealii::MemorySpace::Host>
99
107 template <int dim,
108 typename Number,
109 typename MemorySpace = dealii::MemorySpace::Host>
110 auto view() const
111 {
112 return View<dim, Number, MemorySpace>{*this};
113 }
114
123 template <typename MemorySpace = dealii::MemorySpace::Host,
124 int dim,
125 typename ScalarNumber>
127 const OfflineData<dim, ScalarNumber> &offline_data,
128 StateVector<ScalarNumber> &state_vector,
129 const bool skip_constrained_dofs = true) const;
130
131 private:
136
141 void update_parameters();
142
143 Mirrored<Parameters> parameters_;
144
145 template <int, typename, typename>
147
149 }; /* HyperbolicSystem */
150
151
173 template <int dim, typename Number, typename MemorySpace>
175 {
176 public:
177 static_assert(
178 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
179 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
180 "Unexpected memory space");
181
186
191
195 static constexpr unsigned int problem_dimension = 2 + dim;
196
200 using state_type = dealii::Tensor<1, problem_dimension, Number>;
201
205 using flux_type =
206 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
207
212
216 static constexpr unsigned int n_precomputed_values = 2;
217
221 using precomputed_type = std::array<Number, n_precomputed_values>;
222
226 static constexpr unsigned int n_initial_precomputed_values = 0;
227
232 std::array<Number, n_initial_precomputed_values>;
233
234 template <int n_comp>
237
243
250
252
256
261 HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
262 : parameters_(
263 hyperbolic_system.parameters_.template view<MemorySpace>())
264 {
265 }
266
268
272
273 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber gamma() const
274 {
275 return ScalarNumber(parameters_->gamma);
276 }
277
278 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber reference_density() const
279 {
280 return ScalarNumber(parameters_->reference_density);
281 }
282
283 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
285 {
286 return ScalarNumber(parameters_->vacuum_state_relaxation_small);
287 }
288
289 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
291 {
292 return ScalarNumber(parameters_->vacuum_state_relaxation_large);
293 }
294
296
304
305 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber gamma_inverse() const
306 {
307 return ScalarNumber(parameters_->gamma_inverse);
308 }
309
310 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
312 {
313 return ScalarNumber(parameters_->gamma_plus_one_inverse);
314 }
315
316 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
318 {
319 return ScalarNumber(parameters_->gamma_minus_one_inverse);
320 }
321
322 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
327
329
333
334 static constexpr bool have_gamma = true;
335 static constexpr bool have_covolume_constant = false;
336 static constexpr bool have_energy_equation = true;
337
339
343
348 static DEAL_II_HOST_DEVICE Number density(const state_type &U);
349
356 DEAL_II_HOST_DEVICE Number filter_vacuum_density(const Number &rho) const;
357
362 static DEAL_II_HOST_DEVICE dealii::Tensor<1, dim, Number>
363 momentum(const state_type &U);
364
369 static DEAL_II_HOST_DEVICE Number total_energy(const state_type &U);
370
375 static DEAL_II_HOST_DEVICE Number internal_energy(const state_type &U);
376
382 static DEAL_II_HOST_DEVICE state_type
384
395 DEAL_II_HOST_DEVICE Number pressure(const state_type &U) const;
396
404 DEAL_II_HOST_DEVICE Number speed_of_sound(const state_type &U) const;
405
413 DEAL_II_HOST_DEVICE Number specific_entropy(const state_type &U) const;
414
422 DEAL_II_HOST_DEVICE Number harten_entropy(const state_type &U) const;
423
431 DEAL_II_HOST_DEVICE state_type
433
438 DEAL_II_HOST_DEVICE Number
439 mathematical_entropy(const state_type &U) const;
440
446 DEAL_II_HOST_DEVICE state_type
448
454 DEAL_II_HOST_DEVICE bool is_admissible(const state_type &U) const;
455
457
461
467 template <int component>
468 DEAL_II_HOST_DEVICE std::array<state_type, 2> linearized_eigenvector(
469 const state_type &U,
470 const dealii::Tensor<1, dim, Number> &normal) const;
471
478 template <int component>
480 const state_type &U,
481 const state_type &U_bar,
482 const dealii::Tensor<1, dim, Number> &normal) const;
483
502 template <typename Lambda>
503 DEAL_II_HOST_DEVICE_ALWAYS_INLINE state_type
504 apply_boundary_conditions(const dealii::types::boundary_id id,
505 const state_type &U,
506 const dealii::Tensor<1, dim, Number> &normal,
507 const Lambda &get_dirichlet_data) const;
508
510
514
525 DEAL_II_HOST_DEVICE flux_type f(const state_type &U) const;
526
546 DEAL_II_HOST_DEVICE
550 const unsigned int i,
551 const state_type &U_i) const;
552
553 DEAL_II_HOST_DEVICE
557 const unsigned int *js,
558 const state_type &U_j) const;
559
564 DEAL_II_HOST_DEVICE
567 const flux_contribution_type &flux_j,
568 const dealii::Tensor<1, dim, Number> &c_ij) const;
569
571 static constexpr bool have_high_order_flux = false;
572
573 DEAL_II_HOST_DEVICE
575 const flux_contribution_type &flux_i,
576 const flux_contribution_type &flux_j,
577 const dealii::Tensor<1, dim, Number> &c_ij) const = delete;
578
580
584
586 static constexpr bool have_source_terms = false;
587
588 DEAL_II_HOST_DEVICE
590 const unsigned int i,
591 const state_type &U_i,
592 const ScalarNumber tau) const = delete;
593
594 DEAL_II_HOST_DEVICE
596 const unsigned int *js,
597 const state_type &U_j,
598 const ScalarNumber tau) const = delete;
599
601
605
616 template <typename ST>
617 DEAL_II_HOST_DEVICE state_type expand_state(const ST &state) const;
618
632 template <typename ST>
633 DEAL_II_HOST_DEVICE state_type
634 from_initial_state(const ST &initial_state) const;
635
640 DEAL_II_HOST_DEVICE
641 state_type from_primitive_state(const state_type &primitive_state) const;
642
647 DEAL_II_HOST_DEVICE
648 state_type to_primitive_state(const state_type &state) const;
649
655 template <typename Lambda>
657 const state_type &state, const Lambda &lambda) const;
658
659 private:
661
665
666 const HyperbolicSystem::Parameters *const parameters_;
667
669 }; /* HyperbolicSystemView */
670
671
672 /*
673 * -------------------------------------------------------------------------
674 * Inline definitions
675 * -------------------------------------------------------------------------
676 */
677
678 inline HyperbolicSystem::HyperbolicSystem(const std::string &subsection)
679 : Interface::HyperbolicSystem(
680 "Compressible Euler equations (polytropic gas EOS, optimized)",
681 {{{"rho", "m", "E"},
682 {"rho", "m_1", "m_2", "E"},
683 {"rho", "m_1", "m_2", "m_3", "E"}}},
684 {{{"rho", "v", "p"},
685 {"rho", "v_1", "v_2", "p"},
686 {"rho", "v_1", "v_2", "v_3", "p"}}},
687 {{{"s", "eta_h"}, {"s", "eta_h"}, {"s", "eta_h"}}},
688 {},
689 subsection)
690 , parameters_("euler_hyperbolic_system_parameters",
692 {
693 /* reference remains valid due to implicit_transfers_host_resident */
694 auto &parameters = *parameters_.view();
695
696 parameters.gamma = 7. / 5.;
697 add_parameter("gamma", parameters.gamma, "The ratio of specific heats");
698
699 parameters.reference_density = 1.;
700 add_parameter("reference density",
701 parameters.reference_density,
702 "Problem specific density reference");
703
704 parameters.vacuum_state_relaxation_small = 1.e2;
705 add_parameter("vacuum state relaxation small",
706 parameters.vacuum_state_relaxation_small,
707 "Problem specific vacuum relaxation parameter");
708
709 parameters.vacuum_state_relaxation_large = 1.e4;
710 add_parameter("vacuum state relaxation large",
711 parameters.vacuum_state_relaxation_large,
712 "Problem specific vacuum relaxation parameter");
713
714 ParameterAcceptor::parse_parameters_call_back.connect(
715 [this] { update_parameters(); });
716
717 update_parameters();
718 }
719
720
721 inline void HyperbolicSystem::update_parameters()
722 {
723 auto &parameters = *parameters_.view();
724
725 /*
726 * Precompute a number of derived gamma coefficients that contain
727 * divisions:
728 */
729 const auto gamma = parameters.gamma;
730 parameters.gamma_inverse = 1. / gamma;
731 parameters.gamma_plus_one_inverse = 1. / (gamma + 1.);
732 parameters.gamma_minus_one_inverse = 1. / (gamma - 1.);
733 parameters.gamma_minus_one_over_gamma_plus_one =
734 (gamma - 1.) / (gamma + 1.);
735 }
736
737
738 template <typename MemorySpace, int dim, typename ScalarNumber>
740 const OfflineData<dim, ScalarNumber> &offline_data,
741 StateVector<ScalarNumber> &state_vector,
742 const bool skip_constrained_dofs) const
743 {
744 const unsigned int n_internal = offline_data.n_locally_internal();
745 const unsigned int n_owned = offline_data.n_locally_owned();
746
748
749 const auto sparsity_simd_view =
750 offline_data.sparsity_pattern_simd().template view<MemorySpace>();
751
752 /* We only read the hyperbolic state vector: */
753 const auto U_view =
754 std::as_const(state_vector)
755 .U.template view<ScalarView::problem_dimension, MemorySpace>();
756 const auto precomputed_view =
757 state_vector.precomputed
758 .template view<ScalarView::n_precomputed_values, MemorySpace>();
759
760 const auto hyperbolic_system_views =
761 make_select_view<dim, ScalarNumber, MemorySpace>(*this);
762
763 const auto body = [=](auto sentinel, unsigned int i) {
764 using T = decltype(sentinel);
766 using precomputed_type = typename View::precomputed_type;
767
768 const unsigned int row_length = sparsity_simd_view.row_length(i);
769 if (skip_constrained_dofs && row_length == 1)
770 return;
771
772 const auto view = hyperbolic_system_views.template view<T>();
773
774 const auto U_i = U_view.template read_tensor<T>(i);
775 const precomputed_type prec_i{view.specific_entropy(U_i),
776 view.harten_entropy(U_i)};
777 precomputed_view.template write_tensor<T>(prec_i, i);
778 };
779
780 loop<MemorySpace, ScalarNumber>(
781 "hyperbolic_kernel_01b", body, 0, n_internal, n_owned);
782 }
783
784
785 template <int dim, typename Number, typename MemorySpace>
786 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
791
792
793 template <int dim, typename Number, typename MemorySpace>
794 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
796 const Number &rho) const
797 {
798 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
799 const Number rho_cutoff_large =
800 reference_density() * vacuum_state_relaxation_large() * eps;
801
802 return ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
803 std::abs(rho), rho_cutoff_large, Number(0.), rho);
804 }
805
806
807 template <int dim, typename Number, typename MemorySpace>
808 DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor<1, dim, Number>
810 const state_type &U)
811 {
812 dealii::Tensor<1, dim, Number> result;
813 for (unsigned int i = 0; i < dim; ++i)
814 result[i] = U[1 + i];
815 return result;
816 }
817
818
819 template <int dim, typename Number, typename MemorySpace>
820 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
822 const state_type &U)
823 {
824 return U[1 + dim];
825 }
826
827
828 template <int dim, typename Number, typename MemorySpace>
829 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
831 const state_type &U)
832 {
833 /*
834 * rho e = (E - 1/2*m^2/rho)
835 */
836 const Number rho_inverse = ScalarNumber(1.) / density(U);
837 const auto m = momentum(U);
838 const Number E = total_energy(U);
839 return E - ScalarNumber(0.5) * m.norm_square() * rho_inverse;
840 }
841
842
843 template <int dim, typename Number, typename MemorySpace>
844 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
846 const state_type &U) -> state_type
847 {
848 /*
849 * With
850 * rho e = E - 1/2 |m|^2 / rho
851 * we get
852 * (rho e)' = (1/2m^2/rho^2, -m/rho , 1 )^T
853 */
854
855 const Number rho_inverse = ScalarNumber(1.) / density(U);
856 const auto u = momentum(U) * rho_inverse;
857
858 state_type result;
859
860 result[0] = ScalarNumber(0.5) * u.norm_square();
861 for (unsigned int i = 0; i < dim; ++i) {
862 result[1 + i] = -u[i];
863 }
864 result[dim + 1] = ScalarNumber(1.);
865
866 return result;
867 }
868
869
870 template <int dim, typename Number, typename MemorySpace>
871 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
873 const state_type &U) const
874 {
875 /* p = (gamma - 1) * (rho e) */
876 return (gamma() - ScalarNumber(1.)) * internal_energy(U);
877 }
878
879
880 template <int dim, typename Number, typename MemorySpace>
881 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
883 const state_type &U) const
884 {
885 /* c^2 = gamma * p / rho */
886 const Number rho_inverse = ScalarNumber(1.) / density(U);
887 const Number p = pressure(U);
888 return std::sqrt(gamma() * p * rho_inverse);
889 }
890
891
892 template <int dim, typename Number, typename MemorySpace>
893 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
895 const state_type &U) const
896 {
897 /* exp((gamma - 1)s) = (rho e) / rho ^ gamma */
898 const auto rho_inverse = ScalarNumber(1.) / density(U);
899 return internal_energy(U) * ryujin::pow(rho_inverse, gamma());
900 }
901
902
903 template <int dim, typename Number, typename MemorySpace>
904 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
906 const state_type &U) const
907 {
908 /* rho^2 e = \rho E - 1/2*m^2 */
909
910 const Number rho = density(U);
911 const auto m = momentum(U);
912 const Number E = total_energy(U);
913
914 const Number rho_rho_e = rho * E - ScalarNumber(0.5) * m.norm_square();
915 return ryujin::pow(rho_rho_e, gamma_plus_one_inverse());
916 }
917
918
919 template <int dim, typename Number, typename MemorySpace>
920 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
922 const state_type &U) const -> state_type
923 {
924 /*
925 * With
926 * eta = (rho^2 e) ^ 1/(gamma+1)
927 * rho^2 e = rho * E - 1/2 |m|^2
928 *
929 * we get
930 *
931 * eta' = 1/(gamma+1) * (rho^2 e) ^ -gamma/(gamma+1) * (E,-m,rho)^T
932 *
933 */
934
935 const Number rho = density(U);
936 const auto m = momentum(U);
937 const Number E = total_energy(U);
938
939 const Number rho_rho_e = rho * E - ScalarNumber(0.5) * m.norm_square();
940
941 const auto factor =
942 gamma_plus_one_inverse() *
943 ryujin::pow(rho_rho_e, -gamma() * gamma_plus_one_inverse());
944
945 state_type result;
946
947 result[0] = factor * E;
948 for (unsigned int i = 0; i < dim; ++i)
949 result[1 + i] = -factor * m[i];
950 result[dim + 1] = factor * rho;
951
952 return result;
953 }
954
955
956 template <int dim, typename Number, typename MemorySpace>
957 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
959 const state_type &U) const
960 {
962 const auto p = pressure(U);
963 return ryujin::pow(p, gamma_inverse());
964 }
965
966
967 template <int dim, typename Number, typename MemorySpace>
968 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
971 {
972 /*
973 * With
974 * eta = p ^ (1/gamma)
975 * p = (gamma - 1) * (rho e)
976 * rho e = E - 1/2 |m|^2 / rho
977 *
978 * we get
979 *
980 * eta' = (gamma - 1)/gamma p ^(1/gamma - 1) *
981 *
982 * (1/2m^2/rho^2 , -m/rho , 1 )^T
983 */
984 const Number rho = density(U);
985 const Number rho_inverse = ScalarNumber(1.) / rho;
986 const auto u = momentum(U) * rho_inverse;
987 const auto p = pressure(U);
988
989 const auto factor = (gamma() - ScalarNumber(1.0)) * gamma_inverse() *
990 ryujin::pow(p, gamma_inverse() - ScalarNumber(1.));
991
992 state_type result;
993
994 result[0] = factor * ScalarNumber(0.5) * u.norm_square();
995 result[dim + 1] = factor;
996 for (unsigned int i = 0; i < dim; ++i) {
997 result[1 + i] = -factor * u[i];
998 }
999
1000 return result;
1001 }
1002
1003
1004 template <int dim, typename Number, typename MemorySpace>
1005 DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool
1007 const state_type &U) const
1008 {
1009 const auto rho_new = density(U);
1010 const auto e_new = internal_energy(U);
1011 const auto s_new = specific_entropy(U);
1012
1013 constexpr auto gt = dealii::SIMDComparison::greater_than;
1014 using T = Number;
1015 const auto test =
1016 ryujin::compare_and_apply_mask<gt>(rho_new, T(0.), T(0.), T(-1.)) + //
1017 ryujin::compare_and_apply_mask<gt>(e_new, T(0.), T(0.), T(-1.)) + //
1018 ryujin::compare_and_apply_mask<gt>(s_new, T(0.), T(0.), T(-1.));
1019
1020#ifdef DEBUG_OUTPUT
1021 if (!(test == Number(0.))) {
1022 std::cout << std::fixed << std::setprecision(16);
1023 std::cout << "Bounds violation: Negative state [rho, e, s] detected!\n";
1024 std::cout << "\t\trho: " << rho_new << "\n";
1025 std::cout << "\t\tint: " << e_new << "\n";
1026 std::cout << "\t\tent: " << s_new << "\n" << std::endl;
1027 }
1028#endif
1029
1030 return (test == Number(0.));
1031 }
1032
1033
1034 template <int dim, typename Number, typename MemorySpace>
1035 template <int component>
1036 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1038 const state_type &U, const dealii::Tensor<1, dim, Number> &normal) const
1039 -> std::array<state_type, 2>
1040 {
1041 static_assert(component == 1 || component == problem_dimension,
1042 "Only first and last eigenvectors implemented");
1043
1044 const auto rho = density(U);
1045 const auto m = momentum(U);
1046 const auto v = m / rho;
1047 const auto a = speed_of_sound(U);
1048 const auto gamma = this->gamma();
1049
1050 state_type b;
1051 state_type c;
1052
1053 const auto e_k = 0.5 * v.norm_square();
1054
1055 switch (component) {
1056 case 1:
1057 b[0] = (gamma - 1.) * e_k + a * v * normal;
1058 for (unsigned int i = 0; i < dim; ++i)
1059 b[1 + i] = (1. - gamma) * v[i] - a * normal[i];
1060 b[dim + 1] = gamma - 1.;
1061 b /= 2. * a * a;
1062
1063 c[0] = 1.;
1064 for (unsigned int i = 0; i < dim; ++i)
1065 c[1 + i] = v[i] - a * normal[i];
1066 c[dim + 1] = a * a / (gamma - 1) + e_k - a * (v * normal);
1067
1068 return {b, c};
1069
1070 case problem_dimension:
1071 b[0] = (gamma - 1.) * e_k - a * v * normal;
1072 for (unsigned int i = 0; i < dim; ++i)
1073 b[1 + i] = (1. - gamma) * v[i] + a * normal[i];
1074 b[dim + 1] = gamma - 1.;
1075 b /= 2. * a * a;
1076
1077 c[0] = 1.;
1078 for (unsigned int i = 0; i < dim; ++i)
1079 c[1 + i] = v[i] + a * normal[i];
1080 c[dim + 1] = a * a / (gamma - 1) + e_k + a * (v * normal);
1081
1082 return {b, c};
1083 }
1084
1085 __builtin_unreachable();
1086 }
1087
1088
1089 template <int dim, typename Number, typename MemorySpace>
1090 template <int component>
1091 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1094 const state_type &U,
1095 const state_type &U_bar,
1096 const dealii::Tensor<1, dim, Number> &normal) const -> state_type
1097 {
1098 static_assert(component == 1 || component == 2,
1099 "component has to be 1 or 2");
1100
1101 const auto m = momentum(U);
1102 const auto rho = density(U);
1103 const auto a = speed_of_sound(U);
1104 const auto vn = m * normal / rho;
1105
1106 const auto m_bar = momentum(U_bar);
1107 const auto rho_bar = density(U_bar);
1108 const auto a_bar = speed_of_sound(U_bar);
1109 const auto vn_bar = m_bar * normal / rho_bar;
1110
1111 /* First Riemann characteristic: v* n - 2 / (gamma - 1) * a */
1112
1113 const auto R_1 = component == 1
1114 ? vn_bar - 2. * a_bar / (gamma() - ScalarNumber(1.))
1115 : vn - 2. * a / (gamma() - ScalarNumber(1.));
1116
1117 /* Second Riemann characteristic: v* n + 2 / (gamma() - 1) * a */
1118
1119 const auto R_2 = component == 2
1120 ? vn_bar + 2. * a_bar / (gamma() - ScalarNumber(1.))
1121 : vn + 2. * a / (gamma() - ScalarNumber(1.));
1122
1123 const auto p = pressure(U);
1124 const auto s = p / ryujin::pow(rho, gamma());
1125
1126 const auto vperp = m / rho - vn * normal;
1127
1128 const auto vn_new = 0.5 * (R_1 + R_2);
1129
1130 auto rho_new = 1. / (gamma() * s) *
1131 ryujin::fixed_power<2>(ScalarNumber((gamma() - 1.) / 4.) *
1132 (R_2 - R_1));
1133 rho_new = ryujin::pow(rho_new, 1. / (gamma() - 1.));
1134
1135 const auto p_new = s * std::pow(rho_new, gamma());
1136
1137 state_type U_new;
1138 U_new[0] = rho_new;
1139 for (unsigned int d = 0; d < dim; ++d) {
1140 U_new[1 + d] = rho_new * (vn_new * normal + vperp)[d];
1141 }
1142 U_new[1 + dim] = p_new / ScalarNumber(gamma() - 1.) +
1143 0.5 * rho_new * (vn_new * vn_new + vperp.norm_square());
1144
1145 return U_new;
1146 }
1147
1148
1149 template <int dim, typename Number, typename MemorySpace>
1150 template <typename Lambda>
1151 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1153 dealii::types::boundary_id id,
1154 const state_type &U,
1155 const dealii::Tensor<1, dim, Number> &normal,
1156 const Lambda &get_dirichlet_data) const -> state_type
1157 {
1158 state_type result = U;
1159
1160 if (id == Boundary::dirichlet) {
1161 result = get_dirichlet_data();
1162
1163 } else if (id == Boundary::dirichlet_momentum) {
1164 /*
1165 * Only enforce Dirichlet conditions on the momentum, and keep the
1166 * internal energy constant:
1167 */
1168 const auto m_dirichlet = momentum(get_dirichlet_data());
1169 const auto rho = density(result);
1170 const auto m = momentum(result);
1171
1172 for (unsigned int k = 0; k < dim; ++k)
1173 result[k + 1] = m_dirichlet[k];
1174 result[dim + 1] +=
1175 Number(0.5) / rho * (m_dirichlet.norm_square() - m.norm_square());
1176
1177 } else if (id == Boundary::dirichlet_velocity) {
1178 /*
1179 * Only enforce Dirichlet conditions on the velocity, and keep the
1180 * internal energy constant:
1181 */
1182 const auto U_dirichlet = get_dirichlet_data();
1183 const auto rho_dirichlet = density(U_dirichlet);
1184 const auto v_dirichlet = momentum(U_dirichlet) / rho_dirichlet;
1185 const auto rho = density(result);
1186 const auto v = momentum(result) / rho;
1187
1188 for (unsigned int k = 0; k < dim; ++k)
1189 result[k + 1] = rho * v_dirichlet[k];
1190 result[dim + 1] +=
1191 Number(0.5) * rho * (v_dirichlet.norm_square() - v.norm_square());
1192
1193 } else if (id == Boundary::slip) {
1194 auto m = momentum(U);
1195 m -= 1. * (m * normal) * normal;
1196 for (unsigned int k = 0; k < dim; ++k)
1197 result[k + 1] = m[k];
1198
1199 } else if (id == Boundary::no_slip) {
1200 for (unsigned int k = 0; k < dim; ++k)
1201 result[k + 1] = Number(0.);
1202
1203 } else if (id == Boundary::dynamic) {
1204 /*
1205 * On dynamic boundary conditions, we distinguish four cases:
1206 *
1207 * - supersonic inflow: prescribe full state
1208 * - subsonic inflow:
1209 * decompose into Riemann invariants and leave R_2
1210 * characteristic untouched.
1211 * - supersonic outflow: do nothing
1212 * - subsonic outflow:
1213 * decompose into Riemann invariants and prescribe incoming
1214 * R_1 characteristic.
1215 */
1216 const auto m = momentum(U);
1217 const auto rho = density(U);
1218 const auto a = speed_of_sound(U);
1219 const auto vn = m * normal / rho;
1220
1221 /* Supersonic inflow: */
1222 if (vn < -a) {
1223 result = get_dirichlet_data();
1224 }
1225
1226 /* Subsonic inflow: */
1227 if (vn >= -a && vn <= 0.) {
1228 const auto U_dirichlet = get_dirichlet_data();
1229 result = prescribe_riemann_characteristic<2>(U_dirichlet, U, normal);
1230 }
1231
1232 /* Subsonic outflow: */
1233 if (vn > 0. && vn <= a) {
1234 const auto U_dirichlet = get_dirichlet_data();
1235 result = prescribe_riemann_characteristic<1>(U, U_dirichlet, normal);
1236 }
1237
1238 /* Supersonic outflow: do nothing, i.e., keep U as is */
1239
1240 } else {
1241 Assert(false, dealii::ExcNotImplemented());
1242 }
1243
1244 return result;
1245 }
1246
1247
1248 template <int dim, typename Number, typename MemorySpace>
1249 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1251 -> flux_type
1252 {
1253 const auto rho_inverse = ScalarNumber(1.) / density(U);
1254 const auto m = momentum(U);
1255 const auto p = pressure(U);
1256 const auto E = total_energy(U);
1257
1258 flux_type result;
1259
1260 result[0] = m;
1261 for (unsigned int i = 0; i < dim; ++i) {
1262 result[1 + i] = m * (m[i] * rho_inverse);
1263 result[1 + i][i] += p;
1264 }
1265 result[dim + 1] = m * (rho_inverse * (E + p));
1266
1267 return result;
1268 }
1269
1270
1271 template <int dim, typename Number, typename MemorySpace>
1272 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1274 const PrecomputedVectorView & /*pv*/,
1275 const InitialPrecomputedVectorView & /*ipv*/,
1276 const unsigned int /*i*/,
1277 const state_type &U_i) const -> flux_contribution_type
1278 {
1279 return f(U_i);
1280 }
1281
1282
1283 template <int dim, typename Number, typename MemorySpace>
1284 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1286 const PrecomputedVectorView & /*pv*/,
1287 const InitialPrecomputedVectorView & /*ipv*/,
1288 const unsigned int * /*js*/,
1289 const state_type &U_j) const -> flux_contribution_type
1290 {
1291 return f(U_j);
1292 }
1293
1294
1295 template <int dim, typename Number, typename MemorySpace>
1296 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1298 const flux_contribution_type &flux_i,
1299 const flux_contribution_type &flux_j,
1300 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1301 {
1302 return -contract(add(flux_i, flux_j), c_ij);
1303 }
1304
1305
1306 template <int dim, typename Number, typename MemorySpace>
1307 template <typename ST>
1308 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1310 const ST &state) const -> state_type
1311 {
1312 using T = typename ST::value_type;
1313 static_assert(std::is_same_v<Number, T>, "template mismatch");
1314
1315 constexpr auto dim2 = ST::dimension - 2;
1316 static_assert(dim >= dim2,
1317 "the space dimension of the argument state must not be "
1318 "larger than the one of the target state");
1319
1320 state_type result;
1321 result[0] = state[0];
1322 result[dim + 1] = state[dim2 + 1];
1323 for (unsigned int i = 1; i < dim2 + 1; ++i)
1324 result[i] = state[i];
1325
1326 return result;
1327 }
1328
1329
1330 template <int dim, typename Number, typename MemorySpace>
1331 template <typename ST>
1332 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1334 const ST &initial_state) const -> state_type
1335 {
1336 const auto primitive_state = expand_state(initial_state);
1337 return from_primitive_state(primitive_state);
1338 }
1339
1340
1341 template <int dim, typename Number, typename MemorySpace>
1342 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1344 const state_type &primitive_state) const -> state_type
1345 {
1346 const auto &rho = primitive_state[0];
1347 /* extract velocity: */
1348 const auto u = /*SIC!*/ momentum(primitive_state);
1349 const auto &p = primitive_state[dim + 1];
1350
1351 auto state = primitive_state;
1352 /* Fix up momentum: */
1353 for (unsigned int i = 1; i < dim + 1; ++i)
1354 state[i] *= rho;
1355 /* Compute total energy: */
1356 state[dim + 1] =
1357 p / (ScalarNumber(gamma() - 1.)) + Number(0.5) * rho * u * u;
1358
1359 return state;
1360 }
1361
1362
1363 template <int dim, typename Number, typename MemorySpace>
1364 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1366 const state_type &state) const -> state_type
1367 {
1368 const auto &rho = state[0];
1369 const auto rho_inverse = Number(1.) / rho;
1370 const auto p = pressure(state);
1371
1372 auto primitive_state = state;
1373 /* Fix up velocity: */
1374 for (unsigned int i = 1; i < dim + 1; ++i)
1375 primitive_state[i] *= rho_inverse;
1376 /* Set pressure: */
1377 primitive_state[dim + 1] = p;
1378
1379 return primitive_state;
1380 }
1381
1382
1383 template <int dim, typename Number, typename MemorySpace>
1384 template <typename Lambda>
1385 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1387 const state_type &state, const Lambda &lambda) const -> state_type
1388 {
1389 auto result = state;
1390 const auto M = lambda(momentum(state));
1391 for (unsigned int d = 0; d < dim; ++d)
1392 result[1 + d] = M[d];
1393 return result;
1394 }
1395 } // namespace Euler
1396} // namespace ryujin
static constexpr bool have_covolume_constant
DEAL_II_HOST_DEVICE state_type mathematical_entropy_derivative(const state_type &U) const
DEAL_II_HOST_DEVICE Number filter_vacuum_density(const Number &rho) const
DEAL_II_HOST_DEVICE state_type apply_galilei_transform(const state_type &state, const Lambda &lambda) const
DEAL_II_HOST_DEVICE Number pressure(const state_type &U) const
DEAL_II_HOST_DEVICE state_type from_primitive_state(const state_type &primitive_state) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber gamma_minus_one_inverse() const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber reference_density() const
DEAL_II_HOST_DEVICE state_type prescribe_riemann_characteristic(const state_type &U, const state_type &U_bar, const dealii::Tensor< 1, dim, Number > &normal) const
DEAL_II_HOST_DEVICE state_type from_initial_state(const ST &initial_state) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE 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 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_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_large() const
DEAL_II_HOST_DEVICE std::array< state_type, 2 > linearized_eigenvector(const state_type &U, const dealii::Tensor< 1, dim, Number > &normal) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber gamma_minus_one_over_gamma_plus_one() const
dealii::Tensor< 1, problem_dimension, Number > state_type
DEAL_II_HOST_DEVICE Number mathematical_entropy(const state_type &U) 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
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber gamma_inverse() const
std::array< Number, n_precomputed_values > precomputed_type
DEAL_II_HOST_DEVICE flux_contribution_type flux_contribution(const PrecomputedVectorView &pv, const InitialPrecomputedVectorView &ipv, const unsigned int i, const state_type &U_i) const
static DEAL_II_HOST_DEVICE dealii::Tensor< 1, dim, Number > momentum(const state_type &U)
DEAL_II_HOST_DEVICE state_type harten_entropy_derivative(const state_type &U) const
HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
static DEAL_II_HOST_DEVICE Number density(const state_type &U)
DEAL_II_HOST_DEVICE flux_type f(const state_type &U) 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_HOST_DEVICE Number speed_of_sound(const state_type &U) const
DEAL_II_HOST_DEVICE state_type expand_state(const ST &state) const
static DEAL_II_HOST_DEVICE Number internal_energy(const state_type &U)
static constexpr unsigned int n_precomputed_values
static DEAL_II_HOST_DEVICE state_type internal_energy_derivative(const state_type &U)
typename get_value_type< Number >::type ScalarNumber
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
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
std::array< Number, n_initial_precomputed_values > initial_precomputed_type
DEAL_II_HOST_DEVICE state_type to_primitive_state(const state_type &state) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber gamma() const
DEAL_II_HOST_DEVICE Number harten_entropy(const state_type &U) const
static DEAL_II_HOST_DEVICE Number total_energy(const state_type &U)
DEAL_II_HOST_DEVICE Number specific_entropy(const state_type &U) const
static constexpr unsigned int n_initial_precomputed_values
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber vacuum_state_relaxation_small() const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber gamma_plus_one_inverse() const
HyperbolicSystem(const std::string &subsection="/HyperbolicSystem")
void fill_precomputed_values(const OfflineData< dim, ScalarNumber > &offline_data, StateVector< ScalarNumber > &state_vector, const bool skip_constrained_dofs=true) const
const auto & n_locally_owned() const
const auto & sparsity_pattern_simd() const
const auto & n_locally_internal() const
@ 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)
MultiComponentVector< Number > precomputed