6parser = exahype2.ArgumentParser(
7 "ExaHyPE 2 - Finite Volumes/Finite Differences Coupling Testing Script"
12 degrees_of_freedom=16,
14 periodic_boundary_conditions_x=
False,
15 periodic_boundary_conditions_y=
False,
16 periodic_boundary_conditions_z=
False,
18args = parser.parse_args()
21max_h = 1.1 * min(size) / 3.0**args.min_depth
22min_h = max_h * 3.0 ** (-args.amr_levels)
33if args.dimensions == 3:
34 euler_unknowns[
"rhoW"] = 1
35euler_unknowns[
"rhoE"] = 1
37euler_initial_conditions = f
"""
38 Q[Shortcuts::rho] = 0.1;
39 Q[Shortcuts::rhoU] = 0.0;
40 Q[Shortcuts::rhoV] = 0.0;
42 Q[Shortcuts::rhoW] = 0.0;
44 Q[Shortcuts::rhoE] = ((x(0) < {size[0] / 2}) ? (1.01) : (1.0));
47euler_boundary_conditions =
"""
48 // Reflective boundary conditions
49 Qoutside[Shortcuts::rho] = Qinside[Shortcuts::rho];
50 Qoutside[Shortcuts::rhoU] = -Qinside[Shortcuts::rhoU];
51 Qoutside[Shortcuts::rhoV] = -Qinside[Shortcuts::rhoV];
53 Qoutside[Shortcuts::rhoW] = -Qinside[Shortcuts::rhoW];
55 Qoutside[Shortcuts::rhoE] = Qinside[Shortcuts::rhoE];
58compute_primitive_variables =
r"""
59 const auto irho = 1.0 / Q[Shortcuts::rho];
60 const auto u0 = Q[Shortcuts::rhoU + 0] * irho;
61 const auto u1 = Q[Shortcuts::rhoU + 1] * irho;
63 const auto u2 = Q[Shortcuts::rhoU + 2] * irho;
67 const auto uSq = u0 * u0 + u1 * u1 + u2 * u2;
68 const auto u_n = (normal == 0) ? u0 : (normal == 1) ? u1 : u2;
70 const auto uSq = u0 * u0 + u1 * u1;
71 const auto u_n = (normal == 0) ? u0 : u1;
74 const auto internalE = Q[Shortcuts::rhoE] - 0.5 * Q[Shortcuts::rho] * uSq;
75 const auto p = (GAMMA - 1.0) * internalE;
78euler_max_eigenvalue =
r"""
79 {compute_primitive_variables}
80 const auto speedOfSound = std::sqrt(GAMMA * p * irho);
81 auto result = std::fmax(0.0, std::fabs(u_n - speedOfSound));
82 result = std::fmax(result, std::fabs(u_n + speedOfSound));
85 compute_primitive_variables=compute_primitive_variables
89 {compute_primitive_variables}
91 F[Shortcuts::rho] = Q[Shortcuts::rhoU + normal];
93 F[Shortcuts::rhoU + 0] = Q[Shortcuts::rhoU + 0] * u_n;
94 F[Shortcuts::rhoU + 1] = Q[Shortcuts::rhoU + 1] * u_n;
96 F[Shortcuts::rhoU + 2] = Q[Shortcuts::rhoU + 2] * u_n;
99 F[Shortcuts::rhoU + normal] += p;
101 F[Shortcuts::rhoE] = (Q[Shortcuts::rhoE] + p) * u_n;
103 compute_primitive_variables=compute_primitive_variables
106euler_solver = exahype2.solvers.fv.godunov.GlobalAdaptiveTimeStep(
107 name=
"EulerFVSolver",
108 patch_size=args.degrees_of_freedom,
109 unknowns=euler_unknowns,
110 auxiliary_variables=0,
113 time_step_relaxation=0.5,
116euler_solver.set_implementation(
117 initial_conditions=euler_initial_conditions,
118 boundary_conditions=euler_boundary_conditions,
120 max_eigenvalue=euler_max_eigenvalue,
127diffusion_unknowns = {
131if args.dimensions == 3:
132 diffusion_unknowns[
"rhoW"] = 1
133diffusion_unknowns[
"rhoE"] = 1
134diffusion_auxiliary_variables = {
138diffusion_initial_conditions = f
"""
139 Q[Shortcuts::rhoU] = 0.0;
140 Q[Shortcuts::rhoV] = 0.0;
142 Q[Shortcuts::rhoW] = 0.0;
144 Q[Shortcuts::rhoE] = ((x(0) < {size[0] / 2}) ? (1.01) : (1.0));
145 Q[Shortcuts::rho] = 0.1;
148diffusion_boundary_conditions =
"""
149 // Reflective boundary conditions
150 Qoutside0[Shortcuts::rhoU] = -Qinside[Shortcuts::rhoU];
151 Qoutside0[Shortcuts::rhoV] = -Qinside[Shortcuts::rhoV];
153 Qoutside0[Shortcuts::rhoW] = -Qinside[Shortcuts::rhoW];
155 Qoutside0[Shortcuts::rhoE] = Qinside[Shortcuts::rhoE];
156 Qoutside0[Shortcuts::rho] = Qinside[Shortcuts::rho];
159diffusion_stencil =
"""
160 {{COMPUTE_PRECISION}} velocityLaplacianU = 0.0;
161 {{COMPUTE_PRECISION}} velocityLaplacianV = 0.0;
163 {{COMPUTE_PRECISION}} velocityLaplacianW = 0.0;
166 assertion(Q[Shortcuts::rho] > 0.0);
167 assertion(Q[Shortcuts::rho] == Q[Shortcuts::rho]);
168 const auto irho = 1.0 / Q[Shortcuts::rho];
169 const auto uSquared = (Q[Shortcuts::rhoU] * irho) * (Q[Shortcuts::rhoU] * irho);
170 const auto vSquared = (Q[Shortcuts::rhoV] * irho) * (Q[Shortcuts::rhoV] * irho);
172 const auto wSquared = (Q[Shortcuts::rhoW] * irho) * (Q[Shortcuts::rhoW] * irho);
173 const auto squaredVelocities = uSquared + vSquared + wSquared;
175 const auto squaredVelocities = uSquared + vSquared;
179 velocityLaplacianU += ((QRight0[Shortcuts::rhoU] / QRight0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoU] * irho) + (QLeft0[Shortcuts::rhoU] / QLeft0[Shortcuts::rho])) / (h(0) * h(0));
180 velocityLaplacianV += ((QRight0[Shortcuts::rhoV] / QRight0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoV] * irho) + (QLeft0[Shortcuts::rhoV] / QLeft0[Shortcuts::rho])) / (h(0) * h(0));
182 velocityLaplacianW += ((QRight0[Shortcuts::rhoW] / QRight0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoW] * irho) + (QLeft0[Shortcuts::rhoW] / QLeft0[Shortcuts::rho])) / (h(0) * h(0));
186 velocityLaplacianU += ((QTop0[Shortcuts::rhoU] / QTop0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoU] * irho) + (QDown0[Shortcuts::rhoU] / QDown0[Shortcuts::rho])) / (h(1) * h(1));
187 velocityLaplacianV += ((QTop0[Shortcuts::rhoV] / QTop0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoV] * irho) + (QDown0[Shortcuts::rhoV] / QDown0[Shortcuts::rho])) / (h(1) * h(1));
189 velocityLaplacianW += ((QTop0[Shortcuts::rhoW] / QTop0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoW] * irho) + (QDown0[Shortcuts::rhoW] / QDown0[Shortcuts::rho])) / (h(1) * h(1));
194 velocityLaplacianU += ((QFront0[Shortcuts::rhoU] / QFront0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoU] * irho) + (QBack0[Shortcuts::rhoU] / QBack0[Shortcuts::rho])) / (h(2) * h(2));
195 velocityLaplacianV += ((QFront0[Shortcuts::rhoV] / QFront0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoV] * irho) + (QBack0[Shortcuts::rhoV] / QBack0[Shortcuts::rho])) / (h(2) * h(2));
196 velocityLaplacianW += ((QFront0[Shortcuts::rhoW] / QFront0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoW] * irho) + (QBack0[Shortcuts::rhoW] / QBack0[Shortcuts::rho])) / (h(2) * h(2));
199 QNew[Shortcuts::rhoU] = Q[Shortcuts::rhoU] + dt * Q[Shortcuts::rho] * KINEMATIC_VISCOSITY * velocityLaplacianU;
200 QNew[Shortcuts::rhoV] = Q[Shortcuts::rhoV] + dt * Q[Shortcuts::rho] * KINEMATIC_VISCOSITY * velocityLaplacianV;
202 QNew[Shortcuts::rhoW] = Q[Shortcuts::rhoW] + dt * Q[Shortcuts::rho] * KINEMATIC_VISCOSITY * velocityLaplacianW;
205 auto temperature = [](const double* Q) {
206 const auto irho = 1 / Q[Shortcuts::rho];
207 // Calculate temperature based on energy density
208 const auto uSquared = (Q[Shortcuts::rhoU] * irho) * (Q[Shortcuts::rhoU] * irho);
209 const auto vSquared = (Q[Shortcuts::rhoV] * irho) * (Q[Shortcuts::rhoV] * irho);
211 const auto wSquared = (Q[Shortcuts::rhoW] * irho) * (Q[Shortcuts::rhoW] * irho);
212 const auto squaredVelocities = uSquared + vSquared + wSquared;
214 const auto squaredVelocities = uSquared + vSquared;
216 const auto internalEnergy = Q[Shortcuts::rhoE] - 0.5 * (Q[Shortcuts::rho] * squaredVelocities);
217 const auto temperature = (internalEnergy * (GAMMA - 1.0)) / (Q[Shortcuts::rho] * UNIVERSAL_GAS_CONSTANT);
221 {{COMPUTE_PRECISION}} temperatureLaplacian = 0.0;
222 const auto temperatureQ = temperature(Q);
223 const auto doubleTemperatureQ = 2 * temperatureQ;
226 temperatureLaplacian += (temperature(QRight0) - doubleTemperatureQ + temperature(QLeft0)) / (h(0) * h(0));
228 temperatureLaplacian += (temperature(QTop0) - doubleTemperatureQ + temperature(QDown0)) / (h(1) * h(1));
231 temperatureLaplacian += (temperature(QFront0) - doubleTemperatureQ + temperature(QBack0)) / (h(2) * h(2));
234 const auto newPressure = Q[Shortcuts::rho] * UNIVERSAL_GAS_CONSTANT * (temperatureQ + dt * THERMAL_DIFFUSIVITY * temperatureLaplacian);
235 QNew[Shortcuts::rhoE] = newPressure / (GAMMA - 1.0) + 0.5 * Q[Shortcuts::rho] * squaredVelocities;
236 QNew[Shortcuts::rho] = Q[Shortcuts::rho];
239diffusion_solver = exahype2.solvers.fd.GlobalAdaptiveTimeStep(
240 name=
"DiffusionSolver",
241 patch_size=args.degrees_of_freedom,
242 unknowns=diffusion_unknowns,
243 auxiliary_variables=diffusion_auxiliary_variables,
246 time_step_relaxation=0.5,
247 solvers_before_in_coupling=[euler_solver],
251diffusion_solver.set_implementation(
252 initial_conditions=diffusion_initial_conditions,
253 boundary_conditions=diffusion_boundary_conditions,
254 solver=diffusion_stencil,
264diffusion_solver._compute_time_step_size = (
266 const double timeStepSize = repositories::"""
267 + euler_solver.get_name_of_global_instance()
268 +
""".getAdmissibleTimeStepSize();
272number_of_variables_euler = euler_solver.auxiliary_variables + euler_solver.unknowns
273number_of_variables_diffusion = (
274 diffusion_solver.auxiliary_variables + diffusion_solver.unknowns
279euler_solver.postprocess_updated_patch += f
"""// Copy density, energy, and momenta
280 ::toolbox::blockstructured::copyUnknown(
281 {euler_solver.patch_size}, // no of unknowns per dimension
282 fineGridCell{euler_solver.name}Q.data(), // source
283 {euler_solver.variable_names.index("rho")}, // density in source
284 {number_of_variables_euler}, // unknowns in source (incl material parameters)
285 0, // no overlap/halo here
286 fineGridCell{diffusion_solver.name}Q.data(), // dest
287 {diffusion_solver.variable_names.index("rho")}, // density in dest
288 {number_of_variables_diffusion}, // unknowns in dest (incl material parameters)
289 0 // no overlap/halo here
292 ::toolbox::blockstructured::copyUnknown(
293 {euler_solver.patch_size}, // no of unknowns per dimension
294 fineGridCell{euler_solver.name}Q.data(), // source
295 {euler_solver.variable_names.index("rhoU")}, // x-momentum in source
296 {number_of_variables_euler}, // unknowns in source (incl material parameters)
297 0, // no overlap/halo here
298 fineGridCell{diffusion_solver.name}Q.data(), // dest
299 {diffusion_solver.variable_names.index("rhoU")}, // x-momentum in dest
300 {number_of_variables_diffusion}, // unknowns in dest (incl material parameters)
301 0 // no overlap/halo here
304 ::toolbox::blockstructured::copyUnknown(
305 {euler_solver.patch_size}, // no of unknowns per dimension
306 fineGridCell{euler_solver.name}Q.data(), // source
307 {euler_solver.variable_names.index("rhoV")}, // y-momentum in source
308 {number_of_variables_euler}, // unknowns in source (incl material parameters)
309 0, // no overlap/halo here
310 fineGridCell{diffusion_solver.name}Q.data(), // dest
311 {diffusion_solver.variable_names.index("rhoV")}, // y-momentum in dest
312 {number_of_variables_diffusion}, // unknowns in dest (incl material parameters)
313 0 // no overlap/halo here
316 ::toolbox::blockstructured::copyUnknown(
317 {euler_solver.patch_size}, // no of unknowns per dimension
318 fineGridCell{euler_solver.name}Q.data(), // source
319 {euler_solver.variable_names.index("rhoE")}, // energy in source
320 {number_of_variables_euler}, // unknowns in source (incl material parameters)
321 0, // no overlap/halo here
322 fineGridCell{diffusion_solver.name}Q.data(), // dest
323 {diffusion_solver.variable_names.index("rhoE")}, // energy in dest
324 {number_of_variables_diffusion}, // unknowns in dest (incl material parameters)
325 0 // no overlap/halo here
329if args.dimensions == 3:
330 euler_solver.postprocess_updated_patch += f
"""
332 ::toolbox::blockstructured::copyUnknown(
333 {euler_solver.patch_size}, // no of unknowns per dimension
334 fineGridCell{euler_solver.name}Q.data(), // source
335 {euler_solver.variable_names.index("rhoW")}, // z-momentum in source
336 {number_of_variables_euler}, // unknowns in source (incl material parameters)
337 0, // no overlap/halo here
338 fineGridCell{diffusion_solver.name}Q.data(), // dest
339 {diffusion_solver.variable_names.index("rhoW")}, // z-momentum in dest
340 {number_of_variables_diffusion}, // unknowns in dest (incl material parameters)
341 0 // no overlap/halo here
346euler_solver.add_user_action_set_includes(
'#include "toolbox/blockstructured/Copy.h"\n')
350diffusion_solver.postprocess_updated_patch += f
"""// Copy energy and momenta
351 ::toolbox::blockstructured::copyUnknown(
352 {diffusion_solver.patch_size}, // no of unknowns per dimension
353 fineGridCell{diffusion_solver.name}Q.data(), // source
354 {diffusion_solver.variable_names.index("rhoU")}, // x-momentum in source
355 {number_of_variables_diffusion}, // unknowns in source (incl material parameters)
356 0, // no overlap/halo here
357 fineGridCell{euler_solver.name}Q.data(), // dest
358 {euler_solver.variable_names.index("rhoU")}, // x-momentum in dest
359 {number_of_variables_euler}, // unknowns in dest (incl material parameters)
360 0 // no overlap/halo here
363 ::toolbox::blockstructured::copyUnknown(
364 {diffusion_solver.patch_size}, // no of unknowns per dimension
365 fineGridCell{diffusion_solver.name}Q.data(), // source
366 {diffusion_solver.variable_names.index("rhoV")}, // y-momentum in source
367 {number_of_variables_diffusion}, // unknowns in source (incl material parameters)
368 0, // no overlap/halo here
369 fineGridCell{euler_solver.name}Q.data(), // dest
370 {euler_solver.variable_names.index("rhoV")}, // y-momentum in dest
371 {number_of_variables_euler}, // unknowns in dest (incl material parameters)
372 0 // no overlap/halo here
375 ::toolbox::blockstructured::copyUnknown(
376 {diffusion_solver.patch_size}, // no of unknowns per dimension
377 fineGridCell{diffusion_solver.name}Q.data(), // source
378 {diffusion_solver.variable_names.index("rhoE")}, // energy in source
379 {number_of_variables_diffusion}, // unknowns in source (incl material parameters)
380 0, // no overlap/halo here
381 fineGridCell{euler_solver.name}Q.data(), // dest
382 {euler_solver.variable_names.index("rhoE")}, // energy in dest
383 {number_of_variables_euler}, // unknowns in dest (incl material parameters)
384 0 // no overlap/halo here
388if args.dimensions == 3:
389 diffusion_solver.postprocess_updated_patch += f
"""
391 ::toolbox::blockstructured::copyUnknown(
392 {diffusion_solver.patch_size}, // no of unknowns per dimension
393 fineGridCell{diffusion_solver.name}Q.data(), // source
394 {diffusion_solver.variable_names.index("rhoW")}, // z-momentum in source
395 {number_of_variables_diffusion}, // unknowns in source (incl material parameters)
396 0, // no overlap/halo here
397 fineGridCell{euler_solver.name}Q.data(), // dest
398 {euler_solver.variable_names.index("rhoW")}, // z-momentum in dest
399 {number_of_variables_euler}, // unknowns in dest (incl material parameters)
400 0 // no overlap/halo here
405diffusion_solver.add_user_action_set_includes(
406 '#include "toolbox/blockstructured/Copy.h"\n'
409euler_solver.last_solver = diffusion_solver
415project = exahype2.Project(
416 namespace=[
"tests",
"exahype2",
"fvfd"],
419 executable=
"ExaHyPE",
422project.add_solver(euler_solver)
423project.add_solver(diffusion_solver)
425if args.number_of_snapshots <= 0:
426 time_in_between_plots = 0.0
428 time_in_between_plots = args.end_time / args.number_of_snapshots
429 project.set_output_path(args.output)
431project.set_global_simulation_parameters(
432 dimensions=args.dimensions,
433 size=size[0 : args.dimensions],
434 offset=[0.0, 0.0, 0.0][0 : args.dimensions],
435 min_end_time=args.end_time,
436 max_end_time=args.end_time,
437 first_plot_time_stamp=0.0,
438 time_in_between_plots=time_in_between_plots,
440 args.periodic_boundary_conditions_x,
441 args.periodic_boundary_conditions_y,
442 args.periodic_boundary_conditions_z,
446project.set_load_balancer(
"new ::exahype2::LoadBalancingConfiguration")
447project.set_build_mode(mode=peano4.output.string_to_mode(args.build_mode))
448project = project.generate_Peano4_project(verbose=
False)
449project.output.makefile.add_CXX_flag(
"-DGAMMA=1.4")
450project.output.makefile.add_CXX_flag(
"-DUNIVERSAL_GAS_CONSTANT=8.31")
451project.output.makefile.add_CXX_flag(
"-DKINEMATIC_VISCOSITY=100")
452project.output.makefile.add_CXX_flag(
"-DTHERMAL_DIFFUSIVITY=150")
453project.build(make=
True, make_clean_first=
True, throw_away_data_after_build=
True)