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/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/hydro/GizmoMFM/hydro.h b/src/hydro/GizmoMFM/hydro.h
index 1ab142740b641bdc9a0dff5a02b19479bae8257e..7c38896a4bfb0c44a79c509954e11128244e350e 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,20 +48,16 @@ __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?
@@ -72,7 +65,7 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep(
       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 +85,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 +115,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 +126,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 +152,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 +222,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 +241,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 +270,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 +280,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 +302,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 +361,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 +399,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 +455,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;
 }
 
 /**
@@ -559,10 +515,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 +527,45 @@ __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_therm;
+    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_therm) * m_inv;
+#endif
+    p->P = hydro_gamma_minus_one * u * p->rho;
 #endif
   }
 
+  /* we use a sneaky way to get the gravitational contribtuion to the
+     velocity update */
+  p->v[0] += p->v[0] - xp->v_full[0];
+  p->v[1] += p->v[1] - xp->v_full[1];
+  p->v[2] += p->v[2] - xp->v_full[2];
+
 #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,7 +587,9 @@ __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;
 }
 
 /**
@@ -648,17 +608,16 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
 
   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;
+  p->conserved.momentum[1] += p->flux.momentum[1] * dt;
+  p->conserved.momentum[2] += p->flux.momentum[2] * dt;
 #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;
 #endif
 
   /* Apply the minimal energy limit */
@@ -666,7 +625,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 +635,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 +652,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]);
   }
 
-  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 +696,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 +725,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 +754,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 +782,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 +794,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,17 +833,15 @@ __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?
@@ -910,7 +858,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 +870,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 +891,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 +911,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 +940,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 85617f05b6a5350e7b1b60de53f2c999b6ba7453..6f751d970287ca7ba137c1138ca6f3bf00e6c4cb 100644
--- a/src/hydro/GizmoMFM/hydro_gradients.h
+++ b/src/hydro/GizmoMFM/hydro_gradients.h
@@ -101,38 +101,28 @@ __attribute__((always_inline)) INLINE static void hydro_gradients_predict(
   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 fb54202a86b3e83aad7b2759c18dd3ce548cda13..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
@@ -407,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
@@ -443,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_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/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];