Skip to content

Visualizing the results

A run writes numbers; understanding comes from pictures. The tools/ folder in the download turns snapshots into pictures of every field, field lines and flows, movies, and 3D views. All of them run from the splmhd folder and save their output in output/<run>/plots/.

Tool What it makes Needs
monitor.py The live monitor: a run window (stages, energy, rate, checks) and windows for B, J, v and ρ, p, T numpy, matplotlib
paraview_live.py Opens ParaView with a ready 3D scene, also while a run is going ParaView
plot_fields.py A 3×3 overview, or single fields, for one or all snapshots numpy, matplotlib
plot_timeseries.py Energy budget, reconnected flux and rate, numerical checks numpy, matplotlib
make_movie.py Animated GIF of one field through time numpy, matplotlib
view3d.py Interactive 3D page: field lines, \(\mathbf{B}\) and \(\mathbf{v}\) arrows, the current sheet, slices plotly
show_initial.py The initial state of a config, before you run it (in the lab: type show) numpy, matplotlib
export_vtk.py VTK files for ParaView or VisIt numpy

You do not have to type any of these. The lab (Start Lab, see Run it on your computer) opens the live monitor while a run goes and makes the overview, the energy plot, the movie and, for 3D runs, the interactive page when it ends. The commands below are for when you want a particular picture, or want to know how it is made.

The live monitor

python3 tools/monitor.py output/cartesian_2d_harris          # follow a run that is going, or replay a finished one
python3 tools/monitor.py output/cartesian_2d_harris --save   # just save the five windows as pictures in plots/

Five windows: Run (algorithm stages, progress, energy, reconnection rate, checks, a plain-language reading and the buttons), Magnetic field (\(B_1, B_2, B_3, \lvert\mathbf{B}\rvert\)), Current (\(J_1, J_2, J_3\); in 3D also a 3D view), Flow (\(v_1, v_2, v_3\) and \(\lvert\mathbf{v}\rvert\) with arrows) and Plasma (\(\rho, p, T\)). Components 1, 2, 3 are \(x, y, z\) or \(r, \theta, \phi\). In 2D every panel carries field lines.

The monitor only reads files: the status.json that the solver rewrites once a second (stage, time, step, time step, speed), timeseries.csv and the snapshots. So it can be opened, closed and reopened at any time without disturbing the run, and it can replay any finished run. Its Pause and Stop buttons write the word pause or stop into control.txt in the run folder; the solver checks that file once a second. What each window shows is explained here.

Field names

Every tool uses the same names:

Name Field Name Field
rho density \(\rho\) vmag, v1, v2, v3 flow speed and velocity components
p pressure \(p\) Bmag, B1, B2, B3 field strength and components
T temperature \(p/\rho\) Jmag, J1, J2, J3 current density
beta plasma beta \(2p/B^2\) E1, E2, E3 electric field \(-\mathbf{v}\times\mathbf{B} + \eta\mathbf{J}\)
eta resistivity

Components 1, 2, 3 are \(x, y, z\) in Cartesian runs and \(r, \theta, \phi\) in spherical runs. For reconnection the most telling fields are J3 (the current sheet), E3 (the reconnection electric field), v1 (the outflow jets) and T (where the energy goes).

Overview of a snapshot

python tools/plot_fields.py output/cartesian_2d_harris              # last snapshot
python tools/plot_fields.py output/cartesian_2d_harris --snap 10    # snapshot 10
python tools/plot_fields.py output/cartesian_2d_harris --all        # every snapshot

The overview made by plot_fields.py

Black lines are magnetic field lines. In 2D they are contours of the flux function, \(A_z\) in Cartesian runs and \(r\sin\theta A_\phi\) in spherical ones; contours are field lines because \(\mathbf{B}\cdot\nabla\psi = 0\) (The flux function ψ). White arrows are the flow in the plane.

Spherical runs are drawn in the meridional plane, \(x = r\sin\theta\), \(z = r\cos\theta\), so they look like the real geometry:

Overview of the spherical dipole run

Single fields

python tools/plot_fields.py output/cartesian_2d_harris --fields J3,E3,v1,T --snap 10

Each field is saved as its own picture, larger and with a full title.

3D runs: slices

A 3D snapshot is cut by a plane. The default cut is normal to \(x_3\) (\(z\), or \(\phi\) in spherical runs) through the middle. Choose another with --normal (0, 1 or 2) and --index (the cell number along that direction):

python tools/plot_fields.py output/cartesian_3d_harris --normal 1 --fields J3,v1   # the x-z plane through the sheet
python tools/plot_fields.py output/cartesian_3d_harris --normal 2 --index 4      # an x-y plane near the edge

A slice through the 3D Harris run

The energy budget and checks

python tools/plot_timeseries.py output/cartesian_2d_harris

Timeseries made by plot_timeseries.py

  • Energy budget. Changes of magnetic, thermal and kinetic energy. Reconnection shows up as magnetic energy turning into heat and flow.
  • Reconnected flux and rate. The rate is the electric field at the X-line (why).
  • Peak current and speed. Current sheets thinning, jets accelerating.
  • Numerical checks. \(\nabla\cdot\mathbf{B}\) (should be about \(10^{-16}\)), and the relative change of mass and energy. If these grow suddenly, suspect the numerics before the physics.

Movies

python tools/make_movie.py output/cartesian_2d_harris --field J3
python tools/make_movie.py output/spherical_2d_dipole --field vmag --fps 6

This writes an animated GIF that any browser or slide program can show. More snapshots (a smaller dt_output in the config) make a smoother movie.

Interactive 3D in the browser

pip install plotly          # once
python tools/view3d.py output/cartesian_3d_harris --field Jmag --lines 30

