diff --git a/examples/RadiativeTransferTests/Advection_1D/makeIC.py b/examples/RadiativeTransferTests/Advection_1D/makeIC.py
index 508b96647d8360a76368090d14186e6e0c07d808..4b2abcb4a1563f59179eec151327e6135bb4cb7c 100755
--- a/examples/RadiativeTransferTests/Advection_1D/makeIC.py
+++ b/examples/RadiativeTransferTests/Advection_1D/makeIC.py
@@ -35,7 +35,6 @@ from swiftsimio import Writer
 import unyt
 import numpy as np
 import h5py
-from matplotlib import pyplot as plt
 
 # define unit system to use
 unitsystem = unyt.unit_systems.cgs_unit_system
@@ -83,7 +82,7 @@ def initial_condition(x):
     # Assuming all photons flow in only one direction
     # (optically thin regime, "free streaming limit"),
     #  we have that |F| = c * E
-    F = np.zeros(3, dtype=np.float32)
+    F = np.zeros(3, dtype=np.float64)
     F[0] = unyt.c.to(unitsystem["length"] / unitsystem["time"]) * E
 
     E_list.append(E)
@@ -99,7 +98,7 @@ def initial_condition(x):
     else:
         E = 1.0
 
-    F = np.zeros(3, dtype=np.float32)
+    F = np.zeros(3, dtype=np.float64)
     F[0] = unyt.c.to(unitsystem["length"] / unitsystem["time"]) * E
 
     E_list.append(E)
@@ -112,7 +111,7 @@ def initial_condition(x):
     amplitude = 2.0
 
     E = amplitude * np.exp(-(x[0] - mean) ** 2 / (2 * sigma ** 2))
-    F = np.zeros(3, dtype=np.float32)
+    F = np.zeros(3, dtype=np.float64)
     F[0] = unyt.c.to(unitsystem["length"] / unitsystem["time"]) * E
 
     E_list.append(E)
@@ -123,7 +122,7 @@ def initial_condition(x):
 
 if __name__ == "__main__":
 
-    xp = unyt.unyt_array(np.zeros((n_p, 3), dtype=np.float32), boxsize.units)
+    xp = unyt.unyt_array(np.zeros((n_p, 3), dtype=np.float64), boxsize.units)
 
     dx = boxsize / n_p
 
@@ -134,9 +133,9 @@ if __name__ == "__main__":
 
     w.gas.coordinates = xp
     w.gas.velocities = np.zeros(xp.shape) * (unyt.cm / unyt.s)
-    w.gas.masses = np.ones(xp.shape[0], dtype=np.float32) * 1000 * unyt.g
+    w.gas.masses = np.ones(xp.shape[0], dtype=np.float64) * 1000 * unyt.g
     w.gas.internal_energy = (
-        np.ones(xp.shape[0], dtype=np.float32) * (300.0 * unyt.kb * unyt.K) / (unyt.g)
+        np.ones(xp.shape[0], dtype=np.float64) * (300.0 * unyt.kb * unyt.K) / (unyt.g)
     )
 
     # Generate initial guess for smoothing lengths based on MIPS
@@ -172,6 +171,7 @@ if __name__ == "__main__":
             Fsetname = "PhotonFluxesGroup{0:d}".format(g + 1)
             parts[Fsetname][p] = Flux[g]
 
+    # from matplotlib import pyplot as plt
     #  plt.figure()
     #  for g in range(nPhotonGroups):
     #      #  Esetname = "PhotonEnergiesGroup{0:d}".format(g+1)
diff --git a/examples/RadiativeTransferTests/Advection_1D/plotSolution.py b/examples/RadiativeTransferTests/Advection_1D/plotSolution.py
index 00becd2d8e2ac96df2b9299c90fb9ce0b3ba6d82..8209e6fc58226a84741fe2854282c063e570545b 100755
--- a/examples/RadiativeTransferTests/Advection_1D/plotSolution.py
+++ b/examples/RadiativeTransferTests/Advection_1D/plotSolution.py
@@ -148,7 +148,7 @@ def plot_photons(filename, energy_boundaries=None, flux_boundaries=None):
                 advected_positions[overshooters] -= boxsize
 
         analytical_solutions = np.zeros(
-            (part_positions.shape[0], ngroups), dtype=np.float
+            (part_positions.shape[0], ngroups), dtype=np.float64
         )
         for p in range(part_positions.shape[0]):
             E, F = initial_condition(advected_positions[p])
@@ -319,7 +319,6 @@ def get_minmax_vals(snaplist):
 
             for direction in ["X"]:
                 #  for direction in ["X", "Y", "Z"]:
-                new_attribute_str = "radiation_flux" + str(g + 1) + direction
                 f = getattr(data.gas.photon_fluxes, "Group" + str(g + 1) + direction)
                 fluxmin_group.append(f.min())
                 fluxmax_group.append(f.max())
diff --git a/examples/RadiativeTransferTests/Advection_2D/makeIC.py b/examples/RadiativeTransferTests/Advection_2D/makeIC.py
index 5e2d3507ac39d3176cdae469c4de7ad50b734e6a..4273e2d9da423b9b0b5c4e883f48a0c52bef3655 100755
--- a/examples/RadiativeTransferTests/Advection_2D/makeIC.py
+++ b/examples/RadiativeTransferTests/Advection_2D/makeIC.py
@@ -35,7 +35,6 @@ from swiftsimio import Writer
 import unyt
 import numpy as np
 import h5py
-from matplotlib import pyplot as plt
 
 
 # define unit system to use
@@ -82,7 +81,7 @@ def initial_condition(x):
     # Assuming all photons flow in only one direction
     # (optically thin regime, "free streaming limit"),
     #  we have that |F| = c * E
-    F = np.zeros(3, dtype=np.float32)
+    F = np.zeros(3, dtype=np.float64)
     F[0] = c * E
 
     E_list.append(E)
@@ -98,7 +97,7 @@ def initial_condition(x):
     else:
         E = 1.0
 
-    F = np.zeros(3, dtype=np.float32)
+    F = np.zeros(3, dtype=np.float64)
     F[1] = c * E
 
     E_list.append(E)
@@ -116,7 +115,7 @@ def initial_condition(x):
         * np.exp(-((x[0] - mean) ** 2 + (x[1] - mean) ** 2) / (2 * sigma ** 2))
         + baseline
     )
-    F = np.zeros(3, dtype=np.float32)
+    F = np.zeros(3, dtype=np.float64)
     F[0] = c * E * 1.414213562  # sqrt(2)
     F[1] = c * E * 1.414213562  # sqrt(2)
 
@@ -135,13 +134,13 @@ def initial_condition(x):
         unit_vector = (dx / r, dy / r)
 
         E = 1.0
-        F = np.zeros(3, dtype=np.float32)
+        F = np.zeros(3, dtype=np.float64)
         F[0] = unit_vector[0] * c * E
         F[1] = unit_vector[1] * c * E
 
     else:
         E = 0.0
-        F = np.zeros(3, dtype=np.float32)
+        F = np.zeros(3, dtype=np.float64)
 
     E_list.append(E)
     F_list.append(F)
@@ -166,9 +165,9 @@ if __name__ == "__main__":
 
     w.gas.coordinates = pos
     w.gas.velocities = np.zeros((numPart, 3)) * (unyt.cm / unyt.s)
-    w.gas.masses = np.ones(numPart, dtype=np.float32) * 1000 * unyt.g
+    w.gas.masses = np.ones(numPart, dtype=np.float64) * 1000 * unyt.g
     w.gas.internal_energy = (
-        np.ones(numPart, dtype=np.float32) * (300.0 * unyt.kb * unyt.K) / (unyt.g)
+        np.ones(numPart, dtype=np.float64) * (300.0 * unyt.kb * unyt.K) / (unyt.g)
     )
 
     # Generate initial guess for smoothing lengths based on MIPS
diff --git a/examples/RadiativeTransferTests/Advection_2D/plotSolution.py b/examples/RadiativeTransferTests/Advection_2D/plotSolution.py
index 433aa76160716a77a6e7e21c653df1e8fad4d62c..29bb0b012fe75c6eaddcd1cb0ffcbed92e6c2f39 100755
--- a/examples/RadiativeTransferTests/Advection_2D/plotSolution.py
+++ b/examples/RadiativeTransferTests/Advection_2D/plotSolution.py
@@ -29,7 +29,6 @@
 import sys
 import os
 import swiftsimio
-import numpy as np
 import gc
 from matplotlib import pyplot as plt
 import matplotlib as mpl
@@ -133,7 +132,7 @@ def plot_photons(filename, energy_boundaries=None, flux_boundaries=None):
                 f *= data.gas.masses
                 setattr(data.gas, new_attribute_str, f)
 
-    # get mass surface density projection that we'll use to remove density dependence in  impage
+    # get mass surface density projection that we'll use to remove density dependence in image
     mass_map = swiftsimio.visualisation.projection.project_gas(
         data, project="masses", **projection_kwargs
     )
@@ -271,7 +270,6 @@ def get_minmax_vals(snaplist):
             dirmin = []
             dirmax = []
             for direction in ["X", "Y"]:
-                new_attribute_str = "radiation_flux" + str(g + 1) + direction
                 f = getattr(data.gas.photon_fluxes, "Group" + str(g + 1) + direction)
                 dirmin.append(f.min())
                 dirmax.append(f.max())
diff --git a/examples/RadiativeTransferTests/Advection_2D/plotSolutionScatter.py b/examples/RadiativeTransferTests/Advection_2D/plotSolutionScatter.py
index 3e8491ec5d709f11c271d7a9da6d0eb87f3270f9..a5180c5507a90573b1f6e60a40782b2b523af81b 100755
--- a/examples/RadiativeTransferTests/Advection_2D/plotSolutionScatter.py
+++ b/examples/RadiativeTransferTests/Advection_2D/plotSolutionScatter.py
@@ -29,7 +29,6 @@
 import sys
 import os
 import swiftsimio
-import numpy as np
 import gc
 from matplotlib import pyplot as plt
 import matplotlib as mpl
@@ -87,22 +86,11 @@ def get_snapshot_list(snapshot_basename="output"):
     return snaplist
 
 
-def set_colorbar(ax, im):
-    divider = make_axes_locatable(ax)
-    cax = divider.append_axes("right", size="5%", pad=0.05)
-    plt.colorbar(im, cax=cax)
-    return
-
-
-def plot_photons(filename, energy_boundaries=None, flux_boundaries=None):
+def plot_photons(filename):
     """
     Create the actual plot.
 
     filename: file to work with
-    energy_boundaries:  list of [E_min, E_max] for each photon group. 
-                        If none, limits are set automatically.
-    flux_boundaries:    list of [F_min, F_max] for each photon group. 
-                        If none, limits are set automatically.
     """
 
     print("working on", filename)
@@ -124,7 +112,6 @@ def plot_photons(filename, energy_boundaries=None, flux_boundaries=None):
 
         if plot_all_data:
             # prepare also the fluxes
-            #  for direction in ["X", "Y", "Z"]:
             for direction in ["X", "Y"]:
                 new_attribute_str = "radiation_flux" + str(g + 1) + direction
                 f = getattr(data.gas.photon_fluxes, "Group" + str(g + 1) + direction)
@@ -204,78 +191,9 @@ def plot_photons(filename, energy_boundaries=None, flux_boundaries=None):
     return
 
 
-def get_minmax_vals(snaplist):
-    """
-    Find minimal and maximal values for energy and flux
-    so you can fix axes limits over all snapshots
-
-    snaplist: list of snapshot filenames
-
-    returns:
-
-    energy_boundaries: list of [E_min, E_max] for each photon group
-    flux_boundaries: list of [Fx_min, Fy_max] for each photon group
-    """
-
-    emins = []
-    emaxs = []
-    fmins = []
-    fmaxs = []
-
-    for filename in snaplist:
-
-        data = swiftsimio.load(filename)
-        meta = data.metadata
-
-        ngroups = int(meta.subgrid_scheme["PhotonGroupNumber"])
-        emin_group = []
-        emax_group = []
-        fluxmin_group = []
-        fluxmax_group = []
-
-        for g in range(ngroups):
-            en = getattr(data.gas.photon_energies, "group" + str(g + 1))
-            emin_group.append(en.min())
-            emax_group.append(en.max())
-
-            dirmin = []
-            dirmax = []
-            for direction in ["X", "Y"]:
-                new_attribute_str = "radiation_flux" + str(g + 1) + direction
-                f = getattr(data.gas.photon_fluxes, "Group" + str(g + 1) + direction)
-                dirmin.append(f.min())
-                dirmax.append(f.max())
-            fluxmin_group.append(min(dirmin))
-            fluxmax_group.append(max(dirmax))
-
-        emins.append(emin_group)
-        emaxs.append(emax_group)
-        fmins.append(fluxmin_group)
-        fmaxs.append(fluxmax_group)
-
-    energy_boundaries = []
-    flux_boundaries = []
-    for g in range(ngroups):
-        emin = min([emins[f][g] for f in range(len(snaplist))])
-        emax = max([emaxs[f][g] for f in range(len(snaplist))])
-        energy_boundaries.append([emin, emax])
-        fmin = min([fmins[f][g] for f in range(len(snaplist))])
-        fmax = max([fmaxs[f][g] for f in range(len(snaplist))])
-        flux_boundaries.append([fmin, fmax])
-
-    return energy_boundaries, flux_boundaries
-
-
 if __name__ == "__main__":
 
     snaplist = get_snapshot_list(snapshot_base)
-    if fancy:
-        energy_boundaries, flux_boundaries = get_minmax_vals(snaplist)
-    else:
-        energy_boundaries = None
-        flux_boundaries = None
 
     for f in snaplist:
-        plot_photons(
-            f, energy_boundaries=energy_boundaries, flux_boundaries=flux_boundaries
-        )
+        plot_photons(f)
diff --git a/examples/RadiativeTransferTests/Advection_2D/rt_advection2D.yml b/examples/RadiativeTransferTests/Advection_2D/rt_advection2D.yml
index 8c1b9d88f980109b1446960d0741f13015562e82..5838bc59d8a8405ec7b6f7eefd36ba1c8ddf4635 100644
--- a/examples/RadiativeTransferTests/Advection_2D/rt_advection2D.yml
+++ b/examples/RadiativeTransferTests/Advection_2D/rt_advection2D.yml
@@ -29,7 +29,7 @@ Statistics:
 
 # Parameters for the hydrodynamics scheme
 SPH:
-  resolution_eta:        3.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
+  resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
   CFL_condition:         0.6      # Courant-Friedrich-Levy condition for time integration.
   minimal_temperature:   10.      # Kelvin
 
