ryujin 2.1.1 revision 0348cbb53a3e4b1da2a4c037e81f88f2d21ce219
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 - 2024 by the ryujin authors
5// Copyright (C) 2023 - 2024 by Triad National Security, LLC
6//
7
8#pragma once
9
10#include <convenience_macros.h>
11#include <deal.II/base/config.h>
12#include <discretization.h>
14#include <openmp.h>
15#include <patterns_conversion.h>
16#include <simd.h>
17#include <state_vector.h>
18
19#include <deal.II/base/parameter_acceptor.h>
20#include <deal.II/base/tensor.h>
21
22#include <array>
23
24namespace ryujin
25{
26 namespace ShallowWater
27 {
28 template <int dim, typename Number>
29 class HyperbolicSystemView;
30
40 class HyperbolicSystem final : public dealii::ParameterAcceptor
41 {
42 public:
46 static inline const std::string problem_name = "Shallow water equations";
47
51 HyperbolicSystem(const std::string &subsection = "/HyperbolicSystem");
52
59 template <int dim, typename Number>
60 auto view() const
61 {
63 }
64
65 private:
70 double gravity_;
71 double manning_friction_coefficient_;
72
73 double reference_water_depth_;
74 double dry_state_relaxation_small_;
75 double dry_state_relaxation_large_;
76
77 template <int dim, typename Number>
80 }; /* HyperbolicSystem */
81
82
99 template <int dim, typename Number>
101 {
102 public:
107 HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
108 : hyperbolic_system_(hyperbolic_system)
109 {
110 }
111
115 template <int dim2, typename Number2>
116 auto view() const
117 {
118 return HyperbolicSystemView<dim2, Number2>{hyperbolic_system_};
119 }
120
125
130
131 DEAL_II_ALWAYS_INLINE inline ScalarNumber gravity() const
132 {
133 return hyperbolic_system_.gravity_;
134 }
135
136 DEAL_II_ALWAYS_INLINE inline ScalarNumber
138 {
139 return hyperbolic_system_.manning_friction_coefficient_;
140 }
141
142 DEAL_II_ALWAYS_INLINE inline ScalarNumber reference_water_depth() const
143 {
144 return hyperbolic_system_.reference_water_depth_;
145 }
146
147 DEAL_II_ALWAYS_INLINE inline ScalarNumber
149 {
150 return hyperbolic_system_.dry_state_relaxation_small_;
151 }
152
153 DEAL_II_ALWAYS_INLINE inline ScalarNumber
155 {
156 return hyperbolic_system_.dry_state_relaxation_large_;
157 }
158
160
164
165 private:
166 const HyperbolicSystem &hyperbolic_system_;
167
168 public:
170
174
178 static constexpr unsigned int problem_dimension = 1 + dim;
179
183 using state_type = dealii::Tensor<1, problem_dimension, Number>;
184
188 using flux_type =
189 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
190
194 using flux_contribution_type = std::tuple<state_type, Number>;
195
200 static inline const auto component_names =
201 []() -> std::array<std::string, problem_dimension> {
202 if constexpr (dim == 1)
203 return {"h", "m"};
204 else if constexpr (dim == 2)
205 return {"h", "m_1", "m_2"};
206 else if constexpr (dim == 3)
207 return {"h", "m_1", "m_2", "m_3"};
208 __builtin_trap();
209 }();
210
215 static inline const auto primitive_component_names =
216 []() -> std::array<std::string, problem_dimension> {
217 if constexpr (dim == 1)
218 return {"h", "v"};
219 else if constexpr (dim == 2)
220 return {"h", "v_1", "v_2"};
221 else if constexpr (dim == 3)
222 return {"h", "v_1", "v_2", "v_3"};
223 __builtin_trap();
224 }();
225
229 static constexpr unsigned int n_precomputed_values = 2;
230
234 using precomputed_type = std::array<Number, n_precomputed_values>;
235
239 static inline const auto precomputed_names =
240 std::array<std::string, n_precomputed_values>{"eta_m", "h_star"};
241
245 static constexpr unsigned int n_initial_precomputed_values = 1;
246
251 std::array<Number, n_initial_precomputed_values>;
252
256 static inline const auto initial_precomputed_names =
257 std::array<std::string, n_initial_precomputed_values>{"bathymetry"};
258
262 using StateVector = Vectors::
263 StateVector<ScalarNumber, problem_dimension, n_precomputed_values>;
264
270
276
284
286
290
294 static constexpr unsigned int n_precomputation_cycles = 1;
295
300 template <typename DISPATCH, typename SPARSITY>
301 void precomputation_loop(unsigned int cycle,
302 const DISPATCH &dispatch_check,
303 const SPARSITY &sparsity_simd,
304 StateVector &state_vector,
305 unsigned int left,
306 unsigned int right) const;
307
309
313
318 static Number water_depth(const state_type &U);
319
326 Number inverse_water_depth_mollified(const state_type &U) const;
327
334 Number water_depth_sharp(const state_type &U) const;
335
342 Number inverse_water_depth_sharp(const state_type &U) const;
343
350 Number filter_dry_water_depth(const Number &h) const;
351
356 static dealii::Tensor<1, dim, Number> momentum(const state_type &U);
357
365 Number kinetic_energy(const state_type &U) const;
366
374 Number pressure(const state_type &U) const;
375
383 Number speed_of_sound(const state_type &U) const;
384
389 Number mathematical_entropy(const state_type &U) const;
390
396
402 bool is_admissible(const state_type &U) const;
403
405
409
415 template <int component>
417 const state_type &U,
418 const state_type &U_bar,
419 const dealii::Tensor<1, dim, Number> &normal) const;
420
424 template <typename Lambda>
426 apply_boundary_conditions(const dealii::types::boundary_id id,
427 const state_type &U,
428 const dealii::Tensor<1, dim, Number> &normal,
429 const Lambda &get_dirichlet_data) const;
430
432
436
446 flux_type f(const state_type &U) const;
447
457 flux_type g(const state_type &U) const;
458
465 const Number &Z_left,
466 const Number &Z_right) const;
467
473 std::array<state_type, 2>
475 const flux_contribution_type &) const;
476
499 const InitialPrecomputedVector &piv,
500 const unsigned int i,
501 const state_type &U_i) const;
502
505 const InitialPrecomputedVector &piv,
506 const unsigned int *js,
507 const state_type &U_j) const;
508
516 const flux_contribution_type &flux_j,
517 const dealii::Tensor<1, dim, Number> &c_ij) const;
518
522 static constexpr bool have_high_order_flux = true;
523
530 const flux_contribution_type &flux_i,
531 const flux_contribution_type &flux_j,
532 const dealii::Tensor<1, dim, Number> &c_ij) const;
533
540 const flux_contribution_type &flux_j,
541 const dealii::Tensor<1, dim, Number> &c_ij,
542 const Number &d_ij) const;
543
545
549
551 static constexpr bool have_source_terms = true;
552
559 const Number &h_star,
560 const ScalarNumber tau) const;
561
563 const unsigned int i,
564 const state_type &U_i,
565 const ScalarNumber tau) const;
566
568 const unsigned int *js,
569 const state_type &U_j,
570 const ScalarNumber tau) const;
571
573
578
589 template <typename ST>
590 state_type expand_state(const ST &state) const;
591
603 template <typename ST>
604 state_type from_initial_state(const ST &initial_state) const;
605
610 state_type from_primitive_state(const state_type &primitive_state) const;
611
615 state_type to_primitive_state(const state_type &state) const;
616
622 template <typename Lambda>
624 const Lambda &lambda) const;
625
626 }; /* HyperbolicSystemView */
627
628
629 /*
630 * -------------------------------------------------------------------------
631 * Inline definitions
632 * -------------------------------------------------------------------------
633 */
634
635
636 inline HyperbolicSystem::HyperbolicSystem(const std::string &subsection)
637 : ParameterAcceptor(subsection)
638 {
639 gravity_ = 9.81;
640 add_parameter("gravity", gravity_, "Gravitational constant [m/s^2]");
641
642 manning_friction_coefficient_ = 0.;
643 add_parameter("manning friction coefficient",
644 manning_friction_coefficient_,
645 "Roughness coefficient for friction source");
646
647 reference_water_depth_ = 1.;
648 add_parameter("reference water depth",
649 reference_water_depth_,
650 "Problem specific water depth reference");
651
652 dry_state_relaxation_small_ = 1.e2;
653 add_parameter("dry state relaxation small",
654 dry_state_relaxation_small_,
655 "Problem specific dry-state relaxation parameter");
656
657 dry_state_relaxation_large_ = 1.e4;
658 add_parameter("dry state relaxation large",
659 dry_state_relaxation_large_,
660 "Problem specific dry-state relaxation parameter");
661 }
662
663
664 template <int dim, typename Number>
665 template <typename DISPATCH, typename SPARSITY>
666 DEAL_II_ALWAYS_INLINE inline void
668 unsigned int cycle [[maybe_unused]],
669 const DISPATCH &dispatch_check,
670 const SPARSITY &sparsity_simd,
671 StateVector &state_vector,
672 unsigned int left,
673 unsigned int right) const
674 {
675 Assert(cycle == 0, dealii::ExcInternalError());
676
677 const auto &U = std::get<0>(state_vector);
678 auto &precomputed = std::get<1>(state_vector);
679
680 /* We are inside a thread parallel context */
681
682 unsigned int stride_size = get_stride_size<Number>;
683
685 for (unsigned int i = left; i < right; i += stride_size) {
686
687 /* Skip constrained degrees of freedom: */
688 const unsigned int row_length = sparsity_simd.row_length(i);
689 if (row_length == 1)
690 continue;
691
692 dispatch_check(i);
693
694 const auto U_i = U.template get_tensor<Number>(i);
695
696 const auto eta_m = mathematical_entropy(U_i);
697
698 const auto h_sharp = water_depth_sharp(U_i);
699 const auto h_star = ryujin::pow(h_sharp, ScalarNumber(4. / 3.));
700
701 const precomputed_type prec_i{eta_m, h_star};
702 precomputed.template write_tensor<Number>(prec_i, i);
703 }
704 }
705
706
707 template <int dim, typename Number>
708 DEAL_II_ALWAYS_INLINE inline Number
710 {
711 return U[0];
712 }
713
714
715 template <int dim, typename Number>
716 DEAL_II_ALWAYS_INLINE inline Number
718 const state_type &U) const
719 {
720 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
721
722 const Number h_cutoff_mollified =
723 reference_water_depth() * dry_state_relaxation_large() * Number(eps);
724
725 const Number h = water_depth(U);
726 const Number h_pos = positive_part(water_depth(U));
727 const Number h_max = std::max(h, h_cutoff_mollified);
728 const Number denom = h * h + h_max * h_max;
729 return ScalarNumber(2.) * h_pos / denom;
730 }
731
732
733 template <int dim, typename Number>
734 DEAL_II_ALWAYS_INLINE inline Number
736 const state_type &U) const
737 {
738 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
739
740 const Number h_cutoff_small =
741 reference_water_depth() * dry_state_relaxation_small() * Number(eps);
742
743 const Number h = water_depth(U);
744 const Number h_max = std::max(h, h_cutoff_small);
745 return h_max;
746 }
747
748
749 template <int dim, typename Number>
750 DEAL_II_ALWAYS_INLINE inline Number
752 const state_type &U) const
753 {
754 return ScalarNumber(1.) / water_depth_sharp(U);
755 }
756
757
758 template <int dim, typename Number>
759 DEAL_II_ALWAYS_INLINE inline Number
761 const Number &h) const
762 {
764 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
765
766 const Number h_cutoff_large =
767 reference_water_depth() * dry_state_relaxation_large() * Number(eps);
768
769 return dealii::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
770 std::abs(h), h_cutoff_large, Number(0.), h);
771 }
772
773
774 template <int dim, typename Number>
775 DEAL_II_ALWAYS_INLINE inline dealii::Tensor<1, dim, Number>
777 {
778 dealii::Tensor<1, dim, Number> result;
779
780 for (unsigned int i = 0; i < dim; ++i)
781 result[i] = U[1 + i];
782 return result;
783 }
784
785
786 template <int dim, typename Number>
787 DEAL_II_ALWAYS_INLINE inline Number
789 {
790 const auto h = water_depth(U);
791 const auto vel = momentum(U) * inverse_water_depth_sharp(U);
792
793 /* KE = 1/2 h |v|^2 */
794 return ScalarNumber(0.5) * h * vel.norm_square();
795 }
796
797
798 template <int dim, typename Number>
799 DEAL_II_ALWAYS_INLINE inline Number
801 {
802 const Number h_sqd = U[0] * U[0];
803
804 /* p = 1/2 g h^2 */
805 return ScalarNumber(0.5) * gravity() * h_sqd;
806 }
807
808
809 template <int dim, typename Number>
810 DEAL_II_ALWAYS_INLINE inline Number
812 {
813 /* c^2 = g * h */
814 return std::sqrt(gravity() * U[0]);
815 }
816
817
818 template <int dim, typename Number>
819 DEAL_II_ALWAYS_INLINE inline Number
821 const state_type &U) const
822 {
823 const auto p = pressure(U);
824 const auto k_e = kinetic_energy(U);
825 return p + k_e;
826 }
827
828
829 template <int dim, typename Number>
830 DEAL_II_ALWAYS_INLINE inline auto
832 const state_type &U) const -> state_type
833 {
834 /*
835 * With
836 * eta = 1/2 g h^2 + 1/2 |m|^2 / h
837 *
838 * we get
839 *
840 * eta' = (g h - 1/2 |vel|^2, vel)
841 *
842 * where vel = m / h
843 */
844
845 state_type result;
846
847 const Number &h = U[0];
848 const auto vel = momentum(U) * inverse_water_depth_sharp(U);
849
850 // water depth component
851 result[0] = gravity() * h - ScalarNumber(0.5) * vel.norm_square();
852
853 // momentum components
854 for (unsigned int i = 0; i < dim; ++i) {
855 result[1 + i] = vel[i];
856 }
857
858 return result;
859 }
860
861
862 template <int dim, typename Number>
863 DEAL_II_ALWAYS_INLINE inline bool
865 {
866 const auto h = filter_dry_water_depth(water_depth(U));
867
868 constexpr auto gte = dealii::SIMDComparison::greater_than_or_equal;
869 const auto test = dealii::compare_and_apply_mask<gte>(
870 h, Number(0.), Number(0.), Number(-1.));
871
872#ifdef DEBUG_OUTPUT
873 if (!(test == Number(0.))) {
874 std::cout << std::fixed << std::setprecision(16);
875 std::cout << "Bounds violation: Negative state [h] detected!\n";
876 std::cout << "\t\th: " << h << "\n" << std::endl;
877 __builtin_trap();
878 }
879#endif
880
881 return (test == Number(0.));
882 }
883
884
885 template <int dim, typename Number>
886 template <int component>
887 DEAL_II_ALWAYS_INLINE inline auto
889 const state_type &U,
890 const state_type &U_bar,
891 const dealii::Tensor<1, dim, Number> &normal) const -> state_type
892 {
893 /* Note that U_bar are the dirichlet values that are prescribed */
894 static_assert(component == 1 || component == 2,
895 "component has to be 1 or 2");
896
898
899 const auto m = momentum(U);
900 const auto a = speed_of_sound(U);
901 const auto vn = m * normal * inverse_water_depth_sharp(U);
902
903 const auto m_bar = momentum(U_bar);
904 const auto a_bar = speed_of_sound(U_bar);
905 const auto vn_bar = m_bar * normal * inverse_water_depth_sharp(U_bar);
906
907 /* First Riemann characteristic: v * n - 2 * a */
908
909 const auto R_1 = component == 1 ? vn_bar - ScalarNumber(2.) * a_bar
910 : vn - ScalarNumber(2.) * a;
911
912 /* Second Riemann characteristic: v * n + 2 * a */
913
914 const auto R_2 = component == 2 ? vn_bar + ScalarNumber(2.) * a_bar
915 : vn + ScalarNumber(2.) * a;
916
917 const auto vperp = m * inverse_water_depth_sharp(U) - vn * normal;
918
919 const auto vn_new = ScalarNumber(0.5) * (R_1 + R_2);
920
921 const auto h_new =
922 ryujin::fixed_power<2>((R_2 - R_1) / ScalarNumber(4.)) / gravity();
923
924 state_type U_new;
925 U_new[0] = h_new;
926 for (unsigned int d = 0; d < dim; ++d) {
927 U_new[1 + d] = h_new * (vn_new * normal + vperp)[d];
928 }
929
930 return U_new;
931 }
932
933
934 template <int dim, typename Number>
935 template <typename Lambda>
936 DEAL_II_ALWAYS_INLINE inline auto
938 const dealii::types::boundary_id id,
939 const state_type &U,
940 const dealii::Tensor<1, dim, Number> &normal,
941 const Lambda &get_dirichlet_data) const -> state_type
942 {
943 state_type result = U;
944
945 if (id == Boundary::dirichlet) {
946 result = get_dirichlet_data();
947
948 } else if (id == Boundary::dirichlet_momentum) {
949 /* Only enforce Dirichlet conditions on the momentum: */
950 auto m_dirichlet = momentum(get_dirichlet_data());
951 for (unsigned int k = 0; k < dim; ++k)
952 result[k + 1] = m_dirichlet[k];
953
954 } else if (id == Boundary::slip) {
955 auto m = momentum(U);
956 m -= 1. * (m * normal) * normal;
957 for (unsigned int k = 0; k < dim; ++k)
958 result[k + 1] = m[k];
959
960 } else if (id == Boundary::no_slip) {
961 for (unsigned int k = 0; k < dim; ++k)
962 result[k + 1] = Number(0.);
963
964 } else if (id == Boundary::dynamic) {
965 /*
966 * On dynamic boundary conditions, we distinguish four cases:
967 *
968 * - supersonic inflow: prescribe full state
969 * - subsonic inflow:
970 * decompose into Riemann invariants and leave R_2
971 * characteristic untouched.
972 * - supersonic outflow: do nothing
973 * - subsonic outflow:
974 * decompose into Riemann invariants and prescribe incoming
975 * R_1 characteristic.
976 */
977 const auto m = momentum(U);
978 const auto h_inverse = inverse_water_depth_sharp(U);
979 const auto a = speed_of_sound(U);
980 const auto vn = m * normal * h_inverse;
981
982 /* Supersonic inflow: */
983 if (vn < -a) {
984 result = get_dirichlet_data();
985 }
986
987 /* Subsonic inflow: */
988 if (vn >= -a && vn <= 0.) {
989 const auto U_dirichlet = get_dirichlet_data();
990 result = prescribe_riemann_characteristic<2>(U_dirichlet, U, normal);
991 }
992
993 /* Subsonic outflow: */
994 if (vn > 0. && vn <= a) {
995 const auto U_dirichlet = get_dirichlet_data();
996 result = prescribe_riemann_characteristic<1>(U, U_dirichlet, normal);
997 }
998
999 /* Supersonic outflow: do nothing, i.e., keep U as is */
1000
1001 } else {
1002 AssertThrow(false, dealii::ExcNotImplemented());
1003 }
1004
1005 return result;
1006 }
1007
1008
1009 template <int dim, typename Number>
1010 DEAL_II_ALWAYS_INLINE inline auto
1012 {
1013 const auto h_inverse = inverse_water_depth_sharp(U);
1014 const auto m = momentum(U);
1015 const auto p = pressure(U);
1016
1017 flux_type result;
1018
1019 result[0] = (m * h_inverse) * U[0];
1020 for (unsigned int i = 0; i < dim; ++i) {
1021 result[1 + i] = (m * h_inverse) * m[i];
1022 result[1 + i][i] += p;
1023 }
1024 return result;
1025 }
1026
1027
1028 template <int dim, typename Number>
1029 DEAL_II_ALWAYS_INLINE inline auto
1031 {
1032 const auto h_inverse = inverse_water_depth_sharp(U);
1033 const auto m = momentum(U);
1034
1035 flux_type result;
1036
1037 result[0] = (m * h_inverse) * U[0];
1038 for (unsigned int i = 0; i < dim; ++i) {
1039 result[1 + i] = (m * h_inverse) * m[i];
1040 }
1041 return result;
1042 }
1043
1044
1045 template <int dim, typename Number>
1046 DEAL_II_ALWAYS_INLINE inline auto
1048 const Number &Z_left,
1049 const Number &Z_right) const
1050 -> state_type
1051 {
1052 const Number Z_max = std::max(Z_left, Z_right);
1053 const Number h = water_depth(U);
1054 const Number H_star = std::max(Number(0.), h + Z_left - Z_max);
1055
1056 return U * H_star * inverse_water_depth_mollified(U);
1057 }
1058
1059
1060 template <int dim, typename Number>
1061 DEAL_II_ALWAYS_INLINE inline auto
1063 const flux_contribution_type &flux_i,
1064 const flux_contribution_type &flux_j) const -> std::array<state_type, 2>
1065 {
1066 const auto &[U_i, Z_i] = flux_i;
1067 const auto &[U_j, Z_j] = flux_j;
1068
1069 const auto U_star_ij = star_state(U_i, Z_i, Z_j);
1070 const auto U_star_ji = star_state(U_j, Z_j, Z_i);
1071
1072 return {U_star_ij, U_star_ji};
1073 }
1074
1075
1076 template <int dim, typename Number>
1077 DEAL_II_ALWAYS_INLINE inline auto
1079 const PrecomputedVector & /*pv*/,
1080 const InitialPrecomputedVector &piv,
1081 const unsigned int i,
1082 const state_type &U_i) const -> flux_contribution_type
1083 {
1084 const auto Z_i = piv.template get_tensor<Number>(i)[0];
1085 return {U_i, Z_i};
1086 }
1087
1088
1089 template <int dim, typename Number>
1090 DEAL_II_ALWAYS_INLINE inline auto
1092 const PrecomputedVector & /*pv*/,
1093 const InitialPrecomputedVector &piv,
1094 const unsigned int *js,
1095 const state_type &U_j) const -> flux_contribution_type
1096 {
1097 const auto Z_j = piv.template get_tensor<Number>(js)[0];
1098 return {U_j, Z_j};
1099 }
1100
1101
1102 template <int dim, typename Number>
1103 DEAL_II_ALWAYS_INLINE inline auto
1105 const flux_contribution_type &flux_i,
1106 const flux_contribution_type &flux_j,
1107 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1108 {
1109 const auto &[U_i, Z_i] = flux_i;
1110 const auto &[U_star_ij, U_star_ji] = equilibrated_states(flux_i, flux_j);
1111
1112 const auto H_i = water_depth(U_i);
1113 const auto H_star_ij = water_depth(U_star_ij);
1114 const auto H_star_ji = water_depth(U_star_ji);
1115
1116 const auto g_i = g(U_star_ij);
1117 const auto g_j = g(U_star_ji);
1118
1119 auto result = -add(g_i, g_j);
1120
1121 const auto factor =
1122 (ScalarNumber(0.5) * (H_star_ji * H_star_ji - H_star_ij * H_star_ij) +
1123 H_i * H_i) *
1124 gravity();
1125
1126 for (unsigned int i = 0; i < dim; ++i) {
1127 result[1 + i][i] -= factor;
1128 }
1129
1130 return contract(result, c_ij);
1131 }
1132
1133
1134 template <int dim, typename Number>
1135 DEAL_II_ALWAYS_INLINE inline auto
1137 const flux_contribution_type &flux_i,
1138 const flux_contribution_type &flux_j,
1139 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1140 {
1141 const auto &[U_i, Z_i] = flux_i;
1142 const auto &[U_j, Z_j] = flux_j;
1143
1144 const auto H_i = water_depth(U_i);
1145 const auto H_j = water_depth(U_j);
1146
1147 const auto g_i = g(U_i);
1148 const auto g_j = g(U_j);
1149
1150 auto result = -add(g_i, g_j);
1151
1152 const auto factor = gravity() * H_i * (H_j + Z_j - Z_i);
1153 for (unsigned int i = 0; i < dim; ++i) {
1154 result[1 + i][i] -= factor;
1155 }
1156
1157 return contract(result, c_ij);
1158 }
1159
1160
1161 template <int dim, typename Number>
1162 DEAL_II_ALWAYS_INLINE inline auto
1164 const flux_contribution_type &flux_i,
1165 const flux_contribution_type &flux_j,
1166 const dealii::Tensor<1, dim, Number> &c_ij,
1167 const Number &d_ij) const -> state_type
1168 {
1169 const auto &[U_i, Z_i] = flux_i;
1170 const auto &[U_j, Z_j] = flux_j;
1171 const auto U_star_ij = star_state(U_i, Z_i, Z_j);
1172
1173 const auto h_inverse = inverse_water_depth_sharp(U_i);
1174 const auto m = momentum(U_i);
1175 const auto factor = ScalarNumber(2.) * (d_ij + h_inverse * (m * c_ij));
1176
1177 return -factor * (U_star_ij - U_i);
1178 }
1179
1180
1181 template <int dim, typename Number>
1182 DEAL_II_ALWAYS_INLINE inline auto
1184 const state_type &U, const Number &h_star, const ScalarNumber tau) const
1185 -> state_type
1186 {
1187 state_type result;
1188
1189 const auto g = gravity();
1190 const auto n = manning_friction_coefficient();
1191
1192 const auto h_inverse = inverse_water_depth_mollified(U);
1193
1194 const auto m = momentum(U);
1195 const auto v_norm = (m * h_inverse).norm();
1196 const auto factor = ScalarNumber(2.) * g * n * n * v_norm;
1197
1198 const auto denominator = h_star + std::max(h_star, tau * factor);
1199 const auto denominator_inverse = ScalarNumber(1.) / denominator;
1200
1201 for (unsigned int d = 0; d < dim; ++d)
1202 result[d + 1] = -factor * denominator_inverse * m[d];
1203
1204 return result;
1205 }
1206
1207
1208 template <int dim, typename Number>
1209 DEAL_II_ALWAYS_INLINE inline auto
1211 const PrecomputedVector &pv,
1212 const unsigned int i,
1213 const state_type &U_i,
1214 const ScalarNumber tau) const -> state_type
1215 {
1216 const auto &[eta_m, h_star] =
1217 pv.template get_tensor<Number, precomputed_type>(i);
1218
1219 return manning_friction(U_i, h_star, tau);
1220 }
1221
1222
1223 template <int dim, typename Number>
1224 DEAL_II_ALWAYS_INLINE inline auto
1226 const PrecomputedVector &pv,
1227 const unsigned int *js,
1228 const state_type &U_j,
1229 const ScalarNumber tau) const -> state_type
1230 {
1231 const auto &[eta_m, h_star] =
1232 pv.template get_tensor<Number, precomputed_type>(js);
1233
1234 return manning_friction(U_j, h_star, tau);
1235 }
1236
1237
1238 template <int dim, typename Number>
1239 template <typename ST>
1240 DEAL_II_ALWAYS_INLINE inline auto
1242 -> state_type
1243 {
1244 using T = typename ST::value_type;
1245 static_assert(std::is_same_v<Number, T>, "template mismatch");
1246
1247 constexpr auto dim2 = ST::dimension - 1;
1248 static_assert(dim >= dim2,
1249 "the space dimension of the argument state must not be "
1250 "larger than the one of the target state");
1251
1252 state_type result;
1253 result[0] = state[0];
1254 for (unsigned int i = 1; i < dim2 + 1; ++i)
1255 result[i] = state[i];
1256
1257 return result;
1258 }
1259
1260 template <int dim, typename Number>
1261 template <typename ST>
1262 DEAL_II_ALWAYS_INLINE inline auto
1264 const ST &initial_state) const -> state_type
1265 {
1266 const auto primitive_state = expand_state(initial_state);
1267 return from_primitive_state(primitive_state);
1268 }
1269
1270
1271 template <int dim, typename Number>
1272 DEAL_II_ALWAYS_INLINE inline auto
1274 const state_type &primitive_state) const -> state_type
1275 {
1276 const auto &h = primitive_state[0];
1277
1278 auto state = primitive_state;
1279 /* Fix up momentum: */
1280 for (unsigned int i = 1; i < dim + 1; ++i)
1281 state[i] *= h;
1282
1283 return state;
1284 }
1285
1286
1287 template <int dim, typename Number>
1288 DEAL_II_ALWAYS_INLINE inline auto
1290 const state_type &state) const -> state_type
1291 {
1292 const auto h_inverse = inverse_water_depth_sharp(state);
1293
1294 auto primitive_state = state;
1295 /* Fix up velocity: */
1296 for (unsigned int i = 1; i < dim + 1; ++i)
1297 primitive_state[i] *= h_inverse;
1298
1299 return primitive_state;
1300 }
1301
1302
1303 template <int dim, typename Number>
1304 template <typename Lambda>
1305 DEAL_II_ALWAYS_INLINE inline auto
1307 const state_type &state, const Lambda &lambda) const -> state_type
1308 {
1309 auto result = state;
1310 auto M = lambda(momentum(state));
1311 for (unsigned int d = 0; d < dim; ++d)
1312 result[1 + d] = M[d];
1313 return result;
1314 }
1315
1316 } // namespace ShallowWater
1317} // namespace ryujin
typename get_value_type< Number >::type ScalarNumber
dealii::Tensor< 1, problem_dimension, Number > state_type
std::array< Number, n_precomputed_values > precomputed_type
Vectors::StateVector< ScalarNumber, problem_dimension, n_precomputed_values > StateVector
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
Number pressure(const state_type &U) 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
void precomputation_loop(unsigned int cycle, const DISPATCH &dispatch_check, const SPARSITY &sparsity_simd, StateVector &state_vector, unsigned int left, unsigned int right) 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
state_type nodal_source(const PrecomputedVector &pv, const unsigned int i, const state_type &U_i, const ScalarNumber tau) const
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 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_contribution_type flux_contribution(const PrecomputedVector &pv, const InitialPrecomputedVector &piv, const unsigned int i, const state_type &U_i) const
static constexpr unsigned int n_precomputation_cycles
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
HyperbolicSystem(const std::string &subsection="/HyperbolicSystem")
@ dirichlet_momentum
#define RYUJIN_OMP_FOR
Definition: openmp.h:70
T pow(const T x, const T b)
DEAL_II_ALWAYS_INLINE Number positive_part(const Number number)
Definition: simd.h:112
DEAL_II_ALWAYS_INLINE FT add(const FT &flux_left_ij, const FT &flux_right_ij)
DEAL_II_ALWAYS_INLINE dealii::Tensor< 1, problem_dim, T > contract(const FT &flux_ij, const TT &c_ij)