5Create the PNG illustrations of the tutorial 13_euler-with-amr.ipynb
7The script builds the tutorial's point explosion on a regular grid, runs
8it and writes all pictures into the directory of this script. It then
9builds the setup with the point-wise refinement criterion, runs it on the
10resulting adaptive mesh, and draws the mesh, the solution, a comparison
11with the regular mesh, plus the setup's task graph. Finally, it runs the
12dynamically adaptive setup, which also erases cells while it runs time
13steps, and draws its mesh adaptation task graph, the number of patches
14over time and the mesh before and after it changes. Finally, it runs the
15same dynamically adaptive setup with the gradient-based criterion and
16compares the density profiles, the meshes and the numbers of patches of
17the two criteria. The PDE terms are injected from Python, i.e. we do not
18need any hand-written C++ file. Call it from anywhere:
20 python3 tutorials/exahype2/illustrations/13_euler-with-amr.py
22Pass --gradient-only to create only the pictures of the gradient section.
24All builds and outputs go into a temporary directory (or --work-directory).
35Here = os.path.dirname(os.path.abspath(__file__))
36PeanoRoot = os.path.abspath(os.path.join(Here,
"..",
"..",
".."))
37sys.path.insert(0, os.path.join(PeanoRoot,
"src"))
42import matplotlib.patches
43import matplotlib.pyplot
as plt
52 const double irho = 1.0 / Q[0];
53 constexpr double gamma = 1.4;
54 const double p = (gamma - 1.0) * (Q[3] - 0.5 * irho * (Q[1] * Q[1] + Q[2] * Q[2]));
58 F[1] = irho * Q[1] * Q[1] + p;
59 F[2] = irho * Q[1] * Q[2];
60 F[3] = irho * Q[1] * (Q[3] + p);
64 F[1] = irho * Q[2] * Q[1];
65 F[2] = irho * Q[2] * Q[2] + p;
66 F[3] = irho * Q[2] * (Q[3] + p);
72 const double irho = 1.0 / Q[0];
73 constexpr double gamma = 1.4;
74 const double p = (gamma - 1.0) * (Q[3] - 0.5 * irho * (Q[1] * Q[1] + Q[2] * Q[2]));
75 const double c = std::sqrt(gamma * p * irho);
76 const double u = Q[1 + normal] * irho;
77 lambdaMax[0] = std::max(std::abs(u + c), std::abs(u - c));
81 constexpr double gamma = 1.4;
82 constexpr double radius = 0.1;
83 const bool inside = x[0] * x[0] + x[1] * x[1] < radius * radius;
84 const double rho = inside ? 1.0 : 0.125;
85 const double p = inside ? 1.0 : 0.1;
89 Q[3] = p / (gamma - 1.0);
93AdaptiveVolumeSize = 0.02
94AdaptiveMinVolumeSize = 0.002
95RefineErasePointwisely =
"""
96 if (Q[0] > 0.8) *refinementCommand = ::exahype2::RefinementCommand::Refine;
98DynamicRefineErasePointwisely =
"""
99 if (Q[0] > 0.8) *refinementCommand = ::exahype2::RefinementCommand::Refine;
100 else if (Q[0] < 0.1) *refinementCommand = ::exahype2::RefinementCommand::Erase;
102GradientRefinement =
"""
103 const double densityGradient = std::abs(gradient[0]);
104 if (densityGradient > 5.0) *refinementCommand = ::exahype2::RefinementCommand::Refine;
105 else if (densityGradient < 1.0) *refinementCommand = ::exahype2::RefinementCommand::Erase;
109TimeInBetweenPlots = 0.01
110PatchFile =
"solution-EulerFV.peano-patch-file"
112FD4InitPointWisely =
"""
113 constexpr double gamma = 1.4;
114 constexpr double width = 0.05;
115 const double r2 = x[0] * x[0] + x[1] * x[1];
116 const double rho = 1.0 + 0.5 * std::exp(-r2 / (width * width));
117 const double p = std::pow(rho, gamma);
121 Q[3] = p / (gamma - 1.0);
123FD4PatchFile =
"solution-EulerFD4.peano-patch-file"
129 The tutorial's solver over a regular, an adaptive or a dynamically
132 With gradient, the solver refines and erases with the gradient-based
133 criterion instead of the point-wise one. The flag implies a dynamically
138 solver.add_user_solver_includes(
"#include <cmath>\n#include <algorithm>\n")
146 if adaptive
and gradient:
153 implementation=DynamicRefineErasePointwisely
155 else RefineErasePointwisely
162 min_volume_size=AdaptiveMinVolumeSize,
163 max_volume_size=AdaptiveVolumeSize,
168 solver.grid_construction = (
171 volume_size=AdaptiveVolumeSize,
172 min_volume_size=AdaptiveMinVolumeSize,
177 solver, volume_size=VolumeSize
180 solver, first_plot_time_stamp=0.0, time_in_between_plots=TimeInBetweenPlots
186 """! Generate, compile and run the tutorial setup within directory"""
187 end_time = DynamicEndTime
if dynamic
or gradient
else EndTime
189 namespace=[
"tutorials",
"exahype2",
"euler"],
190 project_name=
"Euler",
195 project.add_solver(solver)
196 project.set_global_simulation_parameters(
200 min_end_time=end_time,
201 max_end_time=end_time,
202 periodic_BC=[
True,
True,
True],
204 project.set_Peano4_installation(PeanoRoot, peano4.api.output.CompileMode.RELEASE)
205 peano4_project = project.generate_Peano4_project()
206 peano4_project.generate()
207 subprocess.run([
"make",
"-j"], cwd=directory, check=
True, stdout=subprocess.DEVNULL)
208 subprocess.run([
"./euler"], cwd=directory, check=
True, stdout=subprocess.DEVNULL)
214 Generate, compile and run the fourth-order Finite Differences over the
215 regular mesh within directory
217 The run writes its output into directory/run.log, so we can parse the
218 time step sizes afterwards. A run of the point explosion breaks down
219 early, so we do not check its exit code.
223 namespace=[
"tutorials",
"exahype2",
"euler"],
224 project_name=
"Euler",
229 solver.add_user_solver_includes(
"#include <cmath>\n#include <algorithm>\n")
238 solver, patch_size=9, rk_order=4
241 solver, volume_size=VolumeSize
244 solver, first_plot_time_stamp=0.0, time_in_between_plots=TimeInBetweenPlots
246 project.add_solver(solver)
247 project.set_global_simulation_parameters(
251 min_end_time=EndTime,
252 max_end_time=EndTime,
253 periodic_BC=[
True,
True,
True],
255 project.set_Peano4_installation(PeanoRoot, peano4.api.output.CompileMode.RELEASE)
256 peano4_project = project.generate_Peano4_project()
257 peano4_project.generate()
258 subprocess.run([
"make",
"-j"], cwd=directory, check=
True, stdout=subprocess.DEVNULL)
259 with open(os.path.join(directory,
"run.log"),
"w")
as log:
260 subprocess.run([
"./euler"], cwd=directory, stdout=log, stderr=subprocess.STDOUT)
264 """! Return the time stamp and all patches (offset, size, values) of a snapshot"""
266 os.path.join(directory, patch_file)
268 time_stamp, patch_files = snapshots[snapshot]
272 return time_stamp, patches
282 """! Return time stamp plus volume centres and densities along y=0, x>=0"""
283 time_stamp, patches =
read_snapshot(directory, snapshot, patch_file)
285 for offset, size, values
in patches:
286 if offset[1] <= 0.0 < offset[1] + size[1]:
287 dof = values.shape[0]
289 row = int((0.0 - offset[1]) / (size[1] / dof))
291 centre = offset[0] + (i + 0.5) * h
294 rho.append(values[row, i, 0])
295 order = np.argsort(x)
296 return time_stamp, np.array(x)[order], np.array(rho)[order]
300 """! Initial density plus the patch boundaries"""
301 file_name = os.path.join(directory, PatchFile)
304 for offset, size, values
in patches:
306 matplotlib.patches.Rectangle(
307 offset, size[0], size[1], fill=
False, edgecolor=
"white", linewidth=0.4
311 "Initial density\n{0}x{0} patches, {1}x{1} volumes per patch".format(
312 round(1.0 / patches[0][1][0]), patches[0][2].shape[0]
316 os.path.join(Here,
"13_euler-with-amr-mesh.png"), dpi=100, bbox_inches=
"tight"
322 """! Density at three time stamps side by side"""
323 file_name = os.path.join(directory, PatchFile)
325 fig, axes = plt.subplots(1, 3, figsize=(15, 4.5))
326 for ax, snapshot
in zip(
327 axes, [(snapshots - 1) // 4, (snapshots - 1) // 2, snapshots - 1]
330 file_name, snapshot, 0, label=
"density", ax=ax
334 os.path.join(Here,
"13_euler-with-amr-snapshots.png"),
342 """! Density along the positive x-axis at a few time stamps"""
343 fig, ax = plt.subplots(figsize=(7, 4))
345 for snapshot, colour
in zip(
346 [0, (snapshots - 1) // 4, (snapshots - 1) // 2, snapshots - 1],
347 [
"C0",
"C1",
"C2",
"C3"],
357 label=
"t={:.2f}".format(t),
359 ax.set_xlabel(
"distance r from the centre (along y=0)")
360 ax.set_ylabel(
"density")
361 ax.set_title(
"Density profile of the point explosion")
364 os.path.join(Here,
"13_euler-with-amr-profile.png"),
374 Highlight the patches which hold steep density gradients at the end
376 A patch counts as active if the largest density jump between two
377 neighbouring volumes within the patch exceeds 20% of the largest such
378 jump in the whole domain. This is the kind of quantity a refinement
379 criterion would look at.
382 file_name = os.path.join(directory, PatchFile)
385 file_name, snapshot, 0, label=
"density"
389 def max_jump(values):
392 np.abs(np.diff(rho, axis=0)).max(), np.abs(np.diff(rho, axis=1)).max()
395 jumps = [max_jump(values)
for _, _, values
in patches]
396 threshold = 0.2 * max(jumps)
398 for (offset, size, values), jump
in zip(patches, jumps):
402 matplotlib.patches.Rectangle(
406 facecolor=(1.0, 0.0, 0.0, 0.35),
412 "t={:.2f}: {} of {} patches ({:.0f}%) hold steep gradients".format(
413 t, active, len(patches), 100.0 * active / len(patches)
417 os.path.join(Here,
"13_euler-with-amr-active-patches.png"),
422 print(
"{} of {} patches are active".format(active, len(patches)))
426 """! Initial density on the adaptive mesh plus the patch boundaries"""
427 file_name = os.path.join(directory, PatchFile)
430 for offset, size, values
in patches:
432 matplotlib.patches.Rectangle(
433 offset, size[0], size[1], fill=
False, edgecolor=
"white", linewidth=0.3
436 sizes = sorted({round(size[0], 6)
for _, size, _
in patches}, reverse=
True)
437 counts = [sum(1
for _, size, _
in patches
if round(size[0], 6) == h)
for h
in sizes]
439 "Initial density on the adaptive mesh\n"
441 "{} patches of size 1/{}".format(count, round(1.0 / h))
442 for h, count
in zip(sizes, counts)
447 os.path.join(Here,
"13_euler-with-amr-adaptive-mesh.png"),
452 print(
"adaptive mesh: {}".format(dict(zip(sizes, counts))))
456 """! Density at three time stamps on the adaptive mesh plus patch boundaries"""
457 file_name = os.path.join(directory, PatchFile)
459 fig, axes = plt.subplots(1, 3, figsize=(15, 4.5))
460 for ax, snapshot
in zip(
461 axes, [(snapshots - 1) // 4, (snapshots - 1) // 2, snapshots - 1]
464 file_name, snapshot, 0, label=
"density", ax=ax
467 for offset, size, values
in patches:
469 matplotlib.patches.Rectangle(
480 os.path.join(Here,
"13_euler-with-amr-adaptive-snapshots.png"),
488 """! Density along the positive x-axis: regular against adaptive mesh"""
489 fig, ax = plt.subplots(figsize=(7, 4))
492 for snapshot, colour
in zip(
493 [(snapshots - 1) // 4, (snapshots - 1) // 2, snapshots - 1],
503 label=
"regular, t={:.2f}".format(t),
512 label=
"adaptive, t={:.2f}".format(t),
514 ax.set_xlabel(
"distance r from the centre (along y=0)")
515 ax.set_ylabel(
"density")
516 ax.set_title(
"Regular mesh (lines) against adaptive mesh (dots)")
517 ax.legend(fontsize=8)
519 os.path.join(Here,
"13_euler-with-amr-profile-comparison.png"),
527 """! Total mass and energy of the first and the last snapshot"""
531 values[..., 0].sum() * (size[0] / values.shape[0]) ** 2
532 for _, size, values
in patches
535 values[..., 3].sum() * (size[0] / values.shape[0]) ** 2
536 for _, size, values
in patches
538 print(
"t={:.3f}: mass={:.8f}, energy={:.8f}".format(t, mass, energy))
542 """! Construct the setup task graph with the refinement criterion and draw it"""
544 tempfile.gettempdir(),
"13-euler-with-amr-log.md"
546 with tempfile.TemporaryDirectory()
as directory:
548 [
"illustration"],
"illustration", directory=directory
551 exahype2_project = types.SimpleNamespace(periodic_BC=[
True,
True,
True])
553 solver.grid_construction.construct_output(
554 exahype2_project, peano_project, setup_simulation
556 setup_simulation.visualise(
557 title=
"Setup task graph with point-wise refinement criterion"
559 output = os.path.join(Here,
"13_euler-with-amr-setup-task-graph.png")
560 plt.gcf().savefig(output, dpi=90)
562 print(
"Wrote", output)
566 """! Time stamps and numbers of patches of all snapshots"""
567 times, counts = [], []
571 counts.append(len(patches))
576 """! Number of patches per snapshot of the dynamically adaptive run"""
578 fig, ax = plt.subplots(figsize=(7, 3.5))
579 ax.step(times, counts, where=
"post", marker=
"o", markersize=3)
580 ax.set_xlabel(
"time")
581 ax.set_ylabel(
"number of patches")
582 ax.set_title(
"Patches of the dynamically adaptive mesh")
584 os.path.join(Here,
"13_euler-with-amr-dynamic-patch-count.png"),
589 print(
"patch counts: {}".format(list(zip([round(t, 3)
for t
in times], counts))))
593 """! Density and patch boundaries right before the first mesh change and at the end"""
595 changes = [i
for i
in range(1, len(counts))
if counts[i] != counts[i - 1]]
597 print(
"the dynamically adaptive mesh has not changed")
599 file_name = os.path.join(directory, PatchFile)
600 fig, axes = plt.subplots(1, 2, figsize=(11, 4.5))
601 for ax, snapshot
in zip(axes, [changes[0] - 1, len(counts) - 1]):
603 file_name, snapshot, 0, label=
"density", ax=ax, clim=(0.0, 0.4)
606 for offset, size, values
in patches:
608 matplotlib.patches.Rectangle(
617 ax.set_xlim(-0.3, 0.3)
618 ax.set_ylim(-0.3, 0.3)
620 "t={:.2f}: {} patches".format(times[snapshot], counts[snapshot]),
625 os.path.join(Here,
"13_euler-with-amr-dynamic-mesh-change.png"),
635 Snapshots for the comparison of the point-wise and the gradient-based
636 criterion: t=0.1, 0.2 and 0.25. We stop before t=0.3, as the shock
637 then reaches the periodic boundary.
642 min(range(len(times)), key=
lambda i: abs(times[i] - t))
643 for t
in [0.1, 0.2, 0.25]
648 """! Density along the positive x-axis: point-wise against gradient-based criterion"""
649 fig, ax = plt.subplots(figsize=(7, 4))
650 for snapshot, colour
in zip(
660 label=
"point-wise, t={:.2f}".format(t),
669 label=
"gradient, t={:.2f}".format(t),
671 ax.set_xlabel(
"distance r from the centre (along y=0)")
672 ax.set_ylabel(
"density")
673 ax.set_title(
"Point-wise criterion (lines) against gradient criterion (dots)")
674 ax.legend(fontsize=8)
676 os.path.join(Here,
"13_euler-with-amr-gradient-profile.png"),
684 """! Number of patches per snapshot of both dynamically adaptive runs"""
685 fig, ax = plt.subplots(figsize=(7, 3.5))
686 for directory, label
in [
687 (pointwise_directory,
"point-wise criterion"),
688 (gradient_directory,
"gradient criterion"),
691 ax.step(times, counts, where=
"post", marker=
"o", markersize=3, label=label)
692 print(
"{}: {}".format(label, list(zip([round(t, 3)
for t
in times], counts))))
693 ax.set_xlabel(
"time")
694 ax.set_ylabel(
"number of patches")
695 ax.set_title(
"Patches of the dynamically adaptive meshes")
698 os.path.join(Here,
"13_euler-with-amr-gradient-patch-count.png"),
708 Density and patch boundaries of both runs at t=0.2
710 We zoom into the upper right quadrant, as the boundaries of the fine
711 patches would otherwise hide the solution.
715 fig, axes = plt.subplots(1, 2, figsize=(11, 4.5))
716 for ax, directory, label
in zip(
718 [pointwise_directory, gradient_directory],
719 [
"point-wise criterion",
"gradient criterion"],
722 os.path.join(directory, PatchFile),
730 for offset, size, values
in patches:
732 matplotlib.patches.Rectangle(
741 ax.set_xlim(0.0, 0.5)
742 ax.set_ylim(0.0, 0.5)
744 "{}, t={:.2f}: {} patches".format(label, t, len(patches)), fontsize=10
748 os.path.join(Here,
"13_euler-with-amr-gradient-mesh.png"),
758 Run the gradient-based criterion and compare it to the point-wise one
760 Expects the point-wise dynamically adaptive run within dynamic_directory.
764 print(
"build and run with gradient criterion in {}".format(gradient_directory))
765 build_and_run(gradient_directory, adaptive=
True, gradient=
True)
773 """! Time step sizes of the fourth-order Finite Differences for the point explosion"""
774 times, sizes = [], []
775 with open(os.path.join(directory,
"run.log"))
as log:
777 match = re.search(
r"\bt=([0-9.eE+-]+), new dt=([0-9.eE+-]+)", line)
779 times.append(float(match.group(1)))
780 sizes.append(float(match.group(2)))
781 fig, ax = plt.subplots(figsize=(7, 3.5))
782 ax.semilogy(times, sizes, marker=
"o", markersize=2, linewidth=0.8)
783 ax.set_xlabel(
"time")
784 ax.set_ylabel(
"time step size")
785 ax.set_title(
"Fourth-order Finite Differences for the point explosion")
787 os.path.join(Here,
"13_euler-with-amr-fd4-explosion-time-step-size.png"),
793 "FD4 explosion: {} time steps, last t={}, first dt={}, last dt={}".format(
794 len(times), times[-1], sizes[0], sizes[-1]
800 """! Density of the Gaussian pulse at three time stamps side by side"""
801 file_name = os.path.join(directory, FD4PatchFile)
803 fig, axes = plt.subplots(1, 3, figsize=(15, 4.5))
804 for ax, snapshot
in zip(
805 axes, [(snapshots - 1) // 4, (snapshots - 1) // 2, snapshots - 1]
808 file_name, snapshot, 0, label=
"density", ax=ax
812 os.path.join(Here,
"13_euler-with-amr-fd4-snapshots.png"),
820 """! Density of the Gaussian pulse along the positive x-axis at a few time stamps"""
821 fig, ax = plt.subplots(figsize=(7, 4))
823 for snapshot, colour
in zip(
824 [0, (snapshots - 1) // 4, (snapshots - 1) // 2, snapshots - 1],
825 [
"C0",
"C1",
"C2",
"C3"],
835 label=
"t={:.2f}".format(t),
838 "FD4 pulse t={:.2f}: density in [{:.4f},{:.4f}], maximum at r={:.3f}".format(
839 t, rho.min(), rho.max(), x[np.argmax(rho)]
842 ax.set_xlabel(
"distance r from the centre (along y=0)")
843 ax.set_ylabel(
"density")
844 ax.set_title(
"Density profile of the Gaussian pulse (FD4)")
847 os.path.join(Here,
"13_euler-with-amr-fd4-profile.png"),
855 """! Construct the mesh adaptation task graph of the dynamically adaptive setup and draw it"""
857 tempfile.gettempdir(),
"13-euler-with-amr-log.md"
859 with tempfile.TemporaryDirectory()
as directory:
861 [
"illustration"],
"illustration",
"illustration", directory=directory
863 exahype2_project.set_global_simulation_parameters(
867 min_end_time=DynamicEndTime,
868 periodic_BC=[
True,
True,
True],
871 [
"illustration"],
"illustration", directory=directory
875 solver.generate_solver_realisation(exahype2_project, peano_project, *graphs)
876 graphs[3].visualise(title=
"Mesh adaptation and load balancing task graph")
877 output = os.path.join(Here,
"13_euler-with-amr-mesh-adaptation-task-graph.png")
878 plt.gcf().savefig(output, dpi=90)
880 print(
"Wrote", output)
883if __name__ ==
"__main__":
884 parser = argparse.ArgumentParser(
885 description=
"Create the PNGs of the tutorial 13_euler-with-amr.ipynb"
890 help=
"Directory for builds and outputs (default: temporary directory)",
895 help=
"Reuse the output of a previous run within the work directory",
900 help=
"Create only the pictures of the section on the fourth-order Finite Differences",
905 help=
"Create only the pictures of the section on the gradient-based refinement",
907 args = parser.parse_args()
909 work_directory = args.work_directory
or tempfile.mkdtemp(
910 prefix=
"13_euler-with-amr-"
912 dynamic_directory = os.path.join(work_directory,
"dynamic-mesh")
913 gradient_directory = os.path.join(work_directory,
"gradient-mesh")
914 if args.gradient_only:
915 os.makedirs(dynamic_directory, exist_ok=
True)
916 os.makedirs(gradient_directory, exist_ok=
True)
917 if not args.skip_run:
919 "build and run over dynamically adaptive mesh in {}".format(
925 print(
"wrote PNGs into {}".format(Here))
928 fd4_explosion_directory = os.path.join(work_directory,
"fd4-explosion")
929 fd4_pulse_directory = os.path.join(work_directory,
"fd4-pulse")
930 os.makedirs(fd4_explosion_directory, exist_ok=
True)
931 os.makedirs(fd4_pulse_directory, exist_ok=
True)
932 if not args.skip_run:
934 "build and run FD4 in {} and {}".format(
935 fd4_explosion_directory, fd4_pulse_directory
944 print(
"wrote PNGs into {}".format(Here))
947 directory = os.path.join(work_directory,
"regular-grid")
948 os.makedirs(directory, exist_ok=
True)
949 if not args.skip_run:
950 print(
"build and run in {}".format(directory))
958 adaptive_directory = os.path.join(work_directory,
"adaptive-mesh")
959 os.makedirs(adaptive_directory, exist_ok=
True)
960 if not args.skip_run:
961 print(
"build and run over adaptive mesh in {}".format(adaptive_directory))
969 os.makedirs(dynamic_directory, exist_ok=
True)
970 if not args.skip_run:
972 "build and run over dynamically adaptive mesh in {}".format(
976 build_and_run(dynamic_directory, adaptive=
True, dynamic=
True)
982 os.makedirs(gradient_directory, exist_ok=
True)
984 print(
"wrote PNGs into {}".format(Here))
The conservative flux F(Q) of a hyperbolic PDE.
Gradient-based refinement criterion: given a one-sided difference quotient of the solution along one ...
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.
Point-wise refinement criterion: given the solution Q at a single degree of freedom,...
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...
Setup over a regular mesh which is then refined adaptively by the user's adaptivity criterion.
Fourth-order central Finite Differences with explicit Runge-Kutta time stepping, realised over a bloc...
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.
build_and_run(directory, adaptive=False, dynamic=False, gradient=False)
Generate, compile and run the tutorial setup within directory.
patch_counts(directory)
Time stamps and numbers of patches of all snapshots.
plot_gradient_mesh(pointwise_directory, gradient_directory)
Density and patch boundaries of both runs at t=0.2.
plot_gradient_profile_comparison(pointwise_directory, gradient_directory)
Density along the positive x-axis: point-wise against gradient-based criterion.
create_solver(adaptive, dynamic=False, gradient=False)
The tutorial's solver over a regular, an adaptive or a dynamically adaptive mesh.
plot_fd4_explosion_time_step_sizes(directory)
Time step sizes of the fourth-order Finite Differences for the point explosion.
build_and_run_fd4(directory, init_point_wisely)
Generate, compile and run the fourth-order Finite Differences over the regular mesh within directory.
plot_dynamic_mesh_change(directory)
Density and patch boundaries right before the first mesh change and at the end.
plot_gradient_patch_counts(pointwise_directory, gradient_directory)
Number of patches per snapshot of both dynamically adaptive runs.
plot_mesh(directory)
Initial density plus the patch boundaries.
plot_setup_task_graph()
Construct the setup task graph with the refinement criterion and draw it.
print_conservation(directory)
Total mass and energy of the first and the last snapshot.
plot_fd4_profile(directory)
Density of the Gaussian pulse along the positive x-axis at a few time stamps.
read_snapshot(directory, snapshot, patch_file=PatchFile)
Return the time stamp and all patches (offset, size, values) of a snapshot.
plot_profile_comparison(regular_directory, adaptive_directory)
Density along the positive x-axis: regular against adaptive mesh.
plot_profile(directory)
Density along the positive x-axis at a few time stamps.
gradient_snapshots(directory)
Snapshots for the comparison of the point-wise and the gradient-based criterion: t=0....
plot_active_patches(directory)
Highlight the patches which hold steep density gradients at the end.
plot_snapshots(directory)
Density at three time stamps side by side.
plot_mesh_adaptation_task_graph()
Construct the mesh adaptation task graph of the dynamically adaptive setup and draw it.
plot_adaptive_mesh(directory)
Initial density on the adaptive mesh plus the patch boundaries.
create_gradient_pictures(dynamic_directory, gradient_directory, skip_run)
Run the gradient-based criterion and compare it to the point-wise one.
plot_dynamic_patch_count(directory)
Number of patches per snapshot of the dynamically adaptive run.
number_of_snapshots(directory, patch_file=PatchFile)
plot_fd4_snapshots(directory)
Density of the Gaussian pulse at three time stamps side by side.
plot_adaptive_snapshots(directory)
Density at three time stamps on the adaptive mesh plus patch boundaries.
density_along_x_axis(directory, snapshot, patch_file=PatchFile)
Return time stamp plus volume centres and densities along y=0, x>=0.
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.