Peano
Loading...
Searching...
No Matches
central-differences-with-runge-kutta-illustrations.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
3"""!
4
5Generate the illustrations of exahype2.api.rkfd4.CentralDifferencesWithRungeKutta
6
7Run from the repository root via
8
9~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10PYTHONPATH=src python3 src/exahype2/api/rkfd4/central-differences-with-runge-kutta-illustrations.py
11~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12
13The script writes two PNGs next to it, which are referenced from the
14documentation of CentralDifferencesWithRungeKutta:
15
16- central-differences-with-runge-kutta-stencil.png draws the reconstructed
17 2d patch of a single cell, i.e. a 9x9 patch with a halo of two, and the
18 stencil of one grid cell next to the patch boundary: the fourth-order
19 central differences reach two grid cells along each axis.
20- central-differences-with-runge-kutta-time-step-task-graph.png shows the
21 time stepping task graph of a second-order Runge-Kutta scheme as drawn by
22 peano4.api.taskgraph.Graph.visualise(). The script constructs it from the
23 actual numerical scheme for a solver with a flux, a maximum eigenvalue and
24 Dirichlet boundary conditions, so the picture always matches the code. The
25 kernels this requires are generated into a temporary directory.
26
27"""
28import os
29
30import matplotlib
31
32matplotlib.use("Agg")
33import matplotlib.pyplot as plt
34from matplotlib.patches import Patch, Rectangle
35
36PATCH_SIZE = 9
37HALO = 2
38
39COLOUR_HALO = "#fdae6b"
40COLOUR_HALO_CORNER = "#e0e0e0"
41COLOUR_PATCH = "#9ecae1"
42COLOUR_DIFFERENCES = "#31a354"
43COLOUR_GRID_CELL = "#de2d26"
44COLOUR_GRID = "#505050"
45
46
47def stencil():
48 figure, axes = plt.subplots(figsize=(6.5, 7.4))
49 for i in range(-HALO, PATCH_SIZE + HALO):
50 for j in range(-HALO, PATCH_SIZE + HALO):
51 outside_x = i < 0 or i >= PATCH_SIZE
52 outside_y = j < 0 or j >= PATCH_SIZE
53 if outside_x and outside_y:
54 colour, hatch = COLOUR_HALO_CORNER, "////"
55 elif outside_x or outside_y:
56 colour, hatch = COLOUR_HALO, None
57 else:
58 colour, hatch = COLOUR_PATCH, None
59 axes.add_patch(
60 Rectangle(
61 (i, j),
62 1,
63 1,
64 facecolor=colour,
65 edgecolor=COLOUR_GRID,
66 linewidth=0.5,
67 hatch=hatch,
68 )
69 )
70
71 # Stencil of the grid cell (1,4): two neighbours per direction
72 centre = (1, 4)
73 for distance in range(1, HALO + 1):
74 for dx, dy in [(distance, 0), (-distance, 0), (0, distance), (0, -distance)]:
75 axes.add_patch(
76 Rectangle(
77 (centre[0] + dx + 0.15, centre[1] + dy + 0.15),
78 0.7,
79 0.7,
80 facecolor=COLOUR_DIFFERENCES,
81 edgecolor="black",
82 linewidth=0.8,
83 )
84 )
85 axes.add_patch(
86 Rectangle(
87 (centre[0] + 0.15, centre[1] + 0.15),
88 0.7,
89 0.7,
90 facecolor=COLOUR_GRID_CELL,
91 edgecolor="black",
92 linewidth=0.8,
93 )
94 )
95
96 for offset, linewidth in [(-HALO, 2.0), (0, 2.0)]:
97 size = PATCH_SIZE - 2 * offset
98 axes.add_patch(
99 Rectangle(
100 (offset, offset),
101 size,
102 size,
103 fill=False,
104 edgecolor="black",
105 linewidth=linewidth,
106 )
107 )
108
109 margin = HALO + 0.3
110 axes.set_xlim(-margin, PATCH_SIZE + margin)
111 axes.set_ylim(-margin, PATCH_SIZE + margin)
112 axes.set_aspect("equal")
113 axes.axis("off")
114 total_size = PATCH_SIZE + 2 * HALO
115 axes.set_title(
116 f"Reconstructed patch, {total_size}x{total_size}:\n"
117 f"{PATCH_SIZE}x{PATCH_SIZE} patch plus a halo of {HALO}",
118 fontsize=12,
119 )
120 figure.legend(
121 handles=[
122 Patch(facecolor=COLOUR_PATCH, edgecolor=COLOUR_GRID, label="patch"),
123 Patch(facecolor=COLOUR_HALO, edgecolor=COLOUR_GRID, label="halo"),
124 Patch(
125 facecolor=COLOUR_HALO_CORNER,
126 edgecolor=COLOUR_GRID,
127 hatch="////",
128 label="halo corner (not used)",
129 ),
130 Patch(
131 facecolor=COLOUR_GRID_CELL,
132 edgecolor="black",
133 label="grid cell to update",
134 ),
135 Patch(
136 facecolor=COLOUR_DIFFERENCES,
137 edgecolor="black",
138 label="fourth-order central differences",
139 ),
140 ],
141 loc="lower center",
142 ncol=2,
143 frameon=False,
144 fontsize=10,
145 )
146 figure.tight_layout(rect=(0, 0.13, 1, 1))
147 output = os.path.join(
148 os.path.dirname(os.path.abspath(__file__)),
149 "central-differences-with-runge-kutta-stencil.png",
150 )
151 figure.savefig(output, dpi=100, bbox_inches="tight")
152 plt.close(figure)
153 print("Wrote", output)
154
155
157 import tempfile
158
159 import peano4.api
161 import exahype2.api
162
163 # The Python API writes a log file when the program terminates. Keep it
164 # out of the working directory.
165 peano4.api.Logger().file_name = os.path.join(
166 tempfile.gettempdir(),
167 "central-differences-with-runge-kutta-illustrations-log.md",
168 )
169
170 with tempfile.TemporaryDirectory() as directory:
171 peano_project = peano4.api.Project(
172 ["illustration"], "illustration", directory=directory
173 )
174 solver = exahype2.api.Solver("Euler", 4, 0)
175 solver.add_pde_term(exahype2.api.Flux(stateless=False))
176 solver.add_pde_term(exahype2.api.MaxEigenvalue(stateless=False))
177 solver.add_pde_term(exahype2.api.DirichletBoundaryConditions(stateless=False))
179 solver, patch_size=PATCH_SIZE, rk_order=2
180 )
181 # Non-periodic boundaries, so the graph shows the boundary tasks
182 exahype2_project = exahype2.api.Project(
183 ["illustration"], "illustration", "illustration", directory=directory
184 )
185 exahype2_project.set_global_simulation_parameters(
186 dimensions=2,
187 offset=[0.0, 0.0],
188 size=[1.0, 1.0],
189 min_end_time=1.0,
190 periodic_BC=[False, False],
191 )
192 time_step = peano4.api.taskgraph.Graph()
193 solver.numerical_scheme.construct_output(
194 exahype2_project, peano_project, time_step
195 )
196
197 time_step.visualise(
198 title="Time stepping task graph of CentralDifferencesWithRungeKutta (rk_order=2)"
199 )
200 output = os.path.join(
201 os.path.dirname(os.path.abspath(__file__)),
202 "central-differences-with-runge-kutta-time-step-task-graph.png",
203 )
204 plt.gcf().savefig(output, dpi=90)
205 plt.close(plt.gcf())
206 print("Wrote", output)
207
208
209if __name__ == "__main__":
210 stencil()
The conservative flux F(Q) of a hyperbolic PDE.
Definition Flux.py:8
The maximum absolute eigenvalue of the flux Jacobian in a given direction, i.e.
ExaHyPE 2 project.
Definition Project.py:15
Abstract base class for all ExaHyPE 2 solvers.
Definition Solver.py:17
Fourth-order central Finite Differences with explicit Runge-Kutta time stepping, realised over a bloc...
Singleton logger for the Peano 4 Python API.
Definition Logger.py:37
Represents a Peano 4 project.
Definition Project.py:23
Holds a sequence of Task instances.
Definition Graph.py:9
The task graph abstraction allows users to formalise their solver steps over small task graphs which ...
Definition __init__.py:1