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