6parser = exahype2.ArgumentParser(
7 "ExaHyPE 2 - Finite Volumes/Finite Differences Coupling Testing Script"
12 degrees_of_freedom=16,
14 number_of_snapshots=0,
15 periodic_boundary_conditions_x=
False,
16 periodic_boundary_conditions_y=
False,
17 periodic_boundary_conditions_z=
False,
19args = parser.parse_args()
22max_h = 1.1 * min(size) / 3.0**args.min_depth
23min_h = max_h * 3.0 ** (-args.amr_levels)
34if args.dimensions == 3:
35 euler_unknowns[
"rhoW"] = 1
36euler_unknowns[
"rhoE"] = 1
38euler_initial_conditions = f
"""
39 Q[Shortcuts::rho] = 0.1;
40 Q[Shortcuts::rhoU] = 0.0;
41 Q[Shortcuts::rhoV] = 0.0;
43 Q[Shortcuts::rhoW] = 0.0;
45 Q[Shortcuts::rhoE] = ((x(0) < {size[0] / 2}) ? (1.01) : (1.0));
48euler_boundary_conditions =
"""
49 // Reflective boundary conditions
50 Qoutside[Shortcuts::rho] = Qinside[Shortcuts::rho];
51 Qoutside[Shortcuts::rhoU] = -Qinside[Shortcuts::rhoU];
52 Qoutside[Shortcuts::rhoV] = -Qinside[Shortcuts::rhoV];
54 Qoutside[Shortcuts::rhoW] = -Qinside[Shortcuts::rhoW];
56 Qoutside[Shortcuts::rhoE] = Qinside[Shortcuts::rhoE];
59compute_primitive_variables =
r"""
60 const auto irho = 1.0 / Q[Shortcuts::rho];
61 const auto u0 = Q[Shortcuts::rhoU + 0] * irho;
62 const auto u1 = Q[Shortcuts::rhoU + 1] * irho;
64 const auto u2 = Q[Shortcuts::rhoU + 2] * irho;
68 const auto uSq = u0 * u0 + u1 * u1 + u2 * u2;
69 const auto u_n = (normal == 0) ? u0 : (normal == 1) ? u1 : u2;
71 const auto uSq = u0 * u0 + u1 * u1;
72 const auto u_n = (normal == 0) ? u0 : u1;
75 const auto internalE = Q[Shortcuts::rhoE] - 0.5 * Q[Shortcuts::rho] * uSq;
76 const auto p = (GAMMA - 1.0) * internalE;
79euler_max_eigenvalue =
r"""
80 {compute_primitive_variables}
81 const auto speedOfSound = std::sqrt(GAMMA * p * irho);
82 auto result = std::fmax(0.0, std::fabs(u_n - speedOfSound));
83 result = std::fmax(result, std::fabs(u_n + speedOfSound));
86 compute_primitive_variables=compute_primitive_variables
90 {compute_primitive_variables}
92 F[Shortcuts::rho] = Q[Shortcuts::rhoU + normal];
94 F[Shortcuts::rhoU + 0] = Q[Shortcuts::rhoU + 0] * u_n;
95 F[Shortcuts::rhoU + 1] = Q[Shortcuts::rhoU + 1] * u_n;
97 F[Shortcuts::rhoU + 2] = Q[Shortcuts::rhoU + 2] * u_n;
100 F[Shortcuts::rhoU + normal] += p;
102 F[Shortcuts::rhoE] = (Q[Shortcuts::rhoE] + p) * u_n;
104 compute_primitive_variables=compute_primitive_variables
107euler_solver = exahype2.solvers.fv.godunov.GlobalAdaptiveTimeStep(
108 name=
"EulerFVSolver",
109 patch_size=args.degrees_of_freedom,
110 unknowns=euler_unknowns,
111 auxiliary_variables=0,
114 time_step_relaxation=0.5,
117euler_solver.set_implementation(
118 initial_conditions=euler_initial_conditions,
119 boundary_conditions=euler_boundary_conditions,
121 max_eigenvalue=euler_max_eigenvalue,
128diffusion_unknowns = {
132if args.dimensions == 3:
133 diffusion_unknowns[
"rhoW"] = 1
134diffusion_unknowns[
"rhoE"] = 1
135diffusion_auxiliary_variables = {
139diffusion_initial_conditions = f
"""
140 Q[Shortcuts::rhoU] = 0.0;
141 Q[Shortcuts::rhoV] = 0.0;
143 Q[Shortcuts::rhoW] = 0.0;
145 Q[Shortcuts::rhoE] = ((x(0) < {size[0] / 2}) ? (1.01) : (1.0));
146 Q[Shortcuts::rho] = 0.1;
149diffusion_boundary_conditions =
"""
150 // Reflective boundary conditions
151 Qoutside0[Shortcuts::rhoU] = -Qinside[Shortcuts::rhoU];
152 Qoutside0[Shortcuts::rhoV] = -Qinside[Shortcuts::rhoV];
154 Qoutside0[Shortcuts::rhoW] = -Qinside[Shortcuts::rhoW];
156 Qoutside0[Shortcuts::rhoE] = Qinside[Shortcuts::rhoE];
157 Qoutside0[Shortcuts::rho] = Qinside[Shortcuts::rho];
160diffusion_stencil =
"""
161 {{COMPUTE_PRECISION}} velocityLaplacianU = 0.0;
162 {{COMPUTE_PRECISION}} velocityLaplacianV = 0.0;
164 {{COMPUTE_PRECISION}} velocityLaplacianW = 0.0;
167 const auto irho = 1.0 / Q[Shortcuts::rho];
168 const auto uSquared = (Q[Shortcuts::rhoU] * irho) * (Q[Shortcuts::rhoU] * irho);
169 const auto vSquared = (Q[Shortcuts::rhoV] * irho) * (Q[Shortcuts::rhoV] * irho);
171 const auto wSquared = (Q[Shortcuts::rhoW] * irho) * (Q[Shortcuts::rhoW] * irho);
172 const auto squaredVelocities = uSquared + vSquared + wSquared;
174 const auto squaredVelocities = uSquared + vSquared;
178 velocityLaplacianU += ((QRight0[Shortcuts::rhoU] / QRight0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoU] * irho) + (QLeft0[Shortcuts::rhoU] / QLeft0[Shortcuts::rho])) / (h(0) * h(0));
179 velocityLaplacianV += ((QRight0[Shortcuts::rhoV] / QRight0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoV] * irho) + (QLeft0[Shortcuts::rhoV] / QLeft0[Shortcuts::rho])) / (h(0) * h(0));
181 velocityLaplacianW += ((QRight0[Shortcuts::rhoW] / QRight0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoW] * irho) + (QLeft0[Shortcuts::rhoW] / QLeft0[Shortcuts::rho])) / (h(0) * h(0));
185 velocityLaplacianU += ((QTop0[Shortcuts::rhoU] / QTop0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoU] * irho) + (QDown0[Shortcuts::rhoU] / QDown0[Shortcuts::rho])) / (h(0) * h(0));
186 velocityLaplacianV += ((QTop0[Shortcuts::rhoV] / QTop0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoV] * irho) + (QDown0[Shortcuts::rhoV] / QDown0[Shortcuts::rho])) / (h(0) * h(0));
188 velocityLaplacianW += ((QTop0[Shortcuts::rhoW] / QTop0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoW] * irho) + (QDown0[Shortcuts::rhoW] / QDown0[Shortcuts::rho])) / (h(0) * h(0));
193 velocityLaplacianU += ((QFront0[Shortcuts::rhoU] / QFront0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoU] * irho) + (QBack0[Shortcuts::rhoU] / QBack0[Shortcuts::rho])) / (h(0) * h(0));
194 velocityLaplacianV += ((QFront0[Shortcuts::rhoV] / QFront0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoV] * irho) + (QBack0[Shortcuts::rhoV] / QBack0[Shortcuts::rho])) / (h(0) * h(0));
195 velocityLaplacianW += ((QFront0[Shortcuts::rhoW] / QFront0[Shortcuts::rho]) - 2 * (Q[Shortcuts::rhoW] * irho) + (QBack0[Shortcuts::rhoW] / QBack0[Shortcuts::rho])) / (h(0) * h(0));
198 QNew[Shortcuts::rhoU] = Q[Shortcuts::rhoU] + dt * Q[Shortcuts::rho] * KINEMATIC_VISCOSITY * velocityLaplacianU;
199 QNew[Shortcuts::rhoV] = Q[Shortcuts::rhoV] + dt * Q[Shortcuts::rho] * KINEMATIC_VISCOSITY * velocityLaplacianV;
201 QNew[Shortcuts::rhoW] = Q[Shortcuts::rhoW] + dt * Q[Shortcuts::rho] * KINEMATIC_VISCOSITY * velocityLaplacianW;
204 auto temperature = [](const double* Q) {
205 const auto irho = 1 / Q[Shortcuts::rho];
206 // Calculate temperature based on energy density
207 const auto uSquared = (Q[Shortcuts::rhoU] * irho) * (Q[Shortcuts::rhoU] * irho);
208 const auto vSquared = (Q[Shortcuts::rhoV] * irho) * (Q[Shortcuts::rhoV] * irho);
210 const auto wSquared = (Q[Shortcuts::rhoW] * irho) * (Q[Shortcuts::rhoW] * irho);
211 const auto squaredVelocities = uSquared + vSquared + wSquared;
213 const auto squaredVelocities = uSquared + vSquared;
215 const auto internalEnergy = Q[Shortcuts::rhoE] - 0.5 * (Q[Shortcuts::rho] * squaredVelocities);
216 const auto temperature = (internalEnergy * (GAMMA - 1.0)) / (Q[Shortcuts::rho] * UNIVERSAL_GAS_CONSTANT);
220 {{COMPUTE_PRECISION}} temperatureLaplacian = 0.0;
221 const auto temperatureQ = temperature(Q);
222 const auto doubleTemperatureQ = 2 * temperatureQ;
225 temperatureLaplacian += (temperature(QRight0) - doubleTemperatureQ + temperature(QLeft0)) / (h(0) * h(0));
227 temperatureLaplacian += (temperature(QTop0) - doubleTemperatureQ + temperature(QDown0)) / (h(1) * h(1));
229 // z-direction temperatureLaplacian += (temperature(QFront0) - doubleTemperatureQ + temperature(QBack0)) / (h(2) * h(2));
232 const auto newPressure = Q[Shortcuts::rho] * UNIVERSAL_GAS_CONSTANT * (temperatureQ + dt * THERMAL_DIFFUSIVITY * temperatureLaplacian);
233 QNew[Shortcuts::rhoE] = newPressure / (GAMMA - 1.0) + 0.5 * Q[Shortcuts::rho] * vSquared;
236diffusion_solver = exahype2.solvers.fd.GlobalAdaptiveTimeStep(
237 name=
"DiffusionSolver",
238 patch_size=args.degrees_of_freedom,
239 unknowns=diffusion_unknowns,
240 auxiliary_variables=diffusion_auxiliary_variables,
243 time_step_relaxation=0.5,
244 solvers_before_in_coupling=[euler_solver],
248diffusion_solver.set_implementation(
249 initial_conditions=diffusion_initial_conditions,
250 boundary_conditions=diffusion_boundary_conditions,
251 solver=diffusion_stencil,
261diffusion_solver._compute_time_step_size = (
263 const double timeStepSize = repositories::"""
264 + euler_solver.get_name_of_global_instance()
265 +
""".getAdmissibleTimeStepSize(false);
269number_of_variables_euler = euler_solver.auxiliary_variables + euler_solver.unknowns
270number_of_variables_diffusion = (
271 diffusion_solver.auxiliary_variables + diffusion_solver.unknowns
276euler_solver.postprocess_updated_patch += f
"""// Copy density, energy, and momenta
277 ::toolbox::blockstructured::copyUnknown(
278 {euler_solver.patch_size}, // no of unknowns per dimension
279 fineGridCell{euler_solver.name}Q.value, // source
280 {euler_solver._variable_names.index("rho")}, // density in source
281 {number_of_variables_euler}, // unknowns in source (incl material parameters)
282 0, // no overlap/halo here
283 fineGridCell{diffusion_solver.name}Q.value, // dest
284 {diffusion_solver._variable_names.index("rho")}, // density in dest
285 {number_of_variables_diffusion}, // unknowns in dest (incl material parameters)
286 0 // no overlap/halo here
289 ::toolbox::blockstructured::copyUnknown(
290 {euler_solver.patch_size}, // no of unknowns per dimension
291 fineGridCell{euler_solver.name}Q.value, // source
292 {euler_solver._variable_names.index("rhoU")}, // x-momentum in source
293 {number_of_variables_euler}, // unknowns in source (incl material parameters)
294 0, // no overlap/halo here
295 fineGridCell{diffusion_solver.name}Q.value, // dest
296 {diffusion_solver._variable_names.index("rhoU")}, // x-momentum in dest
297 {number_of_variables_diffusion}, // unknowns in dest (incl material parameters)
298 0 // no overlap/halo here
301 ::toolbox::blockstructured::copyUnknown(
302 {euler_solver.patch_size}, // no of unknowns per dimension
303 fineGridCell{euler_solver.name}Q.value, // source
304 {euler_solver._variable_names.index("rhoV")}, // y-momentum in source
305 {number_of_variables_euler}, // unknowns in source (incl material parameters)
306 0, // no overlap/halo here
307 fineGridCell{diffusion_solver.name}Q.value, // dest
308 {diffusion_solver._variable_names.index("rhoV")}, // y-momentum in dest
309 {number_of_variables_diffusion}, // unknowns in dest (incl material parameters)
310 0 // no overlap/halo here
313 ::toolbox::blockstructured::copyUnknown(
314 {euler_solver.patch_size}, // no of unknowns per dimension
315 fineGridCell{euler_solver.name}Q.value, // source
316 {euler_solver._variable_names.index("rhoE")}, // energy in source
317 {number_of_variables_euler}, // unknowns in source (incl material parameters)
318 0, // no overlap/halo here
319 fineGridCell{diffusion_solver.name}Q.value, // dest
320 {diffusion_solver._variable_names.index("rhoE")}, // energy in dest
321 {number_of_variables_diffusion}, // unknowns in dest (incl material parameters)
322 0 // no overlap/halo here
326if args.dimensions == 3:
327 euler_solver.postprocess_updated_patch += f
"""
329 ::toolbox::blockstructured::copyUnknown(
330 {euler_solver.patch_size}, // no of unknowns per dimension
331 fineGridCell{euler_solver.name}Q.value, // source
332 {euler_solver._variable_names.index("rhoW")}, // z-momentum in source
333 {number_of_variables_euler}, // unknowns in source (incl material parameters)
334 0, // no overlap/halo here
335 fineGridCell{diffusion_solver.name}Q.value, // dest
336 {diffusion_solver._variable_names.index("rhoW")}, // z-momentum in dest
337 {number_of_variables_diffusion}, // unknowns in dest (incl material parameters)
338 0 // no overlap/halo here
343euler_solver.add_user_action_set_includes(
'#include "toolbox/blockstructured/Copy.h"\n')
347diffusion_solver.postprocess_updated_patch += f
"""// Copy energy and momenta
348 ::toolbox::blockstructured::copyUnknown(
349 {diffusion_solver.patch_size}, // no of unknowns per dimension
350 fineGridCell{diffusion_solver.name}Q.value, // source
351 {diffusion_solver._variable_names.index("rhoU")}, // x-momentum in source
352 {number_of_variables_diffusion}, // unknowns in source (incl material parameters)
353 0, // no overlap/halo here
354 fineGridCell{euler_solver.name}Q.value, // dest
355 {euler_solver._variable_names.index("rhoU")}, // x-momentum in dest
356 {number_of_variables_euler}, // unknowns in dest (incl material parameters)
357 0 // no overlap/halo here
360 ::toolbox::blockstructured::copyUnknown(
361 {diffusion_solver.patch_size}, // no of unknowns per dimension
362 fineGridCell{diffusion_solver.name}Q.value, // source
363 {diffusion_solver._variable_names.index("rhoV")}, // y-momentum in source
364 {number_of_variables_diffusion}, // unknowns in source (incl material parameters)
365 0, // no overlap/halo here
366 fineGridCell{euler_solver.name}Q.value, // dest
367 {euler_solver._variable_names.index("rhoV")}, // y-momentum in dest
368 {number_of_variables_euler}, // unknowns in dest (incl material parameters)
369 0 // no overlap/halo here
372 ::toolbox::blockstructured::copyUnknown(
373 {diffusion_solver.patch_size}, // no of unknowns per dimension
374 fineGridCell{diffusion_solver.name}Q.value, // source
375 {diffusion_solver._variable_names.index("rhoE")}, // energy in source
376 {number_of_variables_diffusion}, // unknowns in source (incl material parameters)
377 0, // no overlap/halo here
378 fineGridCell{euler_solver.name}Q.value, // dest
379 {euler_solver._variable_names.index("rhoE")}, // energy in dest
380 {number_of_variables_euler}, // unknowns in dest (incl material parameters)
381 0 // no overlap/halo here
385if args.dimensions == 3:
386 diffusion_solver.postprocess_updated_patch += f
"""
388 ::toolbox::blockstructured::copyUnknown(
389 {diffusion_solver.patch_size}, // no of unknowns per dimension
390 fineGridCell{diffusion_solver.name}Q.value, // source
391 {diffusion_solver._variable_names.index("rhoW")}, // z-momentum in source
392 {number_of_variables_diffusion}, // unknowns in source (incl material parameters)
393 0, // no overlap/halo here
394 fineGridCell{euler_solver.name}Q.value, // dest
395 {euler_solver._variable_names.index("rhoW")}, // z-momentum in dest
396 {number_of_variables_euler}, // unknowns in dest (incl material parameters)
397 0 // no overlap/halo here
402diffusion_solver.add_user_action_set_includes(
403 '#include "toolbox/blockstructured/Copy.h"\n'
406euler_solver.last_solver = diffusion_solver
412project = exahype2.Project(
413 namespace=[
"tests",
"exahype2",
"fvfd"],
416 executable=
"ExaHyPE",
419project.add_solver(euler_solver)
420project.add_solver(diffusion_solver)
422if args.number_of_snapshots <= 0:
423 time_in_between_plots = 0.0
425 time_in_between_plots = args.end_time / args.number_of_snapshots
426 project.set_output_path(args.output)
428project.set_global_simulation_parameters(
429 dimensions=args.dimensions,
430 size=size[0 : args.dimensions],
431 offset=[0.0, 0.0, 0.0][0 : args.dimensions],
432 min_end_time=args.end_time,
433 max_end_time=args.end_time,
434 first_plot_time_stamp=0.0,
435 time_in_between_plots=time_in_between_plots,
437 args.periodic_boundary_conditions_x,
438 args.periodic_boundary_conditions_y,
439 args.periodic_boundary_conditions_z,
443project.set_load_balancer(
"new ::exahype2::LoadBalancingConfiguration")
444project.set_Peano4_installation(
445 "../../../", mode=peano4.output.string_to_mode(args.build_mode)
447project = project.generate_Peano4_project(verbose=
False)
448project.output.makefile.add_CXX_flag(
"-DGAMMA=1.4")
449project.output.makefile.add_CXX_flag(
"-DUNIVERSAL_GAS_CONSTANT=8.31")
450project.output.makefile.add_CXX_flag(
"-DKINEMATIC_VISCOSITY=100")
451project.output.makefile.add_CXX_flag(
"-DTHERMAL_DIFFUSIVITY=150")
452project.set_fenv_handler(args.fpe)
453project.build(make=
True, make_clean_first=
True, throw_away_data_after_build=
True)