diff --git a/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/README b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/README
new file mode 100644
index 0000000000000000000000000000000000000000..0f0df76c4d5ffd7e4b8bc79fe5f2e2d4c8e7ce11
--- /dev/null
+++ b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/README
@@ -0,0 +1,9 @@
+Ion Mass Fraction Advection Test
+
+In some schemes, like the meshless (gizmo) scheme, particles exchange 
+masses via fluxes. This example tests whether the mass flux exchange 
+is done correctly by setting up regions of special ionization states
+and advecting them through time.
+
+To use the GEAR RT model, compile with :
+    --with-rt=GEAR_1 --with-rt-riemann-solver=GLF --with-hydro-dimension=2 --with-hydro=gizmo-mfv --with-riemann-solver=hllc --with-stars=GEAR --with-feedback=none --with-grackle=$GRACKLE_ROOT
diff --git a/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/advect_ions.yml b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/advect_ions.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9db69ab1cefce55353de7b72580a5e692cf707b3
--- /dev/null
+++ b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/advect_ions.yml
@@ -0,0 +1,57 @@
+MetaData:
+  run_name: "advect ions"
+
+# Define the system of units to use internally. 
+InternalUnitSystem:
+  UnitMass_in_cgs:     1.98841586e+33 # 1 M_Sol
+  UnitLength_in_cgs:   3.08567758e21 # kpc in cm
+  UnitVelocity_in_cgs: 1.e5 # km/s
+  UnitCurrent_in_cgs:  1.
+  UnitTemp_in_cgs:     1. # K
+
+# Parameters governing the time integration
+TimeIntegration:
+  time_begin: 0.    # The starting time of the simulation (in internal units).
+  time_end:   0.01   # end time: radiation reaches edge of box
+  dt_min:     1.e-12 # The minimal time-step size of the simulation (in internal units).
+  dt_max:     1.e-03  # The maximal time-step size of the simulation (in internal units).
+
+
+# Parameters governing the snapshots
+Snapshots:
+  basename:            output # Common part of the name of output files
+  time_first:          0.     # Time of the first output (in internal units)
+  delta_time:          0.001 # Time between snapshots
+
+# Parameters governing the conserved quantities statistics
+Statistics:
+  time_first:          0.
+  delta_time:          5e-4 # Time between statistics output
+
+# Parameters for the hydrodynamics scheme
+SPH:
+  resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
+  CFL_condition:         0.9      # Courant-Friedrich-Levy condition for time integration.
+  minimal_temperature:   10.      # Kelvin
+
+# Parameters related to the initial conditions
+InitialConditions:
+  file_name:  ./advect_ions.hdf5     # The file to read
+  periodic:   1                      # periodic ICs. Keep them periodic so we don't loose photon energy.
+
+Scheduler:
+  max_top_level_cells: 12
+
+GEARRT:
+    f_reduce_c: 1.e-5                                 # reduce the speed of light for the RT solver by multiplying c with this factor
+    CFL_condition: 0.9
+    photon_groups_Hz: [3.288e15, 5.945e15, 13.157e15] # Photon frequency group bin edges in Hz. Needs to be 1 less than the number of groups (N) requested during the configuration (--with-RT=GEAR_N). Outer edges of zero and infinity are assumed.
+    use_const_emission_rates: 1                       # (Optional) use constant emission rates for stars as defined with star_emission_rates_erg_LSol parameter
+    star_emission_rates_LSol: [0., 0., 0., 0.]        # (Optional) constant star emission rates for each photon frequency group to use if use_constant_emission_rates is set, in units of Solar Luminosity.
+    hydrogen_mass_fraction:  0.50                     # total hydrogen (H + H+) mass fraction in the metal-free portion of the gas
+    set_equilibrium_initial_ionization_mass_fractions: 0   # (Optional) set the initial ionization fractions depending on gas temperature assuming ionization equilibrium.
+    set_initial_ionization_mass_fractions: 0          # (Optional) manually overwrite initial mass fraction of each species (using the values you set below)
+    stellar_spectrum_type: 1                          # Which radiation spectrum to use. 0: constant over all frequencies. 1: blackbody spectrum.
+    stellar_spectrum_blackbody_temperature_K: 1.e5    # (Conditional) if stellar_spectrum_type=1, use this temperature (in K) for the blackbody spectrum.
+    skip_thermochemistry: 1
+
diff --git a/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/getGlass.sh b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/getGlass.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a958311b6de07663c7f7c70cff9e95d86ce3efb2
--- /dev/null
+++ b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/getGlass.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/glassPlane_64.hdf5
diff --git a/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/makeIC.py b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/makeIC.py
new file mode 100755
index 0000000000000000000000000000000000000000..f9f0c1afcd6ac9092e0d3c7f50d0bfa13198a0ae
--- /dev/null
+++ b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/makeIC.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python3
+
+# ---------------------------------------------------------------------
+# Test the diffusion/advection of ions by creating regions with/without
+# initial ions. Run without radiation.
+# ---------------------------------------------------------------------
+
+from swiftsimio import Writer
+from swiftsimio.units import cosmo_units
+import unyt
+import numpy as np
+import h5py
+
+gamma = 5.0 / 3.0
+outputfilename = "advect_ions.hdf5"
+
+if __name__ == "__main__":
+
+    glass = h5py.File("glassPlane_64.hdf5", "r")
+    parts = glass["PartType0"]
+    xp = parts["Coordinates"][:]
+    h = parts["SmoothingLength"][:]
+    glass.close()
+
+    # Set up metadata
+    unitL = unyt.Mpc
+    edgelen = 2 * 15 * 1e-3 * unitL  # 30 kpc
+    edgelen = edgelen.to(unitL)
+    boxsize = np.array([1.0, 1.0, 0.0]) * edgelen
+
+    xp *= edgelen
+    h *= edgelen
+
+    w = Writer(unit_system=cosmo_units, box_size=boxsize, dimension=2)
+
+    # write particle positions ans smoothing lengths
+    w.gas.coordinates = xp
+    w.gas.smoothing_length = h
+
+    # get gas masses
+    mpart = 1.6e5 * unyt.Msun
+    masses = np.ones(xp.shape[0], dtype=np.float64) * mpart
+    # change some gas masses
+    mask = xp[:, 0] > 0.5 * edgelen
+    masses[mask] *= 3
+    w.gas.masses = masses
+
+    w.gas.internal_energy = (
+        np.ones(xp.shape[0], dtype=np.float64) * 1.25e6 * unyt.m ** 2 / unyt.s ** 2
+    )
+
+    # get velocities
+    vels = np.zeros((xp.shape[0], 3))
+    vels[:, 0] = -1.0
+    vels[:, 1] = +1.0
+    w.gas.velocities = vels * 1000 * cosmo_units["length"] / cosmo_units["time"]
+
+    w.write(outputfilename)
+
+    # Now open file back up again and add RT data.
+    F = h5py.File(outputfilename, "r+")
+    header = F["Header"]
+    nparts = header.attrs["NumPart_ThisFile"][0]
+    parts = F["/PartType0"]
+    pos = parts["Coordinates"]
+
+    # Create initial ionization species mass fractions.
+    HIdata = np.ones((nparts), dtype=np.float32) * 0.76
+    HIIdata = np.zeros((nparts), dtype=np.float32)
+    HeIdata = np.ones((nparts), dtype=np.float32) * 0.24
+    HeIIdata = np.zeros((nparts), dtype=np.float32)
+    HeIIIdata = np.zeros((nparts), dtype=np.float32)
+
+    mask1 = pos[:, 0] > edgelen / 3
+    mask1 = np.logical_and(mask1, pos[:, 0] < 2 * edgelen / 3)
+    HIdata[mask1] = 0.26
+    HIIdata[mask1] = 0.5
+
+    mask2 = pos[:, 1] > edgelen / 4
+    mask2 = np.logical_and(mask2, pos[:, 1] < edgelen / 2)
+    HeIdata[mask2] = 0.1
+    HeIIdata[mask2] = 0.14
+
+    mask3 = pos[:, 1] > edgelen / 2
+    mask3 = np.logical_and(mask3, pos[:, 1] < 3 * edgelen / 4)
+    HeIdata[mask3] = 0.05
+    HeIIdata[mask3] = 0.09
+    HeIIIdata[mask3] = 0.1
+
+    parts.create_dataset("MassFractionHI", data=HIdata)
+    parts.create_dataset("MassFractionHII", data=HIIdata)
+    parts.create_dataset("MassFractionHeI", data=HeIdata)
+    parts.create_dataset("MassFractionHeII", data=HeIIdata)
+    parts.create_dataset("MassFractionHeIII", data=HeIIIdata)
+
+    # close up, and we're done!
+    F.close()
diff --git a/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/plotIonization.py b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/plotIonization.py
new file mode 100755
index 0000000000000000000000000000000000000000..6f0112bd09d1f33ccf145da888c112a2ccdd45d1
--- /dev/null
+++ b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/plotIonization.py
@@ -0,0 +1,214 @@
+#!/usr/bin/env python3
+
+# ----------------------------------------------------
+# Plot the ionizing species
+# ----------------------------------------------------
+
+import sys
+import os
+import swiftsimio
+import numpy as np
+import gc
+import unyt
+from matplotlib import pyplot as plt
+import matplotlib as mpl
+from mpl_toolkits.axes_grid1 import make_axes_locatable
+from matplotlib.colors import SymLogNorm
+
+# Parameters users should/may tweak
+
+# plot all groups and all photon quantities
+plot_all_data = True
+# snapshot basename
+snapshot_base = "output"
+# fancy up the plots a bit?
+fancy = True
+
+# parameters for imshow plots
+imshow_kwargs = {"origin": "lower", "cmap": "brg"}
+
+# parameters for swiftsimio projections
+projection_kwargs = {"resolution": 512, "parallel": True}
+
+# -----------------------------------------------------------------------
+
+
+# Read in cmdline arg: Are we plotting only one snapshot, or all?
+plot_all = False
+try:
+    snapnr = int(sys.argv[1])
+except IndexError:
+    plot_all = True
+
+mpl.rcParams["text.usetex"] = True
+
+
+def get_snapshot_list(snapshot_basename="output"):
+    """
+    Find the snapshot(s) that are to be plotted 
+    and return their names as list
+    """
+
+    snaplist = []
+
+    if plot_all:
+        dirlist = os.listdir()
+        for f in dirlist:
+            if f.startswith(snapshot_basename) and f.endswith("hdf5"):
+                snaplist.append(f)
+
+        snaplist = sorted(snaplist)
+
+    else:
+        fname = snapshot_basename + "_" + str(snapnr).zfill(4) + ".hdf5"
+        if not os.path.exists(fname):
+            print("Didn't find file", fname)
+            quit(1)
+        snaplist.append(fname)
+
+    return snaplist
+
+
+def set_colorbar(ax, im):
+    """
+    Adapt the colorbar a bit for axis object <ax> and
+    imshow instance <im>
+    """
+    divider = make_axes_locatable(ax)
+    cax = divider.append_axes("right", size="5%", pad=0.05)
+    plt.colorbar(im, cax=cax)
+    return
+
+
+def plot_ionization(filename):
+    """
+    Create and save the plot
+    """
+    print("working on", filename)
+
+    data = swiftsimio.load(filename)
+    meta = data.metadata
+
+    global imshow_kwargs
+    imshow_kwargs["extent"] = [
+        0.01 * meta.boxsize[0].v,
+        0.99 * meta.boxsize[0].v,
+        0.01 * meta.boxsize[1].v,
+        0.99 * meta.boxsize[1].v,
+    ]
+
+    mass_map = swiftsimio.visualisation.projection.project_gas(
+        data, project="masses", **projection_kwargs
+    )
+
+    data.gas.mXHI = data.gas.ion_mass_fractions.HI * data.gas.masses
+    data.gas.mXHII = data.gas.ion_mass_fractions.HII * data.gas.masses
+    data.gas.mXHeI = data.gas.ion_mass_fractions.HeI * data.gas.masses
+    data.gas.mXHeII = data.gas.ion_mass_fractions.HeII * data.gas.masses
+    data.gas.mXHeIII = data.gas.ion_mass_fractions.HeIII * data.gas.masses
+
+    mass_weighted_XHImap = swiftsimio.visualisation.projection.project_gas(
+        data, project="mXHI", **projection_kwargs
+    )
+    mass_weighted_XHIImap = swiftsimio.visualisation.projection.project_gas(
+        data, project="mXHII", **projection_kwargs
+    )
+    mass_weighted_XHeImap = swiftsimio.visualisation.projection.project_gas(
+        data, project="mXHeI", **projection_kwargs
+    )
+    mass_weighted_XHeIImap = swiftsimio.visualisation.projection.project_gas(
+        data, project="mXHeII", **projection_kwargs
+    )
+    mass_weighted_XHeIIImap = swiftsimio.visualisation.projection.project_gas(
+        data, project="mXHeIII", **projection_kwargs
+    )
+
+    XHImap = mass_weighted_XHImap / mass_map
+    XHIImap = mass_weighted_XHIImap / mass_map
+    XHeImap = mass_weighted_XHeImap / mass_map
+    XHeIImap = mass_weighted_XHeIImap / mass_map
+    XHeIIImap = mass_weighted_XHeIIImap / mass_map
+
+    fig = plt.figure(figsize=(20, 8), dpi=200)
+    figname = filename[:-5] + "-mass-fractions.png"
+
+    ax1 = fig.add_subplot(251)
+    ax2 = fig.add_subplot(252)
+    ax3 = fig.add_subplot(253)
+    ax4 = fig.add_subplot(254)
+    ax5 = fig.add_subplot(255)
+    ax6 = fig.add_subplot(256)
+    ax7 = fig.add_subplot(257)
+    ax8 = fig.add_subplot(258)
+    ax9 = fig.add_subplot(259)
+    ax10 = fig.add_subplot(2, 5, 10)
+
+    #  im0 = ax0.imshow(mass_map.T, **imshow_kwargs)
+    #  set_colorbar(ax0, im0)
+    #  ax0.set_title("Mass")
+
+    imshow_kwargs_ions = imshow_kwargs.copy()
+    imshow_kwargs_ions["norm"] = SymLogNorm(vmin=0.0, vmax=1.0, linthresh=1e-3, base=10)
+
+    im1 = ax1.imshow(XHImap.T, **imshow_kwargs_ions)
+    set_colorbar(ax1, im1)
+    ax1.set_title("HI Mass Fraction")
+
+    im2 = ax2.imshow(XHIImap.T, **imshow_kwargs_ions)
+    set_colorbar(ax2, im2)
+    ax2.set_title("HII Mass Fraction")
+
+    im3 = ax3.imshow(XHeImap.T, **imshow_kwargs_ions)
+    set_colorbar(ax3, im3)
+    ax3.set_title("HeI Mass Fraction")
+
+    im4 = ax4.imshow(XHeIImap.T, **imshow_kwargs_ions)
+    set_colorbar(ax4, im4)
+    ax4.set_title("HeII Mass Fraction")
+
+    im5 = ax5.imshow(XHeIIImap.T, **imshow_kwargs_ions)
+    set_colorbar(ax5, im5)
+    ax5.set_title("HeIII Mass Fraction")
+
+    im6 = ax6.imshow(mass_weighted_XHImap.T, **imshow_kwargs)
+    set_colorbar(ax6, im6)
+    ax6.set_title("HI Mass")
+
+    im7 = ax7.imshow(mass_weighted_XHIImap.T, **imshow_kwargs)
+    set_colorbar(ax7, im7)
+    ax7.set_title("HII Mass")
+
+    im8 = ax8.imshow(mass_weighted_XHeImap.T, **imshow_kwargs)
+    set_colorbar(ax8, im8)
+    ax8.set_title("HeI Mass")
+
+    im9 = ax9.imshow(mass_weighted_XHeIImap.T, **imshow_kwargs)
+    set_colorbar(ax9, im9)
+    ax9.set_title("HeII Mass")
+
+    im10 = ax10.imshow(mass_weighted_XHeIIImap.T, **imshow_kwargs)
+    set_colorbar(ax10, im10)
+    ax10.set_title("HeIII Mass")
+
+    for ax in [ax1, ax2, ax3, ax4, ax5, ax6, ax7, ax8, ax9, ax10]:
+        ax.set_xlabel("[kpc]")
+        ax.set_ylabel("[kpc]")
+
+    title = filename.replace("_", "\_")  # exception handle underscore for latex
+    if meta.cosmology is not None:
+        title += ", $z$ = {0:.2e}".format(meta.z)
+    title += ", $t$ = {0:.2e}".format(meta.time.to("Myr"))
+    fig.suptitle(title)
+
+    plt.tight_layout()
+    plt.savefig(figname)
+    plt.close()
+    return
+
+
+if __name__ == "__main__":
+
+    snaplist = get_snapshot_list(snapshot_base)
+
+    for f in snaplist:
+        plot_ionization(f)
diff --git a/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/run.sh b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..51346e2509df292d3368b7bcbd08b982d626ad0d
--- /dev/null
+++ b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/run.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# make run.sh fail if a subcommand fails
+set -e
+set -o pipefail
+
+if [ ! -e glassPlane_64.hdf5 ]
+then
+    echo "Fetching initial glass file ..."
+    ./getGlass.sh
+fi
+
+if [ ! -f 'advect_ions.hdf5' ]; then
+    echo "Generating ICs"
+    python3 makeIC.py
+fi
+
+# Run SWIFT with RT
+../../swift \
+    --hydro --threads=4 --stars --external-gravity \
+    --feedback --radiation \
+    advect_ions.yml 2>&1 | tee output.log
+
+python3 plotIonization.py
+python3 testIonization.py
diff --git a/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/testIonization.py b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/testIonization.py
new file mode 100755
index 0000000000000000000000000000000000000000..fa2cd1fea1a6414f095cf4f800f1d339c86ae762
--- /dev/null
+++ b/examples/RadiativeTransferTests/IonMassFractionAdvectionTest_2D/testIonization.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+
+# ----------------------------------------------------
+# Check that the total amount of ionized species
+# remains constant
+# ----------------------------------------------------
+
+import sys
+import os
+import swiftsimio
+import numpy as np
+import gc
+import unyt
+from matplotlib import pyplot as plt
+import matplotlib as mpl
+from mpl_toolkits.axes_grid1 import make_axes_locatable
+from matplotlib.colors import SymLogNorm
+
+snapshot_base = "output"
+
+
+def get_snapshot_list(snapshot_basename="output"):
+    """
+    Find the snapshot(s) that are to be plotted 
+    and return their names as list
+    """
+
+    snaplist = []
+
+    dirlist = os.listdir()
+    for f in dirlist:
+        if f.startswith(snapshot_basename) and f.endswith("hdf5"):
+            snaplist.append(f)
+
+    snaplist = sorted(snaplist)
+
+    return snaplist
+
+
+def compare_data(snaplist):
+    """
+    Create and save the plot
+    """
+
+    HI = []
+    HII = []
+    HeI = []
+    HeII = []
+    HeIII = []
+
+    for filename in snaplist:
+        data = swiftsimio.load(filename)
+
+        mXHI = data.gas.ion_mass_fractions.HI * data.gas.masses
+        mXHII = data.gas.ion_mass_fractions.HII * data.gas.masses
+        mXHeI = data.gas.ion_mass_fractions.HeI * data.gas.masses
+        mXHeII = data.gas.ion_mass_fractions.HeII * data.gas.masses
+        mXHeIII = data.gas.ion_mass_fractions.HeIII * data.gas.masses
+
+        HI.append(mXHI.sum())
+        HII.append(mXHII.sum())
+        HeI.append(mXHeI.sum())
+        HeII.append(mXHeII.sum())
+        HeIII.append(mXHeIII.sum())
+
+    plt.figure()
+    plt.plot(range(len(snaplist)), HI, label="HI total mass")
+    plt.plot(range(len(snaplist)), HII, label="HII total mass")
+    plt.plot(range(len(snaplist)), HeI, label="HeI total mass")
+    plt.plot(range(len(snaplist)), HeII, label="HeII total mass")
+    plt.plot(range(len(snaplist)), HeIII, label="HeIII total mass")
+    plt.legend()
+
+    #  plt.show()
+    plt.tight_layout()
+    plt.savefig("total_abundancies.png", dpi=200)
+
+    return
+
+
+if __name__ == "__main__":
+
+    snaplist = get_snapshot_list(snapshot_base)
+    compare_data(snaplist)
diff --git a/examples/RadiativeTransferTests/IonizationEquilibriumICSetupTest/makeIC.py b/examples/RadiativeTransferTests/IonizationEquilibriumICSetupTest/makeIC.py
index a57098b4d22284d9001baa83723af170d395ec1d..4506f86e26970047a6b2a69c0c9701d9c66d2804 100755
--- a/examples/RadiativeTransferTests/IonizationEquilibriumICSetupTest/makeIC.py
+++ b/examples/RadiativeTransferTests/IonizationEquilibriumICSetupTest/makeIC.py
@@ -11,7 +11,6 @@ from swiftsimio import Writer
 import unyt
 import numpy as np
 import h5py
-from matplotlib import pyplot as plt
 
 # define unit system to use
 unitsystem = unyt.unit_systems.cgs_unit_system
@@ -33,7 +32,7 @@ n_p = 10000
 outputfilename = "ionization_equilibrium_test.hdf5"
 
 # particle positions
-xp = unyt.unyt_array(np.zeros((n_p, 3), dtype=np.float), boxsize.units)
+xp = unyt.unyt_array(np.zeros((n_p, 3), dtype=np.float64), boxsize.units)
 dx = boxsize / n_p
 for i in range(n_p):
     xp[i, 0] = (i + 0.5) * dx
@@ -42,7 +41,7 @@ w = Writer(unyt.unit_systems.cgs_unit_system, boxsize, dimension=1)
 
 w.gas.coordinates = xp
 w.gas.velocities = np.zeros(xp.shape) * (unyt.cm / unyt.s)
-w.gas.masses = np.ones(xp.shape[0], dtype=np.float) * 1000 * unyt.g
+w.gas.masses = np.ones(xp.shape[0], dtype=np.float64) * 1000 * unyt.g
 w.gas.internal_energy = (
     np.logspace(np.log10(umin.v), np.log10(umax.v), n_p) * unyt.erg / unyt.g
 )
diff --git a/examples/RadiativeTransferTests/IonizationEquilibriumICSetupTest/plotSolution.py b/examples/RadiativeTransferTests/IonizationEquilibriumICSetupTest/plotSolution.py
index 39400b07008e2aa87bb8e78cc5dbb30897b1137f..d744fc0299f589e41cda3b87b36c589df46dde82 100755
--- a/examples/RadiativeTransferTests/IonizationEquilibriumICSetupTest/plotSolution.py
+++ b/examples/RadiativeTransferTests/IonizationEquilibriumICSetupTest/plotSolution.py
@@ -70,7 +70,7 @@ Tmax = T.v.max()
 
 
 u_theory, mu_theory, T_theory, XHI_theory, XHII_theory, XHeI_theory, XHeII_theory, XHeIII_theory = np.loadtxt(
-    "IonizationEquilibriumICSetupTestReference.txt", dtype=float, unpack=True
+    "IonizationEquilibriumICSetupTestReference.txt", dtype=np.float64, unpack=True
 )
 
 # ------------------
