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.
16 We specify the space dimensions here.
17 We support either 2- or 3-dimensional problems.
22 The number of finite volumes per axis in one patch.
27 The number of levels the mesh is refined.
32 The simulation end time.
37 Choose domain size and offset.
39 size = [20.0, 20.0, 20.0]
40 offset = [-5.0, 0.0, 0.0]
43 Choose how often a snapshot is written.
45 time_in_between_two_snapshots = end_time / 10
49 Switch between 'Release', 'Debug', 'Asserts', 'Trace', 'Stats'.
51 compile_mode =
"Release"
54 We first create a new ExaHyPE 2 project.
55 For this, we specify the (nested) namespaces, the name of our main file and our executable name.
57 my_project = exahype2.Project(
58 namespace=[
"tutorials",
"symhype",
"elastic"],
59 project_name=
"Elastic",
65 Add the Finite Volumes solver using named arguments.
66 This is the way you can add further PDE terms.
67 This requires the 'BlockStructured' toolbox and 'ExaHyPE' to be built.
69 my_solver = exahype2.solvers.fv.godunov.GlobalAdaptiveTimeStep(
71 patch_size=patch_size,
74 3
if dimensions == 2
else 6
76 auxiliary_variables=0,
77 min_volume_h=(1.1 *
min(size[0:dimensions]) / (3.0**depth)),
78 max_volume_h=(1.1 *
min(size[0:dimensions]) / (3.0**depth)),
79 time_step_relaxation=0.5,
83 We want to define our PDE symbolically.
85 my_pde = symhype.FirstOrderConservativePDEFormulation(
86 unknowns=dimensions + (3
if dimensions == 2
else 6),
87 auxiliary_variables=0,
88 dimensions=dimensions,
93 v = my_pde.name_Q_entries(0, dimensions,
"v")
95 sigma = my_pde.name_Q_entries(dimensions, 3
if dimensions == 2
else 6,
"sigma")
98 rho = sympy.symbols(
"rho")
99 cp = sympy.symbols(
"cp")
100 cs = sympy.symbols(
"cs")
104 lamb = rho * cp * cp - 2.0 * mu
108 Define the fluxes in each spatial direction.
109 The overall conservative form is:
110 ∂ₜQ + ∂ₓ(F_x(Q)) + ∂ᵧ(F_y(Q)) + ∂𝓏(F_z(Q)) = S
111 where Q = [v_x, v_y, v_z, σ_xx, σ_yy, σ_zz, σ_xy, σ_xz, σ_yz]^T.
116 my_pde.F[0, 0] = -1.0 / rho * sigma[0]
117 my_pde.F[1, 0] = -1.0 / rho * sigma[3]
118 my_pde.F[2, 0] = -1.0 / rho * sigma[4]
121 my_pde.F[3, 0] = -(lamb + 2.0 * mu) * v[0]
122 my_pde.F[4, 0] = -lamb * v[0]
123 my_pde.F[5, 0] = -lamb * v[0]
124 my_pde.F[6, 0] = -mu * v[1]
125 my_pde.F[7, 0] = -mu * v[2]
130 my_pde.F[0, 1] = -1.0 / rho * sigma[3]
131 my_pde.F[1, 1] = -1.0 / rho * sigma[1]
132 my_pde.F[2, 1] = -1.0 / rho * sigma[5]
135 my_pde.F[3, 1] = -lamb * v[1]
136 my_pde.F[4, 1] = -(lamb + 2.0 * mu) * v[1]
137 my_pde.F[5, 1] = -lamb * v[1]
138 my_pde.F[6, 1] = -mu * v[0]
140 my_pde.F[8, 1] = -mu * v[2]
144 my_pde.F[0, 2] = -1.0 / rho * sigma[4]
145 my_pde.F[1, 2] = -1.0 / rho * sigma[5]
146 my_pde.F[2, 2] = -1.0 / rho * sigma[2]
149 my_pde.F[3, 2] = -lamb * v[2]
150 my_pde.F[4, 2] = -lamb * v[2]
151 my_pde.F[5, 2] = -(lamb + 2.0 * mu) * v[2]
153 my_pde.F[7, 2] = -mu * v[0]
154 my_pde.F[8, 2] = -mu * v[1]
157 Define the eigenvalues.
158 For a 3D elastic system the characteristic speeds in a given
160 { cp, cs, cs, 0, 0, 0, -cs, -cs, -cp }
162 cp = sqrt((λ+2μ)/ρ) is the P-wave (compressional) speed,
163 cs = sqrt(μ/ρ) is the S-wave (shear) speed.
166 my_pde.eigenvalues[0] = cp
167 my_pde.eigenvalues[1] = cs
168 my_pde.eigenvalues[2] = cs
169 my_pde.eigenvalues[3] = 0
170 my_pde.eigenvalues[4] = 0
171 my_pde.eigenvalues[5] = 0
172 my_pde.eigenvalues[6] = -cs
173 my_pde.eigenvalues[7] = -cs
174 my_pde.eigenvalues[8] = -cp
177 my_pde.F[0, 0] = -1.0 / rho * sigma[0]
178 my_pde.F[1, 0] = -1.0 / rho * sigma[2]
179 my_pde.F[2, 0] = -(2.0 * mu + lamb) * v[0]
180 my_pde.F[3, 0] = -lamb * v[0]
181 my_pde.F[4, 0] = -mu * v[1]
183 my_pde.F[0, 1] = -1.0 / rho * sigma[2]
184 my_pde.F[1, 1] = -1.0 / rho * sigma[1]
185 my_pde.F[2, 1] = -lamb * v[1]
186 my_pde.F[3, 1] = -(2.0 * mu + lamb) * v[1]
187 my_pde.F[4, 1] = -mu * v[0]
190 my_pde.eigenvalues[0] = cp
191 my_pde.eigenvalues[1] = cs
192 my_pde.eigenvalues[2] = 0
193 my_pde.eigenvalues[3] = -cs
194 my_pde.eigenvalues[4] = -cp
197 Since 'my_pde' only holds the PDE without initial- or boundary conditions,
198 we still need to properly define initial- and boundary conditions.
199 This gives us then a complete description of a 'scenario'.
201 for i
in range(dimensions + (3
if dimensions == 2
else 6)):
202 my_pde.initial_values[i] = 0
203 my_pde.boundary_values[i] = 0
206 Define a source term.
207 Here we add a time-dependent point force applied to one of the
208 shear stress components (σ_xy in this case).
210 t0 = sympy.symbols(
"t0")
211 M0 = sympy.symbols(
"M0")
212 t = sympy.symbols(
"t")
213 force = M0 * t / (t0 * t0) * sympy.exp(-t / t0)
215 max_h = sympy.symbols(
"MaxAdmissibleVolumeH")
218 point_source = sympy.sqrt(
219 (10 - my_pde.x[0]) ** 2 + (10 - my_pde.x[1]) ** 2 + (10 - my_pde.x[2]) ** 2
223 my_pde.sources[0] = 0
224 my_pde.sources[1] = 0
225 my_pde.sources[2] = 0
226 my_pde.sources[3] = 0
227 my_pde.sources[4] = 0
228 my_pde.sources[5] = 0
229 my_pde.sources[6] = sympy.Piecewise((force, point_source <= max_h), (0,
True))
230 my_pde.sources[7] = 0
231 my_pde.sources[8] = 0
233 point_source = sympy.sqrt((10 - my_pde.x[0]) ** 2 + (10 - my_pde.x[1]) ** 2)
235 my_pde.sources[0] = 0
236 my_pde.sources[1] = 0
237 my_pde.sources[2] = 0
238 my_pde.sources[3] = 0
239 my_pde.sources[4] = sympy.Piecewise((force, point_source <= max_h), (0,
True))
242 my_pde.substitute_expression(rho, 2.7)
243 my_pde.substitute_expression(cp, 6.0)
244 my_pde.substitute_expression(cs, 3.464)
245 my_pde.substitute_expression(t0, 0.1)
246 my_pde.substitute_expression(M0, 1000.0)
249 Specify which implementation our solvers uses.
250 Here we want to set the implementation we get from our symbolically defined PDE,
251 i.e., we get the C++ implementation which is generated by SymHyPE.
253 my_solver.set_implementation(
254 initial_conditions=my_pde.implementation_of_initial_conditions(),
255 boundary_conditions=my_pde.implementation_of_boundary_conditions(),
256 flux=my_pde.implementation_of_flux(),
257 max_eigenvalue=my_pde.implementation_of_max_eigenvalue(),
258 source_term=my_pde.implementation_of_sources(),
262 To see which variables (unknowns + auxiliary variables) we can visualise,
263 let's add a plot description for the variables to our solver.
265 my_solver.plot_description = my_pde.unknown_identifier_for_plotter()
268 Add the solver to our project
270 my_project.add_solver(my_solver)
273 Configure some global parameters
275 my_project.set_global_simulation_parameters(
276 dimensions=dimensions,
277 size=size[0:dimensions],
278 offset=offset[0:dimensions],
279 min_end_time=end_time,
280 max_end_time=end_time,
281 first_plot_time_stamp=0.0,
282 time_in_between_plots=time_in_between_two_snapshots,
283 periodic_BC=[
False,
False,
False],
287 This defines where the output files should go.
288 If you omit this, output files are automatically put into the application's folder.
290 my_project.set_output_path(
"solutions")
293 Configure load balancer for parallel execution.
295 my_project.set_load_balancer(
"new ::exahype2::LoadBalancingConfiguration")
298 We need to set the location of our core libraries ('Peano4').
299 This helps us to resolve any dependencies.
300 Additionally, we specify the build mode which you can also change to a different mode.
302 my_project.set_Peano4_installation(
303 "../../../", mode=peano4.output.string_to_mode(compile_mode)
307 We generate and grab the underlying core project of 'Peano4'.
308 This gives us access to some functions we want to use to finalise and build this project.
310 my_project = my_project.generate_Peano4_project(verbose=
False)
313 Finally, we want to build our project.
314 First, all of the necessary glue code is generated in the application folder,
315 then 'make' is invoked automatically which compiles the generated code and links against our core libraries
316 and toolboxes which have been built before.
317 You can also always invoke 'make' yourself to compile, or cleanup with 'make clean'.
319 my_project.build(make=
True, make_clean_first=
True, throw_away_data_after_build=
True)
322 print(my_pde.__str__())
static double min(double const x, double const y)