5Create the PNG illustrations of the tutorial 20_additional-solver-steps.ipynb
7The script writes the following pictures into the directory of this script:
9- 20_additional-solver-steps-fv-task-graph.png: the time stepping task graph
10 of the Finite Volumes with a density floor as additional solver step;
11- 20_additional-solver-steps-rk-task-graph.png: the same for the
12 fourth-order Finite Differences with a Runge-Kutta scheme of order two,
13 where the floor follows each Runge-Kutta stage;
14- 20_additional-solver-steps-profile.png: the density along y=0 after one
15 period with and without the density floor.
19 python3 tutorials/exahype2/illustrations/20_additional-solver-steps.py
21All builds and outputs go into a temporary directory (or --work-directory).
22A run whose directory already holds the output is not repeated. The script
23builds four executables, i.e. it runs for a few minutes.
33Here = os.path.dirname(os.path.abspath(__file__))
34PeanoRoot = os.path.abspath(os.path.join(Here,
"..",
"..",
".."))
35sys.path.insert(0, os.path.join(PeanoRoot,
"src"))
40import matplotlib.pyplot
as plt
51 const double irho = 1.0 / Q[0];
52 constexpr double gamma = 1.4;
53 const double p = (gamma - 1.0) * (Q[3] - 0.5 * irho * (Q[1] * Q[1] + Q[2] * Q[2]));
57 F[1] = irho * Q[1] * Q[1] + p;
58 F[2] = irho * Q[1] * Q[2];
59 F[3] = irho * Q[1] * (Q[3] + p);
63 F[1] = irho * Q[2] * Q[1];
64 F[2] = irho * Q[2] * Q[2] + p;
65 F[3] = irho * Q[2] * (Q[3] + p);
71 const double irho = 1.0 / Q[0];
72 constexpr double gamma = 1.4;
73 const double p = (gamma - 1.0) * (Q[3] - 0.5 * irho * (Q[1] * Q[1] + Q[2] * Q[2]));
74 const double c = std::sqrt(gamma * p * irho);
75 const double u = Q[1 + normal] * irho;
76 lambdaMax[0] = std::max(std::abs(u + c), std::abs(u - c));
80 constexpr double gamma = 1.4;
81 constexpr double p = 1.0;
82 constexpr double u = 1.0;
83 const double rho = 1.0 + 0.2 * std::sin(2.0 * M_PI * (x[0] + 0.1) / 0.2);
87 Q[3] = p / (gamma - 1) + 0.5 * rho * u * u;
91 constexpr double gamma = 1.4;
92 constexpr double minDensity = 0.9;
93 if (Q[0] < minDensity) {
94 const double u = Q[1] / Q[0];
95 const double v = Q[2] / Q[0];
96 const double p = (gamma - 1.0) * (Q[3] - 0.5 * Q[0] * (u * u + v * v));
98 Q[1] = minDensity * u;
99 Q[2] = minDensity * v;
100 Q[3] = p / (gamma - 1.0) + 0.5 * minDensity * (u * u + v * v);
109 Insert the density floor after each task of solver which carries tag
111 Mirrors the routine of the tutorial: The numerical scheme knows which
112 patch its tagged tasks write and passes it in.
115 for anchor
in time_step.find_tasks(tag):
116 if not anchor.name.startswith(solver.name +
"_"):
119 name=f
"{solver.name}_Density floor after {anchor.name[len(solver.name) + 1:]}",
120 entity=peano4.api.taskgraph.Task.GridEntity.CELL,
122 task.use_cell(patch, peano4.api.taskgraph.Task.DataAccess.READ_AND_WRITE)
124 toolbox.blockstructured.api.ApplyPointWiselyToPatch(
126 implementation=DensityFloor,
127 guard=solver.grid_selector.createCellGuard(),
128 additional_includes=solver._get_default_includes()
129 + solver.user_solver_includes,
132 time_step.insert_after(anchor, task)
136 """! Finite Volumes which insert the density floor after each update"""
143 exahype2.api.Solver.SolutionUpdateTaskTag,
149 """! Runge-Kutta Finite Differences which insert the density floor after each stage"""
156 exahype2.api.Solver.SolutionUpdateTaskTag,
162 exahype2.api.Solver.IntermediateSolutionUpdateTag,
174 return 1.0 + 0.2 * np.sin(
175 2.0 * np.pi * (np.asarray(x) - t - DomainOffset) / DomainWidth
182 Create the Euler solver of the tutorial
184 @param rk_order: int or None
185 None selects the Finite Volumes, an integer the fourth-order Finite
186 Differences with the Runge-Kutta scheme of this order.
190 solver.add_user_solver_includes(
"#include <cmath>\n#include <algorithm>\n")
200 RusanovWithDensityFloor
204 solver.numerical_scheme = scheme(solver, 9)
206 solver, volume_size=VolumeSize
209 solver, first_plot_time_stamp=0.0, time_in_between_plots=0.05
213 RungeKuttaWithDensityFloor
217 solver.numerical_scheme = scheme(solver, patch_size=9, rk_order=rk_order)
219 solver, volume_size=VolumeSize
222 solver, first_plot_time_stamp=0.0, time_in_between_plots=0.05
228 """! Construct the time stepping task graph including the density floor and draw it"""
230 tempfile.gettempdir(),
"20-additional-solver-steps-log.md"
232 with tempfile.TemporaryDirectory()
as directory:
234 [
"illustration"],
"illustration", directory=directory
236 solver =
create_solver(
"Euler", rk_order, density_floor=
True)
237 exahype2_project = types.SimpleNamespace(periodic_BC=[
True,
True])
239 solver.numerical_scheme.construct_output(
240 exahype2_project, peano_project, time_step
242 time_step.visualise(title=title)
243 output = os.path.join(Here, file_name)
244 plt.gcf().savefig(output, dpi=90)
246 print(
"Wrote", output)
250 name =
"EulerFV" if rk_order
is None else "EulerFD4"
251 patch_file = os.path.join(directory,
"solution-{}.peano-patch-file".format(name))
252 if os.path.exists(patch_file):
253 print(
"reuse {}".format(directory))
255 print(
"build and run {}".format(directory))
256 os.makedirs(directory, exist_ok=
True)
258 namespace=[
"tutorials",
"exahype2",
"additionalsteps"],
259 project_name=
"AdditionalSteps",
261 executable=
"additional-steps",
263 project.add_solver(
create_solver(name, rk_order, density_floor))
264 project.set_global_simulation_parameters(
266 offset=[DomainOffset, DomainOffset],
267 size=[DomainWidth, DomainWidth],
268 min_end_time=EndTime,
269 max_end_time=EndTime,
270 periodic_BC=[
True,
True,
True],
272 project.set_Peano4_installation(peano_root, peano4.api.output.CompileMode.RELEASE)
273 peano4_project = project.generate_Peano4_project(
274 verbosity=peano4.api.LoggerVerbosity.TEXT
276 peano4_project.generate()
278 [
"make",
"-j4"], cwd=directory, check=
True, stdout=subprocess.DEVNULL
281 [
"./additional-steps"], cwd=directory, check=
True, stdout=subprocess.DEVNULL
287 """! Return time stamp plus grid cell centres and densities along y=0 of the last snapshot"""
290 for file_name
in files:
292 size = np.array([DomainWidth / round(DomainWidth / s)
for s
in size])
294 np.round((np.array(offset) - DomainOffset) / size) * size + DomainOffset
296 dofs = values.shape[0]
297 if offset[1] <= 0.0 < offset[1] + size[1]:
298 row = int((0.0 - offset[1]) / (size[1] / dofs))
299 x += list(offset[0] + (np.arange(dofs) + 0.5) * size[0] / dofs)
300 rho += list(values[row, :, 0])
301 order = np.argsort(x)
302 return time_stamp, np.array(x)[order], np.array(rho)[order]
305if __name__ ==
"__main__":
306 parser = argparse.ArgumentParser(
307 description=
"Create the PNGs of the tutorial 20_additional-solver-steps.ipynb"
312 help=
"Directory for builds and outputs (default: temporary directory)",
317 help=
"Configured and built Peano installation to link against",
319 args = parser.parse_args()
323 "20_additional-solver-steps-fv-task-graph.png",
324 "Finite Volumes with a density floor",
328 "20_additional-solver-steps-rk-task-graph.png",
329 "Runge-Kutta of order two with a density floor",
334 with contextlib.ExitStack()
as stack:
335 work_directory = os.path.abspath(
336 args.work_directory
or stack.enter_context(tempfile.TemporaryDirectory())
338 fig, axes = plt.subplots(1, 2, figsize=(11, 4), sharey=
True)
339 for ax, rk_order, title
in [
340 (axes[0],
None,
"Finite Volumes"),
341 (axes[1], 4,
"Finite Differences, Runge-Kutta 4"),
343 x_fine = np.linspace(DomainOffset, DomainOffset + DomainWidth, 400)
347 for density_floor, marker
in [(
False,
"o"), (
True,
"s")]:
348 directory = os.path.join(
351 "fv" if rk_order
is None else "rk4",
352 "floor" if density_floor
else "plain",
356 rk_order, density_floor, directory, os.path.abspath(args.peano_root)
360 "{}: t={:.4f}, min density={:.4f}, max density={:.4f}".format(
361 directory, t, rho.min(), rho.max()
369 label=
"with density floor" if density_floor
else "without",
371 ax.axhline(0.9, color=
"tab:red", linestyle=
"--", linewidth=1, label=
"floor")
373 ax.set_xlabel(
"x (along y=0)")
374 ax.set_xticks([-0.1, -0.05, 0.0, 0.05, 0.1])
375 axes[0].set_ylabel(
"density after one period")
376 axes[1].legend(loc=
"upper left", bbox_to_anchor=(1.01, 1.0))
377 output = os.path.join(Here,
"20_additional-solver-steps-profile.png")
378 fig.savefig(output, dpi=100, bbox_inches=
"tight")
380 print(
"Wrote", output)
Runge-Kutta Finite Differences which insert the density floor after each stage.
construct_output(self, exahype2_project, peano_project, time_step)
Add the data to the Peano 4 project, generate the kernels and add the tasks of one Runge-Kutta step t...
Finite Volumes which insert the density floor after each update.
construct_output(self, exahype2_project, peano_project, time_step)
Has to be implemented by subclass.
The conservative flux F(Q) of a hyperbolic PDE.
Point-wise initial condition: given the physical position of a single degree of freedom,...
The maximum absolute eigenvalue of the flux Jacobian in a given direction, i.e.
Abstract base class for all ExaHyPE 2 solvers.
Plotting counterpart to RusanovWithExplicitEuler: maps the patch data of a Finite Volume scheme with ...
Finite Volumes with a Rusanov Riemann solver and explicit Euler time stepping, realised over a block-...
_solver
Build the reconstruction tasks befilling the patch_with_halo, which is logically temporary.
Setup phase counterpart to RusanovWithExplicitEuler: sets the initial condition for a Finite Volume s...
Fourth-order central Finite Differences with explicit Runge-Kutta time stepping, realised over a bloc...
_solver
Project the outcome onto the faces.
Plotting counterpart of the fourth-order Finite Differences with Runge-Kutta time stepping (exahype2....
Setup phase of the fourth-order Finite Differences with Runge-Kutta time stepping (exahype2....
Singleton logger for the Peano 4 Python API.
Represents a Peano 4 project.
Holds a sequence of Task instances.
One task within a peano4.api.taskgraph.Graph.
build_and_run(rk_order, density_floor, directory, peano_root)
plot_task_graph(rk_order, file_name, title)
Construct the time stepping task graph including the density floor and draw it.
create_solver(name, rk_order, density_floor)
Create the Euler solver of the tutorial.
density_along_x_axis(patch_file)
Return time stamp plus grid cell centres and densities along y=0 of the last snapshot.
insert_density_floor(solver, time_step, tag, patch)
Insert the density floor after each task of solver which carries tag.
The task graph abstraction allows users to formalise their solver steps over small task graphs which ...
Interactive visualisation of Peano patch files within Jupyter notebooks.
read_patches(patch_file_name)
Return list of (offset, size, values) for all patches of one patch file.
read_snapshots(file_name)
Return list of (time stamp, list of patch files) from a patch meta file.