This writes an HTML page that you can rotate and zoom. Click a name in its legend to show or hide that part:

  • magnetic field lines, coloured by where they go: blue on one side of the sheet (or the equator), red on the other, and green where a line crosses it. For a current sheet the green lines are the reconnected ones, so their number grows during the run;
  • arrows of the direction of \(\mathbf{B}\) on a coarse lattice (hover over one for \(|\mathbf{B}|\)), and arrows of the flow (off at first);
  • the current sheet, where \(|\mathbf{J}|\) is strong;
  • three see-through slices of the chosen field (--field, default \(|\mathbf{J}|\)). In spherical runs \(\mathbf{B}\) and \(\mathbf{J}\) fall off steeply with \(r\), so the slices show the field times \((r/r_{in})^p\), with \(p\) fitted to that fall-off: every variation along the sheet stays visible (--absolute shows the raw values).

In the live monitor of a 3D run, the magnetic window has the same picture as a 3D panel you can rotate with the mouse, and white arrows of the direction of \(\mathbf{B}\) on the \(|\mathbf{B}|\) slice.

How the field lines are traced

A field line is a curve everywhere tangent to \(\mathbf{B}\): \(d\mathbf{x}/ds = \mathbf{B}/|\mathbf{B}|\), with \(s\) the arc length. In curvilinear coordinates each component is divided by its scale factor, \(dx_i/ds = B_i/(h_i|\mathbf{B}|)\). view3d.py integrates this with a second-order Runge–Kutta step, interpolating \(\mathbf{B}\) trilinearly between cells, in both directions from each seed point, until the line leaves the box. The same idea with \(\mathbf{v}\) in place of \(\mathbf{B}\) gives streamlines of the flow.

ParaView for 3D

ParaView is a free, professional 3D visualization program. The quickest way in:

python3 tools/paraview_live.py output/cartesian_3d_harris

converts the snapshots, writes a scene script output/.../vtk/paraview_scene.py and starts ParaView with it: a slice coloured by \(\lvert\mathbf{J}\rvert\), an isosurface of the current sheet and field lines through it. The lab does this by itself, beside the live monitor, when you answer yes to ParaView for a 3D run. While a run is going, new snapshots appear after File → Reload Files → Find new files.

To build the scene yourself, convert snapshots to VTK first:

python tools/export_vtk.py output/cartesian_3d_harris          # all snapshots -> output/.../vtk/

Then in ParaView:

  1. File → Open the snap_..vtk files (they load as a time series) and press Apply.
  2. Colour by Jmag. Add Filters → Contour on Jmag for an isosurface of the current sheet.
  3. Add Filters → Stream Tracer with vectors B for magnetic field lines (or v for flow lines). Choose the Point Cloud seed type and place the seeds at the X-line.
  4. Add Filters → Slice to cut through the sheet; play the time series with the ▶ button.

Spherical runs are exported with Cartesian \((x, y, z)\) points and Cartesian vector components, so everything above works for them too.

Your own analysis in Python

Every snapshot is a NumPy .npz file. Arrays have shape (n1, n2, n3), vectors (3, n1, n2, n3):

import sys
sys.path.insert(0, ".")                      # run from the splmhd folder
import matplotlib.pyplot as plt
from splmhd.io import load_snapshot

d = load_snapshot("output/cartesian_2d_harris/snap_0010.npz")
x, y = d["x1"], d["x2"]
Bx = d["B"][0][len(x) // 2, :, 0]            # B_x along y, through the X-line (x = 0)
plt.plot(y, Bx)
plt.xlabel("y"); plt.ylabel("B_x"); plt.title(f"t = {d['t']:.0f}")
plt.show()

d["config"] holds the run's parameters, and splmhd.io.load_timeseries(run_dir) returns the diagnostics as a dictionary of columns.

Practice problems

Try each problem before opening its solution. Click an option to check a concept question.

Problem 1

Which field shows best where reconnection is happening right now?

  • The density \(\rho\)
  • The out-of-plane electric field \(E_z\) (or \(E_\phi\)) near the X-line
  • The magnetic field strength \(|\mathbf{B}|\)
  • The temperature

The out-of-plane electric field at the X-line is the rate at which flux is reconnected. Density and temperature record what has already happened, and \(|\mathbf{B}|\) is small at the X-line whether or not it is active.

Problem 2

Why are contours of \(A_z\) magnetic field lines in a 2D Cartesian run?

  • Because \(\mathbf{B}\cdot\nabla A_z = 0\): the field runs along the contours
  • Because \(A_z\) is proportional to \(|\mathbf{B}|\)
  • Because \(A_z\) is the electric potential
  • They are only approximately field lines

With \(B_x = \partial_yA_z\) and \(B_y = -\partial_xA_z\), \(\mathbf{B}\cdot\nabla A_z = \partial_yA_z\partial_xA_z - \partial_xA_z\partial_yA_z = 0\). In 2D they are exact; in a 3D slice they are not, which is why the 3D tools trace field lines instead.

Problem 3

In timeseries.png, \(\nabla\cdot\mathbf{B}\) jumps from \(10^{-16}\) to \(10^{-3}\) halfway through a run. What is the most likely explanation?

  • Reconnection creates magnetic monopoles
  • The plotting tool has a bug
  • Something has gone wrong numerically, for example the run is going unstable near a boundary
  • It is normal for \(\nabla\cdot\mathbf{B}\) to grow with time

With \(\mathbf{B} = \nabla\times\mathbf{A}\) the discrete divergence is zero to round-off in every physical cell. A large value means NaNs or extreme values are appearing, typically the first sign of an instability.