7 A solitary wave case implementation based on the papers listed below. the wave shape and initial velocity
8 are taken from the paper "Non-breaking and breaking solitary wave run-up" section 2.5.1.
9 Some more properties, like the characteristic length of the wave, are taken from the paper
10 "Solitary wave runup on plane slopes".
13 title={Non-breaking and breaking solitary wave run-up},
14 author={Li, Ying and Raichlen, Fredric},
15 journal={Journal of Fluid Mechanics},
19 publisher={Cambridge University Press}
23 title={Solitary wave runup on plane slopes},
24 author={Li, Ying and Raichlen, Fredric},
25 journal={Journal of Waterway, Port, Coastal, and Ocean Engineering},
30 publisher={American Society of Civil Engineers}
33 Also interesting is one of the original papers which introduced many of such cases:
35 @article{Synolakis1987,
36 title={The runup of solitary waves},
37 author={Synolakis, Costas Emmanuel},
38 journal={Journal of Fluid Mechanics},
42 publisher={Cambridge University Press}
46initial_conditions =
"""
47 for (int i = 0; i < NumberOfUnknowns + NumberOfAuxiliaryVariables; i++) {
51 constexpr double Depth = 1.0;
52 constexpr double BeachSlopeAngle = 30 * std::numbers::pi / 180;
53 constexpr double WaveAmplitude = 0.5;
55 const double gamma = std::sqrt((3 * WaveAmplitude) / (4 * Depth));
57 // The wave crest is located at L/2 away from the foot of the
58 // slope xZero, where L is the characteristic length of the solitary wave.
59 const double wavePos = 0.5 * ((2/gamma) * (std::acosh(std::sqrt(20))));
61 const double xZero = Depth / std::tan(BeachSlopeAngle);
63 // Set up the bathymetry, extend the beach a bit in negative x direction
64 if (x[0] < 0) { // Beach slope for negative x[0] values
65 Q[Shortcuts::z] = std::fabs(x[0]) * std::tan(BeachSlopeAngle);
66 } else if (x[0] < xZero) { // Initialise the beach slope for x[0] >= 0
67 Q[Shortcuts::z] = -(x[0] * std::tan(BeachSlopeAngle));
68 } else { // Initialise the constant ocean depth
69 Q[Shortcuts::z] = -Depth;
72 // Set up the wave profile
73 const double innerTerm = gamma * ((x[0] - (xZero + wavePos)) / Depth);
74 const double waveProfile = WaveAmplitude * std::pow((1 / (std::cosh(innerTerm))), 2);
76 Q[Shortcuts::h] = Depth + waveProfile;
77 } else if (x[0] < xZero && x[0] >= 0){
78 Q[Shortcuts::h] = std::fabs(Q[Shortcuts::z]);
79 } else if (x[0] >= (xZero + 2 * wavePos)) { // Coordinate outside the characteristic wave region
80 Q[Shortcuts::h] = Depth;
83 // Set up the velocity
84 // Velocity taken from the paper "Non-breaking and breaking solitary wave run-up"
85 const double waveCelerity = std::sqrt(g * (WaveAmplitude + Depth));
86 Q[Shortcuts::hu] = -((waveCelerity * waveProfile) / (Depth + waveProfile)) * Q[Shortcuts::h];
89boundary_conditions =
"""
90 Qoutside[Shortcuts::h] = Qinside[Shortcuts::h];
91 Qoutside[Shortcuts::hu] = -Qinside[Shortcuts::hu];
92 Qoutside[Shortcuts::hv] = -Qinside[Shortcuts::hv];
93 Qoutside[Shortcuts::z] = Qinside[Shortcuts::z];
96refinement_criterion =
"""
97 auto result = ::exahype2::RefinementCommand::Keep;
101parser = exahype2.ArgumentParser()
104 degrees_of_freedom=16,
107args = parser.parse_args()
110 "g": [9.81,
"double"],
111 "hThreshold": [1e-5,
"double"],
116max_h = 1.1 * min(size) / (3.0**args.min_depth)
117min_h = max_h * 3.0 ** (-args.amr_levels)
119fv_solver = exahype2.solvers.fv.godunov.GlobalAdaptiveTimeStep(
121 patch_size=args.degrees_of_freedom,
122 unknowns={
"h": 1,
"hu": 1,
"hv": 1},
123 auxiliary_variables={
"z": 1},
126 time_step_relaxation=0.5,
129fv_solver.set_implementation(
130 initial_conditions=initial_conditions,
131 boundary_conditions=boundary_conditions,
132 refinement_criterion=refinement_criterion,
133 riemann_solver=
"return llfRiemannSolver<double, Shortcuts>(QL, QR, x, h, t, dt, normal, FL, FR);",
136fv_solver.add_user_solver_includes(
138#include "../LLFRiemannSolver.h"
142project = exahype2.Project(
143 namespace=[
"applications",
"exahype2",
"ShallowWater"],
144 project_name=
"SolitaryWave",
146 executable=
"ExaHyPE",
148project.add_solver(fv_solver)
150if args.number_of_snapshots <= 0:
151 time_in_between_plots = 0.0
153 time_in_between_plots = args.end_time / args.number_of_snapshots
154 project.set_output_path(args.output)
156project.set_global_simulation_parameters(
160 min_end_time=args.end_time,
161 max_end_time=args.end_time,
162 first_plot_time_stamp=0.0,
163 time_in_between_plots=time_in_between_plots,
165 args.periodic_boundary_conditions_x,
166 args.periodic_boundary_conditions_y,
170project.set_load_balancer(
171 f
"new ::exahype2::LoadBalancingConfiguration({args.load_balancing_quality}, 1, {args.trees})"
173project.set_build_mode(mode=peano4.output.string_to_mode(args.build_mode))
174project = project.generate_Peano4_project(verbose=
False)
175for const_name, const_info
in constants.items():
176 const_val, const_type = const_info
177 project.constants.export_constexpr_with_type(const_name, str(const_val), const_type)
178project.build(make=
True, make_clean_first=
True, throw_away_data_after_build=
True)