Peano
Loading...
Searching...
No Matches
swe.py
Go to the documentation of this file.
1# This file is part of the ExaHyPE2 project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3import sympy
4
5"""
6We import the required modules for this project.
7We always need the 'peano4' module as this is our core project.
8Since we are creating a SymHyPE/ExaHyPE 2 application, we additionally
9need to import the 'exahype2' and 'symhype' modules.
10"""
11import peano4
12import exahype2
13import symhype
14
15"""
16The number of finite volumes per axis in one patch.
17"""
18patch_size = 16
19
20"""
21The number of levels the mesh is refined.
22"""
23depth = 5
24
25"""
26The simulation end time.
27"""
28end_time = 1.0
29
30"""
31Choose domain size and offset.
32"""
33size = [2.0, 2.0]
34offset = [0.0, 0.0]
35
36"""
37Choose how often a snapshot is written.
38"""
39time_in_between_two_snapshots = end_time / 10
40# time_in_between_two_snapshots = 0 # Set to 0 to disable I/O
41
42"""
43Switch between 'Release', 'Debug', 'Asserts', 'Trace', 'Stats'.
44"""
45compile_mode = "Release"
46
47"""
48We first create a new ExaHyPE 2 project.
49For this, we specify the (nested) namespaces, the name of our main file and our executable name.
50"""
51my_project = exahype2.Project(
52 namespace=["tutorials", "symhype", "swe"],
53 project_name="SWE",
54 directory=".",
55 executable="SWE",
56)
57
58"""
59Add the solver using named arguments.
60This is the way you can add further PDE terms.
61This requires the 'BlockStructured' toolbox and 'ExaHyPE' to be built.
62"""
63my_solver = exahype2.solvers.fv.godunov.GlobalAdaptiveTimeStep(
64 name="FVSolver",
65 patch_size=patch_size,
66 unknowns=2 + 1, # [h, hu, hv]
67 auxiliary_variables=1, # Bathymetry (b)
68 min_volume_h=(1.1 * min(size) / (3.0**depth)),
69 max_volume_h=(1.1 * min(size) / (3.0**depth)),
70 time_step_relaxation=0.5,
71)
72
73"""
74We want to define our PDE symbolically.
75"""
76my_pde = symhype.FirstOrderConservativePDEFormulation(
77 unknowns=2 + 1, auxiliary_variables=1, dimensions=2
78)
79h = my_pde.name_Q_entry(0, "h")
80hu = my_pde.name_Q_entry(1, "hu")
81hv = my_pde.name_Q_entry(2, "hv")
82b = my_pde.name_auxiliary_variable(0, "b")
83
84# Gravitational constant
85g = sympy.symbols("g")
86
87# Speed in x-direction
88u = hu / h
89
90# Speed in y-direction
91v = hv / h
92
93"""
94Define the equation system
95"""
96# Flux [unknowns, dimensions]
97my_pde.F[0, 0] = hu
98my_pde.F[1, 0] = hu * u + (g * h**2) / 2
99my_pde.F[2, 0] = h * u * v
100
101my_pde.F[0, 1] = hv
102my_pde.F[1, 1] = h * u * v
103my_pde.F[2, 1] = hv * v + (g * h**2) / 2
104
105# Eigenvalues [unknowns, dimensions]
106my_pde.eigenvalues[0, 0] = u
107my_pde.eigenvalues[0, 1] = v
108
109my_pde.eigenvalues[1, 0] = u + sympy.sqrt(g * h)
110my_pde.eigenvalues[1, 1] = v + sympy.sqrt(g * h)
111my_pde.eigenvalues[2, 0] = u - sympy.sqrt(g * h)
112my_pde.eigenvalues[2, 1] = v - sympy.sqrt(g * h)
113
114# NCP [unknowns, dimensions]
115delta_b = my_pde.grad(b)
116
117my_pde.ncp[0, 0] = 0.0
118my_pde.ncp[1, 0] = g * h * delta_b
119my_pde.ncp[2, 0] = 0.0
120
121my_pde.ncp[0, 1] = 0.0
122my_pde.ncp[1, 1] = 0.0
123my_pde.ncp[2, 1] = g * h * delta_b
124
125"""
126Since 'my_pde' only holds the PDE without initial- or boundary conditions,
127we still need to properly define initial- and boundary conditions.
128This gives us then a complete description of a 'scenario'.
129"""
130
131# Initial conditions as specified in the documentation.
132my_pde.initial_values[0] = 1.0 # Water height (h)
133my_pde.initial_values[1] = 0 # x-momentum (hu)
134my_pde.initial_values[2] = 0 # y-momentum (hv)
135
136volume_centre = sympy.sqrt((1.0 - my_pde.x[0]) ** 2 + (1.0 - my_pde.x[1]) ** 2)
137my_pde.initial_values[3] = sympy.Piecewise(
138 (0.0, volume_centre < 0.4), (0.1, True)
139) # Bathymetry (b)
140
141# Boundary conditions
142my_pde.boundary_values[0] = h
143my_pde.boundary_values[1] = -hu
144my_pde.boundary_values[2] = -hv
145my_pde.boundary_values[3] = b
146
147my_pde.substitute_expression(g, 9.81)
148
149"""
150Specify which implementation our solvers uses.
151Here we want to set the implementation we get from our symbolically defined PDE,
152i.e., we get the C++ implementation which is generated by SymHyPE.
153"""
154my_solver.set_implementation(
155 initial_conditions=my_pde.implementation_of_initial_conditions(),
156 boundary_conditions=my_pde.implementation_of_boundary_conditions(),
157 flux=my_pde.implementation_of_flux(),
158 max_eigenvalue=my_pde.implementation_of_max_eigenvalue(),
159 ncp=my_pde.implementation_of_ncp(),
160)
161
162"""
163To see which variables (unknowns + auxiliary variables) we can visualise,
164let's add a plot description for the variables to our solver.
165"""
166my_solver.plot_description = my_pde.unknown_identifier_for_plotter()
167
168"""
169Add the solver to our project
170"""
171my_project.add_solver(my_solver)
172
173"""
174Configure some global parameters
175"""
176my_project.set_global_simulation_parameters(
177 dimensions=2, # The dimensionality is fixed for SWE
178 size=size,
179 offset=offset,
180 min_end_time=end_time,
181 max_end_time=end_time,
182 first_plot_time_stamp=0.0,
183 time_in_between_plots=time_in_between_two_snapshots,
184 periodic_BC=[False, False, False],
185)
186
187"""
188This defines where the output files should go.
189If you omit this, output files are automatically put into the application's folder
190"""
191my_project.set_output_path("solutions")
192
193"""
194Configure load balancer for parallel execution.
195"""
196my_project.set_load_balancer("new ::exahype2::LoadBalancingConfiguration")
197
198"""
199We need to set the location of our core libraries ('Peano4').
200This helps us to resolve any dependencies.
201Additionally, we specify the build mode which you can also change to a different mode.
202"""
203my_project.set_Peano4_installation(
204 "../../../", mode=peano4.output.string_to_mode(compile_mode)
205)
206
207"""
208We generate and grab the underlying core project of 'Peano4'.
209This gives us access to some functions we want to use to finalise and build this project.
210"""
211my_project = my_project.generate_Peano4_project(verbose=False)
212
213"""
214Finally, we want to build our project.
215First, all of the necessary glue code is generated in the application folder,
216then 'make' is invoked automatically which compiles the generated code and links against our core libraries
217and toolboxes which have been built before.
218You can also always invoke 'make' yourself to compile, or cleanup with 'make clean'.
219"""
220my_project.build(make=True, make_clean_first=True, throw_away_data_after_build=True)
221
222print("\nPDE is: ")
223print(my_pde.__str__())
224print(my_solver)
225print(my_project)