ryujin 2.5.0 revision c64172211cf21344cb9b9b0f3a1266aa6400d392
Loading...
Searching...
No Matches
hyperbolic_system.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0
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 <ryujin/base/compile_time_options.h>
12#include <ryujin/base/gpu.h>
13#include <ryujin/base/loop.h>
15#include <ryujin/base/simd.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 ShallowWater
30 {
31 template <int dim,
32 typename Number,
33 typename MemorySpace = dealii::MemorySpace::Host>
34 class HyperbolicSystemView;
35
46 {
47 public:
60
64 HyperbolicSystem(const std::string &subsection = "/HyperbolicSystem");
65
71 template <int dim,
72 typename Number = double,
73 typename MemorySpace = dealii::MemorySpace::Host>
75
83 template <int dim,
84 typename Number,
85 typename MemorySpace = dealii::MemorySpace::Host>
86 auto view() const
87 {
89 }
90
99 template <typename MemorySpace = dealii::MemorySpace::Host,
100 int dim,
101 typename ScalarNumber>
103 const OfflineData<dim, ScalarNumber> &offline_data,
104 StateVector<ScalarNumber> &state_vector,
105 const bool skip_constrained_dofs = true) const;
106
107 private:
112
113 Mirrored<Parameters> parameters_;
114
115 template <int, typename, typename>
117
119 }; /* HyperbolicSystem */
120
121
143 template <int dim, typename Number, typename MemorySpace>
145 {
146 public:
147 static_assert(
148 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
149 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
150 "Unexpected memory space");
151
156
161
165 static constexpr unsigned int problem_dimension = 1 + dim;
166
170 using state_type = dealii::Tensor<1, problem_dimension, Number>;
171
175 using flux_type =
176 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
177
183 std::tuple<state_type, Number, dealii::Tensor<1, dim, Number>>;
184
188 static constexpr unsigned int n_precomputed_values = 3;
189
193 using precomputed_type = std::array<Number, n_precomputed_values>;
194
198 static constexpr unsigned int n_initial_precomputed_values = 1;
199
204 std::array<Number, n_initial_precomputed_values>;
205
206 template <int n_comp>
209
215
222
224
228
233 HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
234 : parameters_(
235 hyperbolic_system.parameters_.template view<MemorySpace>())
236 {
237 }
238
240
244
245 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber gravity() const
246 {
247 return ScalarNumber(parameters_->gravity);
248 }
249
250 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
252 {
253 return ScalarNumber(parameters_->manning_friction_coefficient);
254 }
255
256 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
258 {
259 return ScalarNumber(parameters_->reference_water_depth);
260 }
261
262 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
264 {
265 return ScalarNumber(parameters_->dry_state_relaxation_small);
266 }
267
268 DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber
270 {
271 return ScalarNumber(parameters_->dry_state_relaxation_large);
272 }
273
275
279
284 static DEAL_II_HOST_DEVICE Number water_depth(const state_type &U);
285
292 DEAL_II_HOST_DEVICE Number
294
301 DEAL_II_HOST_DEVICE Number water_depth_sharp(const state_type &U) const;
302
309 DEAL_II_HOST_DEVICE Number
311
318 DEAL_II_HOST_DEVICE Number filter_dry_water_depth(const Number &h) const;
319
324 static DEAL_II_HOST_DEVICE dealii::Tensor<1, dim, Number>
325 momentum(const state_type &U);
326
334 DEAL_II_HOST_DEVICE Number kinetic_energy(const state_type &U) const;
335
343 DEAL_II_HOST_DEVICE Number pressure(const state_type &U) const;
344
352 DEAL_II_HOST_DEVICE Number speed_of_sound(const state_type &U) const;
353
358 DEAL_II_HOST_DEVICE Number
359 mathematical_entropy(const state_type &U) const;
360
365 DEAL_II_HOST_DEVICE state_type
367
373 DEAL_II_HOST_DEVICE bool is_admissible(const state_type &U) const;
374
376
380
386 template <int component>
388 const state_type &U,
389 const state_type &U_bar,
390 const dealii::Tensor<1, dim, Number> &normal) const;
391
395 template <typename Lambda>
396 DEAL_II_HOST_DEVICE_ALWAYS_INLINE state_type
397 apply_boundary_conditions(const dealii::types::boundary_id id,
398 const state_type &U,
399 const dealii::Tensor<1, dim, Number> &normal,
400 const Lambda &get_dirichlet_data) const;
401
403
407
417 DEAL_II_HOST_DEVICE flux_type f(const state_type &U) const;
418
428 DEAL_II_HOST_DEVICE flux_type g(const state_type &U) const;
429
436 DEAL_II_HOST_DEVICE state_type
437 star_state(const state_type &U,
438 const dealii::Tensor<1, dim, Number> &V,
439 const Number &Z_left,
440 const Number &Z_right) const;
441
447 DEAL_II_HOST_DEVICE std::array<state_type, 2>
449 const flux_contribution_type &) const;
450
471 DEAL_II_HOST_DEVICE
475 const unsigned int i,
476 const state_type &U_i) const;
477
478 DEAL_II_HOST_DEVICE
482 const unsigned int *js,
483 const state_type &U_j) const;
484
490 DEAL_II_HOST_DEVICE
493 const flux_contribution_type &flux_j,
494 const dealii::Tensor<1, dim, Number> &c_ij) const;
495
499 static constexpr bool have_high_order_flux = true;
500
506 DEAL_II_HOST_DEVICE
508 const flux_contribution_type &flux_i,
509 const flux_contribution_type &flux_j,
510 const dealii::Tensor<1, dim, Number> &c_ij) const;
511
517 DEAL_II_HOST_DEVICE
519 const flux_contribution_type &flux_j,
520 const dealii::Tensor<1, dim, Number> &c_ij,
521 const Number &d_ij) const;
522
524
528
530 static constexpr bool have_source_terms = true;
531
536 DEAL_II_HOST_DEVICE Number
537 manning_friction_factor(const state_type &U) const;
538
544 DEAL_II_HOST_DEVICE
546 const Number &h_star,
547 const Number &factor,
548 const ScalarNumber tau) const;
549
550 DEAL_II_HOST_DEVICE
552 const unsigned int i,
553 const state_type &U_i,
554 const ScalarNumber tau) const;
555
556 DEAL_II_HOST_DEVICE
558 const unsigned int *js,
559 const state_type &U_j,
560 const ScalarNumber tau) const;
561
563
567
578 template <typename ST>
579 DEAL_II_HOST_DEVICE state_type expand_state(const ST &state) const;
580
592 template <typename ST>
593 DEAL_II_HOST_DEVICE state_type
594 from_initial_state(const ST &initial_state) const;
595
600 DEAL_II_HOST_DEVICE
601 state_type from_primitive_state(const state_type &primitive_state) const;
602
606 DEAL_II_HOST_DEVICE
608
614 template <typename Lambda>
616 const state_type &state, const Lambda &lambda) const;
617
618 private:
620
624
625 const HyperbolicSystem::Parameters *const parameters_;
626
628 }; /* HyperbolicSystemView */
629
630
631 /*
632 * -------------------------------------------------------------------------
633 * Inline definitions
634 * -------------------------------------------------------------------------
635 */
636
637
638 inline HyperbolicSystem::HyperbolicSystem(const std::string &subsection)
639 : Interface::HyperbolicSystem(
640 "Shallow water equations",
641 {{{"h", "m"}, {"h", "m_1", "m_2"}, {"h", "m_1", "m_2", "m_3"}}},
642 {{{"h", "v"}, {"h", "v_1", "v_2"}, {"h", "v_1", "v_2", "v_3"}}},
643 {{{"eta_m", "h_star", "friction_factor"},
644 {"eta_m", "h_star", "friction_factor"},
645 {"eta_m", "h_star", "friction_factor"}}},
646 {{{"bathymetry"}, {"bathymetry"}, {"bathymetry"}}},
647 subsection)
648 , parameters_("shallow_water_hyperbolic_system_parameters",
650 {
651 /* reference remains valid due to implicit_transfers_host_resident */
652 auto &parameters = *parameters_.view();
653
654 parameters.gravity = 9.81;
655 add_parameter(
656 "gravity", parameters.gravity, "Gravitational constant [m/s^2]");
657
658 parameters.manning_friction_coefficient = 0.;
659 add_parameter("manning friction coefficient",
660 parameters.manning_friction_coefficient,
661 "Roughness coefficient for friction source");
662
663 parameters.reference_water_depth = 1.;
664 add_parameter("reference water depth",
665 parameters.reference_water_depth,
666 "Problem specific water depth reference");
667
668 parameters.dry_state_relaxation_small = 1.e2;
669 add_parameter("dry state relaxation small",
670 parameters.dry_state_relaxation_small,
671 "Problem specific dry-state relaxation parameter");
672
673 parameters.dry_state_relaxation_large = 1.e4;
674 add_parameter("dry state relaxation large",
675 parameters.dry_state_relaxation_large,
676 "Problem specific dry-state relaxation parameter");
677
678 /* invalidates view on default memory space */
679 ParameterAcceptor::parse_parameters_call_back.connect(
680 [this] { parameters_.view(); });
681 }
682
683
684 template <typename MemorySpace, int dim, typename ScalarNumber>
686 const OfflineData<dim, ScalarNumber> &offline_data,
687 StateVector<ScalarNumber> &state_vector,
688 const bool skip_constrained_dofs) const
689 {
690 const unsigned int n_internal = offline_data.n_locally_internal();
691 const unsigned int n_owned = offline_data.n_locally_owned();
692
694
695 const auto sparsity_simd_view =
696 offline_data.sparsity_pattern_simd().template view<MemorySpace>();
697
698 const auto U_view =
699 std::as_const(state_vector)
700 .state
701 .template view<ScalarView::problem_dimension, MemorySpace>();
702 const auto precomputed_view =
703 state_vector.precomputed
704 .template view<ScalarView::n_precomputed_values, MemorySpace>();
705
706 const auto hyperbolic_system_views =
707 make_select_view<dim, ScalarNumber, MemorySpace>(*this);
708
709 const auto body = [=](auto sentinel, unsigned int i) {
710 using T = decltype(sentinel);
712 using precomputed_type = typename View::precomputed_type;
713
714 const unsigned int row_length = sparsity_simd_view.row_length(i);
715 if (skip_constrained_dofs && row_length == 1)
716 return;
717
718 const auto view = hyperbolic_system_views.template view<T>();
719
720 const auto U_i = U_view.template read_tensor<T>(i);
721 const auto eta_m = view.mathematical_entropy(U_i);
722 const auto h_sharp = view.water_depth_sharp(U_i);
723 const auto h_star = ryujin::pow(h_sharp, ScalarNumber(4. / 3.));
724 const auto factor = view.manning_friction_factor(U_i);
725
726 const precomputed_type prec_i{eta_m, h_star, factor};
727 precomputed_view.template write_tensor<T>(prec_i, i);
728 };
729
730 loop<MemorySpace, ScalarNumber>(
731 "hyperbolic_kernel_01b", body, 0, n_internal, n_owned);
732 }
733
734
735 template <int dim, typename Number, typename MemorySpace>
736 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
742
743
744 template <int dim, typename Number, typename MemorySpace>
745 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
748 {
749 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
750
751 const Number h_cutoff_mollified =
752 reference_water_depth() * dry_state_relaxation_large() * Number(eps);
753
754 const Number h = water_depth(U);
755 const Number h_pos = positive_part(water_depth(U));
756 const Number h_max = std::max(h, h_cutoff_mollified);
757 const Number denom = h * h + h_max * h_max;
758 return ScalarNumber(2.) * h_pos / denom;
759 }
760
761
762 template <int dim, typename Number, typename MemorySpace>
763 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
765 const state_type &U) const
766 {
767 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
768
769 const Number h_cutoff_small =
770 reference_water_depth() * dry_state_relaxation_small() * Number(eps);
771
772 const Number h = water_depth(U);
773 const Number h_max = std::max(h, h_cutoff_small);
774 return h_max;
775 }
776
777
778 template <int dim, typename Number, typename MemorySpace>
779 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
781 const state_type &U) const
782 {
783 return ScalarNumber(1.) / water_depth_sharp(U);
784 }
785
786
787 template <int dim, typename Number, typename MemorySpace>
788 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
790 const Number &h) const
791 {
793 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
794
795 const Number h_cutoff_large =
796 reference_water_depth() * dry_state_relaxation_large() * Number(eps);
797
798 return ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
799 std::abs(h), h_cutoff_large, Number(0.), h);
800 }
801
802
803 template <int dim, typename Number, typename MemorySpace>
804 DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor<1, dim, Number>
806 const state_type &U)
807 {
808 dealii::Tensor<1, dim, Number> result;
809
810 for (unsigned int i = 0; i < dim; ++i)
811 result[i] = U[1 + i];
812 return result;
813 }
814
815
816 template <int dim, typename Number, typename MemorySpace>
817 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
819 const state_type &U) const
820 {
821 const auto h = water_depth(U);
822 const auto vel = momentum(U) * inverse_water_depth_sharp(U);
823
824 /* KE = 1/2 h |v|^2 */
825 return ScalarNumber(0.5) * h * vel.norm_square();
826 }
827
828
829 template <int dim, typename Number, typename MemorySpace>
830 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
832 const state_type &U) const
833 {
834 const Number h_sqd = U[0] * U[0];
835
836 /* p = 1/2 g h^2 */
837 return ScalarNumber(0.5) * gravity() * h_sqd;
838 }
839
840
841 template <int dim, typename Number, typename MemorySpace>
842 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
844 const state_type &U) const
845 {
846 /* c^2 = g * h */
847 return std::sqrt(gravity() * U[0]);
848 }
849
850
851 template <int dim, typename Number, typename MemorySpace>
852 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
854 const state_type &U) const
855 {
856 const auto p = pressure(U);
857 const auto k_e = kinetic_energy(U);
858 return p + k_e;
859 }
860
861
862 template <int dim, typename Number, typename MemorySpace>
863 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
866 {
867 /*
868 * With
869 * eta = 1/2 g h^2 + 1/2 |m|^2 / h
870 *
871 * we get
872 *
873 * eta' = (g h - 1/2 |vel|^2, vel)
874 *
875 * where vel = m / h
876 */
877
878 state_type result;
879
880 const Number &h = U[0];
881 const auto vel = momentum(U) * inverse_water_depth_sharp(U);
882
883 // water depth component
884 result[0] = gravity() * h - ScalarNumber(0.5) * vel.norm_square();
885
886 // momentum components
887 for (unsigned int i = 0; i < dim; ++i) {
888 result[1 + i] = vel[i];
889 }
890
891 return result;
892 }
893
894
895 template <int dim, typename Number, typename MemorySpace>
896 DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool
898 const state_type &U) const
899 {
900 const auto h = filter_dry_water_depth(water_depth(U));
901
902 constexpr auto gte = dealii::SIMDComparison::greater_than_or_equal;
903 const auto test = ryujin::compare_and_apply_mask<gte>(
904 h, Number(0.), Number(0.), Number(-1.));
905
906#ifdef DEBUG_OUTPUT
907 if (!(test == Number(0.))) {
908 std::cout << std::fixed << std::setprecision(16);
909 std::cout << "Bounds violation: Negative state [h] detected!\n";
910 std::cout << "\t\th: " << h << "\n" << std::endl;
911 __builtin_trap();
912 }
913#endif
914
915 return (test == Number(0.));
916 }
917
918
919 template <int dim, typename Number, typename MemorySpace>
920 template <int component>
921 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
924 const state_type &U,
925 const state_type &U_bar,
926 const dealii::Tensor<1, dim, Number> &normal) const -> state_type
927 {
928 /* Note that U_bar are the dirichlet values that are prescribed */
929 static_assert(component == 1 || component == 2,
930 "component has to be 1 or 2");
931
933
934 const auto m = momentum(U);
935 const auto a = speed_of_sound(U);
936 const auto vn = m * normal * inverse_water_depth_sharp(U);
937
938 const auto m_bar = momentum(U_bar);
939 const auto a_bar = speed_of_sound(U_bar);
940 const auto vn_bar = m_bar * normal * inverse_water_depth_sharp(U_bar);
941
942 /* First Riemann characteristic: v * n - 2 * a */
943
944 const auto R_1 = component == 1 ? vn_bar - ScalarNumber(2.) * a_bar
945 : vn - ScalarNumber(2.) * a;
946
947 /* Second Riemann characteristic: v * n + 2 * a */
948
949 const auto R_2 = component == 2 ? vn_bar + ScalarNumber(2.) * a_bar
950 : vn + ScalarNumber(2.) * a;
951
952 const auto vperp = m * inverse_water_depth_sharp(U) - vn * normal;
953
954 const auto vn_new = ScalarNumber(0.5) * (R_1 + R_2);
955
956 const auto h_new =
957 ryujin::fixed_power<2>((R_2 - R_1) / ScalarNumber(4.)) / gravity();
958
959 state_type U_new;
960 U_new[0] = h_new;
961 for (unsigned int d = 0; d < dim; ++d) {
962 U_new[1 + d] = h_new * (vn_new * normal + vperp)[d];
963 }
964
965 return U_new;
966 }
967
968
969 template <int dim, typename Number, typename MemorySpace>
970 template <typename Lambda>
971 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
973 const dealii::types::boundary_id id,
974 const state_type &U,
975 const dealii::Tensor<1, dim, Number> &normal,
976 const Lambda &get_dirichlet_data) const -> state_type
977 {
978 state_type result = U;
979
980 if (id == Boundary::dirichlet) {
981 result = get_dirichlet_data();
982
983 } else if (id == Boundary::dirichlet_momentum) {
984 /* Only enforce Dirichlet conditions on the momentum: */
985 auto m_dirichlet = momentum(get_dirichlet_data());
986 for (unsigned int k = 0; k < dim; ++k)
987 result[k + 1] = m_dirichlet[k];
988
989 } else if (id == Boundary::dirichlet_velocity) {
990 /* Only enforce Dirichlet conditions on the velocity: */
991 const auto U_dirichlet = get_dirichlet_data();
992 const auto h_inv_sharp_dirichlet =
993 inverse_water_depth_sharp(U_dirichlet);
994 const auto v_dirichlet = momentum(U_dirichlet) * h_inv_sharp_dirichlet;
995 const auto h = water_depth_sharp(result);
996 for (unsigned int k = 0; k < dim; ++k)
997 result[k + 1] = h * v_dirichlet[k];
998
999 } else if (id == Boundary::slip) {
1000 auto m = momentum(U);
1001 m -= 1. * (m * normal) * normal;
1002 for (unsigned int k = 0; k < dim; ++k)
1003 result[k + 1] = m[k];
1004
1005 } else if (id == Boundary::no_slip) {
1006 for (unsigned int k = 0; k < dim; ++k)
1007 result[k + 1] = Number(0.);
1008
1009 } else if (id == Boundary::dynamic) {
1010 /*
1011 * On dynamic boundary conditions, we distinguish four cases:
1012 *
1013 * - supersonic inflow: prescribe full state
1014 * - subsonic inflow:
1015 * decompose into Riemann invariants and leave R_2
1016 * characteristic untouched.
1017 * - supersonic outflow: do nothing
1018 * - subsonic outflow:
1019 * decompose into Riemann invariants and prescribe incoming
1020 * R_1 characteristic.
1021 */
1022 const auto m = momentum(U);
1023 const auto h_inverse = inverse_water_depth_sharp(U);
1024 const auto a = speed_of_sound(U);
1025 const auto vn = m * normal * h_inverse;
1026
1027 /* Supersonic inflow: */
1028 if (vn < -a) {
1029 result = get_dirichlet_data();
1030 }
1031
1032 /* Subsonic inflow: */
1033 if (vn >= -a && vn <= 0.) {
1034 const auto U_dirichlet = get_dirichlet_data();
1035 result = prescribe_riemann_characteristic<2>(U_dirichlet, U, normal);
1036 }
1037
1038 /* Subsonic outflow: */
1039 if (vn > 0. && vn <= a) {
1040 const auto U_dirichlet = get_dirichlet_data();
1041 result = prescribe_riemann_characteristic<1>(U, U_dirichlet, normal);
1042 }
1043
1044 /* Supersonic outflow: do nothing, i.e., keep U as is */
1045
1046 } else {
1047 Assert(false, dealii::ExcNotImplemented());
1048 }
1049
1050 return result;
1051 }
1052
1053
1054 template <int dim, typename Number, typename MemorySpace>
1055 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1057 -> flux_type
1058 {
1059 const auto h_inverse = inverse_water_depth_sharp(U);
1060 const auto m = momentum(U);
1061 const auto p = pressure(U);
1062
1063 flux_type result;
1064
1065 result[0] = (m * h_inverse) * U[0];
1066 for (unsigned int i = 0; i < dim; ++i) {
1067 result[1 + i] = (m * h_inverse) * m[i];
1068 result[1 + i][i] += p;
1069 }
1070 return result;
1071 }
1072
1073
1074 template <int dim, typename Number, typename MemorySpace>
1075 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1077 -> flux_type
1078 {
1079 const auto h_inverse = inverse_water_depth_sharp(U);
1080 const auto m = momentum(U);
1081
1082 flux_type result;
1083
1084 result[0] = (m * h_inverse) * U[0];
1085 for (unsigned int i = 0; i < dim; ++i) {
1086 result[1 + i] = (m * h_inverse) * m[i];
1087 }
1088 return result;
1089 }
1090
1091
1092 template <int dim, typename Number, typename MemorySpace>
1093 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1095 const state_type &U,
1096 const dealii::Tensor<1, dim, Number> &V,
1097 const Number &Z_left,
1098 const Number &Z_right) const -> state_type
1099 {
1100 const Number Z_max = std::max(Z_left, Z_right);
1101 const Number h = water_depth(U);
1102 const Number H_star = std::max(Number(0.), h + Z_left - Z_max);
1103
1104 state_type result;
1105 result[0] = H_star;
1106 for (unsigned int d = 0; d < dim; ++d)
1107 result[1 + d] = H_star * V[d];
1108 return result;
1109 }
1110
1111
1112 template <int dim, typename Number, typename MemorySpace>
1113 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1115 const flux_contribution_type &flux_i,
1116 const flux_contribution_type &flux_j) const -> std::array<state_type, 2>
1117 {
1118 const auto &[U_i, Z_i, V_i] = flux_i;
1119 const auto &[U_j, Z_j, V_j] = flux_j;
1120
1121 const auto U_star_ij = star_state(U_i, V_i, Z_i, Z_j);
1122 const auto U_star_ji = star_state(U_j, V_j, Z_j, Z_i);
1123
1124 return {U_star_ij, U_star_ji};
1125 }
1126
1127
1128 template <int dim, typename Number, typename MemorySpace>
1129 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1131 const PrecomputedVectorView & /*pv*/,
1133 const unsigned int i,
1134 const state_type &U_i) const -> flux_contribution_type
1135 {
1136 const auto Z_i = piv.template read_tensor<Number>(i)[0];
1137 const auto V_i = momentum(U_i) * inverse_water_depth_mollified(U_i);
1138 return {U_i, Z_i, V_i};
1139 }
1140
1141
1142 template <int dim, typename Number, typename MemorySpace>
1143 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1145 const PrecomputedVectorView & /*pv*/,
1147 const unsigned int *js,
1148 const state_type &U_j) const -> flux_contribution_type
1149 {
1150 const auto Z_j = piv.template read_tensor<Number>(js)[0];
1151 const auto V_j = momentum(U_j) * inverse_water_depth_mollified(U_j);
1152 return {U_j, Z_j, V_j};
1153 }
1154
1155
1156 template <int dim, typename Number, typename MemorySpace>
1157 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1159 const flux_contribution_type &flux_i,
1160 const flux_contribution_type &flux_j,
1161 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1162 {
1163 const auto &[U_i, Z_i, V_i] = flux_i;
1164 const auto &[U_j, Z_j, V_j] = flux_j;
1165 const auto &[U_star_ij, U_star_ji] = equilibrated_states(flux_i, flux_j);
1166
1167 const auto H_i = water_depth(U_i);
1168 const auto H_star_ij = water_depth(U_star_ij);
1169 const auto H_star_ji = water_depth(U_star_ji);
1170
1171 const auto V_i_c_ij = V_i * c_ij;
1172 const auto V_j_c_ij = V_j * c_ij;
1173
1174 state_type result = -(U_star_ij * V_i_c_ij + U_star_ji * V_j_c_ij);
1175
1176 const auto factor =
1177 (ScalarNumber(0.5) * (H_star_ji * H_star_ji - H_star_ij * H_star_ij) +
1178 H_i * H_i) *
1179 gravity();
1180
1181 for (unsigned int d = 0; d < dim; ++d)
1182 result[1 + d] -= factor * c_ij[d];
1183
1184 return result;
1185 }
1186
1187
1188 template <int dim, typename Number, typename MemorySpace>
1189 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1191 const flux_contribution_type &flux_i,
1192 const flux_contribution_type &flux_j,
1193 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1194 {
1195 const auto &[U_i, Z_i, V_i] = flux_i;
1196 const auto &[U_j, Z_j, V_j] = flux_j;
1197
1198 const auto H_i = water_depth(U_i);
1199 const auto H_j = water_depth(U_j);
1200
1201 state_type result = -(U_i * (V_i * c_ij) + U_j * (V_j * c_ij));
1202
1203 const auto factor = gravity() * H_i * (H_j + Z_j - Z_i);
1204 for (unsigned int d = 0; d < dim; ++d)
1205 result[1 + d] -= factor * c_ij[d];
1206
1207 return result;
1208 }
1209
1210
1211 template <int dim, typename Number, typename MemorySpace>
1212 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1214 const flux_contribution_type &flux_i,
1215 const flux_contribution_type &flux_j,
1216 const dealii::Tensor<1, dim, Number> &c_ij,
1217 const Number &d_ij) const -> state_type
1218 {
1219 const auto &[U_i, Z_i, V_i] = flux_i;
1220 const auto &[U_j, Z_j, V_j] = flux_j;
1221 const auto U_star_ij = star_state(U_i, V_i, Z_i, Z_j);
1222
1223 const auto factor = ScalarNumber(2.) * (d_ij + V_i * c_ij);
1224
1225 return -factor * (U_star_ij - U_i);
1226 }
1227
1228
1229 template <int dim, typename Number, typename MemorySpace>
1230 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1232 const state_type &U) const -> Number
1233 {
1234 const auto g = gravity();
1235 const auto n = manning_friction_coefficient();
1236
1237 const auto v_norm =
1238 (momentum(U) * inverse_water_depth_mollified(U)).norm();
1239 return ScalarNumber(2.) * g * n * n * v_norm;
1240 }
1241
1242
1243 template <int dim, typename Number, typename MemorySpace>
1244 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1246 const state_type &U,
1247 const Number &h_star,
1248 const Number &factor,
1249 const ScalarNumber tau) const -> state_type
1250 {
1251 state_type result;
1252
1253 const auto m = momentum(U);
1254
1255 const auto denominator = h_star + std::max(h_star, tau * factor);
1256 const auto denominator_inverse = ScalarNumber(1.) / denominator;
1257
1258 for (unsigned int d = 0; d < dim; ++d)
1259 result[d + 1] = -factor * denominator_inverse * m[d];
1260
1261 return result;
1262 }
1263
1264
1265 template <int dim, typename Number, typename MemorySpace>
1266 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1268 const PrecomputedVectorView &pv,
1269 const unsigned int i,
1270 const state_type &U_i,
1271 const ScalarNumber tau) const -> state_type
1272 {
1273 const auto &[eta_m, h_star, factor] =
1274 pv.template read_tensor<Number, precomputed_type>(i);
1275
1276 return manning_friction(U_i, h_star, factor, tau);
1277 }
1278
1279
1280 template <int dim, typename Number, typename MemorySpace>
1281 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1283 const PrecomputedVectorView &pv,
1284 const unsigned int *js,
1285 const state_type &U_j,
1286 const ScalarNumber tau) const -> state_type
1287 {
1288 const auto &[eta_m, h_star, factor] =
1289 pv.template read_tensor<Number, precomputed_type>(js);
1290
1291 return manning_friction(U_j, h_star, factor, tau);
1292 }
1293
1294
1295 template <int dim, typename Number, typename MemorySpace>
1296 template <typename ST>
1297 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1299 const ST &state) const -> state_type
1300 {
1301 using T = typename ST::value_type;
1302 static_assert(std::is_same_v<Number, T>, "template mismatch");
1303
1304 constexpr auto dim2 = ST::dimension - 1;
1305 static_assert(dim >= dim2,
1306 "the space dimension of the argument state must not be "
1307 "larger than the one of the target state");
1308
1309 state_type result;
1310 result[0] = state[0];
1311 for (unsigned int i = 1; i < dim2 + 1; ++i)
1312 result[i] = state[i];
1313
1314 return result;
1315 }
1316
1317 template <int dim, typename Number, typename MemorySpace>
1318 template <typename ST>
1319 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1321 const ST &initial_state) const -> state_type
1322 {
1323 const auto primitive_state = expand_state(initial_state);
1324 return from_primitive_state(primitive_state);
1325 }
1326
1327
1328 template <int dim, typename Number, typename MemorySpace>
1329 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1331 const state_type &primitive_state) const -> state_type
1332 {
1333 const auto &h = primitive_state[0];
1334
1335 auto state = primitive_state;
1336 /* Fix up momentum: */
1337 for (unsigned int i = 1; i < dim + 1; ++i)
1338 state[i] *= h;
1339
1340 return state;
1341 }
1342
1343
1344 template <int dim, typename Number, typename MemorySpace>
1345 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1347 const state_type &state) const -> state_type
1348 {
1349 const auto h_inverse = inverse_water_depth_sharp(state);
1350
1351 auto primitive_state = state;
1352 /* Fix up velocity: */
1353 for (unsigned int i = 1; i < dim + 1; ++i)
1354 primitive_state[i] *= h_inverse;
1355
1356 return primitive_state;
1357 }
1358
1359
1360 template <int dim, typename Number, typename MemorySpace>
1361 template <typename Lambda>
1362 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1364 const state_type &state, const Lambda &lambda) const -> state_type
1365 {
1366 auto result = state;
1367 auto M = lambda(momentum(state));
1368 for (unsigned int d = 0; d < dim; ++d)
1369 result[1 + d] = M[d];
1370 return result;
1371 }
1372 } // namespace ShallowWater
1373} // namespace ryujin
dealii::Tensor< 1, problem_dimension, Number > state_type
typename get_value_type< Number >::type ScalarNumber
static constexpr unsigned int problem_dimension
DEAL_II_HOST_DEVICE state_type to_primitive_state(const state_type &state) const
DEAL_II_HOST_DEVICE Number filter_dry_water_depth(const Number &h) 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 Number pressure(const state_type &U) const
typename get_value_type< Number >::type ScalarNumber
DEAL_II_HOST_DEVICE Number inverse_water_depth_mollified(const state_type &U) const
dealii::Tensor< 1, problem_dimension, Number > state_type
DEAL_II_HOST_DEVICE state_type star_state(const state_type &U, const dealii::Tensor< 1, dim, Number > &V, const Number &Z_left, const Number &Z_right) const
DEAL_II_HOST_DEVICE state_type manning_friction(const state_type &U, const Number &h_star, const Number &factor, const ScalarNumber tau) const
DEAL_II_HOST_DEVICE Number kinetic_energy(const state_type &U) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber dry_state_relaxation_large() const
std::tuple< state_type, Number, dealii::Tensor< 1, dim, Number > > flux_contribution_type
DEAL_II_HOST_DEVICE state_type apply_galilei_transform(const state_type &state, const Lambda &lambda) const
DEAL_II_HOST_DEVICE Number manning_friction_factor(const state_type &U) const
DEAL_II_HOST_DEVICE flux_type g(const state_type &U) 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 mathematical_entropy_derivative(const state_type &U) const
DEAL_II_HOST_DEVICE flux_contribution_type flux_contribution(const PrecomputedVectorView &pv, const InitialPrecomputedVectorView &piv, const unsigned int i, const state_type &U_i) const
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 Number mathematical_entropy(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
DEAL_II_HOST_DEVICE std::array< state_type, 2 > equilibrated_states(const flux_contribution_type &, const flux_contribution_type &) const
static DEAL_II_HOST_DEVICE dealii::Tensor< 1, dim, Number > momentum(const state_type &U)
DEAL_II_HOST_DEVICE Number water_depth_sharp(const state_type &U) const
dealii::Tensor< 1, problem_dimension, dealii::Tensor< 1, dim, Number > > flux_type
DEAL_II_HOST_DEVICE state_type from_primitive_state(const state_type &primitive_state) const
DEAL_II_HOST_DEVICE state_type high_order_flux_divergence(const flux_contribution_type &flux_i, const flux_contribution_type &flux_j, const dealii::Tensor< 1, dim, Number > &c_ij) const
DEAL_II_HOST_DEVICE 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
DEAL_II_HOST_DEVICE Number inverse_water_depth_sharp(const state_type &U) const
DEAL_II_HOST_DEVICE bool is_admissible(const state_type &U) const
DEAL_II_HOST_DEVICE Number speed_of_sound(const state_type &U) const
static constexpr unsigned int n_initial_precomputed_values
std::array< Number, n_initial_precomputed_values > initial_precomputed_type
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber gravity() const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber dry_state_relaxation_small() const
DEAL_II_HOST_DEVICE flux_type f(const state_type &U) const
std::array< Number, n_precomputed_values > precomputed_type
DEAL_II_HOST_DEVICE state_type from_initial_state(const ST &initial_state) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber manning_friction_coefficient() const
HyperbolicSystemView(const HyperbolicSystem &hyperbolic_system)
static constexpr unsigned int n_precomputed_values
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber reference_water_depth() const
DEAL_II_HOST_DEVICE state_type expand_state(const ST &state) const
static DEAL_II_HOST_DEVICE Number water_depth(const state_type &U)
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
@ dirichlet_momentum
@ dirichlet_velocity
DEAL_II_HOST_DEVICE T pow(const T x, const T b)
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number positive_part(const Number number)
Definition simd.h:134
MultiComponentVector< Number > precomputed