ryujin 2.1.1 revision ee5cbcbf2346c1299c942d0e1f13b46449973c18
Loading...
Searching...
No Matches
hyperbolic_system.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0
3// [LANL Copyright Statement]
4// Copyright (C) 2020 - 2026 by the ryujin authors
5// Copyright (C) 2023 - 2024 by Triad National Security, LLC
6//
7
8#pragma once
9
10#include <compile_time_options.h>
11
12#include <convenience_macros.h>
13#include <discretization.h>
14#include <loop.h>
16#include <patterns_conversion.h>
17#include <simd.h>
18#include <state_vector.h>
19
20#include <deal.II/base/parameter_acceptor.h>
21#include <deal.II/base/tensor.h>
22
23#include <array>
24
25namespace ryujin
26{
27 namespace ShallowWater
28 {
29 template <int dim, typename Number>
30 class HyperbolicSystemView;
31
41 class HyperbolicSystem final : public dealii::ParameterAcceptor
42 {
43 public:
47 static inline const std::string problem_name = "Shallow water equations";
48
52 HyperbolicSystem(const std::string &subsection = "/HyperbolicSystem");
53
58 template <int dim, typename Number = double>
60
67 template <int dim, typename Number>
68 auto view() const
69 {
70 return View<dim, Number>{*this};
71 }
72
81 template <int dim, typename ScalarNumber>
83 const OfflineData<dim, ScalarNumber> &offline_data,
85 &state_vector,
86 const bool skip_constrained_dofs = true) const;
87
88 private:
93
94 double gravity_;
95 double manning_friction_coefficient_;
96
97 double reference_water_depth_;
98 double dry_state_relaxation_small_;
99 double dry_state_relaxation_large_;
100
102
106
107 template <int dim, typename Number>
109
111 }; /* HyperbolicSystem */
112
113
132 template <int dim, typename Number>
134 {
135 public:
140
145
149 static constexpr unsigned int problem_dimension = 1 + dim;
150
154 using state_type = dealii::Tensor<1, problem_dimension, Number>;
155
159 using flux_type =
160 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
161
165 using flux_contribution_type = std::tuple<state_type, Number>;
166
171 static inline const auto component_names =
172 []() -> std::array<std::string, problem_dimension> {
173 if constexpr (dim == 1)
174 return {"h", "m"};
175 else if constexpr (dim == 2)
176 return {"h", "m_1", "m_2"};
177 else if constexpr (dim == 3)
178 return {"h", "m_1", "m_2", "m_3"};
179 __builtin_trap();
180 }();
181
186 static inline const auto primitive_component_names =
187 []() -> std::array<std::string, problem_dimension> {
188 if constexpr (dim == 1)
189 return {"h", "v"};
190 else if constexpr (dim == 2)
191 return {"h", "v_1", "v_2"};
192 else if constexpr (dim == 3)
193 return {"h", "v_1", "v_2", "v_3"};
194 __builtin_trap();
195 }();
196
200 static constexpr unsigned int n_precomputed_values = 2;
201
205 using precomputed_type = std::array<Number, n_precomputed_values>;
206
210 static inline const auto precomputed_names =
211 std::array<std::string, n_precomputed_values>{"eta_m", "h_star"};
212
216 static constexpr unsigned int n_initial_precomputed_values = 1;
217
222 std::array<Number, n_initial_precomputed_values>;
223
227 static inline const auto initial_precomputed_names =
228 std::array<std::string, n_initial_precomputed_values>{"bathymetry"};
229
233 using StateVector = Vectors::
234 StateVector<ScalarNumber, problem_dimension, n_precomputed_values>;
235
241
247
255 dealii::VectorizedArray<ScalarNumber>::size(),
256 dealii::MemorySpace::Host,
257 /*writable=*/false>;
258
266
274 dealii::VectorizedArray<ScalarNumber>::size(),
275 dealii::MemorySpace::Host,
276 /*writable=*/false>;
277
279
283
288 HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
289 : hyperbolic_system_(hyperbolic_system)
290 {
291 }
292
294
298
299 DEAL_II_ALWAYS_INLINE inline ScalarNumber gravity() const
300 {
301 return hyperbolic_system_.gravity_;
302 }
303
304 DEAL_II_ALWAYS_INLINE inline ScalarNumber
306 {
307 return hyperbolic_system_.manning_friction_coefficient_;
308 }
309
310 DEAL_II_ALWAYS_INLINE inline ScalarNumber reference_water_depth() const
311 {
312 return hyperbolic_system_.reference_water_depth_;
313 }
314
315 DEAL_II_ALWAYS_INLINE inline ScalarNumber
317 {
318 return hyperbolic_system_.dry_state_relaxation_small_;
319 }
320
321 DEAL_II_ALWAYS_INLINE inline ScalarNumber
323 {
324 return hyperbolic_system_.dry_state_relaxation_large_;
325 }
326
328
332
337 static Number water_depth(const state_type &U);
338
345 Number inverse_water_depth_mollified(const state_type &U) const;
346
353 Number water_depth_sharp(const state_type &U) const;
354
361 Number inverse_water_depth_sharp(const state_type &U) const;
362
369 Number filter_dry_water_depth(const Number &h) const;
370
375 static dealii::Tensor<1, dim, Number> momentum(const state_type &U);
376
384 Number kinetic_energy(const state_type &U) const;
385
393 Number pressure(const state_type &U) const;
394
402 Number speed_of_sound(const state_type &U) const;
403
408 Number mathematical_entropy(const state_type &U) const;
409
415
421 bool is_admissible(const state_type &U) const;
422
424
428
434 template <int component>
436 const state_type &U,
437 const state_type &U_bar,
438 const dealii::Tensor<1, dim, Number> &normal) const;
439
443 template <typename Lambda>
445 apply_boundary_conditions(const dealii::types::boundary_id id,
446 const state_type &U,
447 const dealii::Tensor<1, dim, Number> &normal,
448 const Lambda &get_dirichlet_data) const;
449
451
455
465 flux_type f(const state_type &U) const;
466
476 flux_type g(const state_type &U) const;
477
484 const Number &Z_left,
485 const Number &Z_right) const;
486
492 std::array<state_type, 2>
494 const flux_contribution_type &) const;
495
519 const unsigned int i,
520 const state_type &U_i) const;
521
525 const unsigned int *js,
526 const state_type &U_j) const;
527
535 const flux_contribution_type &flux_j,
536 const dealii::Tensor<1, dim, Number> &c_ij) const;
537
541 static constexpr bool have_high_order_flux = true;
542
549 const flux_contribution_type &flux_i,
550 const flux_contribution_type &flux_j,
551 const dealii::Tensor<1, dim, Number> &c_ij) const;
552
559 const flux_contribution_type &flux_j,
560 const dealii::Tensor<1, dim, Number> &c_ij,
561 const Number &d_ij) const;
562
564
568
570 static constexpr bool have_source_terms = true;
571
578 const Number &h_star,
579 const ScalarNumber tau) const;
580
582 const unsigned int i,
583 const state_type &U_i,
584 const ScalarNumber tau) const;
585
587 const unsigned int *js,
588 const state_type &U_j,
589 const ScalarNumber tau) const;
590
592
596
607 template <typename ST>
608 state_type expand_state(const ST &state) const;
609
621 template <typename ST>
622 state_type from_initial_state(const ST &initial_state) const;
623
628 state_type from_primitive_state(const state_type &primitive_state) const;
629
633 state_type to_primitive_state(const state_type &state) const;
634
640 template <typename Lambda>
642 const Lambda &lambda) const;
643
644 private:
646
650
651 const HyperbolicSystem &hyperbolic_system_;
652
654 }; /* HyperbolicSystemView */
655
656
657 /*
658 * -------------------------------------------------------------------------
659 * Inline definitions
660 * -------------------------------------------------------------------------
661 */
662
663
664 inline HyperbolicSystem::HyperbolicSystem(const std::string &subsection)
665 : ParameterAcceptor(subsection)
666 {
667 gravity_ = 9.81;
668 add_parameter("gravity", gravity_, "Gravitational constant [m/s^2]");
669
670 manning_friction_coefficient_ = 0.;
671 add_parameter("manning friction coefficient",
672 manning_friction_coefficient_,
673 "Roughness coefficient for friction source");
674
675 reference_water_depth_ = 1.;
676 add_parameter("reference water depth",
677 reference_water_depth_,
678 "Problem specific water depth reference");
679
680 dry_state_relaxation_small_ = 1.e2;
681 add_parameter("dry state relaxation small",
682 dry_state_relaxation_small_,
683 "Problem specific dry-state relaxation parameter");
684
685 dry_state_relaxation_large_ = 1.e4;
686 add_parameter("dry state relaxation large",
687 dry_state_relaxation_large_,
688 "Problem specific dry-state relaxation parameter");
689 }
690
691
692 template <int dim, typename ScalarNumber>
694 const OfflineData<dim, ScalarNumber> &offline_data,
696 &state_vector,
697 const bool skip_constrained_dofs) const
698 {
699 const unsigned int n_internal = offline_data.n_locally_internal();
700 const unsigned int n_owned = offline_data.n_locally_owned();
701 const auto sparsity_simd_view =
702 offline_data.sparsity_pattern_simd().view();
703 using VA = dealii::VectorizedArray<ScalarNumber>;
704
705 const auto U_view = std::get<0>(state_vector).view();
706 const auto precomputed_view = std::get<1>(state_vector).view();
707
708 const auto body = [&](auto sentinel, unsigned int i) {
709 using T = decltype(sentinel);
711 using precomputed_type = typename View::precomputed_type;
712
713 const unsigned int row_length = sparsity_simd_view.row_length(i);
714 if (skip_constrained_dofs && row_length == 1)
715 return;
716
717 const auto U_i = U_view.template read_tensor<T>(i);
718 const auto view = this->view<dim, T>();
719 const auto eta_m = view.mathematical_entropy(U_i);
720 const auto h_sharp = view.water_depth_sharp(U_i);
721 const auto h_star = ryujin::pow(h_sharp, ScalarNumber(4. / 3.));
722
723 const precomputed_type prec_i{eta_m, h_star};
724
725 precomputed_view.template write_tensor<T>(prec_i, i);
726 };
727
728 cpu_simd_loop<ScalarNumber>("time_step_1", body, 0, n_internal, n_owned);
729 }
730
731
732 template <int dim, typename Number>
733 DEAL_II_ALWAYS_INLINE inline Number
735 {
736 return U[0];
737 }
738
739
740 template <int dim, typename Number>
741 DEAL_II_ALWAYS_INLINE inline Number
743 const state_type &U) const
744 {
745 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
746
747 const Number h_cutoff_mollified =
748 reference_water_depth() * dry_state_relaxation_large() * Number(eps);
749
750 const Number h = water_depth(U);
751 const Number h_pos = positive_part(water_depth(U));
752 const Number h_max = std::max(h, h_cutoff_mollified);
753 const Number denom = h * h + h_max * h_max;
754 return ScalarNumber(2.) * h_pos / denom;
755 }
756
757
758 template <int dim, typename Number>
759 DEAL_II_ALWAYS_INLINE inline Number
761 const state_type &U) const
762 {
763 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
764
765 const Number h_cutoff_small =
766 reference_water_depth() * dry_state_relaxation_small() * Number(eps);
767
768 const Number h = water_depth(U);
769 const Number h_max = std::max(h, h_cutoff_small);
770 return h_max;
771 }
772
773
774 template <int dim, typename Number>
775 DEAL_II_ALWAYS_INLINE inline Number
777 const state_type &U) const
778 {
779 return ScalarNumber(1.) / water_depth_sharp(U);
780 }
781
782
783 template <int dim, typename Number>
784 DEAL_II_ALWAYS_INLINE inline Number
786 const Number &h) const
787 {
789 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
790
791 const Number h_cutoff_large =
792 reference_water_depth() * dry_state_relaxation_large() * Number(eps);
793
794 return dealii::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
795 std::abs(h), h_cutoff_large, Number(0.), h);
796 }
797
798
799 template <int dim, typename Number>
800 DEAL_II_ALWAYS_INLINE inline dealii::Tensor<1, dim, Number>
802 {
803 dealii::Tensor<1, dim, Number> result;
804
805 for (unsigned int i = 0; i < dim; ++i)
806 result[i] = U[1 + i];
807 return result;
808 }
809
810
811 template <int dim, typename Number>
812 DEAL_II_ALWAYS_INLINE inline Number
814 {
815 const auto h = water_depth(U);
816 const auto vel = momentum(U) * inverse_water_depth_sharp(U);
817
818 /* KE = 1/2 h |v|^2 */
819 return ScalarNumber(0.5) * h * vel.norm_square();
820 }
821
822
823 template <int dim, typename Number>
824 DEAL_II_ALWAYS_INLINE inline Number
826 {
827 const Number h_sqd = U[0] * U[0];
828
829 /* p = 1/2 g h^2 */
830 return ScalarNumber(0.5) * gravity() * h_sqd;
831 }
832
833
834 template <int dim, typename Number>
835 DEAL_II_ALWAYS_INLINE inline Number
837 {
838 /* c^2 = g * h */
839 return std::sqrt(gravity() * U[0]);
840 }
841
842
843 template <int dim, typename Number>
844 DEAL_II_ALWAYS_INLINE inline Number
846 const state_type &U) const
847 {
848 const auto p = pressure(U);
849 const auto k_e = kinetic_energy(U);
850 return p + k_e;
851 }
852
853
854 template <int dim, typename Number>
855 DEAL_II_ALWAYS_INLINE inline auto
857 const state_type &U) const -> state_type
858 {
859 /*
860 * With
861 * eta = 1/2 g h^2 + 1/2 |m|^2 / h
862 *
863 * we get
864 *
865 * eta' = (g h - 1/2 |vel|^2, vel)
866 *
867 * where vel = m / h
868 */
869
870 state_type result;
871
872 const Number &h = U[0];
873 const auto vel = momentum(U) * inverse_water_depth_sharp(U);
874
875 // water depth component
876 result[0] = gravity() * h - ScalarNumber(0.5) * vel.norm_square();
877
878 // momentum components
879 for (unsigned int i = 0; i < dim; ++i) {
880 result[1 + i] = vel[i];
881 }
882
883 return result;
884 }
885
886
887 template <int dim, typename Number>
888 DEAL_II_ALWAYS_INLINE inline bool
890 {
891 const auto h = filter_dry_water_depth(water_depth(U));
892
893 constexpr auto gte = dealii::SIMDComparison::greater_than_or_equal;
894 const auto test = dealii::compare_and_apply_mask<gte>(
895 h, Number(0.), Number(0.), Number(-1.));
896
897#ifdef DEBUG_OUTPUT
898 if (!(test == Number(0.))) {
899 std::cout << std::fixed << std::setprecision(16);
900 std::cout << "Bounds violation: Negative state [h] detected!\n";
901 std::cout << "\t\th: " << h << "\n" << std::endl;
902 __builtin_trap();
903 }
904#endif
905
906 return (test == Number(0.));
907 }
908
909
910 template <int dim, typename Number>
911 template <int component>
912 DEAL_II_ALWAYS_INLINE inline auto
914 const state_type &U,
915 const state_type &U_bar,
916 const dealii::Tensor<1, dim, Number> &normal) const -> state_type
917 {
918 /* Note that U_bar are the dirichlet values that are prescribed */
919 static_assert(component == 1 || component == 2,
920 "component has to be 1 or 2");
921
923
924 const auto m = momentum(U);
925 const auto a = speed_of_sound(U);
926 const auto vn = m * normal * inverse_water_depth_sharp(U);
927
928 const auto m_bar = momentum(U_bar);
929 const auto a_bar = speed_of_sound(U_bar);
930 const auto vn_bar = m_bar * normal * inverse_water_depth_sharp(U_bar);
931
932 /* First Riemann characteristic: v * n - 2 * a */
933
934 const auto R_1 = component == 1 ? vn_bar - ScalarNumber(2.) * a_bar
935 : vn - ScalarNumber(2.) * a;
936
937 /* Second Riemann characteristic: v * n + 2 * a */
938
939 const auto R_2 = component == 2 ? vn_bar + ScalarNumber(2.) * a_bar
940 : vn + ScalarNumber(2.) * a;
941
942 const auto vperp = m * inverse_water_depth_sharp(U) - vn * normal;
943
944 const auto vn_new = ScalarNumber(0.5) * (R_1 + R_2);
945
946 const auto h_new =
947 ryujin::fixed_power<2>((R_2 - R_1) / ScalarNumber(4.)) / gravity();
948
949 state_type U_new;
950 U_new[0] = h_new;
951 for (unsigned int d = 0; d < dim; ++d) {
952 U_new[1 + d] = h_new * (vn_new * normal + vperp)[d];
953 }
954
955 return U_new;
956 }
957
958
959 template <int dim, typename Number>
960 template <typename Lambda>
961 DEAL_II_ALWAYS_INLINE inline auto
963 const dealii::types::boundary_id id,
964 const state_type &U,
965 const dealii::Tensor<1, dim, Number> &normal,
966 const Lambda &get_dirichlet_data) const -> state_type
967 {
968 state_type result = U;
969
970 if (id == Boundary::dirichlet) {
971 result = get_dirichlet_data();
972
973 } else if (id == Boundary::dirichlet_momentum) {
974 /* Only enforce Dirichlet conditions on the momentum: */
975 auto m_dirichlet = momentum(get_dirichlet_data());
976 for (unsigned int k = 0; k < dim; ++k)
977 result[k + 1] = m_dirichlet[k];
978
979 } else if (id == Boundary::dirichlet_velocity) {
980 /* Only enforce Dirichlet conditions on the velocity: */
981 const auto U_dirichlet = get_dirichlet_data();
982 const auto h_inv_sharp_dirichlet =
983 inverse_water_depth_sharp(U_dirichlet);
984 const auto v_dirichlet = momentum(U_dirichlet) * h_inv_sharp_dirichlet;
985 const auto h = water_depth_sharp(result);
986 for (unsigned int k = 0; k < dim; ++k)
987 result[k + 1] = h * v_dirichlet[k];
988
989 } else if (id == Boundary::slip) {
990 auto m = momentum(U);
991 m -= 1. * (m * normal) * normal;
992 for (unsigned int k = 0; k < dim; ++k)
993 result[k + 1] = m[k];
994
995 } else if (id == Boundary::no_slip) {
996 for (unsigned int k = 0; k < dim; ++k)
997 result[k + 1] = Number(0.);
998
999 } else if (id == Boundary::dynamic) {
1000 /*
1001 * On dynamic boundary conditions, we distinguish four cases:
1002 *
1003 * - supersonic inflow: prescribe full state
1004 * - subsonic inflow:
1005 * decompose into Riemann invariants and leave R_2
1006 * characteristic untouched.
1007 * - supersonic outflow: do nothing
1008 * - subsonic outflow:
1009 * decompose into Riemann invariants and prescribe incoming
1010 * R_1 characteristic.
1011 */
1012 const auto m = momentum(U);
1013 const auto h_inverse = inverse_water_depth_sharp(U);
1014 const auto a = speed_of_sound(U);
1015 const auto vn = m * normal * h_inverse;
1016
1017 /* Supersonic inflow: */
1018 if (vn < -a) {
1019 result = get_dirichlet_data();
1020 }
1021
1022 /* Subsonic inflow: */
1023 if (vn >= -a && vn <= 0.) {
1024 const auto U_dirichlet = get_dirichlet_data();
1025 result = prescribe_riemann_characteristic<2>(U_dirichlet, U, normal);
1026 }
1027
1028 /* Subsonic outflow: */
1029 if (vn > 0. && vn <= a) {
1030 const auto U_dirichlet = get_dirichlet_data();
1031 result = prescribe_riemann_characteristic<1>(U, U_dirichlet, normal);
1032 }
1033
1034 /* Supersonic outflow: do nothing, i.e., keep U as is */
1035
1036 } else {
1037 AssertThrow(false, dealii::ExcNotImplemented());
1038 }
1039
1040 return result;
1041 }
1042
1043
1044 template <int dim, typename Number>
1045 DEAL_II_ALWAYS_INLINE inline auto
1047 {
1048 const auto h_inverse = inverse_water_depth_sharp(U);
1049 const auto m = momentum(U);
1050 const auto p = pressure(U);
1051
1052 flux_type result;
1053
1054 result[0] = (m * h_inverse) * U[0];
1055 for (unsigned int i = 0; i < dim; ++i) {
1056 result[1 + i] = (m * h_inverse) * m[i];
1057 result[1 + i][i] += p;
1058 }
1059 return result;
1060 }
1061
1062
1063 template <int dim, typename Number>
1064 DEAL_II_ALWAYS_INLINE inline auto
1066 {
1067 const auto h_inverse = inverse_water_depth_sharp(U);
1068 const auto m = momentum(U);
1069
1070 flux_type result;
1071
1072 result[0] = (m * h_inverse) * U[0];
1073 for (unsigned int i = 0; i < dim; ++i) {
1074 result[1 + i] = (m * h_inverse) * m[i];
1075 }
1076 return result;
1077 }
1078
1079
1080 template <int dim, typename Number>
1081 DEAL_II_ALWAYS_INLINE inline auto
1083 const Number &Z_left,
1084 const Number &Z_right) const
1085 -> state_type
1086 {
1087 const Number Z_max = std::max(Z_left, Z_right);
1088 const Number h = water_depth(U);
1089 const Number H_star = std::max(Number(0.), h + Z_left - Z_max);
1090
1091 return U * H_star * inverse_water_depth_mollified(U);
1092 }
1093
1094
1095 template <int dim, typename Number>
1096 DEAL_II_ALWAYS_INLINE inline auto
1098 const flux_contribution_type &flux_i,
1099 const flux_contribution_type &flux_j) const -> std::array<state_type, 2>
1100 {
1101 const auto &[U_i, Z_i] = flux_i;
1102 const auto &[U_j, Z_j] = flux_j;
1103
1104 const auto U_star_ij = star_state(U_i, Z_i, Z_j);
1105 const auto U_star_ji = star_state(U_j, Z_j, Z_i);
1106
1107 return {U_star_ij, U_star_ji};
1108 }
1109
1110
1111 template <int dim, typename Number>
1112 DEAL_II_ALWAYS_INLINE inline auto
1114 const PrecomputedVectorView & /*pv*/,
1116 const unsigned int i,
1117 const state_type &U_i) const -> flux_contribution_type
1118 {
1119 const auto Z_i = piv.template read_tensor<Number>(i)[0];
1120 return {U_i, Z_i};
1121 }
1122
1123
1124 template <int dim, typename Number>
1125 DEAL_II_ALWAYS_INLINE inline auto
1127 const PrecomputedVectorView & /*pv*/,
1129 const unsigned int *js,
1130 const state_type &U_j) const -> flux_contribution_type
1131 {
1132 const auto Z_j = piv.template read_tensor<Number>(js)[0];
1133 return {U_j, Z_j};
1134 }
1135
1136
1137 template <int dim, typename Number>
1138 DEAL_II_ALWAYS_INLINE inline auto
1140 const flux_contribution_type &flux_i,
1141 const flux_contribution_type &flux_j,
1142 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1143 {
1144 const auto &[U_i, Z_i] = flux_i;
1145 const auto &[U_star_ij, U_star_ji] = equilibrated_states(flux_i, flux_j);
1146
1147 const auto H_i = water_depth(U_i);
1148 const auto H_star_ij = water_depth(U_star_ij);
1149 const auto H_star_ji = water_depth(U_star_ji);
1150
1151 const auto g_i = g(U_star_ij);
1152 const auto g_j = g(U_star_ji);
1153
1154 auto result = -add(g_i, g_j);
1155
1156 const auto factor =
1157 (ScalarNumber(0.5) * (H_star_ji * H_star_ji - H_star_ij * H_star_ij) +
1158 H_i * H_i) *
1159 gravity();
1160
1161 for (unsigned int i = 0; i < dim; ++i) {
1162 result[1 + i][i] -= factor;
1163 }
1164
1165 return contract(result, c_ij);
1166 }
1167
1168
1169 template <int dim, typename Number>
1170 DEAL_II_ALWAYS_INLINE inline auto
1172 const flux_contribution_type &flux_i,
1173 const flux_contribution_type &flux_j,
1174 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1175 {
1176 const auto &[U_i, Z_i] = flux_i;
1177 const auto &[U_j, Z_j] = flux_j;
1178
1179 const auto H_i = water_depth(U_i);
1180 const auto H_j = water_depth(U_j);
1181
1182 const auto g_i = g(U_i);
1183 const auto g_j = g(U_j);
1184
1185 auto result = -add(g_i, g_j);
1186
1187 const auto factor = gravity() * H_i * (H_j + Z_j - Z_i);
1188 for (unsigned int i = 0; i < dim; ++i) {
1189 result[1 + i][i] -= factor;
1190 }
1191
1192 return contract(result, c_ij);
1193 }
1194
1195
1196 template <int dim, typename Number>
1197 DEAL_II_ALWAYS_INLINE inline auto
1199 const flux_contribution_type &flux_i,
1200 const flux_contribution_type &flux_j,
1201 const dealii::Tensor<1, dim, Number> &c_ij,
1202 const Number &d_ij) const -> state_type
1203 {
1204 const auto &[U_i, Z_i] = flux_i;
1205 const auto &[U_j, Z_j] = flux_j;
1206 const auto U_star_ij = star_state(U_i, Z_i, Z_j);
1207
1208 const auto h_inverse = inverse_water_depth_sharp(U_i);
1209 const auto m = momentum(U_i);
1210 const auto factor = ScalarNumber(2.) * (d_ij + h_inverse * (m * c_ij));
1211
1212 return -factor * (U_star_ij - U_i);
1213 }
1214
1215
1216 template <int dim, typename Number>
1217 DEAL_II_ALWAYS_INLINE inline auto
1219 const state_type &U, const Number &h_star, const ScalarNumber tau) const
1220 -> state_type
1221 {
1222 state_type result;
1223
1224 const auto g = gravity();
1225 const auto n = manning_friction_coefficient();
1226
1227 const auto h_inverse = inverse_water_depth_mollified(U);
1228
1229 const auto m = momentum(U);
1230 const auto v_norm = (m * h_inverse).norm();
1231 const auto factor = ScalarNumber(2.) * g * n * n * v_norm;
1232
1233 const auto denominator = h_star + std::max(h_star, tau * factor);
1234 const auto denominator_inverse = ScalarNumber(1.) / denominator;
1235
1236 for (unsigned int d = 0; d < dim; ++d)
1237 result[d + 1] = -factor * denominator_inverse * m[d];
1238
1239 return result;
1240 }
1241
1242
1243 template <int dim, typename Number>
1244 DEAL_II_ALWAYS_INLINE inline auto
1246 const PrecomputedVectorView &pv,
1247 const unsigned int i,
1248 const state_type &U_i,
1249 const ScalarNumber tau) const -> state_type
1250 {
1251 const auto &[eta_m, h_star] =
1252 pv.template read_tensor<Number, precomputed_type>(i);
1253
1254 return manning_friction(U_i, h_star, tau);
1255 }
1256
1257
1258 template <int dim, typename Number>
1259 DEAL_II_ALWAYS_INLINE inline auto
1261 const PrecomputedVectorView &pv,
1262 const unsigned int *js,
1263 const state_type &U_j,
1264 const ScalarNumber tau) const -> state_type
1265 {
1266 const auto &[eta_m, h_star] =
1267 pv.template read_tensor<Number, precomputed_type>(js);
1268
1269 return manning_friction(U_j, h_star, tau);
1270 }
1271
1272
1273 template <int dim, typename Number>
1274 template <typename ST>
1275 DEAL_II_ALWAYS_INLINE inline auto
1277 -> state_type
1278 {
1279 using T = typename ST::value_type;
1280 static_assert(std::is_same_v<Number, T>, "template mismatch");
1281
1282 constexpr auto dim2 = ST::dimension - 1;
1283 static_assert(dim >= dim2,
1284 "the space dimension of the argument state must not be "
1285 "larger than the one of the target state");
1286
1287 state_type result;
1288 result[0] = state[0];
1289 for (unsigned int i = 1; i < dim2 + 1; ++i)
1290 result[i] = state[i];
1291
1292 return result;
1293 }
1294
1295 template <int dim, typename Number>
1296 template <typename ST>
1297 DEAL_II_ALWAYS_INLINE inline auto
1299 const ST &initial_state) const -> state_type
1300 {
1301 const auto primitive_state = expand_state(initial_state);
1302 return from_primitive_state(primitive_state);
1303 }
1304
1305
1306 template <int dim, typename Number>
1307 DEAL_II_ALWAYS_INLINE inline auto
1309 const state_type &primitive_state) const -> state_type
1310 {
1311 const auto &h = primitive_state[0];
1312
1313 auto state = primitive_state;
1314 /* Fix up momentum: */
1315 for (unsigned int i = 1; i < dim + 1; ++i)
1316 state[i] *= h;
1317
1318 return state;
1319 }
1320
1321
1322 template <int dim, typename Number>
1323 DEAL_II_ALWAYS_INLINE inline auto
1325 const state_type &state) const -> state_type
1326 {
1327 const auto h_inverse = inverse_water_depth_sharp(state);
1328
1329 auto primitive_state = state;
1330 /* Fix up velocity: */
1331 for (unsigned int i = 1; i < dim + 1; ++i)
1332 primitive_state[i] *= h_inverse;
1333
1334 return primitive_state;
1335 }
1336
1337
1338 template <int dim, typename Number>
1339 template <typename Lambda>
1340 DEAL_II_ALWAYS_INLINE inline auto
1342 const state_type &state, const Lambda &lambda) const -> state_type
1343 {
1344 auto result = state;
1345 auto M = lambda(momentum(state));
1346 for (unsigned int d = 0; d < dim; ++d)
1347 result[1 + d] = M[d];
1348 return result;
1349 }
1350
1351 } // namespace ShallowWater
1352} // namespace ryujin
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
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
Number pressure(const state_type &U) const
flux_contribution_type flux_contribution(const PrecomputedVectorView &pv, const InitialPrecomputedVectorView &piv, const unsigned int i, const state_type &U_i) const
state_type flux_divergence(const flux_contribution_type &flux_i, const flux_contribution_type &flux_j, const dealii::Tensor< 1, dim, Number > &c_ij) const
DEAL_II_ALWAYS_INLINE ScalarNumber gravity() const
bool is_admissible(const state_type &U) const
state_type mathematical_entropy_derivative(const state_type &U) const
typename get_value_type< Number >::type ScalarNumber
static Number water_depth(const state_type &U)
DEAL_II_ALWAYS_INLINE ScalarNumber dry_state_relaxation_large() const
static constexpr unsigned int n_initial_precomputed_values
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
DEAL_II_ALWAYS_INLINE ScalarNumber dry_state_relaxation_small() const
Number inverse_water_depth_mollified(const state_type &U) const
Number water_depth_sharp(const state_type &U) const
Vectors::StateVector< ScalarNumber, problem_dimension, n_precomputed_values > StateVector
static constexpr unsigned int n_precomputed_values
Number inverse_water_depth_sharp(const state_type &U) const
Number kinetic_energy(const state_type &U) const
Number filter_dry_water_depth(const Number &h) const
state_type from_primitive_state(const state_type &primitive_state) const
state_type manning_friction(const state_type &U, const Number &h_star, const ScalarNumber tau) const
state_type expand_state(const ST &state) const
std::array< Number, n_initial_precomputed_values > initial_precomputed_type
DEAL_II_ALWAYS_INLINE ScalarNumber manning_friction_coefficient() const
Number speed_of_sound(const state_type &U) const
state_type star_state(const state_type &U, const Number &Z_left, const Number &Z_right) const
dealii::Tensor< 1, problem_dimension, Number > state_type
static dealii::Tensor< 1, dim, Number > momentum(const state_type &U)
state_type affine_shift(const flux_contribution_type &flux_i, const flux_contribution_type &flux_j, const dealii::Tensor< 1, dim, Number > &c_ij, const Number &d_ij) const
std::array< Number, n_precomputed_values > precomputed_type
state_type nodal_source(const PrecomputedVectorView &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const
state_type to_primitive_state(const state_type &state) const
state_type from_initial_state(const ST &initial_state) const
static constexpr unsigned int problem_dimension
flux_type g(const state_type &U) const
Number mathematical_entropy(const state_type &U) 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
std::array< state_type, 2 > equilibrated_states(const flux_contribution_type &, const flux_contribution_type &) const
std::tuple< state_type, Number > flux_contribution_type
flux_type f(const state_type &U) const
state_type prescribe_riemann_characteristic(const state_type &U, const state_type &U_bar, const dealii::Tensor< 1, dim, Number > &normal) const
state_type apply_galilei_transform(const state_type &state, const Lambda &lambda) const
DEAL_II_ALWAYS_INLINE ScalarNumber reference_water_depth() const
void fill_precomputed_values(const OfflineData< dim, ScalarNumber > &offline_data, typename HyperbolicSystemView< dim, ScalarNumber >::StateVector &state_vector, const bool skip_constrained_dofs=true) const
HyperbolicSystem(const std::string &subsection="/HyperbolicSystem")
@ dirichlet_momentum
@ dirichlet_velocity
DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor< 1, problem_dim, T > contract(const FT &flux_ij, const TT &c_ij)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE FT add(const FT &flux_left_ij, const FT &flux_right_ij)
DEAL_II_HOST_DEVICE T pow(const T x, const T b)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number positive_part(const Number number)
Definition simd.h:149