Peano
Loading...
Searching...
No Matches
euler.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 os
4import sys
5import sympy
6import subprocess
7
8"""
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.
13"""
14import peano4
15import exahype2
16
17"""
18We specify the space dimensions here.
19We support either 2- or 3-dimensional problems.
20"""
21dimensions = 2
22
23"""
24The number of finite volumes per axis in one patch.
25"""
26patch_size = 16
27
28"""
29The size of a finite volume/cell per axis.
30"""
31volume_size = 0.01
32
33"""
34The simulation end time.
35"""
36end_time = 1.0
37
38"""
39Choose domain size and offset.
40"""
41size = [1.0, 1.0, 1.0]
42offset = [0.0, 0.0, 0.0]
43
44"""
45Choose how often a snapshot is written.
46"""
47time_in_between_two_snapshots = end_time / 100
48# time_in_between_two_snapshots = 0 # Set to 0 to disable I/O
49
50"""
51Switch between 'Release', 'Debug', 'Asserts', 'Trace', 'Stats'.
52"""
53compile_mode = peano4.output.CompileMode.Release
54
55"""
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.
58"""
59my_project = exahype2.Project(
60 namespace=["tutorials", "exahype2", "euler"],
61 project_name="Euler",
62 directory=".",
63 executable="Euler",
64)
65
66"""
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.
71"""
73 name="Euler",
74 patch_size=patch_size,
75 unknowns=dimensions + 2, # [rho, u, v, (w), e]
76 auxiliary_variables=0, # This could be something alike material parameters. Not required for Euler.
77 min_volume_h=volume_size,
78 max_volume_h=volume_size,
79 time_step_relaxation=0.5,
80)
81
82"""
83We want to define our PDE symbolically.
84For this we use the 'symhype' package (not to be confused with 'sympy') from 'ExaHyPE'.
85"""
87 unknowns=dimensions + 2, auxiliary_variables=0, dimensions=dimensions
88)
89
90"""
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.
93"""
94gamma = sympy.symbols("gamma")
95# First scalar is density
96rho = my_pde.name_Q_entry(0, "rho")
97# Momentum: Entries 1-dimensions (C counting style) holds j vector
98# (Note: To get the velocities we need to divide with the density)
99j = my_pde.name_Q_entries(1, dimensions, "j")
100# Energy
101E = my_pde.name_Q_entry(dimensions + 1, "E")
102# Pressure
103p = (gamma - 1) * (E - 1 / 2 * exahype2.symhype.dot(j, j) / rho)
104
105"""
106Define the equation system
107"""
108# Flux [unknowns, dimensions]
109my_pde.F[0, :] = j
110my_pde.F[1 : dimensions + 1, :] = 1 / rho * exahype2.symhype.outer(
111 j, j
112) + p * sympy.eye(dimensions)
113my_pde.F[dimensions + 1, :] = 1 / rho * j * (E + p)
114
115# Eigenvalues [unknowns, dimensions]
116c = sympy.sqrt(gamma * p / rho)
117u = j / rho # Velocities
118if dimensions == 3:
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]
124else:
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]
129
130my_pde.substitute_expression(gamma, 1.4)
131
132"""
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'.
136"""
137
138# Initial conditions as specified in the documentation.
139my_pde.initial_values[0] = 1 # rho
140my_pde.initial_values[1] = 0 # u
141my_pde.initial_values[2] = 0 # v
142
143if dimensions == 2:
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)
147 ) # e
148else:
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
151 )
152 my_pde.initial_values[3] = 0 # w
153 my_pde.initial_values[4] = sympy.Piecewise(
154 (1.0, volume_centre < 0.2), (1.01, True)
155 ) # e
156
157"""
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.
161"""
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(),
167)
168
169"""
170To see which variables (unknowns + auxiliary variables) we can visualise,
171let's add a plot description for the variables to our solver.
172"""
173my_solver.plot_description = my_pde.unknown_identifier_for_plotter()
174
175"""
176Add the solver to our project
177"""
178my_project.add_solver(my_solver)
179
180"""
181Configure some global parameters
182"""
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],
192)
193
194"""
195This defines where the output files should go.
196If you omit this, output files are automatically put into the application's folder.
197"""
198my_project.set_output_path("solution")
199
200"""
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.
206"""
207my_project.set_load_balancing(
208 "toolbox::loadbalancing::strategies::SpreadOutOnceGridStagnates",
209 "new ::exahype2::LoadBalancingConfiguration()",
210)
211
212"""
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.
216"""
217my_project.set_Peano4_installation("../../../../", mode=compile_mode)
218
219"""
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.
222"""
223my_project = my_project.generate_Peano4_project(verbose=True)
224
225"""
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'.
231"""
232my_project.build(make=True, make_clean_first=True, throw_away_data_after_build=True)
233
234print("\nPDE is: ")
235print(my_pde.__str__())
236print(my_solver)
237print(my_project)
ExaHyPE 2 project.
Definition Project.py:14
Helper class to model a hyperbolic PDE in first-order conservative formulation.