diff --git a/examples/RadiativeTransferTests/RandomizedBox_3D/README b/examples/RadiativeTransferTests/RandomizedBox_3D/README
index ef80ebb3314670dbc6692e92fa6c042fb298f69f..03d686ed719ea8693409699cae4f505362f04a73 100644
--- a/examples/RadiativeTransferTests/RandomizedBox_3D/README
+++ b/examples/RadiativeTransferTests/RandomizedBox_3D/README
@@ -1,6 +1,6 @@
 This test case contains only gas and stars in a periodic box. The contents have
 no physical meaning, and are background particles on a regular grid overlapping
-a randomly sampled sine wave particle distribution. The purpose of this test are
+a randomly sampled sine wave particle distribution. The purposes of this test are
 as follows:
 
 - Neither the stars nor the gas particles are updated all at the same time. 
@@ -12,3 +12,6 @@ as follows:
 
 You can and should run the same sanity check scripts as in ../UniformBox_3D to
 check that everything's right.
+
+Compile swift with:
+    --with-rt=GEAR_1 --with-rt-riemann-solver=GLF --with-hydro-dimension=3 --with-hydro=gizmo-mfv --with-riemann-solver=hllc --with-stars=GEAR --with-feedback=none --enable-debugging-checks --with-grackle=$GRACKLE_ROOT
diff --git a/examples/RadiativeTransferTests/RandomizedBox_3D/makeIC.py b/examples/RadiativeTransferTests/RandomizedBox_3D/makeIC.py
index 452390e38ea28016421a7e43969c13bb180630b7..3b1850a6dcb092a276d73684e939076e1bbe251d 100755
--- a/examples/RadiativeTransferTests/RandomizedBox_3D/makeIC.py
+++ b/examples/RadiativeTransferTests/RandomizedBox_3D/makeIC.py
@@ -31,8 +31,6 @@ from swiftsimio.units import cosmo_units
 
 import unyt
 import numpy as np
-from scipy import special as sp
-from matplotlib import pyplot as plt
 
 np.random.seed(666)
 
@@ -60,9 +58,9 @@ for i in range(n_p):
         y = (j + 0.501) * dx
         for k in range(n_p):
             z = (k + 0.501) * dx
-            xp.append(np.array([x, y, z], dtype=np.float))
+            xp.append(np.array([x, y, z], dtype=np.float64))
 xp = np.array(xp)
-velp = np.zeros((n_p ** 3, 3), dtype=np.float)
+velp = np.zeros((n_p ** 3, 3), dtype=np.float64)
 
 for i in range(n_s):
     x = (i + 0.001) * ds
@@ -70,9 +68,9 @@ for i in range(n_s):
         y = (j + 0.001) * ds
         for k in range(n_s):
             z = (k + 0.001) * ds
-            xs.append(np.array([x, y, z], dtype=np.float))
+            xs.append(np.array([x, y, z], dtype=np.float64))
 xs = np.array(xs)
-vels = np.zeros((n_s ** 3, 3), dtype=np.float)
+vels = np.zeros((n_s ** 3, 3), dtype=np.float64)
 
 
 amplitude = 0.5
@@ -87,9 +85,9 @@ def sine(x, amplitude=1.0):
 
 def sample(n):
     samples = 0
-    keep = np.zeros((n, 3), dtype=np.float)
+    keep = np.zeros((n, 3), dtype=np.float64)
     while samples < n:
-        sample = np.zeros(3, dtype=np.float)
+        sample = np.zeros(3, dtype=np.float64)
 
         found = False
         while not found:
@@ -155,11 +153,13 @@ w.gas.coordinates = xp
 w.stars.coordinates = xs
 w.gas.velocities = vp
 w.stars.velocities = vs
-w.gas.masses = np.ones(xp.shape[0], dtype=np.float) * 1e6 * unyt.msun
+w.gas.masses = np.ones(xp.shape[0], dtype=np.float64) * 1e6 * unyt.msun
 w.stars.masses = np.random.uniform(1e8, 1e10, size=xs.shape[0]) * unyt.msun
 # Generate internal energy corresponding to 10^4 K
 w.gas.internal_energy = (
-    np.ones(xp.shape[0], dtype=float) * (1e4 * unyt.kb * unyt.K) / (1e6 * unyt.msun)
+    np.ones(xp.shape[0], dtype=np.float64)
+    * (1e4 * unyt.kb * unyt.K)
+    / (1e6 * unyt.msun)
 )
 
 
diff --git a/examples/RadiativeTransferTests/RandomizedBox_3D/plotRadiationProjection.py b/examples/RadiativeTransferTests/RandomizedBox_3D/plotRadiationProjection.py
index e12c63ac7b231826dfe63e186c6076e768abb5de..f6edafe666937837d93eebab6b250a8798aa359e 100755
--- a/examples/RadiativeTransferTests/RandomizedBox_3D/plotRadiationProjection.py
+++ b/examples/RadiativeTransferTests/RandomizedBox_3D/plotRadiationProjection.py
@@ -17,9 +17,10 @@ import unyt
 from matplotlib import pyplot as plt
 import matplotlib as mpl
 from mpl_toolkits.axes_grid1 import make_axes_locatable
-from matplotlib.colors import SymLogNorm, LogNorm
+from matplotlib.colors import SymLogNorm
 
 # Parameters users should/may tweak
+# -----------------------------------
 
 # plot all groups and all photon quantities
 plot_all_data = True
@@ -158,9 +159,6 @@ def plot_photons(filename, energy_boundaries=None, flux_boundaries=None):
             ax = fig.add_subplot(ngroups, 4, g * 4 + 1)
 
             if energy_boundaries is not None:
