diff --git a/.gitignore b/.gitignore
index 27ff2cf7ff880de2007e27978fcc1cfa22d2bd75..d2f69ad4e8759839082a38d4558a5ab7bac0e18d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -165,6 +165,8 @@ m4/lt~obsolete.m4
 /stamp-h1
 /test-driver
 
+src/equation_of_state/planetary/*.txt
+
 # Intel compiler optimization reports
 *.optrpt
 
@@ -316,3 +318,6 @@ sympy-plots-for-*.tex/
 
 #ctags
 *tags
+
+# vim
+*.swp
diff --git a/configure.ac b/configure.ac
index 56f88116c845def33300b87630524f06fec666bb..6ec1ece5ed2fef20ceab484eff4e09fce808e635 100644
--- a/configure.ac
+++ b/configure.ac
@@ -576,7 +576,7 @@ if test "x$with_profiler" != "xno"; then
       proflibs="-lprofiler"
    fi
    AC_CHECK_LIB([profiler],[ProfilerFlush],
-    [have_profiler="yes" 
+    [have_profiler="yes"
       AC_DEFINE([WITH_PROFILER],1,[Link against the gperftools profiling library.])],
     [have_profiler="no"], $proflibs)
 
@@ -973,7 +973,7 @@ esac
 # Hydro scheme.
 AC_ARG_WITH([hydro],
    [AS_HELP_STRING([--with-hydro=<scheme>],
-      [Hydro dynamics to use @<:@gadget2, minimal, pressure-entropy, pressure-energy, default, gizmo-mfv, gizmo-mfm, shadowfax, minimal-multi-mat, debug default: gadget2@:>@]
+      [Hydro dynamics to use @<:@gadget2, minimal, pressure-entropy, pressure-energy, default, gizmo-mfv, gizmo-mfm, shadowfax, planetary, debug default: gadget2@:>@]
    )],
    [with_hydro="$withval"],
    [with_hydro="gadget2"]
@@ -1012,10 +1012,11 @@ case "$with_hydro" in
    shadowfax)
       AC_DEFINE([SHADOWFAX_SPH], [1], [Shadowfax SPH])
    ;;
-   minimal-multi-mat)
-      AC_DEFINE([MINIMAL_MULTI_MAT_SPH], [1], [Minimal Multiple Material SPH])
+   planetary)
+      AC_DEFINE([PLANETARY_SPH], [1], [Planetary SPH])
    ;;
 
+
    *)
       AC_MSG_ERROR([Unknown hydrodynamics scheme: $with_hydro])
    ;;
diff --git a/examples/ConstantCosmoVolume/constant_volume.yml b/examples/ConstantCosmoVolume/constant_volume.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ad31fd1972565b0d7683711a20db78e854c3dc5f
--- /dev/null
+++ b/examples/ConstantCosmoVolume/constant_volume.yml
@@ -0,0 +1,53 @@
+# Define the system of units to use internally. 
+InternalUnitSystem:
+  UnitMass_in_cgs:     1.98848e43    # 10^10 M_sun in grams
+  UnitLength_in_cgs:   3.08567758e24 # Mpc in centimeters
+  UnitVelocity_in_cgs: 1e5   # km/s in centimeters per second
+  UnitCurrent_in_cgs:  1   # Amperes
+  UnitTemp_in_cgs:     1   # Kelvin
+
+Cosmology:
+  Omega_m: 1.
+  Omega_lambda: 0.
+  Omega_b: 1.
+  h: 1.
+  a_begin: 0.00990099
+  a_end: 1.0
+
+# Parameters governing the time integration
+TimeIntegration:
+  dt_min:     1e-7  # The minimal time-step size of the simulation (in internal units).
+  dt_max:     5e-3  # The maximal time-step size of the simulation (in internal units).
+
+# Parameters governing the snapshots
+Snapshots:
+  basename:	       box      # Common part of the name of output files
+  time_first:          0.       # Time of the first output (in internal units)
+  delta_time:          1.04     # Time difference between consecutive outputs (in internal units)
+  scale_factor_first:  0.00991
+  compression:         4
+
+# Parameters governing the conserved quantities statistics
+Statistics:
+  delta_time:          2. # 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 
+  CFL_condition:         0.1      # Courant-Friedrich-Levy condition for time integration.
+
+# Parameters related to the initial conditions
+InitialConditions:
+  file_name:  ./constantBox.hdf5       # The file to read
+
+Scheduler:
+  max_top_level_cells: 8
+  cell_split_size:     50
+  
+Gravity:
+  mesh_side_length:   32
+  eta: 0.025
+  theta: 0.3
+  r_cut_max: 5.
+  comoving_softening: 0.05
+  max_physical_softening: 0.05
diff --git a/examples/ConstantCosmoVolume/makeIC.py b/examples/ConstantCosmoVolume/makeIC.py
new file mode 100644
index 0000000000000000000000000000000000000000..970f197400129d2ca3f3a7b6ff2cfdd5a7f53f3f
--- /dev/null
+++ b/examples/ConstantCosmoVolume/makeIC.py
@@ -0,0 +1,150 @@
+################################################################################
+# This file is part of SWIFT.
+# Copyright (c) 2018 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+################################################################################
+
+import h5py
+from numpy import *
+
+# Parameters
+T_i = 100.           # Initial temperature of the gas (in K)
+z_i = 100.           # Initial redshift
+gamma = 5./3.        # Gas adiabatic index
+numPart_1D = 32
+#glassFile = "glassCube_32.hdf5"
+fileName = "constantBox.hdf5"
+
+
+# Some units
+Mpc_in_m = 3.08567758e22
+Msol_in_kg = 1.98848e30
+Gyr_in_s = 3.08567758e19
+mH_in_kg = 1.6737236e-27
+
+# Some constants
+kB_in_SI = 1.38064852e-23
+G_in_SI = 6.67408e-11
+
+# Some useful variables in h-full units
+H_0 = 1. / Mpc_in_m * 10**5 # h s^-1
+rho_0 = 3. * H_0**2 / (8* math.pi * G_in_SI) # h^2 kg m^-3
+lambda_i = 64. / H_0 * 10**5 # h^-1 m (= 64 h^-1 Mpc)
+x_min = -0.5 * lambda_i
+x_max = 0.5 * lambda_i
+
+# SI system of units
+unit_l_in_si = Mpc_in_m
+unit_m_in_si = Msol_in_kg * 1.e10
+unit_t_in_si = Gyr_in_s
+unit_v_in_si = unit_l_in_si / unit_t_in_si
+unit_u_in_si = unit_v_in_si**2
+
+#---------------------------------------------------
+
+# Read the glass file
+#glass = h5py.File(glassFile, "r" )
+
+# Read particle positions and h from the glass
+#pos = glass["/PartType0/Coordinates"][:,:]
+#h = glass["/PartType0/SmoothingLength"][:] * 0.3
+#glass.close()
+
+# Total number of particles
+#numPart = size(h)
+#if numPart != numPart_1D**3:
+#  print "Non-matching glass file"
+numPart = numPart_1D**3
+
+# Set box size and interparticle distance
+boxSize = x_max - x_min
+delta_x = boxSize / numPart_1D
+
+# Get the particle mass
+a_i = 1. / (1. + z_i)
+m_i = boxSize**3 * rho_0 / numPart
+
+# Build the arrays
+#pos *= boxSize
+#h *= boxSize
+coords = zeros((numPart, 3))
+v = zeros((numPart, 3))
+ids = linspace(1, numPart, numPart)
+m = zeros(numPart)
+h = zeros(numPart)
+u = zeros(numPart)
+
+# Set the particles on the left
+for i in range(numPart_1D):
+  for j in range(numPart_1D):
+    for k in range(numPart_1D):
+      index = i * numPart_1D**2 + j * numPart_1D + k
+      coords[index,0] = (i + 0.5) * delta_x
+      coords[index,1] = (j + 0.5) * delta_x
+      coords[index,2] = (k + 0.5) * delta_x
+      u[index] = kB_in_SI * T_i / (gamma - 1.) / mH_in_kg
+      h[index] = 1.2348 * delta_x
+      m[index] = m_i
+      v[index,0] = 0.
+      v[index,1] = 0.
+      v[index,2] = 0.
+
+# Unit conversion
+coords /= unit_l_in_si
+v /= unit_v_in_si
+m /= unit_m_in_si
+h /= unit_l_in_si
+u /= unit_u_in_si
+
+boxSize /= unit_l_in_si
+
+#File
+file = h5py.File(fileName, 'w')
+
+# Header
+grp = file.create_group("/Header")
+grp.attrs["BoxSize"] = [boxSize, boxSize, boxSize]
+grp.attrs["NumPart_Total"] =  [numPart, 0, 0, 0, 0, 0]
+grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0]
+grp.attrs["NumPart_ThisFile"] = [numPart, 0, 0, 0, 0, 0]
+grp.attrs["Time"] = 0.0
+grp.attrs["NumFilesPerSnapshot"] = 1
+grp.attrs["MassTable"] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
+grp.attrs["Flag_Entropy_ICs"] = 0
+grp.attrs["Dimension"] = 3
+
+#Runtime parameters
+grp = file.create_group("/RuntimePars")
+grp.attrs["PeriodicBoundariesOn"] = 1
+
+#Units
+grp = file.create_group("/Units")
+grp.attrs["Unit length in cgs (U_L)"] = 100. * unit_l_in_si
+grp.attrs["Unit mass in cgs (U_M)"] = 1000. * unit_m_in_si
+grp.attrs["Unit time in cgs (U_t)"] = 1. * unit_t_in_si
+grp.attrs["Unit current in cgs (U_I)"] = 1.
+grp.attrs["Unit temperature in cgs (U_T)"] = 1.
+
+#Particle group
+grp = file.create_group("/PartType0")
+grp.create_dataset('Coordinates', data=coords, dtype='d', compression="gzip", shuffle=True)
+grp.create_dataset('Velocities', data=v, dtype='f',compression="gzip", shuffle=True)
+grp.create_dataset('Masses', data=m, dtype='f', compression="gzip", shuffle=True)
+grp.create_dataset('SmoothingLength', data=h, dtype='f', compression="gzip", shuffle=True)
+grp.create_dataset('InternalEnergy', data=u, dtype='f', compression="gzip", shuffle=True)
+grp.create_dataset('ParticleIDs', data=ids, dtype='L', compression="gzip", shuffle=True)
+
+file.close()
diff --git a/examples/ConstantCosmoVolume/plotSolution.py b/examples/ConstantCosmoVolume/plotSolution.py
new file mode 100644
index 0000000000000000000000000000000000000000..6f772b85d76890dcdcd8f9eb4fdb53305dd26732
--- /dev/null
+++ b/examples/ConstantCosmoVolume/plotSolution.py
@@ -0,0 +1,224 @@
+################################################################################
+# This file is part of SWIFT.
+# Copyright (c) 2018 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+################################################################################
+
+# Computes the analytical solution of the Zeldovich pancake and compares with
+# the simulation result
+
+# Parameters
+T_i = 100.           # Initial temperature of the gas (in K)
+z_c = 1.             # Redshift of caustic formation (non-linear collapse)
+z_i = 100.           # Initial redshift
+gas_gamma = 5./3.    # Gas adiabatic index
+
+# Physical constants needed for internal energy to temperature conversion
+k_in_J_K = 1.38064852e-23
+mH_in_kg = 1.6737236e-27
+
+import matplotlib
+matplotlib.use("Agg")
+from pylab import *
+import h5py
+import os.path
+
+# Plot parameters
+params = {'axes.labelsize': 10,
+'axes.titlesize': 10,
+'font.size': 12,
+'legend.fontsize': 12,
+'xtick.labelsize': 10,
+'ytick.labelsize': 10,
+'text.usetex': True,
+ 'figure.figsize' : (9.90,6.45),
+'figure.subplot.left'    : 0.08,
+'figure.subplot.right'   : 0.99,
+'figure.subplot.bottom'  : 0.06,
+'figure.subplot.top'     : 0.99,
+'figure.subplot.wspace'  : 0.2,
+'figure.subplot.hspace'  : 0.12,
+'lines.markersize' : 6,
+'lines.linewidth' : 3.,
+'text.latex.unicode': True
+}
+rcParams.update(params)
+rc('font',**{'family':'sans-serif','sans-serif':['Times']})
+
+# Read the simulation data
+sim = h5py.File("box_0000.hdf5", "r")
+boxSize = sim["/Header"].attrs["BoxSize"][0]
+time = sim["/Header"].attrs["Time"][0]
+redshift = sim["/Header"].attrs["Redshift"][0]
+a = sim["/Header"].attrs["Scale-factor"][0]
+scheme = sim["/HydroScheme"].attrs["Scheme"]
+kernel = sim["/HydroScheme"].attrs["Kernel function"]
+neighbours = sim["/HydroScheme"].attrs["Kernel target N_ngb"]
+eta = sim["/HydroScheme"].attrs["Kernel eta"]
+git = sim["Code"].attrs["Git Revision"]
+H_0 = sim["/Cosmology"].attrs["H0 [internal units]"][0]
+unit_length_in_cgs = sim["/Units"].attrs["Unit length in cgs (U_L)"]
+unit_mass_in_cgs = sim["/Units"].attrs["Unit mass in cgs (U_M)"]
+unit_time_in_cgs = sim["/Units"].attrs["Unit time in cgs (U_t)"]
+sim.close()
+
+# Mean quantities over time
+z = np.zeros(120)
+a = np.zeros(120)
+S_mean = np.zeros(120)
+S_std = np.zeros(120)
+u_mean = np.zeros(120)
+u_std = np.zeros(120)
+P_mean = np.zeros(120)
+P_std = np.zeros(120)
+rho_mean = np.zeros(120)
+rho_std = np.zeros(120)
+
+vx_mean = np.zeros(120)
+vy_mean = np.zeros(120)
+vz_mean = np.zeros(120)
+vx_std = np.zeros(120)
+vy_std = np.zeros(120)
+vz_std = np.zeros(120)
+
+for i in range(120):
+    sim = h5py.File("box_%04d.hdf5"%i, "r")
+
+    z[i] = sim["/Cosmology"].attrs["Redshift"][0]
+    a[i] = sim["/Cosmology"].attrs["Scale-factor"][0]
+    
+    S = sim["/PartType0/Entropy"][:]
+    S_mean[i] = np.mean(S)
+    S_std[i] = np.std(S)
+    
+    u = sim["/PartType0/InternalEnergy"][:]
+    u_mean[i] = np.mean(u)
+    u_std[i] = np.std(u)
+
+    P = sim["/PartType0/Pressure"][:]
+    P_mean[i] = np.mean(P)
+    P_std[i] = np.std(P)
+
+    rho = sim["/PartType0/Density"][:]
+    rho_mean[i] = np.mean(rho)
+    rho_std[i] = np.std(rho)
+
+    v = sim["/PartType0/Velocities"][:,:]
+    vx_mean[i] = np.mean(v[:,0])
+    vy_mean[i] = np.mean(v[:,1])
+    vz_mean[i] = np.mean(v[:,2])
+    vx_std[i] = np.std(v[:,0])
+    vy_std[i] = np.std(v[:,1])
+    vz_std[i] = np.std(v[:,2])
+    
+# Move to physical quantities
+rho_mean_phys = rho_mean / a**3
+u_mean_phys = u_mean / a**(3*(gas_gamma - 1.))
+S_mean_phys = S_mean
+
+# Solution in physical coordinates
+#T_solution = np.ones(T) / a
+
+figure()
+
+# Density evolution --------------------------------
+subplot(231)#, yscale="log")
+semilogx(a, rho_mean, '-', color='r', lw=1)
+xlabel("${\\rm Scale-factor}$", labelpad=0.)
+ylabel("${\\rm Comoving~density}$", labelpad=0.)
+
+# Thermal energy evolution --------------------------------
+subplot(232)#, yscale="log")
+semilogx(a, u_mean, '-', color='r', lw=1)
+xlabel("${\\rm Scale-factor}$", labelpad=0.)
+ylabel("${\\rm Comoving~internal~energy}$", labelpad=0.)
+
+# Entropy evolution --------------------------------
+subplot(233)#, yscale="log")
+semilogx(a, S_mean, '-', color='r', lw=1)
+xlabel("${\\rm Scale-factor}$", labelpad=0.)
+ylabel("${\\rm Comoving~entropy}$", labelpad=0.)
+
+# Peculiar velocity evolution ---------------------
+subplot(234)
+semilogx(a, vx_mean, '-', color='r', lw=1)
+semilogx(a, vy_mean, '-', color='g', lw=1)
+semilogx(a, vz_mean, '-', color='b', lw=1)
+xlabel("${\\rm Scale-factor}$", labelpad=0.)
+ylabel("${\\rm Peculiar~velocity~mean}$", labelpad=0.)
+
+# Peculiar velocity evolution ---------------------
+subplot(235)
+semilogx(a, vx_std, '--', color='r', lw=1)
+semilogx(a, vy_std, '--', color='g', lw=1)
+semilogx(a, vz_std, '--', color='b', lw=1)
+xlabel("${\\rm Scale-factor}$", labelpad=0.)
+ylabel("${\\rm Peculiar~velocity~std-dev}$", labelpad=0.)
+
+
+# Information -------------------------------------
+subplot(236, frameon=False)
+
+plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1)
+text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10)
+text(-0.49, 0.4, scheme, fontsize=10)
+text(-0.49, 0.3, kernel, fontsize=10)
+text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10)
+xlim(-0.5, 0.5)
+ylim(0, 1)
+xticks([])
+yticks([])
+
+savefig("ConstantBox_comoving.png", dpi=200)
+
+
+
+figure()
+
+# Density evolution --------------------------------
+subplot(231)#, yscale="log")
+loglog(a, rho_mean_phys, '-', color='r', lw=1)
+xlabel("${\\rm Scale-factor}$")
+ylabel("${\\rm Physical~density}$")
+
+# Thermal energy evolution --------------------------------
+subplot(232)#, yscale="log")
+loglog(a, u_mean_phys, '-', color='r', lw=1)
+xlabel("${\\rm Scale-factor}$")
+ylabel("${\\rm Physical~internal~energy}$")
+
+# Entropy evolution --------------------------------
+subplot(233)#, yscale="log")
+semilogx(a, S_mean_phys, '-', color='r', lw=1)
+xlabel("${\\rm Scale-factor}$")
+ylabel("${\\rm Physical~entropy}$")
+
+# Information -------------------------------------
+subplot(236, frameon=False)
+
+plot([-0.49, 0.1], [0.62, 0.62], 'k-', lw=1)
+text(-0.49, 0.5, "$\\textsc{Swift}$ %s"%git, fontsize=10)
+text(-0.49, 0.4, scheme, fontsize=10)
+text(-0.49, 0.3, kernel, fontsize=10)
+text(-0.49, 0.2, "$%.2f$ neighbours ($\\eta=%.3f$)"%(neighbours, eta), fontsize=10)
+xlim(-0.5, 0.5)
+ylim(0, 1)
+xticks([])
+yticks([])
+
+savefig("ConstantBox_physical.png", dpi=200)
+
+
diff --git a/examples/ConstantCosmoVolume/run.sh b/examples/ConstantCosmoVolume/run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..521659b26d6e4d3c07a8322ba92fa3d52f0ba2cf
--- /dev/null
+++ b/examples/ConstantCosmoVolume/run.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+# Generate the initial conditions if they are not present.
+if [ ! -e constantBox.hdf5 ]
+then
+    echo "Generating initial conditions for the uniform cosmo box example..."
+    python makeIC.py
+fi
+
+# Run SWIFT
+../swift -s -c -G -t 8 constant_volume.yml 2>&1 | tee output.log
+
+# Plot the result
+python plotSolution.py $i
diff --git a/examples/MoonFormingImpact/README.md b/examples/MoonFormingImpact/README.md
deleted file mode 100644
index 97a84f67c6aeeff4176a1385381f1cfe9e340c91..0000000000000000000000000000000000000000
--- a/examples/MoonFormingImpact/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-Canonical Moon-Forming Giant Impact
-===================================
-
-NOTE: This doesn't really work because the EOS are different to Canup (2004) so
-the impactor just glances then flies away!
-
-A version of the canonical moon-forming giant impact of Theia onto the early
-Earth (Canup 2004; Barr 2016). Both bodies are here made of a (Tillotson) iron
-core and granite mantle. Only ~10,000 particles are used for a quick and crude
-simulation.
-
-Setup
------
-
-In `swiftsim/`:
-
-`$ ./configure --with-hydro=minimal-multi-mat --with-equation-of-state=planetary`
-`$ make`
-
-In `swiftsim/examples/MoonFormingImpact/`:
-
-`$ ./get_init_cond.sh`
-
-Run
----
-
-`$ ./run.sh`
-
-Output
-------
-
-`$ python plot.py`
-`$ mplayer anim.mpg`
-
diff --git a/examples/MoonFormingImpact/get_init_cond.sh b/examples/MoonFormingImpact/get_init_cond.sh
deleted file mode 100755
index 7d63943c2c5dc3bd4ab88e63a2abba62cc3f04a5..0000000000000000000000000000000000000000
--- a/examples/MoonFormingImpact/get_init_cond.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/moon_forming_impact.hdf5
diff --git a/examples/MoonFormingImpact/moon_forming_impact.yml b/examples/MoonFormingImpact/moon_forming_impact.yml
deleted file mode 100644
index 323adf7f3ac73f41b45b50eaa76a95033dca35d7..0000000000000000000000000000000000000000
--- a/examples/MoonFormingImpact/moon_forming_impact.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-# Define the system of units to use internally.
-InternalUnitSystem:
-    UnitMass_in_cgs:        5.9724e27   # Grams
-    UnitLength_in_cgs:      6.371e8     # Centimeters
-    UnitVelocity_in_cgs:    6.371e8     # Centimeters per second
-    UnitCurrent_in_cgs:     1           # Amperes
-    UnitTemp_in_cgs:        1           # Kelvin
-
-# Parameters governing the time integration
-TimeIntegration:
-    time_begin:     0                   # The starting time of the simulation (in internal units).
-    time_end:       100000              # The end time of the simulation (in internal units).
-    dt_min:         0.001               # The minimal time-step size of the simulation (in internal units).
-    dt_max:         100                 # The maximal time-step size of the simulation (in internal units).
-
-# Parameters governing the snapshots
-Snapshots:
-                                        # Common part of the name of output files
-    basename:       snapshots/moon_forming_impact
-    time_first:     0                   # Time of the first output (in internal units)
-    delta_time:     100                 # Time difference between consecutive outputs (in internal units)
-    label_delta:    100                 # Integer increment between snapshot output labels
-
-# Parameters governing the conserved quantities statistics
-Statistics:
-    delta_time:     500                 # 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).
-    delta_neighbours:   0.1             # The tolerance for the targetted number of neighbours.
-    CFL_condition:      0.2             # Courant-Friedrich-Levy condition for time integration.
-
-# Parameters for the self-gravity scheme
-Gravity:
-    eta:                    0.025       # Constant dimensionless multiplier for time integration.
-    theta:                  0.7         # Opening angle (Multipole acceptance criterion)
-    comoving_softening:     0.005       # Comoving softening length (in internal units).
-    max_physical_softening: 0.005       # Physical softening length (in internal units).
-
-# Parameters related to the initial conditions
-InitialConditions:
-                                        # The initial conditions file to read
-    file_name:  moon_forming_impact.hdf5
-
-# Parameters related to the equation of state
-EoS:
-    planetary_use_Til:    1                       # Whether to prepare the Tillotson EOS
diff --git a/examples/MoonFormingImpact/plot.py b/examples/MoonFormingImpact/plot.py
deleted file mode 100644
index aa0d64a5d0d06709d51b1db231c507e22861f36c..0000000000000000000000000000000000000000
--- a/examples/MoonFormingImpact/plot.py
+++ /dev/null
@@ -1,285 +0,0 @@
-"""
-###############################################################################
-# This file is part of SWIFT.
-# Copyright (c) 2018 Jacob Kegerreis (jacob.kegerreis@durham.ac.uk)
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-###############################################################################
-
-Plotting script for the Canonical Moon-Forming Giant Impact example.
-
-Save a figure for each snapshot in `./plots/` then make them into a simple
-animation with ffmpeg in `./`.
-
-Usage:
-    `$ python  plot.py  time_end  delta_time`
-
-    Sys args:
-        + `time_end` | (opt) int | The time of the last snapshot to plot.
-            Default = 100000
-        + `delta_time` | (opt) int | The time between successive snapshots.
-            Default = 100
-"""
-
-from __future__ import division
-import numpy as np
-import matplotlib
-import matplotlib.pyplot as plt
-import h5py
-import sys
-import subprocess
-
-# Particle array fields
-dtype_picle = [
-    ('m', float), ('x', float), ('y', float), ('z', float), ('v_x', float),
-    ('v_y', float), ('v_z', float), ('ID', int), ('rho', float), ('u', float),
-    ('phi', float), ('P', float), ('h', float), ('mat_ID', int), ('r', float)
-    ]
-
-s_to_hour   = 1 / 60**2
-
-# Snapshot info
-file_snap   = "./snapshots/moon_forming_impact_"
-file_plot   = "./plots/moon_forming_impact_"
-# Number of particles in the target body
-num_target  = 9496
-
-# Material types (copied from src/equation_of_state/planetary/equation_of_state.h)
-type_factor = 100
-Di_type = {
-    'Til'       : 1,
-    'HM80'      : 2,
-    'ANEOS'     : 3,
-    'SESAME'    : 4,
-}
-Di_material = {
-    # Tillotson
-    'Til_iron'      : Di_type['Til']*type_factor,
-    'Til_granite'   : Di_type['Til']*type_factor + 1,
-    'Til_water'     : Di_type['Til']*type_factor + 2,
-    # Hubbard & MacFarlane (1980) Uranus/Neptune
-    'HM80_HHe'      : Di_type['HM80']*type_factor,      # Hydrogen-helium atmosphere
-    'HM80_ice'      : Di_type['HM80']*type_factor + 1,  # H20-CH4-NH3 ice mix
-    'HM80_rock'     : Di_type['HM80']*type_factor + 2,  # SiO2-MgO-FeS-FeO rock mix
-    # ANEOS
-    'ANEOS_iron'        : Di_type['ANEOS']*type_factor,
-    'MANEOS_forsterite' : Di_type['ANEOS']*type_factor + 1,
-    # SESAME
-    'SESAME_iron'   : Di_type['SESAME']*type_factor,
-}
-
-# Material offset for impactor particles
-ID_imp  = 10000
-# Material colours
-Di_mat_colour = {
-    # Target
-    Di_material['Til_iron']             : 'orange',
-    Di_material['Til_granite']          : '#FFF0E0',
-    # Impactor
-    Di_material['Til_iron'] + ID_imp    : 'dodgerblue',
-    Di_material['Til_granite'] + ID_imp : '#A080D0',
-    }
-
-
-def load_snapshot(filename):
-    """ Load the hdf5 snapshot file and return the structured particle array.
-    """
-    # Add extension if needed
-    if (filename[-5:] != ".hdf5"):
-        filename += ".hdf5"
-
-    # Load the hdf5 file
-    with h5py.File(filename, 'r') as f:
-        header      = f['Header'].attrs
-        A2_pos      = f['PartType0/Coordinates'].value
-        A2_vel      = f['PartType0/Velocities'].value
-
-        # Structured array of all particle data
-        A2_picle    = np.empty(header['NumPart_Total'][0],
-                               dtype=dtype_picle)
-
-        A2_picle['x']       = A2_pos[:, 0]
-        A2_picle['y']       = A2_pos[:, 1]
-        A2_picle['z']       = A2_pos[:, 2]
-        A2_picle['v_x']     = A2_vel[:, 0]
-        A2_picle['v_y']     = A2_vel[:, 1]
-        A2_picle['v_z']     = A2_vel[:, 2]
-        A2_picle['m']       = f['PartType0/Masses'].value
-        A2_picle['ID']      = f['PartType0/ParticleIDs'].value
-        A2_picle['rho']     = f['PartType0/Density'].value
-        A2_picle['u']       = f['PartType0/InternalEnergy'].value
-        A2_picle['phi']     = f['PartType0/Potential'].value
-        A2_picle['P']       = f['PartType0/Pressure'].value
-        A2_picle['h']       = f['PartType0/SmoothingLength'].value
-        A2_picle['mat_ID']  = f['PartType0/MaterialID'].value
-
-    return A2_picle
-
-
-def process_particles(A2_picle, num_target):
-    """ Modify things like particle units, material IDs, and coordinate origins.
-    """
-    # Offset material IDs for impactor particles
-    A2_picle['mat_ID'][A2_picle['ID'] >= num_target] += ID_imp
-
-    # Shift coordinates to the centre of the target's core's mass and momentum
-    sel_tar  = np.where(A2_picle['mat_ID'] == Di_material['Til_iron'])[0]
-
-    # Centre of mass
-    m_tot   = np.sum(A2_picle[sel_tar]['m'])
-    x_com   = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['x']) / m_tot
-    y_com   = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['y']) / m_tot
-    z_com   = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['z']) / m_tot
-
-    # Change origin to the centre-of-mass
-    A2_picle['x']   -= x_com
-    A2_picle['y']   -= y_com
-    A2_picle['z']   -= z_com
-    A2_picle['r']   = np.sqrt(
-        A2_picle['x']**2 + A2_picle['y']**2 + A2_picle['z']**2
-        )
-
-    # Centre of momentum
-    v_x_com = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['v_x']) / m_tot
-    v_y_com = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['v_y']) / m_tot
-    v_z_com = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['v_z']) / m_tot
-
-    # Change to the centre-of-momentum frame of reference
-    A2_picle['v_x'] -= v_x_com
-    A2_picle['v_y'] -= v_y_com
-    A2_picle['v_z'] -= v_z_com
-
-    return A2_picle
-
-
-def plot_snapshot(A2_picle, filename, time, ax_lim=100, dz=0.1):
-    """ Plot the snapshot particles and save the figure.
-    """
-    # Add extension if needed
-    if (filename[-5:] != ".png"):
-        filename += ".png"
-
-    fig = plt.figure(figsize=(9, 9))
-    ax  = fig.add_subplot(111, aspect='equal')
-
-    # Plot slices in z below zero
-    for z in np.arange(-ax_lim, 0, dz):
-        sel_z       = np.where((z < A2_picle['z']) & (A2_picle['z'] < z+dz))[0]
-        A2_picle_z  = A2_picle[sel_z]
-
-        # Plot each material
-        for mat_ID, colour in Di_mat_colour.iteritems():
-            sel_col = np.where(A2_picle_z['mat_ID'] == mat_ID)[0]
-
-            ax.scatter(
-                A2_picle_z[sel_col]['x'], A2_picle_z[sel_col]['y'],
-                c=colour, edgecolors='none', marker='.', s=50, alpha=0.7
-                )
-
-    # Axes etc.
-    ax.set_axis_bgcolor('k')
-
-    ax.set_xlabel("x Position ($R_\oplus$)")
-    ax.set_ylabel("y Position ($R_\oplus$)")
-
-    ax.set_xlim(-ax_lim, ax_lim)
-    ax.set_ylim(-ax_lim, ax_lim)
-
-    plt.text(
-        -0.92*ax_lim, 0.85*ax_lim, "%.1f h" % (time*s_to_hour), fontsize=20,
-        color='w'
-        )
-
-    # Font sizes
-    for item in (
-        [ax.title, ax.xaxis.label, ax.yaxis.label] + ax.get_xticklabels() +
-        ax.get_yticklabels()
-        ):
-        item.set_fontsize(20)
-
-    plt.tight_layout()
-
-    plt.savefig(filename)
-    plt.close()
-
-
-if __name__ == '__main__':
-    # Sys args
-    try:
-        time_end    = int(sys.argv[1])
-
-        try:
-            delta_time  = int(sys.argv[2])
-        except IndexError:
-            delta_time  = 100
-    except IndexError:
-        time_end    = 100000
-        delta_time  = 100
-
-    # Load and plot each snapshot
-    for i_snap in range(int(time_end/delta_time) + 1):
-        snap_time   = i_snap * delta_time
-        print "\rPlotting snapshot %06d (%d of %d)" % (
-            snap_time, i_snap+1, int(time_end/delta_time)
-            ),
-        sys.stdout.flush()
-
-        # Load particle data
-        filename    = "%s%06d" % (file_snap, snap_time)
-        A2_picle    = load_snapshot(filename)
-
-        # Process particle data
-        A2_picle    = process_particles(A2_picle, num_target)
-
-        # Plot particles
-        filename    = "%s%06d" % (file_plot, snap_time)
-        plot_snapshot(A2_picle, filename, snap_time)
-
-    # Animation
-    command = (
-        "ffmpeg -framerate 12 -i plots/moon_forming_impact_%*.png -r 25 "
-        "anim.mpg -y"
-        )
-    print "\n%s\n" % command
-    subprocess.check_output(command, shell=True)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/MoonFormingImpact/run.sh b/examples/MoonFormingImpact/run.sh
deleted file mode 100755
index 165dae3a24a9c30960959fbb37aa6e1da2eb851f..0000000000000000000000000000000000000000
--- a/examples/MoonFormingImpact/run.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-../swift -G -s -t 8 moon_forming_impact.yml
diff --git a/examples/SineWavePotential_1D/makeIC.py b/examples/SineWavePotential_1D/makeIC.py
index 321af0714219dfa0c7cbb3d80845881dcbb8416d..afbf1bc0fa47a27677cb9c5645d439432bd9fd9a 100644
--- a/examples/SineWavePotential_1D/makeIC.py
+++ b/examples/SineWavePotential_1D/makeIC.py
@@ -31,12 +31,12 @@ cs2 = 2.*uconst/3.
 A = 10.
 
 fileName = "sineWavePotential.hdf5"
-numPart = 100
+numPart = 1000
 boxSize = 1.
 
 coords = np.zeros((numPart, 3))
 v = np.zeros((numPart, 3))
-m = np.zeros(numPart) + 1.
+m = np.zeros(numPart) + 1000. / numPart
 h = np.zeros(numPart) + 2./numPart
 u = np.zeros(numPart) + uconst
 ids = np.arange(numPart, dtype = 'L')
diff --git a/examples/SineWavePotential_1D/plotSolution.py b/examples/SineWavePotential_1D/plotSolution.py
index 65e981e4648fe0fe5d1da6cf3e753fb8a34f0fb4..3bb889aaabd3cdac0274afb09647d0e3aebb02cc 100644
--- a/examples/SineWavePotential_1D/plotSolution.py
+++ b/examples/SineWavePotential_1D/plotSolution.py
@@ -23,8 +23,13 @@
 import numpy as np
 import h5py
 import sys
+import matplotlib
+matplotlib.use("Agg")
 import pylab as pl
 
+pl.rcParams["figure.figsize"] = (12, 10)
+pl.rcParams["text.usetex"] = True
+
 # these should be the same as in makeIC.py
 uconst = 20.2615290634
 cs2 = 2.*uconst/3.
@@ -39,15 +44,20 @@ fileName = sys.argv[1]
 file = h5py.File(fileName, 'r')
 coords = np.array(file["/PartType0/Coordinates"])
 rho = np.array(file["/PartType0/Density"])
+P = np.array(file["/PartType0/Pressure"])
 u = np.array(file["/PartType0/InternalEnergy"])
-agrav = np.array(file["/PartType0/GravAcceleration"])
 m = np.array(file["/PartType0/Masses"])
+vs = np.array(file["/PartType0/Velocities"])
 ids = np.array(file["/PartType0/ParticleIDs"])
 
 x = np.linspace(0., 1., 1000)
 rho_x = 1000.*np.exp(-0.5*A/np.pi/cs2*np.cos(2.*np.pi*x))
 
-P = cs2*rho
+a = A * np.sin(2. * np.pi * x)
+
+apart = A * np.sin(2. * np.pi * coords[:,0])
+tkin = -0.5 * np.dot(apart, coords[:,0])
+print tkin, 0.5 * np.dot(m, vs[:,0]**2)
 
 ids_reverse = np.argsort(ids)
 
@@ -65,13 +75,38 @@ for i in range(len(P)):
     corr = 1.
   idxp1 = ids_reverse[ip1]
   idxm1 = ids_reverse[im1]
-  gradP[i] = (P[idxp1]-P[idxm1])/(coords[idxp1,0]-coords[idxm1,0])
+  gradP[i] = (P[idxp1] - P[idxm1])/(coords[idxp1,0] - coords[idxm1,0])
+
+fig, ax = pl.subplots(2, 2, sharex = True)
+
+ax[0][0].plot(coords[:,0], rho, ".", label = "gizmo-mfm")
+ax[0][0].plot(x, rho_x, "-", label = "stable solution")
+ax[0][0].set_ylabel("$\\rho{}$ (code units)")
+ax[0][0].legend(loc = "best")
+
+ax[0][1].plot(x, a, "-", label = "$\\nabla{}\\Phi{}$ external")
+ax[0][1].plot(coords[:,0], gradP/rho, ".",
+              label = "$\\nabla{}P/\\rho{}$ gizmo-mfm")
+ax[0][1].set_ylabel("force (code units)")
+ax[0][1].legend(loc = "best")
+
+ax[1][0].axhline(y = uconst, label = "isothermal $u$", color = "k",
+                 linestyle = "--")
+ax[1][0].plot(coords[:,0], u, ".", label = "gizmo-mfm")
+ax[1][0].set_ylabel("$u$ (code units)")
+ax[1][0].set_xlabel("$x$ (code units)")
+ax[1][0].legend(loc = "best")
+
+#ax[1][1].plot(coords[:,0], m, "y.")
+#ax[1][1].set_ylabel("$m_i$ (code units)")
+#ax[1][1].set_xlabel("$x$ (code units)")
 
-fig, ax = pl.subplots(2, 2)
+ax[1][1].axhline(y = 0., label = "target", color = "k",
+                 linestyle = "--")
+ax[1][1].plot(coords[:,0], vs[:,0], ".", label = "gizmo-mfm")
+ax[1][1].set_ylabel("$v_x$ (code units)")
+ax[1][1].set_xlabel("$x$ (code units)")
+ax[1][1].legend(loc = "best")
 
-ax[0][0].plot(coords[:,0], rho, "r.", markersize = 0.5)
-ax[0][0].plot(x, rho_x, "g-")
-ax[0][1].plot(coords[:,0], gradP/rho, "b.")
-ax[1][0].plot(coords[:,0], agrav[:,0], "g.", markersize = 0.5)
-ax[1][1].plot(coords[:,0], m, "y.")
+pl.tight_layout()
 pl.savefig("{fileName}.png".format(fileName = fileName[:-5]))
diff --git a/examples/SineWavePotential_1D/sineWavePotential.yml b/examples/SineWavePotential_1D/sineWavePotential.yml
index 9662841032a12d48870f12de8c1bcfcd579a6b42..e6285785099f10902ea60b21334a0ad26c0593de 100644
--- a/examples/SineWavePotential_1D/sineWavePotential.yml
+++ b/examples/SineWavePotential_1D/sineWavePotential.yml
@@ -10,7 +10,7 @@ InternalUnitSystem:
 TimeIntegration:
   time_begin: 0.    # The starting time of the simulation (in internal units).
   time_end:   10.   # The end time of the simulation (in internal units).
-  dt_min:     1e-6  # The minimal time-step size of the simulation (in internal units).
+  dt_min:     1e-8  # The minimal time-step size of the simulation (in internal units).
   dt_max:     1e-2  # The maximal time-step size of the simulation (in internal units).
 
 # Parameters governing the conserved quantities statistics
@@ -36,3 +36,6 @@ InitialConditions:
 SineWavePotential:
   amplitude: 10.
   timestep_limit: 1.
+
+EoS:
+  isothermal_internal_energy: 20.2615290634
diff --git a/examples/UranusImpact/README.md b/examples/UranusImpact/README.md
deleted file mode 100644
index 178a3937ecbe527df8e8e82a0d8fd8bcbf9dbef7..0000000000000000000000000000000000000000
--- a/examples/UranusImpact/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-Uranus Giant Impact
-===================
-
-A simple version of the low angular momentum impact onto the early Uranus shown
-in Kegerreis et al. (2018), Fig. 2; with only ~10,000 particles for a quick and
-crude simulation.
-
-The collision of a 2 Earth mass impactor onto a proto-Uranus that can explain
-the spin of the present-day planet, with an angular momentum of 2e36 kg m^2 s^-1
-and velocity at infinity of 5 km s^-1 for a relatively head-on impact.
-
-Both bodies have a rocky core and icy mantle, with a hydrogen-helium atmosphere
-on the target as well. Although with this low number of particles it cannot be
-modelled in any detail.
-
-Setup
------
-
-In `swiftsim/`:
-
-`$ ./configure --with-hydro=minimal-multi-mat --with-equation-of-state=planetary`
-
-`$ make`
-
-In `swiftsim/examples/UranusImpact/`:
-
-`$ ./get_init_cond.sh`
-
-Run
----
-
-`$ ./run.sh`
-
-Analysis
---------
-
-`$ python plot.py`
-
-`$ mplayer anim.mpg`
-
diff --git a/examples/UranusImpact/get_init_cond.sh b/examples/UranusImpact/get_init_cond.sh
deleted file mode 100755
index e12e009adfbd727cb2452ac21c477b3ecd77b9c9..0000000000000000000000000000000000000000
--- a/examples/UranusImpact/get_init_cond.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/ICs/uranus_impact.hdf5
diff --git a/examples/UranusImpact/plot.py b/examples/UranusImpact/plot.py
deleted file mode 100644
index 3db3bf21bb15862ec524a069c38e47564b48df1d..0000000000000000000000000000000000000000
--- a/examples/UranusImpact/plot.py
+++ /dev/null
@@ -1,291 +0,0 @@
-"""
-###############################################################################
-# This file is part of SWIFT.
-# Copyright (c) 2018 Jacob Kegerreis (jacob.kegerreis@durham.ac.uk)
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-###############################################################################
-
-Plotting script for the Uranus Giant Impact example.
-
-Save a figure for each snapshot in `./plots/` then make them into a simple
-animation with ffmpeg in `./`.
-
-The snapshot plots show all particles with z < 0, coloured by their material.
-
-Usage:
-    `$ python  plot.py  time_end  delta_time`
-
-    Sys args:
-        + `time_end` | (opt) int | The time of the last snapshot to plot.
-            Default = 100000
-        + `delta_time` | (opt) int | The time between successive snapshots.
-            Default = 500
-"""
-
-from __future__ import division
-import numpy as np
-import matplotlib
-import matplotlib.pyplot as plt
-import h5py
-import sys
-import subprocess
-
-# Particle array fields
-dtype_picle = [
-    ('m', float), ('x', float), ('y', float), ('z', float), ('v_x', float),
-    ('v_y', float), ('v_z', float), ('ID', int), ('rho', float), ('u', float),
-    ('phi', float), ('P', float), ('h', float), ('mat_ID', int), ('r', float)
-    ]
-
-s_to_hour   = 1 / 60**2
-R_Ea        = 6.371e6
-
-# Default sys args
-time_end_default    = 100000
-delta_time_default  = 500
-
-# Snapshot info
-file_snap   = "./snapshots/uranus_impact_"
-file_plot   = "./plots/uranus_impact_"
-
-# Number of particles in the target body
-num_target  = 8992
-
-# Material types (copied from src/equation_of_state/planetary/equation_of_state.h)
-type_factor = 100
-Di_type = {
-    'Til'       : 1,
-    'HM80'      : 2,
-    'ANEOS'     : 3,
-    'SESAME'    : 4,
-}
-Di_material = {
-    # Tillotson
-    'Til_iron'      : Di_type['Til']*type_factor,
-    'Til_granite'   : Di_type['Til']*type_factor + 1,
-    'Til_water'     : Di_type['Til']*type_factor + 2,
-    # Hubbard & MacFarlane (1980) Uranus/Neptune
-    'HM80_HHe'      : Di_type['HM80']*type_factor,      # Hydrogen-helium atmosphere
-    'HM80_ice'      : Di_type['HM80']*type_factor + 1,  # H20-CH4-NH3 ice mix
-    'HM80_rock'     : Di_type['HM80']*type_factor + 2,  # SiO2-MgO-FeS-FeO rock mix
-    # ANEOS
-    'ANEOS_iron'        : Di_type['ANEOS']*type_factor,
-    'MANEOS_forsterite' : Di_type['ANEOS']*type_factor + 1,
-    # SESAME
-    'SESAME_iron'   : Di_type['SESAME']*type_factor,
-}
-
-# Material offset for impactor particles
-ID_imp  = 10000
-# Material colours
-Di_mat_colour = {
-    # Target
-    Di_material['HM80_HHe']     : '#33DDFF',
-    Di_material['HM80_ice']     : 'lightsteelblue',
-    Di_material['HM80_rock']    : 'slategrey',
-    # Impactor
-    Di_material['HM80_ice'] + ID_imp    : '#A080D0',
-    Di_material['HM80_rock'] + ID_imp   : '#706050',
-    }
-
-
-def load_snapshot(filename):
-    """ Load the hdf5 snapshot file and return the structured particle array.
-    """
-    # Add extension if needed
-    if (filename[-5:] != ".hdf5"):
-        filename += ".hdf5"
-
-    # Load the hdf5 file
-    with h5py.File(filename, 'r') as f:
-        header      = f['Header'].attrs
-        A2_pos      = f['PartType0/Coordinates'].value
-        A2_vel      = f['PartType0/Velocities'].value
-
-        # Structured array of all particle data
-        A2_picle    = np.empty(header['NumPart_Total'][0],
-                               dtype=dtype_picle)
-
-        A2_picle['x']       = A2_pos[:, 0]
-        A2_picle['y']       = A2_pos[:, 1]
-        A2_picle['z']       = A2_pos[:, 2]
-        A2_picle['v_x']     = A2_vel[:, 0]
-        A2_picle['v_y']     = A2_vel[:, 1]
-        A2_picle['v_z']     = A2_vel[:, 2]
-        A2_picle['m']       = f['PartType0/Masses'].value
-        A2_picle['ID']      = f['PartType0/ParticleIDs'].value
-        A2_picle['rho']     = f['PartType0/Density'].value
-        A2_picle['u']       = f['PartType0/InternalEnergy'].value
-        A2_picle['phi']     = f['PartType0/Potential'].value
-        A2_picle['P']       = f['PartType0/Pressure'].value
-        A2_picle['h']       = f['PartType0/SmoothingLength'].value
-        A2_picle['mat_ID']  = f['PartType0/MaterialID'].value
-
-    return A2_picle
-
-
-def process_particles(A2_picle, num_target):
-    """ Modify things like particle units, material IDs, and coordinate origins.
-    """
-    # Offset material IDs for impactor particles
-    A2_picle['mat_ID'][A2_picle['ID'] >= num_target] += ID_imp
-
-    # Shift coordinates to the centre of the target's core's mass and momentum
-    sel_tar  = np.where(A2_picle['mat_ID'] == Di_material['HM80_rock'])[0]
-
-    # Centre of mass
-    m_tot   = np.sum(A2_picle[sel_tar]['m'])
-    x_com   = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['x']) / m_tot
-    y_com   = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['y']) / m_tot
-    z_com   = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['z']) / m_tot
-
-    # Change origin to the centre-of-mass
-    A2_picle['x']   -= x_com
-    A2_picle['y']   -= y_com
-    A2_picle['z']   -= z_com
-    A2_picle['r']   = np.sqrt(
-        A2_picle['x']**2 + A2_picle['y']**2 + A2_picle['z']**2
-        )
-
-    # Centre of momentum
-    v_x_com = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['v_x']) / m_tot
-    v_y_com = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['v_y']) / m_tot
-    v_z_com = np.sum(A2_picle[sel_tar]['m'] * A2_picle[sel_tar]['v_z']) / m_tot
-
-    # Change to the centre-of-momentum frame of reference
-    A2_picle['v_x'] -= v_x_com
-    A2_picle['v_y'] -= v_y_com
-    A2_picle['v_z'] -= v_z_com
-
-    return A2_picle
-
-
-def plot_snapshot(A2_picle, filename, time, ax_lim=13, dz=0.1):
-    """ Plot the snapshot particles and save the figure.
-    """
-    # Add extension if needed
-    if (filename[-5:] != ".png"):
-        filename += ".png"
-
-    fig = plt.figure(figsize=(9, 9))
-    ax  = fig.add_subplot(111, aspect='equal')
-
-    # Plot slices in z below zero
-    for z in np.arange(-ax_lim, 0, dz):
-        sel_z       = np.where((z < A2_picle['z']) & (A2_picle['z'] < z+dz))[0]
-        A2_picle_z  = A2_picle[sel_z]
-
-        # Plot each material
-        for mat_ID, colour in Di_mat_colour.iteritems():
-            sel_col = np.where(A2_picle_z['mat_ID'] == mat_ID)[0]
-
-            ax.scatter(
-                A2_picle_z[sel_col]['x'], A2_picle_z[sel_col]['y'],
-                c=colour, edgecolors='none', marker='.', s=50, alpha=0.7
-                )
-
-    # Axes etc.
-    ax.set_axis_bgcolor('k')
-
-    ax.set_xlabel("x Position ($R_\oplus$)")
-    ax.set_ylabel("y Position ($R_\oplus$)")
-
-    ax.set_xlim(-ax_lim, ax_lim)
-    ax.set_ylim(-ax_lim, ax_lim)
-
-    plt.text(
-        -0.92*ax_lim, 0.85*ax_lim, "%.1f h" % (time*s_to_hour), fontsize=20,
-        color='w'
-        )
-
-    # Font sizes
-    for item in (
-        [ax.title, ax.xaxis.label, ax.yaxis.label] + ax.get_xticklabels() +
-        ax.get_yticklabels()
-        ):
-        item.set_fontsize(20)
-
-    plt.tight_layout()
-
-    plt.savefig(filename)
-    plt.close()
-
-
-if __name__ == '__main__':
-    # Sys args
-    try:
-        time_end    = int(sys.argv[1])
-        try:
-            delta_time  = int(sys.argv[2])
-        except IndexError:
-            delta_time  = delta_time_default
-    except IndexError:
-        time_end    = time_end_default
-        delta_time  = delta_time_default
-
-    # Load and plot each snapshot
-    for i_snap in range(int(time_end/delta_time) + 1):
-        snap_time   = i_snap * delta_time
-        print "\rPlotting snapshot %06d (%d of %d)" % (
-            snap_time, i_snap+1, int(time_end/delta_time)
-            ),
-        sys.stdout.flush()
-
-        # Load particle data
-        filename    = "%s%06d" % (file_snap, snap_time)
-        A2_picle    = load_snapshot(filename)
-
-        # Process particle data
-        A2_picle    = process_particles(A2_picle, num_target)
-
-        # Plot particles
-        filename    = "%s%06d" % (file_plot, snap_time)
-        plot_snapshot(A2_picle, filename, snap_time)
-
-    # Animation
-    command = (
-        "ffmpeg -framerate 10 -i plots/uranus_impact_%*.png -r 25 anim.mpg -y"
-        )
-    print "\n$ %s\n" % command
-    subprocess.call(command, shell=True)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/UranusImpact/run.sh b/examples/UranusImpact/run.sh
deleted file mode 100755
index c6773b7e40fff3fa312dfcb5ba4ada9d9e4b1b8d..0000000000000000000000000000000000000000
--- a/examples/UranusImpact/run.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-../swift -G -s -t 8 uranus_impact.yml
diff --git a/examples/UranusImpact/uranus_impact.yml b/examples/UranusImpact/uranus_impact.yml
deleted file mode 100644
index fabddca00f80fcdd79ff6114ff0544cd251046f4..0000000000000000000000000000000000000000
--- a/examples/UranusImpact/uranus_impact.yml
+++ /dev/null
@@ -1,51 +0,0 @@
-# Define the system of units to use internally.
-InternalUnitSystem:
-    UnitMass_in_cgs:        5.9724e27   # Grams
-    UnitLength_in_cgs:      6.371e8     # Centimeters
-    UnitVelocity_in_cgs:    6.371e8     # Centimeters per second
-    UnitCurrent_in_cgs:     1           # Amperes
-    UnitTemp_in_cgs:        1           # Kelvin
-
-# Parameters governing the time integration
-TimeIntegration:
-    time_begin:     0                   # The starting time of the simulation (in internal units).
-    time_end:       100000              # The end time of the simulation (in internal units).
-    dt_min:         0.001               # The minimal time-step size of the simulation (in internal units).
-    dt_max:         100                 # The maximal time-step size of the simulation (in internal units).
-
-# Parameters governing the snapshots
-Snapshots:
-                                        # Common part of the name of output files
-    basename:       snapshots/uranus_impact
-    time_first:     0                   # Time of the first output (in internal units)
-    delta_time:     500                 # Time difference between consecutive outputs (in internal units)
-    label_delta:    500                 # Integer increment between snapshot output labels
-
-# Parameters governing the conserved quantities statistics
-Statistics:
-    delta_time:     1000                # 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).
-    delta_neighbours:   0.1             # The tolerance for the targetted number of neighbours.
-    CFL_condition:      0.2             # Courant-Friedrich-Levy condition for time integration.
-
-# Parameters for the self-gravity scheme
-Gravity:
-    eta:                    0.025       # Constant dimensionless multiplier for time integration.
-    theta:                  0.7         # Opening angle (Multipole acceptance criterion)
-    comoving_softening:     0.01        # Comoving softening length (in internal units).
-    max_physical_softening: 0.01        # Physical softening length (in internal units).
-
-# Parameters related to the initial conditions
-InitialConditions:
-    file_name:      uranus_impact.hdf5  # The initial conditions file to read
-
-# Parameters related to the equation of state
-EoS:
-    planetary_use_HM80:   1                       # Whether to prepare the Hubbard & MacFarlane (1980) EOS
-                                        # Table file paths
-    planetary_HM80_HHe_table_file:    /gpfs/data/dc-kege1/gihr_data/P_rho_u_HHe.txt
-    planetary_HM80_ice_table_file:    /gpfs/data/dc-kege1/gihr_data/P_rho_u_ice.txt
-    planetary_HM80_rock_table_file:   /gpfs/data/dc-kege1/gihr_data/P_rho_u_roc.txt
diff --git a/examples/ZeldovichPancake_3D/makeIC.py b/examples/ZeldovichPancake_3D/makeIC.py
index 15fb8bdef95f6e830e78f4d1b2c419051a6f00af..79ed7e71e924941102049b8457fe070ebd08f5c2 100644
--- a/examples/ZeldovichPancake_3D/makeIC.py
+++ b/examples/ZeldovichPancake_3D/makeIC.py
@@ -28,29 +28,34 @@ z_c = 1.             # Redshift of caustic formation (non-linear collapse)
 z_i = 100.           # Initial redshift
 gamma = 5./3.        # Gas adiabatic index
 numPart_1D = 32      # Number of particles along each dimension
+fileName = "zeldovichPancake.hdf5"
 
 
 # Some units
-Mpc_in_m = 3.085678e22
-Msol_in_kg = 1.989e30
-Gyr_in_s = 3.085678e19
+Mpc_in_m = 3.08567758e22
+Msol_in_kg = 1.98848e30
+Gyr_in_s = 3.08567758e19
 mH_in_kg = 1.6737236e-27
-k_in_J_K = 1.38064852e-23
 
-# Parameters
-rho_0 = 1.8788e-26 # h^2 kg m^-3
-H_0 = 1. / Mpc_in_m * 10**5 # s^-1
+# Some constants
+kB_in_SI = 1.38064852e-23
+G_in_SI = 6.67408e-11
+
+# Some useful variables in h-full units
+H_0 = 1. / Mpc_in_m * 10**5 # h s^-1
+rho_0 = 3. * H_0**2 / (8* math.pi * G_in_SI) # h^2 kg m^-3
 lambda_i = 64. / H_0 * 10**5 # h^-1 m (= 64 h^-1 Mpc)
 x_min = -0.5 * lambda_i
 x_max = 0.5 * lambda_i
-fileName = "zeldovichPancake.hdf5"
 
+# SI system of units
 unit_l_in_si = Mpc_in_m
 unit_m_in_si = Msol_in_kg * 1.e10
 unit_t_in_si = Gyr_in_s
 unit_v_in_si = unit_l_in_si / unit_t_in_si
 unit_u_in_si = unit_v_in_si**2
 
+# Total number of particles
 numPart = numPart_1D**3
 
 #---------------------------------------------------
@@ -87,7 +92,7 @@ for i in range(numPart_1D):
       coords[index,1] = (j + 0.5) * delta_x
       coords[index,2] = (k + 0.5) * delta_x
       T = T_i * (1. / (1. - zfac * cos(k_i * q)))**(2. / 3.)
-      u[index] = k_in_J_K * T / (gamma - 1.) / mH_in_kg
+      u[index] = kB_in_SI * T / (gamma - 1.) / mH_in_kg
       h[index] = 1.2348 * delta_x
       m[index] = m_i
       v[index,0] = -H_0 * (1. + z_c) / sqrt(1. + z_i) * sin(k_i * q) / k_i
@@ -141,7 +146,7 @@ grp.create_dataset('ParticleIDs', data=ids, dtype='L')
 
 file.close()
 
-import pylab as pl
+#import pylab as pl
 
-pl.plot(coords[:,0], v[:,0], "k.")
-pl.show()
+#pl.plot(coords[:,0], v[:,0], "k.")
+#pl.show()
diff --git a/examples/ZeldovichPancake_3D/plotSolution.py b/examples/ZeldovichPancake_3D/plotSolution.py
index 163e61eb9d3738c39912c8c42c0b6c6bb9990cac..2a175e346e041a142c6921052ccf13978afa8a38 100644
--- a/examples/ZeldovichPancake_3D/plotSolution.py
+++ b/examples/ZeldovichPancake_3D/plotSolution.py
@@ -138,8 +138,8 @@ if np.size(x_g) > 1:
     plot(x_g, v_g, 's', color='g', alpha=0.8, lw=1.2, ms=4)
 plot(x, v, '.', color='r', ms=4.0)
 plot(x_s, v_s, '--', color='k', alpha=0.8, lw=1.2)
-xlabel("${\\rm{Comoving Position}}~x$", labelpad=0)
-ylabel("${\\rm{Peculiar Velocity}}~v_x$", labelpad=0)
+xlabel("${\\rm{Comoving~position}}~x$", labelpad=0)
+ylabel("${\\rm{Peculiar~velocity}}~v_x$", labelpad=0)
 
 
 # Density profile --------------------------------
@@ -148,7 +148,7 @@ if np.size(x_g) > 1:
     plot(x_g, rho_g/rho_0, 's', color='g', alpha=0.8, lw=1.2, ms=4)
 plot(x, rho/rho_0, '.', color='r', ms=4.0)
 plot(x_s, rho_s/rho_0, '--', color='k', alpha=0.8, lw=1.2)
-xlabel("${\\rm{Comoving Position}}~x$", labelpad=0)
+xlabel("${\\rm{Comoving~position}}~x$", labelpad=0)
 ylabel("${\\rm{Density}}~\\rho / \\rho_0$", labelpad=0)
 
 # Potential profile --------------------------------
@@ -156,7 +156,7 @@ subplot(233)
 if np.size(x_g) > 1:
     plot(x_g, phi_g, 's', color='g', alpha=0.8, lw=1.2, ms=4)
 plot(x, phi, '.', color='r', ms=4.0)
-xlabel("${\\rm{Comoving Position}}~x$", labelpad=0)
+xlabel("${\\rm{Comoving~position}}~x$", labelpad=0)
 ylabel("${\\rm{Potential}}~\\phi$", labelpad=0)
 
 # Temperature profile -------------------------
@@ -172,7 +172,7 @@ if np.size(x_g) > 1:
     plot(x_g, T_g, 's', color='g', alpha=0.8, lw=1.2, ms=4)
 plot(x, T, '.', color='r', ms=4.0)
 plot(x_s, T_s, '--', color='k', alpha=0.8, lw=1.2)
-xlabel("${\\rm{Comoving Position}}~x$", labelpad=0)
+xlabel("${\\rm{Comoving~position}}~x$", labelpad=0)
 ylabel("${\\rm{Temperature}}~T$", labelpad=0)
 
 # Information -------------------------------------
diff --git a/examples/ZeldovichPancake_3D/run.sh b/examples/ZeldovichPancake_3D/run.sh
index 9b6b8166ac0d084898b96e2de6b0fc1ef378aecd..b3f802f978377a9615f7cdd1cdd14e85ae3baad2 100755
--- a/examples/ZeldovichPancake_3D/run.sh
+++ b/examples/ZeldovichPancake_3D/run.sh
@@ -8,7 +8,7 @@ then
 fi
 
 # Run SWIFT
-../swift -a -s -c -G -t 8 zeldovichPancake.yml 2>&1 | tee output.log
+../swift -s -c -G -t 8 zeldovichPancake.yml 2>&1 | tee output.log
 
 # Plot the result
 for i in {0..119}
diff --git a/examples/ZeldovichPancake_3D/zeldovichPancake.yml b/examples/ZeldovichPancake_3D/zeldovichPancake.yml
index 481432d5875470aa464f69d5aa47fb76328cde7d..5cfa01ff954a959e06076035ae22240bb3c5a120 100644
--- a/examples/ZeldovichPancake_3D/zeldovichPancake.yml
+++ b/examples/ZeldovichPancake_3D/zeldovichPancake.yml
@@ -17,7 +17,7 @@ Cosmology:
 # Parameters governing the time integration
 TimeIntegration:
   dt_min:     1e-7  # The minimal time-step size of the simulation (in internal units).
-  dt_max:     1e-3  # The maximal time-step size of the simulation (in internal units).
+  dt_max:     4e-3  # The maximal time-step size of the simulation (in internal units).
 
 # Parameters governing the snapshots
 Snapshots:
@@ -42,10 +42,9 @@ InitialConditions:
 Scheduler:
   max_top_level_cells: 8
   cell_split_size:     50
-  tasks_per_cell:      125
   
 Gravity:
-  mesh_side_length:   16
+  mesh_side_length:   32
   eta: 0.025
   theta: 0.3
   r_cut_max: 5.
diff --git a/examples/parameter_example.yml b/examples/parameter_example.yml
index ddb71c594122a3e8d6ddbd7c5b73e0474b404a75..5fb48eb17d1c210d2a320917e1fd5d1ad67ddd94 100644
--- a/examples/parameter_example.yml
+++ b/examples/parameter_example.yml
@@ -75,6 +75,7 @@ Snapshots:
   time_first: 0.          # (Optional) Time of the first output if non-cosmological time-integration (in internal units)
   delta_time: 0.01        # Time difference between consecutive outputs (in internal units)
   compression: 0          # (Optional) Set the level of compression of the HDF5 datasets [0-9]. 0 does no compression.
+  label_first: 0          # (Optional) An additional offset for the snapshot output label
   label_delta: 1          # (Optional) Set the integer increment between snapshot output labels
   UnitMass_in_cgs:     1  # (Optional) Unit system for the outputs (Grams)
   UnitLength_in_cgs:   1  # (Optional) Unit system for the outputs (Centimeters)
@@ -142,9 +143,13 @@ EoS:
   planetary_use_ANEOS:  0   # (Optional) Whether to prepare the ANEOS EOS
   planetary_use_SESAME: 0   # (Optional) Whether to prepare the SESAME EOS
                             # (Optional) Table file paths
-  planetary_HM80_HHe_table_file:    HM80_HHe.txt
-  planetary_HM80_ice_table_file:    HM80_ice.txt
-  planetary_HM80_rock_table_file:   HM80_rock.txt
+  planetary_HM80_HHe_table_file:        ./equation_of_state/planetary_HM80_HHe.txt
+  planetary_HM80_ice_table_file:        ./equation_of_state/planetary_HM80_ice.txt
+  planetary_HM80_rock_table_file:       ./equation_of_state/planetary_HM80_rock.txt
+  planetary_SESAME_iron_table_file:     ./equation_of_state/planetary_SESAME_iron_2140.txt
+  planetary_SESAME_basalt_table_file:   ./equation_of_state/planetary_SESAME_basalt_7530.txt
+  planetary_SESAME_water_table_file:    ./equation_of_state/planetary_SESAME_water_7154.txt
+  planetary_SS08_water_table_file:      ./equation_of_state/planetary_SS08_water.txt
 
 # Parameters related to external potentials --------------------------------------------
 
diff --git a/src/Makefile.am b/src/Makefile.am
index fbc1d9fdc025dca2a498208ddce98e716fa2fd03..0f61fb108d8d8acbd420c994266f4803a3f69d3e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -106,7 +106,6 @@ nobase_noinst_HEADERS = align.h approx_math.h atomic.h barrier.h cycle.h error.h
                  hydro/GizmoMFM/hydro_slope_limiters_face.h \
                  hydro/GizmoMFM/hydro_slope_limiters.h \
                  hydro/GizmoMFM/hydro_unphysical.h \
-                 hydro/GizmoMFM/hydro_velocities.h \
                  hydro/Shadowswift/hydro_debug.h \
                  hydro/Shadowswift/hydro_gradients.h hydro/Shadowswift/hydro.h \
                  hydro/Shadowswift/hydro_iact.h \
diff --git a/src/cell.c b/src/cell.c
index 8ca6771a43929b924003630f80b56cbf6d185fa8..1ceb0556a5bfada87d2a5b160dd6c353724dc315 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -62,6 +62,7 @@
 #include "space.h"
 #include "space_getsid.h"
 #include "timers.h"
+#include "tools.h"
 
 /* Global variables. */
 int cell_next_tag = 0;
@@ -2587,6 +2588,36 @@ void cell_drift_part(struct cell *c, const struct engine *e, int force) {
       }
 #endif
 
+#ifdef PLANETARY_SPH
+      /* Remove particles that cross the non-periodic box edge */
+      if (!(e->s->periodic)) {
+        for (int i = 0; i < 3; i++) {
+          if ((p->x[i] - xp->v_full[i] * dt_drift > e->s->dim[i]) ||
+              (p->x[i] - xp->v_full[i] * dt_drift < 0.f) ||
+              ((p->mass != 0.f) && ((p->x[i] < 0.01f * e->s->dim[i]) ||
+                                    (p->x[i] > 0.99f * e->s->dim[i])))) {
+            /* (TEMPORARY) Crudely stop the particle manually */
+            message(
+                "Particle %lld hit a box edge. \n"
+                "  pos=%.4e %.4e %.4e  vel=%.2e %.2e %.2e",
+                p->id, p->x[0], p->x[1], p->x[2], p->v[0], p->v[1], p->v[2]);
+            for (int j = 0; j < 3; j++) {
+              p->v[j] = 0.f;
+              p->gpart->v_full[j] = 0.f;
+              xp->v_full[j] = 0.f;
+            }
+            p->h = hydro_h_max;
+            p->time_bin = time_bin_inhibited;
+            p->gpart->time_bin = time_bin_inhibited;
+            hydro_part_has_no_neighbours(p, xp, e->cosmology);
+            p->mass = 0.f;
+            p->gpart->mass = 0.f;
+            break;
+          }
+        }
+      }
+#endif
+
       /* Limit h to within the allowed range */
       p->h = min(p->h, hydro_h_max);
 
@@ -2689,6 +2720,26 @@ void cell_drift_gpart(struct cell *c, const struct engine *e, int force) {
       /* Drift... */
       drift_gpart(gp, dt_drift, ti_old_gpart, ti_current);
 
+#ifdef PLANETARY_SPH
+      /* Remove particles that cross the non-periodic box edge */
+      if (!(e->s->periodic)) {
+        for (int i = 0; i < 3; i++) {
+          if ((gp->x[i] - gp->v_full[i] * dt_drift > e->s->dim[i]) ||
+              (gp->x[i] - gp->v_full[i] * dt_drift < 0.f) ||
+              ((gp->mass != 0.f) && ((gp->x[i] < 0.01f * e->s->dim[i]) ||
+                                     (gp->x[i] > 0.99f * e->s->dim[i])))) {
+            /* (TEMPORARY) Crudely stop the particle manually */
+            for (int j = 0; j < 3; j++) {
+              gp->v_full[j] = 0.f;
+            }
+            gp->time_bin = time_bin_inhibited;
+            gp->mass = 0.f;
+            break;
+          }
+        }
+      }
+#endif
+
       /* Init gravity force fields. */
       if (gpart_is_active(gp, e)) {
         gravity_init_gpart(gp);
diff --git a/src/cosmology.c b/src/cosmology.c
index 0c81cb00aaae8d0c8d0974e02c41ad99c9e83840..e9d35125f65777ffb7f143896029c5720c14cc54 100644
--- a/src/cosmology.c
+++ b/src/cosmology.c
@@ -265,6 +265,29 @@ double hydro_kick_integrand(double a, void *param) {
   return (1. / H) * pow(a_inv, 3. * hydro_gamma_minus_one) * a_inv;
 }
 
+/**
+ * @brief Computes \f$a dt\f$ for the current cosmology.
+ *
+ * @param a The scale-factor of interest.
+ * @param param The current #cosmology.
+ */
+double hydro_kick_corr_integrand(double a, void *param) {
+
+  const struct cosmology *c = (const struct cosmology *)param;
+  const double Omega_r = c->Omega_r;
+  const double Omega_m = c->Omega_m;
+  const double Omega_k = c->Omega_k;
+  const double Omega_l = c->Omega_lambda;
+  const double w_0 = c->w_0;
+  const double w_a = c->w_a;
+  const double H0 = c->H0;
+
+  const double E_z = E(Omega_r, Omega_m, Omega_k, Omega_l, w_0, w_a, a);
+  const double H = H0 * E_z;
+
+  return 1. / H;
+}
+
 /**
  * @brief Computes \f$ dt \f$ for the current cosmology.
  *
@@ -306,6 +329,8 @@ void cosmology_init_tables(struct cosmology *c) {
       (double *)malloc(cosmology_table_length * sizeof(double));
   c->hydro_kick_fac_interp_table =
       (double *)malloc(cosmology_table_length * sizeof(double));
+  c->hydro_kick_corr_interp_table =
+      (double *)malloc(cosmology_table_length * sizeof(double));
   c->time_interp_table =
       (double *)malloc(cosmology_table_length * sizeof(double));
   c->scale_factor_interp_table =
@@ -354,6 +379,16 @@ void cosmology_init_tables(struct cosmology *c) {
     c->hydro_kick_fac_interp_table[i] = result;
   }
 
+  /* Integrate the kick correction factor \int_{a_begin}^{a_table[i]} a dt */
+  F.function = &hydro_kick_corr_integrand;
+  for (int i = 0; i < cosmology_table_length; i++) {
+    gsl_integration_qag(&F, a_begin, a_table[i], 0, 1.0e-10, GSL_workspace_size,
+                        GSL_INTEG_GAUSS61, space, &result, &abserr);
+
+    /* Store result */
+    c->hydro_kick_corr_interp_table[i] = result;
+  }
+
   /* Integrate the time \int_{a_begin}^{a_table[i]} dt */
   F.function = &time_integrand;
   for (int i = 0; i < cosmology_table_length; i++) {
@@ -374,31 +409,43 @@ void cosmology_init_tables(struct cosmology *c) {
                       GSL_INTEG_GAUSS61, space, &result, &abserr);
   c->universe_age_at_present_day = result;
 
-  /* Inverse t(a) */
-  const double time_init = c->time_interp_table_offset;
-  const double delta_t =
-      (c->universe_age_at_present_day - time_init) / cosmology_table_length;
+  /* Update the times */
+  c->time_begin = cosmology_get_time_since_big_bang(c, c->a_begin);
+  c->time_end = cosmology_get_time_since_big_bang(c, c->a_end);
 
-  int i_prev = 0;
-  for (int i = 0; i < cosmology_table_length; i++) {
-    /* Current time */
-    double time_interp = delta_t * i;
+  /*
+   * Inverse t(a)
+   */
+
+  const double delta_t = (c->time_end - c->time_begin) / cosmology_table_length;
+
+  /* index in the time_interp_table */
+  int i_a = 0;
+
+  for (int i_time = 0; i_time < cosmology_table_length; i_time++) {
+    /* Current time
+     * time_interp_table = \int_a_begin^a => no need of time_begin */
+    double time_interp = delta_t * (i_time + 1);
 
     /* Find next time in time_interp_table */
-    while (i_prev < cosmology_table_length &&
-           c->time_interp_table[i_prev] <= time_interp) {
-      i_prev++;
+    while (i_a < cosmology_table_length &&
+           c->time_interp_table[i_a] <= time_interp) {
+      i_a++;
     }
 
     /* Find linear interpolation scaling */
-    double scale = time_interp - c->time_interp_table[i_prev - 1];
-    scale /= c->time_interp_table[i_prev] - c->time_interp_table[i_prev - 1];
-    scale += i_prev;
+    double scale = 0;
+    if (i_a != cosmology_table_length) {
+      scale = time_interp - c->time_interp_table[i_a - 1];
+      scale /= c->time_interp_table[i_a] - c->time_interp_table[i_a - 1];
+    }
+
+    scale += i_a;
 
     /* Compute interpolated scale factor */
     double log_a = c->log_a_begin + scale * (c->log_a_end - c->log_a_begin) /
                                         cosmology_table_length;
-    c->scale_factor_interp_table[i] = exp(log_a) - c->a_begin;
+    c->scale_factor_interp_table[i_time] = exp(log_a) - c->a_begin;
   }
 
   /* Free the workspace and temp array */
@@ -586,7 +633,8 @@ double cosmology_get_grav_kick_factor(const struct cosmology *c,
 /**
  * @brief Computes the cosmology factor that enters the hydro kick operator.
  *
- * Computes \f$ \int_{a_start}^{a_end} dt/a \f$ using the interpolation table.
+ * Computes \f$ \int_{a_start}^{a_end} dt/a^{3(gamma - 1)} \f$ using the
+ * interpolation table.
  *
  * @param c The current #cosmology.
  * @param ti_start the (integer) time of the start of the drift.
@@ -603,9 +651,38 @@ double cosmology_get_hydro_kick_factor(const struct cosmology *c,
   const double a_start = c->log_a_begin + ti_start * c->time_base;
   const double a_end = c->log_a_begin + ti_end * c->time_base;
 
-  const double int_start = interp_table(c->drift_fac_interp_table, a_start,
+  const double int_start = interp_table(c->hydro_kick_fac_interp_table, a_start,
                                         c->log_a_begin, c->log_a_end);
-  const double int_end = interp_table(c->drift_fac_interp_table, a_end,
+  const double int_end = interp_table(c->hydro_kick_fac_interp_table, a_end,
+                                      c->log_a_begin, c->log_a_end);
+
+  return int_end - int_start;
+}
+
+/**
+ * @brief Computes the cosmology factor that enters the hydro kick correction
+ * operator for the meshless schemes (GIZMO-MFV).
+ *
+ * Computes \f$ \int_{a_start}^{a_end} a dt \f$ using the interpolation table.
+ *
+ * @param c The current #cosmology.
+ * @param ti_start the (integer) time of the start of the drift.
+ * @param ti_end the (integer) time of the end of the drift.
+ */
+double cosmology_get_corr_kick_factor(const struct cosmology *c,
+                                      integertime_t ti_start,
+                                      integertime_t ti_end) {
+
+#ifdef SWIFT_DEBUG_CHECKS
+  if (ti_end < ti_start) error("ti_end must be >= ti_start");
+#endif
+
+  const double a_start = c->log_a_begin + ti_start * c->time_base;
+  const double a_end = c->log_a_begin + ti_end * c->time_base;
+
+  const double int_start = interp_table(c->hydro_kick_corr_interp_table,
+                                        a_start, c->log_a_begin, c->log_a_end);
+  const double int_end = interp_table(c->hydro_kick_corr_interp_table, a_end,
                                       c->log_a_begin, c->log_a_end);
 
   return int_end - int_start;
@@ -632,9 +709,9 @@ double cosmology_get_therm_kick_factor(const struct cosmology *c,
   const double a_start = c->log_a_begin + ti_start * c->time_base;
   const double a_end = c->log_a_begin + ti_end * c->time_base;
 
-  const double int_start = interp_table(c->hydro_kick_fac_interp_table, a_start,
+  const double int_start = interp_table(c->drift_fac_interp_table, a_start,
                                         c->log_a_begin, c->log_a_end);
-  const double int_end = interp_table(c->hydro_kick_fac_interp_table, a_end,
+  const double int_end = interp_table(c->drift_fac_interp_table, a_end,
                                       c->log_a_begin, c->log_a_end);
 
   return int_end - int_start;
@@ -672,9 +749,6 @@ double cosmology_get_delta_time(const struct cosmology *c,
 /**
  * @brief Compute scale factor from time since big bang (in internal units).
  *
- * WARNING: This method has a low accuracy at high redshift.
- * The relative error is around 1e-3 (testCosmology.c is measuring it).
- *
  * @param c The current #cosmology.
  * @param t time since the big bang
  * @return The scale factor.
@@ -707,6 +781,7 @@ void cosmology_clean(struct cosmology *c) {
   free(c->drift_fac_interp_table);
   free(c->grav_kick_fac_interp_table);
   free(c->hydro_kick_fac_interp_table);
+  free(c->hydro_kick_corr_interp_table);
   free(c->time_interp_table);
   free(c->scale_factor_interp_table);
 }
diff --git a/src/cosmology.h b/src/cosmology.h
index 7136b65667195953971060b76ddfd447a5fdf500..4556b039bd0e306dab37a05bc200c3aa2ab8a602 100644
--- a/src/cosmology.h
+++ b/src/cosmology.h
@@ -153,6 +153,9 @@ struct cosmology {
   /*! Kick factor (hydro) interpolation table */
   double *hydro_kick_fac_interp_table;
 
+  /*! Kick factor (hydro correction) interpolation table (GIZMO-MFV only) */
+  double *hydro_kick_corr_interp_table;
+
   /*! Time interpolation table */
   double *time_interp_table;
 
@@ -180,6 +183,9 @@ double cosmology_get_hydro_kick_factor(const struct cosmology *cosmo,
 double cosmology_get_therm_kick_factor(const struct cosmology *cosmo,
                                        integertime_t ti_start,
                                        integertime_t ti_end);
+double cosmology_get_corr_kick_factor(const struct cosmology *cosmo,
+                                      integertime_t ti_start,
+                                      integertime_t ti_end);
 double cosmology_get_delta_time(const struct cosmology *c,
                                 integertime_t ti_start, integertime_t ti_end);
 
diff --git a/src/debug.c b/src/debug.c
index da8ef0e118b57a6aa94577898b03bcf7c56b006a..5c2523da7b97e44febe52405e954eef1c5f865d2 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -56,8 +56,8 @@
 #include "./hydro/GizmoMFM/hydro_debug.h"
 #elif defined(SHADOWFAX_SPH)
 #include "./hydro/Shadowswift/hydro_debug.h"
-#elif defined(MINIMAL_MULTI_MAT_SPH)
-#include "./hydro/MinimalMultiMat/hydro_debug.h"
+#elif defined(PLANETARY_SPH)
+#include "./hydro/Planetary/hydro_debug.h"
 #else
 #error "Invalid choice of SPH variant"
 #endif
diff --git a/src/engine.c b/src/engine.c
index 93c033d0c398e7a0e9865ab1feb5e0ef5c34d290..78705411d455ab032d184410cad3f957b7b0cfec 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -62,6 +62,7 @@
 #include "cosmology.h"
 #include "cycle.h"
 #include "debug.h"
+#include "equation_of_state.h"
 #include "error.h"
 #include "gravity.h"
 #include "gravity_cache.h"
@@ -2745,6 +2746,9 @@ void engine_link_gravity_tasks(struct engine *e) {
     /* Get a pointer to the task. */
     struct task *t = &sched->tasks[k];
 
+    if(t->type == task_type_none)
+      continue;
+
     /* Get the cells we act on */
     struct cell *ci = t->ci;
     struct cell *cj = t->cj;
@@ -5770,6 +5774,10 @@ void engine_init(struct engine *e, struct space *s, struct swift_params *params,
   parser_get_param_string(params, "Snapshots:basename", e->snapshot_base_name);
   e->snapshot_compression =
       parser_get_opt_param_int(params, "Snapshots:compression", 0);
+  e->snapshot_label_first =
+      parser_get_opt_param_int(params, "Snapshots:label_first", 0);
+  if (e->snapshot_label_first < 0)
+    error("Snapshots:label_first must be zero or positive");
   e->snapshot_label_delta =
       parser_get_opt_param_int(params, "Snapshots:label_delta", 1);
   e->snapshot_units = (struct unit_system *)malloc(sizeof(struct unit_system));
@@ -6980,6 +6988,10 @@ void engine_struct_restore(struct engine *e, FILE *stream) {
     e->output_list_stf = output_list_stf;
   }
 
+#ifdef EOS_PLANETARY
+  eos_init(&eos, e->physical_constants, e->snapshot_units, e->parameter_file);
+#endif
+
   /* Want to force a rebuild before using this engine. Wait to repartition.*/
   e->forcerebuild = 1;
   e->forcerepart = 0;
diff --git a/src/engine.h b/src/engine.h
index aeb57c65ac36ff5ddbf4b74185adeb94f3d460da..cfd656712bdea84484101cf7e83795f795200f5f 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -223,6 +223,7 @@ struct engine {
 
   char snapshot_base_name[PARSER_MAX_LINE_SIZE];
   int snapshot_compression;
+  int snapshot_label_first;
   int snapshot_label_delta;
   struct unit_system *snapshot_units;
   int snapshot_output_count;
diff --git a/src/equation_of_state/planetary/aneos.h b/src/equation_of_state/planetary/aneos.h
deleted file mode 100644
index 904288b2fdf3ba825cdc7d114ebb61cd42de198d..0000000000000000000000000000000000000000
--- a/src/equation_of_state/planetary/aneos.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*******************************************************************************
- * This file is part of SWIFT.
- * Copyright (c) 2016   Matthieu Schaller (matthieu.schaller@durham.ac.uk).
- *               2018   Jacob Kegerreis (jacob.kegerreis@durham.ac.uk).
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- ******************************************************************************/
-#ifndef SWIFT_ANEOS_EQUATION_OF_STATE_H
-#define SWIFT_ANEOS_EQUATION_OF_STATE_H
-
-/**
- * @file equation_of_state/planetary/aneos.h
- *
- * Contains the (M)ANEOS EOS functions for
- * equation_of_state/planetary/equation_of_state.h
- *
- * Adapted from the implementation in Gadget 2 of Cuk & Stewart (2012)
- *
- */
-
-/* Some standard headers. */
-#include <math.h>
-
-/* Local headers. */
-#include "adiabatic_index.h"
-#include "common_io.h"
-#include "equation_of_state.h"
-#include "inline.h"
-#include "physical_constants.h"
-#include "units.h"
-
-// ANEOS parameters
-struct ANEOS_params {
-  enum eos_planetary_material_id mat_id;
-};
-
-// Parameter values for each material (cgs units)
-INLINE static void set_ANEOS_iron(struct ANEOS_params *mat,
-                                  enum eos_planetary_material_id mat_id) {
-  mat->mat_id = mat_id;
-}
-INLINE static void set_MANEOS_forsterite(
-    struct ANEOS_params *mat, enum eos_planetary_material_id mat_id) {
-  mat->mat_id = mat_id;
-}
-
-// Convert from cgs to internal units
-INLINE static void convert_units_ANEOS(struct ANEOS_params *mat,
-                                       const struct unit_system *us) {}
-
-// gas_internal_energy_from_entropy
-INLINE static float ANEOS_internal_energy_from_entropy(
-    float density, float entropy, const struct ANEOS_params *mat) {
-
-  error("This EOS function is not yet implemented!");
-
-  return 0;
-}
-
-// gas_pressure_from_entropy
-INLINE static float ANEOS_pressure_from_entropy(
-    float density, float entropy, const struct ANEOS_params *mat) {
-
-  error("This EOS function is not yet implemented!");
-
-  return 0;
-}
-
-// gas_entropy_from_pressure
-INLINE static float ANEOS_entropy_from_pressure(
-    float density, float pressure, const struct ANEOS_params *mat) {
-
-  error("This EOS function is not yet implemented!");
-
-  return 0;
-}
-
-// gas_soundspeed_from_entropy
-INLINE static float ANEOS_soundspeed_from_entropy(
-    float density, float entropy, const struct ANEOS_params *mat) {
-
-  error("This EOS function is not yet implemented!");
-
-  return 0;
-}
-
-// gas_entropy_from_internal_energy
-INLINE static float ANEOS_entropy_from_internal_energy(
-    float density, float u, const struct ANEOS_params *mat) {
-
-  error("This EOS function is not yet implemented!");
-
-  return 0;
-}
-
-// gas_pressure_from_internal_energy
-INLINE static float ANEOS_pressure_from_internal_energy(
-    float density, float u, const struct ANEOS_params *mat) {
-
-  error("This EOS function is not yet implemented!");
-
-  return 0;
-}
-
-// gas_internal_energy_from_pressure
-INLINE static float ANEOS_internal_energy_from_pressure(
-    float density, float P, const struct ANEOS_params *mat) {
-
-  error("This EOS function is not yet implemented!");
-
-  return 0;
-}
-
-// gas_soundspeed_from_internal_energy
-INLINE static float ANEOS_soundspeed_from_internal_energy(
-    float density, float u, const struct ANEOS_params *mat) {
-
-  error("This EOS function is not yet implemented!");
-
-  return 0;
-}
-
-// gas_soundspeed_from_pressure
-INLINE static float ANEOS_soundspeed_from_pressure(
-    float density, float P, const struct ANEOS_params *mat) {
-
-  error("This EOS function is not yet implemented!");
-
-  return 0;
-}
-
-#endif /* SWIFT_ANEOS_EQUATION_OF_STATE_H */
diff --git a/src/equation_of_state/planetary/equation_of_state.h b/src/equation_of_state/planetary/equation_of_state.h
index 61e23dc0b4eb82e9ae5c0869f7a10dfff97fc45e..644167bb4795a2a3d0fefe130cba93c64f29941b 100644
--- a/src/equation_of_state/planetary/equation_of_state.h
+++ b/src/equation_of_state/planetary/equation_of_state.h
@@ -39,6 +39,7 @@
 #include "common_io.h"
 #include "inline.h"
 #include "physical_constants.h"
+#include "restart.h"
 #include "units.h"
 
 extern struct eos_parameters eos;
@@ -50,10 +51,15 @@ extern struct eos_parameters eos;
  * @brief Master type for the planetary equation of state.
  */
 enum eos_planetary_type_id {
+
+  /*! Tillotson */
   eos_planetary_type_Til = 1,
+
+  /*! Hubbard & MacFarlane (1980) Uranus/Neptune */
   eos_planetary_type_HM80 = 2,
-  eos_planetary_type_ANEOS = 3,
-  eos_planetary_type_SESAME = 4,
+
+  /*! SESAME */
+  eos_planetary_type_SESAME = 3,
 };
 
 /**
@@ -89,25 +95,26 @@ enum eos_planetary_material_id {
   eos_planetary_id_HM80_rock =
       eos_planetary_type_HM80 * eos_planetary_type_factor + 2,
 
-  /* ANEOS */
-
-  /*! ANEOS iron */
-  eos_planetary_id_ANEOS_iron =
-      eos_planetary_type_ANEOS * eos_planetary_type_factor,
-
-  /*! MANEOS forsterite */
-  eos_planetary_id_MANEOS_forsterite =
-      eos_planetary_type_ANEOS * eos_planetary_type_factor + 1,
-
   /* SESAME */
 
-  /*! SESAME iron */
+  /*! SESAME iron 2140 */
   eos_planetary_id_SESAME_iron =
       eos_planetary_type_SESAME * eos_planetary_type_factor,
+
+  /*! SESAME basalt 7530 */
+  eos_planetary_id_SESAME_basalt =
+      eos_planetary_type_SESAME * eos_planetary_type_factor + 1,
+
+  /*! SESAME water 7154 */
+  eos_planetary_id_SESAME_water =
+      eos_planetary_type_SESAME * eos_planetary_type_factor + 2,
+
+  /*! Senft & Stewart (2008) SESAME-like water */
+  eos_planetary_id_SS08_water =
+      eos_planetary_type_SESAME * eos_planetary_type_factor + 3,
 };
 
 /* Individual EOS function headers. */
-#include "aneos.h"
 #include "hm80.h"
 #include "sesame.h"
 #include "tillotson.h"
@@ -118,8 +125,7 @@ enum eos_planetary_material_id {
 struct eos_parameters {
   struct Til_params Til_iron, Til_granite, Til_water;
   struct HM80_params HM80_HHe, HM80_ice, HM80_rock;
-  struct ANEOS_params ANEOS_iron, MANEOS_forsterite;
-  struct SESAME_params SESAME_iron;
+  struct SESAME_params SESAME_iron, SESAME_basalt, SESAME_water, SS08_water;
 };
 
 /**
@@ -190,35 +196,29 @@ gas_internal_energy_from_entropy(float density, float entropy,
       };
       break;
 
-    /* ANEOS EoS */
-    case eos_planetary_type_ANEOS:
+    /* SESAME EoS */
+    case eos_planetary_type_SESAME:;
 
       /* Select the material */
       switch (mat_id) {
-        case eos_planetary_id_ANEOS_iron:
-          return ANEOS_internal_energy_from_entropy(density, entropy,
-                                                    &eos.ANEOS_iron);
+        case eos_planetary_id_SESAME_iron:
+          return SESAME_internal_energy_from_entropy(density, entropy,
+                                                     &eos.SESAME_iron);
           break;
 
-        case eos_planetary_id_MANEOS_forsterite:
-          return ANEOS_internal_energy_from_entropy(density, entropy,
-                                                    &eos.MANEOS_forsterite);
+        case eos_planetary_id_SESAME_basalt:
+          return SESAME_internal_energy_from_entropy(density, entropy,
+                                                     &eos.SESAME_basalt);
           break;
 
-        default:
-          error("Unknown material ID! mat_id = %d", mat_id);
-          return 0.f;
-      };
-      break;
-
-    /* SESAME EoS */
-    case eos_planetary_type_SESAME:;
+        case eos_planetary_id_SESAME_water:
+          return SESAME_internal_energy_from_entropy(density, entropy,
+                                                     &eos.SESAME_water);
+          break;
 
-      /* Select the material */
-      switch (mat_id) {
-        case eos_planetary_id_SESAME_iron:
+        case eos_planetary_id_SS08_water:
           return SESAME_internal_energy_from_entropy(density, entropy,
-                                                     &eos.SESAME_iron);
+                                                     &eos.SS08_water);
           break;
 
         default:
@@ -294,34 +294,29 @@ __attribute__((always_inline)) INLINE static float gas_pressure_from_entropy(
       };
       break;
 
-    /* ANEOS EoS */
-    case eos_planetary_type_ANEOS:
+    /* SESAME EoS */
+    case eos_planetary_type_SESAME:;
 
       /* Select the material */
       switch (mat_id) {
-        case eos_planetary_id_ANEOS_iron:
-          return ANEOS_pressure_from_entropy(density, entropy, &eos.ANEOS_iron);
+        case eos_planetary_id_SESAME_iron:
+          return SESAME_pressure_from_entropy(density, entropy,
+                                              &eos.SESAME_iron);
           break;
 
-        case eos_planetary_id_MANEOS_forsterite:
-          return ANEOS_pressure_from_entropy(density, entropy,
-                                             &eos.MANEOS_forsterite);
+        case eos_planetary_id_SESAME_basalt:
+          return SESAME_pressure_from_entropy(density, entropy,
+                                              &eos.SESAME_basalt);
           break;
 
-        default:
-          error("Unknown material ID! mat_id = %d", mat_id);
-          return 0.f;
-      };
-      break;
-
-    /* SESAME EoS */
-    case eos_planetary_type_SESAME:;
+        case eos_planetary_id_SESAME_water:
+          return SESAME_pressure_from_entropy(density, entropy,
+                                              &eos.SESAME_water);
 
-      /* Select the material */
-      switch (mat_id) {
-        case eos_planetary_id_SESAME_iron:
+        case eos_planetary_id_SS08_water:
           return SESAME_pressure_from_entropy(density, entropy,
-                                              &eos.SESAME_iron);
+                                              &eos.SS08_water);
+          break;
           break;
 
         default:
@@ -398,33 +393,25 @@ __attribute__((always_inline)) INLINE static float gas_entropy_from_pressure(
       };
       break;
 
-    /* ANEOS EoS */
-    case eos_planetary_type_ANEOS:
+    /* SESAME EoS */
+    case eos_planetary_type_SESAME:;
 
       /* Select the material */
       switch (mat_id) {
-        case eos_planetary_id_ANEOS_iron:
-          return ANEOS_entropy_from_pressure(density, P, &eos.ANEOS_iron);
+        case eos_planetary_id_SESAME_iron:
+          return SESAME_entropy_from_pressure(density, P, &eos.SESAME_iron);
           break;
 
-        case eos_planetary_id_MANEOS_forsterite:
-          return ANEOS_entropy_from_pressure(density, P,
-                                             &eos.MANEOS_forsterite);
+        case eos_planetary_id_SESAME_basalt:
+          return SESAME_entropy_from_pressure(density, P, &eos.SESAME_basalt);
           break;
 
-        default:
-          error("Unknown material ID! mat_id = %d", mat_id);
-          return 0.f;
-      };
-      break;
-
-    /* SESAME EoS */
-    case eos_planetary_type_SESAME:;
+        case eos_planetary_id_SESAME_water:
+          return SESAME_entropy_from_pressure(density, P, &eos.SESAME_water);
+          break;
 
-      /* Select the material */
-      switch (mat_id) {
-        case eos_planetary_id_SESAME_iron:
-          return SESAME_entropy_from_pressure(density, P, &eos.SESAME_iron);
+        case eos_planetary_id_SS08_water:
+          return SESAME_entropy_from_pressure(density, P, &eos.SS08_water);
           break;
 
         default:
@@ -501,35 +488,29 @@ __attribute__((always_inline)) INLINE static float gas_soundspeed_from_entropy(
       };
       break;
 
-    /* ANEOS EoS */
-    case eos_planetary_type_ANEOS:
+    /* SESAME EoS */
+    case eos_planetary_type_SESAME:;
 
       /* Select the material */
       switch (mat_id) {
-        case eos_planetary_id_ANEOS_iron:
-          return ANEOS_soundspeed_from_entropy(density, entropy,
-                                               &eos.ANEOS_iron);
+        case eos_planetary_id_SESAME_iron:
+          return SESAME_soundspeed_from_entropy(density, entropy,
+                                                &eos.SESAME_iron);
           break;
 
-        case eos_planetary_id_MANEOS_forsterite:
-          return ANEOS_soundspeed_from_entropy(density, entropy,
-                                               &eos.MANEOS_forsterite);
+        case eos_planetary_id_SESAME_basalt:
+          return SESAME_soundspeed_from_entropy(density, entropy,
+                                                &eos.SESAME_basalt);
           break;
 
-        default:
-          error("Unknown material ID! mat_id = %d", mat_id);
-          return 0.f;
-      };
-      break;
-
-    /* SESAME EoS */
-    case eos_planetary_type_SESAME:;
+        case eos_planetary_id_SESAME_water:
+          return SESAME_soundspeed_from_entropy(density, entropy,
+                                                &eos.SESAME_water);
+          break;
 
-      /* Select the material */
-      switch (mat_id) {
-        case eos_planetary_id_SESAME_iron:
+        case eos_planetary_id_SS08_water:
           return SESAME_soundspeed_from_entropy(density, entropy,
-                                                &eos.SESAME_iron);
+                                                &eos.SS08_water);
           break;
 
         default:
@@ -605,35 +586,29 @@ gas_entropy_from_internal_energy(float density, float u,
       };
       break;
 
-    /* ANEOS EoS */
-    case eos_planetary_type_ANEOS:
+    /* SESAME EoS */
+    case eos_planetary_type_SESAME:;
 
       /* Select the material */
       switch (mat_id) {
-        case eos_planetary_id_ANEOS_iron:
-          return ANEOS_entropy_from_internal_energy(density, u,
-                                                    &eos.ANEOS_iron);
+        case eos_planetary_id_SESAME_iron:
+          return SESAME_entropy_from_internal_energy(density, u,
+                                                     &eos.SESAME_iron);
           break;
 
-        case eos_planetary_id_MANEOS_forsterite:
-          return ANEOS_entropy_from_internal_energy(density, u,
-                                                    &eos.MANEOS_forsterite);
+        case eos_planetary_id_SESAME_basalt:
+          return SESAME_entropy_from_internal_energy(density, u,
+                                                     &eos.SESAME_basalt);
           break;
 
-        default:
-          error("Unknown material ID! mat_id = %d", mat_id);
-          return 0.f;
-      };
-      break;
-
-    /* SESAME EoS */
-    case eos_planetary_type_SESAME:;
+        case eos_planetary_id_SESAME_water:
+          return SESAME_entropy_from_internal_energy(density, u,
+                                                     &eos.SESAME_water);
+          break;
 
-      /* Select the material */
-      switch (mat_id) {
-        case eos_planetary_id_SESAME_iron:
+        case eos_planetary_id_SS08_water:
           return SESAME_entropy_from_internal_energy(density, u,
-                                                     &eos.SESAME_iron);
+                                                     &eos.SS08_water);
           break;
 
         default:
@@ -711,35 +686,29 @@ gas_pressure_from_internal_energy(float density, float u,
       };
       break;
 
-    /* ANEOS EoS */
-    case eos_planetary_type_ANEOS:
+    /* SESAME EoS */
+    case eos_planetary_type_SESAME:;
 
       /* Select the material */
       switch (mat_id) {
-        case eos_planetary_id_ANEOS_iron:
-          return ANEOS_pressure_from_internal_energy(density, u,
-                                                     &eos.ANEOS_iron);
+        case eos_planetary_id_SESAME_iron:
+          return SESAME_pressure_from_internal_energy(density, u,
+                                                      &eos.SESAME_iron);
           break;
 
-        case eos_planetary_id_MANEOS_forsterite:
-          return ANEOS_pressure_from_internal_energy(density, u,
-                                                     &eos.MANEOS_forsterite);
+        case eos_planetary_id_SESAME_basalt:
+          return SESAME_pressure_from_internal_energy(density, u,
+                                                      &eos.SESAME_basalt);
           break;
 
-        default:
-          error("Unknown material ID! mat_id = %d", mat_id);
-          return 0.f;
-      };
-      break;
-
-    /* SESAME EoS */
-    case eos_planetary_type_SESAME:;
+        case eos_planetary_id_SESAME_water:
+          return SESAME_pressure_from_internal_energy(density, u,
+                                                      &eos.SESAME_water);
+          break;
 
-      /* Select the material */
-      switch (mat_id) {
-        case eos_planetary_id_SESAME_iron:
+        case eos_planetary_id_SS08_water:
           return SESAME_pressure_from_internal_energy(density, u,
-                                                      &eos.SESAME_iron);
+                                                      &eos.SS08_water);
           break;
 
         default:
@@ -820,35 +789,29 @@ gas_internal_energy_from_pressure(float density, float P,
       };
       break;
 
-    /* ANEOS EoS */
-    case eos_planetary_type_ANEOS:
+    /* SESAME EoS */
+    case eos_planetary_type_SESAME:;
 
       /* Select the material */
       switch (mat_id) {
-        case eos_planetary_id_ANEOS_iron:
-          return ANEOS_internal_energy_from_pressure(density, P,
-                                                     &eos.ANEOS_iron);
+        case eos_planetary_id_SESAME_iron:
+          return SESAME_internal_energy_from_pressure(density, P,
+                                                      &eos.SESAME_iron);
           break;
 
-        case eos_planetary_id_MANEOS_forsterite:
-          return ANEOS_internal_energy_from_pressure(density, P,
-                                                     &eos.MANEOS_forsterite);
+        case eos_planetary_id_SESAME_basalt:
+          return SESAME_internal_energy_from_pressure(density, P,
+                                                      &eos.SESAME_basalt);
           break;
 
-        default:
-          error("Unknown material ID! mat_id = %d", mat_id);
-          return 0.f;
-      };
-      break;
-
-    /* SESAME EoS */
-    case eos_planetary_type_SESAME:;
+        case eos_planetary_id_SESAME_water:
+          return SESAME_internal_energy_from_pressure(density, P,
+                                                      &eos.SESAME_water);
+          break;
 
-      /* Select the material */
-      switch (mat_id) {
-        case eos_planetary_id_SESAME_iron:
+        case eos_planetary_id_SS08_water:
           return SESAME_internal_energy_from_pressure(density, P,
-                                                      &eos.SESAME_iron);
+                                                      &eos.SS08_water);
           break;
 
         default:
@@ -930,35 +893,29 @@ gas_soundspeed_from_internal_energy(float density, float u,
       };
       break;
 
-    /* ANEOS EoS */
-    case eos_planetary_type_ANEOS:
+    /* SESAME EoS */
+    case eos_planetary_type_SESAME:;
 
       /* Select the material */
       switch (mat_id) {
-        case eos_planetary_id_ANEOS_iron:
-          return ANEOS_soundspeed_from_internal_energy(density, u,
-                                                       &eos.ANEOS_iron);
+        case eos_planetary_id_SESAME_iron:
+          return SESAME_soundspeed_from_internal_energy(density, u,
+                                                        &eos.SESAME_iron);
           break;
 
-        case eos_planetary_id_MANEOS_forsterite:
-          return ANEOS_soundspeed_from_internal_energy(density, u,
-                                                       &eos.MANEOS_forsterite);
+        case eos_planetary_id_SESAME_basalt:
+          return SESAME_soundspeed_from_internal_energy(density, u,
+                                                        &eos.SESAME_basalt);
           break;
 
-        default:
-          error("Unknown material ID! mat_id = %d", mat_id);
-          return 0.f;
-      };
-      break;
-
-    /* SESAME EoS */
-    case eos_planetary_type_SESAME:;
+        case eos_planetary_id_SESAME_water:
+          return SESAME_soundspeed_from_internal_energy(density, u,
+                                                        &eos.SESAME_water);
+          break;
 
-      /* Select the material */
-      switch (mat_id) {
-        case eos_planetary_id_SESAME_iron:
+        case eos_planetary_id_SS08_water:
           return SESAME_soundspeed_from_internal_energy(density, u,
-                                                        &eos.SESAME_iron);
+                                                        &eos.SS08_water);
           break;
 
         default:
@@ -1034,33 +991,26 @@ __attribute__((always_inline)) INLINE static float gas_soundspeed_from_pressure(
       };
       break;
 
-    /* ANEOS EoS */
-    case eos_planetary_type_ANEOS:
+    /* SESAME EoS */
+    case eos_planetary_type_SESAME:;
 
       /* Select the material */
       switch (mat_id) {
-        case eos_planetary_id_ANEOS_iron:
-          return ANEOS_soundspeed_from_pressure(density, P, &eos.ANEOS_iron);
+        case eos_planetary_id_SESAME_iron:
+          return SESAME_soundspeed_from_pressure(density, P, &eos.SESAME_iron);
           break;
 
-        case eos_planetary_id_MANEOS_forsterite:
-          return ANEOS_soundspeed_from_pressure(density, P,
-                                                &eos.MANEOS_forsterite);
+        case eos_planetary_id_SESAME_basalt:
+          return SESAME_soundspeed_from_pressure(density, P,
+                                                 &eos.SESAME_basalt);
           break;
 
-        default:
-          error("Unknown material ID! mat_id = %d", mat_id);
-          return 0.f;
-      };
-      break;
-
-    /* SESAME EoS */
-    case eos_planetary_type_SESAME:;
+        case eos_planetary_id_SESAME_water:
+          return SESAME_soundspeed_from_pressure(density, P, &eos.SESAME_water);
+          break;
 
-      /* Select the material */
-      switch (mat_id) {
-        case eos_planetary_id_SESAME_iron:
-          return SESAME_soundspeed_from_pressure(density, P, &eos.SESAME_iron);
+        case eos_planetary_id_SS08_water:
+          return SESAME_soundspeed_from_pressure(density, P, &eos.SS08_water);
           break;
 
         default:
@@ -1089,6 +1039,10 @@ __attribute__((always_inline)) INLINE static void eos_init(
   char HM80_HHe_table_file[PARSER_MAX_LINE_SIZE];
   char HM80_ice_table_file[PARSER_MAX_LINE_SIZE];
   char HM80_rock_table_file[PARSER_MAX_LINE_SIZE];
+  char SESAME_iron_table_file[PARSER_MAX_LINE_SIZE];
+  char SESAME_basalt_table_file[PARSER_MAX_LINE_SIZE];
+  char SESAME_water_table_file[PARSER_MAX_LINE_SIZE];
+  char SS08_water_table_file[PARSER_MAX_LINE_SIZE];
 
   // Set the parameters and material IDs, load tables, etc. for each material
   // and convert to internal units
@@ -1116,30 +1070,49 @@ __attribute__((always_inline)) INLINE static void eos_init(
     parser_get_param_string(params, "EoS:planetary_HM80_rock_table_file",
                             HM80_rock_table_file);
 
-    load_HM80_table(&e->HM80_HHe, HM80_HHe_table_file);
-    load_HM80_table(&e->HM80_ice, HM80_ice_table_file);
-    load_HM80_table(&e->HM80_rock, HM80_rock_table_file);
+    load_table_HM80(&e->HM80_HHe, HM80_HHe_table_file);
+    load_table_HM80(&e->HM80_ice, HM80_ice_table_file);
+    load_table_HM80(&e->HM80_rock, HM80_rock_table_file);
+
+    prepare_table_HM80(&e->HM80_HHe);
+    prepare_table_HM80(&e->HM80_ice);
+    prepare_table_HM80(&e->HM80_rock);
 
     convert_units_HM80(&e->HM80_HHe, us);
     convert_units_HM80(&e->HM80_ice, us);
     convert_units_HM80(&e->HM80_rock, us);
   }
 
-  // ANEOS
-  if (parser_get_opt_param_int(params, "EoS:planetary_use_ANEOS", 0)) {
-    set_ANEOS_iron(&e->ANEOS_iron, eos_planetary_id_ANEOS_iron);
-    set_MANEOS_forsterite(&e->MANEOS_forsterite,
-                          eos_planetary_id_MANEOS_forsterite);
-
-    convert_units_ANEOS(&e->ANEOS_iron, us);
-    convert_units_ANEOS(&e->MANEOS_forsterite, us);
-  }
-
   // SESAME
   if (parser_get_opt_param_int(params, "EoS:planetary_use_SESAME", 0)) {
     set_SESAME_iron(&e->SESAME_iron, eos_planetary_id_SESAME_iron);
+    set_SESAME_basalt(&e->SESAME_basalt, eos_planetary_id_SESAME_basalt);
+    set_SESAME_water(&e->SESAME_water, eos_planetary_id_SESAME_water);
+    set_SS08_water(&e->SESAME_water, eos_planetary_id_SS08_water);
+
+    parser_get_param_string(params, "EoS:planetary_SESAME_iron_table_file",
+                            SESAME_iron_table_file);
+    parser_get_param_string(params, "EoS:planetary_SESAME_basalt_table_file",
+                            SESAME_basalt_table_file);
+    parser_get_param_string(params, "EoS:planetary_SESAME_water_table_file",
+                            SESAME_water_table_file);
+    parser_get_param_string(params, "EoS:planetary_SS08_water_table_file",
+                            SS08_water_table_file);
+
+    load_table_SESAME(&e->SESAME_iron, SESAME_iron_table_file);
+    load_table_SESAME(&e->SESAME_basalt, SESAME_basalt_table_file);
+    load_table_SESAME(&e->SESAME_water, SESAME_water_table_file);
+    load_table_SESAME(&e->SS08_water, SS08_water_table_file);
+
+    prepare_table_SESAME(&e->SESAME_iron);
+    prepare_table_SESAME(&e->SESAME_basalt);
+    prepare_table_SESAME(&e->SESAME_water);
+    prepare_table_SESAME(&e->SS08_water);
 
     convert_units_SESAME(&e->SESAME_iron, us);
+    convert_units_SESAME(&e->SESAME_basalt, us);
+    convert_units_SESAME(&e->SESAME_water, us);
+    convert_units_SESAME(&e->SS08_water, us);
   }
 }
 
diff --git a/src/equation_of_state/planetary/get_eos_tables.sh b/src/equation_of_state/planetary/get_eos_tables.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c0a751252bb060341a01ac70320a16251069a84e
--- /dev/null
+++ b/src/equation_of_state/planetary/get_eos_tables.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# Download the tables of the publicly available planetary equations of state
+wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/EoS/planetary_HM80_HHe.txt
+wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/EoS/planetary_HM80_ice.txt
+wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/EoS/planetary_HM80_rock.txt
+
+mv planetary_HM80_HHe.txt ../../../examples/
+mv planetary_HM80_ice.txt ../../../examples/
+mv planetary_HM80_rock.txt ../../../examples/
diff --git a/src/equation_of_state/planetary/hm80.h b/src/equation_of_state/planetary/hm80.h
index 0131bab6c447e5a8898e29e13dc3f8f6e1c897c6..5e80c240018756cb57cc8974df4974a6cc53724a 100644
--- a/src/equation_of_state/planetary/hm80.h
+++ b/src/equation_of_state/planetary/hm80.h
@@ -41,75 +41,80 @@
 
 // Hubbard & MacFarlane (1980) parameters
 struct HM80_params {
-  float *table_P_rho_u;
+  float *table_log_P_rho_u;
   int num_rho, num_u;
   float log_rho_min, log_rho_max, log_rho_step, inv_log_rho_step, log_u_min,
-      log_u_max, log_u_step, inv_log_u_step, bulk_mod;
+      log_u_max, log_u_step, inv_log_u_step, bulk_mod, P_min_for_c_min;
   enum eos_planetary_material_id mat_id;
 };
 
-// Parameter values for each material (cgs units)
+// Parameter values for each material (SI units)
 INLINE static void set_HM80_HHe(struct HM80_params *mat,
                                 enum eos_planetary_material_id mat_id) {
   mat->mat_id = mat_id;
-  mat->num_rho = 100;
-  mat->num_u = 100;
-  mat->log_rho_min = -9.2103404f;
-  mat->log_rho_max = 1.6094379f;
-  mat->log_rho_step = 0.1092907f;
-  mat->log_u_min = 9.2103404f;
-  mat->log_u_max = 22.3327037f;
-  mat->log_u_step = 0.1325491f;
-  mat->bulk_mod = 0;
-
-  mat->inv_log_rho_step = 1.f / mat->log_rho_step;
-  mat->inv_log_u_step = 1.f / mat->log_u_step;
+  mat->bulk_mod = 0.f;
+  mat->P_min_for_c_min = 1e3f;
 }
 INLINE static void set_HM80_ice(struct HM80_params *mat,
                                 enum eos_planetary_material_id mat_id) {
   mat->mat_id = mat_id;
-  mat->num_rho = 200;
-  mat->num_u = 200;
-  mat->log_rho_min = -6.9077553f;
-  mat->log_rho_max = 2.7080502f;
-  mat->log_rho_step = 0.0483206f;
-  mat->log_u_min = 6.9077553f;
-  mat->log_u_max = 22.3327037f;
-  mat->log_u_step = 0.0775123f;
-  mat->bulk_mod = 2.0e10f;
-
-  mat->inv_log_rho_step = 1.f / mat->log_rho_step;
-  mat->inv_log_u_step = 1.f / mat->log_u_step;
+  mat->bulk_mod = 2.0e9f;
+  mat->P_min_for_c_min = 0.f;
 }
 INLINE static void set_HM80_rock(struct HM80_params *mat,
                                  enum eos_planetary_material_id mat_id) {
   mat->mat_id = mat_id;
-  mat->num_rho = 100;
-  mat->num_u = 100;
-  mat->log_rho_min = -6.9077553f;
-  mat->log_rho_max = 2.9957323f;
-  mat->log_rho_step = 0.1000352f;
-  mat->log_u_min = 9.2103404f;
-  mat->log_u_max = 20.7232658f;
-  mat->log_u_step = 0.1162922f;
-  mat->bulk_mod = 3.49e11f;
-
-  mat->inv_log_rho_step = 1.f / mat->log_rho_step;
-  mat->inv_log_u_step = 1.f / mat->log_u_step;
+  mat->bulk_mod = 3.49e10f;
+  mat->P_min_for_c_min = 0.f;
 }
 
 // Read the table from file
-INLINE static void load_HM80_table(struct HM80_params *mat, char *table_file) {
-  // Allocate table memory
-  mat->table_P_rho_u =
-      (float *)malloc(mat->num_rho * mat->num_u * sizeof(float *));
+INLINE static void load_table_HM80(struct HM80_params *mat, char *table_file) {
+
+  /* File contents:
+  header (four lines)
+  log_rho_min  log_rho_max  num_rho  log_u_min  log_u_max  num_u  (SI)
+  P_0_0   P_0_1   ...     P_0_num_u           # Array of pressures (Pa)
+  P_1_0   ...     ...     P_1_num_u
+  ...     ...     ...     ...
+  P_num_rho_0     ...     P_num_rho_num_u
+  T_0_0   T_0_1   ...     T_0_num_u           # Array of temperatures (K)
+  T_1_0   ...     ...     T_1_num_u
+  ...     ...     ...     ...
+  T_num_rho_0     ...     T_num_rho_num_u
+  */
 
   // Load table contents from file
   FILE *f = fopen(table_file, "r");
   int c;
-  for (int i = 0; i < mat->num_rho; i++) {
-    for (int j = 0; j < mat->num_u; j++) {
-      c = fscanf(f, "%f", &mat->table_P_rho_u[i * mat->num_rho + j]);
+
+  // Ignore header lines
+  char buffer[100];
+  for (int i = 0; i < 4; i++) {
+    if (fgets(buffer, 100, f) == NULL)
+      error("Something incorrect happening with the file header.");
+  }
+
+  // Table properties
+  c = fscanf(f, "%f %f %d %f %f %d", &mat->log_rho_min, &mat->log_rho_max,
+             &mat->num_rho, &mat->log_u_min, &mat->log_u_max, &mat->num_u);
+  if (c != 6) {
+    error("Failed to read EOS table %s", table_file);
+  }
+  mat->log_rho_step =
+      (mat->log_rho_max - mat->log_rho_min) / (mat->num_rho - 1);
+  mat->log_u_step = (mat->log_u_max - mat->log_u_min) / (mat->num_u - 1);
+  mat->inv_log_rho_step = 1.f / mat->log_rho_step;
+  mat->inv_log_u_step = 1.f / mat->log_u_step;
+
+  // Allocate table memory
+  mat->table_log_P_rho_u =
+      (float *)malloc(mat->num_rho * mat->num_u * sizeof(float));
+
+  // Pressures (not log yet)
+  for (int i_rho = 0; i_rho < mat->num_rho; i_rho++) {
+    for (int i_u = 0; i_u < mat->num_u; i_u++) {
+      c = fscanf(f, "%f", &mat->table_log_P_rho_u[i_rho * mat->num_u + i_u]);
       if (c != 1) {
         error("Failed to read EOS table");
       }
@@ -118,33 +123,49 @@ INLINE static void load_HM80_table(struct HM80_params *mat, char *table_file) {
   fclose(f);
 }
 
-// Convert from cgs to internal units
+// Misc. modifications
+INLINE static void prepare_table_HM80(struct HM80_params *mat) {
+
+  // Convert pressures to log(pressure)
+  for (int i_rho = 0; i_rho < mat->num_rho; i_rho++) {
+    for (int i_u = 0; i_u < mat->num_u; i_u++) {
+      mat->table_log_P_rho_u[i_rho * mat->num_u + i_u] =
+          logf(mat->table_log_P_rho_u[i_rho * mat->num_u + i_u]);
+    }
+  }
+}
+
+// Convert to internal units
 INLINE static void convert_units_HM80(struct HM80_params *mat,
                                       const struct unit_system *us) {
-  const float Mbar_to_Ba = 1e12f;    // Convert Megabar to Barye
-  const float J_kg_to_erg_g = 1e4f;  // Convert J/kg to erg/g
+  struct unit_system si;
+  units_init_si(&si);
 
-  // Table densities in cgs
-  mat->log_rho_min -= logf(units_cgs_conversion_factor(us, UNIT_CONV_DENSITY));
-  mat->log_rho_max -= logf(units_cgs_conversion_factor(us, UNIT_CONV_DENSITY));
+  // All table values in SI
+  mat->log_rho_min += logf(units_cgs_conversion_factor(&si, UNIT_CONV_DENSITY) /
+                           units_cgs_conversion_factor(us, UNIT_CONV_DENSITY));
+  mat->log_rho_max += logf(units_cgs_conversion_factor(&si, UNIT_CONV_DENSITY) /
+                           units_cgs_conversion_factor(us, UNIT_CONV_DENSITY));
 
-  // Table energies in SI
   mat->log_u_min +=
-      logf(J_kg_to_erg_g /
+      logf(units_cgs_conversion_factor(&si, UNIT_CONV_ENERGY_PER_UNIT_MASS) /
            units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS));
   mat->log_u_max +=
-      logf(J_kg_to_erg_g /
+      logf(units_cgs_conversion_factor(&si, UNIT_CONV_ENERGY_PER_UNIT_MASS) /
            units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS));
 
-  // Table Pressures in Mbar
-  for (int i = 0; i < mat->num_rho; i++) {
-    for (int j = 0; j < mat->num_u; j++) {
-      mat->table_P_rho_u[i * mat->num_rho + j] *=
-          Mbar_to_Ba / units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
+  for (int i_rho = 0; i_rho < mat->num_rho; i_rho++) {
+    for (int i_u = 0; i_u < mat->num_u; i_u++) {
+      mat->table_log_P_rho_u[i_rho * mat->num_u + i_u] +=
+          logf(units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE) /
+               units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE));
     }
   }
 
-  mat->bulk_mod /= units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
+  mat->bulk_mod *= units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE) /
+                   units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
+  mat->P_min_for_c_min *= units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE) /
+                          units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
 }
 
 // gas_internal_energy_from_entropy
@@ -153,7 +174,7 @@ INLINE static float HM80_internal_energy_from_entropy(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_pressure_from_entropy
@@ -162,7 +183,7 @@ INLINE static float HM80_pressure_from_entropy(float density, float entropy,
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_entropy_from_pressure
@@ -171,7 +192,7 @@ INLINE static float HM80_entropy_from_pressure(float density, float pressure,
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_soundspeed_from_entropy
@@ -180,75 +201,62 @@ INLINE static float HM80_soundspeed_from_entropy(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_entropy_from_internal_energy
 INLINE static float HM80_entropy_from_internal_energy(
     float density, float u, const struct HM80_params *mat) {
 
-  return 0;
+  return 0.f;
 }
 
 // gas_pressure_from_internal_energy
 INLINE static float HM80_pressure_from_internal_energy(
     float density, float u, const struct HM80_params *mat) {
 
-  float P;
+  float log_P, log_P_1, log_P_2, log_P_3, log_P_4;
 
   if (u <= 0.f) {
     return 0.f;
   }
 
-  int rho_idx, u_idx;
+  int idx_rho, idx_u;
   float intp_rho, intp_u;
   const float log_rho = logf(density);
   const float log_u = logf(u);
 
-  // 2D interpolation (linear in log(rho), log(u)) to find P(rho, u)
-  rho_idx = floorf((log_rho - mat->log_rho_min) * mat->inv_log_rho_step);
-  u_idx = floorf((log_u - mat->log_u_min) * mat->inv_log_u_step);
+  // 2D interpolation (bilinear with log(rho), log(u)) to find P(rho, u)
+  idx_rho = floor((log_rho - mat->log_rho_min) * mat->inv_log_rho_step);
+  idx_u = floor((log_u - mat->log_u_min) * mat->inv_log_u_step);
 
-  intp_rho = (log_rho - mat->log_rho_min - rho_idx * mat->log_rho_step) *
-             mat->inv_log_rho_step;
-  intp_u =
-      (log_u - mat->log_u_min - u_idx * mat->log_u_step) * mat->inv_log_u_step;
-
-  // Return zero pressure if below the table minimum/a
-  // Extrapolate the pressure for low densities
-  if (rho_idx < 0) {  // Too-low rho
-    P = expf(logf((1 - intp_u) * mat->table_P_rho_u[u_idx] +
-                  intp_u * mat->table_P_rho_u[u_idx + 1]) +
-             log_rho - mat->log_rho_min);
-    if (u_idx < 0) {  // and too-low u
-      P = 0.f;
-    }
-  } else if (u_idx < 0) {  // Too-low u
-    P = 0.f;
+  // If outside the table then extrapolate from the edge and edge-but-one values
+  if (idx_rho <= -1) {
+    idx_rho = 0;
+  } else if (idx_rho >= mat->num_rho - 1) {
+    idx_rho = mat->num_rho - 2;
   }
-  // Return an edge value if above the table maximum/a
-  else if (rho_idx >= mat->num_rho - 1) {  // Too-high rho
-    if (u_idx >= mat->num_u - 1) {         // and too-high u
-      P = mat->table_P_rho_u[(mat->num_rho - 1) * mat->num_u + mat->num_u - 1];
-    } else {
-      P = mat->table_P_rho_u[(mat->num_rho - 1) * mat->num_u + u_idx];
-    }
-  } else if (u_idx >= mat->num_u - 1) {  // Too-high u
-    P = mat->table_P_rho_u[rho_idx * mat->num_u + mat->num_u - 1];
-  }
-  // Normal interpolation within the table
-  else {
-    P = (1.f - intp_rho) *
-            ((1.f - intp_u) * mat->table_P_rho_u[rho_idx * mat->num_u + u_idx] +
-             intp_u * mat->table_P_rho_u[rho_idx * mat->num_u + u_idx + 1]) +
-        intp_rho *
-            ((1 - intp_u) *
-                 mat->table_P_rho_u[(rho_idx + 1) * mat->num_u + u_idx] +
-             intp_u *
-                 mat->table_P_rho_u[(rho_idx + 1) * mat->num_u + u_idx + 1]);
+  if (idx_u <= -1) {
+    idx_u = 0;
+  } else if (idx_u >= mat->num_u - 1) {
+    idx_u = mat->num_u - 2;
   }
 
-  return P;
+  intp_rho = (log_rho - mat->log_rho_min - idx_rho * mat->log_rho_step) *
+             mat->inv_log_rho_step;
+  intp_u =
+      (log_u - mat->log_u_min - idx_u * mat->log_u_step) * mat->inv_log_u_step;
+
+  // Table values
+  log_P_1 = mat->table_log_P_rho_u[idx_rho * mat->num_u + idx_u];
+  log_P_2 = mat->table_log_P_rho_u[idx_rho * mat->num_u + idx_u + 1];
+  log_P_3 = mat->table_log_P_rho_u[(idx_rho + 1) * mat->num_u + idx_u];
+  log_P_4 = mat->table_log_P_rho_u[(idx_rho + 1) * mat->num_u + idx_u + 1];
+
+  log_P = (1.f - intp_rho) * ((1.f - intp_u) * log_P_1 + intp_u * log_P_2) +
+          intp_rho * ((1.f - intp_u) * log_P_3 + intp_u * log_P_4);
+
+  return expf(log_P);
 }
 
 // gas_internal_energy_from_pressure
@@ -257,7 +265,7 @@ INLINE static float HM80_internal_energy_from_pressure(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_soundspeed_from_internal_energy
@@ -274,6 +282,10 @@ INLINE static float HM80_soundspeed_from_internal_energy(
   else {
     P = HM80_pressure_from_internal_energy(density, u, mat);
     c = sqrtf(hydro_gamma * P / density);
+
+    if (c <= 0) {
+      c = sqrtf(hydro_gamma * mat->P_min_for_c_min / density);
+    }
   }
 
   return c;
@@ -283,18 +295,9 @@ INLINE static float HM80_soundspeed_from_internal_energy(
 INLINE static float HM80_soundspeed_from_pressure(
     float density, float P, const struct HM80_params *mat) {
 
-  float c;
-
-  // Bulk modulus
-  if (mat->bulk_mod != 0) {
-    c = sqrtf(mat->bulk_mod / density);
-  }
-  // Ideal gas
-  else {
-    c = sqrtf(hydro_gamma * P / density);
-  }
+  error("This EOS function is not yet implemented!");
 
-  return c;
+  return 0.f;
 }
 
 #endif /* SWIFT_HUBBARD_MACFARLANE_EQUATION_OF_STATE_H */
diff --git a/src/equation_of_state/planetary/sesame.h b/src/equation_of_state/planetary/sesame.h
index 76574c2ad00282a82649705cd8a2b5a1b428d867..d958c9b9d09ffe37eefd77ad0384d85bf8c055dd 100644
--- a/src/equation_of_state/planetary/sesame.h
+++ b/src/equation_of_state/planetary/sesame.h
@@ -40,21 +40,229 @@
 #include "inline.h"
 #include "physical_constants.h"
 #include "units.h"
+#include "utilities.h"
 
 // SESAME parameters
 struct SESAME_params {
+  float *table_log_rho;
+  float *table_log_u_rho_T;
+  float *table_P_rho_T;
+  float *table_c_rho_T;
+  float *table_s_rho_T;
+  int num_rho, num_T;
+  float P_tiny, c_tiny;
   enum eos_planetary_material_id mat_id;
 };
 
 // Parameter values for each material (cgs units)
 INLINE static void set_SESAME_iron(struct SESAME_params *mat,
                                    enum eos_planetary_material_id mat_id) {
+  // SESAME 2140
   mat->mat_id = mat_id;
 }
+INLINE static void set_SESAME_basalt(struct SESAME_params *mat,
+                                     enum eos_planetary_material_id mat_id) {
+  // SESAME 7530
+  mat->mat_id = mat_id;
+}
+INLINE static void set_SESAME_water(struct SESAME_params *mat,
+                                    enum eos_planetary_material_id mat_id) {
+  // SESAME 7154
+  mat->mat_id = mat_id;
+}
+INLINE static void set_SS08_water(struct SESAME_params *mat,
+                                  enum eos_planetary_material_id mat_id) {
+  // Senft & Stewart (2008)
+  mat->mat_id = mat_id;
+}
+
+// Read the tables from file
+INLINE static void load_table_SESAME(struct SESAME_params *mat,
+                                     char *table_file) {
+
+  // Load table contents from file
+  FILE *f = fopen(table_file, "r");
+  int c;
+
+  // Ignore header lines
+  char buffer[100];
+  for (int i = 0; i < 5; i++) {
+    if (fgets(buffer, 100, f) == NULL)
+      error("Something incorrect happening with the file header.");
+  }
+  float ignore;
+
+  // Table properties
+  c = fscanf(f, "%d %d", &mat->num_rho, &mat->num_T);
+  if (c != 2) {
+    error("Failed to read EOS table %s", table_file);
+  }
+
+  // Ignore the first elements of rho = 0, T = 0
+  mat->num_rho--;
+  mat->num_T--;
+
+  // Allocate table memory
+  mat->table_log_rho = (float *)malloc(mat->num_rho * sizeof(float));
+  mat->table_log_u_rho_T =
+      (float *)malloc(mat->num_rho * mat->num_T * sizeof(float));
+  mat->table_P_rho_T =
+      (float *)malloc(mat->num_rho * mat->num_T * sizeof(float));
+  mat->table_c_rho_T =
+      (float *)malloc(mat->num_rho * mat->num_T * sizeof(float));
+  mat->table_s_rho_T =
+      (float *)malloc(mat->num_rho * mat->num_T * sizeof(float));
+
+  // Densities (not log yet)
+  for (int i_rho = -1; i_rho < mat->num_rho; i_rho++) {
+    // Ignore the first elements of rho = 0, T = 0
+    if (i_rho == -1) {
+      c = fscanf(f, "%f", &ignore);
+      if (c != 1) {
+        error("Failed to read EOS table %s", table_file);
+      }
+    } else {
+      c = fscanf(f, "%f", &mat->table_log_rho[i_rho]);
+      if (c != 1) {
+        error("Failed to read EOS table %s", table_file);
+      }
+    }
+  }
+
+  // Temperatures (ignored)
+  for (int i_T = -1; i_T < mat->num_T; i_T++) {
+    c = fscanf(f, "%f", &ignore);
+    if (c != 1) {
+      error("Failed to read EOS table %s", table_file);
+    }
+  }
+
+  // Sp. int. energies (not log yet), pressures, sound speeds, and entropies
+  for (int i_T = -1; i_T < mat->num_T; i_T++) {
+    for (int i_rho = -1; i_rho < mat->num_rho; i_rho++) {
+      // Ignore the first elements of rho = 0, T = 0
+      if ((i_T == -1) || (i_rho == -1)) {
+        c = fscanf(f, "%f %f %f %f", &ignore, &ignore, &ignore, &ignore);
+        if (c != 4) {
+          error("Failed to read EOS table %s", table_file);
+        }
+      } else {
+        c = fscanf(f, "%f %f %f %f",
+                   &mat->table_log_u_rho_T[i_rho * mat->num_T + i_T],
+                   &mat->table_P_rho_T[i_rho * mat->num_T + i_T],
+                   &mat->table_c_rho_T[i_rho * mat->num_T + i_T],
+                   &mat->table_s_rho_T[i_rho * mat->num_T + i_T]);
+        if (c != 4) {
+          error("Failed to read EOS table %s", table_file);
+        }
+      }
+    }
+  }
+
+  fclose(f);
+}
 
-// Convert from cgs to internal units
+// Misc. modifications
+INLINE static void prepare_table_SESAME(struct SESAME_params *mat) {
+
+  // Convert densities to log(density)
+  for (int i_rho = 0; i_rho < mat->num_rho; i_rho++) {
+    mat->table_log_rho[i_rho] = logf(mat->table_log_rho[i_rho]);
+  }
+
+  // Convert sp. int. energies to log(sp. int. energy)
+  for (int i_rho = 0; i_rho < mat->num_rho; i_rho++) {
+    for (int i_T = 0; i_T < mat->num_T; i_T++) {
+      // If not positive then set very small for the log
+      if (mat->table_log_u_rho_T[i_rho * mat->num_T + i_T] <= 0) {
+        mat->table_log_u_rho_T[i_rho * mat->num_T + i_T] = 1.f;
+      }
+
+      mat->table_log_u_rho_T[i_rho * mat->num_T + i_T] =
+          logf(mat->table_log_u_rho_T[i_rho * mat->num_T + i_T]);
+    }
+  }
+
+  // Tiny pressure and soundspeed, initialise in the middle
+  mat->P_tiny =
+      mat->table_P_rho_T[mat->num_rho / 2 * mat->num_T + mat->num_T / 2];
+  mat->c_tiny =
+      mat->table_c_rho_T[mat->num_rho / 2 * mat->num_T + mat->num_T / 2];
+
+  // Enforce that the 1D arrays of u (at each rho) are monotonic
+  // This is necessary because, for some high-density u slices at very low T,
+  // u decreases (very slightly) with T, which makes the interpolation fail
+  for (int i_rho = 0; i_rho < mat->num_rho; i_rho++) {
+    for (int i_T = mat->num_T - 1; i_T > 0; i_T--) {
+
+      // If the one-lower-T u is greater than this u
+      if (mat->table_log_u_rho_T[i_rho * mat->num_T + i_T] <
+          mat->table_log_u_rho_T[i_rho * mat->num_T + i_T - 1]) {
+
+        // Replace it and all elements below it with that value
+        for (int j_u = 0; j_u < i_T; j_u++) {
+          mat->table_log_u_rho_T[i_rho * mat->num_T + j_u] =
+              mat->table_log_u_rho_T[i_rho * mat->num_T + i_T];
+        }
+        break;
+      }
+
+      // Smallest positive pressure and sound speed
+      if ((mat->table_P_rho_T[i_rho * mat->num_T + i_T] < mat->P_tiny) &&
+          (mat->table_P_rho_T[i_rho * mat->num_T + i_T] > 0)) {
+        mat->P_tiny = mat->table_P_rho_T[i_rho * mat->num_T + i_T];
+      }
+      if ((mat->table_c_rho_T[i_rho * mat->num_T + i_T] < mat->c_tiny) &&
+          (mat->table_c_rho_T[i_rho * mat->num_T + i_T] > 0)) {
+        mat->c_tiny = mat->table_c_rho_T[i_rho * mat->num_T + i_T];
+      }
+    }
+  }
+
+  // Tiny pressure to allow interpolation near non-positive values
+  mat->P_tiny *= 1e-3f;
+  mat->c_tiny *= 1e-3f;
+}
+
+// Convert to internal units
 INLINE static void convert_units_SESAME(struct SESAME_params *mat,
-                                        const struct unit_system *us) {}
+                                        const struct unit_system *us) {
+
+  struct unit_system si;
+  units_init_si(&si);
+
+  // All table values in SI
+  // Densities (log)
+  for (int i_rho = 0; i_rho < mat->num_rho; i_rho++) {
+    mat->table_log_rho[i_rho] +=
+        logf(units_cgs_conversion_factor(&si, UNIT_CONV_DENSITY) /
+             units_cgs_conversion_factor(us, UNIT_CONV_DENSITY));
+  }
+
+  // Sp. Int. Energies (log), pressures, and sound speeds
+  for (int i_rho = 0; i_rho < mat->num_rho; i_rho++) {
+    for (int i_T = 0; i_T < mat->num_T; i_T++) {
+      mat->table_log_u_rho_T[i_rho * mat->num_T + i_T] += logf(
+          units_cgs_conversion_factor(&si, UNIT_CONV_ENERGY_PER_UNIT_MASS) /
+          units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS));
+      mat->table_P_rho_T[i_rho * mat->num_T + i_T] *=
+          units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE) /
+          units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
+      mat->table_c_rho_T[i_rho * mat->num_T + i_T] *=
+          units_cgs_conversion_factor(&si, UNIT_CONV_SPEED) /
+          units_cgs_conversion_factor(us, UNIT_CONV_SPEED);
+      mat->table_s_rho_T[i_rho * mat->num_T + i_T] *=
+          units_cgs_conversion_factor(&si, UNIT_CONV_ENERGY_PER_UNIT_MASS) /
+          units_cgs_conversion_factor(us, UNIT_CONV_ENTROPY);
+    }
+  }
+
+  // Tiny pressure and sound speed
+  mat->P_tiny *= units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE) /
+                 units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
+  mat->c_tiny *= units_cgs_conversion_factor(&si, UNIT_CONV_SPEED) /
+                 units_cgs_conversion_factor(us, UNIT_CONV_SPEED);
+}
 
 // gas_internal_energy_from_entropy
 INLINE static float SESAME_internal_energy_from_entropy(
@@ -62,7 +270,7 @@ INLINE static float SESAME_internal_energy_from_entropy(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_pressure_from_entropy
@@ -71,7 +279,7 @@ INLINE static float SESAME_pressure_from_entropy(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_entropy_from_pressure
@@ -80,7 +288,7 @@ INLINE static float SESAME_entropy_from_pressure(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_soundspeed_from_entropy
@@ -89,25 +297,109 @@ INLINE static float SESAME_soundspeed_from_entropy(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_entropy_from_internal_energy
 INLINE static float SESAME_entropy_from_internal_energy(
     float density, float u, const struct SESAME_params *mat) {
 
-  error("This EOS function is not yet implemented!");
-
-  return 0;
+  return 0.f;
 }
 
 // gas_pressure_from_internal_energy
 INLINE static float SESAME_pressure_from_internal_energy(
     float density, float u, const struct SESAME_params *mat) {
 
-  error("This EOS function is not yet implemented!");
-
-  return 0;
+  float P, P_1, P_2, P_3, P_4;
+
+  if (u <= 0.f) {
+    return 0.f;
+  }
+
+  int idx_rho, idx_u_1, idx_u_2;
+  float intp_rho, intp_u_1, intp_u_2;
+  const float log_rho = logf(density);
+  const float log_u = logf(u);
+
+  // 2D interpolation (bilinear with log(rho), log(u)) to find P(rho, u)
+  // Density index
+  idx_rho =
+      find_value_in_monot_incr_array(log_rho, mat->table_log_rho, mat->num_rho);
+
+  // Sp. int. energy at this and the next density (in relevant slice of u array)
+  idx_u_1 = find_value_in_monot_incr_array(
+      log_u, mat->table_log_u_rho_T + idx_rho * mat->num_T, mat->num_T);
+  idx_u_2 = find_value_in_monot_incr_array(
+      log_u, mat->table_log_u_rho_T + (idx_rho + 1) * mat->num_T, mat->num_T);
+
+  // If outside the table then extrapolate from the edge and edge-but-one values
+  if (idx_rho <= -1) {
+    idx_rho = 0;
+  } else if (idx_rho >= mat->num_rho) {
+    idx_rho = mat->num_rho - 2;
+  }
+  if (idx_u_1 <= -1) {
+    idx_u_1 = 0;
+  } else if (idx_u_1 >= mat->num_T) {
+    idx_u_1 = mat->num_T - 2;
+  }
+  if (idx_u_2 <= -1) {
+    idx_u_2 = 0;
+  } else if (idx_u_2 >= mat->num_T) {
+    idx_u_2 = mat->num_T - 2;
+  }
+
+  intp_rho = (log_rho - mat->table_log_rho[idx_rho]) /
+             (mat->table_log_rho[idx_rho + 1] - mat->table_log_rho[idx_rho]);
+  intp_u_1 = (log_u - mat->table_log_u_rho_T[idx_rho * mat->num_T + idx_u_1]) /
+             (mat->table_log_u_rho_T[idx_rho * mat->num_T + (idx_u_1 + 1)] -
+              mat->table_log_u_rho_T[idx_rho * mat->num_T + idx_u_1]);
+  intp_u_2 =
+      (log_u - mat->table_log_u_rho_T[(idx_rho + 1) * mat->num_T + idx_u_2]) /
+      (mat->table_log_u_rho_T[(idx_rho + 1) * mat->num_T + (idx_u_2 + 1)] -
+       mat->table_log_u_rho_T[(idx_rho + 1) * mat->num_T + idx_u_2]);
+
+  // Table values
+  P_1 = mat->table_P_rho_T[idx_rho * mat->num_T + idx_u_1];
+  P_2 = mat->table_P_rho_T[idx_rho * mat->num_T + idx_u_1 + 1];
+  P_3 = mat->table_P_rho_T[(idx_rho + 1) * mat->num_T + idx_u_2];
+  P_4 = mat->table_P_rho_T[(idx_rho + 1) * mat->num_T + idx_u_2 + 1];
+
+  // If more than two table values are non-positive then return zero
+  int num_non_pos = 0;
+  if (P_1 <= 0.f) num_non_pos++;
+  if (P_2 <= 0.f) num_non_pos++;
+  if (P_3 <= 0.f) num_non_pos++;
+  if (P_4 <= 0.f) num_non_pos++;
+  if (num_non_pos > 2) {
+    return 0.f;
+  }
+  // If just one or two are non-positive then replace them with a tiny value
+  else if (num_non_pos > 0) {
+    // Unless already trying to extrapolate in which case return zero
+    if ((intp_rho < 0.f) || (intp_u_1 < 0.f) || (intp_u_2 < 0.f)) {
+      return 0.f;
+    }
+    if (P_1 <= 0.f) P_1 = mat->P_tiny;
+    if (P_2 <= 0.f) P_2 = mat->P_tiny;
+    if (P_3 <= 0.f) P_3 = mat->P_tiny;
+    if (P_4 <= 0.f) P_4 = mat->P_tiny;
+  }
+
+  // Interpolate with the log values
+  P_1 = logf(P_1);
+  P_2 = logf(P_2);
+  P_3 = logf(P_3);
+  P_4 = logf(P_4);
+
+  P = (1.f - intp_rho) * ((1.f - intp_u_1) * P_1 + intp_u_1 * P_2) +
+      intp_rho * ((1.f - intp_u_2) * P_3 + intp_u_2 * P_4);
+
+  // Convert back from log
+  P = expf(P);
+
+  return P;
 }
 
 // gas_internal_energy_from_pressure
@@ -116,16 +408,102 @@ INLINE static float SESAME_internal_energy_from_pressure(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_soundspeed_from_internal_energy
 INLINE static float SESAME_soundspeed_from_internal_energy(
     float density, float u, const struct SESAME_params *mat) {
 
-  error("This EOS function is not yet implemented!");
-
-  return 0;
+  float c, c_1, c_2, c_3, c_4;
+
+  if (u <= 0.f) {
+    return 0.f;
+  }
+
+  int idx_rho, idx_u_1, idx_u_2;
+  float intp_rho, intp_u_1, intp_u_2;
+  const float log_rho = logf(density);
+  const float log_u = logf(u);
+
+  // 2D interpolation (bilinear with log(rho), log(u)) to find c(rho, u)
+  // Density index
+  idx_rho =
+      find_value_in_monot_incr_array(log_rho, mat->table_log_rho, mat->num_rho);
+
+  // Sp. int. energy at this and the next density (in relevant slice of u array)
+  idx_u_1 = find_value_in_monot_incr_array(
+      log_u, mat->table_log_u_rho_T + idx_rho * mat->num_T, mat->num_T);
+  idx_u_2 = find_value_in_monot_incr_array(
+      log_u, mat->table_log_u_rho_T + (idx_rho + 1) * mat->num_T, mat->num_T);
+
+  // If outside the table then extrapolate from the edge and edge-but-one values
+  if (idx_rho <= -1) {
+    idx_rho = 0;
+  } else if (idx_rho >= mat->num_rho) {
+    idx_rho = mat->num_rho - 2;
+  }
+  if (idx_u_1 <= -1) {
+    idx_u_1 = 0;
+  } else if (idx_u_1 >= mat->num_T) {
+    idx_u_1 = mat->num_T - 2;
+  }
+  if (idx_u_2 <= -1) {
+    idx_u_2 = 0;
+  } else if (idx_u_2 >= mat->num_T) {
+    idx_u_2 = mat->num_T - 2;
+  }
+
+  intp_rho = (log_rho - mat->table_log_rho[idx_rho]) /
+             (mat->table_log_rho[idx_rho + 1] - mat->table_log_rho[idx_rho]);
+  intp_u_1 = (log_u - mat->table_log_u_rho_T[idx_rho * mat->num_T + idx_u_1]) /
+             (mat->table_log_u_rho_T[idx_rho * mat->num_T + (idx_u_1 + 1)] -
+              mat->table_log_u_rho_T[idx_rho * mat->num_T + idx_u_1]);
+  intp_u_2 =
+      (log_u - mat->table_log_u_rho_T[(idx_rho + 1) * mat->num_T + idx_u_2]) /
+      (mat->table_log_u_rho_T[(idx_rho + 1) * mat->num_T + (idx_u_2 + 1)] -
+       mat->table_log_u_rho_T[(idx_rho + 1) * mat->num_T + idx_u_2]);
+
+  // Table values
+  c_1 = mat->table_c_rho_T[idx_rho * mat->num_T + idx_u_1];
+  c_2 = mat->table_c_rho_T[idx_rho * mat->num_T + idx_u_1 + 1];
+  c_3 = mat->table_c_rho_T[(idx_rho + 1) * mat->num_T + idx_u_2];
+  c_4 = mat->table_c_rho_T[(idx_rho + 1) * mat->num_T + idx_u_2 + 1];
+
+  // If more than two table values are non-positive then return zero
+  int num_non_pos = 0;
+  if (c_1 <= 0.f) num_non_pos++;
+  if (c_2 <= 0.f) num_non_pos++;
+  if (c_3 <= 0.f) num_non_pos++;
+  if (c_4 <= 0.f) num_non_pos++;
+  if (num_non_pos > 2) {
+    return mat->c_tiny;
+  }
+  // If just one or two are non-positive then replace them with a tiny value
+  else if (num_non_pos > 0) {
+    // Unless already trying to extrapolate in which case return zero
+    if ((intp_rho < 0.f) || (intp_u_1 < 0.f) || (intp_u_2 < 0.f)) {
+      return mat->c_tiny;
+    }
+    if (c_1 <= 0.f) c_1 = mat->c_tiny;
+    if (c_2 <= 0.f) c_2 = mat->c_tiny;
+    if (c_3 <= 0.f) c_3 = mat->c_tiny;
+    if (c_4 <= 0.f) c_4 = mat->c_tiny;
+  }
+
+  // Interpolate with the log values
+  c_1 = logf(c_1);
+  c_2 = logf(c_2);
+  c_3 = logf(c_3);
+  c_4 = logf(c_4);
+
+  c = (1.f - intp_rho) * ((1.f - intp_u_1) * c_1 + intp_u_1 * c_2) +
+      intp_rho * ((1.f - intp_u_2) * c_3 + intp_u_2 * c_4);
+
+  // Convert back from log
+  c = expf(c);
+
+  return c;
 }
 
 // gas_soundspeed_from_pressure
@@ -134,7 +512,7 @@ INLINE static float SESAME_soundspeed_from_pressure(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 #endif /* SWIFT_SESAME_EQUATION_OF_STATE_H */
diff --git a/src/equation_of_state/planetary/tillotson.h b/src/equation_of_state/planetary/tillotson.h
index d5b6d5c35d5edf9e114fe7f010c4f5b1e2327a83..1a4210699380b3b0398506dde7fce6ca8055e4dc 100644
--- a/src/equation_of_state/planetary/tillotson.h
+++ b/src/equation_of_state/planetary/tillotson.h
@@ -41,22 +41,22 @@
 
 // Tillotson parameters
 struct Til_params {
-  float rho_0, a, b, A, B, E_0, E_iv, E_cv, alpha, beta, eta_min, P_min;
+  float rho_0, a, b, A, B, u_0, u_iv, u_cv, alpha, beta, eta_min, P_min;
   enum eos_planetary_material_id mat_id;
 };
 
-// Parameter values for each material (cgs units)
+// Parameter values for each material (SI units)
 INLINE static void set_Til_iron(struct Til_params *mat,
                                 enum eos_planetary_material_id mat_id) {
   mat->mat_id = mat_id;
-  mat->rho_0 = 7.800f;
+  mat->rho_0 = 7800.0f;
   mat->a = 0.5f;
   mat->b = 1.5f;
-  mat->A = 1.28e12f;
-  mat->B = 1.05e12f;
-  mat->E_0 = 9.5e10f;
-  mat->E_iv = 2.4e10f;
-  mat->E_cv = 8.67e10f;
+  mat->A = 1.28e11f;
+  mat->B = 1.05e11f;
+  mat->u_0 = 9.5e9f;
+  mat->u_iv = 2.4e9f;
+  mat->u_cv = 8.67e9f;
   mat->alpha = 5.0f;
   mat->beta = 5.0f;
   mat->eta_min = 0.0f;
@@ -65,14 +65,14 @@ INLINE static void set_Til_iron(struct Til_params *mat,
 INLINE static void set_Til_granite(struct Til_params *mat,
                                    enum eos_planetary_material_id mat_id) {
   mat->mat_id = mat_id;
-  mat->rho_0 = 2.680f;
+  mat->rho_0 = 2680.0f;
   mat->a = 0.5f;
   mat->b = 1.3f;
-  mat->A = 1.8e11f;
-  mat->B = 1.8e11f;
-  mat->E_0 = 1.6e11f;
-  mat->E_iv = 3.5e10f;
-  mat->E_cv = 1.8e11f;
+  mat->A = 1.8e10f;
+  mat->B = 1.8e10f;
+  mat->u_0 = 1.6e10f;
+  mat->u_iv = 3.5e9f;
+  mat->u_cv = 1.8e10f;
   mat->alpha = 5.0f;
   mat->beta = 5.0f;
   mat->eta_min = 0.0f;
@@ -81,30 +81,43 @@ INLINE static void set_Til_granite(struct Til_params *mat,
 INLINE static void set_Til_water(struct Til_params *mat,
                                  enum eos_planetary_material_id mat_id) {
   mat->mat_id = mat_id;
-  mat->rho_0 = 0.998f;
+  mat->rho_0 = 998.0f;
   mat->a = 0.7f;
   mat->b = 0.15f;
-  mat->A = 2.18e10f;
-  mat->B = 1.325e11f;
-  mat->E_0 = 7.0e10f;
-  mat->E_iv = 4.19e9f;
-  mat->E_cv = 2.69e10f;
+  mat->A = 2.18e9f;
+  mat->B = 1.325e10f;
+  mat->u_0 = 7.0e9f;
+  mat->u_iv = 4.19e8f;
+  mat->u_cv = 2.69e9f;
   mat->alpha = 10.0f;
   mat->beta = 5.0f;
-  mat->eta_min = 0.915f;
+  mat->eta_min = 0.9f;
   mat->P_min = 0.0f;
 }
 
-// Convert from cgs to internal units
+// Convert to internal units
 INLINE static void convert_units_Til(struct Til_params *mat,
                                      const struct unit_system *us) {
 
+  struct unit_system si;
+  units_init_si(&si);
+
+  // SI to cgs
+  mat->rho_0 *= units_cgs_conversion_factor(&si, UNIT_CONV_DENSITY);
+  mat->A *= units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE);
+  mat->B *= units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE);
+  mat->u_0 *= units_cgs_conversion_factor(&si, UNIT_CONV_ENERGY_PER_UNIT_MASS);
+  mat->u_iv *= units_cgs_conversion_factor(&si, UNIT_CONV_ENERGY_PER_UNIT_MASS);
+  mat->u_cv *= units_cgs_conversion_factor(&si, UNIT_CONV_ENERGY_PER_UNIT_MASS);
+  mat->P_min *= units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE);
+
+  // cgs to internal
   mat->rho_0 /= units_cgs_conversion_factor(us, UNIT_CONV_DENSITY);
   mat->A /= units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
   mat->B /= units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
-  mat->E_0 /= units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
-  mat->E_iv /= units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
-  mat->E_cv /= units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
+  mat->u_0 /= units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
+  mat->u_iv /= units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
+  mat->u_cv /= units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
   mat->P_min /= units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
 }
 
@@ -114,7 +127,7 @@ INLINE static float Til_internal_energy_from_entropy(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_pressure_from_entropy
@@ -123,7 +136,7 @@ INLINE static float Til_pressure_from_entropy(float density, float entropy,
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_entropy_from_pressure
@@ -132,7 +145,7 @@ INLINE static float Til_entropy_from_pressure(float density, float pressure,
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_soundspeed_from_entropy
@@ -141,14 +154,14 @@ INLINE static float Til_soundspeed_from_entropy(float density, float entropy,
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_entropy_from_internal_energy
 INLINE static float Til_entropy_from_internal_energy(
     float density, float u, const struct Til_params *mat) {
 
-  return 0;
+  return 0.f;
 }
 
 // gas_pressure_from_internal_energy
@@ -156,35 +169,37 @@ INLINE static float Til_pressure_from_internal_energy(
     float density, float u, const struct Til_params *mat) {
 
   const float eta = density / mat->rho_0;
+  const float eta_sq = eta * eta;
   const float mu = eta - 1.f;
   const float nu = 1.f / eta - 1.f;
+  const float w = u / (mat->u_0 * eta_sq) + 1.f;
+  const float w_inv = 1.f / w;
   float P_c, P_e, P;
 
   // Condensed or cold
   if (eta < mat->eta_min) {
     P_c = 0.f;
   } else {
-    P_c = (mat->a + mat->b / (u / (mat->E_0 * eta * eta) + 1.f)) * density * u +
-          mat->A * mu + mat->B * mu * mu;
+    P_c = (mat->a + mat->b * w_inv) * density * u + mat->A * mu +
+          mat->B * mu * mu;
   }
   // Expanded and hot
   P_e = mat->a * density * u +
-        (mat->b * density * u / (u / (mat->E_0 * eta * eta) + 1.f) +
-         mat->A * mu * expf(-mat->beta * nu)) *
+        (mat->b * density * u * w_inv + mat->A * mu * expf(-mat->beta * nu)) *
             expf(-mat->alpha * nu * nu);
 
   // Condensed or cold state
-  if ((1.f < eta) || (u < mat->E_iv)) {
+  if ((1.f < eta) || (u < mat->u_iv)) {
     P = P_c;
   }
   // Expanded and hot state
-  else if ((eta < 1.f) && (mat->E_cv < u)) {
+  else if ((eta < 1.f) && (mat->u_cv < u)) {
     P = P_e;
   }
   // Hybrid state
   else {
-    P = ((u - mat->E_iv) * P_e + (mat->E_cv - u) * P_c) /
-        (mat->E_cv - mat->E_iv);
+    P = ((u - mat->u_iv) * P_e + (mat->u_cv - u) * P_c) /
+        (mat->u_cv - mat->u_iv);
   }
 
   // Minimum pressure
@@ -201,81 +216,78 @@ INLINE static float Til_internal_energy_from_pressure(
 
   error("This EOS function is not yet implemented!");
 
-  return 0;
+  return 0.f;
 }
 
 // gas_soundspeed_from_internal_energy
 INLINE static float Til_soundspeed_from_internal_energy(
     float density, float u, const struct Til_params *mat) {
 
-  //    const float eta = density / mat->rho_0;
-  //    const float mu = eta - 1.f;
-  //    const float nu = 1.f/eta - 1.f;
-  //    float P_c, P_e, P, c_c, c_e, c;
-  //
-  //    // Condensed or cold
-  //    if (eta < mat->eta_min) {
-  //        P_c = 0.f;
-  //    }
-  //    else {
-  //        P_c = (mat->a + mat->b / (u / (mat->E_0 * eta*eta) + 1.f)) * density
-  //        * u
-  //            + mat->A * mu + mat->B * mu*mu;
-  //    }
-  //    c_c = mat->a*u + mat->b*u / ((u / (mat->E_0*eta*eta)+1.f) *
-  //        (u / (mat->E_0*eta*eta)+1.f)) *
-  //        (3.f*(u / (mat->E_0*eta*eta)+1.f) - 2.f) +
-  //        (mat->A + 2.f*mat->B*mu) / mat->rho_0  +  P_c / (rho*rho) *
-  //        (mat->a*rho + mat->b*rho / ((u / (mat->E_0*eta*eta)+1.f) *
-  //        (u / (mat->E_0*eta*eta)+1.f)));
-  //
-  //    c_c = max(c_c, mat->A / mat->rho_0);
-  //
-  //    // Expanded and hot
-  //    P_e = mat->a*density*u + (
-  //        mat->b * density * u / (u / (mat->E_0 * eta*eta) + 1.f)
-  //        + mat->A*mu * expf(-mat->beta * nu)
-  //        ) * expf(-mat->alpha * nu*nu);
-  //
-  //    c_e = (mat->a + mat->b / (u / (mat->E_0*eta*eta)+1.f) *
-  //        expf(-mat->beta*((1.f - eta)/eta)*((1.f - eta)/eta))
-  //        + 1.f)*P_e/rho + mat->A/mat->rho_0
-  //        *expf(-(mat->alpha*((1.f - eta)/eta)+mat->beta *
-  //        ((1.f - eta)/eta)*((1.f - eta)/eta)))*(1.f+mu/(eta*eta)
-  //        *(mat->alpha+2.f*mat->beta*((1.f - eta)/eta)-eta)) +
-  //        mat->b*rho*u/((u / (mat->E_0*eta*eta)+1.f)*
-  //        (u / (mat->E_0*eta*eta)+1.f)*eta*eta)*
-  //        expf(-mat->beta*((1.f - eta)/eta)*((1.f - eta)/eta))*
-  //        (2.f*mat->beta*((1.f - eta)/eta)*(u / (mat->E_0*eta*eta)+1.f) /
-  //         mat->rho_0 + 1.f/(mat->E_0*rho)*(2.f*u-P_e/rho));
-  //
-  //    // Condensed or cold state
-  //    if ((1.f < eta) || (u < mat->E_iv)) {
-  //        c = c_c;
-  //    }
-  //    // Expanded and hot state
-  //    else if ((eta < 1.f) && (mat->E_cv < u)) {
-  //        c = c_e;
-  //    }
-  //    // Hybrid state
-  //    else {
-  //		c = ((u - mat->E_iv)*c_e + (mat->E_cv - u)*c_c) /
-  //            (mat->E_cv - mat->E_iv);
-  //
-  //        c = max(c_c, mat->A / mat->rho0);
-  //    }
-  float c = sqrtf(mat->A / mat->rho_0);
-
-  return c;
+  const float rho_0_inv = 1.f / mat->rho_0;
+  const float eta = density * rho_0_inv;
+  const float rho_inv = 1.f / density;
+  const float eta_sq = eta * eta;
+  const float mu = eta - 1.f;
+  const float nu = 1.f / eta - 1.f;
+  const float w = u / (mat->u_0 * eta_sq) + 1.f;
+  const float w_inv = 1.f / w;
+  const float w_inv_sq = w_inv * w_inv;
+  const float exp_beta = expf(-mat->beta * nu);
+  const float exp_alpha = expf(-mat->alpha * nu * nu);
+  float P_c, P_e, c_sq_c, c_sq_e, c_sq;
+
+  // Condensed or cold
+  if (eta < mat->eta_min) {
+    P_c = 0.f;
+  } else {
+    P_c = (mat->a + mat->b * w_inv) * density * u + mat->A * mu +
+          mat->B * mu * mu;
+  }
+  c_sq_c = P_c * rho_inv * (1.f - mat->a - mat->b * w_inv) +
+           mat->b * (w - 1.f) * w_inv_sq * (2 * u + P_c * rho_inv) +
+           rho_inv * (mat->A + mat->B * (eta_sq - 1.f));
+
+  c_sq_c = fmax(c_sq_c, mat->A * rho_0_inv);
+
+  // Expanded and hot
+  P_e = mat->a * density * u +
+        (mat->b * density * u * w_inv + mat->A * mu * exp_beta) * exp_alpha;
+
+  c_sq_e = P_e * rho_inv * (1.f - mat->a) +
+           (mat->b * density * u / (w * w * eta_sq) *
+                (rho_inv / mat->u_0 * (2 * u - P_e * rho_inv * eta_sq) +
+                 2.f * mat->alpha * nu * rho_0_inv) +
+            mat->A * rho_0_inv *
+                (1 + mu / eta_sq * (mat->beta + 2.f * mat->alpha * nu - eta)) *
+                exp_beta) *
+               exp_alpha;
+
+  // Condensed or cold state
+  if ((1.f < eta) || (u < mat->u_iv)) {
+    c_sq = c_sq_c;
+  }
+  // Expanded and hot state
+  else if ((eta < 1.f) && (mat->u_cv < u)) {
+    c_sq = c_sq_e;
+  }
+  // Hybrid state
+  else {
+    c_sq = ((u - mat->u_iv) * c_sq_e + (mat->u_cv - u) * c_sq_c) /
+           (mat->u_cv - mat->u_iv);
+
+    c_sq = fmax(c_sq_c, mat->A * rho_0_inv);
+  }
+
+  return sqrtf(c_sq);
 }
 
 // gas_soundspeed_from_pressure
 INLINE static float Til_soundspeed_from_pressure(float density, float P,
                                                  const struct Til_params *mat) {
 
-  float c = sqrtf(mat->A / mat->rho_0);
+  error("This EOS function is not yet implemented!");
 
-  return c;
+  return 0.f;
 }
 
 #endif /* SWIFT_TILLOTSON_EQUATION_OF_STATE_H */
diff --git a/src/hydro.h b/src/hydro.h
index 950f63526a1590fa0fdcf2bfb5e650a2dfe14431..b3716996cc4da68f9445adccd12315b32d81a34c 100644
--- a/src/hydro.h
+++ b/src/hydro.h
@@ -62,9 +62,9 @@
 #include "./hydro/Shadowswift/hydro_iact.h"
 #define SPH_IMPLEMENTATION \
   "Shadowfax moving mesh (Vandenbroucke and De Rijcke 2016)"
-#elif defined(MINIMAL_MULTI_MAT_SPH)
-#include "./hydro/MinimalMultiMat/hydro.h"
-#include "./hydro/MinimalMultiMat/hydro_iact.h"
+#elif defined(PLANETARY_SPH)
+#include "./hydro/Planetary/hydro.h"
+#include "./hydro/Planetary/hydro_iact.h"
 #define SPH_IMPLEMENTATION "Minimal version of SPH with multiple materials"
 #else
 #error "Invalid choice of SPH variant"
diff --git a/src/hydro/Default/hydro.h b/src/hydro/Default/hydro.h
index 2c3a9c46f0500fb20aa3cfa2e5feb682b3dcec63..237a34283e1b89b06a4de1d6f1890f9a7e1af509 100644
--- a/src/hydro/Default/hydro.h
+++ b/src/hydro/Default/hydro.h
@@ -506,6 +506,7 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
     struct part *restrict p, struct xpart *restrict xp, float dt_therm,
+    float dt_grav, float dt_hydro, float dt_kick_corr,
     const struct cosmology *cosmo, const struct hydro_props *hydro_props) {}
 
 /**
diff --git a/src/hydro/Gadget2/hydro.h b/src/hydro/Gadget2/hydro.h
index 26e3bf97dd1924abbe7380d1eaadce75213344df..4511b2d655b0e7b3293633a466c76757a0237874 100644
--- a/src/hydro/Gadget2/hydro.h
+++ b/src/hydro/Gadget2/hydro.h
@@ -530,6 +530,7 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
     struct part *restrict p, struct xpart *restrict xp, float dt_therm,
+    float dt_grav, float dt_hydro, float dt_kick_corr,
     const struct cosmology *cosmo, const struct hydro_props *hydro_props) {
 
   /* Do not decrease the entropy by more than a factor of 2 */
diff --git a/src/hydro/GizmoMFM/hydro.h b/src/hydro/GizmoMFM/hydro.h
index 1ab142740b641bdc9a0dff5a02b19479bae8257e..41c870da0cc4630896324b5fdab4b6ca2d4362bc 100644
--- a/src/hydro/GizmoMFM/hydro.h
+++ b/src/hydro/GizmoMFM/hydro.h
@@ -28,14 +28,11 @@
 #include "hydro_properties.h"
 #include "hydro_space.h"
 #include "hydro_unphysical.h"
-#include "hydro_velocities.h"
 #include "minmax.h"
 #include "riemann.h"
 
 #include <float.h>
 
-//#define GIZMO_LLOYD_ITERATION
-
 /**
  * @brief Computes the hydro time-step of a given particle
  *
@@ -51,28 +48,23 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep(
 
   const float CFL_condition = hydro_properties->CFL_condition;
 
-#ifdef GIZMO_LLOYD_ITERATION
-  return CFL_condition;
-#endif
-
-  /* v_full is the actual velocity of the particle, primitives.v is its
+  /* v_full is the actual velocity of the particle, v is its
      hydrodynamical velocity. The time step depends on the relative difference
      of the two. */
   float vrel[3];
-  vrel[0] = p->primitives.v[0] - xp->v_full[0];
-  vrel[1] = p->primitives.v[1] - xp->v_full[1];
-  vrel[2] = p->primitives.v[2] - xp->v_full[2];
+  vrel[0] = p->v[0] - xp->v_full[0];
+  vrel[1] = p->v[1] - xp->v_full[1];
+  vrel[2] = p->v[2] - xp->v_full[2];
   float vmax =
       sqrtf(vrel[0] * vrel[0] + vrel[1] * vrel[1] + vrel[2] * vrel[2]) +
-      sqrtf(hydro_gamma * p->primitives.P / p->primitives.rho);
+      sqrtf(hydro_gamma * p->P / p->rho);
   vmax = max(vmax, p->timestepvars.vmax);
 
-  // MATTHIEU: Bert is this correct? Do we need more cosmology terms here?
-  const float psize =
-      cosmo->a * powf(p->geometry.volume / hydro_dimension_unit_sphere,
-                      hydro_dimension_inv);
+  const float psize = cosmo->a * cosmo->a *
+                      powf(p->geometry.volume / hydro_dimension_unit_sphere,
+                           hydro_dimension_inv);
   float dt = FLT_MAX;
-  if (vmax > 0.) {
+  if (vmax > 0.0f) {
     dt = psize / vmax;
   }
   return CFL_condition * dt;
@@ -92,7 +84,7 @@ __attribute__((always_inline)) INLINE static void hydro_timestep_extra(
     struct part* p, float dt) {
 
 #ifdef SWIFT_DEBUG_CHECKS
-  if (dt == 0.) {
+  if (dt == 0.0f) {
     error("Zero time step assigned to particle!");
   }
 
@@ -122,14 +114,10 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part(
 
   const float mass = p->conserved.mass;
 
-  p->primitives.v[0] = p->v[0];
-  p->primitives.v[1] = p->v[1];
-  p->primitives.v[2] = p->v[2];
-
   /* we can already initialize the momentum */
-  p->conserved.momentum[0] = mass * p->primitives.v[0];
-  p->conserved.momentum[1] = mass * p->primitives.v[1];
-  p->conserved.momentum[2] = mass * p->primitives.v[2];
+  p->conserved.momentum[0] = mass * p->v[0];
+  p->conserved.momentum[1] = mass * p->v[1];
+  p->conserved.momentum[2] = mass * p->v[2];
 
 /* and the thermal energy */
 /* remember that we store the total thermal energy, not the specific thermal
@@ -137,39 +125,22 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part(
 #if defined(EOS_ISOTHERMAL_GAS)
   /* this overwrites the internal energy from the initial condition file
    * Note that we call the EoS function just to get the constant u here. */
-  p->conserved.energy = mass * gas_internal_energy_from_entropy(0.f, 0.f);
+  p->conserved.energy = mass * gas_internal_energy_from_entropy(0.0f, 0.0f);
 #else
   p->conserved.energy *= mass;
 #endif
 
 #ifdef GIZMO_TOTAL_ENERGY
   /* add the total kinetic energy */
-  p->conserved.energy += 0.5f * (p->conserved.momentum[0] * p->primitives.v[0] +
-                                 p->conserved.momentum[1] * p->primitives.v[1] +
-                                 p->conserved.momentum[2] * p->primitives.v[2]);
-#endif
-
-#ifdef GIZMO_LLOYD_ITERATION
-  /* overwrite all variables to make sure they have safe values */
-  p->primitives.rho = 1.;
-  p->primitives.v[0] = 0.;
-  p->primitives.v[1] = 0.;
-  p->primitives.v[2] = 0.;
-  p->primitives.P = 1.;
-
-  p->conserved.mass = 1.;
-  p->conserved.momentum[0] = 0.;
-  p->conserved.momentum[1] = 0.;
-  p->conserved.momentum[2] = 0.;
-  p->conserved.energy = 1.;
-
-  p->v[0] = 0.;
-  p->v[1] = 0.;
-  p->v[2] = 0.;
+  p->conserved.energy += 0.5f * (p->conserved.momentum[0] * p->v[0] +
+                                 p->conserved.momentum[1] * p->v[1] +
+                                 p->conserved.momentum[2] * p->v[2]);
 #endif
 
   /* initialize the particle velocity based on the primitive fluid velocity */
-  hydro_velocities_init(p, xp);
+  xp->v_full[0] = p->v[0];
+  xp->v_full[1] = p->v[1];
+  xp->v_full[2] = p->v[2];
 
   /* ignore accelerations present in the initial condition */
   p->a_hydro[0] = 0.0f;
@@ -180,7 +151,7 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part(
      time the density loop is repeated, and the whole point of storing wcorr
      is to have a way of remembering that we need more neighbours for this
      particle */
-  p->density.wcorr = 1.0f;
+  p->geometry.wcorr = 1.0f;
 }
 
 /**
@@ -250,7 +221,8 @@ __attribute__((always_inline)) INLINE static void hydro_end_density(
   /* Final operation on the geometry. */
   /* we multiply with the smoothing kernel normalization ih3 and calculate the
    * volume */
-  const float volume = 1.f / (ihdim * (p->geometry.volume + kernel_root));
+  const float volume_inv = ihdim * (p->geometry.volume + kernel_root);
+  const float volume = 1.0f / volume_inv;
   p->geometry.volume = volume;
 
   /* we multiply with the smoothing kernel normalization */
@@ -268,9 +240,10 @@ __attribute__((always_inline)) INLINE static void hydro_end_density(
   p->geometry.centroid[1] *= kernel_norm;
   p->geometry.centroid[2] *= kernel_norm;
 
-  p->geometry.centroid[0] /= p->density.wcount;
-  p->geometry.centroid[1] /= p->density.wcount;
-  p->geometry.centroid[2] /= p->density.wcount;
+  const float wcount_inv = 1.0f / p->density.wcount;
+  p->geometry.centroid[0] *= wcount_inv;
+  p->geometry.centroid[1] *= wcount_inv;
+  p->geometry.centroid[2] *= wcount_inv;
 
   /* Check the condition number to see if we have a stable geometry. */
   float condition_number_E = 0.0f;
@@ -296,7 +269,7 @@ __attribute__((always_inline)) INLINE static void hydro_end_density(
       hydro_dimension_inv * sqrtf(condition_number_E * condition_number_Einv);
 
   if (condition_number > const_gizmo_max_condition_number &&
-      p->density.wcorr > const_gizmo_min_wcorr) {
+      p->geometry.wcorr > const_gizmo_min_wcorr) {
 #ifdef GIZMO_PATHOLOGICAL_ERROR
     error("Condition number larger than %g (%g)!",
           const_gizmo_max_condition_number, condition_number);
@@ -306,21 +279,19 @@ __attribute__((always_inline)) INLINE static void hydro_end_density(
             condition_number, const_gizmo_max_condition_number, p->id);
 #endif
     /* add a correction to the number of neighbours for this particle */
-    p->density.wcorr *= const_gizmo_w_correction_factor;
+    p->geometry.wcorr *= const_gizmo_w_correction_factor;
   }
 
-  hydro_gradients_init(p);
-
   /* compute primitive variables */
   /* eqns (3)-(5) */
   const float m = p->conserved.mass;
 
 #ifdef SWIFT_DEBUG_CHECKS
-  if (m < 0.) {
+  if (m < 0.0f) {
     error("Mass is negative!");
   }
 
-  if (volume == 0.) {
+  if (volume == 0.0f) {
     error("Volume is 0!");
   }
 #endif
@@ -330,55 +301,45 @@ __attribute__((always_inline)) INLINE static void hydro_end_density(
   momentum[0] = p->conserved.momentum[0];
   momentum[1] = p->conserved.momentum[1];
   momentum[2] = p->conserved.momentum[2];
-  p->primitives.rho = m / volume;
-  if (m == 0.) {
-    p->primitives.v[0] = 0.;
-    p->primitives.v[1] = 0.;
-    p->primitives.v[2] = 0.;
+  p->rho = m * volume_inv;
+  if (m == 0.0f) {
+    p->v[0] = 0.0f;
+    p->v[1] = 0.0f;
+    p->v[2] = 0.0f;
   } else {
-    p->primitives.v[0] = momentum[0] / m;
-    p->primitives.v[1] = momentum[1] / m;
-    p->primitives.v[2] = momentum[2] / m;
+    const float m_inv = 1.0f / m;
+    p->v[0] = momentum[0] * m_inv;
+    p->v[1] = momentum[1] * m_inv;
+    p->v[2] = momentum[2] * m_inv;
   }
 
 #ifdef EOS_ISOTHERMAL_GAS
   /* although the pressure is not formally used anywhere if an isothermal eos
      has been selected, we still make sure it is set to the correct value */
-  p->primitives.P = gas_pressure_from_internal_energy(p->primitives.rho, 0.);
+  p->P = gas_pressure_from_internal_energy(p->rho, 0.0f);
 #else
 
   float energy = p->conserved.energy;
 
 #ifdef GIZMO_TOTAL_ENERGY
   /* subtract the kinetic energy; we want the thermal energy */
-  energy -= 0.5f * (momentum[0] * p->primitives.v[0] +
-                    momentum[1] * p->primitives.v[1] +
-                    momentum[2] * p->primitives.v[2]);
+  energy -= 0.5f * (momentum[0] * p->v[0] + momentum[1] * p->v[1] +
+                    momentum[2] * p->v[2]);
 #endif
 
   /* energy contains the total thermal energy, we want the specific energy.
      this is why we divide by the volume, and not by the density */
-  p->primitives.P = hydro_gamma_minus_one * energy / volume;
+  p->P = hydro_gamma_minus_one * energy * volume_inv;
 #endif
 
   /* sanity checks */
-  gizmo_check_physical_quantities("density", "pressure", p->primitives.rho,
-                                  p->primitives.v[0], p->primitives.v[1],
-                                  p->primitives.v[2], p->primitives.P);
-
-#ifdef GIZMO_LLOYD_ITERATION
-  /* overwrite primitive variables to make sure they still have safe values */
-  p->primitives.rho = 1.;
-  p->primitives.v[0] = 0.;
-  p->primitives.v[1] = 0.;
-  p->primitives.v[2] = 0.;
-  p->primitives.P = 1.;
-#endif
+  gizmo_check_physical_quantities("density", "pressure", p->rho, p->v[0],
+                                  p->v[1], p->v[2], p->P);
 
   /* Add a correction factor to wcount (to force a neighbour number increase if
      the geometry matrix is close to singular) */
-  p->density.wcount *= p->density.wcorr;
-  p->density.wcount_dh *= p->density.wcorr;
+  p->density.wcount *= p->geometry.wcorr;
+  p->density.wcount_dh *= p->geometry.wcorr;
 }
 
 /**
@@ -399,7 +360,7 @@ __attribute__((always_inline)) INLINE static void hydro_part_has_no_neighbours(
 
   /* Re-set problematic values */
   p->density.wcount = kernel_root * h_inv_dim;
-  p->density.wcount_dh = 0.f;
+  p->density.wcount_dh = 0.0f;
   p->geometry.volume = 1.0f;
   p->geometry.matrix_E[0][0] = 1.0f;
   p->geometry.matrix_E[0][1] = 0.0f;
@@ -437,12 +398,11 @@ __attribute__((always_inline)) INLINE static void hydro_prepare_gradient(
     const struct cosmology* cosmo) {
 
   /* Initialize time step criterion variables */
-  p->timestepvars.vmax = 0.;
+  p->timestepvars.vmax = 0.0f;
 
-  // MATTHIEU: Bert is this correct? Do we need cosmology terms here?
+  hydro_gradients_init(p);
 
-  /* Set the actual velocity of the particle */
-  hydro_velocities_prepare_force(p, xp);
+  // MATTHIEU: Bert is this correct? Do we need cosmology terms here?
 }
 
 /**
@@ -494,15 +454,10 @@ __attribute__((always_inline)) INLINE static void hydro_prepare_force(
     const struct cosmology* cosmo) {
 
   /* Initialise values that are used in the force loop */
-  p->gravity.mflux[0] = 0.0f;
-  p->gravity.mflux[1] = 0.0f;
-  p->gravity.mflux[2] = 0.0f;
-
-  p->conserved.flux.mass = 0.0f;
-  p->conserved.flux.momentum[0] = 0.0f;
-  p->conserved.flux.momentum[1] = 0.0f;
-  p->conserved.flux.momentum[2] = 0.0f;
-  p->conserved.flux.energy = 0.0f;
+  p->flux.momentum[0] = 0.0f;
+  p->flux.momentum[1] = 0.0f;
+  p->flux.momentum[2] = 0.0f;
+  p->flux.energy = 0.0f;
 }
 
 /**
@@ -546,7 +501,10 @@ __attribute__((always_inline)) INLINE static void hydro_reset_predicted_values(
  * @param p The particle to act upon.
  */
 __attribute__((always_inline)) INLINE static void hydro_convert_quantities(
-    struct part* p, struct xpart* xp, const struct cosmology* cosmo) {}
+    struct part* p, struct xpart* xp, const struct cosmology* cosmo) {
+
+  p->conserved.energy /= cosmo->a_factor_internal_energy;
+}
 
 /**
  * @brief Extra operations to be done during the drift
@@ -559,10 +517,6 @@ __attribute__((always_inline)) INLINE static void hydro_convert_quantities(
 __attribute__((always_inline)) INLINE static void hydro_predict_extra(
     struct part* p, struct xpart* xp, float dt_drift, float dt_therm) {
 
-#ifdef GIZMO_LLOYD_ITERATION
-  return;
-#endif
-
   const float h_inv = 1.0f / p->h;
 
   /* Predict smoothing length */
@@ -575,39 +529,39 @@ __attribute__((always_inline)) INLINE static void hydro_predict_extra(
 
   /* Limit the smoothing length correction (and make sure it is always
      positive). */
-  if (h_corr < 2.0f && h_corr > 0.) {
+  if (h_corr < 2.0f && h_corr > 0.0f) {
     p->h *= h_corr;
   }
 
   /* drift the primitive variables based on the old fluxes */
-  if (p->geometry.volume > 0.) {
-    p->primitives.rho += p->conserved.flux.mass * dt_drift / p->geometry.volume;
-  }
+  if (p->conserved.mass > 0.0f) {
+    const float m_inv = 1.0f / p->conserved.mass;
 
-  if (p->conserved.mass > 0.) {
-    p->primitives.v[0] +=
-        p->conserved.flux.momentum[0] * dt_drift / p->conserved.mass;
-    p->primitives.v[1] +=
-        p->conserved.flux.momentum[1] * dt_drift / p->conserved.mass;
-    p->primitives.v[2] +=
-        p->conserved.flux.momentum[2] * dt_drift / p->conserved.mass;
+    p->v[0] += p->flux.momentum[0] * dt_drift * m_inv;
+    p->v[1] += p->flux.momentum[1] * dt_drift * m_inv;
+    p->v[2] += p->flux.momentum[2] * dt_drift * m_inv;
 
 #if !defined(EOS_ISOTHERMAL_GAS)
-    const float u = p->conserved.energy + p->conserved.flux.energy * dt_therm;
-    p->primitives.P =
-        hydro_gamma_minus_one * u * p->primitives.rho / p->conserved.mass;
+#ifdef GIZMO_TOTAL_ENERGY
+    const float Etot = p->conserved.energy + p->flux.energy * dt_drift;
+    const float v2 =
+        (p->v[0] * p->v[0] + p->v[1] * p->v[1] + p->v[2] * p->v[2]);
+    const float u = (Etot * m_inv - 0.5f * v2);
+#else
+    const float u = (p->conserved.energy + p->flux.energy * dt_drift) * m_inv;
+#endif
+    p->P = hydro_gamma_minus_one * u * p->rho;
 #endif
   }
 
 #ifdef SWIFT_DEBUG_CHECKS
-  if (p->h <= 0.) {
+  if (p->h <= 0.0f) {
     error("Zero or negative smoothing length (%g)!", p->h);
   }
 #endif
 
-  gizmo_check_physical_quantities("density", "pressure", p->primitives.rho,
-                                  p->primitives.v[0], p->primitives.v[1],
-                                  p->primitives.v[2], p->primitives.P);
+  gizmo_check_physical_quantities("density", "pressure", p->rho, p->v[0],
+                                  p->v[1], p->v[2], p->P);
 }
 
 /**
@@ -629,36 +583,48 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
   /* set the variables that are used to drift the primitive variables */
 
   // MATTHIEU: Bert is this correct? Do we need cosmology terms here?
-  hydro_velocities_end_force(p);
+
+  /* Add normalization to h_dt. */
+  p->force.h_dt *= p->h * hydro_dimension_inv;
 }
 
 /**
  * @brief Extra operations done during the kick
  *
- * Not used for GIZMO.
- *
  * @param p Particle to act upon.
  * @param xp Extended particle data to act upon.
- * @param dt Physical time step.
- * @param half_dt Half the physical time step.
+ * @param dt_therm Thermal energy time-step @f$\frac{dt}{a^2}@f$.
+ * @param dt_grav Gravity time-step @f$\frac{dt}{a}@f$.
+ * @param dt_hydro Hydro acceleration time-step
+ * @f$\frac{dt}{a^{3(\gamma{}-1)}}@f$.
+ * @param dt_kick_corr Gravity correction time-step @f$adt@f$.
+ * @param cosmo Cosmology.
+ * @param hydro_props Additional hydro properties.
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
-    struct part* p, struct xpart* xp, float dt, const struct cosmology* cosmo,
+    struct part* p, struct xpart* xp, float dt_therm, float dt_grav,
+    float dt_hydro, float dt_kick_corr, const struct cosmology* cosmo,
     const struct hydro_props* hydro_props) {
 
   float a_grav[3];
 
-  /* Update conserved variables. */
-  p->conserved.mass += p->conserved.flux.mass * dt;
-  p->conserved.momentum[0] += p->conserved.flux.momentum[0] * dt;
-  p->conserved.momentum[1] += p->conserved.flux.momentum[1] * dt;
-  p->conserved.momentum[2] += p->conserved.flux.momentum[2] * dt;
+  /* Update conserved variables (note: the mass does not change). */
+  p->conserved.momentum[0] += p->flux.momentum[0] * dt_therm;
+  p->conserved.momentum[1] += p->flux.momentum[1] * dt_therm;
+  p->conserved.momentum[2] += p->flux.momentum[2] * dt_therm;
 #if defined(EOS_ISOTHERMAL_GAS)
   /* We use the EoS equation in a sneaky way here just to get the constant u */
   p->conserved.energy =
-      p->conserved.mass * gas_internal_energy_from_entropy(0.f, 0.f);
+      p->conserved.mass * gas_internal_energy_from_entropy(0.0f, 0.0f);
 #else
-  p->conserved.energy += p->conserved.flux.energy * dt;
+  p->conserved.energy += p->flux.energy * dt_therm;
+#endif
+
+#ifndef HYDRO_GAMMA_5_3
+  const float Pcorr = (dt_hydro - dt_therm) * p->geometry.volume;
+  p->conserved.momentum[0] -= Pcorr * p->gradients.P[0];
+  p->conserved.momentum[1] -= Pcorr * p->gradients.P[1];
+  p->conserved.momentum[2] -= Pcorr * p->gradients.P[2];
 #endif
 
   /* Apply the minimal energy limit */
@@ -666,7 +632,7 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
       hydro_props->minimal_internal_energy * cosmo->a_factor_internal_energy;
   if (p->conserved.energy < min_energy * p->conserved.mass) {
     p->conserved.energy = min_energy * p->conserved.mass;
-    p->conserved.flux.energy = 0.f;
+    p->flux.energy = 0.0f;
   }
 
   gizmo_check_physical_quantities(
@@ -676,17 +642,11 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
 #ifdef SWIFT_DEBUG_CHECKS
   /* Note that this check will only have effect if no GIZMO_UNPHYSICAL option
      was selected. */
-  if (p->conserved.mass < 0.) {
-    error(
-        "Negative mass after conserved variables update (mass: %g, dmass: %g)!",
-        p->conserved.mass, p->conserved.flux.mass);
-  }
-
-  if (p->conserved.energy < 0.) {
+  if (p->conserved.energy < 0.0f) {
     error(
         "Negative energy after conserved variables update (energy: %g, "
         "denergy: %g)!",
-        p->conserved.energy, p->conserved.flux.energy);
+        p->conserved.energy, p->flux.energy);
   }
 #endif
 
@@ -699,44 +659,40 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
     a_grav[1] = p->gpart->a_grav[1];
     a_grav[2] = p->gpart->a_grav[2];
 
-    /* Make sure the gpart knows the mass has changed. */
-    p->gpart->mass = p->conserved.mass;
-
     /* Kick the momentum for half a time step */
     /* Note that this also affects the particle movement, as the velocity for
        the particles is set after this. */
-    p->conserved.momentum[0] += dt * p->conserved.mass * a_grav[0];
-    p->conserved.momentum[1] += dt * p->conserved.mass * a_grav[1];
-    p->conserved.momentum[2] += dt * p->conserved.mass * a_grav[2];
-
-    p->conserved.energy += dt * (p->gravity.mflux[0] * a_grav[0] +
-                                 p->gravity.mflux[1] * a_grav[1] +
-                                 p->gravity.mflux[2] * a_grav[2]);
+    p->conserved.momentum[0] += dt_grav * p->conserved.mass * a_grav[0];
+    p->conserved.momentum[1] += dt_grav * p->conserved.mass * a_grav[1];
+    p->conserved.momentum[2] += dt_grav * p->conserved.mass * a_grav[2];
   }
 
-  hydro_velocities_set(p, xp);
+  /* Set the velocities: */
+  /* We first set the particle velocity */
+  if (p->conserved.mass > 0.0f && p->rho > 0.0f) {
 
-#ifdef GIZMO_LLOYD_ITERATION
-  /* reset conserved variables to safe values */
-  p->conserved.mass = 1.;
-  p->conserved.momentum[0] = 0.;
-  p->conserved.momentum[1] = 0.;
-  p->conserved.momentum[2] = 0.;
-  p->conserved.energy = 1.;
-
-  /* set the particle velocities to the Lloyd velocities */
-  /* note that centroid is the relative position of the centroid w.r.t. the
-     particle position (position - centroid) */
-  xp->v_full[0] = -p->geometry.centroid[0] / p->force.dt;
-  xp->v_full[1] = -p->geometry.centroid[1] / p->force.dt;
-  xp->v_full[2] = -p->geometry.centroid[2] / p->force.dt;
-  p->v[0] = xp->v_full[0];
-  p->v[1] = xp->v_full[1];
-  p->v[2] = xp->v_full[2];
-#endif
+    const float inverse_mass = 1.0f / p->conserved.mass;
+
+    /* Normal case: set particle velocity to fluid velocity. */
+    xp->v_full[0] = p->conserved.momentum[0] * inverse_mass;
+    xp->v_full[1] = p->conserved.momentum[1] * inverse_mass;
+    xp->v_full[2] = p->conserved.momentum[2] * inverse_mass;
+
+  } else {
+    /* Vacuum particles have no fluid velocity. */
+    xp->v_full[0] = 0.0f;
+    xp->v_full[1] = 0.0f;
+    xp->v_full[2] = 0.0f;
+  }
+
+  if (p->gpart) {
+    p->gpart->v_full[0] = xp->v_full[0];
+    p->gpart->v_full[1] = xp->v_full[1];
+    p->gpart->v_full[2] = xp->v_full[2];
+  }
 
   /* reset wcorr */
-  p->density.wcorr = 1.0f;
+  p->geometry.wcorr = 1.0f;
 }
 
 /**
@@ -747,11 +703,11 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
 __attribute__((always_inline)) INLINE static float
 hydro_get_comoving_internal_energy(const struct part* restrict p) {
 
-  if (p->primitives.rho > 0.)
-    return gas_internal_energy_from_pressure(p->primitives.rho,
-                                             p->primitives.P);
-  else
-    return 0.;
+  if (p->rho > 0.0f) {
+    return gas_internal_energy_from_pressure(p->rho, p->P);
+  } else {
+    return 0.0f;
+  }
 }
 
 /**
@@ -776,10 +732,10 @@ hydro_get_physical_internal_energy(const struct part* restrict p,
 __attribute__((always_inline)) INLINE static float hydro_get_comoving_entropy(
     const struct part* restrict p) {
 
-  if (p->primitives.rho > 0.) {
-    return gas_entropy_from_pressure(p->primitives.rho, p->primitives.P);
+  if (p->rho > 0.0f) {
+    return gas_entropy_from_pressure(p->rho, p->P);
   } else {
-    return 0.;
+    return 0.0f;
   }
 }
 
@@ -805,10 +761,11 @@ __attribute__((always_inline)) INLINE static float hydro_get_physical_entropy(
 __attribute__((always_inline)) INLINE static float
 hydro_get_comoving_soundspeed(const struct part* restrict p) {
 
-  if (p->primitives.rho > 0.)
-    return gas_soundspeed_from_pressure(p->primitives.rho, p->primitives.P);
-  else
-    return 0.;
+  if (p->rho > 0.0f) {
+    return gas_soundspeed_from_pressure(p->rho, p->P);
+  } else {
+    return 0.0f;
+  }
 }
 
 /**
@@ -832,7 +789,7 @@ hydro_get_physical_soundspeed(const struct part* restrict p,
 __attribute__((always_inline)) INLINE static float hydro_get_comoving_pressure(
     const struct part* restrict p) {
 
-  return p->primitives.P;
+  return p->P;
 }
 
 /**
@@ -844,7 +801,7 @@ __attribute__((always_inline)) INLINE static float hydro_get_comoving_pressure(
 __attribute__((always_inline)) INLINE static float hydro_get_physical_pressure(
     const struct part* restrict p, const struct cosmology* cosmo) {
 
-  return cosmo->a_factor_pressure * p->primitives.P;
+  return cosmo->a_factor_pressure * p->P;
 }
 
 /**
@@ -883,20 +840,17 @@ __attribute__((always_inline)) INLINE static void hydro_get_drifted_velocities(
     const struct part* restrict p, const struct xpart* xp, float dt_kick_hydro,
     float dt_kick_grav, float v[3]) {
 
-  if (p->conserved.mass > 0.) {
-    v[0] = p->primitives.v[0] +
-           p->conserved.flux.momentum[0] * dt_kick_hydro / p->conserved.mass;
-    v[1] = p->primitives.v[1] +
-           p->conserved.flux.momentum[1] * dt_kick_hydro / p->conserved.mass;
-    v[2] = p->primitives.v[2] +
-           p->conserved.flux.momentum[2] * dt_kick_hydro / p->conserved.mass;
+  if (p->conserved.mass > 0.0f) {
+    const float inverse_mass = 1.0f / p->conserved.mass;
+    v[0] = p->v[0] + p->flux.momentum[0] * dt_kick_hydro * inverse_mass;
+    v[1] = p->v[1] + p->flux.momentum[1] * dt_kick_hydro * inverse_mass;
+    v[2] = p->v[2] + p->flux.momentum[2] * dt_kick_hydro * inverse_mass;
   } else {
-    v[0] = p->primitives.v[0];
-    v[1] = p->primitives.v[1];
-    v[2] = p->primitives.v[2];
+    v[0] = p->v[0];
+    v[1] = p->v[1];
+    v[2] = p->v[2];
   }
 
-  // MATTHIEU: Bert is this correct?
   v[0] += xp->a_grav[0] * dt_kick_grav;
   v[1] += xp->a_grav[1] * dt_kick_grav;
   v[2] += xp->a_grav[2] * dt_kick_grav;
@@ -910,7 +864,7 @@ __attribute__((always_inline)) INLINE static void hydro_get_drifted_velocities(
 __attribute__((always_inline)) INLINE static float hydro_get_comoving_density(
     const struct part* restrict p) {
 
-  return p->primitives.rho;
+  return p->rho;
 }
 
 /**
@@ -922,7 +876,7 @@ __attribute__((always_inline)) INLINE static float hydro_get_comoving_density(
 __attribute__((always_inline)) INLINE static float hydro_get_physical_density(
     const struct part* restrict p, const struct cosmology* cosmo) {
 
-  return cosmo->a3_inv * p->primitives.rho;
+  return cosmo->a3_inv * p->rho;
 }
 
 /**
@@ -943,12 +897,12 @@ __attribute__((always_inline)) INLINE static void hydro_set_internal_energy(
   p->conserved.energy = u * p->conserved.mass;
 #ifdef GIZMO_TOTAL_ENERGY
   /* add the kinetic energy */
-  p->conserved.energy += 0.5f * p->conserved.mass *
-                         (p->conserved.momentum[0] * p->primitives.v[0] +
-                          p->conserved.momentum[1] * p->primitives.v[1] +
-                          p->conserved.momentum[2] * p->primitives.v[2]);
+  p->conserved.energy +=
+      0.5f * p->conserved.mass *
+      (p->conserved.momentum[0] * p->v[0] + p->conserved.momentum[1] * p->v[1] +
+       p->conserved.momentum[2] * p->v[2]);
 #endif
-  p->primitives.P = hydro_gamma_minus_one * p->primitives.rho * u;
+  p->P = hydro_gamma_minus_one * p->rho * u;
 }
 
 /**
@@ -963,16 +917,16 @@ __attribute__((always_inline)) INLINE static void hydro_set_internal_energy(
 __attribute__((always_inline)) INLINE static void hydro_set_entropy(
     struct part* restrict p, float S) {
 
-  p->conserved.energy = S * pow_gamma_minus_one(p->primitives.rho) *
+  p->conserved.energy = S * pow_gamma_minus_one(p->rho) *
                         hydro_one_over_gamma_minus_one * p->conserved.mass;
 #ifdef GIZMO_TOTAL_ENERGY
   /* add the kinetic energy */
-  p->conserved.energy += 0.5f * p->conserved.mass *
-                         (p->conserved.momentum[0] * p->primitives.v[0] +
-                          p->conserved.momentum[1] * p->primitives.v[1] +
-                          p->conserved.momentum[2] * p->primitives.v[2]);
+  p->conserved.energy +=
+      0.5f * p->conserved.mass *
+      (p->conserved.momentum[0] * p->v[0] + p->conserved.momentum[1] * p->v[1] +
+       p->conserved.momentum[2] * p->v[2]);
 #endif
-  p->primitives.P = S * pow_gamma(p->primitives.rho);
+  p->P = S * pow_gamma(p->rho);
 }
 
 /**
@@ -992,12 +946,12 @@ hydro_set_init_internal_energy(struct part* p, float u_init) {
   p->conserved.energy = u_init * p->conserved.mass;
 #ifdef GIZMO_TOTAL_ENERGY
   /* add the kinetic energy */
-  p->conserved.energy += 0.5f * p->conserved.mass *
-                         (p->conserved.momentum[0] * p->primitives.v[0] +
-                          p->conserved.momentum[1] * p->primitives.v[1] +
-                          p->conserved.momentum[2] * p->primitives.v[2]);
+  p->conserved.energy +=
+      0.5f * p->conserved.mass *
+      (p->conserved.momentum[0] * p->v[0] + p->conserved.momentum[1] * p->v[1] +
+       p->conserved.momentum[2] * p->v[2]);
 #endif
-  p->primitives.P = hydro_gamma_minus_one * p->primitives.rho * u_init;
+  p->P = hydro_gamma_minus_one * p->rho * u_init;
 }
 
 #endif /* SWIFT_GIZMO_MFM_HYDRO_H */
diff --git a/src/hydro/GizmoMFM/hydro_debug.h b/src/hydro/GizmoMFM/hydro_debug.h
index 6603bc216b986b40513383120587d3caec1adc87..e8b0914bd3cf6a99210399c6fc654e526319009f 100644
--- a/src/hydro/GizmoMFM/hydro_debug.h
+++ b/src/hydro/GizmoMFM/hydro_debug.h
@@ -27,8 +27,6 @@ __attribute__((always_inline)) INLINE static void hydro_debug_particle(
       "a=[%.3e,%.3e,%.3e], "
       "h=%.3e, "
       "time_bin=%d, "
-      "primitives={"
-      "v=[%.3e,%.3e,%.3e], "
       "rho=%.3e, "
       "P=%.3e, "
       "gradients={"
@@ -39,7 +37,7 @@ __attribute__((always_inline)) INLINE static void hydro_debug_particle(
       "rho=[%.3e,%.3e], "
       "v=[[%.3e,%.3e],[%.3e,%.3e],[%.3e,%.3e]], "
       "P=[%.3e,%.3e], "
-      "maxr=%.3e}}, "
+      "maxr=%.3e}, "
       "conserved={"
       "momentum=[%.3e,%.3e,%.3e], "
       "mass=%.3e, "
@@ -53,24 +51,18 @@ __attribute__((always_inline)) INLINE static void hydro_debug_particle(
       "wcount_dh=%.3e, "
       "wcount=%.3e}\n",
       p->x[0], p->x[1], p->x[2], p->v[0], p->v[1], p->v[2], p->a_hydro[0],
-      p->a_hydro[1], p->a_hydro[2], p->h, p->time_bin, p->primitives.v[0],
-      p->primitives.v[1], p->primitives.v[2], p->primitives.rho,
-      p->primitives.P, p->primitives.gradients.rho[0],
-      p->primitives.gradients.rho[1], p->primitives.gradients.rho[2],
-      p->primitives.gradients.v[0][0], p->primitives.gradients.v[0][1],
-      p->primitives.gradients.v[0][2], p->primitives.gradients.v[1][0],
-      p->primitives.gradients.v[1][1], p->primitives.gradients.v[1][2],
-      p->primitives.gradients.v[2][0], p->primitives.gradients.v[2][1],
-      p->primitives.gradients.v[2][2], p->primitives.gradients.P[0],
-      p->primitives.gradients.P[1], p->primitives.gradients.P[2],
-      p->primitives.limiter.rho[0], p->primitives.limiter.rho[1],
-      p->primitives.limiter.v[0][0], p->primitives.limiter.v[0][1],
-      p->primitives.limiter.v[1][0], p->primitives.limiter.v[1][1],
-      p->primitives.limiter.v[2][0], p->primitives.limiter.v[2][1],
-      p->primitives.limiter.P[0], p->primitives.limiter.P[1],
-      p->primitives.limiter.maxr, p->conserved.momentum[0],
-      p->conserved.momentum[1], p->conserved.momentum[2], p->conserved.mass,
-      p->conserved.energy, p->geometry.volume, p->geometry.matrix_E[0][0],
+      p->a_hydro[1], p->a_hydro[2], p->h, p->time_bin, p->rho, p->P,
+      p->gradients.rho[0], p->gradients.rho[1], p->gradients.rho[2],
+      p->gradients.v[0][0], p->gradients.v[0][1], p->gradients.v[0][2],
+      p->gradients.v[1][0], p->gradients.v[1][1], p->gradients.v[1][2],
+      p->gradients.v[2][0], p->gradients.v[2][1], p->gradients.v[2][2],
+      p->gradients.P[0], p->gradients.P[1], p->gradients.P[2],
+      p->limiter.rho[0], p->limiter.rho[1], p->limiter.v[0][0],
+      p->limiter.v[0][1], p->limiter.v[1][0], p->limiter.v[1][1],
+      p->limiter.v[2][0], p->limiter.v[2][1], p->limiter.P[0], p->limiter.P[1],
+      p->limiter.maxr, p->conserved.momentum[0], p->conserved.momentum[1],
+      p->conserved.momentum[2], p->conserved.mass, p->conserved.energy,
+      p->geometry.volume, p->geometry.matrix_E[0][0],
       p->geometry.matrix_E[0][1], p->geometry.matrix_E[0][2],
       p->geometry.matrix_E[1][0], p->geometry.matrix_E[1][1],
       p->geometry.matrix_E[1][2], p->geometry.matrix_E[2][0],
diff --git a/src/hydro/GizmoMFM/hydro_gradients.h b/src/hydro/GizmoMFM/hydro_gradients.h
index 964a2adcfe09b95c2a221af540e5e3ff0830dd67..6f751d970287ca7ba137c1138ca6f3bf00e6c4cb 100644
--- a/src/hydro/GizmoMFM/hydro_gradients.h
+++ b/src/hydro/GizmoMFM/hydro_gradients.h
@@ -98,42 +98,31 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_predict(
   /* perform gradient reconstruction in space and time */
   /* Compute interface position (relative to pj, since we don't need the actual
    * position) eqn. (8) */
-  const float xfac = hj / (hi + hj);
-  const float xij_j[3] = {xfac * dx[0], xfac * dx[1], xfac * dx[2]};
+  const float xij_j[3] = {xij_i[0] + dx[0], xij_i[1] + dx[1], xij_i[2] + dx[2]};
 
   float dWi[5];
-  dWi[0] = pi->primitives.gradients.rho[0] * xij_i[0] +
-           pi->primitives.gradients.rho[1] * xij_i[1] +
-           pi->primitives.gradients.rho[2] * xij_i[2];
-  dWi[1] = pi->primitives.gradients.v[0][0] * xij_i[0] +
-           pi->primitives.gradients.v[0][1] * xij_i[1] +
-           pi->primitives.gradients.v[0][2] * xij_i[2];
-  dWi[2] = pi->primitives.gradients.v[1][0] * xij_i[0] +
-           pi->primitives.gradients.v[1][1] * xij_i[1] +
-           pi->primitives.gradients.v[1][2] * xij_i[2];
-  dWi[3] = pi->primitives.gradients.v[2][0] * xij_i[0] +
-           pi->primitives.gradients.v[2][1] * xij_i[1] +
-           pi->primitives.gradients.v[2][2] * xij_i[2];
-  dWi[4] = pi->primitives.gradients.P[0] * xij_i[0] +
-           pi->primitives.gradients.P[1] * xij_i[1] +
-           pi->primitives.gradients.P[2] * xij_i[2];
+  dWi[0] = pi->gradients.rho[0] * xij_i[0] + pi->gradients.rho[1] * xij_i[1] +
+           pi->gradients.rho[2] * xij_i[2];
+  dWi[1] = pi->gradients.v[0][0] * xij_i[0] + pi->gradients.v[0][1] * xij_i[1] +
+           pi->gradients.v[0][2] * xij_i[2];
+  dWi[2] = pi->gradients.v[1][0] * xij_i[0] + pi->gradients.v[1][1] * xij_i[1] +
+           pi->gradients.v[1][2] * xij_i[2];
+  dWi[3] = pi->gradients.v[2][0] * xij_i[0] + pi->gradients.v[2][1] * xij_i[1] +
+           pi->gradients.v[2][2] * xij_i[2];
+  dWi[4] = pi->gradients.P[0] * xij_i[0] + pi->gradients.P[1] * xij_i[1] +
+           pi->gradients.P[2] * xij_i[2];
 
   float dWj[5];
-  dWj[0] = pj->primitives.gradients.rho[0] * xij_j[0] +
-           pj->primitives.gradients.rho[1] * xij_j[1] +
-           pj->primitives.gradients.rho[2] * xij_j[2];
-  dWj[1] = pj->primitives.gradients.v[0][0] * xij_j[0] +
-           pj->primitives.gradients.v[0][1] * xij_j[1] +
-           pj->primitives.gradients.v[0][2] * xij_j[2];
-  dWj[2] = pj->primitives.gradients.v[1][0] * xij_j[0] +
-           pj->primitives.gradients.v[1][1] * xij_j[1] +
-           pj->primitives.gradients.v[1][2] * xij_j[2];
-  dWj[3] = pj->primitives.gradients.v[2][0] * xij_j[0] +
-           pj->primitives.gradients.v[2][1] * xij_j[1] +
-           pj->primitives.gradients.v[2][2] * xij_j[2];
-  dWj[4] = pj->primitives.gradients.P[0] * xij_j[0] +
-           pj->primitives.gradients.P[1] * xij_j[1] +
-           pj->primitives.gradients.P[2] * xij_j[2];
+  dWj[0] = pj->gradients.rho[0] * xij_j[0] + pj->gradients.rho[1] * xij_j[1] +
+           pj->gradients.rho[2] * xij_j[2];
+  dWj[1] = pj->gradients.v[0][0] * xij_j[0] + pj->gradients.v[0][1] * xij_j[1] +
+           pj->gradients.v[0][2] * xij_j[2];
+  dWj[2] = pj->gradients.v[1][0] * xij_j[0] + pj->gradients.v[1][1] * xij_j[1] +
+           pj->gradients.v[1][2] * xij_j[2];
+  dWj[3] = pj->gradients.v[2][0] * xij_j[0] + pj->gradients.v[2][1] * xij_j[1] +
+           pj->gradients.v[2][2] * xij_j[2];
+  dWj[4] = pj->gradients.P[0] * xij_j[0] + pj->gradients.P[1] * xij_j[1] +
+           pj->gradients.P[2] * xij_j[2];
 
   /* Apply the slope limiter at this interface */
   hydro_slope_limit_face(Wi, Wj, dWi, dWj, xij_i, xij_j, r);
diff --git a/src/hydro/GizmoMFM/hydro_gradients_gizmo.h b/src/hydro/GizmoMFM/hydro_gradients_gizmo.h
index 1c3b68bb28375259628e09f16730710fbbd80149..90c8096a85b3418c8ee4c5382d6f087c14f8907e 100644
--- a/src/hydro/GizmoMFM/hydro_gradients_gizmo.h
+++ b/src/hydro/GizmoMFM/hydro_gradients_gizmo.h
@@ -28,25 +28,25 @@
 __attribute__((always_inline)) INLINE static void hydro_gradients_init(
     struct part *p) {
 
-  p->primitives.gradients.rho[0] = 0.0f;
-  p->primitives.gradients.rho[1] = 0.0f;
-  p->primitives.gradients.rho[2] = 0.0f;
+  p->gradients.rho[0] = 0.0f;
+  p->gradients.rho[1] = 0.0f;
+  p->gradients.rho[2] = 0.0f;
 
-  p->primitives.gradients.v[0][0] = 0.0f;
-  p->primitives.gradients.v[0][1] = 0.0f;
-  p->primitives.gradients.v[0][2] = 0.0f;
+  p->gradients.v[0][0] = 0.0f;
+  p->gradients.v[0][1] = 0.0f;
+  p->gradients.v[0][2] = 0.0f;
 
-  p->primitives.gradients.v[1][0] = 0.0f;
-  p->primitives.gradients.v[1][1] = 0.0f;
-  p->primitives.gradients.v[1][2] = 0.0f;
+  p->gradients.v[1][0] = 0.0f;
+  p->gradients.v[1][1] = 0.0f;
+  p->gradients.v[1][2] = 0.0f;
 
-  p->primitives.gradients.v[2][0] = 0.0f;
-  p->primitives.gradients.v[2][1] = 0.0f;
-  p->primitives.gradients.v[2][2] = 0.0f;
+  p->gradients.v[2][0] = 0.0f;
+  p->gradients.v[2][1] = 0.0f;
+  p->gradients.v[2][2] = 0.0f;
 
-  p->primitives.gradients.P[0] = 0.0f;
-  p->primitives.gradients.P[1] = 0.0f;
-  p->primitives.gradients.P[2] = 0.0f;
+  p->gradients.P[0] = 0.0f;
+  p->gradients.P[1] = 0.0f;
+  p->gradients.P[2] = 0.0f;
 
   hydro_slope_limit_cell_init(p);
 }
@@ -65,7 +65,7 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_collect(
     float r2, const float *dx, float hi, float hj, struct part *restrict pi,
     struct part *restrict pj) {
 
-  const float r_inv = 1.f / sqrtf(r2);
+  const float r_inv = 1.0f / sqrtf(r2);
   const float r = r2 * r_inv;
 
   float wi, wj, wi_dx, wj_dx;
@@ -80,211 +80,100 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_collect(
       Bj[k][l] = pj->geometry.matrix_E[k][l];
     }
   }
-  Wi[0] = pi->primitives.rho;
-  Wi[1] = pi->primitives.v[0];
-  Wi[2] = pi->primitives.v[1];
-  Wi[3] = pi->primitives.v[2];
-  Wi[4] = pi->primitives.P;
-  Wj[0] = pj->primitives.rho;
-  Wj[1] = pj->primitives.v[0];
-  Wj[2] = pj->primitives.v[1];
-  Wj[3] = pj->primitives.v[2];
-  Wj[4] = pj->primitives.P;
+  Wi[0] = pi->rho;
+  Wi[1] = pi->v[0];
+  Wi[2] = pi->v[1];
+  Wi[3] = pi->v[2];
+  Wi[4] = pi->P;
+  Wj[0] = pj->rho;
+  Wj[1] = pj->v[0];
+  Wj[2] = pj->v[1];
+  Wj[3] = pj->v[2];
+  Wj[4] = pj->P;
 
   /* Compute kernel of pi. */
-  const float hi_inv = 1.f / hi;
+  const float hi_inv = 1.0f / hi;
   const float xi = r * hi_inv;
   kernel_deval(xi, &wi, &wi_dx);
 
-  if (pi->density.wcorr > const_gizmo_min_wcorr) {
-    /* Compute gradients for pi */
-    /* there is a sign difference w.r.t. eqn. (6) because of the inverse
-     * definition of dx */
-    pi->primitives.gradients.rho[0] +=
-        (Wi[0] - Wj[0]) * wi *
-        (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
-    pi->primitives.gradients.rho[1] +=
-        (Wi[0] - Wj[0]) * wi *
-        (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
-    pi->primitives.gradients.rho[2] +=
-        (Wi[0] - Wj[0]) * wi *
-        (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
-
-    pi->primitives.gradients.v[0][0] +=
-        (Wi[1] - Wj[1]) * wi *
-        (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
-    pi->primitives.gradients.v[0][1] +=
-        (Wi[1] - Wj[1]) * wi *
-        (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
-    pi->primitives.gradients.v[0][2] +=
-        (Wi[1] - Wj[1]) * wi *
-        (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
-    pi->primitives.gradients.v[1][0] +=
-        (Wi[2] - Wj[2]) * wi *
-        (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
-    pi->primitives.gradients.v[1][1] +=
-        (Wi[2] - Wj[2]) * wi *
-        (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
-    pi->primitives.gradients.v[1][2] +=
-        (Wi[2] - Wj[2]) * wi *
-        (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
-    pi->primitives.gradients.v[2][0] +=
-        (Wi[3] - Wj[3]) * wi *
-        (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
-    pi->primitives.gradients.v[2][1] +=
-        (Wi[3] - Wj[3]) * wi *
-        (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
-    pi->primitives.gradients.v[2][2] +=
-        (Wi[3] - Wj[3]) * wi *
-        (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
-
-    pi->primitives.gradients.P[0] +=
-        (Wi[4] - Wj[4]) * wi *
-        (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
-    pi->primitives.gradients.P[1] +=
-        (Wi[4] - Wj[4]) * wi *
-        (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
-    pi->primitives.gradients.P[2] +=
-        (Wi[4] - Wj[4]) * wi *
-        (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
+  const float dW[5] = {Wi[0] - Wj[0], Wi[1] - Wj[1], Wi[2] - Wj[2],
+                       Wi[3] - Wj[3], Wi[4] - Wj[4]};
 
+  float wiBidx[3];
+  if (pi->geometry.wcorr > const_gizmo_min_wcorr) {
+    wiBidx[0] = wi * (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
+    wiBidx[1] = wi * (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
+    wiBidx[2] = wi * (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
   } else {
-    /* The gradient matrix was not well-behaved, switch to SPH gradients */
-
-    pi->primitives.gradients.rho[0] -=
-        wi_dx * dx[0] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-    pi->primitives.gradients.rho[1] -=
-        wi_dx * dx[1] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-    pi->primitives.gradients.rho[2] -=
-        wi_dx * dx[2] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-
-    pi->primitives.gradients.v[0][0] -=
-        wi_dx * dx[0] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-    pi->primitives.gradients.v[0][1] -=
-        wi_dx * dx[1] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-    pi->primitives.gradients.v[0][2] -=
-        wi_dx * dx[2] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-
-    pi->primitives.gradients.v[1][0] -=
-        wi_dx * dx[0] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-    pi->primitives.gradients.v[1][1] -=
-        wi_dx * dx[1] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-    pi->primitives.gradients.v[1][2] -=
-        wi_dx * dx[2] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-
-    pi->primitives.gradients.v[2][0] -=
-        wi_dx * dx[0] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-    pi->primitives.gradients.v[2][1] -=
-        wi_dx * dx[1] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-    pi->primitives.gradients.v[2][2] -=
-        wi_dx * dx[2] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-
-    pi->primitives.gradients.P[0] -=
-        wi_dx * dx[0] * (pi->primitives.P - pj->primitives.P) * r_inv;
-    pi->primitives.gradients.P[1] -=
-        wi_dx * dx[1] * (pi->primitives.P - pj->primitives.P) * r_inv;
-    pi->primitives.gradients.P[2] -=
-        wi_dx * dx[2] * (pi->primitives.P - pj->primitives.P) * r_inv;
+    const float norm = -wi_dx * r_inv;
+    wiBidx[0] = norm * dx[0];
+    wiBidx[1] = norm * dx[1];
+    wiBidx[2] = norm * dx[2];
   }
 
+  /* Compute gradients for pi */
+  /* there is a sign difference w.r.t. eqn. (6) because of the inverse
+   * definition of dx */
+  pi->gradients.rho[0] += dW[0] * wiBidx[0];
+  pi->gradients.rho[1] += dW[0] * wiBidx[1];
+  pi->gradients.rho[2] += dW[0] * wiBidx[2];
+
+  pi->gradients.v[0][0] += dW[1] * wiBidx[0];
+  pi->gradients.v[0][1] += dW[1] * wiBidx[1];
+  pi->gradients.v[0][2] += dW[1] * wiBidx[2];
+  pi->gradients.v[1][0] += dW[2] * wiBidx[0];
+  pi->gradients.v[1][1] += dW[2] * wiBidx[1];
+  pi->gradients.v[1][2] += dW[2] * wiBidx[2];
+  pi->gradients.v[2][0] += dW[3] * wiBidx[0];
+  pi->gradients.v[2][1] += dW[3] * wiBidx[1];
+  pi->gradients.v[2][2] += dW[3] * wiBidx[2];
+
+  pi->gradients.P[0] += dW[4] * wiBidx[0];
+  pi->gradients.P[1] += dW[4] * wiBidx[1];
+  pi->gradients.P[2] += dW[4] * wiBidx[2];
+
   hydro_slope_limit_cell_collect(pi, pj, r);
 
   /* Compute kernel of pj. */
-  const float hj_inv = 1.f / hj;
+  const float hj_inv = 1.0f / hj;
   const float xj = r * hj_inv;
   kernel_deval(xj, &wj, &wj_dx);
 
-  if (pj->density.wcorr > const_gizmo_min_wcorr) {
-    /* Compute gradients for pj */
-    /* there is no sign difference w.r.t. eqn. (6) because dx is now what we
-     * want
-     * it to be */
-    pj->primitives.gradients.rho[0] +=
-        (Wi[0] - Wj[0]) * wj *
-        (Bj[0][0] * dx[0] + Bj[0][1] * dx[1] + Bj[0][2] * dx[2]);
-    pj->primitives.gradients.rho[1] +=
-        (Wi[0] - Wj[0]) * wj *
-        (Bj[1][0] * dx[0] + Bj[1][1] * dx[1] + Bj[1][2] * dx[2]);
-    pj->primitives.gradients.rho[2] +=
-        (Wi[0] - Wj[0]) * wj *
-        (Bj[2][0] * dx[0] + Bj[2][1] * dx[1] + Bj[2][2] * dx[2]);
-
-    pj->primitives.gradients.v[0][0] +=
-        (Wi[1] - Wj[1]) * wj *
-        (Bj[0][0] * dx[0] + Bj[0][1] * dx[1] + Bj[0][2] * dx[2]);
-    pj->primitives.gradients.v[0][1] +=
-        (Wi[1] - Wj[1]) * wj *
-        (Bj[1][0] * dx[0] + Bj[1][1] * dx[1] + Bj[1][2] * dx[2]);
-    pj->primitives.gradients.v[0][2] +=
-        (Wi[1] - Wj[1]) * wj *
-        (Bj[2][0] * dx[0] + Bj[2][1] * dx[1] + Bj[2][2] * dx[2]);
-    pj->primitives.gradients.v[1][0] +=
-        (Wi[2] - Wj[2]) * wj *
-        (Bj[0][0] * dx[0] + Bj[0][1] * dx[1] + Bj[0][2] * dx[2]);
-    pj->primitives.gradients.v[1][1] +=
-        (Wi[2] - Wj[2]) * wj *
-        (Bj[1][0] * dx[0] + Bj[1][1] * dx[1] + Bj[1][2] * dx[2]);
-    pj->primitives.gradients.v[1][2] +=
-        (Wi[2] - Wj[2]) * wj *
-        (Bj[2][0] * dx[0] + Bj[2][1] * dx[1] + Bj[2][2] * dx[2]);
-    pj->primitives.gradients.v[2][0] +=
-        (Wi[3] - Wj[3]) * wj *
-        (Bj[0][0] * dx[0] + Bj[0][1] * dx[1] + Bj[0][2] * dx[2]);
-    pj->primitives.gradients.v[2][1] +=
-        (Wi[3] - Wj[3]) * wj *
-        (Bj[1][0] * dx[0] + Bj[1][1] * dx[1] + Bj[1][2] * dx[2]);
-    pj->primitives.gradients.v[2][2] +=
-        (Wi[3] - Wj[3]) * wj *
-        (Bj[2][0] * dx[0] + Bj[2][1] * dx[1] + Bj[2][2] * dx[2]);
-
-    pj->primitives.gradients.P[0] +=
-        (Wi[4] - Wj[4]) * wj *
-        (Bj[0][0] * dx[0] + Bj[0][1] * dx[1] + Bj[0][2] * dx[2]);
-    pj->primitives.gradients.P[1] +=
-        (Wi[4] - Wj[4]) * wj *
-        (Bj[1][0] * dx[0] + Bj[1][1] * dx[1] + Bj[1][2] * dx[2]);
-    pj->primitives.gradients.P[2] +=
-        (Wi[4] - Wj[4]) * wj *
-        (Bj[2][0] * dx[0] + Bj[2][1] * dx[1] + Bj[2][2] * dx[2]);
+  float wjBjdx[3];
+  if (pj->geometry.wcorr > const_gizmo_min_wcorr) {
+
+    wjBjdx[0] = wj * (Bj[0][0] * dx[0] + Bj[0][1] * dx[1] + Bj[0][2] * dx[2]);
+    wjBjdx[1] = wj * (Bj[1][0] * dx[0] + Bj[1][1] * dx[1] + Bj[1][2] * dx[2]);
+    wjBjdx[2] = wj * (Bj[2][0] * dx[0] + Bj[2][1] * dx[1] + Bj[2][2] * dx[2]);
 
   } else {
-    /* SPH gradients */
-
-    pj->primitives.gradients.rho[0] -=
-        wj_dx * dx[0] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-    pj->primitives.gradients.rho[1] -=
-        wj_dx * dx[1] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-    pj->primitives.gradients.rho[2] -=
-        wj_dx * dx[2] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-
-    pj->primitives.gradients.v[0][0] -=
-        wj_dx * dx[0] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-    pj->primitives.gradients.v[0][1] -=
-        wj_dx * dx[1] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-    pj->primitives.gradients.v[0][2] -=
-        wj_dx * dx[2] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-
-    pj->primitives.gradients.v[1][0] -=
-        wj_dx * dx[0] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-    pj->primitives.gradients.v[1][1] -=
-        wj_dx * dx[1] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-    pj->primitives.gradients.v[1][2] -=
-        wj_dx * dx[2] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-    pj->primitives.gradients.v[2][0] -=
-        wj_dx * dx[0] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-    pj->primitives.gradients.v[2][1] -=
-        wj_dx * dx[1] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-    pj->primitives.gradients.v[2][2] -=
-        wj_dx * dx[2] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-
-    pj->primitives.gradients.P[0] -=
-        wj_dx * dx[0] * (pi->primitives.P - pj->primitives.P) * r_inv;
-    pj->primitives.gradients.P[1] -=
-        wj_dx * dx[1] * (pi->primitives.P - pj->primitives.P) * r_inv;
-    pj->primitives.gradients.P[2] -=
-        wj_dx * dx[2] * (pi->primitives.P - pj->primitives.P) * r_inv;
+    const float norm = -wj_dx * r_inv;
+    wjBjdx[0] = norm * dx[0];
+    wjBjdx[1] = norm * dx[1];
+    wjBjdx[2] = norm * dx[2];
   }
 
+  /* Compute gradients for pj */
+  /* there is no sign difference w.r.t. eqn. (6) because dx is now what we
+   * want it to be */
+  pj->gradients.rho[0] += dW[0] * wjBjdx[0];
+  pj->gradients.rho[1] += dW[0] * wjBjdx[1];
+  pj->gradients.rho[2] += dW[0] * wjBjdx[2];
+
+  pj->gradients.v[0][0] += dW[1] * wjBjdx[0];
+  pj->gradients.v[0][1] += dW[1] * wjBjdx[1];
+  pj->gradients.v[0][2] += dW[1] * wjBjdx[2];
+  pj->gradients.v[1][0] += dW[2] * wjBjdx[0];
+  pj->gradients.v[1][1] += dW[2] * wjBjdx[1];
+  pj->gradients.v[1][2] += dW[2] * wjBjdx[2];
+  pj->gradients.v[2][0] += dW[3] * wjBjdx[0];
+  pj->gradients.v[2][1] += dW[3] * wjBjdx[1];
+  pj->gradients.v[2][2] += dW[3] * wjBjdx[2];
+
+  pj->gradients.P[0] += dW[4] * wjBjdx[0];
+  pj->gradients.P[1] += dW[4] * wjBjdx[1];
+  pj->gradients.P[2] += dW[4] * wjBjdx[2];
+
   hydro_slope_limit_cell_collect(pj, pi, r);
 }
 
@@ -303,7 +192,7 @@ hydro_gradients_nonsym_collect(float r2, const float *dx, float hi, float hj,
                                struct part *restrict pi,
                                struct part *restrict pj) {
 
-  const float r_inv = 1.f / sqrtf(r2);
+  const float r_inv = 1.0f / sqrtf(r2);
   const float r = r2 * r_inv;
 
   float Bi[3][3];
@@ -315,113 +204,59 @@ hydro_gradients_nonsym_collect(float r2, const float *dx, float hi, float hj,
       Bi[k][l] = pi->geometry.matrix_E[k][l];
     }
   }
-  Wi[0] = pi->primitives.rho;
-  Wi[1] = pi->primitives.v[0];
-  Wi[2] = pi->primitives.v[1];
-  Wi[3] = pi->primitives.v[2];
-  Wi[4] = pi->primitives.P;
-  Wj[0] = pj->primitives.rho;
-  Wj[1] = pj->primitives.v[0];
-  Wj[2] = pj->primitives.v[1];
-  Wj[3] = pj->primitives.v[2];
-  Wj[4] = pj->primitives.P;
+  Wi[0] = pi->rho;
+  Wi[1] = pi->v[0];
+  Wi[2] = pi->v[1];
+  Wi[3] = pi->v[2];
+  Wi[4] = pi->P;
+  Wj[0] = pj->rho;
+  Wj[1] = pj->v[0];
+  Wj[2] = pj->v[1];
+  Wj[3] = pj->v[2];
+  Wj[4] = pj->P;
 
   /* Compute kernel of pi. */
   float wi, wi_dx;
-  const float hi_inv = 1.f / hi;
+  const float hi_inv = 1.0f / hi;
   const float xi = r * hi_inv;
   kernel_deval(xi, &wi, &wi_dx);
 
-  if (pi->density.wcorr > const_gizmo_min_wcorr) {
-    /* Compute gradients for pi */
-    /* there is a sign difference w.r.t. eqn. (6) because of the inverse
-     * definition of dx */
-    pi->primitives.gradients.rho[0] +=
-        (Wi[0] - Wj[0]) * wi *
-        (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
-    pi->primitives.gradients.rho[1] +=
-        (Wi[0] - Wj[0]) * wi *
-        (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
-    pi->primitives.gradients.rho[2] +=
-        (Wi[0] - Wj[0]) * wi *
-        (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
-
-    pi->primitives.gradients.v[0][0] +=
-        (Wi[1] - Wj[1]) * wi *
-        (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
-    pi->primitives.gradients.v[0][1] +=
-        (Wi[1] - Wj[1]) * wi *
-        (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
-    pi->primitives.gradients.v[0][2] +=
-        (Wi[1] - Wj[1]) * wi *
-        (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
-    pi->primitives.gradients.v[1][0] +=
-        (Wi[2] - Wj[2]) * wi *
-        (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
-    pi->primitives.gradients.v[1][1] +=
-        (Wi[2] - Wj[2]) * wi *
-        (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
-    pi->primitives.gradients.v[1][2] +=
-        (Wi[2] - Wj[2]) * wi *
-        (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
-    pi->primitives.gradients.v[2][0] +=
-        (Wi[3] - Wj[3]) * wi *
-        (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
-    pi->primitives.gradients.v[2][1] +=
-        (Wi[3] - Wj[3]) * wi *
-        (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
-    pi->primitives.gradients.v[2][2] +=
-        (Wi[3] - Wj[3]) * wi *
-        (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
-
-    pi->primitives.gradients.P[0] +=
-        (Wi[4] - Wj[4]) * wi *
-        (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
-    pi->primitives.gradients.P[1] +=
-        (Wi[4] - Wj[4]) * wi *
-        (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
-    pi->primitives.gradients.P[2] +=
-        (Wi[4] - Wj[4]) * wi *
-        (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
+  const float dW[5] = {Wi[0] - Wj[0], Wi[1] - Wj[1], Wi[2] - Wj[2],
+                       Wi[3] - Wj[3], Wi[4] - Wj[4]};
 
+  float wiBidx[3];
+  if (pi->geometry.wcorr > const_gizmo_min_wcorr) {
+    wiBidx[0] = wi * (Bi[0][0] * dx[0] + Bi[0][1] * dx[1] + Bi[0][2] * dx[2]);
+    wiBidx[1] = wi * (Bi[1][0] * dx[0] + Bi[1][1] * dx[1] + Bi[1][2] * dx[2]);
+    wiBidx[2] = wi * (Bi[2][0] * dx[0] + Bi[2][1] * dx[1] + Bi[2][2] * dx[2]);
   } else {
-    /* Gradient matrix is not well-behaved, switch to SPH gradients */
-
-    pi->primitives.gradients.rho[0] -=
-        wi_dx * dx[0] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-    pi->primitives.gradients.rho[1] -=
-        wi_dx * dx[1] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-    pi->primitives.gradients.rho[2] -=
-        wi_dx * dx[2] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-
-    pi->primitives.gradients.v[0][0] -=
-        wi_dx * dx[0] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-    pi->primitives.gradients.v[0][1] -=
-        wi_dx * dx[1] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-    pi->primitives.gradients.v[0][2] -=
-        wi_dx * dx[2] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-    pi->primitives.gradients.v[1][0] -=
-        wi_dx * dx[0] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-    pi->primitives.gradients.v[1][1] -=
-        wi_dx * dx[1] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-    pi->primitives.gradients.v[1][2] -=
-        wi_dx * dx[2] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-
-    pi->primitives.gradients.v[2][0] -=
-        wi_dx * dx[0] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-    pi->primitives.gradients.v[2][1] -=
-        wi_dx * dx[1] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-    pi->primitives.gradients.v[2][2] -=
-        wi_dx * dx[2] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-
-    pi->primitives.gradients.P[0] -=
-        wi_dx * dx[0] * (pi->primitives.P - pj->primitives.P) * r_inv;
-    pi->primitives.gradients.P[1] -=
-        wi_dx * dx[1] * (pi->primitives.P - pj->primitives.P) * r_inv;
-    pi->primitives.gradients.P[2] -=
-        wi_dx * dx[2] * (pi->primitives.P - pj->primitives.P) * r_inv;
+    const float norm = -wi_dx * r_inv;
+    wiBidx[0] = norm * dx[0];
+    wiBidx[1] = norm * dx[1];
+    wiBidx[2] = norm * dx[2];
   }
 
+  /* Compute gradients for pi */
+  /* there is a sign difference w.r.t. eqn. (6) because of the inverse
+   * definition of dx */
+  pi->gradients.rho[0] += dW[0] * wiBidx[0];
+  pi->gradients.rho[1] += dW[0] * wiBidx[1];
+  pi->gradients.rho[2] += dW[0] * wiBidx[2];
+
+  pi->gradients.v[0][0] += dW[1] * wiBidx[0];
+  pi->gradients.v[0][1] += dW[1] * wiBidx[1];
+  pi->gradients.v[0][2] += dW[1] * wiBidx[2];
+  pi->gradients.v[1][0] += dW[2] * wiBidx[0];
+  pi->gradients.v[1][1] += dW[2] * wiBidx[1];
+  pi->gradients.v[1][2] += dW[2] * wiBidx[2];
+  pi->gradients.v[2][0] += dW[3] * wiBidx[0];
+  pi->gradients.v[2][1] += dW[3] * wiBidx[1];
+  pi->gradients.v[2][2] += dW[3] * wiBidx[2];
+
+  pi->gradients.P[0] += dW[4] * wiBidx[0];
+  pi->gradients.P[1] += dW[4] * wiBidx[1];
+  pi->gradients.P[2] += dW[4] * wiBidx[2];
+
   hydro_slope_limit_cell_collect(pi, pj, r);
 }
 
@@ -438,50 +273,33 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_finalize(
   const float h = p->h;
   const float h_inv = 1.0f / h;
   const float ihdim = pow_dimension(h_inv);
-  const float ihdimp1 = pow_dimension_plus_one(h_inv);
-
-  if (p->density.wcorr > const_gizmo_min_wcorr) {
-    p->primitives.gradients.rho[0] *= ihdim;
-    p->primitives.gradients.rho[1] *= ihdim;
-    p->primitives.gradients.rho[2] *= ihdim;
-
-    p->primitives.gradients.v[0][0] *= ihdim;
-    p->primitives.gradients.v[0][1] *= ihdim;
-    p->primitives.gradients.v[0][2] *= ihdim;
-    p->primitives.gradients.v[1][0] *= ihdim;
-    p->primitives.gradients.v[1][1] *= ihdim;
-    p->primitives.gradients.v[1][2] *= ihdim;
-    p->primitives.gradients.v[2][0] *= ihdim;
-    p->primitives.gradients.v[2][1] *= ihdim;
-    p->primitives.gradients.v[2][2] *= ihdim;
-
-    p->primitives.gradients.P[0] *= ihdim;
-    p->primitives.gradients.P[1] *= ihdim;
-    p->primitives.gradients.P[2] *= ihdim;
 
+  float norm;
+  if (p->geometry.wcorr > const_gizmo_min_wcorr) {
+    norm = ihdim;
   } else {
-
-    /* finalize gradients by multiplying with volume */
-    p->primitives.gradients.rho[0] *= ihdimp1 * volume;
-    p->primitives.gradients.rho[1] *= ihdimp1 * volume;
-    p->primitives.gradients.rho[2] *= ihdimp1 * volume;
-
-    p->primitives.gradients.v[0][0] *= ihdimp1 * volume;
-    p->primitives.gradients.v[0][1] *= ihdimp1 * volume;
-    p->primitives.gradients.v[0][2] *= ihdimp1 * volume;
-
-    p->primitives.gradients.v[1][0] *= ihdimp1 * volume;
-    p->primitives.gradients.v[1][1] *= ihdimp1 * volume;
-    p->primitives.gradients.v[1][2] *= ihdimp1 * volume;
-    p->primitives.gradients.v[2][0] *= ihdimp1 * volume;
-    p->primitives.gradients.v[2][1] *= ihdimp1 * volume;
-    p->primitives.gradients.v[2][2] *= ihdimp1 * volume;
-
-    p->primitives.gradients.P[0] *= ihdimp1 * volume;
-    p->primitives.gradients.P[1] *= ihdimp1 * volume;
-    p->primitives.gradients.P[2] *= ihdimp1 * volume;
+    const float ihdimp1 = pow_dimension_plus_one(h_inv);
+    norm = ihdimp1 * volume;
   }
 
+  p->gradients.rho[0] *= norm;
+  p->gradients.rho[1] *= norm;
+  p->gradients.rho[2] *= norm;
+
+  p->gradients.v[0][0] *= norm;
+  p->gradients.v[0][1] *= norm;
+  p->gradients.v[0][2] *= norm;
+  p->gradients.v[1][0] *= norm;
+  p->gradients.v[1][1] *= norm;
+  p->gradients.v[1][2] *= norm;
+  p->gradients.v[2][0] *= norm;
+  p->gradients.v[2][1] *= norm;
+  p->gradients.v[2][2] *= norm;
+
+  p->gradients.P[0] *= norm;
+  p->gradients.P[1] *= norm;
+  p->gradients.P[2] *= norm;
+
   hydro_slope_limit_cell(p);
 }
 
diff --git a/src/hydro/GizmoMFM/hydro_gradients_sph.h b/src/hydro/GizmoMFM/hydro_gradients_sph.h
index 169bed74f0b1b7e966f9880248f811d100bec13b..58233c3b75b22c4ba6347bb6e5db5e4e0e2ebe71 100644
--- a/src/hydro/GizmoMFM/hydro_gradients_sph.h
+++ b/src/hydro/GizmoMFM/hydro_gradients_sph.h
@@ -28,24 +28,24 @@
 __attribute__((always_inline)) INLINE static void hydro_gradients_init(
     struct part *p) {
 
-  p->primitives.gradients.rho[0] = 0.0f;
-  p->primitives.gradients.rho[1] = 0.0f;
-  p->primitives.gradients.rho[2] = 0.0f;
+  p->gradients.rho[0] = 0.0f;
+  p->gradients.rho[1] = 0.0f;
+  p->gradients.rho[2] = 0.0f;
 
-  p->primitives.gradients.v[0][0] = 0.0f;
-  p->primitives.gradients.v[0][1] = 0.0f;
-  p->primitives.gradients.v[0][2] = 0.0f;
+  p->gradients.v[0][0] = 0.0f;
+  p->gradients.v[0][1] = 0.0f;
+  p->gradients.v[0][2] = 0.0f;
 
-  p->primitives.gradients.v[1][0] = 0.0f;
-  p->primitives.gradients.v[1][1] = 0.0f;
-  p->primitives.gradients.v[1][2] = 0.0f;
-  p->primitives.gradients.v[2][0] = 0.0f;
-  p->primitives.gradients.v[2][1] = 0.0f;
-  p->primitives.gradients.v[2][2] = 0.0f;
+  p->gradients.v[1][0] = 0.0f;
+  p->gradients.v[1][1] = 0.0f;
+  p->gradients.v[1][2] = 0.0f;
+  p->gradients.v[2][0] = 0.0f;
+  p->gradients.v[2][1] = 0.0f;
+  p->gradients.v[2][2] = 0.0f;
 
-  p->primitives.gradients.P[0] = 0.0f;
-  p->primitives.gradients.P[1] = 0.0f;
-  p->primitives.gradients.P[2] = 0.0f;
+  p->gradients.P[0] = 0.0f;
+  p->gradients.P[1] = 0.0f;
+  p->gradients.P[2] = 0.0f;
 
   hydro_slope_limit_cell_init(p);
 }
@@ -64,7 +64,7 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_collect(
     float r2, const float *dx, float hi, float hj, struct part *restrict pi,
     struct part *restrict pj) {
 
-  const float r_inv = 1.f / sqrtf(r2);
+  const float r_inv = 1.0f / sqrtf(r2);
   const float r = r2 * r_inv;
 
   float wi, wi_dx;
@@ -72,41 +72,29 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_collect(
   const float xi = r * hi_inv;
   kernel_deval(xi, &wi, &wi_dx);
 
-  /* very basic gradient estimate */
-  pi->primitives.gradients.rho[0] -=
-      wi_dx * dx[0] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-  pi->primitives.gradients.rho[1] -=
-      wi_dx * dx[1] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-  pi->primitives.gradients.rho[2] -=
-      wi_dx * dx[2] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-
-  pi->primitives.gradients.v[0][0] -=
-      wi_dx * dx[0] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-  pi->primitives.gradients.v[0][1] -=
-      wi_dx * dx[1] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-  pi->primitives.gradients.v[0][2] -=
-      wi_dx * dx[2] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-
-  pi->primitives.gradients.v[1][0] -=
-      wi_dx * dx[0] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-  pi->primitives.gradients.v[1][1] -=
-      wi_dx * dx[1] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-  pi->primitives.gradients.v[1][2] -=
-      wi_dx * dx[2] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-
-  pi->primitives.gradients.v[2][0] -=
-      wi_dx * dx[0] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-  pi->primitives.gradients.v[2][1] -=
-      wi_dx * dx[1] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-  pi->primitives.gradients.v[2][2] -=
-      wi_dx * dx[2] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-
-  pi->primitives.gradients.P[0] -=
-      wi_dx * dx[0] * (pi->primitives.P - pj->primitives.P) * r_inv;
-  pi->primitives.gradients.P[1] -=
-      wi_dx * dx[1] * (pi->primitives.P - pj->primitives.P) * r_inv;
-  pi->primitives.gradients.P[2] -=
-      wi_dx * dx[2] * (pi->primitives.P - pj->primitives.P) * r_inv;
+  const float dW[5] = {pi->rho - pj->rho, pi->v[0] - pj->v[0],
+                       pi->v[1] - pj->v[1], pi->v[2] - pj->v[2], pi->P - pj->P};
+
+  const float normi = wi_dx * r_inv;
+  const float nidx[3] = {normi * dx[0], normi * dx[1], normi * dx[2]};
+
+  pi->gradients.rho[0] -= dW[0] * nidx[0];
+  pi->gradients.rho[1] -= dW[0] * nidx[1];
+  pi->gradients.rho[2] -= dW[0] * nidx[2];
+
+  pi->gradients.v[0][0] -= dW[1] * nidx[0];
+  pi->gradients.v[0][1] -= dW[1] * nidx[1];
+  pi->gradients.v[0][2] -= dW[1] * nidx[2];
+  pi->gradients.v[1][0] -= dW[2] * nidx[0];
+  pi->gradients.v[1][1] -= dW[2] * nidx[1];
+  pi->gradients.v[1][2] -= dW[2] * nidx[2];
+  pi->gradients.v[2][0] -= dW[3] * nidx[0];
+  pi->gradients.v[2][1] -= dW[3] * nidx[1];
+  pi->gradients.v[2][2] -= dW[3] * nidx[2];
+
+  pi->gradients.P[0] -= dW[4] * nidx[0];
+  pi->gradients.P[1] -= dW[4] * nidx[1];
+  pi->gradients.P[2] -= dW[4] * nidx[2];
 
   hydro_slope_limit_cell_collect(pi, pj, r);
 
@@ -115,40 +103,27 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_collect(
   const float xj = r * hj_inv;
   kernel_deval(xj, &wj, &wj_dx);
 
+  const float normj = wj_dx * r_inv;
+  const float njdx[3] = {normj * dx[0], normj * dx[1], normj * dx[2]};
+
   /* signs are the same as before, since we swap i and j twice */
-  pj->primitives.gradients.rho[0] -=
-      wj_dx * dx[0] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-  pj->primitives.gradients.rho[1] -=
-      wj_dx * dx[1] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-  pj->primitives.gradients.rho[2] -=
-      wj_dx * dx[2] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-
-  pj->primitives.gradients.v[0][0] -=
-      wj_dx * dx[0] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-  pj->primitives.gradients.v[0][1] -=
-      wj_dx * dx[1] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-  pj->primitives.gradients.v[0][2] -=
-      wj_dx * dx[2] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-
-  pj->primitives.gradients.v[1][0] -=
-      wj_dx * dx[0] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-  pj->primitives.gradients.v[1][1] -=
-      wj_dx * dx[1] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-  pj->primitives.gradients.v[1][2] -=
-      wj_dx * dx[2] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-  pj->primitives.gradients.v[2][0] -=
-      wj_dx * dx[0] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-  pj->primitives.gradients.v[2][1] -=
-      wj_dx * dx[1] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-  pj->primitives.gradients.v[2][2] -=
-      wj_dx * dx[2] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-
-  pj->primitives.gradients.P[0] -=
-      wj_dx * dx[0] * (pi->primitives.P - pj->primitives.P) * r_inv;
-  pj->primitives.gradients.P[1] -=
-      wj_dx * dx[1] * (pi->primitives.P - pj->primitives.P) * r_inv;
-  pj->primitives.gradients.P[2] -=
-      wj_dx * dx[2] * (pi->primitives.P - pj->primitives.P) * r_inv;
+  pj->gradients.rho[0] -= dW[0] * njdx[0];
+  pj->gradients.rho[1] -= dW[0] * njdx[1];
+  pj->gradients.rho[2] -= dW[0] * njdx[2];
+
+  pj->gradients.v[0][0] -= dW[1] * njdx[0];
+  pj->gradients.v[0][1] -= dW[1] * njdx[1];
+  pj->gradients.v[0][2] -= dW[1] * njdx[2];
+  pj->gradients.v[1][0] -= dW[2] * njdx[0];
+  pj->gradients.v[1][1] -= dW[2] * njdx[1];
+  pj->gradients.v[1][2] -= dW[2] * njdx[2];
+  pj->gradients.v[2][0] -= dW[3] * njdx[0];
+  pj->gradients.v[2][1] -= dW[3] * njdx[1];
+  pj->gradients.v[2][2] -= dW[3] * njdx[2];
+
+  pj->gradients.P[0] -= dW[4] * njdx[0];
+  pj->gradients.P[1] -= dW[4] * njdx[1];
+  pj->gradients.P[2] -= dW[4] * njdx[2];
 
   hydro_slope_limit_cell_collect(pj, pi, r);
 }
@@ -169,7 +144,7 @@ hydro_gradients_nonsym_collect(float r2, const float *dx, float hi, float hj,
                                struct part *restrict pi,
                                struct part *restrict pj) {
 
-  const float r_inv = 1.f / sqrtf(r2);
+  const float r_inv = 1.0f / sqrtf(r2);
   const float r = r2 * r_inv;
 
   float wi, wi_dx;
@@ -177,41 +152,29 @@ hydro_gradients_nonsym_collect(float r2, const float *dx, float hi, float hj,
   const float xi = r * hi_inv;
   kernel_deval(xi, &wi, &wi_dx);
 
-  /* very basic gradient estimate */
-  pi->primitives.gradients.rho[0] -=
-      wi_dx * dx[0] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-  pi->primitives.gradients.rho[1] -=
-      wi_dx * dx[1] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-  pi->primitives.gradients.rho[2] -=
-      wi_dx * dx[2] * (pi->primitives.rho - pj->primitives.rho) * r_inv;
-
-  pi->primitives.gradients.v[0][0] -=
-      wi_dx * dx[0] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-  pi->primitives.gradients.v[0][1] -=
-      wi_dx * dx[1] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-  pi->primitives.gradients.v[0][2] -=
-      wi_dx * dx[2] * (pi->primitives.v[0] - pj->primitives.v[0]) * r_inv;
-
-  pi->primitives.gradients.v[1][0] -=
-      wi_dx * dx[0] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-  pi->primitives.gradients.v[1][1] -=
-      wi_dx * dx[1] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-  pi->primitives.gradients.v[1][2] -=
-      wi_dx * dx[2] * (pi->primitives.v[1] - pj->primitives.v[1]) * r_inv;
-
-  pi->primitives.gradients.v[2][0] -=
-      wi_dx * dx[0] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-  pi->primitives.gradients.v[2][1] -=
-      wi_dx * dx[1] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-  pi->primitives.gradients.v[2][2] -=
-      wi_dx * dx[2] * (pi->primitives.v[2] - pj->primitives.v[2]) * r_inv;
-
-  pi->primitives.gradients.P[0] -=
-      wi_dx * dx[0] * (pi->primitives.P - pj->primitives.P) * r_inv;
-  pi->primitives.gradients.P[1] -=
-      wi_dx * dx[1] * (pi->primitives.P - pj->primitives.P) * r_inv;
-  pi->primitives.gradients.P[2] -=
-      wi_dx * dx[2] * (pi->primitives.P - pj->primitives.P) * r_inv;
+  const float dW[5] = {pi->rho - pj->rho, pi->v[0] - pj->v[0],
+                       pi->v[1] - pj->v[1], pi->v[2] - pj->v[2], pi->P - pj->P};
+
+  const float normi = wi_dx * r_inv;
+  const float nidx[3] = {normi * dx[0], normi * dx[1], normi * dx[2]};
+
+  pi->gradients.rho[0] -= dW[0] * nidx[0];
+  pi->gradients.rho[1] -= dW[0] * nidx[1];
+  pi->gradients.rho[2] -= dW[0] * nidx[2];
+
+  pi->gradients.v[0][0] -= dW[1] * nidx[0];
+  pi->gradients.v[0][1] -= dW[1] * nidx[1];
+  pi->gradients.v[0][2] -= dW[1] * nidx[2];
+  pi->gradients.v[1][0] -= dW[2] * nidx[0];
+  pi->gradients.v[1][1] -= dW[2] * nidx[1];
+  pi->gradients.v[1][2] -= dW[2] * nidx[2];
+  pi->gradients.v[2][0] -= dW[3] * nidx[0];
+  pi->gradients.v[2][1] -= dW[3] * nidx[1];
+  pi->gradients.v[2][2] -= dW[3] * nidx[2];
+
+  pi->gradients.P[0] -= dW[4] * nidx[0];
+  pi->gradients.P[1] -= dW[4] * nidx[1];
+  pi->gradients.P[2] -= dW[4] * nidx[2];
 
   hydro_slope_limit_cell_collect(pi, pj, r);
 }
@@ -229,26 +192,28 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_finalize(
   const float ihdimp1 = pow_dimension_plus_one(ih);
   const float volume = p->geometry.volume;
 
+  const float norm = ihdimp1 * volume;
+
   /* finalize gradients by multiplying with volume */
-  p->primitives.gradients.rho[0] *= ihdimp1 * volume;
-  p->primitives.gradients.rho[1] *= ihdimp1 * volume;
-  p->primitives.gradients.rho[2] *= ihdimp1 * volume;
+  p->gradients.rho[0] *= norm;
+  p->gradients.rho[1] *= norm;
+  p->gradients.rho[2] *= norm;
 
-  p->primitives.gradients.v[0][0] *= ihdimp1 * volume;
-  p->primitives.gradients.v[0][1] *= ihdimp1 * volume;
-  p->primitives.gradients.v[0][2] *= ihdimp1 * volume;
+  p->gradients.v[0][0] *= norm;
+  p->gradients.v[0][1] *= norm;
+  p->gradients.v[0][2] *= norm;
 
-  p->primitives.gradients.v[1][0] *= ihdimp1 * volume;
-  p->primitives.gradients.v[1][1] *= ihdimp1 * volume;
-  p->primitives.gradients.v[1][2] *= ihdimp1 * volume;
+  p->gradients.v[1][0] *= norm;
+  p->gradients.v[1][1] *= norm;
+  p->gradients.v[1][2] *= norm;
 
-  p->primitives.gradients.v[2][0] *= ihdimp1 * volume;
-  p->primitives.gradients.v[2][1] *= ihdimp1 * volume;
-  p->primitives.gradients.v[2][2] *= ihdimp1 * volume;
+  p->gradients.v[2][0] *= norm;
+  p->gradients.v[2][1] *= norm;
+  p->gradients.v[2][2] *= norm;
 
-  p->primitives.gradients.P[0] *= ihdimp1 * volume;
-  p->primitives.gradients.P[1] *= ihdimp1 * volume;
-  p->primitives.gradients.P[2] *= ihdimp1 * volume;
+  p->gradients.P[0] *= norm;
+  p->gradients.P[1] *= norm;
+  p->gradients.P[2] *= norm;
 
   hydro_slope_limit_cell(p);
 }
diff --git a/src/hydro/GizmoMFM/hydro_iact.h b/src/hydro/GizmoMFM/hydro_iact.h
index a1a82e514baa60d5895343ea84ef1c3aedc8a6b7..5bed20d7f894a76d5fe3642c7438dc03195e43d6 100644
--- a/src/hydro/GizmoMFM/hydro_iact.h
+++ b/src/hydro/GizmoMFM/hydro_iact.h
@@ -57,7 +57,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_density(
   const float r = sqrtf(r2);
 
   /* Compute density of pi. */
-  const float hi_inv = 1.f / hi;
+  const float hi_inv = 1.0f / hi;
   const float xi = r * hi_inv;
   kernel_deval(xi, &wi, &wi_dx);
 
@@ -75,7 +75,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_density(
   pi->geometry.centroid[2] -= dx[2] * wi;
 
   /* Compute density of pj. */
-  const float hj_inv = 1.f / hj;
+  const float hj_inv = 1.0f / hj;
   const float xj = r * hj_inv;
   kernel_deval(xj, &wj, &wj_dx);
 
@@ -123,7 +123,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density(
   /* Get r and h inverse. */
   const float r = sqrtf(r2);
 
-  const float hi_inv = 1.f / hi;
+  const float hi_inv = 1.0f / hi;
   const float xi = r * hi_inv;
   kernel_deval(xi, &wi, &wi_dx);
 
@@ -220,7 +220,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
     float r2, const float *dx, float hi, float hj, struct part *restrict pi,
     struct part *restrict pj, int mode, float a, float H) {
 
-  const float r_inv = 1.f / sqrtf(r2);
+  const float r_inv = 1.0f / sqrtf(r2);
   const float r = r2 * r_inv;
 
   /* Initialize local variables */
@@ -238,16 +238,16 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   const float Vi = pi->geometry.volume;
   const float Vj = pj->geometry.volume;
   float Wi[5], Wj[5];
-  Wi[0] = pi->primitives.rho;
-  Wi[1] = pi->primitives.v[0];
-  Wi[2] = pi->primitives.v[1];
-  Wi[3] = pi->primitives.v[2];
-  Wi[4] = pi->primitives.P;
-  Wj[0] = pj->primitives.rho;
-  Wj[1] = pj->primitives.v[0];
-  Wj[2] = pj->primitives.v[1];
-  Wj[3] = pj->primitives.v[2];
-  Wj[4] = pj->primitives.P;
+  Wi[0] = pi->rho;
+  Wi[1] = pi->v[0];
+  Wi[2] = pi->v[1];
+  Wi[3] = pi->v[2];
+  Wi[4] = pi->P;
+  Wj[0] = pj->rho;
+  Wj[1] = pj->v[0];
+  Wj[2] = pj->v[1];
+  Wj[3] = pj->v[2];
+  Wj[4] = pj->P;
 
   /* calculate the maximal signal velocity */
   float vmax;
@@ -258,21 +258,17 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   } else
     vmax = 0.0f;
 
-  float dvdr = (pi->v[0] - pj->v[0]) * dx[0] + (pi->v[1] - pj->v[1]) * dx[1] +
-               (pi->v[2] - pj->v[2]) * dx[2];
-
   /* Velocity on the axis linking the particles */
-  float dvdotdx = (Wi[1] - Wj[1]) * dx[0] + (Wi[2] - Wj[2]) * dx[1] +
-                  (Wi[3] - Wj[3]) * dx[2];
-  dvdotdx = min(dvdotdx, dvdr);
+  float dvdr = (Wi[1] - Wj[1]) * dx[0] + (Wi[2] - Wj[2]) * dx[1] +
+               (Wi[3] - Wj[3]) * dx[2];
 
-  /* We only care about this velocity for particles moving towards each others
+  /* We only care about this velocity for particles moving towards each other
    */
-  dvdotdx = min(dvdotdx, 0.f);
+  const float dvdotdx = min(dvdr, 0.0f);
 
   /* Get the signal velocity */
   /* the magical factor 3 also appears in Gadget2 */
-  vmax -= 3.f * dvdotdx * r_inv;
+  vmax -= 3.0f * dvdotdx * r_inv;
 
   /* Store the signal velocity */
   pi->timestepvars.vmax = max(pi->timestepvars.vmax, vmax);
@@ -280,14 +276,14 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
 
   /* Compute kernel of pi. */
   float wi, wi_dx;
-  const float hi_inv = 1.f / hi;
+  const float hi_inv = 1.0f / hi;
   const float hi_inv_dim = pow_dimension(hi_inv);
   const float xi = r * hi_inv;
   kernel_deval(xi, &wi, &wi_dx);
 
   /* Compute kernel of pj. */
   float wj, wj_dx;
-  const float hj_inv = 1.f / hj;
+  const float hj_inv = 1.0f / hj;
   const float hj_inv_dim = pow_dimension(hj_inv);
   const float xj = r * hj_inv;
   kernel_deval(xj, &wj, &wj_dx);
@@ -298,17 +294,17 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   const float wi_dr = hidp1 * wi_dx;
   const float wj_dr = hjdp1 * wj_dx;
   dvdr *= r_inv;
-  if (pj->primitives.rho > 0.)
-    pi->force.h_dt -= pj->conserved.mass * dvdr / pj->primitives.rho * wi_dr;
-  if (mode == 1 && pi->primitives.rho > 0.)
-    pj->force.h_dt -= pi->conserved.mass * dvdr / pi->primitives.rho * wj_dr;
+  if (pj->rho > 0.0f)
+    pi->force.h_dt -= pj->conserved.mass * dvdr / pj->rho * wi_dr;
+  if (mode == 1 && pi->rho > 0.0f)
+    pj->force.h_dt -= pi->conserved.mass * dvdr / pi->rho * wj_dr;
 
   /* Compute (square of) area */
   /* eqn. (7) */
   float Anorm2 = 0.0f;
   float A[3];
-  if (pi->density.wcorr > const_gizmo_min_wcorr &&
-      pj->density.wcorr > const_gizmo_min_wcorr) {
+  if (pi->geometry.wcorr > const_gizmo_min_wcorr &&
+      pj->geometry.wcorr > const_gizmo_min_wcorr) {
     /* in principle, we use Vi and Vj as weights for the left and right
        contributions to the generalized surface vector.
        However, if Vi and Vj are very different (because they have very
@@ -342,10 +338,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
 
   /* if the interface has no area, nothing happens and we return */
   /* continuing results in dividing by zero and NaN's... */
-  if (Anorm2 == 0.f) return;
+  if (Anorm2 == 0.0f) return;
 
   /* Compute the area */
-  const float Anorm_inv = 1. / sqrtf(Anorm2);
+  const float Anorm_inv = 1.0f / sqrtf(Anorm2);
   const float Anorm = Anorm2 * Anorm_inv;
 
 #ifdef SWIFT_DEBUG_CHECKS
@@ -375,11 +371,9 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
 
   /* Compute interface velocity */
   /* eqn. (9) */
-  float xijdotdx = xij_i[0] * dx[0] + xij_i[1] * dx[1] + xij_i[2] * dx[2];
-  xijdotdx *= r_inv * r_inv;
-  const float vij[3] = {vi[0] + (vi[0] - vj[0]) * xijdotdx,
-                        vi[1] + (vi[1] - vj[1]) * xijdotdx,
-                        vi[2] + (vi[2] - vj[2]) * xijdotdx};
+  const float vij[3] = {vi[0] + (vi[0] - vj[0]) * xfac,
+                        vi[1] + (vi[1] - vj[1]) * xfac,
+                        vi[2] + (vi[2] - vj[2]) * xfac};
 
   /* complete calculation of position of interface */
   /* NOTE: dx is not necessarily just pi->x - pj->x but can also contain
@@ -391,6 +385,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   //    for ( k = 0 ; k < 3 ; k++ )
   //      xij[k] += pi->x[k];
 
+  hydro_gradients_predict(pi, pj, hi, hj, dx, r, xij_i, Wi, Wj);
+
   /* Boost the primitive variables to the frame of reference of the interface */
   /* Note that velocities are indices 1-3 in W */
   Wi[1] -= vij[0];
@@ -400,8 +396,6 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   Wj[2] -= vij[1];
   Wj[3] -= vij[2];
 
-  hydro_gradients_predict(pi, pj, hi, hj, dx, r, xij_i, Wi, Wj);
-
   /* we don't need to rotate, we can use the unit vector in the Riemann problem
    * itself (see GIZMO) */
 
@@ -409,34 +403,24 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   riemann_solve_for_middle_state_flux(Wi, Wj, n_unit, vij, totflux);
 
   /* Multiply with the interface surface area */
-  totflux[0] *= Anorm;
   totflux[1] *= Anorm;
   totflux[2] *= Anorm;
   totflux[3] *= Anorm;
   totflux[4] *= Anorm;
 
-  /* Store mass flux */
-  const float mflux_i = totflux[0];
-  pi->gravity.mflux[0] += mflux_i * dx[0];
-  pi->gravity.mflux[1] += mflux_i * dx[1];
-  pi->gravity.mflux[2] += mflux_i * dx[2];
-
   /* Update conserved variables */
+  /* We shamelessly exploit the fact that the mass flux is zero and omit all
+     terms involving it */
   /* eqn. (16) */
-  pi->conserved.flux.mass -= totflux[0];
-  pi->conserved.flux.momentum[0] -= totflux[1];
-  pi->conserved.flux.momentum[1] -= totflux[2];
-  pi->conserved.flux.momentum[2] -= totflux[3];
-  pi->conserved.flux.energy -= totflux[4];
+  pi->flux.momentum[0] -= totflux[1];
+  pi->flux.momentum[1] -= totflux[2];
+  pi->flux.momentum[2] -= totflux[3];
+  pi->flux.energy -= totflux[4];
 
 #ifndef GIZMO_TOTAL_ENERGY
-  const float ekin_i = 0.5f * (pi->primitives.v[0] * pi->primitives.v[0] +
-                               pi->primitives.v[1] * pi->primitives.v[1] +
-                               pi->primitives.v[2] * pi->primitives.v[2]);
-  pi->conserved.flux.energy += totflux[1] * pi->primitives.v[0];
-  pi->conserved.flux.energy += totflux[2] * pi->primitives.v[1];
-  pi->conserved.flux.energy += totflux[3] * pi->primitives.v[2];
-  pi->conserved.flux.energy -= totflux[0] * ekin_i;
+  pi->flux.energy += totflux[1] * pi->v[0];
+  pi->flux.energy += totflux[2] * pi->v[1];
+  pi->flux.energy += totflux[3] * pi->v[2];
 #endif
 
   /* Note that this used to be much more complicated in early implementations of
@@ -445,26 +429,15 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
    * conservation anymore and just assume the current fluxes are representative
    * for the flux over the entire time step. */
   if (mode == 1) {
-    /* Store mass flux */
-    const float mflux_j = totflux[0];
-    pj->gravity.mflux[0] -= mflux_j * dx[0];
-    pj->gravity.mflux[1] -= mflux_j * dx[1];
-    pj->gravity.mflux[2] -= mflux_j * dx[2];
-
-    pj->conserved.flux.mass += totflux[0];
-    pj->conserved.flux.momentum[0] += totflux[1];
-    pj->conserved.flux.momentum[1] += totflux[2];
-    pj->conserved.flux.momentum[2] += totflux[3];
-    pj->conserved.flux.energy += totflux[4];
+    pj->flux.momentum[0] += totflux[1];
+    pj->flux.momentum[1] += totflux[2];
+    pj->flux.momentum[2] += totflux[3];
+    pj->flux.energy += totflux[4];
 
 #ifndef GIZMO_TOTAL_ENERGY
-    const float ekin_j = 0.5f * (pj->primitives.v[0] * pj->primitives.v[0] +
-                                 pj->primitives.v[1] * pj->primitives.v[1] +
-                                 pj->primitives.v[2] * pj->primitives.v[2]);
-    pj->conserved.flux.energy -= totflux[1] * pj->primitives.v[0];
-    pj->conserved.flux.energy -= totflux[2] * pj->primitives.v[1];
-    pj->conserved.flux.energy -= totflux[3] * pj->primitives.v[2];
-    pj->conserved.flux.energy += totflux[0] * ekin_j;
+    pj->flux.energy -= totflux[1] * pj->v[0];
+    pj->flux.energy -= totflux[2] * pj->v[1];
+    pj->flux.energy -= totflux[3] * pj->v[2];
 #endif
   }
 }
diff --git a/src/hydro/GizmoMFM/hydro_io.h b/src/hydro/GizmoMFM/hydro_io.h
index 59d579f70cd4aedc728dbf42038eff78d4c507d5..1f956edf3fdc31990c6aba254603ea69a98238eb 100644
--- a/src/hydro/GizmoMFM/hydro_io.h
+++ b/src/hydro/GizmoMFM/hydro_io.h
@@ -63,7 +63,7 @@ INLINE static void hydro_read_particles(struct part* parts,
   list[6] = io_make_input_field("Accelerations", FLOAT, 3, OPTIONAL,
                                 UNIT_CONV_ACCELERATION, parts, a_hydro);
   list[7] = io_make_input_field("Density", FLOAT, 1, OPTIONAL,
-                                UNIT_CONV_DENSITY, parts, primitives.rho);
+                                UNIT_CONV_DENSITY, parts, rho);
 }
 
 /**
@@ -203,12 +203,12 @@ INLINE static void hydro_write_particles(const struct part* parts,
                                               parts, xparts, convert_u);
   list[5] = io_make_output_field("ParticleIDs", ULONGLONG, 1,
                                  UNIT_CONV_NO_UNITS, parts, id);
-  list[6] = io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts,
-                                 primitives.rho);
+  list[6] =
+      io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts, rho);
   list[7] = io_make_output_field_convert_part(
       "Entropy", FLOAT, 1, UNIT_CONV_ENTROPY, parts, xparts, convert_A);
-  list[8] = io_make_output_field("Pressure", FLOAT, 1, UNIT_CONV_PRESSURE,
-                                 parts, primitives.P);
+  list[8] =
+      io_make_output_field("Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, P);
   list[9] = io_make_output_field_convert_part(
       "TotEnergy", FLOAT, 1, UNIT_CONV_ENERGY, parts, xparts, convert_Etot);
 
diff --git a/src/hydro/GizmoMFM/hydro_part.h b/src/hydro/GizmoMFM/hydro_part.h
index 857c429ec933ad3eea730e8f0b6f830782cdf77b..0055d7d86a35746a8ba90015b3a6986f8ddb5f9f 100644
--- a/src/hydro/GizmoMFM/hydro_part.h
+++ b/src/hydro/GizmoMFM/hydro_part.h
@@ -63,31 +63,23 @@ struct part {
   /* Particle smoothing length. */
   float h;
 
-  /* The primitive hydrodynamical variables. */
-  struct {
-
-    /* Density. */
-    float rho;
-
-    /* Fluid velocity. */
-    float v[3];
+  /* Density. */
+  float rho;
 
-    /* Pressure. */
-    float P;
+  /* Pressure. */
+  float P;
 
-    /* Gradients of the primitive variables. */
+  union {
+    /* Quantities used during the volume (=density) loop. */
     struct {
 
-      /* Density gradients. */
-      float rho[3];
+      /* Derivative of particle number density. */
+      float wcount_dh;
 
-      /* Fluid velocity gradients. */
-      float v[3][3];
+      /* Particle number density. */
+      float wcount;
 
-      /* Pressure gradients. */
-      float P[3];
-
-    } gradients;
+    } density;
 
     /* Quantities needed by the slope limiter. */
     struct {
@@ -106,7 +98,56 @@ struct part {
 
     } limiter;
 
-  } primitives;
+    struct {
+      /* Fluxes. */
+      struct {
+
+        /* No mass flux, since it is always zero. */
+
+        /* Momentum flux. */
+        float momentum[3];
+
+        /* Energy flux. */
+        float energy;
+
+      } flux;
+
+      /* Variables used for timestep calculation. */
+      struct {
+
+        /* Maximum signal velocity among all the neighbours of the particle. The
+         * signal velocity encodes information about the relative fluid
+         * velocities
+         * AND particle velocities of the neighbour and this particle, as well
+         * as
+         * the sound speed of both particles. */
+        float vmax;
+
+      } timestepvars;
+
+      /* Quantities used during the force loop. */
+      struct {
+
+        /* Needed to drift the primitive variables. */
+        float h_dt;
+
+      } force;
+    };
+  };
+
+  /* Gradients of the primitive variables. */
+  struct {
+
+    /* Density gradients. */
+    float rho[3];
+
+    /* Fluid velocity gradients. */
+    float v[3][3];
+
+    /* Pressure gradients. */
+    float P[3];
+
+  } gradients;
 
   /* The conserved hydrodynamical variables. */
   struct {
@@ -120,20 +161,6 @@ struct part {
     /* Fluid thermal energy (not per unit mass!). */
     float energy;
 
-    /* Fluxes. */
-    struct {
-
-      /* Mass flux. */
-      float mass;
-
-      /* Momentum flux. */
-      float momentum[3];
-
-      /* Energy flux. */
-      float energy;
-
-    } flux;
-
   } conserved;
 
   /* Geometrical quantities used for hydro. */
@@ -149,48 +176,10 @@ struct part {
     /* Centroid of the "cell". */
     float centroid[3];
 
-  } geometry;
-
-  /* Variables used for timestep calculation. */
-  struct {
-
-    /* Maximum signal velocity among all the neighbours of the particle. The
-     * signal velocity encodes information about the relative fluid velocities
-     * AND particle velocities of the neighbour and this particle, as well as
-     * the sound speed of both particles. */
-    float vmax;
-
-  } timestepvars;
-
-  /* Quantities used during the volume (=density) loop. */
-  struct {
-
-    /* Derivative of particle number density. */
-    float wcount_dh;
-
-    /* Particle number density. */
-    float wcount;
-
     /* Correction factor for wcount. */
     float wcorr;
 
-  } density;
-
-  /* Quantities used during the force loop. */
-  struct {
-
-    /* Needed to drift the primitive variables. */
-    float h_dt;
-
-  } force;
-
-  /* Specific stuff for the gravity-hydro coupling. */
-  struct {
-
-    /* Current value of the mass flux vector. */
-    float mflux[3];
-
-  } gravity;
+  } geometry;
 
   /* Chemistry information */
   struct chemistry_part_data chemistry_data;
diff --git a/src/hydro/GizmoMFM/hydro_slope_limiters.h b/src/hydro/GizmoMFM/hydro_slope_limiters.h
index 78f2785cdae5dc2334d37e3924dd5b259cca8c05..7c9c759830a4b0ee98412d5a200700c0a148d316 100644
--- a/src/hydro/GizmoMFM/hydro_slope_limiters.h
+++ b/src/hydro/GizmoMFM/hydro_slope_limiters.h
@@ -47,8 +47,8 @@
  * @param r Distance between particle i and particle j.
  */
 __attribute__((always_inline)) INLINE static void hydro_slope_limit_face(
-    float *Wi, float *Wj, float *dWi, float *dWj, float *xij_i, float *xij_j,
-    float r) {}
+    float *Wi, float *Wj, float *dWi, float *dWj, const float *xij_i,
+    const float *xij_j, float r) {}
 
 #endif
 
diff --git a/src/hydro/GizmoMFM/hydro_slope_limiters_cell.h b/src/hydro/GizmoMFM/hydro_slope_limiters_cell.h
index 7dec6f499da31de1f10652a31781a788166957cc..329ca5fda4510a3672bfe698bed52c8f0bebc895 100644
--- a/src/hydro/GizmoMFM/hydro_slope_limiters_cell.h
+++ b/src/hydro/GizmoMFM/hydro_slope_limiters_cell.h
@@ -29,18 +29,18 @@
 __attribute__((always_inline)) INLINE static void hydro_slope_limit_cell_init(
     struct part* p) {
 
-  p->primitives.limiter.rho[0] = FLT_MAX;
-  p->primitives.limiter.rho[1] = -FLT_MAX;
-  p->primitives.limiter.v[0][0] = FLT_MAX;
-  p->primitives.limiter.v[0][1] = -FLT_MAX;
-  p->primitives.limiter.v[1][0] = FLT_MAX;
-  p->primitives.limiter.v[1][1] = -FLT_MAX;
-  p->primitives.limiter.v[2][0] = FLT_MAX;
-  p->primitives.limiter.v[2][1] = -FLT_MAX;
-  p->primitives.limiter.P[0] = FLT_MAX;
-  p->primitives.limiter.P[1] = -FLT_MAX;
-
-  p->primitives.limiter.maxr = -FLT_MAX;
+  p->limiter.rho[0] = FLT_MAX;
+  p->limiter.rho[1] = -FLT_MAX;
+  p->limiter.v[0][0] = FLT_MAX;
+  p->limiter.v[0][1] = -FLT_MAX;
+  p->limiter.v[1][0] = FLT_MAX;
+  p->limiter.v[1][1] = -FLT_MAX;
+  p->limiter.v[2][0] = FLT_MAX;
+  p->limiter.v[2][1] = -FLT_MAX;
+  p->limiter.P[0] = FLT_MAX;
+  p->limiter.P[1] = -FLT_MAX;
+
+  p->limiter.maxr = -FLT_MAX;
 }
 
 /**
@@ -56,30 +56,20 @@ hydro_slope_limit_cell_collect(struct part* pi, struct part* pj, float r) {
 
   /* basic slope limiter: collect the maximal and the minimal value for the
    * primitive variables among the ngbs */
-  pi->primitives.limiter.rho[0] =
-      min(pj->primitives.rho, pi->primitives.limiter.rho[0]);
-  pi->primitives.limiter.rho[1] =
-      max(pj->primitives.rho, pi->primitives.limiter.rho[1]);
-
-  pi->primitives.limiter.v[0][0] =
-      min(pj->primitives.v[0], pi->primitives.limiter.v[0][0]);
-  pi->primitives.limiter.v[0][1] =
-      max(pj->primitives.v[0], pi->primitives.limiter.v[0][1]);
-  pi->primitives.limiter.v[1][0] =
-      min(pj->primitives.v[1], pi->primitives.limiter.v[1][0]);
-  pi->primitives.limiter.v[1][1] =
-      max(pj->primitives.v[1], pi->primitives.limiter.v[1][1]);
-  pi->primitives.limiter.v[2][0] =
-      min(pj->primitives.v[2], pi->primitives.limiter.v[2][0]);
-  pi->primitives.limiter.v[2][1] =
-      max(pj->primitives.v[2], pi->primitives.limiter.v[2][1]);
-
-  pi->primitives.limiter.P[0] =
-      min(pj->primitives.P, pi->primitives.limiter.P[0]);
-  pi->primitives.limiter.P[1] =
-      max(pj->primitives.P, pi->primitives.limiter.P[1]);
-
-  pi->primitives.limiter.maxr = max(r, pi->primitives.limiter.maxr);
+  pi->limiter.rho[0] = min(pj->rho, pi->limiter.rho[0]);
+  pi->limiter.rho[1] = max(pj->rho, pi->limiter.rho[1]);
+
+  pi->limiter.v[0][0] = min(pj->v[0], pi->limiter.v[0][0]);
+  pi->limiter.v[0][1] = max(pj->v[0], pi->limiter.v[0][1]);
+  pi->limiter.v[1][0] = min(pj->v[1], pi->limiter.v[1][0]);
+  pi->limiter.v[1][1] = max(pj->v[1], pi->limiter.v[1][1]);
+  pi->limiter.v[2][0] = min(pj->v[2], pi->limiter.v[2][0]);
+  pi->limiter.v[2][1] = max(pj->v[2], pi->limiter.v[2][1]);
+
+  pi->limiter.P[0] = min(pj->P, pi->limiter.P[0]);
+  pi->limiter.P[1] = max(pj->P, pi->limiter.P[1]);
+
+  pi->limiter.maxr = max(r, pi->limiter.maxr);
 }
 
 /**
@@ -92,94 +82,94 @@ __attribute__((always_inline)) INLINE static void hydro_slope_limit_cell(
 
   float gradtrue, gradrho[3], gradv[3][3], gradP[3];
 
-  gradrho[0] = p->primitives.gradients.rho[0];
-  gradrho[1] = p->primitives.gradients.rho[1];
-  gradrho[2] = p->primitives.gradients.rho[2];
+  gradrho[0] = p->gradients.rho[0];
+  gradrho[1] = p->gradients.rho[1];
+  gradrho[2] = p->gradients.rho[2];
 
-  gradv[0][0] = p->primitives.gradients.v[0][0];
-  gradv[0][1] = p->primitives.gradients.v[0][1];
-  gradv[0][2] = p->primitives.gradients.v[0][2];
+  gradv[0][0] = p->gradients.v[0][0];
+  gradv[0][1] = p->gradients.v[0][1];
+  gradv[0][2] = p->gradients.v[0][2];
 
-  gradv[1][0] = p->primitives.gradients.v[1][0];
-  gradv[1][1] = p->primitives.gradients.v[1][1];
-  gradv[1][2] = p->primitives.gradients.v[1][2];
+  gradv[1][0] = p->gradients.v[1][0];
+  gradv[1][1] = p->gradients.v[1][1];
+  gradv[1][2] = p->gradients.v[1][2];
 
-  gradv[2][0] = p->primitives.gradients.v[2][0];
-  gradv[2][1] = p->primitives.gradients.v[2][1];
-  gradv[2][2] = p->primitives.gradients.v[2][2];
+  gradv[2][0] = p->gradients.v[2][0];
+  gradv[2][1] = p->gradients.v[2][1];
+  gradv[2][2] = p->gradients.v[2][2];
 
-  gradP[0] = p->primitives.gradients.P[0];
-  gradP[1] = p->primitives.gradients.P[1];
-  gradP[2] = p->primitives.gradients.P[2];
+  gradP[0] = p->gradients.P[0];
+  gradP[1] = p->gradients.P[1];
+  gradP[2] = p->gradients.P[2];
 
   gradtrue = sqrtf(gradrho[0] * gradrho[0] + gradrho[1] * gradrho[1] +
                    gradrho[2] * gradrho[2]);
   if (gradtrue) {
-    gradtrue *= p->primitives.limiter.maxr;
-    const float gradmax = p->primitives.limiter.rho[1] - p->primitives.rho;
-    const float gradmin = p->primitives.rho - p->primitives.limiter.rho[0];
-    const float gradtrue_inv = 1.f / gradtrue;
+    gradtrue *= p->limiter.maxr;
+    const float gradmax = p->limiter.rho[1] - p->rho;
+    const float gradmin = p->rho - p->limiter.rho[0];
+    const float gradtrue_inv = 1.0f / gradtrue;
     const float alpha =
         min3(1.0f, gradmax * gradtrue_inv, gradmin * gradtrue_inv);
-    p->primitives.gradients.rho[0] *= alpha;
-    p->primitives.gradients.rho[1] *= alpha;
-    p->primitives.gradients.rho[2] *= alpha;
+    p->gradients.rho[0] *= alpha;
+    p->gradients.rho[1] *= alpha;
+    p->gradients.rho[2] *= alpha;
   }
 
   gradtrue = sqrtf(gradv[0][0] * gradv[0][0] + gradv[0][1] * gradv[0][1] +
                    gradv[0][2] * gradv[0][2]);
   if (gradtrue) {
-    gradtrue *= p->primitives.limiter.maxr;
-    const float gradmax = p->primitives.limiter.v[0][1] - p->primitives.v[0];
-    const float gradmin = p->primitives.v[0] - p->primitives.limiter.v[0][0];
-    const float gradtrue_inv = 1.f / gradtrue;
+    gradtrue *= p->limiter.maxr;
+    const float gradmax = p->limiter.v[0][1] - p->v[0];
+    const float gradmin = p->v[0] - p->limiter.v[0][0];
+    const float gradtrue_inv = 1.0f / gradtrue;
     const float alpha =
         min3(1.0f, gradmax * gradtrue_inv, gradmin * gradtrue_inv);
-    p->primitives.gradients.v[0][0] *= alpha;
-    p->primitives.gradients.v[0][1] *= alpha;
-    p->primitives.gradients.v[0][2] *= alpha;
+    p->gradients.v[0][0] *= alpha;
+    p->gradients.v[0][1] *= alpha;
+    p->gradients.v[0][2] *= alpha;
   }
 
   gradtrue = sqrtf(gradv[1][0] * gradv[1][0] + gradv[1][1] * gradv[1][1] +
                    gradv[1][2] * gradv[1][2]);
   if (gradtrue) {
-    gradtrue *= p->primitives.limiter.maxr;
-    const float gradmax = p->primitives.limiter.v[1][1] - p->primitives.v[1];
-    const float gradmin = p->primitives.v[1] - p->primitives.limiter.v[1][0];
-    const float gradtrue_inv = 1.f / gradtrue;
+    gradtrue *= p->limiter.maxr;
+    const float gradmax = p->limiter.v[1][1] - p->v[1];
+    const float gradmin = p->v[1] - p->limiter.v[1][0];
+    const float gradtrue_inv = 1.0f / gradtrue;
     const float alpha =
         min3(1.0f, gradmax * gradtrue_inv, gradmin * gradtrue_inv);
-    p->primitives.gradients.v[1][0] *= alpha;
-    p->primitives.gradients.v[1][1] *= alpha;
-    p->primitives.gradients.v[1][2] *= alpha;
+    p->gradients.v[1][0] *= alpha;
+    p->gradients.v[1][1] *= alpha;
+    p->gradients.v[1][2] *= alpha;
   }
 
   gradtrue = sqrtf(gradv[2][0] * gradv[2][0] + gradv[2][1] * gradv[2][1] +
                    gradv[2][2] * gradv[2][2]);
   if (gradtrue) {
-    gradtrue *= p->primitives.limiter.maxr;
-    const float gradmax = p->primitives.limiter.v[2][1] - p->primitives.v[2];
-    const float gradmin = p->primitives.v[2] - p->primitives.limiter.v[2][0];
-    const float gradtrue_inv = 1.f / gradtrue;
+    gradtrue *= p->limiter.maxr;
+    const float gradmax = p->limiter.v[2][1] - p->v[2];
+    const float gradmin = p->v[2] - p->limiter.v[2][0];
+    const float gradtrue_inv = 1.0f / gradtrue;
     const float alpha =
         min3(1.0f, gradmax * gradtrue_inv, gradmin * gradtrue_inv);
-    p->primitives.gradients.v[2][0] *= alpha;
-    p->primitives.gradients.v[2][1] *= alpha;
-    p->primitives.gradients.v[2][2] *= alpha;
+    p->gradients.v[2][0] *= alpha;
+    p->gradients.v[2][1] *= alpha;
+    p->gradients.v[2][2] *= alpha;
   }
 
   gradtrue =
       sqrtf(gradP[0] * gradP[0] + gradP[1] * gradP[1] + gradP[2] * gradP[2]);
   if (gradtrue) {
-    gradtrue *= p->primitives.limiter.maxr;
-    const float gradmax = p->primitives.limiter.P[1] - p->primitives.P;
-    const float gradmin = p->primitives.P - p->primitives.limiter.P[0];
-    const float gradtrue_inv = 1.f / gradtrue;
+    gradtrue *= p->limiter.maxr;
+    const float gradmax = p->limiter.P[1] - p->P;
+    const float gradmin = p->P - p->limiter.P[0];
+    const float gradtrue_inv = 1.0f / gradtrue;
     const float alpha =
         min3(1.0f, gradmax * gradtrue_inv, gradmin * gradtrue_inv);
-    p->primitives.gradients.P[0] *= alpha;
-    p->primitives.gradients.P[1] *= alpha;
-    p->primitives.gradients.P[2] *= alpha;
+    p->gradients.P[0] *= alpha;
+    p->gradients.P[1] *= alpha;
+    p->gradients.P[2] *= alpha;
   }
 }
 
diff --git a/src/hydro/GizmoMFM/hydro_slope_limiters_face.h b/src/hydro/GizmoMFM/hydro_slope_limiters_face.h
index 8f0636c992ccbd615cc62ca09c1b0ca9b08ea56b..a7c0e37d3953d1d385128b4a1c72dd2311ac00ae 100644
--- a/src/hydro/GizmoMFM/hydro_slope_limiters_face.h
+++ b/src/hydro/GizmoMFM/hydro_slope_limiters_face.h
@@ -56,15 +56,17 @@ hydro_slope_limit_face_quantity(float phi_i, float phi_j, float phi_mid0,
 
   float phiplus, phiminus, phi_mid;
 
-  if (same_signf(phimax + delta1, phimax))
+  if (same_signf(phimax + delta1, phimax)) {
     phiplus = phimax + delta1;
-  else
+  } else {
     phiplus = phimax / (1.0f + delta1 / (fabsf(phimax) + FLT_MIN));
+  }
 
-  if (same_signf(phimin - delta1, phimin))
+  if (same_signf(phimin - delta1, phimin)) {
     phiminus = phimin - delta1;
-  else
+  } else {
     phiminus = phimin / (1.0f + delta1 / (fabsf(phimin) + FLT_MIN));
+  }
 
   if (phi_i < phi_j) {
     const float temp = min(phibar + delta2, phi_mid0);
diff --git a/src/hydro/GizmoMFM/hydro_velocities.h b/src/hydro/GizmoMFM/hydro_velocities.h
deleted file mode 100644
index ea30d5a6c9c74d34ffd73fa6ab941640f37b02e4..0000000000000000000000000000000000000000
--- a/src/hydro/GizmoMFM/hydro_velocities.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*******************************************************************************
- * This file is part of SWIFT.
- * Coypright (c) 2017 Bert Vandenbroucke (bert.vandenbroucke@gmail.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- ******************************************************************************/
-#ifndef SWIFT_HYDRO_VELOCITIES_H
-#define SWIFT_HYDRO_VELOCITIES_H
-
-/**
- * @brief Initialize the GIZMO particle velocities before the start of the
- * actual run based on the initial value of the primitive velocity.
- *
- * @param p The particle to act upon.
- * @param xp The extended particle data to act upon.
- */
-__attribute__((always_inline)) INLINE static void hydro_velocities_init(
-    struct part* restrict p, struct xpart* restrict xp) {
-
-#ifdef GIZMO_FIX_PARTICLES
-  p->v[0] = 0.f;
-  p->v[1] = 0.f;
-  p->v[2] = 0.f;
-#else
-  p->v[0] = p->primitives.v[0];
-  p->v[1] = p->primitives.v[1];
-  p->v[2] = p->primitives.v[2];
-#endif
-
-  xp->v_full[0] = p->v[0];
-  xp->v_full[1] = p->v[1];
-  xp->v_full[2] = p->v[2];
-}
-
-/**
- * @brief Set the particle velocity field that will be used to deboost fluid
- * velocities during the force loop.
- *
- * @param p The particle to act upon.
- * @param xp The extended particle data to act upon.
- */
-__attribute__((always_inline)) INLINE static void
-hydro_velocities_prepare_force(struct part* restrict p,
-                               const struct xpart* restrict xp) {}
-
-/**
- * @brief Set the variables that will be used to update the smoothing length
- * during the drift (these will depend on the movement of the particles).
- *
- * @param p The particle to act upon.
- */
-__attribute__((always_inline)) INLINE static void hydro_velocities_end_force(
-    struct part* restrict p) {
-
-#ifdef GIZMO_FIX_PARTICLES
-  /* disable the smoothing length update, since the smoothing lengths should
-     stay the same for all steps (particles don't move) */
-  p->force.h_dt = 0.0f;
-#else
-  /* Add normalization to h_dt. */
-  p->force.h_dt *= p->h * hydro_dimension_inv;
-#endif
-}
-
-/**
- * @brief Set the velocity of a GIZMO particle, based on the values of its
- * primitive variables and the geometry of its mesh-free "cell".
- *
- * @param p The particle to act upon.
- * @param xp The extended particle data to act upon.
- */
-__attribute__((always_inline)) INLINE static void hydro_velocities_set(
-    struct part* restrict p, struct xpart* restrict xp) {
-
-/* We first set the particle velocity. */
-#ifdef GIZMO_FIX_PARTICLES
-
-  p->v[0] = 0.f;
-  p->v[1] = 0.f;
-  p->v[2] = 0.f;
-
-#else  // GIZMO_FIX_PARTICLES
-
-  if (p->conserved.mass > 0.f && p->primitives.rho > 0.f) {
-
-    const float inverse_mass = 1.f / p->conserved.mass;
-
-    /* Normal case: set particle velocity to fluid velocity. */
-    p->v[0] = p->conserved.momentum[0] * inverse_mass;
-    p->v[1] = p->conserved.momentum[1] * inverse_mass;
-    p->v[2] = p->conserved.momentum[2] * inverse_mass;
-
-#ifdef GIZMO_STEER_MOTION
-
-    /* Add a correction to the velocity to keep particle positions close enough
-       to
-       the centroid of their mesh-free "cell". */
-    /* The correction term below is the same one described in Springel (2010).
-     */
-    float ds[3];
-    ds[0] = p->geometry.centroid[0];
-    ds[1] = p->geometry.centroid[1];
-    ds[2] = p->geometry.centroid[2];
-    const float d = sqrtf(ds[0] * ds[0] + ds[1] * ds[1] + ds[2] * ds[2]);
-    const float R = get_radius_dimension_sphere(p->geometry.volume);
-    const float eta = 0.25f;
-    const float etaR = eta * R;
-    const float xi = 1.f;
-    const float soundspeed =
-        sqrtf(hydro_gamma * p->primitives.P / p->primitives.rho);
-    /* We only apply the correction if the offset between centroid and position
-       is too large. */
-    if (d > 0.9f * etaR) {
-      float fac = xi * soundspeed / d;
-      if (d < 1.1f * etaR) {
-        fac *= 5.f * (d - 0.9f * etaR) / etaR;
-      }
-      p->v[0] -= ds[0] * fac;
-      p->v[1] -= ds[1] * fac;
-      p->v[2] -= ds[2] * fac;
-    }
-
-#endif  // GIZMO_STEER_MOTION
-  } else {
-    /* Vacuum particles have no fluid velocity. */
-    p->v[0] = 0.f;
-    p->v[1] = 0.f;
-    p->v[2] = 0.f;
-  }
-
-#endif  // GIZMO_FIX_PARTICLES
-
-  /* Now make sure all velocity variables are up to date. */
-  xp->v_full[0] = p->v[0];
-  xp->v_full[1] = p->v[1];
-  xp->v_full[2] = p->v[2];
-
-  if (p->gpart) {
-    p->gpart->v_full[0] = p->v[0];
-    p->gpart->v_full[1] = p->v[1];
-    p->gpart->v_full[2] = p->v[2];
-  }
-}
-
-#endif /* SWIFT_HYDRO_VELOCITIES_H */
diff --git a/src/hydro/GizmoMFV/hydro.h b/src/hydro/GizmoMFV/hydro.h
index 6916fe33272692316354385b723ce9969606b6a2..c1a62e3c16b98e98b881f3fe4ddcd539cf842c9d 100644
--- a/src/hydro/GizmoMFV/hydro.h
+++ b/src/hydro/GizmoMFV/hydro.h
@@ -68,14 +68,13 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep(
   vmax = max(vmax, p->timestepvars.vmax);
 
   // MATTHIEU: Bert is this correct? Do we need more cosmology terms here?
-  const float psize =
-      cosmo->a * powf(p->geometry.volume / hydro_dimension_unit_sphere,
-                      hydro_dimension_inv);
+  const float psize = powf(p->geometry.volume / hydro_dimension_unit_sphere,
+                           hydro_dimension_inv);
   float dt = FLT_MAX;
   if (vmax > 0.) {
     dt = psize / vmax;
   }
-  return CFL_condition * dt;
+  return cosmo->a * cosmo->a * CFL_condition * dt;
 }
 
 /**
@@ -544,7 +543,10 @@ __attribute__((always_inline)) INLINE static void hydro_reset_predicted_values(
  * @param p The particle to act upon.
  */
 __attribute__((always_inline)) INLINE static void hydro_convert_quantities(
-    struct part* p, struct xpart* xp, const struct cosmology* cosmo) {}
+    struct part* p, struct xpart* xp, const struct cosmology* cosmo) {
+
+  p->conserved.energy /= cosmo->a_factor_internal_energy;
+}
 
 /**
  * @brief Extra operations to be done during the drift
@@ -579,24 +581,40 @@ __attribute__((always_inline)) INLINE static void hydro_predict_extra(
 
   /* drift the primitive variables based on the old fluxes */
   if (p->geometry.volume > 0.) {
-    p->primitives.rho += p->conserved.flux.mass * dt_drift / p->geometry.volume;
+    p->primitives.rho += p->conserved.flux.mass * dt_therm / p->geometry.volume;
   }
 
   if (p->conserved.mass > 0.) {
     p->primitives.v[0] +=
-        p->conserved.flux.momentum[0] * dt_drift / p->conserved.mass;
+        p->conserved.flux.momentum[0] * dt_therm / p->conserved.mass;
     p->primitives.v[1] +=
-        p->conserved.flux.momentum[1] * dt_drift / p->conserved.mass;
+        p->conserved.flux.momentum[1] * dt_therm / p->conserved.mass;
     p->primitives.v[2] +=
-        p->conserved.flux.momentum[2] * dt_drift / p->conserved.mass;
+        p->conserved.flux.momentum[2] * dt_therm / p->conserved.mass;
 
 #if !defined(EOS_ISOTHERMAL_GAS)
-    const float u = p->conserved.energy + p->conserved.flux.energy * dt_therm;
-    p->primitives.P =
-        hydro_gamma_minus_one * u * p->primitives.rho / p->conserved.mass;
+#ifdef GIZMO_TOTAL_ENERGY
+    const float Etot =
+        p->conserved.energy + p->conserved.flux.energy * dt_therm;
+    const float v2 = (p->primitives.v[0] * p->primitives.v[0] +
+                      p->primitives.v[1] * p->primitives.v[1] +
+                      p->primitives.v[2] * p->primitives.v[2]);
+    const float u = (Etot / p->conserved.mass - 0.5 * v2);
+#else
+    const float u =
+        (p->conserved.energy + p->conserved.flux.energy * dt_therm) /
+        p->conserved.mass;
+#endif
+    p->primitives.P = hydro_gamma_minus_one * u * p->primitives.rho;
 #endif
   }
 
+  /* we use a sneaky way to get the gravitational contribution to the
+     velocity update */
+  p->primitives.v[0] += p->v[0] - xp->v_full[0];
+  p->primitives.v[1] += p->v[1] - xp->v_full[1];
+  p->primitives.v[2] += p->v[2] - xp->v_full[2];
+
 #ifdef SWIFT_DEBUG_CHECKS
   if (p->h <= 0.) {
     error("Zero or negative smoothing length (%g)!", p->h);
@@ -633,30 +651,75 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
 /**
  * @brief Extra operations done during the kick
  *
- * Not used for GIZMO.
- *
  * @param p Particle to act upon.
  * @param xp Extended particle data to act upon.
- * @param dt Physical time step.
- * @param half_dt Half the physical time step.
+ * @param dt_therm Thermal energy time-step @f$\frac{dt}{a^2}@f$.
+ * @param dt_grav Gravity time-step @f$\frac{dt}{a}@f$.
+ * @param dt_hydro Hydro acceleration time-step
+ * @f$\frac{dt}{a^{3(\gamma{}-1)}}@f$.
+ * @param dt_kick_corr Gravity correction time-step @f$adt@f$.
+ * @param cosmo Cosmology.
+ * @param hydro_props Additional hydro properties.
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
-    struct part* p, struct xpart* xp, float dt, const struct cosmology* cosmo,
+    struct part* p, struct xpart* xp, float dt_therm, float dt_grav,
+    float dt_hydro, float dt_kick_corr, const struct cosmology* cosmo,
     const struct hydro_props* hydro_props) {
 
   float a_grav[3];
 
+  /* Add gravity. We only do this if we have gravity activated. */
+  if (p->gpart) {
+    /* Retrieve the current value of the gravitational acceleration from the
+       gpart. We are only allowed to do this because this is the kick. We still
+       need to check whether gpart exists though.*/
+    a_grav[0] = p->gpart->a_grav[0];
+    a_grav[1] = p->gpart->a_grav[1];
+    a_grav[2] = p->gpart->a_grav[2];
+
+#ifdef GIZMO_TOTAL_ENERGY
+    p->conserved.energy += dt_grav * (p->conserved.momentum[0] * a_grav[0] +
+                                      p->conserved.momentum[1] * a_grav[1] +
+                                      p->conserved.momentum[2] * a_grav[2]);
+#endif
+
+    /* Kick the momentum for half a time step */
+    /* Note that this also affects the particle movement, as the velocity for
+       the particles is set after this. */
+    p->conserved.momentum[0] += p->conserved.mass * a_grav[0] * dt_grav;
+    p->conserved.momentum[1] += p->conserved.mass * a_grav[1] * dt_grav;
+    p->conserved.momentum[2] += p->conserved.mass * a_grav[2] * dt_grav;
+
+    p->conserved.energy -=
+        0.5f * dt_kick_corr *
+        (p->gravity.mflux[0] * a_grav[0] + p->gravity.mflux[1] * a_grav[1] +
+         p->gravity.mflux[2] * a_grav[2]);
+  }
+
   /* Update conserved variables. */
-  p->conserved.mass += p->conserved.flux.mass * dt;
-  p->conserved.momentum[0] += p->conserved.flux.momentum[0] * dt;
-  p->conserved.momentum[1] += p->conserved.flux.momentum[1] * dt;
-  p->conserved.momentum[2] += p->conserved.flux.momentum[2] * dt;
+  p->conserved.mass += p->conserved.flux.mass * dt_therm;
+  p->conserved.momentum[0] += p->conserved.flux.momentum[0] * dt_therm;
+  p->conserved.momentum[1] += p->conserved.flux.momentum[1] * dt_therm;
+  p->conserved.momentum[2] += p->conserved.flux.momentum[2] * dt_therm;
 #if defined(EOS_ISOTHERMAL_GAS)
   /* We use the EoS equation in a sneaky way here just to get the constant u */
   p->conserved.energy =
       p->conserved.mass * gas_internal_energy_from_entropy(0.f, 0.f);
 #else
-  p->conserved.energy += p->conserved.flux.energy * dt;
+  p->conserved.energy += p->conserved.flux.energy * dt_therm;
+#endif
+
+#ifndef HYDRO_GAMMA_5_3
+  const float Pcorr = (dt_hydro - dt_therm) * p->geometry.volume;
+  p->conserved.momentum[0] -= Pcorr * p->primitives.gradients.P[0];
+  p->conserved.momentum[1] -= Pcorr * p->primitives.gradients.P[1];
+  p->conserved.momentum[2] -= Pcorr * p->primitives.gradients.P[2];
+#ifdef GIZMO_TOTAL_ENERGY
+  p->conserved.energy -=
+      Pcorr * (p->primitives.v[0] * p->primitives.gradients.P[0] +
+               p->primitives.v[1] * p->primitives.gradients.P[1] +
+               p->primitives.v[2] * p->primitives.gradients.P[2]);
+#endif
 #endif
 
   /* Apply the minimal energy limit */
@@ -688,28 +751,9 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
   }
 #endif
 
-  /* Add gravity. We only do this if we have gravity activated. */
   if (p->gpart) {
-    /* Retrieve the current value of the gravitational acceleration from the
-       gpart. We are only allowed to do this because this is the kick. We still
-       need to check whether gpart exists though.*/
-    a_grav[0] = p->gpart->a_grav[0];
-    a_grav[1] = p->gpart->a_grav[1];
-    a_grav[2] = p->gpart->a_grav[2];
-
     /* Make sure the gpart knows the mass has changed. */
     p->gpart->mass = p->conserved.mass;
-
-    /* Kick the momentum for half a time step */
-    /* Note that this also affects the particle movement, as the velocity for
-       the particles is set after this. */
-    p->conserved.momentum[0] += dt * p->conserved.mass * a_grav[0];
-    p->conserved.momentum[1] += dt * p->conserved.mass * a_grav[1];
-    p->conserved.momentum[2] += dt * p->conserved.mass * a_grav[2];
-
-    p->conserved.energy += dt * (p->gravity.mflux[0] * a_grav[0] +
-                                 p->gravity.mflux[1] * a_grav[1] +
-                                 p->gravity.mflux[2] * a_grav[2]);
   }
 
   hydro_velocities_set(p, xp);
diff --git a/src/hydro/GizmoMFV/hydro_gradients.h b/src/hydro/GizmoMFV/hydro_gradients.h
index 387c263775ddfb37e4c7cb31a624ba5dc673beb2..4046e121bad9e329fecc30afb435bffca2815346 100644
--- a/src/hydro/GizmoMFV/hydro_gradients.h
+++ b/src/hydro/GizmoMFV/hydro_gradients.h
@@ -98,8 +98,7 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_predict(
   /* perform gradient reconstruction in space and time */
   /* Compute interface position (relative to pj, since we don't need the actual
    * position) eqn. (8) */
-  const float xfac = hj / (hi + hj);
-  const float xij_j[3] = {xfac * dx[0], xfac * dx[1], xfac * dx[2]};
+  const float xij_j[3] = {xij_i[0] + dx[0], xij_i[1] + dx[1], xij_i[2] + dx[2]};
 
   float dWi[5];
   dWi[0] = pi->primitives.gradients.rho[0] * xij_i[0] +
diff --git a/src/hydro/GizmoMFV/hydro_iact.h b/src/hydro/GizmoMFV/hydro_iact.h
index bb835094acd285b109383c1f5d04a6f5e2d936df..c766ce3cc9048f8da8b3438c3c27e6998dd5df7e 100644
--- a/src/hydro/GizmoMFV/hydro_iact.h
+++ b/src/hydro/GizmoMFV/hydro_iact.h
@@ -375,21 +375,11 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
 
   /* Compute interface velocity */
   /* eqn. (9) */
-  float xijdotdx = xij_i[0] * dx[0] + xij_i[1] * dx[1] + xij_i[2] * dx[2];
-  xijdotdx *= r_inv * r_inv;
-  const float vij[3] = {vi[0] + (vi[0] - vj[0]) * xijdotdx,
-                        vi[1] + (vi[1] - vj[1]) * xijdotdx,
-                        vi[2] + (vi[2] - vj[2]) * xijdotdx};
-
-  /* complete calculation of position of interface */
-  /* NOTE: dx is not necessarily just pi->x - pj->x but can also contain
-           correction terms for periodicity. If we do the interpolation,
-           we have to use xij w.r.t. the actual particle.
-           => we need a separate xij for pi and pj... */
-  /* tldr: we do not need the code below, but we do need the same code as above
-     but then with i and j swapped */
-  //    for ( k = 0 ; k < 3 ; k++ )
-  //      xij[k] += pi->x[k];
+  const float vij[3] = {vi[0] + xfac * (vi[0] - vj[0]),
+                        vi[1] + xfac * (vi[1] - vj[1]),
+                        vi[2] + xfac * (vi[2] - vj[2])};
+
+  hydro_gradients_predict(pi, pj, hi, hj, dx, r, xij_i, Wi, Wj);
 
   /* Boost the primitive variables to the frame of reference of the interface */
   /* Note that velocities are indices 1-3 in W */
@@ -400,8 +390,6 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   Wj[2] -= vij[1];
   Wj[3] -= vij[2];
 
-  hydro_gradients_predict(pi, pj, hi, hj, dx, r, xij_i, Wi, Wj);
-
   /* we don't need to rotate, we can use the unit vector in the Riemann problem
    * itself (see GIZMO) */
 
@@ -447,9 +435,9 @@ __attribute__((always_inline)) INLINE static void runner_iact_fluxes_common(
   if (mode == 1) {
     /* Store mass flux */
     const float mflux_j = totflux[0];
-    pj->gravity.mflux[0] -= mflux_j * dx[0];
-    pj->gravity.mflux[1] -= mflux_j * dx[1];
-    pj->gravity.mflux[2] -= mflux_j * dx[2];
+    pj->gravity.mflux[0] += mflux_j * dx[0];
+    pj->gravity.mflux[1] += mflux_j * dx[1];
+    pj->gravity.mflux[2] += mflux_j * dx[2];
 
     pj->conserved.flux.mass += totflux[0];
     pj->conserved.flux.momentum[0] += totflux[1];
diff --git a/src/hydro/GizmoMFV/hydro_velocities.h b/src/hydro/GizmoMFV/hydro_velocities.h
index ea30d5a6c9c74d34ffd73fa6ab941640f37b02e4..a61a482683291cfc0662116ada99b94a4ccfe68d 100644
--- a/src/hydro/GizmoMFV/hydro_velocities.h
+++ b/src/hydro/GizmoMFV/hydro_velocities.h
@@ -103,7 +103,6 @@ __attribute__((always_inline)) INLINE static void hydro_velocities_set(
     p->v[2] = p->conserved.momentum[2] * inverse_mass;
 
 #ifdef GIZMO_STEER_MOTION
-
     /* Add a correction to the velocity to keep particle positions close enough
        to
        the centroid of their mesh-free "cell". */
diff --git a/src/hydro/Minimal/hydro.h b/src/hydro/Minimal/hydro.h
index 812f8ad72de55ad7990ee6ef88223a401780bc4b..01abe55e7267ca04a7f3e9740c10c681f86f29ea 100644
--- a/src/hydro/Minimal/hydro.h
+++ b/src/hydro/Minimal/hydro.h
@@ -527,6 +527,7 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
     struct part *restrict p, struct xpart *restrict xp, float dt_therm,
+    float dt_grav, float dt_hydro, float dt_kick_corr,
     const struct cosmology *cosmo, const struct hydro_props *hydro_props) {
 
   /* Do not decrease the energy by more than a factor of 2*/
diff --git a/src/hydro/MinimalMultiMat/hydro.h b/src/hydro/Planetary/hydro.h
similarity index 92%
rename from src/hydro/MinimalMultiMat/hydro.h
rename to src/hydro/Planetary/hydro.h
index cfad6b2b2b389da9f423540cb30f1df4cebc5416..106e1a96ae57868c94d1077b74e84909ab0f0830 100644
--- a/src/hydro/MinimalMultiMat/hydro.h
+++ b/src/hydro/Planetary/hydro.h
@@ -17,11 +17,11 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  ******************************************************************************/
-#ifndef SWIFT_MINIMAL_MULTI_MAT_HYDRO_H
-#define SWIFT_MINIMAL_MULTI_MAT_HYDRO_H
+#ifndef SWIFT_PLANETARY_HYDRO_H
+#define SWIFT_PLANETARY_HYDRO_H
 
 /**
- * @file MinimalMultiMat/hydro.h
+ * @file Planetary/hydro.h
  * @brief Minimal conservative implementation of SPH (Non-neighbour loop
  * equations) with multiple materials.
  *
@@ -44,6 +44,12 @@
 #include "kernel_hydro.h"
 #include "minmax.h"
 
+/*
+ * Note: Define PLANETARY_SPH_BALSARA to use the Balsara (1995) switch for
+ * the artificial viscosity, instead of the default Monaghan (1992).
+ * i.e. compile with:  make CFLAGS=-DPLANETARY_SPH_BALSARA  to use.
+ */
+
 /**
  * @brief Returns the comoving internal energy of a particle
  *
@@ -257,6 +263,7 @@ __attribute__((always_inline)) INLINE static void hydro_set_internal_energy_dt(
 
   p->u_dt = du_dt;
 }
+
 /**
  * @brief Computes the hydro time-step of a given particle
  *
@@ -391,23 +398,52 @@ __attribute__((always_inline)) INLINE static void hydro_prepare_force(
     struct part *restrict p, struct xpart *restrict xp,
     const struct cosmology *cosmo) {
 
+#ifdef PLANETARY_SPH_BALSARA
+  const float fac_mu = cosmo->a_factor_mu;
+
+  /* Compute the norm of the curl */
+  const float curl_v = sqrtf(p->density.rot_v[0] * p->density.rot_v[0] +
+                             p->density.rot_v[1] * p->density.rot_v[1] +
+                             p->density.rot_v[2] * p->density.rot_v[2]);
+
+  /* Compute the norm of div v */
+  const float abs_div_v = fabsf(p->density.div_v);
+#endif  // PLANETARY_SPH_BALSARA
+
   /* Compute the pressure */
   const float pressure =
       gas_pressure_from_internal_energy(p->rho, p->u, p->mat_id);
 
   /* Compute the sound speed */
   const float soundspeed =
-      gas_soundspeed_from_pressure(p->rho, pressure, p->mat_id);
+      gas_soundspeed_from_internal_energy(p->rho, p->u, p->mat_id);
 
   /* Compute the "grad h" term */
   const float rho_inv = 1.f / p->rho;
-  const float grad_h_term =
-      1.f / (1.f + hydro_dimension_inv * p->h * p->density.rho_dh * rho_inv);
+  float grad_h_term;
+  const float grad_h_term_inv =
+      1.f + hydro_dimension_inv * p->h * p->density.rho_dh * rho_inv;
+  /* Avoid 1/0 from only having one neighbour right at the edge of the kernel */
+  if (grad_h_term_inv != 0.f) {
+    grad_h_term = 1.f / grad_h_term_inv;
+  } else {
+    grad_h_term = 0.f;
+  }
+
+#ifdef PLANETARY_SPH_BALSARA
+  /* Compute the Balsara switch */
+  const float balsara =
+      abs_div_v / (abs_div_v + curl_v + 0.0001f * fac_mu * soundspeed / p->h);
+#endif  // PLANETARY_SPH_BALSARA
 
   /* Update variables. */
   p->force.f = grad_h_term;
   p->force.pressure = pressure;
   p->force.soundspeed = soundspeed;
+
+#ifdef PLANETARY_SPH_BALSARA
+  p->force.balsara = balsara;
+#endif  // PLANETARY_SPH_BALSARA
 }
 
 /**
@@ -494,7 +530,7 @@ __attribute__((always_inline)) INLINE static void hydro_predict_extra(
 
   /* Compute the new sound speed */
   const float soundspeed =
-      gas_soundspeed_from_pressure(p->rho, pressure, p->mat_id);
+      gas_soundspeed_from_internal_energy(p->rho, p->u, p->mat_id);
 
   p->force.pressure = pressure;
   p->force.soundspeed = soundspeed;
@@ -532,6 +568,7 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
     struct part *restrict p, struct xpart *restrict xp, float dt_therm,
+    float dt_grav, float dt_hydro, float dt_kick_corr,
     const struct cosmology *cosmo, const struct hydro_props *hydro_props) {
 
   /* Do not decrease the energy by more than a factor of 2*/
@@ -631,4 +668,4 @@ hydro_set_init_internal_energy(struct part *p, float u_init) {
   p->u = u_init;
 }
 
-#endif /* SWIFT_MINIMAL_MULTI_MAT_HYDRO_H */
+#endif /* SWIFT_PLANETARY_HYDRO_H */
diff --git a/src/hydro/MinimalMultiMat/hydro_debug.h b/src/hydro/Planetary/hydro_debug.h
similarity index 89%
rename from src/hydro/MinimalMultiMat/hydro_debug.h
rename to src/hydro/Planetary/hydro_debug.h
index 17b624ad0f660152be4ba685905a3c855e1761f8..74261f3b49e2881af1c403013005560efa53a7f1 100644
--- a/src/hydro/MinimalMultiMat/hydro_debug.h
+++ b/src/hydro/Planetary/hydro_debug.h
@@ -17,13 +17,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  ******************************************************************************/
-#ifndef SWIFT_MINIMAL_MULTI_MAT_HYDRO_DEBUG_H
-#define SWIFT_MINIMAL_MULTI_MAT_HYDRO_DEBUG_H
+#ifndef SWIFT_PLANETARY_HYDRO_DEBUG_H
+#define SWIFT_PLANETARY_HYDRO_DEBUG_H
 
 /**
- * @file MinimalMultiMat/hydro_debug.h
- * @brief MinimalMultiMat conservative implementation of SPH (Debugging
- * routines)
+ * @file Planetary/hydro_debug.h
+ * @brief Minimal conservative implementation of SPH (Debugging routines)
  *
  * The thermal variable is the internal energy (u). Simple constant
  * viscosity term without switches is implemented. No thermal conduction
@@ -51,4 +50,4 @@ __attribute__((always_inline)) INLINE static void hydro_debug_particle(
       p->density.wcount, p->rho, p->density.rho_dh, p->time_bin, p->mat_id);
 }
 
-#endif /* SWIFT_MINIMAL_MULTI_MAT_HYDRO_DEBUG_H */
+#endif /* SWIFT_PLANETARY_HYDRO_DEBUG_H */
diff --git a/src/hydro/MinimalMultiMat/hydro_iact.h b/src/hydro/Planetary/hydro_iact.h
similarity index 89%
rename from src/hydro/MinimalMultiMat/hydro_iact.h
rename to src/hydro/Planetary/hydro_iact.h
index 5984c1c483546d87800792ced0ffcc41e0aaa408..bf96034696806e3adff1d8ba7f385af65461b9ea 100644
--- a/src/hydro/MinimalMultiMat/hydro_iact.h
+++ b/src/hydro/Planetary/hydro_iact.h
@@ -17,13 +17,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  ******************************************************************************/
-#ifndef SWIFT_MINIMAL_MULTI_MAT_HYDRO_IACT_H
-#define SWIFT_MINIMAL_MULTI_MAT_HYDRO_IACT_H
+#ifndef SWIFT_PLANETARY_HYDRO_IACT_H
+#define SWIFT_PLANETARY_HYDRO_IACT_H
 
 /**
- * @file MinimalMultiMat/hydro_iact.h
- * @brief MinimalMultiMat conservative implementation of SPH (Neighbour loop
- * equations)
+ * @file Planetary/hydro_iact.h
+ * @brief Minimal conservative implementation of SPH (Neighbour loop equations)
  *
  * The thermal variable is the internal energy (u). Simple constant
  * viscosity term without switches is implemented. No thermal conduction
@@ -177,7 +176,13 @@ __attribute__((always_inline)) INLINE static void runner_iact_force(
                      (pi->v[1] - pj->v[1]) * dx[1] +
                      (pi->v[2] - pj->v[2]) * dx[2] + a2_Hubble * r2;
 
-  /* Are the particles moving towards each others ? */
+#ifdef PLANETARY_SPH_BALSARA
+  /* Balsara term */
+  const float balsara_i = pi->force.balsara;
+  const float balsara_j = pj->force.balsara;
+#endif  // PLANETARY_SPH_BALSARA
+
+  /* Are the particles moving towards each other? */
   const float omega_ij = min(dvdr, 0.f);
   const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
 
@@ -186,9 +191,14 @@ __attribute__((always_inline)) INLINE static void runner_iact_force(
   const float cj = pj->force.soundspeed;
   const float v_sig = ci + cj - 3.f * mu_ij;
 
-  /* Construct the full viscosity term */
+  /* Now construct the full viscosity term */
   const float rho_ij = 0.5f * (rhoi + rhoj);
+#ifdef PLANETARY_SPH_BALSARA
+  const float visc = -0.25f * const_viscosity_alpha * v_sig * mu_ij *
+                     (balsara_i + balsara_j) / rho_ij;
+#else
   const float visc = -0.5f * const_viscosity_alpha * v_sig * mu_ij / rho_ij;
+#endif  // PLANETARY_SPH_BALSARA
 
   /* Convolve with the kernel */
   const float visc_acc_term = 0.5f * visc * (wi_dr + wj_dr) * r_inv;
@@ -220,7 +230,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_force(
   const float du_dt_i = sph_du_term_i + visc_du_term;
   const float du_dt_j = sph_du_term_j + visc_du_term;
 
-  /* Internal energy time derivatibe */
+  /* Internal energy time derivative */
   pi->u_dt += du_dt_i * mj;
   pj->u_dt += du_dt_j * mi;
 
@@ -290,18 +300,31 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force(
                      (pi->v[1] - pj->v[1]) * dx[1] +
                      (pi->v[2] - pj->v[2]) * dx[2] + a2_Hubble * r2;
 
-  /* Are the particles moving towards each others ? */
+#ifdef PLANETARY_SPH_BALSARA
+  /* Balsara term */
+  const float balsara_i = pi->force.balsara;
+  const float balsara_j = pj->force.balsara;
+#endif  // PLANETARY_SPH_BALSARA
+
+  /* Are the particles moving towards each other? */
   const float omega_ij = min(dvdr, 0.f);
   const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
 
-  /* Compute sound speeds and signal velocity */
+  /* Compute sound speeds */
   const float ci = pi->force.soundspeed;
   const float cj = pj->force.soundspeed;
+
+  /* Signal velocity */
   const float v_sig = ci + cj - 3.f * mu_ij;
 
   /* Construct the full viscosity term */
   const float rho_ij = 0.5f * (rhoi + rhoj);
+#ifdef PLANETARY_SPH_BALSARA
+  const float visc = -0.25f * const_viscosity_alpha * v_sig * mu_ij *
+                     (balsara_i + balsara_j) / rho_ij;
+#else
   const float visc = -0.5f * const_viscosity_alpha * v_sig * mu_ij / rho_ij;
+#endif  // PLANETARY_SPH_BALSARA
 
   /* Convolve with the kernel */
   const float visc_acc_term = 0.5f * visc * (wi_dr + wj_dr) * r_inv;
@@ -327,7 +350,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force(
   /* Assemble the energy equation term */
   const float du_dt_i = sph_du_term_i + visc_du_term;
 
-  /* Internal energy time derivatibe */
+  /* Internal energy time derivative */
   pi->u_dt += du_dt_i * mj;
 
   /* Get the time derivative for h. */
@@ -337,4 +360,4 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force(
   pi->force.v_sig = max(pi->force.v_sig, v_sig);
 }
 
-#endif /* SWIFT_MINIMAL_MULTI_MAT_HYDRO_IACT_H */
+#endif /* SWIFT_PLANETARY_HYDRO_IACT_H */
diff --git a/src/hydro/MinimalMultiMat/hydro_io.h b/src/hydro/Planetary/hydro_io.h
similarity index 95%
rename from src/hydro/MinimalMultiMat/hydro_io.h
rename to src/hydro/Planetary/hydro_io.h
index 7f41f5e227b6c8a8904b5546a2568b4700109abd..afb37d884494fd02e30c143194804a2b49a77be0 100644
--- a/src/hydro/MinimalMultiMat/hydro_io.h
+++ b/src/hydro/Planetary/hydro_io.h
@@ -17,12 +17,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  ******************************************************************************/
-#ifndef SWIFT_MINIMAL_MULTI_MAT_HYDRO_IO_H
-#define SWIFT_MINIMAL_MULTI_MAT_HYDRO_IO_H
+#ifndef SWIFT_PLANETARY_HYDRO_IO_H
+#define SWIFT_PLANETARY_HYDRO_IO_H
 
 /**
- * @file MinimalMultiMat/hydro_io.h
- * @brief MinimalMultiMat conservative implementation of SPH (i/o routines)
+ * @file Planetary/hydro_io.h
+ * @brief Minimal conservative implementation of SPH (i/o routines)
  *
  * The thermal variable is the internal energy (u). Simple constant
  * viscosity term without switches is implemented. No thermal conduction
@@ -197,8 +197,14 @@ INLINE static void hydro_write_flavour(hid_t h_grpsph) {
   /* Viscosity and thermal conduction */
   /* Nothing in this minimal model... */
   io_write_attribute_s(h_grpsph, "Thermal Conductivity Model", "No treatment");
+#ifdef PLANETARY_SPH_BALSARA
+  io_write_attribute_s(
+      h_grpsph, "Viscosity Model",
+      "as in Springel (2005), i.e. Monaghan (1992) with Balsara (1995) switch");
+#else
   io_write_attribute_s(h_grpsph, "Viscosity Model",
                        "Minimal treatment as in Monaghan (1992)");
+#endif  // PLANETARY_SPH_BALSARA
 
   /* Time integration properties */
   io_write_attribute_f(h_grpsph, "Maximal Delta u change over dt",
@@ -212,4 +218,4 @@ INLINE static void hydro_write_flavour(hid_t h_grpsph) {
  */
 INLINE static int writeEntropyFlag(void) { return 0; }
 
-#endif /* SWIFT_MINIMAL_MULTI_MAT_HYDRO_IO_H */
+#endif /* SWIFT_PLANETARY_HYDRO_IO_H */
diff --git a/src/hydro/MinimalMultiMat/hydro_part.h b/src/hydro/Planetary/hydro_part.h
similarity index 90%
rename from src/hydro/MinimalMultiMat/hydro_part.h
rename to src/hydro/Planetary/hydro_part.h
index dad13e889aa531636e34846825109086177b3dae..7d1fc8f6729992bfdf2eeaba6e33cc9a7b071655 100644
--- a/src/hydro/MinimalMultiMat/hydro_part.h
+++ b/src/hydro/Planetary/hydro_part.h
@@ -17,13 +17,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  ******************************************************************************/
-#ifndef SWIFT_MINIMAL_MULTI_MAT_HYDRO_PART_H
-#define SWIFT_MINIMAL_MULTI_MAT_HYDRO_PART_H
+#ifndef SWIFT_PLANETARY_HYDRO_PART_H
+#define SWIFT_PLANETARY_HYDRO_PART_H
 
 /**
- * @file MinimalMultiMat/hydro_part.h
- * @brief MinimalMultiMat conservative implementation of SPH (Particle
- * definition)
+ * @file Planetary/hydro_part.h
+ * @brief Minimal conservative implementation of SPH (Particle definition)
  *
  * The thermal variable is the internal energy (u). Simple constant
  * viscosity term without switches is implemented. No thermal conduction
@@ -127,6 +126,14 @@ struct part {
       /*! Derivative of density with respect to h */
       float rho_dh;
 
+#ifdef PLANETARY_SPH_BALSARA
+      /*! Velocity divergence. */
+      float div_v;
+
+      /*! Velocity curl. */
+      float rot_v[3];
+#endif  // PLANETARY_SPH_BALSARA
+
     } density;
 
     /**
@@ -153,6 +160,11 @@ struct part {
       /*! Time derivative of smoothing length  */
       float h_dt;
 
+#ifdef PLANETARY_SPH_BALSARA
+      /*! Balsara switch */
+      float balsara;
+#endif  // PLANETARY_SPH_BALSARA
+
     } force;
   };
 
@@ -177,4 +189,4 @@ struct part {
 
 } SWIFT_STRUCT_ALIGN;
 
-#endif /* SWIFT_MINIMAL_MULTI_MAT_HYDRO_PART_H */
+#endif /* SWIFT_PLANETARY_HYDRO_PART_H */
diff --git a/src/hydro/PressureEnergy/hydro.h b/src/hydro/PressureEnergy/hydro.h
index ea086daeeb1e93d7f1476302564fb4182a6fb611..5082db6c792701511972a52fd2fb00a6a45f7271 100644
--- a/src/hydro/PressureEnergy/hydro.h
+++ b/src/hydro/PressureEnergy/hydro.h
@@ -581,6 +581,7 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
     struct part *restrict p, struct xpart *restrict xp, float dt_therm,
+    float dt_grav, float dt_hydro, float dt_kick_corr,
     const struct cosmology *cosmo,
     const struct hydro_props *restrict hydro_properties) {
 
diff --git a/src/hydro/PressureEntropy/hydro.h b/src/hydro/PressureEntropy/hydro.h
index e4b7cf06e083638a94526cc1f9e7212cf19dfad4..3f0f9931ebd557fffcab7e89f3c6297c2fb26474 100644
--- a/src/hydro/PressureEntropy/hydro.h
+++ b/src/hydro/PressureEntropy/hydro.h
@@ -541,6 +541,7 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
     struct part *restrict p, struct xpart *restrict xp, float dt_therm,
+    float dt_grav, float dt_hydro, float dt_kick_corr,
     const struct cosmology *cosmo, const struct hydro_props *hydro_props) {
 
   /* Do not decrease the entropy (temperature) by more than a factor of 2*/
diff --git a/src/hydro/Shadowswift/hydro.h b/src/hydro/Shadowswift/hydro.h
index d70d58c6ba508ba4282ac9dd32565478afb40692..cca2a241866fc797055922a48c25cebd6fa1b140 100644
--- a/src/hydro/Shadowswift/hydro.h
+++ b/src/hydro/Shadowswift/hydro.h
@@ -443,7 +443,8 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  * @param dt Physical time step.
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
-    struct part* p, struct xpart* xp, float dt, const struct cosmology* cosmo,
+    struct part* p, struct xpart* xp, float dt, float dt_grav, float dt_hydro,
+    float dt_kick_corr, const struct cosmology* cosmo,
     const struct hydro_props* hydro_props) {
 
   /* Update the conserved variables. We do this here and not in the kick,
diff --git a/src/hydro_io.h b/src/hydro_io.h
index d752bb8bc03f619fe759fc8f5de32a01b3a61abe..b6e0c36cc7415a1f628a109795aa98b4f583036c 100644
--- a/src/hydro_io.h
+++ b/src/hydro_io.h
@@ -39,8 +39,8 @@
 #include "./hydro/GizmoMFM/hydro_io.h"
 #elif defined(SHADOWFAX_SPH)
 #include "./hydro/Shadowswift/hydro_io.h"
-#elif defined(MINIMAL_MULTI_MAT_SPH)
-#include "./hydro/MinimalMultiMat/hydro_io.h"
+#elif defined(PLANETARY_SPH)
+#include "./hydro/Planetary/hydro_io.h"
 #else
 #error "Invalid choice of SPH variant"
 #endif
diff --git a/src/hydro_properties.c b/src/hydro_properties.c
index f79fd832248fba8fbc55bd9fcec57e645be93159..905bf6973447b1ddd1c174b2e65d6841917ef736 100644
--- a/src/hydro_properties.c
+++ b/src/hydro_properties.c
@@ -135,6 +135,14 @@ void hydro_props_init(struct hydro_props *p,
     mean_molecular_weight = 4. / (1. + 3. * p->hydrogen_mass_fraction);
 
   p->minimal_internal_energy = u_min / mean_molecular_weight;
+
+#ifdef PLANETARY_SPH
+#ifdef PLANETARY_SPH_BALSARA
+  message("Planetary SPH: Balsara switch enabled");
+#else
+  message("Planetary SPH: Balsara switch disabled");
+#endif  // PLANETARY_SPH_BALSARA
+#endif  // PLANETARY_SPH
 }
 
 /**
diff --git a/src/kick.h b/src/kick.h
index 9d10f1e78d3934c4277c14217cbbc46514e87033..50ecaea498bdd401cc0ac27525ed27986a344c59 100644
--- a/src/kick.h
+++ b/src/kick.h
@@ -68,6 +68,7 @@ __attribute__((always_inline)) INLINE static void kick_gpart(
  * @param dt_kick_hydro The kick time-step for hydro accelerations.
  * @param dt_kick_grav The kick time-step for gravity accelerations.
  * @param dt_kick_therm The kick time-step for changes in thermal state.
+ * @param dt_kick_corr The kick time-step for the gizmo-mfv gravity correction.
  * @param cosmo The cosmological model.
  * @param hydro_props The constants used in the scheme
  * @param ti_start The starting (integer) time of the kick (for debugging
@@ -76,9 +77,9 @@ __attribute__((always_inline)) INLINE static void kick_gpart(
  */
 __attribute__((always_inline)) INLINE static void kick_part(
     struct part *restrict p, struct xpart *restrict xp, double dt_kick_hydro,
-    double dt_kick_grav, double dt_kick_therm, const struct cosmology *cosmo,
-    const struct hydro_props *hydro_props, integertime_t ti_start,
-    integertime_t ti_end) {
+    double dt_kick_grav, double dt_kick_therm, double dt_kick_corr,
+    const struct cosmology *cosmo, const struct hydro_props *hydro_props,
+    integertime_t ti_start, integertime_t ti_end) {
 
 #ifdef SWIFT_DEBUG_CHECKS
   if (p->ti_kick != ti_start)
@@ -110,7 +111,8 @@ __attribute__((always_inline)) INLINE static void kick_part(
   }
 
   /* Extra kick work */
-  hydro_kick_extra(p, xp, dt_kick_therm, cosmo, hydro_props);
+  hydro_kick_extra(p, xp, dt_kick_therm, dt_kick_grav, dt_kick_hydro,
+                   dt_kick_corr, cosmo, hydro_props);
   if (p->gpart != NULL) gravity_kick_extra(p->gpart, dt_kick_grav);
 }
 
diff --git a/src/multipole.h b/src/multipole.h
index e0e6da32a2950d7fce164b2abc422302b7c7de5e..c05aa36890313ea22f725ee272746bdf63f597ea 100644
--- a/src/multipole.h
+++ b/src/multipole.h
@@ -240,17 +240,17 @@ INLINE static void gravity_drift(struct gravity_tensors *m, double dt) {
   m->CoM[2] += dz;
 
 #ifdef SWIFT_DEBUG_CHECKS
-  if (m->m_pole.vel[0] > m->m_pole.max_delta_vel[0])
+  if (m->m_pole.vel[0] > m->m_pole.max_delta_vel[0] * 1.1)
     error("Invalid maximal velocity");
-  if (m->m_pole.vel[0] < m->m_pole.min_delta_vel[0])
+  if (m->m_pole.vel[0] < m->m_pole.min_delta_vel[0] * 1.1)
     error("Invalid minimal velocity");
-  if (m->m_pole.vel[1] > m->m_pole.max_delta_vel[1])
+  if (m->m_pole.vel[1] > m->m_pole.max_delta_vel[1] * 1.1)
     error("Invalid maximal velocity");
-  if (m->m_pole.vel[1] < m->m_pole.min_delta_vel[1])
+  if (m->m_pole.vel[1] < m->m_pole.min_delta_vel[1] * 1.1)
     error("Invalid minimal velocity");
-  if (m->m_pole.vel[2] > m->m_pole.max_delta_vel[2])
+  if (m->m_pole.vel[2] > m->m_pole.max_delta_vel[2] * 1.1)
     error("Invalid maximal velocity");
-  if (m->m_pole.vel[2] < m->m_pole.min_delta_vel[2])
+  if (m->m_pole.vel[2] < m->m_pole.min_delta_vel[2] * 1.1)
     error("Invalid minimal velocity");
 #endif
 
@@ -1037,6 +1037,13 @@ INLINE static void gravity_P2M(struct gravity_tensors *multi,
     vel[2] += gparts[k].v_full[2] * m;
   }
 
+#ifdef PLANETARY_SPH
+  /* Prevent FPE from zero mass with the temporary outside-the-box particles */
+  if (mass == 0.f) {
+    mass = FLT_MIN;
+  }
+#endif  // PLANETARY_SPH
+
   /* Final operation on CoM */
   const double imass = 1.0 / mass;
   com[0] *= imass;
diff --git a/src/outputlist.c b/src/outputlist.c
index 09874ca93cea0c7cc7d91038e49ec33bb851516f..fd33370ca45f25c17ecd2cc8df622138842507f3 100644
--- a/src/outputlist.c
+++ b/src/outputlist.c
@@ -208,7 +208,8 @@ void output_list_read_next_time(struct output_list *t, const struct engine *e,
  * time)
  */
 void output_list_init(struct output_list **list, const struct engine *e,
-                      char *name, double *delta_time, double *time_first) {
+                      const char *name, double *delta_time,
+                      double *time_first) {
   struct swift_params *params = e->parameter_file;
 
   /* get cosmo */
diff --git a/src/outputlist.h b/src/outputlist.h
index ddc08c84d3739097e990c175cd83e809231845a9..6045d75ea29f0aab44252835147502f3df0de20c 100644
--- a/src/outputlist.h
+++ b/src/outputlist.h
@@ -56,7 +56,7 @@ void output_list_read_file(struct output_list *outputlist, const char *filename,
 void output_list_read_next_time(struct output_list *t, const struct engine *e,
                                 const char *name, integertime_t *ti_next);
 void output_list_init(struct output_list **list, const struct engine *e,
-                      char *name, double *delta_time, double *time_first);
+                      const char *name, double *delta_time, double *time_first);
 void output_list_print(const struct output_list *outputlist);
 void output_list_clean(struct output_list *outputlist);
 void output_list_struct_dump(struct output_list *list, FILE *stream);
diff --git a/src/parallel_io.c b/src/parallel_io.c
index b82443b33ba767cfe2050cf300535db924bfb537..a3a71d0ac5703f194bfa8e53c9b0b62b25e6a602 100644
--- a/src/parallel_io.c
+++ b/src/parallel_io.c
@@ -928,10 +928,11 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6],
   char fileName[FILENAME_BUFFER_SIZE];
   if (e->snapshot_label_delta == 1)
     snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName,
-             e->snapshot_output_count);
+             e->snapshot_output_count + e->snapshot_label_first);
   else
     snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%06i.hdf5", baseName,
-             e->snapshot_output_count * e->snapshot_label_delta);
+             e->snapshot_output_count * e->snapshot_label_delta +
+                 e->snapshot_label_first);
 
   /* Open HDF5 file with the chosen parameters */
   hid_t h_file = H5Fcreate(fileName, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
@@ -1204,8 +1205,13 @@ void write_output_parallel(struct engine* e, const char* baseName,
 
   /* HDF5 File name */
   char fileName[FILENAME_BUFFER_SIZE];
-  snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName,
-           e->snapshot_output_count);
+  if (e->snapshot_label_delta == 1)
+    snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName,
+             e->snapshot_output_count + e->snapshot_label_first);
+  else
+    snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%06i.hdf5", baseName,
+             e->snapshot_output_count * e->snapshot_label_delta +
+                 e->snapshot_label_first);
 
   /* Prepare some file-access properties */
   hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS);
diff --git a/src/part.h b/src/part.h
index bca84cc0212e79e15ffbeeeb0bbcfc714d5481be..145bf2111771d8ad254affb213b93b7ac829f1a6 100644
--- a/src/part.h
+++ b/src/part.h
@@ -69,8 +69,8 @@
 #include "./hydro/Shadowswift/hydro_part.h"
 #define hydro_need_extra_init_loop 0
 #define EXTRA_HYDRO_LOOP
-#elif defined(MINIMAL_MULTI_MAT_SPH)
-#include "./hydro/MinimalMultiMat/hydro_part.h"
+#elif defined(PLANETARY_SPH)
+#include "./hydro/Planetary/hydro_part.h"
 #define hydro_need_extra_init_loop 0
 #else
 #error "Invalid choice of SPH variant"
diff --git a/src/riemann/riemann_hllc.h b/src/riemann/riemann_hllc.h
index d7e376fe667dd3cfeac58d5820053057ab928d3e..a34b907ba5c6142755f2c4107d7b456393c12b42 100644
--- a/src/riemann/riemann_hllc.h
+++ b/src/riemann/riemann_hllc.h
@@ -33,11 +33,6 @@
 #include "riemann_checks.h"
 #include "riemann_vacuum.h"
 
-#ifndef EOS_IDEAL_GAS
-#error \
-    "The HLLC Riemann solver currently only supports and ideal gas equation of state. Either select this equation of state, or try using another Riemann solver!"
-#endif
-
 __attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
     const float *WL, const float *WR, const float *n, const float *vij,
     float *totflux) {
@@ -48,19 +43,21 @@ __attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
 
   /* Handle pure vacuum */
   if (!WL[0] && !WR[0]) {
-    totflux[0] = 0.f;
-    totflux[1] = 0.f;
-    totflux[2] = 0.f;
-    totflux[3] = 0.f;
-    totflux[4] = 0.f;
+    totflux[0] = 0.0f;
+    totflux[1] = 0.0f;
+    totflux[2] = 0.0f;
+    totflux[3] = 0.0f;
+    totflux[4] = 0.0f;
     return;
   }
 
   /* STEP 0: obtain velocity in interface frame */
   const float uL = WL[1] * n[0] + WL[2] * n[1] + WL[3] * n[2];
   const float uR = WR[1] * n[0] + WR[2] * n[1] + WR[3] * n[2];
-  const float aL = sqrtf(hydro_gamma * WL[4] / WL[0]);
-  const float aR = sqrtf(hydro_gamma * WR[4] / WR[0]);
+  const float rhoLinv = 1.0f / WL[0];
+  const float rhoRinv = 1.0f / WR[0];
+  const float aL = sqrtf(hydro_gamma * WL[4] * rhoLinv);
+  const float aR = sqrtf(hydro_gamma * WR[4] * rhoRinv);
 
   /* Handle vacuum: vacuum does not require iteration and is always exact */
   if (riemann_is_vacuum(WL, WR, uL, uR, aL, aR)) {
@@ -69,98 +66,90 @@ __attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
   }
 
   /* STEP 1: pressure estimate */
-  const float rhobar = 0.5f * (WL[0] + WR[0]);
-  const float abar = 0.5f * (aL + aR);
-  const float pPVRS = 0.5f * (WL[4] + WR[4]) - 0.5f * (uR - uL) * rhobar * abar;
-  const float pstar = max(0.f, pPVRS);
+  const float rhobar = WL[0] + WR[0];
+  const float abar = aL + aR;
+  const float pPVRS =
+      0.5f * ((WL[4] + WR[4]) - 0.25f * (uR - uL) * rhobar * abar);
+  const float pstar = max(0.0f, pPVRS);
 
   /* STEP 2: wave speed estimates
      all these speeds are along the interface normal, since uL and uR are */
-  float qL = 1.f;
-  if (pstar > WL[4] && WL[4] > 0.f) {
-    qL = sqrtf(1.f + 0.5f * hydro_gamma_plus_one * hydro_one_over_gamma *
-                         (pstar / WL[4] - 1.f));
+  float qL = 1.0f;
+  if (pstar > WL[4] && WL[4] > 0.0f) {
+    qL = sqrtf(1.0f + 0.5f * hydro_gamma_plus_one * hydro_one_over_gamma *
+                          (pstar / WL[4] - 1.0f));
   }
-  float qR = 1.f;
-  if (pstar > WR[4] && WR[4] > 0.f) {
-    qR = sqrtf(1.f + 0.5f * hydro_gamma_plus_one * hydro_one_over_gamma *
-                         (pstar / WR[4] - 1.f));
+  float qR = 1.0f;
+  if (pstar > WR[4] && WR[4] > 0.0f) {
+    qR = sqrtf(1.0f + 0.5f * hydro_gamma_plus_one * hydro_one_over_gamma *
+                          (pstar / WR[4] - 1.0f));
   }
-  const float SL = uL - aL * qL;
-  const float SR = uR + aR * qR;
+  const float SLmuL = -aL * qL;
+  const float SRmuR = aR * qR;
   const float Sstar =
-      (WR[4] - WL[4] + WL[0] * uL * (SL - uL) - WR[0] * uR * (SR - uR)) /
-      (WL[0] * (SL - uL) - WR[0] * (SR - uR));
+      (WR[4] - WL[4] + WL[0] * uL * SLmuL - WR[0] * uR * SRmuR) /
+      (WL[0] * SLmuL - WR[0] * SRmuR);
 
   /* STEP 3: HLLC flux in a frame moving with the interface velocity */
-  if (Sstar >= 0.f) {
+  if (Sstar >= 0.0f) {
+    const float rhoLuL = WL[0] * uL;
+    const float v2 = WL[1] * WL[1] + WL[2] * WL[2] + WL[3] * WL[3];
+    const float eL =
+        WL[4] * rhoLinv * hydro_one_over_gamma_minus_one + 0.5f * v2;
+    const float SL = SLmuL + uL;
+
     /* flux FL */
-    totflux[0] = WL[0] * uL;
+    totflux[0] = rhoLuL;
     /* these are the actual correct fluxes in the boosted lab frame
        (not rotated to interface frame) */
-    totflux[1] = WL[0] * WL[1] * uL + WL[4] * n[0];
-    totflux[2] = WL[0] * WL[2] * uL + WL[4] * n[1];
-    totflux[3] = WL[0] * WL[3] * uL + WL[4] * n[2];
-    const float v2 = WL[1] * WL[1] + WL[2] * WL[2] + WL[3] * WL[3];
-    const float eL = WL[4] * hydro_one_over_gamma_minus_one / WL[0] + 0.5f * v2;
-    totflux[4] = WL[0] * eL * uL + WL[4] * uL;
-    if (SL < 0.f) {
-
-      float UstarL[5];
-
-      /* add flux FstarL */
-      UstarL[0] = 1.f;
-      /* we need UstarL in the lab frame:
-       * subtract the velocity in the interface frame from the lab frame
-       * velocity and then add Sstar in interface frame */
-      UstarL[1] = WL[1] + (Sstar - uL) * n[0];
-      UstarL[2] = WL[2] + (Sstar - uL) * n[1];
-      UstarL[3] = WL[3] + (Sstar - uL) * n[2];
-      UstarL[4] = eL + (Sstar - uL) * (Sstar + WL[4] / (WL[0] * (SL - uL)));
-      UstarL[0] *= WL[0] * (SL - uL) / (SL - Sstar);
-      UstarL[1] *= WL[0] * (SL - uL) / (SL - Sstar);
-      UstarL[2] *= WL[0] * (SL - uL) / (SL - Sstar);
-      UstarL[3] *= WL[0] * (SL - uL) / (SL - Sstar);
-      UstarL[4] *= WL[0] * (SL - uL) / (SL - Sstar);
-      totflux[0] += SL * (UstarL[0] - WL[0]);
-      totflux[1] += SL * (UstarL[1] - WL[0] * WL[1]);
-      totflux[2] += SL * (UstarL[2] - WL[0] * WL[2]);
-      totflux[3] += SL * (UstarL[3] - WL[0] * WL[3]);
-      totflux[4] += SL * (UstarL[4] - WL[0] * eL);
+    totflux[1] = rhoLuL * WL[1] + WL[4] * n[0];
+    totflux[2] = rhoLuL * WL[2] + WL[4] * n[1];
+    totflux[3] = rhoLuL * WL[3] + WL[4] * n[2];
+    totflux[4] = rhoLuL * eL + WL[4] * uL;
+
+    if (SL < 0.0f) {
+
+      const float starfac = SLmuL / (SL - Sstar) - 1.0f;
+      const float rhoLSL = WL[0] * SL;
+      const float SstarmuL = Sstar - uL;
+      const float rhoLSLstarfac = rhoLSL * starfac;
+      const float rhoLSLSstarmuL = rhoLSL * SstarmuL;
+
+      totflux[0] += rhoLSLstarfac;
+      totflux[1] += rhoLSLstarfac * WL[1] + rhoLSLSstarmuL * n[0];
+      totflux[2] += rhoLSLstarfac * WL[2] + rhoLSLSstarmuL * n[1];
+      totflux[3] += rhoLSLstarfac * WL[3] + rhoLSLSstarmuL * n[2];
+      totflux[4] += rhoLSLstarfac * eL +
+                    rhoLSLSstarmuL * (Sstar + WL[4] / (WL[0] * SLmuL));
     }
   } else {
-    /* flux FR */
-    totflux[0] = WR[0] * uR;
-    totflux[1] = WR[0] * WR[1] * uR + WR[4] * n[0];
-    totflux[2] = WR[0] * WR[2] * uR + WR[4] * n[1];
-    totflux[3] = WR[0] * WR[3] * uR + WR[4] * n[2];
+    const float rhoRuR = WR[0] * uR;
     const float v2 = WR[1] * WR[1] + WR[2] * WR[2] + WR[3] * WR[3];
-    const float eR = WR[4] * hydro_one_over_gamma_minus_one / WR[0] + 0.5f * v2;
-    totflux[4] = WR[0] * eR * uR + WR[4] * uR;
-    if (SR > 0.f) {
+    const float eR =
+        WR[4] * rhoRinv * hydro_one_over_gamma_minus_one + 0.5f * v2;
+    const float SR = SRmuR + uR;
 
-      float UstarR[5];
-
-      /* add flux FstarR */
-      UstarR[0] = 1.f;
-
-      /* we need UstarR in the lab frame:
-       * subtract the velocity in the interface frame from the lab frame
-       * velocity and then add Sstar in interface frame */
-      UstarR[1] = WR[1] + (Sstar - uR) * n[0];
-      UstarR[2] = WR[2] + (Sstar - uR) * n[1];
-      UstarR[3] = WR[3] + (Sstar - uR) * n[2];
-      UstarR[4] = eR + (Sstar - uR) * (Sstar + WR[4] / (WR[0] * (SR - uR)));
-      UstarR[0] *= WR[0] * (SR - uR) / (SR - Sstar);
-      UstarR[1] *= WR[0] * (SR - uR) / (SR - Sstar);
-      UstarR[2] *= WR[0] * (SR - uR) / (SR - Sstar);
-      UstarR[3] *= WR[0] * (SR - uR) / (SR - Sstar);
-      UstarR[4] *= WR[0] * (SR - uR) / (SR - Sstar);
-      totflux[0] += SR * (UstarR[0] - WR[0]);
-      totflux[1] += SR * (UstarR[1] - WR[0] * WR[1]);
-      totflux[2] += SR * (UstarR[2] - WR[0] * WR[2]);
-      totflux[3] += SR * (UstarR[3] - WR[0] * WR[3]);
-      totflux[4] += SR * (UstarR[4] - WR[0] * eR);
+    /* flux FR */
+    totflux[0] = rhoRuR;
+    totflux[1] = rhoRuR * WR[1] + WR[4] * n[0];
+    totflux[2] = rhoRuR * WR[2] + WR[4] * n[1];
+    totflux[3] = rhoRuR * WR[3] + WR[4] * n[2];
+    totflux[4] = rhoRuR * eR + WR[4] * uR;
+
+    if (SR > 0.0f) {
+
+      const float starfac = SRmuR / (SR - Sstar) - 1.0f;
+      const float rhoRSR = WR[0] * SR;
+      const float SstarmuR = Sstar - uR;
+      const float rhoRSRstarfac = rhoRSR * starfac;
+      const float rhoRSRSstarmuR = rhoRSR * SstarmuR;
+
+      totflux[0] += rhoRSRstarfac;
+      totflux[1] += rhoRSRstarfac * WR[1] + rhoRSRSstarmuR * n[0];
+      totflux[2] += rhoRSRstarfac * WR[2] + rhoRSRSstarmuR * n[1];
+      totflux[3] += rhoRSRstarfac * WR[3] + rhoRSRSstarmuR * n[2];
+      totflux[4] += rhoRSRstarfac * eR +
+                    rhoRSRSstarmuR * (Sstar + WR[4] / (WR[0] * SRmuR));
     }
   }
 
@@ -194,11 +183,11 @@ riemann_solve_for_middle_state_flux(const float *WL, const float *WR,
 
   /* Handle pure vacuum */
   if (!WL[0] && !WR[0]) {
-    totflux[0] = 0.f;
-    totflux[1] = 0.f;
-    totflux[2] = 0.f;
-    totflux[3] = 0.f;
-    totflux[4] = 0.f;
+    totflux[0] = 0.0f;
+    totflux[1] = 0.0f;
+    totflux[2] = 0.0f;
+    totflux[3] = 0.0f;
+    totflux[4] = 0.0f;
     return;
   }
 
@@ -210,37 +199,38 @@ riemann_solve_for_middle_state_flux(const float *WL, const float *WR,
 
   /* Handle vacuum: vacuum does not require iteration and is always exact */
   if (riemann_is_vacuum(WL, WR, uL, uR, aL, aR)) {
-    totflux[0] = 0.f;
-    totflux[1] = 0.f;
-    totflux[2] = 0.f;
-    totflux[3] = 0.f;
-    totflux[4] = 0.f;
+    totflux[0] = 0.0f;
+    totflux[1] = 0.0f;
+    totflux[2] = 0.0f;
+    totflux[3] = 0.0f;
+    totflux[4] = 0.0f;
     return;
   }
 
   /* STEP 1: pressure estimate */
-  const float rhobar = 0.5f * (WL[0] + WR[0]);
-  const float abar = 0.5f * (aL + aR);
-  const float pPVRS = 0.5f * (WL[4] + WR[4]) - 0.5f * (uR - uL) * rhobar * abar;
+  const float rhobar = WL[0] + WR[0];
+  const float abar = aL + aR;
+  const float pPVRS =
+      0.5f * ((WL[4] + WR[4]) - 0.25f * (uR - uL) * rhobar * abar);
   const float pstar = max(0.f, pPVRS);
 
   /* STEP 2: wave speed estimates
      all these speeds are along the interface normal, since uL and uR are */
-  float qL = 1.f;
-  if (pstar > WL[4] && WL[4] > 0.f) {
-    qL = sqrtf(1.f + 0.5f * hydro_gamma_plus_one * hydro_one_over_gamma *
-                         (pstar / WL[4] - 1.f));
+  float qL = 1.0f;
+  if (pstar > WL[4] && WL[4] > 0.0f) {
+    qL = sqrtf(1.0f + 0.5f * hydro_gamma_plus_one * hydro_one_over_gamma *
+                          (pstar / WL[4] - 1.0f));
   }
-  float qR = 1.f;
-  if (pstar > WR[4] && WR[4] > 0.f) {
-    qR = sqrtf(1.f + 0.5f * hydro_gamma_plus_one * hydro_one_over_gamma *
-                         (pstar / WR[4] - 1.f));
+  float qR = 1.0f;
+  if (pstar > WR[4] && WR[4] > 0.0f) {
+    qR = sqrtf(1.0f + 0.5f * hydro_gamma_plus_one * hydro_one_over_gamma *
+                          (pstar / WR[4] - 1.0f));
   }
-  const float SL = uL - aL * qL;
-  const float SR = uR + aR * qR;
+  const float SLmuL = -aL * qL;
+  const float SRmuR = aR * qR;
   const float Sstar =
-      (WR[4] - WL[4] + WL[0] * uL * (SL - uL) - WR[0] * uR * (SR - uR)) /
-      (WL[0] * (SL - uL) - WR[0] * (SR - uR));
+      (WR[4] - WL[4] + WL[0] * uL * SLmuL - WR[0] * uR * SRmuR) /
+      (WL[0] * SLmuL - WR[0] * SRmuR);
 
   totflux[0] = 0.0f;
   totflux[1] = pstar * n[0];
diff --git a/src/runner.c b/src/runner.c
index 187e601315555fa44f686cd212365694a2e505ff..60c2999b9a3dcc3907eeea17406401f3f56e5f7f 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -766,6 +766,7 @@ void runner_do_ghost(struct runner *r, struct cell *c, int timer) {
 
           /* Double h and try again */
           h_new = 2.f * h_old;
+
         } else {
 
           /* Finish the density calculation */
@@ -780,6 +781,46 @@ void runner_do_ghost(struct runner *r, struct cell *c, int timer) {
               p->density.wcount_dh * h_old_dim +
               hydro_dimension * p->density.wcount * h_old_dim_minus_one;
 
+          /* Skip if h is already h_max and we don't have enough neighbours */
+          if ((p->h >= hydro_h_max) && (f < 0.f)) {
+
+          /* We have a particle whose smoothing length is already set (wants to
+           * be larger but has already hit the maximum). So, just tidy up as if
+           * the smoothing length had converged correctly  */
+
+#ifdef EXTRA_HYDRO_LOOP
+
+            /* As of here, particle gradient variables will be set. */
+            /* The force variables are set in the extra ghost. */
+
+            /* Compute variables required for the gradient loop */
+            hydro_prepare_gradient(p, xp, cosmo);
+
+            /* The particle gradient values are now set.  Do _NOT_
+               try to read any particle density variables! */
+
+            /* Prepare the particle for the gradient loop over neighbours */
+            hydro_reset_gradient(p);
+
+#else
+            /* As of here, particle force variables will be set. */
+
+            /* Compute variables required for the force loop */
+            hydro_prepare_force(p, xp, cosmo);
+
+            /* The particle force values are now set.  Do _NOT_
+               try to read any particle density variables! */
+
+            /* Prepare the particle for the force loop over neighbours */
+            hydro_reset_acceleration(p);
+
+#endif /* EXTRA_HYDRO_LOOP */
+
+            continue;
+          }
+
+          /* Normal case: Use Newton-Raphson to get a better value of h */
+
           /* Avoid floating point exception from f_prime = 0 */
           h_new = h_old - f / (f_prime + FLT_MIN);
 
@@ -1101,7 +1142,7 @@ void runner_do_kick1(struct runner *r, struct cell *c, int timer) {
 #endif
 
         /* Time interval for this half-kick */
-        double dt_kick_grav, dt_kick_hydro, dt_kick_therm;
+        double dt_kick_grav, dt_kick_hydro, dt_kick_therm, dt_kick_corr;
         if (with_cosmology) {
           dt_kick_hydro = cosmology_get_hydro_kick_factor(
               cosmo, ti_begin, ti_begin + ti_step / 2);
@@ -1109,15 +1150,19 @@ void runner_do_kick1(struct runner *r, struct cell *c, int timer) {
                                                         ti_begin + ti_step / 2);
           dt_kick_therm = cosmology_get_therm_kick_factor(
               cosmo, ti_begin, ti_begin + ti_step / 2);
+          dt_kick_corr = cosmology_get_corr_kick_factor(cosmo, ti_begin,
+                                                        ti_begin + ti_step / 2);
         } else {
           dt_kick_hydro = (ti_step / 2) * time_base;
           dt_kick_grav = (ti_step / 2) * time_base;
           dt_kick_therm = (ti_step / 2) * time_base;
+          dt_kick_corr = (ti_step / 2) * time_base;
         }
 
         /* do the kick */
-        kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm, cosmo,
-                  hydro_props, ti_begin, ti_begin + ti_step / 2);
+        kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm,
+                  dt_kick_corr, cosmo, hydro_props, ti_begin,
+                  ti_begin + ti_step / 2);
 
         /* Update the accelerations to be used in the drift for hydro */
         if (p->gpart != NULL) {
@@ -1267,7 +1312,7 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) {
               ti_begin, ti_step, p->time_bin, ti_current);
 #endif
         /* Time interval for this half-kick */
-        double dt_kick_grav, dt_kick_hydro, dt_kick_therm;
+        double dt_kick_grav, dt_kick_hydro, dt_kick_therm, dt_kick_corr;
         if (with_cosmology) {
           dt_kick_hydro = cosmology_get_hydro_kick_factor(
               cosmo, ti_begin + ti_step / 2, ti_begin + ti_step);
@@ -1275,15 +1320,19 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) {
               cosmo, ti_begin + ti_step / 2, ti_begin + ti_step);
           dt_kick_therm = cosmology_get_therm_kick_factor(
               cosmo, ti_begin + ti_step / 2, ti_begin + ti_step);
+          dt_kick_corr = cosmology_get_corr_kick_factor(
+              cosmo, ti_begin + ti_step / 2, ti_begin + ti_step);
         } else {
           dt_kick_hydro = (ti_step / 2) * time_base;
           dt_kick_grav = (ti_step / 2) * time_base;
           dt_kick_therm = (ti_step / 2) * time_base;
+          dt_kick_corr = (ti_step / 2) * time_base;
         }
 
         /* Finish the time-step with a second half-kick */
-        kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm, cosmo,
-                  hydro_props, ti_begin + ti_step / 2, ti_begin + ti_step);
+        kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm,
+                  dt_kick_corr, cosmo, hydro_props, ti_begin + ti_step / 2,
+                  ti_begin + ti_step);
 
 #ifdef SWIFT_DEBUG_CHECKS
         /* Check that kick and the drift are synchronized */
diff --git a/src/runner_doiact_grav.h b/src/runner_doiact_grav.h
index dcc3265f34e405a1a414085851ce8d30b9cd3d3d..812a6e3850fa66f614326c872511c36ba91b5635 100644
--- a/src/runner_doiact_grav.h
+++ b/src/runner_doiact_grav.h
@@ -1529,7 +1529,6 @@ static INLINE void runner_do_grav_long_range(struct runner *r, struct cell *ci,
 
   /* Flag that contributions will be recieved */
   struct gravity_tensors *const multi_i = ci->multipole;
-  multi_i->pot.interacted = 1;
 
   /* Recover the top-level multipole (for distance checks) */
   struct gravity_tensors *const multi_top = top->multipole;
@@ -1585,6 +1584,9 @@ static INLINE void runner_do_grav_long_range(struct runner *r, struct cell *ci,
       runner_dopair_grav_mm(r, ci, cj);
       // runner_dopair_recursive_grav_pm(r, ci, cj);
 
+      /* Record that this multipole received a contribution */
+      multi_i->pot.interacted = 1;
+
     } /* We are in charge of this pair */
   }   /* Loop over top-level cells */
 
diff --git a/src/serial_io.c b/src/serial_io.c
index dafa75ab0baacb1b5ddeee34020c9773893bced7..3a7d2e5a68873ca9523fe09bbf19fb2e185482dd 100644
--- a/src/serial_io.c
+++ b/src/serial_io.c
@@ -759,10 +759,11 @@ void write_output_serial(struct engine* e, const char* baseName,
   char fileName[FILENAME_BUFFER_SIZE];
   if (e->snapshot_label_delta == 1)
     snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName,
-             e->snapshot_output_count);
+             e->snapshot_output_count + e->snapshot_label_first);
   else
     snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%06i.hdf5", baseName,
-             e->snapshot_output_count * e->snapshot_label_delta);
+             e->snapshot_output_count * e->snapshot_label_delta +
+                 e->snapshot_label_first);
 
   /* Compute offset in the file and total number of particles */
   size_t N[swift_type_count] = {Ngas, Ndm, 0, 0, Nstars, 0};
diff --git a/src/single_io.c b/src/single_io.c
index a0f02878b52c89beca94d15c09ef7d456ce0a4eb..8cbb6743d38a022581273a0a0b03c9b3b6fda32e 100644
--- a/src/single_io.c
+++ b/src/single_io.c
@@ -625,10 +625,11 @@ void write_output_single(struct engine* e, const char* baseName,
   char fileName[FILENAME_BUFFER_SIZE];
   if (e->snapshot_label_delta == 1)
     snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%04i.hdf5", baseName,
-             e->snapshot_output_count);
+             e->snapshot_output_count + e->snapshot_label_first);
   else
     snprintf(fileName, FILENAME_BUFFER_SIZE, "%s_%06i.hdf5", baseName,
-             e->snapshot_output_count * e->snapshot_label_delta);
+             e->snapshot_output_count * e->snapshot_label_delta +
+                 e->snapshot_label_first);
 
   /* First time, we need to create the XMF file */
   if (e->snapshot_output_count == 0) xmf_create_file(baseName);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2744164e2c794ef4471a51ffb66db3049d9fa048..ae234581228b2ea6035af845292e9cc22d6bcaa8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -28,7 +28,7 @@ TESTS = testGreetings testMaths testReading.sh testSingle testKernel testSymmetr
         testVoronoi1D testVoronoi2D testVoronoi3D testGravityDerivatives \
 	testPeriodicBC.sh testPeriodicBCPerturbed.sh testPotentialSelf \
 	testPotentialPair testEOS testUtilities testSelectOutput.sh \
-	testCbrt testCosmology
+	testCbrt testCosmology testOutputList
 
 # List of test programs to compile
 check_PROGRAMS = testGreetings testReading testSingle testTimeIntegration \
@@ -39,7 +39,7 @@ check_PROGRAMS = testGreetings testReading testSingle testTimeIntegration \
                  testRiemannHLLC testMatrixInversion testDump testLogger \
 		 testVoronoi1D testVoronoi2D testVoronoi3D testPeriodicBC \
 		 testGravityDerivatives testPotentialSelf testPotentialPair testEOS testUtilities \
-		 testSelectOutput testCbrt testCosmology
+		 testSelectOutput testCbrt testCosmology testOutputList
 
 # Rebuild tests when SWIFT is updated.
 $(check_PROGRAMS): ../src/.libs/libswiftsim.a
@@ -55,6 +55,8 @@ testSelectOutput_SOURCES = testSelectOutput.c
 
 testCosmology_SOURCES = testCosmology.c
 
+testOutputList_SOURCES = testOutputList.c
+
 testSymmetry_SOURCES = testSymmetry.c
 
 # Added because of issues using memcmp on clang 4.x
@@ -126,4 +128,6 @@ EXTRA_DIST = testReading.sh makeInput.py testActivePair.sh \
              tolerance_27_normal.dat tolerance_27_perturbed.dat tolerance_27_perturbed_h.dat tolerance_27_perturbed_h2.dat \
 	     tolerance_testInteractions.dat tolerance_pair_active.dat tolerance_pair_force_active.dat \
 	     fft_params.yml tolerance_periodic_BC_normal.dat tolerance_periodic_BC_perturbed.dat \
-	     testEOS.sh testEOS_plot.sh testSelectOutput.sh selectOutput.yml
+	     testEOS.sh testEOS_plot.sh testSelectOutput.sh selectOutput.yml \
+             output_list_params.yml output_list_time.txt output_list_redshift.txt \
+             output_list_scale_factor.txt
diff --git a/tests/output_list_params.yml b/tests/output_list_params.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2aad7573351f6c8fb3f45fc78be3a1a326f23310
--- /dev/null
+++ b/tests/output_list_params.yml
@@ -0,0 +1,28 @@
+# Cosmological parameters
+Cosmology:
+  h:              0.6777        # Reduced Hubble constant
+  a_begin:        1e-2         # Initial scale-factor of the simulation
+  a_end:          1.0           # Final scale factor of the simulation
+  Omega_m:        0.307         # Matter density parameter
+  Omega_lambda:   0.693         # Dark-energy density parameter
+  Omega_b:        0.0455        # Baryon density parameter
+
+# Define the system of units to use internally. 
+Units:
+  UnitMass_in_cgs:     1.48e43       # 10^10 M_sun in grams
+  UnitLength_in_cgs:   3.08e21       # kpc in centimeters
+  UnitVelocity_in_cgs: 1e5           # km/s in centimeters per second
+  UnitCurrent_in_cgs:  1             # Amperes
+  UnitTemp_in_cgs:     1             # Kelvin
+
+Redshift:
+  output_list_on:      1  # (Optional) Enable the output list
+  output_list:         output_list_redshift.txt # (Optional) File containing the output times (see documentation in "Parameter File" section)
+
+Time:
+  output_list_on:      1  # (Optional) Enable the output list
+  output_list:         output_list_time.txt # (Optional) File containing the output times (see documentation in "Parameter File" section)
+
+ScaleFactor:
+  output_list_on:      1  # (Optional) Enable the output list
+  output_list:         output_list_scale_factor.txt # (Optional) File containing the output times (see documentation in "Parameter File" section)
diff --git a/tests/output_list_redshift.txt b/tests/output_list_redshift.txt
new file mode 100644
index 0000000000000000000000000000000000000000..311648ebf5fc8199d97bf49f0d9686b28726688c
--- /dev/null
+++ b/tests/output_list_redshift.txt
@@ -0,0 +1,4 @@
+# Redshift
+99
+9
+1
diff --git a/tests/output_list_scale_factor.txt b/tests/output_list_scale_factor.txt
new file mode 100644
index 0000000000000000000000000000000000000000..94ca1aa88660fb0f6cd6cbcb37a16ae19be69056
--- /dev/null
+++ b/tests/output_list_scale_factor.txt
@@ -0,0 +1,4 @@
+# Scale Factor
+0.01
+0.1
+0.5
diff --git a/tests/output_list_time.txt b/tests/output_list_time.txt
new file mode 100644
index 0000000000000000000000000000000000000000..887087651a5c978e4cbdeeedb283918ad770f9be
--- /dev/null
+++ b/tests/output_list_time.txt
@@ -0,0 +1,4 @@
+# Time
+0.
+10.
+12.
diff --git a/tests/test125cells.c b/tests/test125cells.c
index 70af9dfb19aeee812fdc90733a604f795b7f478f..2a2c20dbb064539b481e169b49b74389e79a8174 100644
--- a/tests/test125cells.c
+++ b/tests/test125cells.c
@@ -120,7 +120,7 @@ void set_energy_state(struct part *part, enum pressure_field press, float size,
   part->u = pressure / (hydro_gamma_minus_one * density);
 #elif defined(MINIMAL_SPH) || defined(HOPKINS_PU_SPH)
   part->u = pressure / (hydro_gamma_minus_one * density);
-#elif defined(MINIMAL_MULTI_MAT_SPH)
+#elif defined(PLANETARY_SPH)
   part->u = pressure / (hydro_gamma_minus_one * density);
 #elif defined(GIZMO_MFV_SPH) || defined(SHADOWFAX_SPH)
   part->primitives.P = pressure;
@@ -407,8 +407,8 @@ void dump_particle_fields(char *fileName, struct cell *main_cell,
             main_cell->parts[pid].v[0], main_cell->parts[pid].v[1],
             main_cell->parts[pid].v[2], main_cell->parts[pid].h,
             hydro_get_comoving_density(&main_cell->parts[pid]),
-#if defined(MINIMAL_SPH) || defined(MINIMAL_MULTI_MAT_SPH) || \
-    defined(GIZMO_MFV_SPH) || defined(SHADOWFAX_SPH) ||       \
+#if defined(MINIMAL_SPH) || defined(PLANETARY_SPH) ||   \
+    defined(GIZMO_MFV_SPH) || defined(SHADOWFAX_SPH) || \
     defined(HOPKINS_PU_SPH)
             0.f,
 #else
diff --git a/tests/testCosmology.c b/tests/testCosmology.c
index 698351ad952e7d0b5f7d8e354c45a1a2dd53f968..bafad55471453f7308d1498daa15dbae3a76a6bc 100644
--- a/tests/testCosmology.c
+++ b/tests/testCosmology.c
@@ -24,7 +24,7 @@
 #include "swift.h"
 
 #define N_CHECK 20
-#define TOLERANCE 1e-3
+#define TOLERANCE 1e-7
 
 void test_params_init(struct swift_params *params) {
   parser_init("", params);
@@ -72,5 +72,6 @@ int main(int argc, char *argv[]) {
 
   message("Everything seems fine with cosmology.");
 
+  cosmology_clean(&cosmo);
   return 0;
 }
diff --git a/tests/testEOS.c b/tests/testEOS.c
index d090d83d77a16b2c5b4506c5f9224b3e4434d1be..4a1e666b47acc55a5ed7f1800e7199a1abb5e821 100644
--- a/tests/testEOS.c
+++ b/tests/testEOS.c
@@ -74,6 +74,11 @@
  *  P_1_0   ...     ...     P_1_num_u
  *  ...     ...     ...     ...
  *  P_num_rho_0     ...     P_num_rho_num_u
+ *  c_0_0   c_0_1   ...     c_0_num_u           # Array of sound speeds, c(rho,
+ * u)
+ *  c_1_0   ...     ...     c_1_num_u
+ *  ...     ...     ...     ...
+ *  c_num_rho_0     ...     c_num_rho_num_u
  *
  * Note that the values tested extend beyond the range that most EOS are
  * designed for (e.g. outside table limits), to help test the EOS in case of
@@ -83,21 +88,24 @@
 
 #ifdef EOS_PLANETARY
 int main(int argc, char *argv[]) {
-  float rho, log_rho, log_u, P;
+  float rho, u, log_rho, log_u, P, c;
   struct unit_system us;
+  struct swift_params *params =
+      (struct swift_params *)malloc(sizeof(struct swift_params));
+  if (params == NULL) error("Error allocating memory for the parameter file.");
   const struct phys_const *phys_const = 0;  // Unused placeholder
-  struct swift_params *params = 0;          // Unused placeholder
   const float J_kg_to_erg_g = 1e4;          // Convert J/kg to erg/g
   char filename[64];
   // Output table params
   const int num_rho = 100, num_u = 100;
-  float log_rho_min = logf(1e-4), log_rho_max = logf(30.f),
-        log_u_min = logf(1e4), log_u_max = logf(1e10),
-        log_rho_step = (log_rho_max - log_rho_min) / (num_rho - 1.f),
+  float log_rho_min = logf(1e-4f), log_rho_max = logf(1e3f),  // Densities (cgs)
+      log_u_min = logf(1e4f),
+        log_u_max = logf(1e13f),  // Sp. int. energies (SI)
+      log_rho_step = (log_rho_max - log_rho_min) / (num_rho - 1.f),
         log_u_step = (log_u_max - log_u_min) / (num_u - 1.f);
   float A1_rho[num_rho], A1_u[num_u];
   // Sys args
-  int mat_id, do_output;
+  int mat_id_in, do_output;
   // Default sys args
   const int mat_id_def = eos_planetary_id_HM80_ice;
   const int do_output_def = 0;
@@ -106,34 +114,40 @@ int main(int argc, char *argv[]) {
   switch (argc) {
     case 1:
       // Default both
-      mat_id = mat_id_def;
+      mat_id_in = mat_id_def;
       do_output = do_output_def;
       break;
 
     case 2:
       // Read mat_id, default do_output
-      mat_id = atoi(argv[1]);
+      mat_id_in = atoi(argv[1]);
       do_output = do_output_def;
       break;
 
     case 3:
       // Read both
-      mat_id = atoi(argv[1]);
+      mat_id_in = atoi(argv[1]);
       do_output = atoi(argv[2]);
       break;
 
     default:
       error("Invalid number of system arguments!\n");
-      mat_id = mat_id_def;  // Ignored, just here to keep the compiler happy
+      mat_id_in = mat_id_def;  // Ignored, just here to keep the compiler happy
       do_output = do_output_def;
   };
 
+  enum eos_planetary_material_id mat_id =
+      (enum eos_planetary_material_id)mat_id_in;
+
   /* Greeting message */
   printf("This is %s\n", package_description());
 
   // Check material ID
-  // Material base type
-  switch ((int)(mat_id / eos_planetary_type_factor)) {
+  const enum eos_planetary_type_id type =
+      (enum eos_planetary_type_id)(mat_id / eos_planetary_type_factor);
+
+  // Select the material base type
+  switch (type) {
     // Tillotson
     case eos_planetary_type_Til:
       switch (mat_id) {
@@ -174,27 +188,23 @@ int main(int argc, char *argv[]) {
       };
       break;
 
-    // ANEOS
-    case eos_planetary_type_ANEOS:
+    // SESAME
+    case eos_planetary_type_SESAME:
       switch (mat_id) {
-        case eos_planetary_id_ANEOS_iron:
-          printf("  ANEOS iron \n");
+        case eos_planetary_id_SESAME_iron:
+          printf("  SESAME basalt 7530 \n");
           break;
 
-        case eos_planetary_id_MANEOS_forsterite:
-          printf("  MANEOS forsterite \n");
+        case eos_planetary_id_SESAME_basalt:
+          printf("  SESAME basalt 7530 \n");
           break;
 
-        default:
-          error("Unknown material ID! mat_id = %d \n", mat_id);
-      };
-      break;
+        case eos_planetary_id_SESAME_water:
+          printf("  SESAME water 7154 \n");
+          break;
 
-    // SESAME
-    case eos_planetary_type_SESAME:
-      switch (mat_id) {
-        case eos_planetary_id_SESAME_iron:
-          printf("  SESAME iron \n");
+        case eos_planetary_id_SS08_water:
+          printf("  Senft & Stewart (2008) SESAME-like water \n");
           break;
 
         default:
@@ -206,8 +216,11 @@ int main(int argc, char *argv[]) {
       error("Unknown material type! mat_id = %d \n", mat_id);
   }
 
-  // Convert to internal units (Earth masses and radii)
-  units_init(&us, 5.9724e27, 6.3710e8, 1.f, 1.f, 1.f);
+  // Convert to internal units
+  // Earth masses and radii
+  //  units_init(&us, 5.9724e27, 6.3710e8, 1.f, 1.f, 1.f);
+  // SI
+  units_init(&us, 1000.f, 100.f, 1.f, 1.f, 1.f);
   log_rho_min -= logf(units_cgs_conversion_factor(&us, UNIT_CONV_DENSITY));
   log_rho_max -= logf(units_cgs_conversion_factor(&us, UNIT_CONV_DENSITY));
   log_u_min += logf(J_kg_to_erg_g / units_cgs_conversion_factor(
@@ -215,11 +228,51 @@ int main(int argc, char *argv[]) {
   log_u_max += logf(J_kg_to_erg_g / units_cgs_conversion_factor(
                                         &us, UNIT_CONV_ENERGY_PER_UNIT_MASS));
 
+  // Set the input parameters
+  // Which EOS to initialise
+  parser_set_param(params, "EoS:planetary_use_Til:1");
+  parser_set_param(params, "EoS:planetary_use_HM80:1");
+  parser_set_param(params, "EoS:planetary_use_SESAME:1");
+  // Table file names
+  parser_set_param(params,
+                   "EoS:planetary_HM80_HHe_table_file:"
+                   "../examples/planetary_HM80_HHe.txt");
+  parser_set_param(params,
+                   "EoS:planetary_HM80_ice_table_file:"
+                   "../examples/planetary_HM80_ice.txt");
+  parser_set_param(params,
+                   "EoS:planetary_HM80_rock_table_file:"
+                   "../examples/planetary_HM80_rock.txt");
+  parser_set_param(params,
+                   "EoS:planetary_SESAME_iron_table_file:"
+                   "../examples/planetary_SESAME_iron_2140.txt");
+  parser_set_param(params,
+                   "EoS:planetary_SESAME_basalt_table_file:"
+                   "../examples/planetary_SESAME_basalt_7530.txt");
+  parser_set_param(params,
+                   "EoS:planetary_SESAME_water_table_file:"
+                   "../examples/planetary_SESAME_water_7154.txt");
+  parser_set_param(params,
+                   "EoS:planetary_SS08_water_table_file:"
+                   "../examples/planetary_SS08_water.txt");
+
   // Initialise the EOS materials
   eos_init(&eos, phys_const, &us, params);
 
+  // Manual debug testing
+  if (1) {
+    printf("\n ### MANUAL DEBUG TESTING ### \n");
+
+    rho = 5960;
+    u = 1.7e8;
+    P = gas_pressure_from_internal_energy(rho, u, eos_planetary_id_HM80_ice);
+    printf("u = %.2e,    rho = %.2e,    P = %.2e \n", u, rho, P);
+
+    return 0;
+  }
+
   // Output file
-  sprintf(filename, "testEOS_rho_u_P_%d.txt", mat_id);
+  sprintf(filename, "testEOS_rho_u_P_c_%d.txt", mat_id);
   FILE *f = fopen(filename, "w");
   if (f == NULL) {
     printf("Could not open output file!\n");
@@ -270,6 +323,21 @@ int main(int argc, char *argv[]) {
 
     if (do_output == 1) fprintf(f, "\n");
   }
+
+  // Sound speeds
+  for (int i = 0; i < num_rho; i++) {
+    rho = A1_rho[i];
+
+    for (int j = 0; j < num_u; j++) {
+      c = gas_soundspeed_from_internal_energy(rho, A1_u[j], mat_id);
+
+      if (do_output == 1)
+        fprintf(f, "%.6e ",
+                c * units_cgs_conversion_factor(&us, UNIT_CONV_SPEED));
+    }
+
+    if (do_output == 1) fprintf(f, "\n");
+  }
   fclose(f);
 
   return 0;
diff --git a/tests/testEOS.py b/tests/testEOS.py
index 363bab200b58c65fa24cc033af4b8d3c04b7b503..a2a31a248a2073a834d9543b706a6a12ba12796c 100644
--- a/tests/testEOS.py
+++ b/tests/testEOS.py
@@ -18,8 +18,8 @@
  #
  ##############################################################################
 """
-Plot the output of testEOS to show how the equation of state pressure varies
-with density and specific internal energy.
+Plot the output of testEOS to show how the equation of state pressure and sound
+speed varies with density and specific internal energy.
 
 Usage:
     python  testEOS.py  (mat_id)
@@ -37,9 +37,13 @@ Text file contains:
     P_1_0   ...     ...     P_1_num_u
     ...     ...     ...     ...
     P_num_rho_0     ...     P_num_rho_num_u
+    c_0_0   c_0_1   ...     c_0_num_u           # Array of sound speeds, c(rho, u)
+    c_1_0   ...     ...     c_1_num_u
+    ...     ...     ...     ...
+    c_num_rho_0     ...     c_num_rho_num_u
 
 Note that the values tested extend beyond the range that most EOS are
-designed for (e.g. outside table limits), to help test the EOS in case of
+designed for (e.g. outside table limits), to help test the EOS in cases of
 unexpected particle behaviour.
 """
 
@@ -58,8 +62,7 @@ type_factor = 100
 Di_type = {
     'Til'       : 1,
     'HM80'      : 2,
-    'ANEOS'     : 3,
-    'SESAME'    : 4,
+    'SESAME'    : 3,
 }
 Di_material = {
     # Tillotson
@@ -70,11 +73,11 @@ Di_material = {
     'HM80_HHe'      : Di_type['HM80']*type_factor,      # Hydrogen-helium atmosphere
     'HM80_ice'      : Di_type['HM80']*type_factor + 1,  # H20-CH4-NH3 ice mix
     'HM80_rock'     : Di_type['HM80']*type_factor + 2,  # SiO2-MgO-FeS-FeO rock mix
-    # ANEOS
-    'ANEOS_iron'        : Di_type['ANEOS']*type_factor,
-    'MANEOS_forsterite' : Di_type['ANEOS']*type_factor + 1,
     # SESAME
-    'SESAME_iron'   : Di_type['SESAME']*type_factor,
+    'SESAME_iron'   : Di_type['SESAME']*type_factor,        # 2140
+    'SESAME_basalt' : Di_type['SESAME']*type_factor + 1,    # 7530
+    'SESAME_water'  : Di_type['SESAME']*type_factor + 2,    # 7154
+    'SS08_water'    : Di_type['SESAME']*type_factor + 3,    # Senft & Stewart (2008)
 }
 # Invert so the mat_id are the keys
 Di_mat_id = {mat_id : mat for mat, mat_id in Di_material.iteritems()}
@@ -82,6 +85,7 @@ Di_mat_id = {mat_id : mat for mat, mat_id in Di_material.iteritems()}
 # Unit conversion
 Ba_to_Mbar = 1e-12
 erg_g_to_J_kg = 1e-4
+cm_s_to_m_s = 1e-2
 
 if __name__ == '__main__':
     # Sys args
@@ -101,7 +105,7 @@ if __name__ == '__main__':
         for mat_id, mat in sorted(Di_mat_id.iteritems()):
             print "  %s%s%d" % (mat, (20 - len("%s" % mat))*" ", mat_id)
 
-    filename = "testEOS_rho_u_P_%d.txt" % mat_id
+    filename = "testEOS_rho_u_P_c_%d.txt" % mat_id
 
     # Load the header info and density and energy arrays
     with open(filename) as f:
@@ -110,31 +114,37 @@ if __name__ == '__main__':
         A1_rho = np.array(f.readline().split(), dtype=float)
         A1_u = np.array(f.readline().split(), dtype=float)
 
-    # Load pressure array
+    # Load pressure and soundspeed arrays
     A2_P = np.loadtxt(filename, skiprows=4)
+    A2_c = A2_P[num_rho:]
+    A2_P = A2_P[:num_rho]
 
-    # Convert pressures from cgs Barye to Mbar
-    A2_P *= Ba_to_Mbar
     # Convert energies from cgs to SI
     A1_u *= erg_g_to_J_kg
+    # Convert pressures from cgs (Barye) to Mbar
+    A2_P *= Ba_to_Mbar
+    # Convert sound speeds from cgs to SI
+    A1_u *= cm_s_to_m_s
 
     # Check that the numbers are right
     assert A1_rho.shape == (num_rho,)
     assert A1_u.shape == (num_u,)
     assert A2_P.shape == (num_rho, num_u)
+    assert A2_c.shape == (num_rho, num_u)
 
     # Plot
+    # Pressure: P(rho) at fixed u
     plt.figure(figsize=(7, 7))
     ax = plt.gca()
 
-    # P(rho) at fixed u
-    num_u_fix = 9
-    A1_idx = np.floor(np.linspace(0, num_u - 1, num_u_fix)).astype(int)
-    A1_colour = matplotlib.cm.rainbow(np.linspace(0, 1, num_u_fix))
+    A1_colour = matplotlib.cm.rainbow(np.linspace(0, 1, num_u))
 
-    for i, idx in enumerate(A1_idx):
-        plt.plot(A1_rho, A2_P[:, idx], c=A1_colour[i],
-                 label=r"%.2e" % A1_u[idx])
+    for i_u, u in enumerate(A1_u):
+        if i_u%10 == 0:
+            plt.plot(A1_rho, A2_P[:, i_u], c=A1_colour[i_u],
+                     label=r"%.2e" % u)
+        else:
+            plt.plot(A1_rho, A2_P[:, i_u], c=A1_colour[i_u])
 
     plt.legend(title="Sp. Int. Energy (J kg$^{-1}$)")
     plt.xscale('log')
@@ -144,7 +154,31 @@ if __name__ == '__main__':
     plt.title(mat)
     plt.tight_layout()
 
-    plt.savefig("testEOS_%d.png" % mat_id)
+    plt.savefig("testEOS_P_%d.png" % mat_id)
+    plt.close()
+
+    # Sound speed: c(rho) at fixed u
+    plt.figure(figsize=(7, 7))
+    ax = plt.gca()
+
+    A1_colour = matplotlib.cm.rainbow(np.linspace(0, 1, num_u))
+
+    for i_u, u in enumerate(A1_u):
+        if i_u%10 == 0:
+            plt.plot(A1_rho, A2_c[:, i_u], c=A1_colour[i_u],
+                     label=r"%.2e" % u)
+        else:
+            plt.plot(A1_rho, A2_c[:, i_u], c=A1_colour[i_u])
+
+    plt.legend(title="Sp. Int. Energy (J kg$^{-1}$)")
+    plt.xscale('log')
+    plt.yscale('log')
+    plt.xlabel(r"Density (g cm$^{-3}$)")
+    plt.ylabel(r"Sound Speed (m s^{-1})")
+    plt.title(mat)
+    plt.tight_layout()
+
+    plt.savefig("testEOS_c_%d.png" % mat_id)
     plt.close()
 
 
diff --git a/tests/testEOS.sh b/tests/testEOS.sh
index 411ac746be186bfe5758e03c2a852e081daefd10..bcd87eabbf15a962808843dda76d1829f2917c97 100755
--- a/tests/testEOS.sh
+++ b/tests/testEOS.sh
@@ -13,6 +13,10 @@ A1_mat_id=(
     200
     201
     202
+    300
+    301
+    302
+    303
 )
 
 for mat_id in "${A1_mat_id[@]}"
diff --git a/tests/testEOS_plot.sh b/tests/testEOS_plot.sh
index 39108c5e19d8f4474de508e205951a1fd0aebcc9..5fd7f4976496223e467aae65b2846a8c4e1b7485 100755
--- a/tests/testEOS_plot.sh
+++ b/tests/testEOS_plot.sh
@@ -2,6 +2,8 @@
 
 echo ""
 
+rm -f testEOS*.png
+
 echo "Plotting testEOS output for each planetary material"
 
 A1_mat_id=(
@@ -11,6 +13,10 @@ A1_mat_id=(
     200
     201
     202
+    300
+    301
+    302
+    303
 )
 
 for mat_id in "${A1_mat_id[@]}"
diff --git a/tests/testInteractions.c b/tests/testInteractions.c
index 0a7354f0d2a5e1853ba2c22d696dbb910de2b667..306f14a35ca047430f67e33e9fd63848e9207b68 100644
--- a/tests/testInteractions.c
+++ b/tests/testInteractions.c
@@ -107,8 +107,8 @@ struct part *make_particles(size_t count, double *offset, double spacing,
  */
 void prepare_force(struct part *parts, size_t count) {
 
-#if !defined(GIZMO_MFV_SPH) && !defined(SHADOWFAX_SPH) &&       \
-    !defined(MINIMAL_SPH) && !defined(MINIMAL_MULTI_MAT_SPH) && \
+#if !defined(GIZMO_MFV_SPH) && !defined(SHADOWFAX_SPH) && \
+    !defined(MINIMAL_SPH) && !defined(PLANETARY_SPH) &&   \
     !defined(HOPKINS_PU_SPH)
   struct part *p;
   for (size_t i = 0; i < count; ++i) {
@@ -136,8 +136,7 @@ void dump_indv_particle_fields(char *fileName, struct part *p) {
           "%8.5f %8.5f %13e %13e %13e %13e %13e %8.5f %8.5f\n",
           p->id, p->x[0], p->x[1], p->x[2], p->v[0], p->v[1], p->v[2], p->h,
           hydro_get_comoving_density(p),
-#if defined(MINIMAL_SPH) || defined(MINIMAL_MULTI_MAT_SPH) || \
-    defined(SHADOWFAX_SPH)
+#if defined(MINIMAL_SPH) || defined(PLANETARY_SPH) || defined(SHADOWFAX_SPH)
           0.f,
 #else
           p->density.div_v,
diff --git a/tests/testOutputList.c b/tests/testOutputList.c
new file mode 100644
index 0000000000000000000000000000000000000000..b7df197405ee095cf9bf0a63e8cf7f00585f269f
--- /dev/null
+++ b/tests/testOutputList.c
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Copyright (C) 2016 James Willis (james.s.willis@durham.ac.uk).
+ *               2018 Peter W. Draper (p.w.draper@durham.ac.uk)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ******************************************************************************/
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include "swift.h"
+
+#define Ntest 3
+#define tol 1e-12
+#define filename "output_list_params.yml"
+
+/* Expected values from file */
+const double time_values[Ntest] = {
+    0.,
+    10.,
+    12.,
+};
+
+/* Expected values from file */
+const double a_values[Ntest] = {
+    0.5,
+    0.1,
+    0.01,
+};
+
+void test_no_cosmo(struct engine *e, char *name, int with_assert) {
+  message("Testing output time for %s without cosmology", name);
+
+  struct output_list *list;
+  double delta_time = 0;
+  double output_time = 0;
+
+  /* Test Time */
+  e->time_begin = 0;
+  e->time_end = 14;
+  e->time_base = (e->time_end - e->time_begin) / max_nr_timesteps;
+  e->ti_current = 0;
+  e->policy = !engine_policy_cosmology;
+
+  /* initialize output_list */
+  output_list_init(&list, e, name, &delta_time, &output_time);
+  output_list_print(list);
+
+  for (int i = 0; i < Ntest; i++) {
+    /* Test last value */
+    if (with_assert) {
+      assert(abs(output_time - time_values[i]) < tol);
+    }
+
+    /* Set current time */
+    e->ti_current = (output_time - e->time_begin) / e->time_base;
+    e->ti_current += 1;
+
+    /* Read next value */
+    integertime_t ti_next;
+    output_list_read_next_time(list, e, name, &ti_next);
+
+    output_time = (double)(ti_next * e->time_base) + e->time_begin;
+  }
+
+  output_list_clean(list);
+};
+
+void test_cosmo(struct engine *e, char *name, int with_assert) {
+  message("Testing output time for %s with cosmology", name);
+
+  struct output_list *list;
+  double delta_time = 0;
+  double output_time = 0;
+
+  /* Test Time */
+  e->time_base = log(e->time_end / e->cosmology->a_begin) / max_nr_timesteps;
+  e->ti_current = 0;
+  e->policy = engine_policy_cosmology;
+
+  /* initialize output_list */
+  output_list_init(&list, e, name, &delta_time, &output_time);
+  output_list_print(list);
+
+  for (int i = 0; i < Ntest; i++) {
+    /* Test last value */
+    if (with_assert) {
+      assert(abs(output_time - a_values[i]) < tol);
+    }
+
+    /* Set current time */
+    e->ti_current = log(output_time / e->cosmology->a_begin) / e->time_base;
+    e->ti_current += 1;
+
+    /* Read next value */
+    integertime_t ti_next;
+    output_list_read_next_time(list, e, name, &ti_next);
+
+    output_time = (double)exp(ti_next * e->time_base) * e->cosmology->a_begin;
+  }
+
+  output_list_clean(list);
+};
+
+int main(int argc, char *argv[]) {
+  /* Create a structure to read file into. */
+  struct swift_params params;
+
+  /* Read the parameter file. */
+  parser_read_file(filename, &params);
+
+  /* initialization of unit system */
+  struct unit_system us;
+  units_init_from_params(&us, &params, "Units");
+
+  /* initialization of phys_const */
+  struct phys_const phys_const;
+  phys_const_init(&us, &params, &phys_const);
+
+  /* initialization of cosmo */
+  struct cosmology cosmo;
+  cosmology_init(&params, &us, &phys_const, &cosmo);
+
+  /* Pseudo initialization of engine */
+  struct engine e;
+  e.cosmology = &cosmo;
+  e.parameter_file = &params;
+  e.physical_constants = &phys_const;
+  e.internal_units = &us;
+
+  int with_assert = 1;
+  int without_assert = 0;
+  /* Test without cosmo */
+  test_no_cosmo(&e, "Time", with_assert);
+
+  /* Test with cosmo */
+  test_cosmo(&e, "Redshift", with_assert);
+  test_cosmo(&e, "ScaleFactor", with_assert);
+  test_cosmo(&e, "Time", without_assert);
+
+  /* Write message and leave */
+  message("Test done");
+  return 0;
+}
diff --git a/theory/Cosmology/coordinates.tex b/theory/Cosmology/coordinates.tex
index 22d0da29330f850df7fc3bdb979b49c70670d96c..38a571aefea68fbe1bc7a8ebc3867109f1c4736e 100644
--- a/theory/Cosmology/coordinates.tex
+++ b/theory/Cosmology/coordinates.tex
@@ -35,7 +35,7 @@ respectively. Following \cite{Peebles1980} (ch.7), we introduce the
 gauge transformation $\Lag \rightarrow \Lag + \frac{d}{dt}\Psi$ with
 $\Psi \equiv \frac{1}{2}a\dot{a}\mathbf{r}_i^2$ and obtain
 \begin{align}
-  \Lag &= \frac{1}{2}m_ia^2 \dot{\mathbf{r}}_i^2 -
+  \Lag &= \frac{1}{2}m_ia^2 \dot{\mathbf{r}}_i'^2 -
   \frac{1}{\gamma-1}m_iA_i'\left(\frac{\rho_i'}{a^3}\right)^{\gamma-1}
   -\frac{\phi'}{a},\\
   \phi' &= a\phi + \frac{1}{2}a^2\ddot{a}\mathbf{r}_i'^2,\nonumber