ryujin 2.1.1 revision b04fb4aba7bd97ddfa5994a6b4b6e8586eb15db2
Loading...
Searching...
No Matches
hyperbolic_system.h
Go to the documentation of this file.
1//
2// SPDX-License-Identifier: Apache-2.0
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 <ryujin/interface/hyperbolic_system.h>
13
14#include <convenience_macros.h>
15#include <discretization.h>
16#include <gpu.h>
17#include <loop.h>
19#include <patterns_conversion.h>
20#include <simd.h>
21#include <state_vector.h>
22
23#include <deal.II/base/memory_space.h>
24#include <deal.II/base/parameter_acceptor.h>
25#include <deal.II/base/tensor.h>
26
27#include <array>
28
29namespace ryujin
30{
31 namespace ShallowWater
32 {
33 template <int dim,
34 typename Number,
35 typename MemorySpace = dealii::MemorySpace::Host>
36 class HyperbolicSystemView;
37
47 class HyperbolicSystem final : public Interface::HyperbolicSystem
48 {
49 public:
62
66 HyperbolicSystem(const std::string &subsection = "/HyperbolicSystem");
67
73 template <int dim,
74 typename Number = double,
75 typename MemorySpace = dealii::MemorySpace::Host>
77
85 template <int dim,
86 typename Number,
87 typename MemorySpace = dealii::MemorySpace::Host>
88 auto view() const
89 {
91 }
92
101 template <typename MemorySpace = dealii::MemorySpace::Host,
102 int dim,
103 typename ScalarNumber>
105 const OfflineData<dim, ScalarNumber> &offline_data,
106 StateVector<ScalarNumber> &state_vector,
107 const bool skip_constrained_dofs = true) const;
108
109 private:
114
115 Mirrored<Parameters> parameters_;
116
117 template <int, typename, typename>
119
121 }; /* HyperbolicSystem */
122
123
145 template <int dim, typename Number, typename MemorySpace>
147 {
148 public:
149 static_assert(
150 std::is_same_v<MemorySpace, dealii::MemorySpace::Host> ||
151 std::is_same_v<MemorySpace, dealii::MemorySpace::Default>,
152 "Unexpected memory space");
153
158
163
167 static constexpr unsigned int problem_dimension = 1 + dim;
168
172 using state_type = dealii::Tensor<1, problem_dimension, Number>;
173
177 using flux_type =
178 dealii::Tensor<1, problem_dimension, dealii::Tensor<1, dim, Number>>;
179
183 using flux_contribution_type = std::tuple<state_type, Number>;
184
188 static constexpr unsigned int n_precomputed_values = 2;
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
435 DEAL_II_HOST_DEVICE state_type star_state(const state_type &U,
436 const Number &Z_left,
437 const Number &Z_right) const;
438
444 DEAL_II_HOST_DEVICE std::array<state_type, 2>
446 const flux_contribution_type &) const;
447
468 DEAL_II_HOST_DEVICE
472 const unsigned int i,
473 const state_type &U_i) const;
474
475 DEAL_II_HOST_DEVICE
479 const unsigned int *js,
480 const state_type &U_j) const;
481
487 DEAL_II_HOST_DEVICE
490 const flux_contribution_type &flux_j,
491 const dealii::Tensor<1, dim, Number> &c_ij) const;
492
496 static constexpr bool have_high_order_flux = true;
497
503 DEAL_II_HOST_DEVICE
505 const flux_contribution_type &flux_i,
506 const flux_contribution_type &flux_j,
507 const dealii::Tensor<1, dim, Number> &c_ij) const;
508
514 DEAL_II_HOST_DEVICE
516 const flux_contribution_type &flux_j,
517 const dealii::Tensor<1, dim, Number> &c_ij,
518 const Number &d_ij) const;
519
521
525
527 static constexpr bool have_source_terms = true;
528
534 DEAL_II_HOST_DEVICE
536 const Number &h_star,
537 const ScalarNumber tau) const;
538
539 DEAL_II_HOST_DEVICE
541 const unsigned int i,
542 const state_type &U_i,
543 const ScalarNumber tau) const;
544
545 DEAL_II_HOST_DEVICE
547 const unsigned int *js,
548 const state_type &U_j,
549 const ScalarNumber tau) const;
550
552
556
567 template <typename ST>
568 DEAL_II_HOST_DEVICE state_type expand_state(const ST &state) const;
569
581 template <typename ST>
582 DEAL_II_HOST_DEVICE state_type
583 from_initial_state(const ST &initial_state) const;
584
589 DEAL_II_HOST_DEVICE
590 state_type from_primitive_state(const state_type &primitive_state) const;
591
595 DEAL_II_HOST_DEVICE
596 state_type to_primitive_state(const state_type &state) const;
597
603 template <typename Lambda>
605 const state_type &state, const Lambda &lambda) const;
606
607 private:
609
613
614 const HyperbolicSystem::Parameters *const parameters_;
615
617 }; /* HyperbolicSystemView */
618
619
620 /*
621 * -------------------------------------------------------------------------
622 * Inline definitions
623 * -------------------------------------------------------------------------
624 */
625
626
627 inline HyperbolicSystem::HyperbolicSystem(const std::string &subsection)
628 : Interface::HyperbolicSystem(
629 "Shallow water equations",
630 {{{"h", "m"}, {"h", "m_1", "m_2"}, {"h", "m_1", "m_2", "m_3"}}},
631 {{{"h", "v"}, {"h", "v_1", "v_2"}, {"h", "v_1", "v_2", "v_3"}}},
632 {{{"eta_m", "h_star"}, {"eta_m", "h_star"}, {"eta_m", "h_star"}}},
633 {{{"bathymetry"}, {"bathymetry"}, {"bathymetry"}}},
634 subsection)
635 , parameters_("shallow_water_hyperbolic_system_parameters",
637 {
638 /* reference remains valid due to implicit_transfers_host_resident */
639 auto &parameters = *parameters_.view();
640
641 parameters.gravity = 9.81;
642 add_parameter(
643 "gravity", parameters.gravity, "Gravitational constant [m/s^2]");
644
645 parameters.manning_friction_coefficient = 0.;
646 add_parameter("manning friction coefficient",
647 parameters.manning_friction_coefficient,
648 "Roughness coefficient for friction source");
649
650 parameters.reference_water_depth = 1.;
651 add_parameter("reference water depth",
652 parameters.reference_water_depth,
653 "Problem specific water depth reference");
654
655 parameters.dry_state_relaxation_small = 1.e2;
656 add_parameter("dry state relaxation small",
657 parameters.dry_state_relaxation_small,
658 "Problem specific dry-state relaxation parameter");
659
660 parameters.dry_state_relaxation_large = 1.e4;
661 add_parameter("dry state relaxation large",
662 parameters.dry_state_relaxation_large,
663 "Problem specific dry-state relaxation parameter");
664
665 /* invalidates view on default memory space */
666 ParameterAcceptor::parse_parameters_call_back.connect(
667 [this] { parameters_.view(); });
668 }
669
670
671 template <typename MemorySpace, int dim, typename ScalarNumber>
673 const OfflineData<dim, ScalarNumber> &offline_data,
674 StateVector<ScalarNumber> &state_vector,
675 const bool skip_constrained_dofs) const
676 {
677 const unsigned int n_internal = offline_data.n_locally_internal();
678 const unsigned int n_owned = offline_data.n_locally_owned();
679
681
682 const auto sparsity_simd_view =
683 offline_data.sparsity_pattern_simd().template view<MemorySpace>();
684
685 const auto U_view =
686 std::as_const(state_vector)
687 .U.template view<ScalarView::problem_dimension, MemorySpace>();
688 const auto precomputed_view =
689 state_vector.precomputed
690 .template view<ScalarView::n_precomputed_values, MemorySpace>();
691
692 const auto hyperbolic_system_views =
693 make_select_view<dim, ScalarNumber, MemorySpace>(*this);
694
695 const auto body = [=](auto sentinel, unsigned int i) {
696 using T = decltype(sentinel);
698 using precomputed_type = typename View::precomputed_type;
699
700 const unsigned int row_length = sparsity_simd_view.row_length(i);
701 if (skip_constrained_dofs && row_length == 1)
702 return;
703
704 const auto view = hyperbolic_system_views.template view<T>();
705
706 const auto U_i = U_view.template read_tensor<T>(i);
707 const auto eta_m = view.mathematical_entropy(U_i);
708 const auto h_sharp = view.water_depth_sharp(U_i);
709 const auto h_star = ryujin::pow(h_sharp, ScalarNumber(4. / 3.));
710
711 const precomputed_type prec_i{eta_m, h_star};
712 precomputed_view.template write_tensor<T>(prec_i, i);
713 };
714
715 loop<MemorySpace, ScalarNumber>(
716 "hyperbolic_kernel_01b", body, 0, n_internal, n_owned);
717 }
718
719
720 template <int dim, typename Number, typename MemorySpace>
721 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
727
728
729 template <int dim, typename Number, typename MemorySpace>
730 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
733 {
734 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
735
736 const Number h_cutoff_mollified =
737 reference_water_depth() * dry_state_relaxation_large() * Number(eps);
738
739 const Number h = water_depth(U);
740 const Number h_pos = positive_part(water_depth(U));
741 const Number h_max = std::max(h, h_cutoff_mollified);
742 const Number denom = h * h + h_max * h_max;
743 return ScalarNumber(2.) * h_pos / denom;
744 }
745
746
747 template <int dim, typename Number, typename MemorySpace>
748 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
750 const state_type &U) const
751 {
752 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
753
754 const Number h_cutoff_small =
755 reference_water_depth() * dry_state_relaxation_small() * Number(eps);
756
757 const Number h = water_depth(U);
758 const Number h_max = std::max(h, h_cutoff_small);
759 return h_max;
760 }
761
762
763 template <int dim, typename Number, typename MemorySpace>
764 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
766 const state_type &U) const
767 {
768 return ScalarNumber(1.) / water_depth_sharp(U);
769 }
770
771
772 template <int dim, typename Number, typename MemorySpace>
773 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
775 const Number &h) const
776 {
778 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
779
780 const Number h_cutoff_large =
781 reference_water_depth() * dry_state_relaxation_large() * Number(eps);
782
783 return ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
784 std::abs(h), h_cutoff_large, Number(0.), h);
785 }
786
787
788 template <int dim, typename Number, typename MemorySpace>
789 DEAL_II_HOST_DEVICE_ALWAYS_INLINE dealii::Tensor<1, dim, Number>
791 const state_type &U)
792 {
793 dealii::Tensor<1, dim, Number> result;
794
795 for (unsigned int i = 0; i < dim; ++i)
796 result[i] = U[1 + i];
797 return result;
798 }
799
800
801 template <int dim, typename Number, typename MemorySpace>
802 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
804 const state_type &U) const
805 {
806 const auto h = water_depth(U);
807 const auto vel = momentum(U) * inverse_water_depth_sharp(U);
808
809 /* KE = 1/2 h |v|^2 */
810 return ScalarNumber(0.5) * h * vel.norm_square();
811 }
812
813
814 template <int dim, typename Number, typename MemorySpace>
815 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
817 const state_type &U) const
818 {
819 const Number h_sqd = U[0] * U[0];
820
821 /* p = 1/2 g h^2 */
822 return ScalarNumber(0.5) * gravity() * h_sqd;
823 }
824
825
826 template <int dim, typename Number, typename MemorySpace>
827 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
829 const state_type &U) const
830 {
831 /* c^2 = g * h */
832 return std::sqrt(gravity() * U[0]);
833 }
834
835
836 template <int dim, typename Number, typename MemorySpace>
837 DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number
839 const state_type &U) const
840 {
841 const auto p = pressure(U);
842 const auto k_e = kinetic_energy(U);
843 return p + k_e;
844 }
845
846
847 template <int dim, typename Number, typename MemorySpace>
848 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
851 {
852 /*
853 * With
854 * eta = 1/2 g h^2 + 1/2 |m|^2 / h
855 *
856 * we get
857 *
858 * eta' = (g h - 1/2 |vel|^2, vel)
859 *
860 * where vel = m / h
861 */
862
863 state_type result;
864
865 const Number &h = U[0];
866 const auto vel = momentum(U) * inverse_water_depth_sharp(U);
867
868 // water depth component
869 result[0] = gravity() * h - ScalarNumber(0.5) * vel.norm_square();
870
871 // momentum components
872 for (unsigned int i = 0; i < dim; ++i) {
873 result[1 + i] = vel[i];
874 }
875
876 return result;
877 }
878
879
880 template <int dim, typename Number, typename MemorySpace>
881 DEAL_II_HOST_DEVICE_ALWAYS_INLINE bool
883 const state_type &U) const
884 {
885 const auto h = filter_dry_water_depth(water_depth(U));
886
887 constexpr auto gte = dealii::SIMDComparison::greater_than_or_equal;
888 const auto test = ryujin::compare_and_apply_mask<gte>(
889 h, Number(0.), Number(0.), Number(-1.));
890
891#ifdef DEBUG_OUTPUT
892 if (!(test == Number(0.))) {
893 std::cout << std::fixed << std::setprecision(16);
894 std::cout << "Bounds violation: Negative state [h] detected!\n";
895 std::cout << "\t\th: " << h << "\n" << std::endl;
896 __builtin_trap();
897 }
898#endif
899
900 return (test == Number(0.));
901 }
902
903
904 template <int dim, typename Number, typename MemorySpace>
905 template <int component>
906 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
909 const state_type &U,
910 const state_type &U_bar,
911 const dealii::Tensor<1, dim, Number> &normal) const -> state_type
912 {
913 /* Note that U_bar are the dirichlet values that are prescribed */
914 static_assert(component == 1 || component == 2,
915 "component has to be 1 or 2");
916
918
919 const auto m = momentum(U);
920 const auto a = speed_of_sound(U);
921 const auto vn = m * normal * inverse_water_depth_sharp(U);
922
923 const auto m_bar = momentum(U_bar);
924 const auto a_bar = speed_of_sound(U_bar);
925 const auto vn_bar = m_bar * normal * inverse_water_depth_sharp(U_bar);
926
927 /* First Riemann characteristic: v * n - 2 * a */
928
929 const auto R_1 = component == 1 ? vn_bar - ScalarNumber(2.) * a_bar
930 : vn - ScalarNumber(2.) * a;
931
932 /* Second Riemann characteristic: v * n + 2 * a */
933
934 const auto R_2 = component == 2 ? vn_bar + ScalarNumber(2.) * a_bar
935 : vn + ScalarNumber(2.) * a;
936
937 const auto vperp = m * inverse_water_depth_sharp(U) - vn * normal;
938
939 const auto vn_new = ScalarNumber(0.5) * (R_1 + R_2);
940
941 const auto h_new =
942 ryujin::fixed_power<2>((R_2 - R_1) / ScalarNumber(4.)) / gravity();
943
944 state_type U_new;
945 U_new[0] = h_new;
946 for (unsigned int d = 0; d < dim; ++d) {
947 U_new[1 + d] = h_new * (vn_new * normal + vperp)[d];
948 }
949
950 return U_new;
951 }
952
953
954 template <int dim, typename Number, typename MemorySpace>
955 template <typename Lambda>
956 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
958 const dealii::types::boundary_id id,
959 const state_type &U,
960 const dealii::Tensor<1, dim, Number> &normal,
961 const Lambda &get_dirichlet_data) const -> state_type
962 {
963 state_type result = U;
964
965 if (id == Boundary::dirichlet) {
966 result = get_dirichlet_data();
967
968 } else if (id == Boundary::dirichlet_momentum) {
969 /* Only enforce Dirichlet conditions on the momentum: */
970 auto m_dirichlet = momentum(get_dirichlet_data());
971 for (unsigned int k = 0; k < dim; ++k)
972 result[k + 1] = m_dirichlet[k];
973
974 } else if (id == Boundary::dirichlet_velocity) {
975 /* Only enforce Dirichlet conditions on the velocity: */
976 const auto U_dirichlet = get_dirichlet_data();
977 const auto h_inv_sharp_dirichlet =
978 inverse_water_depth_sharp(U_dirichlet);
979 const auto v_dirichlet = momentum(U_dirichlet) * h_inv_sharp_dirichlet;
980 const auto h = water_depth_sharp(result);
981 for (unsigned int k = 0; k < dim; ++k)
982 result[k + 1] = h * v_dirichlet[k];
983
984 } else if (id == Boundary::slip) {
985 auto m = momentum(U);
986 m -= 1. * (m * normal) * normal;
987 for (unsigned int k = 0; k < dim; ++k)
988 result[k + 1] = m[k];
989
990 } else if (id == Boundary::no_slip) {
991 for (unsigned int k = 0; k < dim; ++k)
992 result[k + 1] = Number(0.);
993
994 } else if (id == Boundary::dynamic) {
995 /*
996 * On dynamic boundary conditions, we distinguish four cases:
997 *
998 * - supersonic inflow: prescribe full state
999 * - subsonic inflow:
1000 * decompose into Riemann invariants and leave R_2
1001 * characteristic untouched.
1002 * - supersonic outflow: do nothing
1003 * - subsonic outflow:
1004 * decompose into Riemann invariants and prescribe incoming
1005 * R_1 characteristic.
1006 */
1007 const auto m = momentum(U);
1008 const auto h_inverse = inverse_water_depth_sharp(U);
1009 const auto a = speed_of_sound(U);
1010 const auto vn = m * normal * h_inverse;
1011
1012 /* Supersonic inflow: */
1013 if (vn < -a) {
1014 result = get_dirichlet_data();
1015 }
1016
1017 /* Subsonic inflow: */
1018 if (vn >= -a && vn <= 0.) {
1019 const auto U_dirichlet = get_dirichlet_data();
1020 result = prescribe_riemann_characteristic<2>(U_dirichlet, U, normal);
1021 }
1022
1023 /* Subsonic outflow: */
1024 if (vn > 0. && vn <= a) {
1025 const auto U_dirichlet = get_dirichlet_data();
1026 result = prescribe_riemann_characteristic<1>(U, U_dirichlet, normal);
1027 }
1028
1029 /* Supersonic outflow: do nothing, i.e., keep U as is */
1030
1031 } else {
1032 Assert(false, dealii::ExcNotImplemented());
1033 }
1034
1035 return result;
1036 }
1037
1038
1039 template <int dim, typename Number, typename MemorySpace>
1040 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1042 -> flux_type
1043 {
1044 const auto h_inverse = inverse_water_depth_sharp(U);
1045 const auto m = momentum(U);
1046 const auto p = pressure(U);
1047
1048 flux_type result;
1049
1050 result[0] = (m * h_inverse) * U[0];
1051 for (unsigned int i = 0; i < dim; ++i) {
1052 result[1 + i] = (m * h_inverse) * m[i];
1053 result[1 + i][i] += p;
1054 }
1055 return result;
1056 }
1057
1058
1059 template <int dim, typename Number, typename MemorySpace>
1060 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1062 -> flux_type
1063 {
1064 const auto h_inverse = inverse_water_depth_sharp(U);
1065 const auto m = momentum(U);
1066
1067 flux_type result;
1068
1069 result[0] = (m * h_inverse) * U[0];
1070 for (unsigned int i = 0; i < dim; ++i) {
1071 result[1 + i] = (m * h_inverse) * m[i];
1072 }
1073 return result;
1074 }
1075
1076
1077 template <int dim, typename Number, typename MemorySpace>
1078 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1080 const state_type &U, const Number &Z_left, const Number &Z_right) const
1081 -> state_type
1082 {
1083 const Number Z_max = std::max(Z_left, Z_right);
1084 const Number h = water_depth(U);
1085 const Number H_star = std::max(Number(0.), h + Z_left - Z_max);
1086
1087 return U * H_star * inverse_water_depth_mollified(U);
1088 }
1089
1090
1091 template <int dim, typename Number, typename MemorySpace>
1092 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1094 const flux_contribution_type &flux_i,
1095 const flux_contribution_type &flux_j) const -> std::array<state_type, 2>
1096 {
1097 const auto &[U_i, Z_i] = flux_i;
1098 const auto &[U_j, Z_j] = flux_j;
1099
1100 const auto U_star_ij = star_state(U_i, Z_i, Z_j);
1101 const auto U_star_ji = star_state(U_j, Z_j, Z_i);
1102
1103 return {U_star_ij, U_star_ji};
1104 }
1105
1106
1107 template <int dim, typename Number, typename MemorySpace>
1108 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1110 const PrecomputedVectorView & /*pv*/,
1112 const unsigned int i,
1113 const state_type &U_i) const -> flux_contribution_type
1114 {
1115 const auto Z_i = piv.template read_tensor<Number>(i)[0];
1116 return {U_i, Z_i};
1117 }
1118
1119
1120 template <int dim, typename Number, typename MemorySpace>
1121 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1123 const PrecomputedVectorView & /*pv*/,
1125 const unsigned int *js,
1126 const state_type &U_j) const -> flux_contribution_type
1127 {
1128 const auto Z_j = piv.template read_tensor<Number>(js)[0];
1129 return {U_j, Z_j};
1130 }
1131
1132
1133 template <int dim, typename Number, typename MemorySpace>
1134 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1136 const flux_contribution_type &flux_i,
1137 const flux_contribution_type &flux_j,
1138 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1139 {
1140 const auto &[U_i, Z_i] = flux_i;
1141 const auto &[U_star_ij, U_star_ji] = equilibrated_states(flux_i, flux_j);
1142
1143 const auto H_i = water_depth(U_i);
1144 const auto H_star_ij = water_depth(U_star_ij);
1145 const auto H_star_ji = water_depth(U_star_ji);
1146
1147 const auto g_i = g(U_star_ij);
1148 const auto g_j = g(U_star_ji);
1149
1150 auto result = -add(g_i, g_j);
1151
1152 const auto factor =
1153 (ScalarNumber(0.5) * (H_star_ji * H_star_ji - H_star_ij * H_star_ij) +
1154 H_i * H_i) *
1155 gravity();
1156
1157 for (unsigned int i = 0; i < dim; ++i) {
1158 result[1 + i][i] -= factor;
1159 }
1160
1161 return contract(result, c_ij);
1162 }
1163
1164
1165 template <int dim, typename Number, typename MemorySpace>
1166 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1168 const flux_contribution_type &flux_i,
1169 const flux_contribution_type &flux_j,
1170 const dealii::Tensor<1, dim, Number> &c_ij) const -> state_type
1171 {
1172 const auto &[U_i, Z_i] = flux_i;
1173 const auto &[U_j, Z_j] = flux_j;
1174
1175 const auto H_i = water_depth(U_i);
1176 const auto H_j = water_depth(U_j);
1177
1178 const auto g_i = g(U_i);
1179 const auto g_j = g(U_j);
1180
1181 auto result = -add(g_i, g_j);
1182
1183 const auto factor = gravity() * H_i * (H_j + Z_j - Z_i);
1184 for (unsigned int i = 0; i < dim; ++i) {
1185 result[1 + i][i] -= factor;
1186 }
1187
1188 return contract(result, c_ij);
1189 }
1190
1191
1192 template <int dim, typename Number, typename MemorySpace>
1193 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1195 const flux_contribution_type &flux_i,
1196 const flux_contribution_type &flux_j,
1197 const dealii::Tensor<1, dim, Number> &c_ij,
1198 const Number &d_ij) const -> state_type
1199 {
1200 const auto &[U_i, Z_i] = flux_i;
1201 const auto &[U_j, Z_j] = flux_j;
1202 const auto U_star_ij = star_state(U_i, Z_i, Z_j);
1203
1204 const auto h_inverse = inverse_water_depth_sharp(U_i);
1205 const auto m = momentum(U_i);
1206 const auto factor = ScalarNumber(2.) * (d_ij + h_inverse * (m * c_ij));
1207
1208 return -factor * (U_star_ij - U_i);
1209 }
1210
1211
1212 template <int dim, typename Number, typename MemorySpace>
1213 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1215 const state_type &U, const Number &h_star, const ScalarNumber tau) const
1216 -> state_type
1217 {
1218 state_type result;
1219
1220 const auto g = gravity();
1221 const auto n = manning_friction_coefficient();
1222
1223 const auto h_inverse = inverse_water_depth_mollified(U);
1224
1225 const auto m = momentum(U);
1226 const auto v_norm = (m * h_inverse).norm();
1227 const auto factor = ScalarNumber(2.) * g * n * n * v_norm;
1228
1229 const auto denominator = h_star + std::max(h_star, tau * factor);
1230 const auto denominator_inverse = ScalarNumber(1.) / denominator;
1231
1232 for (unsigned int d = 0; d < dim; ++d)
1233 result[d + 1] = -factor * denominator_inverse * m[d];
1234
1235 return result;
1236 }
1237
1238
1239 template <int dim, typename Number, typename MemorySpace>
1240 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1242 const PrecomputedVectorView &pv,
1243 const unsigned int i,
1244 const state_type &U_i,
1245 const ScalarNumber tau) const -> state_type
1246 {
1247 const auto &[eta_m, h_star] =
1248 pv.template read_tensor<Number, precomputed_type>(i);
1249
1250 return manning_friction(U_i, h_star, tau);
1251 }
1252
1253
1254 template <int dim, typename Number, typename MemorySpace>
1255 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1257 const PrecomputedVectorView &pv,
1258 const unsigned int *js,
1259 const state_type &U_j,
1260 const ScalarNumber tau) const -> state_type
1261 {
1262 const auto &[eta_m, h_star] =
1263 pv.template read_tensor<Number, precomputed_type>(js);
1264
1265 return manning_friction(U_j, h_star, tau);
1266 }
1267
1268
1269 template <int dim, typename Number, typename MemorySpace>
1270 template <typename ST>
1271 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1273 const ST &state) const -> state_type
1274 {
1275 using T = typename ST::value_type;
1276 static_assert(std::is_same_v<Number, T>, "template mismatch");
1277
1278 constexpr auto dim2 = ST::dimension - 1;
1279 static_assert(dim >= dim2,
1280 "the space dimension of the argument state must not be "
1281 "larger than the one of the target state");
1282
1283 state_type result;
1284 result[0] = state[0];
1285 for (unsigned int i = 1; i < dim2 + 1; ++i)
1286 result[i] = state[i];
1287
1288 return result;
1289 }
1290
1291 template <int dim, typename Number, typename MemorySpace>
1292 template <typename ST>
1293 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1295 const ST &initial_state) const -> state_type
1296 {
1297 const auto primitive_state = expand_state(initial_state);
1298 return from_primitive_state(primitive_state);
1299 }
1300
1301
1302 template <int dim, typename Number, typename MemorySpace>
1303 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1305 const state_type &primitive_state) const -> state_type
1306 {
1307 const auto &h = primitive_state[0];
1308
1309 auto state = primitive_state;
1310 /* Fix up momentum: */
1311 for (unsigned int i = 1; i < dim + 1; ++i)
1312 state[i] *= h;
1313
1314 return state;
1315 }
1316
1317
1318 template <int dim, typename Number, typename MemorySpace>
1319 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1321 const state_type &state) const -> state_type
1322 {
1323 const auto h_inverse = inverse_water_depth_sharp(state);
1324
1325 auto primitive_state = state;
1326 /* Fix up velocity: */
1327 for (unsigned int i = 1; i < dim + 1; ++i)
1328 primitive_state[i] *= h_inverse;
1329
1330 return primitive_state;
1331 }
1332
1333
1334 template <int dim, typename Number, typename MemorySpace>
1335 template <typename Lambda>
1336 DEAL_II_HOST_DEVICE_ALWAYS_INLINE auto
1338 const state_type &state, const Lambda &lambda) const -> state_type
1339 {
1340 auto result = state;
1341 auto M = lambda(momentum(state));
1342 for (unsigned int d = 0; d < dim; ++d)
1343 result[1 + d] = M[d];
1344 return result;
1345 }
1346 } // namespace ShallowWater
1347} // 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
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
std::tuple< state_type, Number > flux_contribution_type
dealii::Tensor< 1, problem_dimension, Number > state_type
DEAL_II_HOST_DEVICE Number kinetic_energy(const state_type &U) const
DEAL_II_HOST_DEVICE_ALWAYS_INLINE ScalarNumber dry_state_relaxation_large() const
DEAL_II_HOST_DEVICE state_type apply_galilei_transform(const state_type &state, const Lambda &lambda) const
DEAL_II_HOST_DEVICE state_type star_state(const state_type &U, const Number &Z_left, const Number &Z_right) const
DEAL_II_HOST_DEVICE flux_type g(const state_type &U) const
DEAL_II_HOST_DEVICE state_type manning_friction(const state_type &U, const Number &h_star, const ScalarNumber tau) 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_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:134
MultiComponentVector< Number > precomputed