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