9We import the required modules for this project.
10We always need the 'peano4' module as this is our core project.
11Since we are creating an ExaHyPE 2 application, we additionally
12need to import the 'exahype2' module.
18We specify the space dimensions here.
19We support either 2- or 3-dimensional problems.
24The number of finite volumes per axis in one patch.
29The size of a finite volume/cell per axis.
34The simulation end time.
39Choose domain size and offset.
42offset = [0.0, 0.0, 0.0]
45Choose how often a snapshot is written.
47time_in_between_two_snapshots = end_time / 100
51Switch between 'Release', 'Debug', 'Asserts', 'Trace', 'Stats'.
53compile_mode = peano4.output.CompileMode.Release
56We first create a new ExaHyPE 2 project.
57For this, we specify the (nested) namespaces, the name of our main file and our executable name.
60 namespace=[
"tutorials",
"exahype2",
"euler"],
67Add the Finite Volumes solver using named arguments.
68This is the way you can add further PDE terms.
69This requires the 'BlockStructured' toolbox and 'ExaHyPE' to be built.
70Rusanov is the type of flux that is used to solve the Riemann problem at boundaries between cells.
74 patch_size=patch_size,
75 unknowns=dimensions + 2,
76 auxiliary_variables=0,
77 min_volume_h=volume_size,
78 max_volume_h=volume_size,
79 time_step_relaxation=0.5,
83We want to define our PDE symbolically.
84For this we use the 'symhype' package (not to be confused with 'sympy') from 'ExaHyPE'.
87 unknowns=dimensions + 2, auxiliary_variables=0, dimensions=dimensions
91Give entries in input vector symbolic names. We first declare the constant
92gamma. Then we tell the solver how we would like to name the Q entries.
94gamma = sympy.symbols(
"gamma")
96rho = my_pde.name_Q_entry(0,
"rho")
99j = my_pde.name_Q_entries(1, dimensions,
"j")
101E = my_pde.name_Q_entry(dimensions + 1,
"E")
103p = (gamma - 1) * (E - 1 / 2 * exahype2.symhype.dot(j, j) / rho)
106Define the equation system
110my_pde.F[1 : dimensions + 1, :] = 1 / rho * exahype2.symhype.outer(
112) + p * sympy.eye(dimensions)
113my_pde.F[dimensions + 1, :] = 1 / rho * j * (E + p)
116c = sympy.sqrt(gamma * p / rho)
119 my_pde.eigenvalues[0] = [u[0] - c, u[1] - c, u[2] - c]
120 my_pde.eigenvalues[1] = [u[0], u[1], u[2]]
121 my_pde.eigenvalues[2] = [u[0], u[1], u[2]]
122 my_pde.eigenvalues[3] = [u[0], u[1], u[2]]
123 my_pde.eigenvalues[4] = [u[0] + c, u[1] + c, u[2] + c]
125 my_pde.eigenvalues[0] = [u[0] - c, u[1] - c]
126 my_pde.eigenvalues[1] = [u[0], u[1]]
127 my_pde.eigenvalues[2] = [u[0], u[1]]
128 my_pde.eigenvalues[3] = [u[0] + c, u[1] + c]
130my_pde.substitute_expression(gamma, 1.4)
133Since 'my_pde' only holds the PDE without initial- or boundary conditions,
134we still need to properly define initial- and boundary conditions.
135This gives us then a complete description of a 'scenario'.
139my_pde.initial_values[0] = 1
140my_pde.initial_values[1] = 0
141my_pde.initial_values[2] = 0
144 volume_centre = sympy.sqrt((0.5 - my_pde.x[0]) ** 2 + (0.5 - my_pde.x[1]) ** 2)
145 my_pde.initial_values[3] = sympy.Piecewise(
146 (1.0, volume_centre < 0.2), (1.01,
True)
149 volume_centre = sympy.sqrt(
150 (0.5 - my_pde.x[0]) ** 2 + (0.5 - my_pde.x[1]) ** 2 + (0.5 - my_pde.x[2]) ** 2
152 my_pde.initial_values[3] = 0
153 my_pde.initial_values[4] = sympy.Piecewise(
154 (1.0, volume_centre < 0.2), (1.01,
True)
158Specify which implementation our solvers uses.
159Here we want to set the implementation we get from our symbolically defined PDE,
160i.e., we get the C++ implementation which is generated by ExaHyPE's 'symhype' package.
162my_solver.set_implementation(
163 initial_conditions=my_pde.implementation_of_initial_conditions(),
164 boundary_conditions=my_pde.implementation_of_homogeneous_Neumann_BC(),
165 flux=my_pde.implementation_of_flux(),
166 eigenvalues=my_pde.implementation_of_max_eigenvalue(),
170To see which variables (unknowns + auxiliary variables) we can visualise,
171let's add a plot description for the variables to our solver.
173my_solver.plot_description = my_pde.unknown_identifier_for_plotter()
176Add the solver to our project
178my_project.add_solver(my_solver)
181Configure some global parameters
183my_project.set_global_simulation_parameters(
184 dimensions=dimensions,
185 size=size[0:dimensions],
186 offset=offset[0:dimensions],
187 min_end_time=end_time,
188 max_end_time=end_time,
189 first_plot_time_stamp=0.0,
190 time_in_between_plots=time_in_between_two_snapshots,
191 periodic_BC=[
False,
False,
False],
195This defines where the output files should go.
196If you omit this, output files are automatically put into the application's folder.
198my_project.set_output_path(
"solution")
201If you only target a sequential execution, you can omit the load balancing.
202However, for a parallel build and execution you need to set load balancing.
203This requires the 'LoadBalancing' toolbox to be built.
204The type of load balancer can greatly impact the speedup and overall performance.
205For an overview of available load balancer refer to the documentation.
207my_project.set_load_balancing(
208 "toolbox::loadbalancing::strategies::SpreadOutOnceGridStagnates",
209 "new ::exahype2::LoadBalancingConfiguration()",
213We need to set the location of our core libraries ('Peano4').
214This helps us to resolve any dependencies.
215Additionally, we specify the build mode which you can also change to a different mode.
217my_project.set_Peano4_installation(
"../../../../", mode=compile_mode)
220We generate and grab the underlying core project of 'Peano4'.
221This gives us access to some functions we want to use to finalise and build this project.
223my_project = my_project.generate_Peano4_project(verbose=
True)
226Finally, we want to build our project.
227First, all of the necessary glue code is generated in the application folder,
228then 'make' is invoked automatically which compiles the generated code and links against our core libraries
229and toolboxes which have been built before.
230You can also always invoke 'make' yourself to compile, or cleanup with 'make clean'.
232my_project.build(make=
True, make_clean_first=
True, throw_away_data_after_build=
True)
235print(my_pde.__str__())