-                #  imshow_kwargs["norm"] = None
-                #  imshow_kwargs["vmin"] = energy_boundaries[g][0]
-                #  imshow_kwargs["vmax"] = energy_boundaries[g][1]
                 imshow_kwargs["norm"] = SymLogNorm(
                     vmin=energy_boundaries[g][0],
                     vmax=energy_boundaries[g][1],
@@ -259,12 +257,6 @@ def plot_photons(filename, energy_boundaries=None, flux_boundaries=None):
             if energy_boundaries is not None:
                 imshow_kwargs["vmin"] = energy_boundaries[g][0]
                 imshow_kwargs["vmax"] = energy_boundaries[g][1]
-                #  imshow_kwargs["norm"] = SymLogNorm(
-                #      vmin=energy_boundaries[g][0],
-                #      vmax=energy_boundaries[g][1],
-                #      linthresh = 1e-2,
-                #      base=10
-                # )
             im = ax.imshow(photon_map.T, **imshow_kwargs)
             set_colorbar(ax, im)
             ax.set_title("Group {0:2d}".format(g + 1))
@@ -331,7 +323,6 @@ def get_minmax_vals(snaplist):
             dirmin = []
             dirmax = []
             for direction in ["X", "Y", "Z"]:
-                new_attribute_str = "radiation_flux" + str(g + 1) + direction
                 f = getattr(data.gas.photon_fluxes, "Group" + str(g + 1) + direction)
                 dirmin.append(f.min())
                 dirmax.append(f.max())
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_2D/README b/examples/RadiativeTransferTests/StromgrenSphere_2D/README
index 0a0f3010ca265be9e4433fe7fcbc3762425c60bf..e9d6f81934406afab8a03d50f432e83736e5ed1a 100644
--- a/examples/RadiativeTransferTests/StromgrenSphere_2D/README
+++ b/examples/RadiativeTransferTests/StromgrenSphere_2D/README
@@ -1,22 +1,25 @@
 Strömgen Sphere example in 2D
+-----------------------------
 
-For now, there are no gas interactions, and we use this
-example to perform tests and checks on photon injection
-and their propagation. The example contains 1 star in a
-glass hydro distribution in 2D. (State 09/2021)
+This directory contains two examples in one:
 
-Intented to compile with :
-    --with-rt=GEAR_1 --with-hydro-dimension=2 --with-rt-riemann-solver=GLF
+    -   run a Strömgren sphere example, where a single central
+        star ionizes the surrounding medium in a 2D plane.
+        To run this example, use the provided `run.sh` script.
+        This script will then make use of the `makeIC.py` and
+        `plotSolution.py` script.
 
-Scripts in this directory:
+    -   run a propagation test of photons emitted from a single 
+        central source in an otherwise uniform 2D plane.
+        To run this example, use the provided `runPropagationTest.sh` script.
+        This script will then make use of the `makePropagationTestIC.py` and
+        `plotPhotonPropagationCheck.py` script.
 
-    - plotRadiationProjection.py:
-        plot photon energies and fluxes as a 2D image
+Additional scripts:
+    -   `plotRadiationProjection.py`: Plots a projection of the radiation
+        quantities (energies, fluxes). NOTE: you might need to change the
+        'snapshot_base' variable at the top of the script depending on which
+        solutions you want to plot.
 
-    - plotPhotonPropagationCheck.py:
-        Plots radiation energies and fluxes as function of 
-        radius centered on the injecting star. 
-        NOTE: Make sure that you use a photon group that 
-        doesn't interact with the gas to check the 
-        propagation properly. You'll have to hard-code
-        the index of the photon group in the script itself.
+To use the GEAR RT model, compile with :
+    --with-rt=GEAR_1 --with-rt-riemann-solver=GLF --with-hydro-dimension=2 --with-hydro=gizmo-mfv --with-riemann-solver=hllc --with-stars=GEAR --with-feedback=none --with-grackle=$GRACKLE_ROOT
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_2D/makeIC.py b/examples/RadiativeTransferTests/StromgrenSphere_2D/makeIC.py
index f57ee898b7fe7427734699d33cfbb67188e60e0c..3e39b9248a6e2fef65db51cbebd9d9d8fb0fa0ca 100755
--- a/examples/RadiativeTransferTests/StromgrenSphere_2D/makeIC.py
+++ b/examples/RadiativeTransferTests/StromgrenSphere_2D/makeIC.py
@@ -130,15 +130,8 @@ def get_number_densities_array(Temp, XH, XHe):
     # n_He = X_He * rho_gas / m_He = (1 - X_H) / (4 X_H) * n_H
     #      =  X_He / 4(1 - X_He) * nH = y * nH
 
-    #  if XH == 0:
-    #      nH = 0.0
-    #      nHe = 1.0
-    #  else:
-    #      nH = XH
-    #      nHe = XHe / 4
-
-    nH = np.zeros(XH.shape, dtype=float)
-    nHe = np.zeros(XH.shape, dtype=float)
+    nH = np.zeros(XH.shape, dtype=np.float64)
+    nHe = np.zeros(XH.shape, dtype=np.float64)
 
     mask = XH == 0
     nH[mask] = 0.0
@@ -148,13 +141,13 @@ def get_number_densities_array(Temp, XH, XHe):
     nH[inv_mask] = XH[inv_mask]
     nHe[inv_mask] = 0.25 * XHe[inv_mask]
 
-    # NOTE: This is not the ionization threshold!
-    nH0 = np.zeros(XH.shape, dtype=float)
-    nHp = np.zeros(XH.shape, dtype=float)
-    nHe0 = np.zeros(XH.shape, dtype=float)
-    nHep = np.zeros(XH.shape, dtype=float)
-    nHepp = np.zeros(XH.shape, dtype=float)
+    nH0 = np.zeros(XH.shape, dtype=np.float64)
+    nHp = np.zeros(XH.shape, dtype=np.float64)
+    nHe0 = np.zeros(XH.shape, dtype=np.float64)
+    nHep = np.zeros(XH.shape, dtype=np.float64)
+    nHepp = np.zeros(XH.shape, dtype=np.float64)
 
+    # NOTE: This is not the ionization threshold!
     neutral = Temp < 5000 * unyt.K
 
     nH0[neutral] = nH[neutral]
@@ -291,8 +284,8 @@ def mean_molecular_weight(XH0, XHp, XHe0, XHep, XHepp):
 
 if __name__ == "__main__":
 
-    glass = h5py.File("glassPlane_64.hdf5", "r")
-    #  glass = h5py.File("glassPlane_128.hdf5", "r")
+    #  glass = h5py.File("glassPlane_64.hdf5", "r")
+    glass = h5py.File("glassPlane_128.hdf5", "r")
     parts = glass["PartType0"]
     xp = parts["Coordinates"][:]
     h = parts["SmoothingLength"][:]
@@ -340,8 +333,8 @@ if __name__ == "__main__":
     Mtot = rhoH * edgelen ** 3
     mpart = Mtot / xp.shape[0]
     mpart = mpart.to(cosmo_units["mass"])
-    w.gas.masses = np.ones(xp.shape[0], dtype=np.float) * mpart
-    w.stars.masses = np.ones(xs.shape[0], dtype=np.float) * mpart
+    w.gas.masses = np.ones(xp.shape[0], dtype=np.float64) * mpart
+    w.stars.masses = np.ones(xs.shape[0], dtype=np.float64) * mpart
 
     # get gas internal energy for a given temperature and composition
     XH = 1.0  # hydrogen mass fraction
@@ -351,6 +344,6 @@ if __name__ == "__main__":
     mu = mean_molecular_weight(XHI, XHII, XHeI, XHeII, XHeIII)
     internal_energy = internal_energy(T, mu)
 
-    w.gas.internal_energy = np.ones(xp.shape[0], dtype=np.float) * internal_energy
+    w.gas.internal_energy = np.ones(xp.shape[0], dtype=np.float64) * internal_energy
 
     w.write("stromgrenSphere-2D.hdf5")
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_2D/makePropagationTestIC.py b/examples/RadiativeTransferTests/StromgrenSphere_2D/makePropagationTestIC.py
new file mode 100755
index 0000000000000000000000000000000000000000..f1bc41207c606706d9e1abf80802b54b2e6b6c0c
--- /dev/null
+++ b/examples/RadiativeTransferTests/StromgrenSphere_2D/makePropagationTestIC.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+
+# ---------------------------------------------------------------------
+# Add a single star in the center of a glass distribution
+# Intended for the photon propagation test.
+# ---------------------------------------------------------------------
+
+from swiftsimio import Writer
+import unyt
+import numpy as np
+import h5py
+
+
+glass = h5py.File("glassPlane_128.hdf5", "r")
+parts = glass["PartType0"]
+xp = parts["Coordinates"][:]
+h = parts["SmoothingLength"][:]
+glass.close()
+
+# replace the particle closest to the center
+# by the star
+r = np.sqrt(np.sum((0.5 - xp) ** 2, axis=1))
+rmin = np.argmin(r)
+xs = xp[rmin]
+xp = np.delete(xp, rmin, axis=0)
+h = np.delete(h, rmin)
+
+
+unitL = unyt.cm
+t_end = 1e-3 * unyt.s
+edgelen = unyt.c.to("cm/s") * t_end * 2.0
+edgelen = edgelen.to(unitL)
+boxsize = unyt.unyt_array([edgelen.v, edgelen.v, 0.0], unitL)
+
+xs = unyt.unyt_array(
+    [np.array([xs[0] * edgelen, xs[1] * edgelen, 0.0 * edgelen])], unitL
+)
+xp *= edgelen
+h *= edgelen
+
+
+w = Writer(unit_system=unyt.unit_systems.cgs_unit_system, box_size=boxsize, dimension=2)
+
+w.gas.coordinates = xp
+w.stars.coordinates = xs
+w.gas.velocities = np.zeros(xp.shape) * (unyt.cm / unyt.s)
+w.stars.velocities = np.zeros(xs.shape) * (unyt.cm / unyt.s)
+w.gas.masses = np.ones(xp.shape[0], dtype=np.float64) * 100 * unyt.g
+w.stars.masses = np.ones(xs.shape[0], dtype=np.float64) * 100 * unyt.g
+w.gas.internal_energy = (
+    np.ones(xp.shape[0], dtype=np.float64) * (300.0 * unyt.kb * unyt.K) / (unyt.g)
+)
+
+w.gas.smoothing_length = h
+w.stars.smoothing_length = w.gas.smoothing_length[:1]
+
+w.write("propagationTest-2D.hdf5")
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_2D/plotPhotonPropagationCheck.py b/examples/RadiativeTransferTests/StromgrenSphere_2D/plotPhotonPropagationCheck.py
index c8eb62f5dbe47841e957924b8e9d7333f9f32c52..548feee03bd4e94ccc3ce089cf1e5125f2e5d988 100755
--- a/examples/RadiativeTransferTests/StromgrenSphere_2D/plotPhotonPropagationCheck.py
+++ b/examples/RadiativeTransferTests/StromgrenSphere_2D/plotPhotonPropagationCheck.py
@@ -16,21 +16,26 @@
 #   correctly.
 # ----------------------------------------------------------------------
 
-import sys, os, gc
+import sys
+import os
+import gc
 import swiftsimio
 import numpy as np
 import unyt
 from matplotlib import pyplot as plt
 import matplotlib as mpl
 from scipy import stats
-from scipy.optimize import curve_fit
 
 # Parameters users should/may tweak
 
 # snapshot basename
-snapshot_base = "output"
+snapshot_base = "propagation_test"
+
+# additional anisotropy estimate plot?
+plot_anisotropy_estimate = False
 
 # which photon group to use.
+# NOTE: array index, not group number (which starts at 1 for GEAR)
 group_index = 0
 
 scatterplot_kwargs = {
@@ -55,7 +60,7 @@ except IndexError:
 mpl.rcParams["text.usetex"] = True
 
 
-def analytical_intgrated_energy_solution(L, time, r, rmax):
+def analytical_integrated_energy_solution(L, time, r, rmax):
     """
     Compute analytical solution for the sum of the energy
     in bins for given injection rate <L> at time <time> 
@@ -169,6 +174,7 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     r_expect = meta.time * meta.reduced_lightspeed
 
     use_const_emission_rates = bool(meta.parameters["GEARRT:use_const_emission_rates"])
+    L = None
     if use_const_emission_rates:
         # read emission rate parameter as string
         emissionstr = meta.parameters["GEARRT:star_emission_rates_LSol"].decode("utf-8")
@@ -186,7 +192,11 @@ def plot_photons(filename, emin, emax, fmin, fmax):
         const_emission_rates = unyt.unyt_array(emlist, unyt.L_Sun)
         L = const_emission_rates[group_index]
 
-    fig = plt.figure(figsize=(5 * 4, 5.5), dpi=200)
+    if plot_anisotropy_estimate:
+        ncols = 4
+    else:
+        ncols = 3
+    fig = plt.figure(figsize=(5 * ncols, 5.5), dpi=200)
 
     nbins = 100
     r_bin_edges = np.linspace(0.5 * edgelen * 1e-2, 0.507 * edgelen, nbins + 1)
@@ -204,8 +214,6 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     Fy = getattr(data.gas.photon_fluxes, "Group" + str(group_index + 1) + "Y")
 
     fmag = np.sqrt(Fx ** 2 + Fy ** 2)
-    sum_fmag = fmag.sum()
-    max_fmag = fmag.max()
     particle_count, _ = np.histogram(
         r,
         bins=r_analytical_bin_edges,
@@ -220,7 +228,7 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     # ------------------------
     # Plot photon energies
     # ------------------------
-    ax1 = fig.add_subplot(1, 4, 1)
+    ax1 = fig.add_subplot(1, ncols, 1)
     ax1.set_title("Particle Radiation Energies")
     ax1.set_ylabel("Photon Energy [$" + energy_units_str + "$]")
 
@@ -278,7 +286,7 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     # ------------------------------
     # Plot binned photon energies
     # ------------------------------
-    ax2 = fig.add_subplot(1, 4, 2)
+    ax2 = fig.add_subplot(1, ncols, 2)
     ax2.set_title("Total Radiation Energy in radial bins")
     ax2.set_ylabel("Total Photon Energy [$" + energy_units_str + "$]")
 
@@ -301,7 +309,7 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     if use_const_emission_rates:
         # plot entire expected solution
         # Note: you need to use the same bins as for the actual results
-        rA, EA = analytical_intgrated_energy_solution(L, time, r_bin_edges, r_expect)
+        rA, EA = analytical_integrated_energy_solution(L, time, r_bin_edges, r_expect)
 
         ax2.plot(
             rA,
@@ -323,7 +331,7 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     # ------------------------------
     # Plot photon fluxes
     # ------------------------------
-    ax3 = fig.add_subplot(1, 4, 3)
+    ax3 = fig.add_subplot(1, ncols, 3)
     ax3.set_title("Particle Radiation Flux Magnitudes")
     ax3.set_ylabel("Photon Flux Magnitude [$" + flux_units_str + "$]")
 
@@ -387,55 +395,57 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     # Plot photon flux sum
     # ------------------------------
 
-    ax4 = fig.add_subplot(1, 4, 4)
-    ax4.set_title("Vectorial Sum of Radiation Flux in radial bins")
-    ax4.set_ylabel("[1]")
+    if plot_anisotropy_estimate:
 
-    fmag_sum_bin, _, _ = stats.binned_statistic(
-        r,
-        fmag,
-        statistic="sum",
-        bins=r_bin_edges,
-        range=(r_bin_edges[0], r_bin_edges[-1]),
-    )
-    mask_sum = fmag_sum_bin > 0
-    fmag_max_bin, _, _ = stats.binned_statistic(
-        r,
-        fmag,
-        statistic="max",
-        bins=r_bin_edges,
-        range=(r_bin_edges[0], r_bin_edges[-1]),
-    )
-    mask_max = fmag_max_bin > 0
-    Fx_sum_bin, _, _ = stats.binned_statistic(
-        r,
-        Fx,
-        statistic="sum",
-        bins=r_bin_edges,
-        range=(r_bin_edges[0], r_bin_edges[-1]),
-    )
-    Fy_sum_bin, _, _ = stats.binned_statistic(
-        r,
-        Fy,
-        statistic="sum",
-        bins=r_bin_edges,
-        range=(r_bin_edges[0], r_bin_edges[-1]),
-    )
-    F_sum_bin = np.sqrt(Fx_sum_bin ** 2 + Fy_sum_bin ** 2)
+        ax4 = fig.add_subplot(1, ncols, 4)
+        ax4.set_title("Vectorial Sum of Radiation Flux in radial bins")
+        ax4.set_ylabel("[1]")
 
-    ax4.plot(
-        r_bin_centres[mask_sum],
-        F_sum_bin[mask_sum] / fmag_sum_bin[mask_sum],
-        **lineplot_kwargs,
-        label="$\left| \sum_{i \in \mathrm{particles \ in \ bin}} \mathbf{F}_i \\right| $ / $\sum_{i \in \mathrm{particles \ in \ bin}} \left| \mathbf{F}_{i} \\right| $",
-    )
-    ax4.plot(
-        r_bin_centres[mask_max],
-        F_sum_bin[mask_max] / fmag_max_bin[mask_max],
-        **lineplot_kwargs,
-        linestyle="--",
-        label="$\left| \sum_{i \in \mathrm{particles \ in \ bin}} \mathbf{F}_i \\right| $ / $\max_{i \in \mathrm{particles \ in \ bin}} \left| \mathbf{F}_{i} \\right| $",
-    )
+        fmag_sum_bin, _, _ = stats.binned_statistic(
+            r,
+            fmag,
+            statistic="sum",
+            bins=r_bin_edges,
+            range=(r_bin_edges[0], r_bin_edges[-1]),
+        )
+        mask_sum = fmag_sum_bin > 0
+        fmag_max_bin, _, _ = stats.binned_statistic(
+            r,
+            fmag,
+            statistic="max",
+            bins=r_bin_edges,
+            range=(r_bin_edges[0], r_bin_edges[-1]),
+        )
+        mask_max = fmag_max_bin > 0
+        Fx_sum_bin, _, _ = stats.binned_statistic(
+            r,
+            Fx,
+            statistic="sum",
+            bins=r_bin_edges,
+            range=(r_bin_edges[0], r_bin_edges[-1]),
+        )
+        Fy_sum_bin, _, _ = stats.binned_statistic(
+            r,
+            Fy,
+            statistic="sum",
+            bins=r_bin_edges,
+            range=(r_bin_edges[0], r_bin_edges[-1]),
+        )
+        F_sum_bin = np.sqrt(Fx_sum_bin ** 2 + Fy_sum_bin ** 2)
+
+        ax4.plot(
+            r_bin_centres[mask_sum],
+            F_sum_bin[mask_sum] / fmag_sum_bin[mask_sum],
+            **lineplot_kwargs,
+            label="$\left| \sum_{i \in \mathrm{particles \ in \ bin}} \mathbf{F}_i \\right| $ / $\sum_{i \in \mathrm{particles \ in \ bin}} \left| \mathbf{F}_{i} \\right| $",
+        )
+        ax4.plot(
+            r_bin_centres[mask_max],
+            F_sum_bin[mask_max] / fmag_max_bin[mask_max],
+            **lineplot_kwargs,
+            linestyle="--",
+            label="$\left| \sum_{i \in \mathrm{particles \ in \ bin}} \mathbf{F}_i \\right| $ / $\max_{i \in \mathrm{particles \ in \ bin}} \left| \mathbf{F}_{i} \\right| $",
+        )
 
     # -------------------------------------------
     # Cosmetics that all axes have in common
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_2D/plotRadiationProjection.py b/examples/RadiativeTransferTests/StromgrenSphere_2D/plotRadiationProjection.py
index 148c5e0c032e3ead59689881a3ec9ed1eca2310d..ef6298538bf3f9abd840a49a2bf341d537071776 100755
--- a/examples/RadiativeTransferTests/StromgrenSphere_2D/plotRadiationProjection.py
+++ b/examples/RadiativeTransferTests/StromgrenSphere_2D/plotRadiationProjection.py
@@ -11,7 +11,6 @@
 import sys
 import os
 import swiftsimio
-import numpy as np
 import gc
 import unyt
 from matplotlib import pyplot as plt
@@ -23,8 +22,10 @@ from matplotlib.colors import SymLogNorm
 
 # plot all groups and all photon quantities
 plot_all_data = True
-# snapshot basename
-snapshot_base = "output"
+
+# plotting propagation tests or Stromgren sphere?
+do_stromgren_sphere = True
+
 # fancy up the plots a bit?
 fancy = True
 
@@ -34,12 +35,24 @@ imshow_kwargs = {"origin": "lower", "cmap": "viridis"}
 # parameters for swiftsimio projections
 projection_kwargs = {"resolution": 1024, "parallel": True}
 
+# snapshot basename
+snapshot_base = "propagation_test"
+
 # Set Units of your choice
 energy_units = unyt.erg
 energy_units_str = "\\rm{erg}"
 flux_units = 1e10 * energy_units / unyt.cm ** 2 / unyt.s
 flux_units_str = "10^{10} \\rm{erg} \\ \\rm{cm}^{-2} \\ \\rm{s}^{-1}"
 time_units = unyt.s
+
+if do_stromgren_sphere:
+    snapshot_base = "output"
+
+    energy_units = 1e50 * unyt.erg
+    energy_units_str = "10^{50} \\rm{erg}"
+    flux_units = 1e50 * unyt.erg / unyt.kpc ** 2 / unyt.Gyr
+    flux_units_str = "10^{60} \\rm{erg} \\ \\rm{kpc}^{-2} \\ \\rm{Gyr}^{-1}"
+    time_units = unyt.Myr
 # -----------------------------------------------------------------------
 
 
@@ -76,6 +89,10 @@ def get_snapshot_list(snapshot_basename="output"):
             quit(1)
         snaplist.append(fname)
 
+    if len(snaplist) == 0:
+        print("Didn't find any snapshots with basename '", snapshot_basename, "'")
+        quit(1)
+
     return snaplist
 
 
@@ -139,7 +156,7 @@ def plot_photons(filename, energy_boundaries=None, flux_boundaries=None):
 
     if plot_all_data:
         fig = plt.figure(figsize=(5 * 3, 5.05 * ngroups), dpi=200)
-        figname = filename[:-5] + "-all-quantities.png"
+        figname = filename[:-5] + "-radiation.png"
 
         for g in range(ngroups):
 
@@ -296,7 +313,6 @@ def get_minmax_vals(snaplist):
             dirmin = []
             dirmax = []
             for direction in ["X", "Y"]:
-                new_attribute_str = "radiation_flux" + str(g + 1) + direction
                 f = getattr(data.gas.photon_fluxes, "Group" + str(g + 1) + direction)
                 dirmin.append(f.min())
                 dirmax.append(f.max())
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_2D/plotSolution.py b/examples/RadiativeTransferTests/StromgrenSphere_2D/plotSolution.py
index 9417b943d80d7f5871d38893647b415494a6a1be..06257017567beb26027544d9c9ce09689e482f7f 100755
--- a/examples/RadiativeTransferTests/StromgrenSphere_2D/plotSolution.py
+++ b/examples/RadiativeTransferTests/StromgrenSphere_2D/plotSolution.py
@@ -8,14 +8,12 @@
 import sys
 import os
 import swiftsimio
-import numpy as np
 import gc
 import unyt
 from matplotlib import pyplot as plt
 import matplotlib as mpl
 from mpl_toolkits.axes_grid1 import make_axes_locatable
-from matplotlib.colors import SymLogNorm, LogNorm
-from swiftsimio.visualisation.slice import slice_gas
+from matplotlib.colors import LogNorm
 
 # Parameters users should/may tweak
 
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_2D/propagationTest-2D.yml b/examples/RadiativeTransferTests/StromgrenSphere_2D/propagationTest-2D.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3b0e7190c40263969969702c4530900002274da4
--- /dev/null
+++ b/examples/RadiativeTransferTests/StromgrenSphere_2D/propagationTest-2D.yml
@@ -0,0 +1,60 @@
+MetaData:
+  run_name: StromgrenSpherePropagationTest2D
+
+# Define the system of units to use internally. 
+InternalUnitSystem:
+  UnitMass_in_cgs:     1.
+  UnitLength_in_cgs:   1.
+  UnitVelocity_in_cgs: 1.
+  UnitCurrent_in_cgs:  1.
+  UnitTemp_in_cgs:     1.
+
+# Parameters governing the time integration
+TimeIntegration:
+  time_begin: 0.    # The starting time of the simulation (in internal units).
+  time_end:   0.001 # end time: radiation reaches edge of box
+  dt_min:     1.e-12 # The minimal time-step size of the simulation (in internal units).
+  dt_max:     2.e-04  # The maximal time-step size of the simulation (in internal units).
+
+# Parameters governing the snapshots
+Snapshots:
+  basename:            propagation_test # Common part of the name of output files
+  time_first:          0.     # Time of the first output (in internal units)
+  delta_time:          0.0001 # Time between snapshots
+
+# Parameters governing the conserved quantities statistics
+Statistics:
+  time_first:          0.
+  delta_time:          5e-4 # Time between statistics output
+
+# Parameters for the hydrodynamics scheme
+SPH:
+  resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
+  CFL_condition:         0.6      # Courant-Friedrich-Levy condition for time integration.
+  minimal_temperature:   10.      # Kelvin
+
+# Parameters related to the initial conditions
+InitialConditions:
+  file_name:  ./propagationTest-2D.hdf5     # The file to read
+  periodic:   1                             # peridioc ICs. Keep them periodic so we don't loose photon energy. TODO: CHANGE LATER WHEN YOU ACTUALLY DO GAS INTERACTIONS
+
+Scheduler:
+  max_top_level_cells: 12
+
+GEARRT:
+    f_reduce_c: 1.        # reduce the speed of light for the RT solver by multiplying c with this factor
+    CFL_condition: 0.99
+    photon_groups_Hz: []  # Photon frequency group bin edges in Hz. Needs to be 1 less than the number of groups (N) requested during the configuration (--with-RT=GEAR_N).
+    use_const_emission_rates: 1         # (Optional) use constant emission rates for stars as defined with star_emission_rates_erg_LSol parameter
+    star_emission_rates_LSol: [1e-28]   # (Optional) constant star emission rates for each photon frequency group to use if use_constant_emission_rates is set.
+    hydrogen_mass_fraction:  0.76                     # total hydrogen (H + H+) mass fraction in the metal-free portion of the gas
+    stellar_spectrum_type: 0                          # Which radiation spectrum to use. 0: constant from 0 until some max frequency set by stellar_spectrum_const_max_frequency_Hz. 1: blackbody spectrum.
+    stellar_spectrum_const_max_frequency_Hz: 1.e17    # (Conditional) if stellar_spectrum_type=0, use this maximal frequency for the constant spectrum. 
+    set_initial_ionization_mass_fractions: 1          # (Optional) manually overwrite initial mass fraction of each species (using the values you set below)
+    mass_fraction_HI: 0.76                            # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HI mass fractions to this value
+    mass_fraction_HII: 0.                             # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HII mass fractions to this value
+    mass_fraction_HeI: 0.24                           # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HeI mass fractions to this value
+    mass_fraction_HeII: 0.                            # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HeII mass fractions to this value
+    mass_fraction_HeIII: 0.                           # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HeIII mass fractions to this value
+    skip_thermochemistry: 1                           # skip thermochemistry.
+    stars_max_timestep: 7.812500e-06                  # update stars every step!
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_2D/run.sh b/examples/RadiativeTransferTests/StromgrenSphere_2D/run.sh
index 4db90a0b079f3c92c4f5bdb079b13edb709707c5..74153c46bdb51790cbca1dfa78f3832031ca5c63 100755
--- a/examples/RadiativeTransferTests/StromgrenSphere_2D/run.sh
+++ b/examples/RadiativeTransferTests/StromgrenSphere_2D/run.sh
@@ -1,5 +1,9 @@
 #!/bin/bash
 
+#---------------------------------------
+# Runs the Stromgren Sphere example
+#---------------------------------------
+
 # make run.sh fail if a subcommand fails
 set -e
 set -o pipefail
@@ -18,11 +22,12 @@ fi
 # Run SWIFT with RT
 ../../swift \
     --hydro --threads=4 --stars --external-gravity \
-    --feedback --radiation --fpe \
+    --feedback --radiation \
+    --fpe \
     stromgrenSphere-2D.yml 2>&1 | tee output.log
 
 # Plot the photon propagation checks.
 # Make sure you set the correct photon group to plot
 # inside the script
-python3 ./plotPhotonPropagationCheck.py
+python3 ./plotSolution.py
 
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_2D/runPropagationTest.sh b/examples/RadiativeTransferTests/StromgrenSphere_2D/runPropagationTest.sh
new file mode 100755
index 0000000000000000000000000000000000000000..83ec3c33c1a98e8640820e4139109c6c725e4673
--- /dev/null
+++ b/examples/RadiativeTransferTests/StromgrenSphere_2D/runPropagationTest.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+#---------------------------------------
+# Runs the Propagation Test example
+#---------------------------------------
+
+
+# make run.sh fail if a subcommand fails
+set -e
+set -o pipefail
+
+if [ ! -e glassPlane_128.hdf5 ]
+then
+    echo "Fetching initial glass file for Strömgen Sphere 2D example ..."
+    ./getGlass.sh
+fi
+
+if [ ! -f 'propagationTest-2D.hdf5' ]; then
+    echo "Generating ICs"
+    python3 makePropagationTestIC.py
+fi
+
+# Run SWIFT with RT
+../../swift \
+    --hydro --threads=4 --stars --external-gravity \
+    --feedback --radiation --fpe \
+    ./propagationTest-2D.yml 2>&1 | tee output.log
+
+# Plot the photon propagation checks.
+# Make sure you set the correct photon group to plot
+# inside the script
+python3 ./plotPhotonPropagationCheck.py
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_2D/stromgrenSphere-2D.yml b/examples/RadiativeTransferTests/StromgrenSphere_2D/stromgrenSphere-2D.yml
index 8b6cc7688869c60416672708509ff1c91e753f18..5e8d44eb2b873476d331e2af6db159b4568ad6e9 100644
--- a/examples/RadiativeTransferTests/StromgrenSphere_2D/stromgrenSphere-2D.yml
+++ b/examples/RadiativeTransferTests/StromgrenSphere_2D/stromgrenSphere-2D.yml
@@ -8,33 +8,24 @@ InternalUnitSystem:
   UnitVelocity_in_cgs: 1.e5 # km/s
   UnitCurrent_in_cgs:  1.
   UnitTemp_in_cgs:     1. # K
-  # UnitMass_in_cgs:     7.98841586e+23 # 1 M_Sol
-  # UnitLength_in_cgs:   7.08567758e12 # kpc in cm
-  # UnitVelocity_in_cgs: 113.e7 # km/s
-  # UnitCurrent_in_cgs:  1.
-  # UnitTemp_in_cgs:     123. # K
 
 # Parameters governing the time integration
 TimeIntegration:
   time_begin: 0.    # The starting time of the simulation (in internal units).
   time_end:   0.512 
-  # time_end: 4.882813e-03
-  # time_end: 5.960465e-06
   dt_min:     1.e-12 # The minimal time-step size of the simulation (in internal units).
   dt_max:     1.e-03  # The maximal time-step size of the simulation (in internal units).
-  # dt_max: 5.960465e-07
-
 
 # Parameters governing the snapshots
 Snapshots:
   basename:            output # Common part of the name of output files
   time_first:          0.     # Time of the first output (in internal units)
-  delta_time:          0.004  # Time between snapshots
+  delta_time:          0.001  # Time between snapshots
 
 # Parameters governing the conserved quantities statistics
 Statistics:
   time_first:          0.
-  delta_time:          1e-4 # Time between statistics output
+  delta_time:          1e-3 # Time between statistics output
 
 # Parameters for the hydrodynamics scheme
 SPH:
@@ -45,7 +36,7 @@ SPH:
 # Parameters related to the initial conditions
 InitialConditions:
   file_name:  ./stromgrenSphere-2D.hdf5     # The file to read
-  periodic:   0                             # periodic ICs. Keep them periodic so we don't loose photon energy. TODO: CHANGE LATER WHEN YOU ACTUALLY DO GAS INTERACTIONS
+  periodic:   0                             # periodic ICs. Keep them periodic so we don't loose photon energy. 
 
 Scheduler:
   max_top_level_cells: 12
@@ -58,8 +49,6 @@ GEARRT:
     CFL_condition: 0.9
     photon_groups_Hz: [3.288e15, 5.945e15, 13.157e15] # Photon frequency group bin edges in Hz. Needs to be 1 less than the number of groups (N) requested during the configuration (--with-RT=GEAR_N). Outer edges of zero and infinity are assumed.
     use_const_emission_rates: 1                       # (Optional) use constant emission rates for stars as defined with star_emission_rates_erg_LSol parameter
-    # star_emission_rates_LSol: [1000000., 1000000., 1000000., 1000000.]        # (Optional) constant star emission rates for each photon frequency group to use if use_constant_emission_rates is set, in units of Solar Luminosity.
-    # star_emission_rates_LSol: [61996.44159, 61996.44159]       # (Optional) constant star emission rates for each photon frequency group to use if use_constant_emission_rates is set, in units of Solar Luminosity.
     star_emission_rates_LSol: [247985.76636, 247985.76636]       # (Optional) constant star emission rates for each photon frequency group to use if use_constant_emission_rates is set, in units of Solar Luminosity.
     hydrogen_mass_fraction:  1.00                     # total hydrogen (H + H+) mass fraction in the metal-free portion of the gas
     set_equilibrium_initial_ionization_mass_fractions: 0   # (Optional) set the initial ionization fractions depending on gas temperature assuming ionization equilibrium.
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_3D/README b/examples/RadiativeTransferTests/StromgrenSphere_3D/README
index da3fd209a4945dd051a4e1a9f9d74e7ac84a0ab1..a123177f03b2c06af367c719be442646deb62fef 100644
--- a/examples/RadiativeTransferTests/StromgrenSphere_3D/README
+++ b/examples/RadiativeTransferTests/StromgrenSphere_3D/README
@@ -1,23 +1,27 @@
 Strömgen Sphere example in 3D
+-----------------------------
 
-For now, there are no gas interactions, and we use this
-example to perform tests and checks on photon injection
-and their propagation. The example contains 1 star in a
-glass hydro distribution in 3D. (State 09/2021)
+This directory contains two examples in one:
 
-Intented to compile with :
-    --with-rt=GEAR_1 --with-hydro-dimension=3
+    -   run a Strömgren sphere example, where a single central
+        star ionizes the surrounding medium in a box.
+        To run this example, use the provided `run.sh` script.
+        This script will then make use of the `makeIC.py` and
+        `plotSolution.py` script.
 
-Scripts in this directory:
+    -   run a propagation test of photons emitted from a single 
+        central source in an otherwise uniform box.
+        To run this example, use the provided `runPropagationTest.sh` script.
+        This script will then make use of the `makePropagationTestIC.py` and
+        `plotPhotonPropagationCheck.py` script.
 
-    - plotRadiationProjection.py:
-        plot photon energies and fluxes as a 2D projected 
-        image
 
-    - plotPhotonPropagationCheck.py:
-        Plots radiation energies and fluxes as function of 
-        radius centered on the injecting star. 
-        NOTE: Make sure that you use a photon group that 
-        doesn't interact with the gas to check the 
-        propagation properly. You'll have to hard-code
-        the index of the photon group in the script itself.
+Additional scripts:
+    -   `plotRadiationProjection.py`: Plots a projection of the radiation
+        quantities (energies, fluxes). NOTE: you might need to change the
+        'snapshot_base' variable at the top of the script depending on which
+        solutions you want to plot.
+
+To use the GEAR RT model, compile with :
+    --with-rt=GEAR_1 --with-rt-riemann-solver=GLF --with-hydro=gizmo-mfv --with-riemann-solver=hllc --with-stars=GEAR --with-feedback=none --with-grackle=$GRACKLE_ROOT
+
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_3D/makeIC.py b/examples/RadiativeTransferTests/StromgrenSphere_3D/makeIC.py
index 384178ba209617144391170a1a95bd7d0f619402..dc34328b232ec98ee89b2107add90832167ae36a 100755
--- a/examples/RadiativeTransferTests/StromgrenSphere_3D/makeIC.py
+++ b/examples/RadiativeTransferTests/StromgrenSphere_3D/makeIC.py
@@ -5,52 +5,344 @@
 # ---------------------------------------------------------------------
 
 from swiftsimio import Writer
+from swiftsimio.units import cosmo_units
 import unyt
 import numpy as np
 import h5py
 
+gamma = 5.0 / 3.0
 
-glass = h5py.File("glassCube_64.hdf5", "r")
-parts = glass["PartType0"]
-xp = parts["Coordinates"][:]
-h = parts["SmoothingLength"][:]
-glass.close()
 
-# replace the particle closest to the center
-# by the star
-r = np.sqrt(np.sum((0.5 - xp) ** 2, axis=1))
-rmin = np.argmin(r)
-xs = xp[rmin]
-xp = np.delete(xp, rmin, axis=0)
-h = np.delete(h, rmin)
+def get_number_densities(Temp, XH, XHe):
+    """
+    Compute the number densities of all species at a given
+    temperature following Katz, Hernquist, and Weinberg 1996
 
+    Temp: temperature [unyt quantity]
+    XH: total mass fraction of all hydrogen species (HI + HII)
+    XHe: total mass fraction of all helium species (HeI + HeII + HeIII)
+    """
 
-unitL = unyt.cm
-t_end = 1e-3 * unyt.s
-edgelen = unyt.c.to("cm/s") * t_end * 2.0
-edgelen = edgelen.to(unitL)
-boxsize = unyt.unyt_array([edgelen.v, edgelen.v, edgelen.v], unitL)
+    # n_H = X_H * rho_gas / m_H =
+    # n_He = X_He * rho_gas / m_He = (1 - X_H) / (4 X_H) * n_H
+    #      =  X_He / 4(1 - X_He) * nH = y * nH
 
-xs = unyt.unyt_array(
-    [np.array([xs[0] * edgelen, xs[1] * edgelen, xs[2] * edgelen])], unitL
-)
-xp *= edgelen
-h *= edgelen
+    if XH == 0:
+        nH = 0.0
+        nHe = 1.0
+    else:
+        nH = XH
+        nHe = XHe / 4
 
+    # NOTE: This is not the ionization threshold!
+    if Temp < 5000 * unyt.K:
+        nH0 = nH
+        nHp = 0.0
+        nHe0 = nHe
+        nHep = 0.0
+        nHepp = 0.0
 
-w = Writer(unit_system=unyt.unit_systems.cgs_unit_system, box_size=boxsize, dimension=3)
+    else:
 
-w.gas.coordinates = xp
-w.stars.coordinates = xs
-w.gas.velocities = np.zeros(xp.shape) * (unyt.cm / unyt.s)
-w.stars.velocities = np.zeros(xs.shape) * (unyt.cm / unyt.s)
-w.gas.masses = np.ones(xp.shape[0], dtype=np.float) * 100 * unyt.g
-w.stars.masses = np.ones(xs.shape[0], dtype=np.float) * 100 * unyt.g
-w.gas.internal_energy = (
-    np.ones(xp.shape[0], dtype=np.float) * (300.0 * unyt.kb * unyt.K) / (unyt.g)
-)
+        Temp.convert_to_cgs()
+        T = Temp.v
+        # Recombination rate for H+ in units of cm^3 s^-1
+        A_Hp = (
+            8.40e-11
+            / np.sqrt(T)
+            * (T * 1e-3) ** (-0.2)
+            * 1.0
+            / (1.0 + (T * 1e-6) ** 0.7)
+        )
 
-w.gas.smoothing_length = h
-w.stars.smoothing_length = w.gas.smoothing_length[:1]
+        # Dielectronic recombination rate for He+ in units of cm^3 s^-1
+        A_d = (
+            1.9e-3
+            / T ** 1.5
+            * np.exp(-470000.0 / T)
+            * (1.0 + 0.3 * np.exp(-94000.0 / T))
+        )
+        # Recombination rate for He+ in units of cm^3 s^-1
+        A_Hep = 1.5e-10 / T ** 0.6353
+        # Recombination rate for He++ in units of cm^3 s^-1
+        A_Hepp = (
+            3.36e-10
+            / np.sqrt(T)
+            * (T * 1e-3) ** (-0.2)
+            * 1.0
+            / (1.0 + (T * 1e-6) ** 0.7)
+        )
+        # collisional ionization rate for H0 in units of cm^3 s^-1
+        #  G_H0 = 1.17e-10 * np.sqrt(T) * np.exp(-157809.1 / T) * 1. / (1. + np.sqrt(T*1e-5))
+        G_H0 = (
+            5.85e-11
+            * np.sqrt(T)
+            * np.exp(-157809.1 / T)
+            * 1.0
+            / (1.0 + np.sqrt(T * 1e-5))
+        )
+        # collisional ionization rate for He0 in units of cm^3 s^-1
+        G_He0 = (
+            2.38e-11
+            * np.sqrt(T)
+            * np.exp(-285335.4 / T)
+            * 1.0
+            / (1.0 + np.sqrt(T * 1e-5))
+        )
+        # collisional ionization rate for He+ in units of cm^3 s^-1
+        G_Hep = (
+            5.68e-12
+            * np.sqrt(T)
+            * np.exp(-631515.0 / T)
+            * 1.0
+            / (1.0 + np.sqrt(T * 1e-5))
+        )
 
-w.write("stromgrenSphere-3D.hdf5")
+        # Katz et al. 1996 eq. 33 - 38
+        # Note: We assume all photoionization rates to be zero.
+        # Also, here we don't care about the actual number density, i.e.
+        # about the volume, since it'll cancel out later when we compute
+        # the mass fractions.
+
+        nH0 = nH * A_Hp / (A_Hp + G_H0)
+        nHp = nH - nH0
+        nHep = nHe / (1.0 + (A_Hep + A_d) / G_He0 + G_Hep / A_Hepp)
+        nHe0 = nHep * (A_Hep + A_d) / G_He0
+        nHepp = nHep * G_Hep / A_Hepp
+
+    # electron density
+    ne = nHp + nHep + 2.0 * nHepp
+
+    return nH0, nHp, nHe0, nHep, nHepp, ne
+
+
+def get_number_densities_array(Temp, XH, XHe):
+    """
+    Compute the number densities of all species at a given
+    temperature following Katz, Hernquist, and Weinberg 1996
+
+    Temp: temperature [unyt array]
+    XH: total mass fraction of all hydrogen species (HI + HII)
+    XHe: total mass fraction of all helium species (HeI + HeII + HeIII)
+    """
+
+    # n_H = X_H * rho_gas / m_H =
+    # n_He = X_He * rho_gas / m_He = (1 - X_H) / (4 X_H) * n_H
+    #      =  X_He / 4(1 - X_He) * nH = y * nH
+
+    nH = np.zeros(XH.shape, dtype=np.float64)
+    nHe = np.zeros(XH.shape, dtype=np.float64)
+
+    mask = XH == 0
+    nH[mask] = 0.0
+    nHe[mask] = 1.0
+
+    inv_mask = np.logical_not(mask)
+    nH[inv_mask] = XH[inv_mask]
+    nHe[inv_mask] = 0.25 * XHe[inv_mask]
+
+    nH0 = np.zeros(XH.shape, dtype=np.float64)
+    nHp = np.zeros(XH.shape, dtype=np.float64)
+    nHe0 = np.zeros(XH.shape, dtype=np.float64)
+    nHep = np.zeros(XH.shape, dtype=np.float64)
+    nHepp = np.zeros(XH.shape, dtype=np.float64)
+
+    # NOTE: This is not the ionization threshold!
+    neutral = Temp < 5000 * unyt.K
+
+    nH0[neutral] = nH[neutral]
+    nHp[neutral] = 0.0
+    nHe0[neutral] = nHe[neutral]
+    nHep[neutral] = 0.0
+    nHepp[neutral] = 0.0
+
+    Temp.convert_to_cgs()
+    T = Temp.v
+    ionized = np.logical_not(neutral)
+
+    # Recombination rate for H+ in units of cm^3 s^-1
+    A_Hp = (
+        8.40e-11 / np.sqrt(T) * (T * 1e-3) ** (-0.2) * 1.0 / (1.0 + (T * 1e-6) ** 0.7)
+    )
+    # Dielectronic recombination rate for He+ in units of cm^3 s^-1
+    A_d = 1.9e-3 / T ** 1.5 * np.exp(-470000.0 / T) * (1.0 + 0.3 * np.exp(-94000.0 / T))
+    # Recombination rate for He+ in units of cm^3 s^-1
+    A_Hep = 1.5e-10 / T ** 0.6353
+    # Recombination rate for He++ in units of cm^3 s^-1
+    A_Hepp = (
+        3.36e-10 / np.sqrt(T) * (T * 1e-3) ** (-0.2) * 1.0 / (1.0 + (T * 1e-6) ** 0.7)
+    )
+    # collisional ionization rate for H0 in units of cm^3 s^-1
+    G_H0 = (
+        5.85e-11 * np.sqrt(T) * np.exp(-157809.1 / T) * 1.0 / (1.0 + np.sqrt(T * 1e-5))
+    )
+    # collisional ionization rate for He0 in units of cm^3 s^-1
+    G_He0 = (
+        2.38e-11 * np.sqrt(T) * np.exp(-285335.4 / T) * 1.0 / (1.0 + np.sqrt(T * 1e-5))
+    )
+    # collisional ionization rate for He+ in units of cm^3 s^-1
+    G_Hep = (
+        5.68e-12 * np.sqrt(T) * np.exp(-631515.0 / T) * 1.0 / (1.0 + np.sqrt(T * 1e-5))
+    )
+
+    # Katz et al. 1996 eq. 33 - 38
+    # Note: We assume all photoionization rates to be zero.
+    # Also, here we don't care about the actual number density, i.e.
+    # about the volume, since it'll cancel out later when we compute
+    # the mass fractions.
+
+    nH0[ionized] = nH[ionized] * A_Hp[ionized] / (A_Hp[ionized] + G_H0[ionized])
+    nHp[ionized] = nH[ionized] - nH0[ionized]
+    nHep[ionized] = nHe[ionized] / (
+        1.0
+        + (A_Hep[ionized] + A_d[ionized]) / G_He0[ionized]
+        + G_Hep[ionized] / A_Hepp[ionized]
+    )
+    nHe0[ionized] = nHep[ionized] * (A_Hep[ionized] + A_d[ionized]) / G_He0[ionized]
+    nHepp[ionized] = nHep[ionized] * G_Hep[ionized] / A_Hepp[ionized]
+
+    # electron density
+    ne = nHp + nHep + 2.0 * nHepp
+
+    return nH0, nHp, nHe0, nHep, nHepp, ne
+
+
+def get_mass_fractions(T, XH, XHe):
+    """
+    Compute the mass fractions of all species at a
+    given temperature
+
+    T: temperature
+    XH: total mass fraction of all hydrogen species (HI + HII)
+    XHe: total mass fraction of all helium species (HeI + HeII + HeIII)
+    """
+
+    # first get number densities
+    if isinstance(XH, np.ndarray):
+        nH0, nHp, nHe0, nHep, nHepp, ne = get_number_densities_array(T, XH, XHe)
+    else:
+        nH0, nHp, nHe0, nHep, nHepp, ne = get_number_densities(T, XH, XHe)
+
+    # now get mass denities in units of atomic mass units
+    mH0 = nH0
+    mHp = nHp
+    mHe0 = 4.0 * nHe0
+    mHep = 4.0 * nHep
+    mHepp = 4.0 * nHepp
+    # neglect electron mass contributions
+
+    mtot = mH0 + mHp + mHe0 + mHep + mHepp  # + me
+
+    XH0 = mH0 / mtot
+    XHp = mHp / mtot
+    XHe0 = mHe0 / mtot
+    XHep = mHep / mtot
+    XHepp = mHepp / mtot
+    #  Xe = me / mtot
+
+    return XH0, XHp, XHe0, XHep, XHepp
+
+
+def internal_energy(T, mu):
+    """
+    Compute the internal energy of the gas for a given
+    temperature and mean molecular weight
+    """
+    # Using u = 1 / (gamma - 1) * p / rho
+    #   and p = N/V * kT = rho / (mu * m_u) * kT
+
+    u = unyt.boltzmann_constant * T / (gamma - 1) / (mu * unyt.atomic_mass_unit)
+    return u
+
+
+def mean_molecular_weight(XH0, XHp, XHe0, XHep, XHepp):
+    """
+    Determines the mean molecular weight for given 
+    mass fractions of
+        hydrogen:   XH0
+        H+:         XHp
+        He:         XHe0
+        He+:        XHep
+        He++:       XHepp
+
+    returns:
+        mu: mean molecular weight [in atomic mass units]
+        NOTE: to get the actual mean mass, you still need
+        to multiply it by m_u, as is tradition in the formulae
+    """
+
+    # 1/mu = sum_j X_j / A_j * (1 + E_j)
+    # A_H    = 1, E_H    = 0
+    # A_Hp   = 1, E_Hp   = 1
+    # A_He   = 4, E_He   = 0
+    # A_Hep  = 4, E_Hep  = 1
+    # A_Hepp = 4, E_Hepp = 2
+    one_over_mu = XH0 + 2 * XHp + 0.25 * XHe0 + 0.5 * XHep + 0.75 * XHepp
+
+    return 1.0 / one_over_mu
+
+
+if __name__ == "__main__":
+
+    glass = h5py.File("glassCube_64.hdf5", "r")
+    parts = glass["PartType0"]
+    xp = parts["Coordinates"][:]
+    h = parts["SmoothingLength"][:]
+    glass.close()
+
+    # find particles closest to the center
+    # and select a couple of them to put the star in their middle
+    r = np.sqrt(np.sum((0.5 - xp) ** 2, axis=1))
+    mininds = np.argsort(r)
+    center_parts = xp[mininds[:4]]
+    xs = center_parts.sum(axis=0) / center_parts.shape[0]
+
+    # Double-check all particles for boundaries
+    for i in range(3):
+        mask = xp[:, i] < 0.0
+        xp[mask, i] += 1.0
+        mask = xp[:, i] > 1.0
+        xp[mask, i] -= 1.0
+
+    # Set up metadata
+    unitL = unyt.Mpc
+    edgelen = 22 * 1e-3 * unitL  # 22 so we can cut off 1kpc on each edge for image
+    edgelen = edgelen.to(unitL)
+    boxsize = np.array([1.0, 1.0, 1.0]) * edgelen
+
+    xs = unyt.unyt_array(
+        [np.array([xs[0] * edgelen, xs[1] * edgelen, xs[2] * edgelen])], unitL
+    )
+    xp *= edgelen
+    h *= edgelen
+
+    w = Writer(unit_system=cosmo_units, box_size=boxsize, dimension=3)
+
+    # write particle positions and smoothing lengths
+    w.gas.coordinates = xp
+    w.stars.coordinates = xs
+    w.gas.velocities = np.zeros(xp.shape) * (unitL / unyt.Myr)
+    w.stars.velocities = np.zeros(xs.shape) * (unitL / unyt.Myr)
+    w.gas.smoothing_length = h
+    w.stars.smoothing_length = w.gas.smoothing_length[:1]
+
+    # get gas masses
+    nH = 1e-3 * unyt.cm ** (-3)
+    rhoH = nH * unyt.proton_mass
+    Mtot = rhoH * edgelen ** 3
+    mpart = Mtot / xp.shape[0]
+    mpart = mpart.to(cosmo_units["mass"])
+    w.gas.masses = np.ones(xp.shape[0], dtype=np.float64) * mpart
+    w.stars.masses = np.ones(xs.shape[0], dtype=np.float64) * mpart
+
+    # get gas internal energy for a given temperature and composition
+    XH = 1.0  # hydrogen mass fraction
+    XHe = 0.0  # hydrogen mass fraction
+    T = 100 * unyt.K
+    XHI, XHII, XHeI, XHeII, XHeIII = get_mass_fractions(T, XH, XHe)
+    mu = mean_molecular_weight(XHI, XHII, XHeI, XHeII, XHeIII)
+    internal_energy = internal_energy(T, mu)
+
+    w.gas.internal_energy = np.ones(xp.shape[0], dtype=np.float64) * internal_energy
+
+    w.write("stromgrenSphere-3D.hdf5")
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_3D/makePropagationTestIC.py b/examples/RadiativeTransferTests/StromgrenSphere_3D/makePropagationTestIC.py
new file mode 100755
index 0000000000000000000000000000000000000000..fa81877a54fecb06d24ec848e5bba3e74e4324ec
--- /dev/null
+++ b/examples/RadiativeTransferTests/StromgrenSphere_3D/makePropagationTestIC.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+
+# ---------------------------------------------------------------------
+# Add a single star in the center of a glass distribution
+# Intended for the photon propagation test.
+# ---------------------------------------------------------------------
+
+from swiftsimio import Writer
+import unyt
+import numpy as np
+import h5py
+
+
+glass = h5py.File("glassCube_64.hdf5", "r")
+parts = glass["PartType0"]
+xp = parts["Coordinates"][:]
+h = parts["SmoothingLength"][:]
+glass.close()
+
+# replace the particle closest to the center
+# by the star
+r = np.sqrt(np.sum((0.5 - xp) ** 2, axis=1))
+rmin = np.argmin(r)
+xs = xp[rmin]
+xp = np.delete(xp, rmin, axis=0)
+h = np.delete(h, rmin)
+
+
+unitL = unyt.cm
+t_end = 1e-3 * unyt.s
+edgelen = unyt.c.to("cm/s") * t_end * 2.0
+edgelen = edgelen.to(unitL)
+boxsize = unyt.unyt_array([edgelen.v, edgelen.v, edgelen.v], unitL)
+
+xs = unyt.unyt_array(
+    [np.array([xs[0] * edgelen, xs[1] * edgelen, xs[2] * edgelen])], unitL
+)
+xp *= edgelen
+h *= edgelen
+
+
+w = Writer(unit_system=unyt.unit_systems.cgs_unit_system, box_size=boxsize, dimension=3)
+
+w.gas.coordinates = xp
+w.stars.coordinates = xs
+w.gas.velocities = np.zeros(xp.shape) * (unyt.cm / unyt.s)
+w.stars.velocities = np.zeros(xs.shape) * (unyt.cm / unyt.s)
+w.gas.masses = np.ones(xp.shape[0], dtype=float) * 100 * unyt.g
+w.stars.masses = np.ones(xs.shape[0], dtype=float) * 100 * unyt.g
+w.gas.internal_energy = (
+    np.ones(xp.shape[0], dtype=float) * (300.0 * unyt.kb * unyt.K) / unyt.g
+)
+
+w.gas.smoothing_length = h
+w.stars.smoothing_length = w.gas.smoothing_length[:1]
+
+w.write("propagationTest-3D.hdf5")
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_3D/plotPhotonPropagationCheck.py b/examples/RadiativeTransferTests/StromgrenSphere_3D/plotPhotonPropagationCheck.py
index 253389a6c8dadc762e3398ea3cde60e903ef8cb0..11516371aa4535c10ff62d82d9f3cad1504fd12f 100755
--- a/examples/RadiativeTransferTests/StromgrenSphere_3D/plotPhotonPropagationCheck.py
+++ b/examples/RadiativeTransferTests/StromgrenSphere_3D/plotPhotonPropagationCheck.py
@@ -16,21 +16,27 @@
 #   correctly.
 # ----------------------------------------------------------------------
 
-import sys, os, gc
-import swiftsimio
+import gc
+import os
+import sys
+import matplotlib as mpl
 import numpy as np
+import swiftsimio
 import unyt
 from matplotlib import pyplot as plt
-import matplotlib as mpl
 from scipy import stats
 from scipy.optimize import curve_fit
 
 # Parameters users should/may tweak
 
 # snapshot basename
-snapshot_base = "output"
+snapshot_base = "propagation_test"
+
+# additional anisotropy estimate plot?
+plot_anisotropy_estimate = False
 
 # which photon group to use.
+# NOTE: array index, not group number (which starts at 1 for GEAR)
 group_index = 0
 
 scatterplot_kwargs = {
@@ -168,6 +174,7 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     time = meta.time
     r_expect = meta.time * meta.reduced_lightspeed
 
+    L = None
     use_const_emission_rates = bool(meta.parameters["GEARRT:use_const_emission_rates"])
     if use_const_emission_rates:
         # read emission rate parameter as string
@@ -186,7 +193,11 @@ def plot_photons(filename, emin, emax, fmin, fmax):
         const_emission_rates = unyt.unyt_array(emlist, unyt.L_Sun)
         L = const_emission_rates[group_index]
 
-    fig = plt.figure(figsize=(5 * 4, 5.5), dpi=200)
+    if plot_anisotropy_estimate:
+        ncols = 4
+    else:
+        ncols = 3
+    fig = plt.figure(figsize=(5 * ncols, 5.5), dpi=200)
 
     nbins = 100
     r_bin_edges = np.linspace(0.5 * edgelen * 1e-3, 0.507 * edgelen, nbins + 1)
@@ -205,8 +216,6 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     Fz = getattr(data.gas.photon_fluxes, "Group" + str(group_index + 1) + "Z")
 
     fmag = np.sqrt(Fx ** 2 + Fy ** 2 + Fz ** 2)
-    sum_fmag = fmag.sum()
-    max_fmag = fmag.max()
     particle_count, _ = np.histogram(
         r,
         bins=r_analytical_bin_edges,
@@ -221,7 +230,7 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     # ------------------------
     # Plot photon energies
     # ------------------------
-    ax1 = fig.add_subplot(1, 4, 1)
+    ax1 = fig.add_subplot(1, ncols, 1)
     ax1.set_title("Particle Radiation Energies")
     ax1.set_ylabel("Photon Energy [$" + energy_units_str + "$]")
 
@@ -278,7 +287,7 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     # ------------------------------
     # Plot binned photon energies
     # ------------------------------
-    ax2 = fig.add_subplot(1, 4, 2)
+    ax2 = fig.add_subplot(1, ncols, 2)
     ax2.set_title("Total Radiation Energy in radial bins")
     ax2.set_ylabel("Total Photon Energy [$" + energy_units_str + "$]")
 
@@ -323,7 +332,7 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     # ------------------------------
     # Plot photon fluxes
     # ------------------------------
-    ax3 = fig.add_subplot(1, 4, 3)
+    ax3 = fig.add_subplot(1, ncols, 3)
     ax3.set_title("Particle Radiation Flux Magnitudes")
     ax3.set_ylabel("Photon Flux Magnitude [$" + flux_units_str + "$]")
 
@@ -387,55 +396,58 @@ def plot_photons(filename, emin, emax, fmin, fmax):
     # Plot photon flux sum
     # ------------------------------
 
-    ax4 = fig.add_subplot(1, 4, 4)
-    ax4.set_title("Vectorial Sum of Radiation Flux in radial bins")
-    ax4.set_ylabel("[1]")
-
-    fmag_sum_bin, _, _ = stats.binned_statistic(
-        r,
-        fmag,
-        statistic="sum",
-        bins=r_bin_edges,
-        range=(r_bin_edges[0], r_bin_edges[-1]),
-    )
-    mask_sum = fmag_sum_bin > 0
-    fmag_max_bin, _, _ = stats.binned_statistic(
-        r,
-        fmag,
-        statistic="max",
-        bins=r_bin_edges,
-        range=(r_bin_edges[0], r_bin_edges[-1]),
-    )
-    mask_max = fmag_max_bin > 0
-    Fx_sum_bin, _, _ = stats.binned_statistic(
-        r,
-        Fx,
-        statistic="sum",
-        bins=r_bin_edges,
-        range=(r_bin_edges[0], r_bin_edges[-1]),
-    )
-    Fy_sum_bin, _, _ = stats.binned_statistic(
-        r,
-        Fy,
-        statistic="sum",
-        bins=r_bin_edges,
-        range=(r_bin_edges[0], r_bin_edges[-1]),
-    )
-    F_sum_bin = np.sqrt(Fx_sum_bin ** 2 + Fy_sum_bin ** 2)
+    if plot_anisotropy_estimate:
+        ax4 = fig.add_subplot(1, ncols, 4)
+        ax4.set_title("Vectorial Sum of Radiation Flux in radial bins")
+        ax4.set_ylabel("[1]")
+
+        fmag_sum_bin, _, _ = stats.binned_statistic(
+            r,
+            fmag,
+            statistic="sum",
+            bins=r_bin_edges,
+            range=(r_bin_edges[0], r_bin_edges[-1]),
+        )
+        mask_sum = fmag_sum_bin > 0
+        fmag_max_bin, _, _ = stats.binned_statistic(
+            r,
+            fmag,
+            statistic="max",
+            bins=r_bin_edges,
+            range=(r_bin_edges[0], r_bin_edges[-1]),
+        )
+        mask_max = fmag_max_bin > 0
+        Fx_sum_bin, _, _ = stats.binned_statistic(
+            r,
+            Fx,
+            statistic="sum",
+            bins=r_bin_edges,
+            range=(r_bin_edges[0], r_bin_edges[-1]),
+        )
+        Fy_sum_bin, _, _ = stats.binned_statistic(
+            r,
+            Fy,
+            statistic="sum",
+            bins=r_bin_edges,
+            range=(r_bin_edges[0], r_bin_edges[-1]),
+        )
+        F_sum_bin = np.sqrt(Fx_sum_bin ** 2 + Fy_sum_bin ** 2)
 
-    ax4.plot(
-        r_bin_centres[mask_sum],
-        F_sum_bin[mask_sum] / fmag_sum_bin[mask_sum],
-        **lineplot_kwargs,
-        label="$\left| \sum_{i \in \mathrm{particles \ in \ bin}} \mathbf{F}_i \\right| $ / $\sum_{i \in \mathrm{particles \ in \ bin}} \left| \mathbf{F}_{i} \\right| $",
-    )
-    ax4.plot(
-        r_bin_centres[mask_max],
-        F_sum_bin[mask_max] / fmag_max_bin[mask_max],
-        **lineplot_kwargs,
-        linestyle="--",
-        label="$\left| \sum_{i \in \mathrm{particles \ in \ bin}} \mathbf{F}_i \\right| $ / $\max_{i \in \mathrm{particles \ in \ bin}} \left| \mathbf{F}_{i} \\right| $",
-    )
+        ax4.plot(
+            r_bin_centres[mask_sum],
+            F_sum_bin[mask_sum] / fmag_sum_bin[mask_sum],
+            **lineplot_kwargs,
+            label="$\left| \sum_{i \in \mathrm{particles \ in \ bin}} \mathbf{F}_i \\right| $ "
+            + "/ $\sum_{i \in \mathrm{particles \ in \ bin}} \left| \mathbf{F}_{i} \\right| $",
+        )
+        ax4.plot(
+            r_bin_centres[mask_max],
+            F_sum_bin[mask_max] / fmag_max_bin[mask_max],
+            **lineplot_kwargs,
+            linestyle="--",
+            label="$\left| \sum_{i \in \mathrm{particles \ in \ bin}} \mathbf{F}_i \\right| $ "
+            + " / $\max_{i \in \mathrm{particles \ in \ bin}} \left| \mathbf{F}_{i} \\right| $",
+        )
 
     # -------------------------------------------
     # Cosmetics that all axes have in common
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_3D/plotRadiationProjection.py b/examples/RadiativeTransferTests/StromgrenSphere_3D/plotRadiationProjection.py
index 05cfa4a6a82dda75934ebeb2914c95a2129d0a6c..617226cc71433109cba19160769b7fc219882fd2 100755
--- a/examples/RadiativeTransferTests/StromgrenSphere_3D/plotRadiationProjection.py
+++ b/examples/RadiativeTransferTests/StromgrenSphere_3D/plotRadiationProjection.py
@@ -23,8 +23,10 @@ from matplotlib.colors import SymLogNorm
 
 # plot all groups and all photon quantities
 plot_all_data = True
-# snapshot basename
-snapshot_base = "output"
+
+# plotting propagation tests or Stromgren sphere?
+do_stromgren_sphere = True
+
 # fancy up the plots a bit?
 fancy = True
 
@@ -34,12 +36,24 @@ imshow_kwargs = {"origin": "lower", "cmap": "viridis"}
 # parameters for swiftsimio projections
 projection_kwargs = {"resolution": 1024, "parallel": True}
 
+# snapshot basename
+snapshot_base = "propagation_test"
+
 # Set Units of your choice
 energy_units = unyt.erg
 energy_units_str = "\\rm{erg}"
 flux_units = 1e10 * energy_units / unyt.cm ** 2 / unyt.s
 flux_units_str = "10^{10} \\rm{erg} \\ \\rm{cm}^{-2} \\ \\rm{s}^{-1}"
 time_units = unyt.s
+
+if do_stromgren_sphere:
+    snapshot_base = "output"
+
+    energy_units = 1e50 * unyt.erg
+    energy_units_str = "10^{50} \\rm{erg}"
+    flux_units = 1e50 * unyt.erg / unyt.kpc ** 2 / unyt.Gyr
+    flux_units_str = "10^{60} \\rm{erg} \\ \\rm{kpc}^{-2} \\ \\rm{Gyr}^{-1}"
+    time_units = unyt.Myr
 # -----------------------------------------------------------------------
 
 
@@ -76,6 +90,10 @@ def get_snapshot_list(snapshot_basename="output"):
             quit(1)
         snaplist.append(fname)
 
+    if len(snaplist) == 0:
+        print("Didn't find any snapshots with basename '", snapshot_basename, "'")
+        quit(1)
+
     return snaplist
 
 
@@ -142,7 +160,7 @@ def plot_photons(filename, energy_boundaries=None, flux_boundaries=None):
 
     if plot_all_data:
         fig = plt.figure(figsize=(5 * 4, 5.05 * ngroups), dpi=200)
-        figname = filename[:-5] + "-all-quantities.png"
+        figname = filename[:-5] + "-radiation-projection.png"
 
         for g in range(ngroups):
 
@@ -320,7 +338,6 @@ def get_minmax_vals(snaplist):
             dirmin = []
             dirmax = []
             for direction in ["X", "Y", "Z"]:
-                new_attribute_str = "radiation_flux" + str(g + 1) + direction
                 f = getattr(data.gas.photon_fluxes, "Group" + str(g + 1) + direction)
                 dirmin.append(f.min())
                 dirmax.append(f.max())
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_3D/plotSolution.py b/examples/RadiativeTransferTests/StromgrenSphere_3D/plotSolution.py
new file mode 100755
index 0000000000000000000000000000000000000000..1c00fb71c14f94583e8a9b4532bd91f5339bc474
--- /dev/null
+++ b/examples/RadiativeTransferTests/StromgrenSphere_3D/plotSolution.py
@@ -0,0 +1,285 @@
+#!/usr/bin/env python3
+
+# ----------------------------------------------------
+# Plot slices of the hydrogen number density,
+# pressure, temperature, and hydrogen mass fraction.
+# ----------------------------------------------------
+
+import sys
+import os
+import swiftsimio
+import gc
+import unyt
+from matplotlib import pyplot as plt
+import matplotlib as mpl
+from mpl_toolkits.axes_grid1 import make_axes_locatable
+from matplotlib.colors import LogNorm
+from swiftsimio.visualisation.slice import slice_gas
+
+# Parameters users should/may tweak
+
+# snapshot basename
+snapshot_base = "output"
+
+# parameters for imshow plots
+imshow_kwargs = {"origin": "lower"}
+
+# parameters for swiftsimio slices
+slice_kwargs = {"slice": 0.5, "resolution": 1000, "parallel": True}
+
+# -----------------------------------------------------------------------
+
+
+# Read in cmdline arg: Are we plotting only one snapshot, or all?
+plot_all = False
+try:
+    snapnr = int(sys.argv[1])
+except IndexError:
+    plot_all = True
+
+mpl.rcParams["text.usetex"] = True
+
+
+def get_snapshot_list(snapshot_basename="output"):
+    """
+    Find the snapshot(s) that are to be plotted 
+    and return their names as list
+    """
+
+    snaplist = []
+
+    if plot_all:
+        dirlist = os.listdir()
+        for f in dirlist:
+            if f.startswith(snapshot_basename) and f.endswith("hdf5"):
+                snaplist.append(f)
+
+        snaplist = sorted(snaplist)
+
+    else:
+        fname = snapshot_basename + "_" + str(snapnr).zfill(4) + ".hdf5"
+        if not os.path.exists(fname):
+            print("Didn't find file", fname)
+            quit(1)
+        snaplist.append(fname)
+
+    if len(snaplist) == 0:
+        print("Didn't find any outputs with basename '", snapshot_basename, "'")
+        quit(1)
+
+    return snaplist
+
+
+def mean_molecular_weight(XH0, XHp, XHe0, XHep, XHepp):
+    """
+    Determines the mean molecular weight for given 
+    mass fractions of
+        hydrogen:   XH0
+        H+:         XHp
+        He:         XHe0
+        He+:        XHep
+        He++:       XHepp
+
+    returns:
+        mu: mean molecular weight [in atomic mass units]
+        NOTE: to get the actual mean mass, you still need
+        to multiply it by m_u, as is tradition in the formulae
+    """
+
+    # 1/mu = sum_j X_j / A_j * (1 + E_j)
+    # A_H    = 1, E_H    = 0
+    # A_Hp   = 1, E_Hp   = 1
+    # A_He   = 4, E_He   = 0
+    # A_Hep  = 4, E_Hep  = 1
+    # A_Hepp = 4, E_Hepp = 2
+    one_over_mu = XH0 + 2 * XHp + 0.25 * XHe0 + 0.5 * XHep + 0.75 * XHepp
+
+    return 1.0 / one_over_mu
+
+
+def gas_temperature(u, mu, gamma):
+    """
+    Compute the gas temperature given the specific internal 
+    energy u and the mean molecular weight mu
+    """
+
+    # Using u = 1 / (gamma - 1) * p / rho
+    #   and p = N/V * kT = rho / (mu * m_u) * kT
+
+    T = u * (gamma - 1) * mu * unyt.atomic_mass_unit / unyt.boltzmann_constant
+
+    return T.to("K")
+
+
+def set_colorbar(ax, im):
+    """
+    Adapt the colorbar a bit for axis object <ax> and
+    imshow instance <im>
+    """
+    divider = make_axes_locatable(ax)
+    cax = divider.append_axes("right", size="5%", pad=0.05)
+    plt.colorbar(im, cax=cax)
+    return
+
+
+def plot_result(filename):
+    """
+    Create and save the plot
+    """
+    print("working on", filename)
+
+    data = swiftsimio.load(filename)
+    meta = data.metadata
+
+    global imshow_kwargs
+    imshow_kwargs["extent"] = [
+        0.0 * meta.boxsize[0].v,
+        0.9 * meta.boxsize[0].v,
+        0.0 * meta.boxsize[1].v,
+        0.9 * meta.boxsize[1].v,
+    ]
+    cutoff = int(0.05 * slice_kwargs["resolution"])
+
+    mass_map = slice_gas(data, project="masses", **slice_kwargs)
+    gamma = meta.hydro_scheme["Adiabatic index"][0]
+
+    data.gas.mXHI = data.gas.ion_mass_fractions.HI * data.gas.masses
+    data.gas.mXHII = data.gas.ion_mass_fractions.HII * data.gas.masses
+    data.gas.mP = data.gas.pressures * data.gas.masses
+    data.gas.mrho = data.gas.densities * data.gas.masses
+
+    imf = data.gas.ion_mass_fractions
+    mu = mean_molecular_weight(imf.HI, imf.HII, imf.HeI, imf.HeII, imf.HeIII)
+    data.gas.mT = (
+        gas_temperature(data.gas.internal_energies, mu, gamma) * data.gas.masses
+    )
+
+    mass_weighted_hydrogen_map = slice_gas(data, project="mXHI", **slice_kwargs)
+    mass_weighted_pressure_map = slice_gas(data, project="mP", **slice_kwargs)
+    mass_weighted_density_map = slice_gas(data, project="mrho", **slice_kwargs)
+    mass_weighted_temperature_map = slice_gas(data, project="mT", **slice_kwargs)
+
+    hydrogen_map = mass_weighted_hydrogen_map / mass_map
+    hydrogen_map = hydrogen_map[cutoff:-cutoff, cutoff:-cutoff]
+
+    pressure_map = mass_weighted_pressure_map / mass_map
+    pressure_map = pressure_map[cutoff:-cutoff, cutoff:-cutoff]
+    pressure_map = pressure_map.to("g/cm/s**2")
+
+    density_map = mass_weighted_density_map / mass_map
+    density_map = density_map[cutoff:-cutoff, cutoff:-cutoff]
+    density_map = density_map.to("kg/cm**3")
+    density_map = density_map / unyt.proton_mass
+
+    temperature_map = mass_weighted_temperature_map / mass_map
+    temperature_map = temperature_map[cutoff:-cutoff, cutoff:-cutoff]
+    temperature_map = temperature_map.to("K")
+
+    fig = plt.figure(figsize=(12, 12), dpi=200)
+    figname = filename[:-5] + ".png"
+
+    ax1 = fig.add_subplot(221)
+    ax2 = fig.add_subplot(222)
+    ax3 = fig.add_subplot(223)
+    ax4 = fig.add_subplot(224)
+
+    try:
+        im1 = ax1.imshow(
+            density_map.T,
+            **imshow_kwargs,
+            norm=LogNorm(vmin=1e-4, vmax=1e-1),
+            cmap="bone",
+        )
+        set_colorbar(ax1, im1)
+        ax1.set_title(r"Hydrogen Number Density [cm$^{-3}$]")
+    except ValueError:
+        print(
+            filename,
+            "densities wrong? min",
+            data.gas.densities.min(),
+            "max",
+            data.gas.densities.max(),
+        )
+        return
+
+    try:
+        im2 = ax2.imshow(
+            hydrogen_map.T,
+            **imshow_kwargs,
+            norm=LogNorm(vmin=1e-3, vmax=1.0),
+            cmap="cividis",
+        )
+        set_colorbar(ax2, im2)
+        ax2.set_title("Hydrogen Mass Fraction [1]")
+    except ValueError:
+        print(
+            filename,
+            "mass fraction wrong? min",
+            data.gas.ion_mass_fractions.HI.min(),
+            "max",
+            data.gas.ion_mass_fractions.HI.max(),
+        )
+        return
+
+    try:
+        im3 = ax3.imshow(
+            pressure_map.T,
+            **imshow_kwargs,
+            norm=LogNorm(vmin=1e-15, vmax=1e-12),
+            cmap="viridis",
+        )
+        set_colorbar(ax3, im3)
+        ax3.set_title(r"Pressure [g/cm/s$^2$]")
+    except ValueError:
+        print(
+            filename,
+            "pressures wrong? min",
+            data.gas.pressures.min(),
+            "max",
+            data.gas.pressures.max(),
+        )
+        return
+
+    try:
+        im4 = ax4.imshow(
+            temperature_map.T,
+            **imshow_kwargs,
+            norm=LogNorm(vmin=1e2, vmax=4e4),
+            cmap="inferno",
+        )
+        set_colorbar(ax4, im4)
+        ax4.set_title(r"Temperature [K]")
+    except ValueError:
+        print(
+            filename,
+            "temperatures wrong? min",
+            temperature_map.min(),
+            "max",
+            temperature_map.max(),
+        )
+        return
+
+    for ax in [ax1, ax2, ax3, ax4]:
+        ax.set_xlabel("[kpc]")
+        ax.set_ylabel("[kpc]")
+
+    title = filename.replace("_", "\_")  # exception handle underscore for latex
+    if meta.cosmology is not None:
+        title += ", $z$ = {0:.2e}".format(meta.z)
+    title += ", $t$ = {0:.2e}".format(meta.time.to("Myr"))
+    fig.suptitle(title)
+
+    plt.tight_layout()
+    plt.savefig(figname)
+    plt.close()
+    gc.collect()
+    return
+
+
+if __name__ == "__main__":
+
+    snaplist = get_snapshot_list(snapshot_base)
+    #  snaplist = snaplist[118:]
+
+    for f in snaplist:
+        plot_result(f)
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_3D/propagationTest-3D.yml b/examples/RadiativeTransferTests/StromgrenSphere_3D/propagationTest-3D.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b47058bbb49e4c396b83c4794ff1fc9c562ca3e1
--- /dev/null
+++ b/examples/RadiativeTransferTests/StromgrenSphere_3D/propagationTest-3D.yml
@@ -0,0 +1,60 @@
+MetaData:
+  run_name: StromgrenSpherePropagationTest3D
+
+# Define the system of units to use internally. 
+InternalUnitSystem:
+  UnitMass_in_cgs:     1.
+  UnitLength_in_cgs:   1.
+  UnitVelocity_in_cgs: 1.
+  UnitCurrent_in_cgs:  1.
+  UnitTemp_in_cgs:     1.
+
+# Parameters governing the time integration
+TimeIntegration:
+  time_begin: 0.    # The starting time of the simulation (in internal units).
+  time_end:   0.001 # end time: radiation reaches edge of box
+  dt_min:     1.e-12 # The minimal time-step size of the simulation (in internal units).
+  dt_max:     2.e-04  # The maximal time-step size of the simulation (in internal units).
+
+# Parameters governing the snapshots
+Snapshots:
+  basename:            propagation_test # Common part of the name of output files
+  time_first:          0.     # Time of the first output (in internal units)
+  delta_time:          0.0001 # Time between snapshots
+
+# Parameters governing the conserved quantities statistics
+Statistics:
+  time_first:          0.
+  delta_time:          5e-4 # Time between statistics output
+
+# Parameters for the hydrodynamics scheme
+SPH:
+  resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
+  CFL_condition:         0.6      # Courant-Friedrich-Levy condition for time integration.
+  minimal_temperature:   10.      # Kelvin
+
+# Parameters related to the initial conditions
+InitialConditions:
+  file_name:  ./propagationTest-3D.hdf5     # The file to read
+  periodic:   1                             # peridioc ICs. Keep them periodic so we don't loose photon energy. TODO: CHANGE LATER WHEN YOU ACTUALLY DO GAS INTERACTIONS
+
+Scheduler:
+  max_top_level_cells: 64
+
+GEARRT:
+    f_reduce_c: 1.        # reduce the speed of light for the RT solver by multiplying c with this factor
+    CFL_condition: 0.99
+    photon_groups_Hz: []  # Photon frequency group bin edges in Hz. Needs to be 1 less than the number of groups (N) requested during the configuration (--with-RT=GEAR_N).
+    use_const_emission_rates: 1         # (Optional) use constant emission rates for stars as defined with star_emission_rates_erg_LSol parameter
+    star_emission_rates_LSol: [1e-28]   # (Optional) constant star emission rates for each photon frequency group to use if use_constant_emission_rates is set.
+    hydrogen_mass_fraction:  0.76                     # total hydrogen (H + H+) mass fraction in the metal-free portion of the gas
+    stellar_spectrum_type: 0                          # Which radiation spectrum to use. 0: constant from 0 until some max frequency set by stellar_spectrum_const_max_frequency_Hz. 1: blackbody spectrum.
+    stellar_spectrum_const_max_frequency_Hz: 1.e17    # (Conditional) if stellar_spectrum_type=0, use this maximal frequency for the constant spectrum. 
+    set_initial_ionization_mass_fractions: 1          # (Optional) manually overwrite initial mass fraction of each species (using the values you set below)
+    mass_fraction_HI: 0.76                            # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HI mass fractions to this value
+    mass_fraction_HII: 0.                             # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HII mass fractions to this value
+    mass_fraction_HeI: 0.24                           # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HeI mass fractions to this value
+    mass_fraction_HeII: 0.                            # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HeII mass fractions to this value
+    mass_fraction_HeIII: 0.                           # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HeIII mass fractions to this value
+    skip_thermochemistry: 1                           # skip thermochemistry.
+    stars_max_timestep: 1.562500e-05                  # (Optional) restrict the maximal timestep of stars to this value (in internal units). Set to negative to turn off.
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_3D/run.sh b/examples/RadiativeTransferTests/StromgrenSphere_3D/run.sh
index 0afaf94220f0aa102c5db22c05c79e47ec2da6e0..1e60f3e825a4cecfdd7540d371421e0a6970d05b 100755
--- a/examples/RadiativeTransferTests/StromgrenSphere_3D/run.sh
+++ b/examples/RadiativeTransferTests/StromgrenSphere_3D/run.sh
@@ -24,5 +24,4 @@ fi
 # Plot the photon propagation checks.
 # Make sure you set the correct photon group to plot
 # inside the script
-python3 ./plotPhotonPropagationCheck.py
-
+python3 ./plotSolution.py
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_3D/runPropagationTest.sh b/examples/RadiativeTransferTests/StromgrenSphere_3D/runPropagationTest.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c61fc9de7dd0badf1efcf26f0f73ecf9a872b521
--- /dev/null
+++ b/examples/RadiativeTransferTests/StromgrenSphere_3D/runPropagationTest.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# make run.sh fail if a subcommand fails
+set -e
+set -o pipefail
+
+if [ ! -e glassCube_64.hdf5 ]
+then
+    echo "Fetching initial glass file for Strömgen Sphere 3D example ..."
+    ./getGlass.sh
+fi
+
+if [ ! -f 'propagationTest-3D.hdf5' ]; then
+    echo "Generating ICs"
+    python3 makePropagationTestIC.py
+fi
+
+# Run SWIFT with RT
+../../swift \
+    --hydro --threads=4 --stars --external-gravity \
+    --feedback --radiation --fpe \
+    ./propagationTest-3D.yml 2>&1 | tee output.log
+
+# Plot the photon propagation checks.
+# Make sure you set the correct photon group to plot
+# inside the script
+python3 ./plotPhotonPropagationCheck.py
diff --git a/examples/RadiativeTransferTests/StromgrenSphere_3D/stromgrenSphere-3D.yml b/examples/RadiativeTransferTests/StromgrenSphere_3D/stromgrenSphere-3D.yml
index 97499f58f4342e14c827b97d062a9129247d1484..048c948d61a88dfb4cd5e9bce23db7dc524d2ff6 100644
--- a/examples/RadiativeTransferTests/StromgrenSphere_3D/stromgrenSphere-3D.yml
+++ b/examples/RadiativeTransferTests/StromgrenSphere_3D/stromgrenSphere-3D.yml
@@ -3,57 +3,62 @@ MetaData:
 
 # Define the system of units to use internally. 
 InternalUnitSystem:
-  UnitMass_in_cgs:     1.
-  UnitLength_in_cgs:   1.
-  UnitVelocity_in_cgs: 1.
+  UnitMass_in_cgs:     1.98841586e+33 # 1 M_Sol
+  UnitLength_in_cgs:   3.08567758e21 # kpc in cm
+  UnitVelocity_in_cgs: 1.e5 # km/s
   UnitCurrent_in_cgs:  1.
-  UnitTemp_in_cgs:     1.
+  UnitTemp_in_cgs:     1. # K
+
 
 # Parameters governing the time integration
 TimeIntegration:
   time_begin: 0.    # The starting time of the simulation (in internal units).
-  time_end:   0.001 # end time: radiation reaches edge of box
+  time_end:   0.512 # end time: radiation reaches edge of box
   dt_min:     1.e-12 # The minimal time-step size of the simulation (in internal units).
-  dt_max:     2.e-04  # The maximal time-step size of the simulation (in internal units).
+  dt_max:     1.e-03  # The maximal time-step size of the simulation (in internal units).
 
 # Parameters governing the snapshots
 Snapshots:
   basename:            output # Common part of the name of output files
   time_first:          0.     # Time of the first output (in internal units)
-  delta_time:          0.0001 # Time between snapshots
+  delta_time:          0.001 # Time between snapshots
 
 # Parameters governing the conserved quantities statistics
 Statistics:
   time_first:          0.
-  delta_time:          5e-4 # Time between statistics output
+  delta_time:          1e-3 # Time between statistics output
 
 # Parameters for the hydrodynamics scheme
 SPH:
   resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
-  CFL_condition:         0.6      # Courant-Friedrich-Levy condition for time integration.
+  CFL_condition:         0.8      # Courant-Friedrich-Levy condition for time integration.
   minimal_temperature:   10.      # Kelvin
 
 # Parameters related to the initial conditions
 InitialConditions:
   file_name:  ./stromgrenSphere-3D.hdf5     # The file to read
-  periodic:   1                             # peridioc ICs. Keep them periodic so we don't loose photon energy. TODO: CHANGE LATER WHEN YOU ACTUALLY DO GAS INTERACTIONS
+  periodic:   0                             # periodic ICs. 
 
 Scheduler:
   max_top_level_cells: 64
 
+Stars:
+  resolution_eta:       2.2348        # (Optional) Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). Defaults to the SPH value.
+
 GEARRT:
-    f_reduce_c: 1.        # reduce the speed of light for the RT solver by multiplying c with this factor
-    CFL_condition: 0.6
-    photon_groups_Hz: []  # Photon frequency group bin edges in Hz. Needs to be 1 less than the number of groups (N) requested during the configuration (--with-RT=GEAR_N).
-    use_const_emission_rates: 1         # (Optional) use constant emission rates for stars as defined with star_emission_rates_erg_LSol parameter
-    star_emission_rates_LSol: [1e-28]   # (Optional) constant star emission rates for each photon frequency group to use if use_constant_emission_rates is set.
-    hydrogen_mass_fraction:  0.76                     # total hydrogen (H + H+) mass fraction in the metal-free portion of the gas
-    stellar_spectrum_type: 0                          # Which radiation spectrum to use. 0: constant from 0 until some max frequency set by stellar_spectrum_const_max_frequency_Hz. 1: blackbody spectrum.
-    stellar_spectrum_const_max_frequency_Hz: 1.e17    # (Conditional) if stellar_spectrum_type=0, use this maximal frequency for the constant spectrum. 
+    f_reduce_c: 0.01        # reduce the speed of light for the RT solver by multiplying c with this factor
+    CFL_condition: 0.9
+    photon_groups_Hz: [3.288e15, 5.945e15, 13.157e15] # Photon frequency group bin edges in Hz. Needs to be 1 less than the number of groups (N) requested during the configuration (--with-RT=GEAR_N). Outer edges of zero and infinity are assumed.
+    use_const_emission_rates: 1                       # (Optional) use constant emission rates for stars as defined with star_emission_rates_erg_LSol parameter
+    star_emission_rates_LSol: [247985.76636, 247985.76636]       # (Optional) constant star emission rates for each photon frequency group to use if use_constant_emission_rates is set, in units of Solar Luminosity.
+    hydrogen_mass_fraction:  1.00                     # total hydrogen (H + H+) mass fraction in the metal-free portion of the gas
+    set_equilibrium_initial_ionization_mass_fractions: 0   # (Optional) set the initial ionization fractions depending on gas temperature assuming ionization equilibrium.
     set_initial_ionization_mass_fractions: 1          # (Optional) manually overwrite initial mass fraction of each species (using the values you set below)
-    mass_fraction_HI: 0.76                            # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HI mass fractions to this value
-    mass_fraction_HII: 0.                             # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HII mass fractions to this value
-    mass_fraction_HeI: 0.24                           # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HeI mass fractions to this value
+    mass_fraction_HI: 0.999999                        # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HI mass fractions to this value
+    mass_fraction_HII: 1.e-6                          # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HII mass fractions to this value
+    mass_fraction_HeI: 0.                             # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HeI mass fractions to this value
     mass_fraction_HeII: 0.                            # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HeII mass fractions to this value
     mass_fraction_HeIII: 0.                           # (Conditional) If overwrite_initial_ionization_fractions=1, needed to set initial HeIII mass fractions to this value
-
+    stellar_spectrum_type: 1                          # Which radiation spectrum to use. 0: constant from 0 until some max frequency set by stellar_spectrum_const_max_frequency_Hz. 1: blackbody spectrum.
+    stellar_spectrum_blackbody_temperature_K: 1.e5    # (Conditional) if stellar_spectrum_type=1, use this temperature (in K) for the blackbody spectrum.
+    stars_max_timestep: 5e-4                         # (Optional) restrict the maximal timestep of stars to this value (in internal units)
diff --git a/examples/RadiativeTransferTests/UniformBox_3D/README b/examples/RadiativeTransferTests/UniformBox_3D/README
index 6305fd99428c497843e590d218b6b6326632999b..dd27a9062be5d36c8a615a9d29b2ba44e2b07ff7 100644
--- a/examples/RadiativeTransferTests/UniformBox_3D/README
+++ b/examples/RadiativeTransferTests/UniformBox_3D/README
@@ -29,4 +29,3 @@ Tl;dr:
       GEAR scheme with debugging checks enabled
     - `./rt_sanity_checks-GEAR.py` is made to work on any run with the GEAR
       scheme and debugging checks enabled.
-
diff --git a/examples/RadiativeTransferTests/UniformBox_3D/makeIC.py b/examples/RadiativeTransferTests/UniformBox_3D/makeIC.py
index bcfd67f510f2a89cf15940f8b68cac5fc8aad7b5..ff47c49a102869c399d55b2d62455be63839c288 100755
--- a/examples/RadiativeTransferTests/UniformBox_3D/makeIC.py
+++ b/examples/RadiativeTransferTests/UniformBox_3D/makeIC.py
@@ -53,7 +53,7 @@ for i in range(n_p):
         y = (j + 0.5) * dx
         for k in range(n_p):
             z = (k + 0.5) * dx
-            xp.append(np.array([x, y, z], dtype=np.float))
+            xp.append(np.array([x, y, z], dtype=np.float64))
 
 # Generate star coordinates
 for i in range(n_s):
@@ -63,7 +63,7 @@ for i in range(n_s):
         y = 0.4 * boxsize + (j + 0.52) * ds
         for k in range(n_s):
             z = 0.4 * boxsize + (k + 0.52) * ds
-            xs.append(np.array([x, y, z], dtype=np.float))
+            xs.append(np.array([x, y, z], dtype=np.float64))
 
 xp = unyt.unyt_array(xp, boxsize.units)
 xs = unyt.unyt_array(xs, boxsize.units)
@@ -75,10 +75,10 @@ w.gas.coordinates = xp
 w.stars.coordinates = xs
 w.gas.velocities = np.zeros(xp.shape) * (unyt.cm / unyt.s)
 w.stars.velocities = np.zeros(xs.shape) * (unyt.cm / unyt.s)
-w.gas.masses = np.ones(xp.shape[0], dtype=np.float) * 1000 * unyt.g
-w.stars.masses = np.ones(xs.shape[0], dtype=np.float) * 1000 * unyt.g
+w.gas.masses = np.ones(xp.shape[0], dtype=np.float64) * 1000 * unyt.g
+w.stars.masses = np.ones(xs.shape[0], dtype=np.float64) * 1000 * unyt.g
 w.gas.internal_energy = (
-    np.ones(xp.shape[0], dtype=np.float) * (300.0 * unyt.kb * unyt.K) / (unyt.g)
+    np.ones(xp.shape[0], dtype=np.float64) * (300.0 * unyt.kb * unyt.K) / unyt.g
 )
 
 # Generate initial guess for smoothing lengths based on MIPS
@@ -110,12 +110,11 @@ parts = F["/PartType0"]
 
 for grp in range(nPhotonGroups):
     dsetname = "PhotonEnergiesGroup{0:d}".format(grp + 1)
-    energydata = np.ones((nparts), dtype=np.float) * (grp + 1)
+    energydata = np.ones((nparts), dtype=np.float64) * (grp + 1)
     parts.create_dataset(dsetname, data=energydata)
 
     dsetname = "PhotonFluxesGroup{0:d}".format(grp + 1)
-    #  if dsetname not in parts.keys():
-    fluxdata = np.ones((nparts, 3), dtype=np.float) * (grp + 1)
+    fluxdata = np.ones((nparts, 3), dtype=np.float64) * (grp + 1)
     fluxdata[:, 1] *= 2.0
     fluxdata[:, 2] *= 3.0
     parts.create_dataset(dsetname, data=fluxdata)
diff --git a/examples/RadiativeTransferTests/UniformBox_3D/plotRadiationProjection.py b/examples/RadiativeTransferTests/UniformBox_3D/plotRadiationProjection.py
index aec820ea3a62b8abd314f95d3b7f7ebc6d493581..c820b283139ba8eb527d190b4e07a89fadb9b18b 100755
--- a/examples/RadiativeTransferTests/UniformBox_3D/plotRadiationProjection.py
+++ b/examples/RadiativeTransferTests/UniformBox_3D/plotRadiationProjection.py
@@ -320,7 +320,6 @@ def get_minmax_vals(snaplist):
             dirmin = []
             dirmax = []
             for direction in ["X", "Y", "Z"]:
-                new_attribute_str = "radiation_flux" + str(g + 1) + direction
                 f = getattr(data.gas.photon_fluxes, "Group" + str(g + 1) + direction)
                 dirmin.append(f.min())
                 dirmax.append(f.max())
diff --git a/examples/RadiativeTransferTests/UniformBox_3D/rt_sanity_checks-GEAR.py b/examples/RadiativeTransferTests/UniformBox_3D/rt_sanity_checks-GEAR.py
index 62392fe87b478bcda916ff8523e903a5ac300cbe..a9af4f62b94dfe3563fa3145979be1d05e32d895 100755
--- a/examples/RadiativeTransferTests/UniformBox_3D/rt_sanity_checks-GEAR.py
+++ b/examples/RadiativeTransferTests/UniformBox_3D/rt_sanity_checks-GEAR.py
@@ -124,14 +124,12 @@ def check_injection(snapdata, rundata):
     ngroups = rundata.ngroups
 
     initial_energies = np.sum(snapdata[0].gas.PhotonEnergies, axis=0)
-    initial_time = snapdata[0].time
 
     # Check 1a) : sum initial energy + sum injected energy = sum current energy
     # --------------------------------------------------------------------------
     # TODO: this assumes no cosmological expansion
 
     for snap in snapdata[1:]:
-        dt = snap.time - initial_time
         # sum of each group over all particles
         photon_energies = np.sum(snap.gas.PhotonEnergies, axis=0)
         if snap.has_stars:
@@ -140,7 +138,7 @@ def check_injection(snapdata, rundata):
                 np.sum(snap.stars.InjectedPhotonEnergy, axis=0)
             )
         else:
-            injected_energies = np.zeros(ngroups, dtype=np.float)
+            injected_energies = np.zeros(ngroups, dtype=np.float64)
 
         for g in range(ngroups):
             energy_expected = initial_energies[g] + injected_energies[g]
@@ -183,7 +181,9 @@ def check_injection(snapdata, rundata):
     if snapdata[0].has_stars:
         emission_at_initial_time = snapdata[0].stars.InjectedPhotonEnergy.sum(axis=0)
     else:
-        emission_at_initial_time = np.zeros(rundata.ngroups, dtype=np.float) * unyt.erg
+        emission_at_initial_time = (
+            np.zeros(rundata.ngroups, dtype=np.float64) * unyt.erg
+        )
 
     if rundata.use_const_emission_rate and not rundata.hydro_controlled_injection:
         if len(snapdata) <= 2:
diff --git a/examples/RadiativeTransferTests/UniformBox_3D/rt_sanity_checks.py b/examples/RadiativeTransferTests/UniformBox_3D/rt_sanity_checks.py
index 6214eba725a34adc1eefe1956b463c1db16fab73..86eafab768de3b1482bc6fdbb6fd4b357a6f6981 100755
--- a/examples/RadiativeTransferTests/UniformBox_3D/rt_sanity_checks.py
+++ b/examples/RadiativeTransferTests/UniformBox_3D/rt_sanity_checks.py
@@ -67,7 +67,6 @@ def check_hydro_sanity(snapdata):
     - RT transport calls >= RT gradient calls?
     """
 
-    nsnaps = len(snapdata)
     npart = snapdata[0].gas.coords.shape[0]
 
     print("Checking hydro")
@@ -78,7 +77,7 @@ def check_hydro_sanity(snapdata):
     for snap in snapdata:
 
         gas = snap.gas
-        stars = snap.stars
+        # stars = snap.stars
 
         # has a particle been called at least once?
         called = (
@@ -221,8 +220,6 @@ def check_stars_sanity(snapdata):
 
     print("Checking stars")
 
-    nsnaps = len(snapdata)
-
     # ----------------------------------------------
     #  check consistency of individual snapshots
     # ----------------------------------------------
@@ -260,9 +257,6 @@ def check_stars_hydro_interaction_sanity(snapdata):
     - are total calls each step equal?
     """
 
-    nsnaps = len(snapdata)
-    npart = snapdata[0].gas.coords.shape[0]
-
     print("Checking hydro vs stars")
 
     # ----------------------------------------------
diff --git a/examples/RadiativeTransferTests/UniformBox_3D/rt_uniform_box_checks-GEAR.py b/examples/RadiativeTransferTests/UniformBox_3D/rt_uniform_box_checks-GEAR.py
index d521a77d79e72ef531055a7914c2cdab89fcef36..0d855cc6529cd59c0a785726e0be039c847592a2 100755
--- a/examples/RadiativeTransferTests/UniformBox_3D/rt_uniform_box_checks-GEAR.py
+++ b/examples/RadiativeTransferTests/UniformBox_3D/rt_uniform_box_checks-GEAR.py
@@ -41,7 +41,6 @@
 
 
 import numpy as np
-import unyt
 from sys import argv
 from swift_rt_GEAR_io import get_snap_data
 
diff --git a/examples/RadiativeTransferTests/UniformBox_3D/swift_rt_GEAR_io.py b/examples/RadiativeTransferTests/UniformBox_3D/swift_rt_GEAR_io.py
index f1e6d88836c07756e8e5fed489c5c5b8affcba9a..623653ba02d0a6bfe5f9974f404a36c85dad4c98 100644
--- a/examples/RadiativeTransferTests/UniformBox_3D/swift_rt_GEAR_io.py
+++ b/examples/RadiativeTransferTests/UniformBox_3D/swift_rt_GEAR_io.py
@@ -26,8 +26,6 @@
 
 
 import os
-import h5py
-import numpy as np
 import unyt
 import swiftsimio
 
@@ -166,7 +164,6 @@ def get_snap_data(prefix="output", skip_snap_zero=False, skip_last_snap=False):
             "These tests only work for the GEAR RT scheme.",
             "Compile swift --with-rt=GEAR_N",
         )
-        quit()
 
     ngroups = int(firstfile.metadata.subgrid_scheme["PhotonGroupNumber"])
     rundata.ngroups = ngroups
@@ -266,7 +263,7 @@ def get_snap_data(prefix="output", skip_snap_zero=False, skip_last_snap=False):
             newsnap.stars = Stars
             newsnap.nstars = Stars.IDs.shape[0]
         except AttributeError:
-            Stars = RTStarData()
+            newsnap.stars = RTStarData()
             newsnap.has_stars = False
             newsnap.nstars = 0
 
diff --git a/src/rt/GEAR/rt.h b/src/rt/GEAR/rt.h
index 90350dffaa6108495b894b78ff82b4cd78324b21..d15f601c12ca239aea3aeb5bba8f6310af833ca4 100644
--- a/src/rt/GEAR/rt.h
+++ b/src/rt/GEAR/rt.h
@@ -467,12 +467,13 @@ __attribute__((always_inline)) INLINE static void rt_finalise_transport(
   struct rt_part_data* restrict rtd = &p->rt_data;
 
   for (int g = 0; g < RT_NGROUPS; g++) {
+    const float e_old = rtd->conserved[g].energy;
     rtd->conserved[g].energy += rtd->flux[g].energy * dt;
     rtd->conserved[g].flux[0] += rtd->flux[g].flux[0] * dt;
     rtd->conserved[g].flux[1] += rtd->flux[g].flux[1] * dt;
     rtd->conserved[g].flux[2] += rtd->flux[g].flux[2] * dt;
     rt_check_unphysical_conserved(&rtd->conserved[g].energy,
-                                  rtd->conserved[g].flux, 1);
+                                  rtd->conserved[g].flux, e_old, 1);
   }
 }
 
diff --git a/src/rt/GEAR/rt_getters.h b/src/rt/GEAR/rt_getters.h
index 5c04f4755c6b05812535863938148ee45381f284..c4c2d3f8795c2371c87a1e591181cb03d02e84a8 100644
--- a/src/rt/GEAR/rt_getters.h
+++ b/src/rt/GEAR/rt_getters.h
@@ -104,10 +104,9 @@ __attribute__((always_inline)) INLINE static void rt_get_pressure_tensor(
     return;
   }
 
-  const float f = rt_params.reduced_speed_of_light_inverse * Fnorm / U[0];
-  /* f^2 mustn't be > 1. This may happen since we use the reduced speed of
-   * light. */
-  const float f2 = min(1.f, f * f);
+  /* f mustn't be > 1. This may happen since we use the reduced speed of light. */
+  const float f = min(1.f, rt_params.reduced_speed_of_light_inverse * Fnorm / U[0]);
+  const float f2 = f * f;
   const float rootterm = 4.f - 3.f * f2;
   const float chi = (3.f + 4.f * f2) / (5.f + 2.f * sqrtf(rootterm));
 
diff --git a/src/rt/GEAR/rt_interaction_rates.h b/src/rt/GEAR/rt_interaction_rates.h
index 62db9467a1d32546a7638020f07859db2d341496..fb89bbf6426d31a780bb59fea641264aaae7e703 100644
--- a/src/rt/GEAR/rt_interaction_rates.h
+++ b/src/rt/GEAR/rt_interaction_rates.h
@@ -300,6 +300,7 @@ static void rt_interaction_rates_init(struct rt_props *restrict rt_props,
                                                    integration_params.kB,
                                                    integration_params.h_planck);
   } else {
+    nu_stop_final = -1.;
     error("Unknown stellar spectrum type %d", rt_props->stellar_spectrum_type);
   }
 
diff --git a/src/rt/GEAR/rt_slope_limiters_face.h b/src/rt/GEAR/rt_slope_limiters_face.h
index cfde3ea8cbcdc7ddca53cb674aa7541ec4258a65..2b4f8ad939064010554d71f77ae85c12fb528ea0 100644
--- a/src/rt/GEAR/rt_slope_limiters_face.h
+++ b/src/rt/GEAR/rt_slope_limiters_face.h
@@ -126,7 +126,7 @@ __attribute__((always_inline)) INLINE static float rt_limiter_mc(
 __attribute__((always_inline)) INLINE static float rt_limiter_vanLeer(
     const float dQi, const float dQj) {
   const float r = dQj == 0.f ? dQi * 1e6 : dQi / dQj;
-  const float absr = fabs(r);
+  const float absr = fabsf(r);
   return (r + absr) / (1.f + absr);
 }
 
diff --git a/src/rt/GEAR/rt_thermochemistry.h b/src/rt/GEAR/rt_thermochemistry.h
index 427a64ad94287f8dcfeb554cfe05bba13f492252..d50e9cb62262a599df4c9e7ad1b074257efaa730 100644
--- a/src/rt/GEAR/rt_thermochemistry.h
+++ b/src/rt/GEAR/rt_thermochemistry.h
@@ -189,13 +189,14 @@ static void rt_do_thermochemistry(struct part* restrict p,
 
   /* update radiation fields */
   for (int g = 0; g < RT_NGROUPS; g++) {
+    const float e_old = p->rt_data.conserved[g].energy;
     const float factor_new = (1.f - dt * rates_by_frequency_bin[g]);
     p->rt_data.conserved[g].energy *= factor_new;
     for (int i = 0; i < 3; i++) {
       p->rt_data.conserved[g].flux[i] *= factor_new;
     }
     rt_check_unphysical_conserved(&p->rt_data.conserved[g].energy,
-                                  p->rt_data.conserved[g].flux, 2);
+                                  p->rt_data.conserved[g].flux, e_old, 2);
   }
 
   /* copy updated grackle data to particle */
diff --git a/src/rt/GEAR/rt_unphysical.h b/src/rt/GEAR/rt_unphysical.h
index dd1ae1ed33f451db12217e1a31834f91e73a14b0..7804ef16a1216d4e11e0abe446e4085a771e0a33 100644
--- a/src/rt/GEAR/rt_unphysical.h
+++ b/src/rt/GEAR/rt_unphysical.h
@@ -79,16 +79,24 @@ __attribute__((always_inline)) INLINE static void rt_check_unphysical_density(
  *
  * @param energy pointer to the photon energy
  * @param flux pointer to photon fluxes (3 dimensional)
+ * @param e_old photon energy before the change to be checked, if available.
  * @param c integer indentifier where this function was called from
  */
 __attribute__((always_inline)) INLINE static void rt_check_unphysical_conserved(
-    float* energy, float* flux, int c) {
+    float* energy, float* flux, const float e_old, int c) {
 
   /* Check for negative energies */
+  /* Note to self for printouts: Maximal allowable F = E * c. 
+   * In some cases, e.g. while cooling, we don't modify the fluxes,
+   * so you can get an estimate of what the photon energy used to be
+   * by dividing the printed out fluxes by the speed of light in
+   * code units */
 #ifdef SWIFT_DEBUG_CHECKS
-  if (*energy < 0.f && fabs(*energy) > 1.e-1)
-    message("Fixing unphysical energy case %d | %.6e | %.6e %.6e %.6e", c,
-            *energy, flux[0], flux[1], flux[2]);
+  float ratio = 1.;
+  if (e_old != 0.f) ratio = fabs(*energy / e_old);
+  if (*energy < 0.f && ratio > 1.e-4)
+    message("Fixing unphysical energy case %d | %.6e | %.6e %.6e %.6e | %.6e", c,
+            *energy, flux[0], flux[1], flux[2], ratio);
 #endif
   if (isinf(*energy) || isnan(*energy))
     error("Got inf/nan radiation energy case %d | %.6e | %.6e %.6e %.6e", c,