5Create the PNG illustrations of the tutorial 10_euler.ipynb
7The script builds the tutorial's Euler setup for two volume sizes, runs it,
8probes the solution at the origin and writes all pictures into the
9directory of this script. The PDE terms are injected from Python, i.e. we
10do not need any hand-written C++ file. Call it from anywhere:
12 python3 tutorials/exahype2/illustrations/10_euler.py
14All builds and outputs go into a temporary directory (or --work-directory).
25Here = os.path.dirname(os.path.abspath(__file__))
26PeanoRoot = os.path.abspath(os.path.join(Here,
"..",
"..",
".."))
27sys.path.insert(0, os.path.join(PeanoRoot,
"src"))
32import matplotlib.patches
33import matplotlib.pyplot
as plt
42 const double irho = 1.0 / Q[0];
43 constexpr double gamma = 1.4;
44 const double p = (gamma - 1.0) * (Q[3] - 0.5 * irho * (Q[1] * Q[1] + Q[2] * Q[2]));
48 F[1] = irho * Q[1] * Q[1] + p;
49 F[2] = irho * Q[1] * Q[2];
50 F[3] = irho * Q[1] * (Q[3] + p);
54 F[1] = irho * Q[2] * Q[1];
55 F[2] = irho * Q[2] * Q[2] + p;
56 F[3] = irho * Q[2] * (Q[3] + p);
62 const double irho = 1.0 / Q[0];
63 constexpr double gamma = 1.4;
64 const double p = (gamma - 1.0) * (Q[3] - 0.5 * irho * (Q[1] * Q[1] + Q[2] * Q[2]));
65 const double c = std::sqrt(gamma * p * irho);
66 const double u = Q[1 + normal] * irho;
67 lambdaMax[0] = std::max(std::abs(u + c), std::abs(u - c));
71 constexpr double gamma = 1.4;
72 constexpr double p = 1.0;
73 constexpr double u = 1.0;
74 const double rho = 1.0 + 0.2 * std::sin(2.0 * M_PI * (x[0] + 0.1) / 0.2);
78 Q[3] = p / (gamma - 1) + 0.5 * rho * u * u;
82TimeInBetweenPlots = 0.005
83PatchFile =
"solution-EulerFV.peano-patch-file"
87 """! Density of the entropy wave advected with u=1 over [-0.1,0.1]"""
88 return 1.0 + 0.2 * np.sin(2.0 * np.pi * (np.asarray(x) - t + 0.1) / 0.2)
92 """! Generate, compile and run the tutorial setup within directory"""
94 namespace=[
"tutorials",
"exahype2",
"euler"],
100 solver.add_user_solver_includes(
"#include <cmath>\n#include <algorithm>\n")
110 solver, volume_size=volume_size
113 solver, first_plot_time_stamp=0.0, time_in_between_plots=TimeInBetweenPlots
115 project.add_solver(solver)
116 project.set_global_simulation_parameters(
120 min_end_time=EndTime,
121 max_end_time=EndTime,
122 periodic_BC=[
True,
True,
True],
124 project.set_Peano4_installation(PeanoRoot, peano4.api.output.CompileMode.RELEASE)
125 peano4_project = project.generate_Peano4_project()
126 peano4_project.generate()
127 subprocess.run([
"make",
"-j"], cwd=directory, check=
True, stdout=subprocess.DEVNULL)
128 subprocess.run([
"./euler"], cwd=directory, check=
True, stdout=subprocess.DEVNULL)
132 os.path.join(PeanoRoot,
"src",
"tarch",
"plotter",
"api",
"probe.py"),
144 stdout=subprocess.DEVNULL,
145 env=dict(os.environ, PYTHONPATH=os.path.join(PeanoRoot,
"src")),
150 """! Return arrays time, density from the probe's csv file"""
151 with open(os.path.join(directory,
"probe.csv"))
as csv_file:
152 rows = list(csv.DictReader(csv_file))
154 np.array([float(row[
"time"])
for row
in rows]),
155 np.array([float(row[
"EulerFVQ_0"])
for row
in rows]),
160 """! Return time stamp plus volume centres and densities along y=0"""
162 os.path.join(directory, PatchFile)
165 for patch_file
in patch_files:
167 if offset[1] <= 0.0 < offset[1] + size[1]:
168 dof = values.shape[0]
170 row = int((0.0 - offset[1]) / (size[1] / dof))
172 x.append(offset[0] + (i + 0.5) * h)
173 rho.append(values[row, i, 0])
174 order = np.argsort(x)
175 return time_stamp, np.array(x)[order], np.array(rho)[order]
179 """! Initial density plus patch boundaries and the volumes of one patch"""
180 file_name = os.path.join(directory, PatchFile)
186 for offset, size, values
in patches:
188 matplotlib.patches.Rectangle(
189 offset, size[0], size[1], fill=
False, edgecolor=
"white", linewidth=1.2
193 offset, size, values = min(patches, key=
lambda p: (p[0][0] ** 2 + p[0][1] ** 2))
194 dof = values.shape[0]
195 for i
in range(1, dof):
197 [offset[0] + i * size[0] / dof] * 2,
198 [offset[1], offset[1] + size[1]],
203 [offset[0], offset[0] + size[0]],
204 [offset[1] + i * size[1] / dof] * 2,
209 matplotlib.patches.Rectangle(
210 offset, size[0], size[1], fill=
False, edgecolor=
"red", linewidth=1.5
214 "Initial density\n{0}x{0} patches, {1}x{1} volumes per patch".format(
215 round(0.2 / size[0]), dof
219 os.path.join(Here,
"10_euler-mesh.png"), dpi=100, bbox_inches=
"tight"
225 """! Density along y=0 at a few time stamps against the exact solution"""
226 fig, ax = plt.subplots(figsize=(7, 4))
227 x_exact = np.linspace(-0.1, 0.1, 400)
231 for snapshot, colour
in zip(
232 [0, (snapshots - 1) // 4, (snapshots - 1) // 2], [
"C0",
"C1",
"C2"]
235 ax.plot(x_exact,
exact_density(x_exact, t), color=colour, linewidth=1)
236 ax.plot(x, rho,
"o", color=colour, markersize=2.5, label=
"t={:.3f}".format(t))
238 ax.set_ylabel(
"density")
239 ax.set_title(
"Density along y=0: ExaHyPE (dots) vs exact solution (lines)")
242 os.path.join(Here,
"10_euler-advection.png"), dpi=100, bbox_inches=
"tight"
248 """! Probe at the origin over time against the exact sine"""
250 t_exact = np.linspace(0, EndTime, 400)
251 fig, ax = plt.subplots(figsize=(7, 4))
257 label=
"exact: 1+0.2 sin(10 pi t)",
259 ax.plot(t, rho,
"o", markersize=3, label=
"probe.py at (0,0)")
261 ax.set_ylabel(
"density")
262 ax.set_title(
"Density at the origin over time")
264 fig.savefig(os.path.join(Here,
"10_euler-probe.png"), dpi=100, bbox_inches=
"tight")
269 """! Probe error over time for several volume sizes"""
270 fig, ax = plt.subplots(figsize=(7, 4))
271 for volume_size, directory
in directories:
279 label=
"volume_size={}: max error {:.4f}".format(volume_size, error.max()),
282 ax.set_ylabel(
"|density - exact density| at (0,0)")
283 ax.set_title(
"Error at the probe point for two mesh resolutions")
286 os.path.join(Here,
"10_euler-convergence.png"), dpi=100, bbox_inches=
"tight"
291if __name__ ==
"__main__":
292 parser = argparse.ArgumentParser(
293 description=
"Create the PNGs of the tutorial 10_euler.ipynb"
298 help=
"Directory for builds and outputs (default: temporary directory)",
300 args = parser.parse_args()
302 work_directory = args.work_directory
or tempfile.mkdtemp(prefix=
"10_euler-")
304 for volume_size
in [0.005, 0.001]:
305 directory = os.path.join(work_directory,
"volume-size-{}".format(volume_size))
306 os.makedirs(directory, exist_ok=
True)
307 print(
"build and run volume size {} in {}".format(volume_size, directory))
309 runs.append((volume_size, directory))
315 print(
"wrote PNGs into {}".format(Here))
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-...
Setup phase counterpart to RusanovWithExplicitEuler: sets the initial condition for a Finite Volume s...
plot_convergence(directories)
Probe error over time for several volume sizes.
density_along_x_axis(directory, snapshot)
Return time stamp plus volume centres and densities along y=0.
build_and_run(volume_size, directory)
Generate, compile and run the tutorial setup within directory.
plot_probe(directory)
Probe at the origin over time against the exact sine.
plot_advection(directory)
Density along y=0 at a few time stamps against the exact solution.
plot_mesh(directory)
Initial density plus patch boundaries and the volumes of one patch.
exact_density(x, t)
Density of the entropy wave advected with u=1 over [-0.1,0.1].
read_probe(directory)
Return arrays time, density from the probe's csv file.
Interactive visualisation of Peano patch files within Jupyter notebooks.
plot_snapshot(file_name, snapshot=-1, unknown=0, clim=None, ax=None, cmap="viridis", label=None)
Plot one unknown of one snapshot.
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.