Peano
Loading...
Searching...
No Matches
rusanov-with-optimistic-explicit-euler-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.fv.RusanovWithOptimisticExplicitEuler
6
7Run from the repository root via
8
9~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10PYTHONPATH=src:python python3 src/exahype2/api/fv/rusanov-with-optimistic-explicit-euler-illustrations.py
11~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12
13The script writes two PNGs next to it, which are referenced from the
14documentation of RusanovWithOptimisticExplicitEuler:
15
16- rusanov-with-optimistic-explicit-euler-volume-classes.png draws the
17 reconstructed 2d patch of a single cell, i.e. a 10x10 patch with a halo
18 of one, and colours its volumes by class: halo, shell and patch interior.
19- rusanov-with-optimistic-explicit-euler-time-step-task-graph.png shows
20 the time stepping task graph as drawn by peano4.api.taskgraph.Graph.visualise().
21 The script constructs it from the actual numerical scheme for a solver
22 with a flux and a maximum eigenvalue, so the picture always matches the
23 code. The kernels this requires are generated into a temporary directory.
24
25"""
26import os
27
28import matplotlib
29
30matplotlib.use("Agg")
31import matplotlib.pyplot as plt
32from matplotlib.patches import Patch, Rectangle
33
34PATCH_SIZE = 10
35HALO = 1
36
37COLOUR_HALO = "#fdae6b"
38COLOUR_HALO_CORNER = "#e0e0e0"
39COLOUR_SHELL = "#9ecae1"
40COLOUR_PATCH_INTERIOR = "#a1d99b"
41COLOUR_GRID = "#505050"
42
43
44def _volume_class(i, j):
45 """Class of volume (i,j) of the reconstructed patch, with 0<=i,j<PATCH_SIZE the patch itself"""
46 outside_x = i < 0 or i >= PATCH_SIZE
47 outside_y = j < 0 or j >= PATCH_SIZE
48 if outside_x and outside_y:
49 return "halo corner"
50 if outside_x or outside_y:
51 return "halo"
52 if i < HALO or i >= PATCH_SIZE - HALO or j < HALO or j >= PATCH_SIZE - HALO:
53 return "shell"
54 return "patch interior"
55
56
58 colours = {
59 "halo": COLOUR_HALO,
60 "halo corner": COLOUR_HALO_CORNER,
61 "shell": COLOUR_SHELL,
62 "patch interior": COLOUR_PATCH_INTERIOR,
63 }
64 figure, axes = plt.subplots(figsize=(6.5, 7.2))
65 for i in range(-HALO, PATCH_SIZE + HALO):
66 for j in range(-HALO, PATCH_SIZE + HALO):
67 volume_class = _volume_class(i, j)
68 axes.add_patch(
69 Rectangle(
70 (i, j), 1, 1,
71 facecolor=colours[volume_class],
72 edgecolor=COLOUR_GRID,
73 linewidth=0.5,
74 hatch="////" if volume_class == "halo corner" else None,
75 )
76 )
77 # Outlines of the reconstructed patch, of the patch, and of the patch interior
78 for offset, linewidth in [(-HALO, 2.0), (0, 2.0), (HALO, 1.5)]:
79 size = PATCH_SIZE - 2 * offset
80 axes.add_patch(Rectangle((offset, offset), size, size, fill=False, edgecolor="black", linewidth=linewidth))
81
82 interior_size = PATCH_SIZE - 2 * HALO
83 axes.text(PATCH_SIZE / 2, PATCH_SIZE / 2, f"patch interior\n{interior_size}x{interior_size}", ha="center", va="center", fontsize=12)
84 margin = HALO + 0.3
85 axes.set_xlim(-margin, PATCH_SIZE + margin)
86 axes.set_ylim(-margin, PATCH_SIZE + margin)
87 axes.set_aspect("equal")
88 axes.axis("off")
89 total_size = PATCH_SIZE + 2 * HALO
90 axes.set_title(
91 f"Reconstructed patch, {total_size}x{total_size}:\n"
92 f"{PATCH_SIZE}x{PATCH_SIZE} patch plus a halo of {HALO}",
93 fontsize=12,
94 )
95 figure.legend(
96 handles=[
97 Patch(facecolor=COLOUR_HALO, edgecolor=COLOUR_GRID, label="halo"),
98 Patch(facecolor=COLOUR_SHELL, edgecolor=COLOUR_GRID, label="shell"),
99 Patch(facecolor=COLOUR_PATCH_INTERIOR, edgecolor=COLOUR_GRID, label="patch interior"),
100 Patch(facecolor=COLOUR_HALO_CORNER, edgecolor=COLOUR_GRID, hatch="////", label="halo corner (not used by Rusanov)"),
101 ],
102 loc="lower center",
103 ncol=2,
104 frameon=False,
105 fontsize=11,
106 )
107 figure.tight_layout(rect=(0, 0.1, 1, 1))
108 output = os.path.join(
109 os.path.dirname(os.path.abspath(__file__)), "rusanov-with-optimistic-explicit-euler-volume-classes.png"
110 )
111 figure.savefig(output, dpi=100, bbox_inches="tight")
112 plt.close(figure)
113 print("Wrote", output)
114
115
117 import tempfile
118
119 import peano4.api
121 import exahype2.api
122
123 # The Python API writes a log file when the program terminates. Keep it
124 # out of the working directory.
125 peano4.api.Logger().file_name = os.path.join(
126 tempfile.gettempdir(), "rusanov-with-optimistic-explicit-euler-illustrations-log.md"
127 )
128
129 with tempfile.TemporaryDirectory() as directory:
130 peano_project = peano4.api.Project(["illustration"], "illustration", directory=directory)
131 solver = exahype2.api.Solver("Euler", 4, 0)
132 solver.add_pde_term(exahype2.api.Flux(stateless=False))
133 solver.add_pde_term(exahype2.api.MaxEigenvalue(stateless=False))
134 solver.add_pde_term(exahype2.api.DirichletBoundaryConditions(stateless=False))
135 solver.numerical_scheme = exahype2.api.fv.RusanovWithOptimisticExplicitEuler(solver, PATCH_SIZE - 1)
136 # Non-periodic boundaries, so the graph shows the boundary task
137 exahype2_project = exahype2.api.Project(["illustration"], "illustration", "illustration", directory=directory)
138 exahype2_project.set_global_simulation_parameters(
139 dimensions=2, offset=[0.0, 0.0], size=[1.0, 1.0], min_end_time=1.0, periodic_BC=[False, False]
140 )
141 time_step = peano4.api.taskgraph.Graph()
142 solver.numerical_scheme.construct_output(exahype2_project, peano_project, time_step)
143
144 time_step.visualise(title="Time stepping task graph of RusanovWithOptimisticExplicitEuler")
145 output = os.path.join(
146 os.path.dirname(os.path.abspath(__file__)), "rusanov-with-optimistic-explicit-euler-time-step-task-graph.png"
147 )
148 plt.gcf().savefig(output, dpi=90)
149 plt.close(plt.gcf())
150 print("Wrote", output)
151
152
153if __name__ == "__main__":
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
Finite Volumes with a Rusanov Riemann solver and optimistic explicit Euler time stepping,...
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
_volume_class(i, j)
Class of volume (i,j) of the reconstructed patch, with 0<=i,j<PATCH_SIZE the patch itself.
The task graph abstraction allows users to formalise their solver steps over small task graphs which ...
Definition __init__.py:1