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