Peano
Loading...
Searching...
No Matches
fv-coupling.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 peano4
4import exahype2
5
6parser = exahype2.ArgumentParser("ExaHyPE 2 - Finite Volumes Coupling Testing Script")
7
8parser.set_defaults(
9 min_depth=3,
10 degrees_of_freedom=16,
11 end_time=1.0,
12 number_of_snapshots=0,
13 periodic_boundary_conditions_x=False,
14 periodic_boundary_conditions_y=False,
15 periodic_boundary_conditions_z=False,
16)
17args = parser.parse_args()
18
19max_h = 1.1 / 3.0**args.min_depth
20min_h = max_h * 3.0 ** (-args.amr_levels)
21
22
25
26euler_unknowns = {
27 "rho": 1,
28 "rhoU": 1,
29 "rhoV": 1,
30}
31if args.dimensions == 3:
32 euler_unknowns["rhoW"] = 1
33euler_unknowns["rhoE"] = 1
34
35euler_initial_conditions = """
36 Q[Shortcuts::rho] = 0.1;
37 Q[Shortcuts::rhoU] = 0.0;
38 Q[Shortcuts::rhoV] = 0.0;
39#if DIMENSIONS == 3
40 Q[Shortcuts::rhoW] = 0.0;
41#endif
42 Q[Shortcuts::rhoE] = ((x(0) < 0.5) ? (1.01) : (1.0));
43"""
44
45euler_boundary_conditions = """
46 // Reflective boundary conditions
47 Qoutside[Shortcuts::rho] = Qinside[Shortcuts::rho];
48 Qoutside[Shortcuts::rhoU] = -Qinside[Shortcuts::rhoU];
49 Qoutside[Shortcuts::rhoV] = -Qinside[Shortcuts::rhoV];
50#if DIMENSIONS == 3
51 Qoutside[Shortcuts::rhoW] = -Qinside[Shortcuts::rhoW];
52#endif
53 Qoutside[Shortcuts::rhoE] = Qinside[Shortcuts::rhoE];
54"""
55
56compute_primitive_variables = r"""
57 const auto irho = 1.0 / Q[Shortcuts::rho];
58 const auto u0 = Q[Shortcuts::rhoU + 0] * irho;
59 const auto u1 = Q[Shortcuts::rhoU + 1] * irho;
60#if DIMENSIONS == 3
61 const auto u2 = Q[Shortcuts::rhoU + 2] * irho;
62#endif
63
64#if DIMENSIONS == 3
65 const auto uSq = u0 * u0 + u1 * u1 + u2 * u2;
66 const auto u_n = (normal == 0) ? u0 : (normal == 1) ? u1 : u2;
67#else
68 const auto uSq = u0 * u0 + u1 * u1;
69 const auto u_n = (normal == 0) ? u0 : u1;
70#endif
71
72 const auto internalE = Q[Shortcuts::rhoE] - 0.5 * Q[Shortcuts::rho] * uSq;
73 const auto p = (GAMMA - 1.0) * internalE;
74"""
75
76euler_max_eigenvalue = r"""
77 {compute_primitive_variables}
78 const auto speedOfSound = std::sqrt(GAMMA * p * irho);
79 auto result = std::fmax(0.0, std::fabs(u_n - speedOfSound));
80 result = std::fmax(result, std::fabs(u_n + speedOfSound));
81 return result;
82""".format(
83 compute_primitive_variables=compute_primitive_variables
84)
85
86euler_flux = r"""
87 {compute_primitive_variables}
88
89 F[Shortcuts::rho] = Q[Shortcuts::rhoU + normal];
90
91 F[Shortcuts::rhoU + 0] = Q[Shortcuts::rhoU + 0] * u_n;
92 F[Shortcuts::rhoU + 1] = Q[Shortcuts::rhoU + 1] * u_n;
93#if DIMENSIONS == 3
94 F[Shortcuts::rhoU + 2] = Q[Shortcuts::rhoU + 2] * u_n;
95#endif
96
97 F[Shortcuts::rhoU + normal] += p;
98
99 F[Shortcuts::rhoE] = (Q[Shortcuts::rhoE] + p) * u_n;
100""".format(
101 compute_primitive_variables=compute_primitive_variables
102)
103
104euler_solver = exahype2.solvers.fv.godunov.GlobalAdaptiveTimeStep(
105 name="EulerFVSolver",
106 patch_size=args.degrees_of_freedom,
107 unknowns=euler_unknowns,
108 auxiliary_variables=0,
109 min_volume_h=min_h,
110 max_volume_h=max_h,
111 time_step_relaxation=0.5,
112)
113
114euler_solver.set_implementation(
115 initial_conditions=euler_initial_conditions,
116 boundary_conditions=euler_boundary_conditions,
117 flux=euler_flux,
118 max_eigenvalue=euler_max_eigenvalue,
119)
120
121
124
125advection_unknowns = {"scalar": 1} # Represents some material that is "moved" (advected) through the velocity field computed by the Euler equations
126advection_auxiliary_variables = {
127 "rho": 1,
128 "rhoU": 1,
129 "rhoV": 1,
130}
131if args.dimensions == 3:
132 advection_auxiliary_variables["rhoW"] = 1
133
134advection_initial_conditions = """
135 Q[Shortcuts::scalar] = ((x(0) < 0.5) ? (50) : 0.0);
136 Q[Shortcuts::rho] = 0.1;
137 Q[Shortcuts::rhoU] = 0.0;
138 Q[Shortcuts::rhoV] = 0.0;
139#if DIMENSIONS == 3
140 Q[Shortcuts::rhoW] = 0.0;
141#endif
142"""
143
144advection_boundary_conditions = """
145 // Reflective boundary conditions
146 Qoutside[Shortcuts::scalar] = Qinside[Shortcuts::scalar];
147 Qoutside[Shortcuts::rho] = Qinside[Shortcuts::rho];
148 Qoutside[Shortcuts::rhoU] = -Qinside[Shortcuts::rhoU];
149 Qoutside[Shortcuts::rhoV] = -Qinside[Shortcuts::rhoV];
150#if DIMENSIONS == 3
151 Qoutside[Shortcuts::rhoW] = -Qinside[Shortcuts::rhoW];
152#endif
153"""
154
155advection_flux = """
156 const auto irho = 1.0 / Q[Shortcuts::rho];
157 const auto u_n = Q[Shortcuts::rhoU + normal] * irho;
158 F[Shortcuts::scalar] = Q[Shortcuts::scalar] * u_n;
159"""
160
161advection_max_eigenvalue = """
162 if (dt == 0) {
163 // Return dummy value initially because all velocities are 0
164 return 1.0;
165 }
166 // We could also return a dummy value here but this way, mistakes are more obvious.
167 const auto irho = 1.0 / Q[Shortcuts::rho];
168 const auto u_n = Q[Shortcuts::rhoU + normal] * irho;
169 return u_n;
170"""
171
172advection_solver = exahype2.solvers.fv.godunov.GlobalAdaptiveTimeStep(
173 name="AdvectionFVSolver",
174 patch_size=args.degrees_of_freedom,
175 unknowns=advection_unknowns,
176 auxiliary_variables=advection_auxiliary_variables,
177 min_volume_h=min_h,
178 max_volume_h=max_h,
179 time_step_relaxation=0.5,
180 solvers_before_in_coupling=[euler_solver],
181)
182
183advection_solver.set_implementation(
184 initial_conditions=advection_initial_conditions,
185 boundary_conditions=advection_boundary_conditions,
186 flux=advection_flux,
187 max_eigenvalue=advection_max_eigenvalue,
188)
189
190
193
194advection_solver._compute_time_step_size = (
195 """
196 const double timeStepSize = repositories::"""
197 + euler_solver.get_name_of_global_instance()
198 + """.getAdmissibleTimeStepSize(false);
199"""
200)
201
202number_of_variables_euler = euler_solver.auxiliary_variables + euler_solver.unknowns
203number_of_variables_advection = (
204 advection_solver.auxiliary_variables + advection_solver.unknowns
205)
206
207# TODO: This is really ugly!
208euler_solver.postprocess_updated_patch += f"""// Copy density and momenta
209 ::toolbox::blockstructured::copyUnknown(
210 {euler_solver.patch_size}, // no of unknowns per dimension
211 fineGridCell{euler_solver.name}Q.value, // source
212 {euler_solver._variable_names.index("rho")}, // density in source
213 {number_of_variables_euler}, // unknowns in source (incl material parameters)
214 0, // no overlap/halo here
215 fineGridCell{advection_solver.name}Q.value, // dest
216 {advection_solver._variable_names.index("rho")}, // density in dest
217 {number_of_variables_advection}, // unknowns in dest (incl material parameters)
218 0 // no overlap/halo here
219 );
220
221 ::toolbox::blockstructured::copyUnknown(
222 {euler_solver.patch_size}, // no of unknowns per dimension
223 fineGridCell{euler_solver.name}Q.value, // source
224 {euler_solver._variable_names.index("rhoU")}, // x-momentum in source
225 {number_of_variables_euler}, // unknowns in source (incl material parameters)
226 0, // no overlap/halo here
227 fineGridCell{advection_solver.name}Q.value, // dest
228 {advection_solver._variable_names.index("rhoU")}, // x-momentum in dest
229 {number_of_variables_advection}, // unknowns in dest (incl material parameters)
230 0 // no overlap/halo here
231 );
232
233 ::toolbox::blockstructured::copyUnknown(
234 {euler_solver.patch_size}, // no of unknowns per dimension
235 fineGridCell{euler_solver.name}Q.value, // source
236 {euler_solver._variable_names.index("rhoV")}, // y-momentum in source
237 {number_of_variables_euler}, // unknowns in source (incl material parameters)
238 0, // no overlap/halo here
239 fineGridCell{advection_solver.name}Q.value, // dest
240 {advection_solver._variable_names.index("rhoV")}, // y-momentum in dest
241 {number_of_variables_advection}, // unknowns in dest (incl material parameters)
242 0 // no overlap/halo here
243 );
244"""
245
246if args.dimensions == 3:
247 euler_solver.postprocess_updated_patch += f"""
248#if DIMENSIONS == 3
249 ::toolbox::blockstructured::copyUnknown(
250 {euler_solver.patch_size}, // no of unknowns per dimension
251 fineGridCell{euler_solver.name}Q.value, // source
252 {euler_solver._variable_names.index("rhoW")}, // z-momentum in source
253 {number_of_variables_euler}, // unknowns in source (incl material parameters)
254 0, // no overlap/halo here
255 fineGridCell{advection_solver.name}Q.value, // dest
256 {advection_solver._variable_names.index("rhoW")}, // z-momentum in dest
257 {number_of_variables_advection}, // unknowns in dest (incl material parameters)
258 0 // no overlap/halo here
259 );
260#endif
261"""
262
263euler_solver.add_user_action_set_includes('#include "toolbox/blockstructured/Copy.h"\n')
264
265euler_solver.last_solver = advection_solver
266
267
270
271project = exahype2.Project(
272 namespace=["tests", "exahype2", "fv"],
273 project_name=".",
274 directory=".",
275 executable="ExaHyPE",
276)
277
278project.add_solver(euler_solver)
279project.add_solver(advection_solver)
280
281if args.number_of_snapshots <= 0:
282 time_in_between_plots = 0.0
283else:
284 time_in_between_plots = args.end_time / args.number_of_snapshots
285 project.set_output_path(args.output)
286
287project.set_global_simulation_parameters(
288 dimensions=args.dimensions,
289 size=[1.0, 1.0, 1.0][0 : args.dimensions],
290 offset=[0.0, 0.0, 0.0][0 : args.dimensions],
291 min_end_time=args.end_time,
292 max_end_time=args.end_time,
293 first_plot_time_stamp=0.0,
294 time_in_between_plots=time_in_between_plots,
295 periodic_BC=[
296 args.periodic_boundary_conditions_x,
297 args.periodic_boundary_conditions_y,
298 args.periodic_boundary_conditions_z,
299 ],
300)
301
302project.set_load_balancer("new ::exahype2::LoadBalancingConfiguration")
303project.set_Peano4_installation(
304 "../../../", mode=peano4.output.string_to_mode(args.build_mode)
305)
306project = project.generate_Peano4_project(verbose=False)
307project.output.makefile.add_CXX_flag("-DGAMMA=1.4")
308project.set_fenv_handler(args.fpe)
309project.build(make=True, make_clean_first=True, throw_away_data_after_build=True)