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