diff --git a/src/hydro/AnarchyDU/hydro_iact.h b/src/hydro/AnarchyDU/hydro_iact.h
index d1d3b1f6c0e4941539044d14bda1dd9f7a5ca615..27353e78bac4f848a5d7d1c53ff62648613f1b2d 100644
--- a/src/hydro/AnarchyDU/hydro_iact.h
+++ b/src/hydro/AnarchyDU/hydro_iact.h
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * This file is part* of SWIFT.
+ * This file is part of SWIFT.
  * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) &
  *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
  *
@@ -33,10 +33,10 @@
 #include "./hydro_parameters.h"
 
 /**
- * @brief Density interaction between two part*icles.
+ * @brief Density interaction between two particles.
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -109,10 +109,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_density(
 }
 
 /**
- * @brief Density interaction between two part*icles (non-symmetric).
+ * @brief Density interaction between two particles (non-symmetric).
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -292,10 +292,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_gradient(
 }
 
 /**
- * @brief Force interaction between two part*icles.
+ * @brief Force interaction between two particles.
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -418,10 +418,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_force(
 }
 
 /**
- * @brief Force interaction between two part*icles (non-symmetric).
+ * @brief Force interaction between two particles (non-symmetric).
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -538,8 +538,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force(
 /**
  * @brief Timestep limiter loop
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -558,8 +558,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_limiter(
 /**
  * @brief Timestep limiter loop (non-symmetric version)
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
diff --git a/src/hydro/AnarchyDU/hydro_io.h b/src/hydro/AnarchyDU/hydro_io.h
index fcec103b1e634a793268851935392e51a1611a97..db9995c3fe8a5089415dc9152a44a655ec97f0f3 100644
--- a/src/hydro/AnarchyDU/hydro_io.h
+++ b/src/hydro/AnarchyDU/hydro_io.h
@@ -10,7 +10,7 @@
  *
  * 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 DURPOSE.  See the
+ * 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
diff --git a/src/hydro/AnarchyPU/hydro_iact.h b/src/hydro/AnarchyPU/hydro_iact.h
index bf683fb447a3c6aa10ca750e5c967356f9dabbfd..106fbdbcd42b4b7f2f837d542496551445c4b752 100644
--- a/src/hydro/AnarchyPU/hydro_iact.h
+++ b/src/hydro/AnarchyPU/hydro_iact.h
@@ -35,10 +35,10 @@
 #include "./hydro_parameters.h"
 
 /**
- * @brief Density interaction between two part*icles.
+ * @brief Density interaction between two particles.
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -117,10 +117,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_density(
 }
 
 /**
- * @brief Density interaction between two part*icles (non-symmetric).
+ * @brief Density interaction between two particles (non-symmetric).
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -304,10 +304,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_gradient(
 }
 
 /**
- * @brief Force interaction between two part*icles.
+ * @brief Force interaction between two particles.
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -434,10 +434,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_force(
 }
 
 /**
- * @brief Force interaction between two part*icles (non-symmetric).
+ * @brief Force interaction between two particles (non-symmetric).
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -557,8 +557,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force(
 /**
  * @brief Timestep limiter loop
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -577,8 +577,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_limiter(
 /**
  * @brief Timestep limiter loop (non-symmetric version)
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
diff --git a/src/hydro/Default/hydro.h b/src/hydro/Default/hydro.h
index 4bcc0bcd4fa4ebaf8f43d738230c597f19873ce5..694441c8b02f1071119d41df9b70999efd75be1f 100644
--- a/src/hydro/Default/hydro.h
+++ b/src/hydro/Default/hydro.h
@@ -1,6 +1,7 @@
 /*******************************************************************************
  * This file is part of SWIFT.
- * Coypright (c) 2015 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) &
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published
@@ -19,6 +20,14 @@
 #ifndef SWIFT_DEFAULT_HYDRO_H
 #define SWIFT_DEFAULT_HYDRO_H
 
+/**
+ * @file Default/hydro.h
+ * @brief Density-Energy conservative implementation of SPH,
+ *        with added diffusive physics (Cullen & Denhen 2011 AV,
+ *        Price 2017 (PHANTOM) diffusion)  (Non-neighbour loop
+ *        equations)
+ */
+
 #include "adiabatic_index.h"
 #include "approx_math.h"
 #include "cosmology.h"
@@ -38,6 +47,10 @@
  * @brief Returns the comoving internal energy of a particle at the last
  * time the particle was kicked.
  *
+ * For implementations where the main thermodynamic variable
+ * is not internal energy, this function computes the internal
+ * energy from the thermodynamic variable.
+ *
  * @param p The particle of interest
  * @param xp The extended data of the particle of interest.
  */
@@ -52,6 +65,11 @@ hydro_get_comoving_internal_energy(const struct part *restrict p,
  * @brief Returns the physical internal energy of a particle at the last
  * time the particle was kicked.
  *
+ * For implementations where the main thermodynamic variable
+ * is not internal energy, this function computes the internal
+ * energy from the thermodynamic variable and converts it to
+ * physical coordinates.
+ *
  * @param p The particle of interest.
  * @param xp The extended data of the particle of interest.
  * @param cosmo The cosmological model.
@@ -93,6 +111,8 @@ hydro_get_drifted_physical_internal_energy(const struct part *restrict p,
 /**
  * @brief Returns the comoving pressure of a particle
  *
+ * Computes the pressure based on the particle's properties.
+ *
  * @param p The particle of interest
  */
 __attribute__((always_inline)) INLINE static float hydro_get_comoving_pressure(
@@ -104,21 +124,27 @@ __attribute__((always_inline)) INLINE static float hydro_get_comoving_pressure(
 /**
  * @brief Returns the physical pressure of a particle
  *
+ * Computes the pressure based on the particle's properties and
+ * convert it to physical coordinates.
+ *
  * @param p The particle of interest
  * @param cosmo The cosmological model.
  */
 __attribute__((always_inline)) INLINE static float hydro_get_physical_pressure(
     const struct part *restrict p, const struct cosmology *cosmo) {
 
-  return cosmo->a_factor_pressure *
-         gas_pressure_from_internal_energy(p->rho, p->u);
+  return cosmo->a_factor_pressure * hydro_get_comoving_pressure(p);
 }
 
 /**
  * @brief Returns the comoving entropy of a particle at the last
  * time the particle was kicked.
  *
- * @param p The particle of interest.
+ * For implementations where the main thermodynamic variable
+ * is not entropy, this function computes the entropy from
+ * the thermodynamic variable.
+ *
+ * @param p The particle of interest
  * @param xp The extended data of the particle of interest.
  */
 __attribute__((always_inline)) INLINE static float hydro_get_comoving_entropy(
@@ -131,6 +157,11 @@ __attribute__((always_inline)) INLINE static float hydro_get_comoving_entropy(
  * @brief Returns the physical entropy of a particle at the last
  * time the particle was kicked.
  *
+ * For implementations where the main thermodynamic variable
+ * is not entropy, this function computes the entropy from
+ * the thermodynamic variable and converts it to
+ * physical coordinates.
+ *
  * @param p The particle of interest.
  * @param xp The extended data of the particle of interest.
  * @param cosmo The cosmological model.
@@ -180,7 +211,7 @@ hydro_get_drifted_physical_entropy(const struct part *restrict p,
 __attribute__((always_inline)) INLINE static float
 hydro_get_comoving_soundspeed(const struct part *restrict p) {
 
-  return p->force.soundspeed;
+  return gas_soundspeed_from_internal_energy(p->rho, p->u);
 }
 
 /**
@@ -193,7 +224,7 @@ __attribute__((always_inline)) INLINE static float
 hydro_get_physical_soundspeed(const struct part *restrict p,
                               const struct cosmology *cosmo) {
 
-  return cosmo->a_factor_sound_speed * p->force.soundspeed;
+  return cosmo->a_factor_sound_speed * hydro_get_comoving_soundspeed(p);
 }
 
 /**
@@ -208,14 +239,15 @@ __attribute__((always_inline)) INLINE static float hydro_get_comoving_density(
 }
 
 /**
- * @brief Returns the physical density of a particle
+ * @brief Returns the comoving density of a particle.
  *
  * @param p The particle of interest
+ * @param cosmo The cosmological model.
  */
 __attribute__((always_inline)) INLINE static float hydro_get_physical_density(
     const struct part *restrict p, const struct cosmology *cosmo) {
 
-  return p->rho * cosmo->a3_inv;
+  return cosmo->a3_inv * p->rho;
 }
 
 /**
@@ -272,7 +304,7 @@ __attribute__((always_inline)) INLINE static void hydro_get_drifted_velocities(
 __attribute__((always_inline)) INLINE static float
 hydro_get_comoving_internal_energy_dt(const struct part *restrict p) {
 
-  return p->force.u_dt;
+  return p->u_dt;
 }
 
 /**
@@ -287,11 +319,11 @@ __attribute__((always_inline)) INLINE static float
 hydro_get_physical_internal_energy_dt(const struct part *restrict p,
                                       const struct cosmology *cosmo) {
 
-  return p->force.u_dt * cosmo->a_factor_internal_energy;
+  return p->u_dt * cosmo->a_factor_internal_energy;
 }
 
 /**
- * @brief Returns the time derivative of internal energy of a particle
+ * @brief Sets the time derivative of internal energy of a particle
  *
  * We assume a constant density.
  *
@@ -301,7 +333,7 @@ hydro_get_physical_internal_energy_dt(const struct part *restrict p,
 __attribute__((always_inline)) INLINE static void
 hydro_set_comoving_internal_energy_dt(struct part *restrict p, float du_dt) {
 
-  p->force.u_dt = du_dt;
+  p->u_dt = du_dt;
 }
 
 /**
@@ -318,7 +350,7 @@ hydro_set_physical_internal_energy_dt(struct part *restrict p,
                                       const struct cosmology *cosmo,
                                       float du_dt) {
 
-  p->force.u_dt = du_dt * cosmo->a_factor_internal_energy;
+  p->u_dt = du_dt / cosmo->a_factor_internal_energy;
 }
 
 /**
@@ -372,9 +404,11 @@ hydro_set_drifted_physical_internal_energy(struct part *p,
 
   /* Compute the sound speed */
   const float soundspeed = hydro_get_comoving_soundspeed(p);
+  const float pressure = hydro_get_comoving_pressure(p);
 
   /* Update variables. */
   p->force.soundspeed = soundspeed;
+  p->force.pressure = pressure;
 }
 
 /**
@@ -385,7 +419,7 @@ hydro_set_drifted_physical_internal_energy(struct part *p,
  */
 __attribute__((always_inline)) INLINE static void hydro_set_viscosity_alpha(
     struct part *restrict p, float alpha) {
-  p->alpha = alpha;
+  p->viscosity.alpha = alpha;
 }
 
 /**
@@ -403,9 +437,12 @@ hydro_set_viscosity_alpha_max_feedback(struct part *restrict p) {
 /**
  * @brief Computes the hydro time-step of a given particle
  *
+ * This function returns the time-step of a particle given its hydro-dynamical
+ * state. A typical time-step calculation would be the use of the CFL condition.
+ *
  * @param p Pointer to the particle data
  * @param xp Pointer to the extended particle data
- * @param hydro_properties The constants used in the scheme
+ * @param hydro_properties The SPH parameters
  * @param cosmo The cosmological model.
  */
 __attribute__((always_inline)) INLINE static float hydro_compute_timestep(
@@ -413,18 +450,13 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep(
     const struct hydro_props *restrict hydro_properties,
     const struct cosmology *restrict cosmo) {
 
-  const float CFL = hydro_properties->CFL_condition;
+  const float CFL_condition = hydro_properties->CFL_condition;
 
   /* CFL condition */
-  const float dt_cfl = 2.f * kernel_gamma * CFL * cosmo->a * p->h /
-                       (cosmo->a_factor_sound_speed * p->force.v_sig);
-
-  /* Limit change in u */
-  const float dt_u_change =
-      (p->force.u_dt != 0.0f) ? fabsf(const_max_u_change * p->u / p->force.u_dt)
-                              : FLT_MAX;
+  const float dt_cfl = 2.f * kernel_gamma * CFL_condition * cosmo->a * p->h /
+                       (cosmo->a_factor_sound_speed * p->viscosity.v_sig);
 
-  return min(dt_cfl, dt_u_change);
+  return dt_cfl;
 }
 
 /**
@@ -437,11 +469,22 @@ __attribute__((always_inline)) INLINE static float hydro_compute_timestep(
 __attribute__((always_inline)) INLINE static void hydro_timestep_extra(
     struct part *p, float dt) {}
 
+/**
+ * @brief Operations performed when a particle gets removed from the
+ * simulation volume.
+ *
+ * @param p The particle.
+ * @param xp The extended particle data.
+ */
+__attribute__((always_inline)) INLINE static void hydro_remove_part(
+    const struct part *p, const struct xpart *xp) {}
+
 /**
  * @brief Prepares a particle for the density calculation.
  *
  * Zeroes all the relevant arrays in preparation for the sums taking place in
- * the variaous density tasks
+ * the various density loop over neighbours. Typically, all fields of the
+ * density sub-structure of a particle get zeroed in here.
  *
  * @param p The particle to act upon
  * @param hs #hydro_space containing hydro specific space information.
@@ -452,11 +495,13 @@ __attribute__((always_inline)) INLINE static void hydro_init_part(
   p->density.wcount = 0.f;
   p->density.wcount_dh = 0.f;
   p->rho = 0.f;
-  p->rho_dh = 0.f;
-  p->density.div_v = 0.f;
+  p->density.rho_dh = 0.f;
+
   p->density.rot_v[0] = 0.f;
   p->density.rot_v[1] = 0.f;
   p->density.rot_v[2] = 0.f;
+
+  p->viscosity.div_v = 0.f;
 }
 
 /**
@@ -464,9 +509,13 @@ __attribute__((always_inline)) INLINE static void hydro_init_part(
  *
  * Multiplies the density and number of neighbours by the appropiate constants
  * and add the self-contribution term.
+ * Additional quantities such as velocity gradients will also get the final
+ * terms added to them here.
+ *
+ * Also adds/multiplies the cosmological terms if need be.
  *
  * @param p The particle to act upon
- * @param cosmo The current cosmological model.
+ * @param cosmo The cosmological model.
  */
 __attribute__((always_inline)) INLINE static void hydro_end_density(
     struct part *restrict p, const struct cosmology *cosmo) {
@@ -479,33 +528,115 @@ __attribute__((always_inline)) INLINE static void hydro_end_density(
 
   /* Final operation on the density (add self-contribution). */
   p->rho += p->mass * kernel_root;
-  p->rho_dh -= hydro_dimension * p->mass * kernel_root;
+  p->density.rho_dh -= hydro_dimension * p->mass * kernel_root;
   p->density.wcount += kernel_root;
+  p->density.wcount_dh -= hydro_dimension * kernel_root;
 
   /* Finish the calculation by inserting the missing h-factors */
   p->rho *= h_inv_dim;
-  p->rho_dh *= h_inv_dim_plus_one;
-  p->density.wcount *= kernel_norm;
-  p->density.wcount_dh *= h_inv * kernel_gamma * kernel_norm;
+  p->density.rho_dh *= h_inv_dim_plus_one;
+  p->density.wcount *= h_inv_dim;
+  p->density.wcount_dh *= h_inv_dim_plus_one;
 
-  const float irho = 1.f / p->rho;
+  const float rho_inv = 1.f / p->rho;
   const float a_inv2 = cosmo->a2_inv;
 
   /* Finish calculation of the velocity curl components */
-  p->density.rot_v[0] *= h_inv_dim_plus_one * a_inv2 * irho;
-  p->density.rot_v[1] *= h_inv_dim_plus_one * a_inv2 * irho;
-  p->density.rot_v[2] *= h_inv_dim_plus_one * a_inv2 * irho;
+  p->density.rot_v[0] *= h_inv_dim_plus_one * a_inv2 * rho_inv;
+  p->density.rot_v[1] *= h_inv_dim_plus_one * a_inv2 * rho_inv;
+  p->density.rot_v[2] *= h_inv_dim_plus_one * a_inv2 * rho_inv;
 
   /* Finish calculation of the velocity divergence */
-  p->density.div_v *= h_inv_dim_plus_one * a_inv2 * irho;
+  p->viscosity.div_v *= h_inv_dim_plus_one * rho_inv * a_inv2;
+  p->viscosity.div_v += cosmo->H * hydro_dimension;
 }
 
+/**
+ * @brief Prepare a particle for the gradient calculation.
+ *
+ * This function is called after the density loop and before the gradient loop.
+ *
+ * We use it to set the physical timestep for the particle and to copy the
+ * actual velocities, which we need to boost our interfaces during the flux
+ * calculation. We also initialize the variables used for the time step
+ * calculation.
+ *
+ * @param p The particle to act upon.
+ * @param xp The extended particle data to act upon.
+ * @param cosmo The cosmological model.
+ */
+__attribute__((always_inline)) INLINE static void hydro_prepare_gradient(
+    struct part *restrict p, struct xpart *restrict xp,
+    const struct cosmology *cosmo) {
+
+  const float fac_B = cosmo->a_factor_Balsara_eps;
+
+  /* Compute the norm of the curl */
+  const float curl_v = sqrtf(p->density.rot_v[0] * p->density.rot_v[0] +
+                             p->density.rot_v[1] * p->density.rot_v[1] +
+                             p->density.rot_v[2] * p->density.rot_v[2]);
+
+  /* Compute the norm of div v */
+  const float abs_div_v = fabsf(p->viscosity.div_v);
+
+  /* Compute the sound speed -- see theory section for justification */
+  const float soundspeed = hydro_get_comoving_soundspeed(p);
+  const float pressure = hydro_get_comoving_pressure(p);
+
+  /* Compute the Balsara switch */
+  const float balsara =
+      abs_div_v / (abs_div_v + curl_v + 0.0001f * soundspeed * fac_B / p->h);
+
+  /* Compute the "grad h" term */
+  const float rho_inv = 1.f / p->rho;
+  const float grad_h_term =
+      1.f / (1.f + hydro_dimension_inv * p->h * p->density.rho_dh * rho_inv);
+
+  /* Update variables. */
+  p->force.f = grad_h_term;
+  p->force.pressure = pressure;
+  p->force.soundspeed = soundspeed;
+  p->force.balsara = balsara;
+}
+
+/**
+ * @brief Resets the variables that are required for a gradient calculation.
+ *
+ * This function is called after hydro_prepare_gradient.
+ *
+ * @param p The particle to act upon.
+ * @param xp The extended particle data to act upon.
+ * @param cosmo The cosmological model.
+ */
+__attribute__((always_inline)) INLINE static void hydro_reset_gradient(
+    struct part *restrict p) {
+
+  p->viscosity.v_sig = 2.f * p->force.soundspeed;
+}
+
+/**
+ * @brief Finishes the gradient calculation.
+ *
+ * Just a wrapper around hydro_gradients_finalize, which can be an empty method,
+ * in which case no gradients are used.
+ *
+ * This method also initializes the force loop variables.
+ *
+ * @param p The particle to act upon.
+ */
+__attribute__((always_inline)) INLINE static void hydro_end_gradient(
+    struct part *p) {}
+
 /**
  * @brief Sets all particle fields to sensible values when the #part has 0 ngbs.
  *
+ * In the desperate case where a particle has no neighbours (likely because
+ * of the h_max ceiling), set the particle fields to something sensible to avoid
+ * NaNs in the next calculations.
+ *
  * @param p The particle to act upon
  * @param xp The extended particle data to act upon
- * @param cosmo The current cosmological model.
+ * @param cosmo The cosmological model.
  */
 __attribute__((always_inline)) INLINE static void hydro_part_has_no_neighbours(
     struct part *restrict p, struct xpart *restrict xp,
@@ -518,13 +649,17 @@ __attribute__((always_inline)) INLINE static void hydro_part_has_no_neighbours(
 
   /* Re-set problematic values */
   p->rho = p->mass * kernel_root * h_inv_dim;
+  p->viscosity.v_sig = 0.f;
   p->density.wcount = kernel_root * h_inv_dim;
-  p->rho_dh = 0.f;
+  p->density.rho_dh = 0.f;
   p->density.wcount_dh = 0.f;
-  p->density.div_v = 0.f;
+
   p->density.rot_v[0] = 0.f;
   p->density.rot_v[1] = 0.f;
   p->density.rot_v[2] = 0.f;
+
+  /* Probably not shocking, so this is safe to do */
+  p->viscosity.div_v = 0.f;
 }
 
 /**
@@ -548,62 +683,67 @@ __attribute__((always_inline)) INLINE static void hydro_prepare_force(
     struct part *restrict p, struct xpart *restrict xp,
     const struct cosmology *cosmo, const struct hydro_props *hydro_props,
     const float dt_alpha) {
-  const float fac_mu = cosmo->a_factor_mu;
-
-  /* Some smoothing length multiples. */
-  const float h = p->h;
-  const float h_inv = 1.0f / h;
 
-  /* Pre-compute some stuff for the balsara switch. */
-  const float normDiv_v = fabs(p->density.div_v);
-  const float normRot_v = sqrtf(p->density.rot_v[0] * p->density.rot_v[0] +
-                                p->density.rot_v[1] * p->density.rot_v[1] +
-                                p->density.rot_v[2] * p->density.rot_v[2]);
+  /* Here we need to update the artificial viscosity */
 
-  /* Compute this particle's sound speed. */
-  const float u = p->u;
-  const float fc = p->force.soundspeed =
-      sqrtf(hydro_gamma * hydro_gamma_minus_one * u);
+  /* We use in this function that h is the radius of support */
+  const float kernel_support_physical = p->h * cosmo->a * kernel_gamma;
+  const float kernel_support_physical_inv = 1.f / kernel_support_physical;
+  const float v_sig_physical = p->viscosity.v_sig * cosmo->a_factor_sound_speed;
+  const float soundspeed_physical = hydro_get_physical_soundspeed(p, cosmo);
 
-  /* Compute the derivative term */
-  p->rho_dh = 1.f / (1.f + hydro_dimension_inv * p->h * p->rho_dh / p->rho);
+  const float sound_crossing_time_inverse =
+      soundspeed_physical * kernel_support_physical_inv;
 
-  /* Compute the P/Omega/rho2. */
-  xp->omega = 1.0f + hydro_dimension_inv * h * p->rho_dh / p->rho;
-  p->force.P_over_rho2 = u * hydro_gamma_minus_one / (p->rho * xp->omega);
+  /* Construct time differential of div.v implicitly following the ANARCHY spec
+   */
 
-  /* Balsara switch */
-  p->force.balsara =
-      normDiv_v / (normDiv_v + normRot_v + 0.0001f * fac_mu * fc * h_inv);
+  const float div_v_dt =
+      dt_alpha == 0.f
+          ? 0.f
+          : (p->viscosity.div_v - p->viscosity.div_v_previous_step) / dt_alpha;
 
-  /* Set the AV property */
-  p->alpha = hydro_props->viscosity.alpha;
+  /* Construct the source term for the AV; if shock detected this is _positive_
+   * as div_v_dt should be _negative_ before the shock hits */
+  const float S = kernel_support_physical * kernel_support_physical *
+                  max(0.f, -1.f * div_v_dt);
+  /* 0.25 factor comes from our definition of v_sig (sum of soundspeeds rather
+   * than mean). */
+  /* Note this is v_sig_physical squared, not comoving */
+  const float v_sig_square = 0.25 * v_sig_physical * v_sig_physical;
 
-  /* Set the diffusion parameter */
-  p->alpha_diff = hydro_props->diffusion.alpha;
+  /* Calculate the current appropriate value of the AV based on the above */
+  const float alpha_loc =
+      hydro_props->viscosity.alpha_max * S / (v_sig_square + S);
 
-  /* Viscosity parameter decay time */
-  /* const float tau = h / (2.f * const_viscosity_length * p->force.soundspeed);
-   */
+  if (alpha_loc > p->viscosity.alpha) {
+    /* Reset the value of alpha to the appropriate value */
+    p->viscosity.alpha = alpha_loc;
+  } else {
+    /* Integrate the alpha forward in time to decay back to alpha = alpha_loc */
+    p->viscosity.alpha =
+        alpha_loc + (p->viscosity.alpha - alpha_loc) *
+                        expf(-dt_alpha * sound_crossing_time_inverse *
+                             hydro_props->viscosity.length);
+  }
 
-  /* Viscosity source term */
-  /* const float S = max(-normDiv_v, 0.f); */
+  /* Check that we did not hit the minimum */
+  p->viscosity.alpha =
+      max(p->viscosity.alpha, hydro_props->viscosity.alpha_min);
 
-  /* Compute the particle's viscosity parameter time derivative */
-  /* const float alpha_dot = (hydro_props->viscosity.alpha_max) - p->alpha) /
-   * tau + */
-  /*                         (hydro_props->viscosity.alpha_max - p->alpha) * S;
-   */
+  /* Set our old div_v to the one for the next loop */
+  p->viscosity.div_v_previous_step = p->viscosity.div_v;
 
-  /* Update particle's viscosity paramter */
-  /* p->alpha += alpha_dot * (p->ti_end - p->ti_begin) * timeBase; */  // MATTHIEU
+  /* Multiply the alpha value in here, as we want to limit on an individual
+   * basis! */
+  p->force.balsara *= p->viscosity.alpha;
 }
 
 /**
  * @brief Reset acceleration fields of a particle
  *
  * Resets all hydro acceleration and time derivative fields in preparation
- * for the sums taking place in the variaous force tasks
+ * for the sums taking  place in the various force tasks.
  *
  * @param p The particle to act upon
  */
@@ -616,9 +756,8 @@ __attribute__((always_inline)) INLINE static void hydro_reset_acceleration(
   p->a_hydro[2] = 0.0f;
 
   /* Reset the time derivatives. */
-  p->force.u_dt = 0.0f;
+  p->u_dt = 0.0f;
   p->force.h_dt = 0.0f;
-  p->force.v_sig = p->force.soundspeed;
 }
 
 /**
@@ -636,14 +775,28 @@ __attribute__((always_inline)) INLINE static void hydro_reset_predicted_values(
   p->v[1] = xp->v_full[1];
   p->v[2] = xp->v_full[2];
 
+  /* Re-set the entropy */
   p->u = xp->u_full;
+
+  /* Compute the sound speed */
+  const float pressure = gas_pressure_from_internal_energy(p->rho, p->u);
+  const float soundspeed = hydro_get_comoving_soundspeed(p);
+
+  p->force.pressure = pressure;
+  p->force.soundspeed = soundspeed;
 }
 
 /**
  * @brief Predict additional particle fields forward in time when drifting
  *
- * @param p The particle
- * @param xp The extended data of the particle
+ * Additional hydrodynamic quantites are drifted forward in time here. These
+ * include thermal quantities (thermal energy or total energy or entropy, ...).
+ *
+ * Note the different time-step sizes used for the different quantities as they
+ * include cosmological factors.
+ *
+ * @param p The particle.
+ * @param xp The extended data of the particle.
  * @param dt_drift The drift time-step for positions.
  * @param dt_therm The drift time-step for thermal quantities.
  * @param cosmo The cosmological model.
@@ -651,13 +804,13 @@ __attribute__((always_inline)) INLINE static void hydro_reset_predicted_values(
  * @param floor_props The properties of the entropy floor.
  */
 __attribute__((always_inline)) INLINE static void hydro_predict_extra(
-    struct part *restrict p, struct xpart *restrict xp, float dt_drift,
+    struct part *restrict p, const struct xpart *restrict xp, float dt_drift,
     float dt_therm, const struct cosmology *cosmo,
     const struct hydro_props *hydro_props,
     const struct entropy_floor_properties *floor_props) {
 
   /* Predict the internal energy */
-  p->u += p->force.u_dt * dt_therm;
+  p->u += p->u_dt * dt_therm;
 
   /* Check against entropy floor */
   const float floor_A = entropy_floor(p, cosmo, floor_props);
@@ -679,61 +832,143 @@ __attribute__((always_inline)) INLINE static void hydro_predict_extra(
   else
     p->h *= expf(w1);
 
-  /* Predict density */
+  /* Predict density and weighted pressure */
   const float w2 = -hydro_dimension * w1;
-  if (fabsf(w2) < 0.2f)
-    p->rho *= approx_expf(w2); /* 4th order expansion of exp(w) */
-  else
-    p->rho *= expf(w2);
+  if (fabsf(w2) < 0.2f) {
+    const float expf_approx =
+        approx_expf(w2); /* 4th order expansion of exp(w) */
+    p->rho *= expf_approx;
+  } else {
+    const float expf_exact = expf(w2);
+    p->rho *= expf_exact;
+  }
+
+  /* Compute the new sound speed */
+  const float pressure = gas_pressure_from_internal_energy(p->rho, p->u);
+  const float soundspeed = hydro_get_comoving_soundspeed(p);
 
-  /* Predict gradient term */
-  p->force.P_over_rho2 = p->u * hydro_gamma_minus_one / (p->rho * xp->omega);
+  p->force.pressure = pressure;
+  p->force.soundspeed = soundspeed;
 }
 
 /**
  * @brief Finishes the force calculation.
  *
- * Multiplies the forces and accelerationsby the appropiate constants
+ * Multiplies the force and accelerations by the appropiate constants
+ * and add the self-contribution term. In most cases, there is little
+ * to do here.
+ *
+ * Cosmological terms are also added/multiplied here.
  *
  * @param p The particle to act upon
  * @param cosmo The current cosmological model.
  */
 __attribute__((always_inline)) INLINE static void hydro_end_force(
     struct part *restrict p, const struct cosmology *cosmo) {
+
   p->force.h_dt *= p->h * hydro_dimension_inv;
 }
 
 /**
  * @brief Kick the additional variables
  *
- * @param p The particle to act upon
- * @param xp The particle extended data to act upon
- * @param dt_therm The time-step for this kick (for thermodynamic quantities)
+ * Additional hydrodynamic quantites are kicked forward in time here. These
+ * include thermal quantities (thermal energy or total energy or entropy, ...).
+ *
+ * @param p The particle to act upon.
+ * @param xp The particle extended data to act upon.
+ * @param dt_therm The time-step for this kick (for thermodynamic quantities).
+ * @param dt_grav The time-step for this kick (for gravity quantities).
+ * @param dt_hydro The time-step for this kick (for hydro quantities).
+ * @param dt_kick_corr The time-step for this kick (for gravity corrections).
+ * @param cosmo The cosmological model.
+ * @param hydro_props The constants used in the scheme
+ * @param floor_props The properties of the entropy floor.
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
     struct part *restrict p, struct xpart *restrict xp, float dt_therm,
     float dt_grav, float dt_hydro, float dt_kick_corr,
     const struct cosmology *cosmo, const struct hydro_props *hydro_props,
-    const struct entropy_floor_properties *floor_props) {}
+    const struct entropy_floor_properties *floor_props) {
+
+  /* Integrate the internal energy forward in time */
+  const float delta_u = p->u_dt * dt_therm;
+
+  /* Do not decrease the energy by more than a factor of 2*/
+  xp->u_full = max(xp->u_full + delta_u, 0.5f * xp->u_full);
+
+  /* Check against entropy floor */
+  const float floor_A = entropy_floor(p, cosmo, floor_props);
+  const float floor_u = gas_internal_energy_from_entropy(p->rho, floor_A);
+
+  /* Check against absolute minimum */
+  const float min_u =
+      hydro_props->minimal_internal_energy / cosmo->a_factor_internal_energy;
+
+  /* Take highest of both limits */
+  const float energy_min = max(min_u, floor_u);
+
+  if (xp->u_full < energy_min) {
+    xp->u_full = energy_min;
+    p->u_dt = 0.f;
+  }
+}
 
 /**
- *  @brief Converts hydro quantity of a particle at the start of a run
+ * @brief Converts hydro quantity of a particle at the start of a run
  *
- * Requires the density to be known
+ * This function is called once at the end of the engine_init_particle()
+ * routine (at the start of a calculation) after the densities of
+ * particles have been computed.
+ * This can be used to convert internal energy into entropy for instance.
  *
  * @param p The particle to act upon
- * @param xp The extended data.
+ * @param xp The extended particle to act upon
  * @param cosmo The cosmological model.
+ * @param hydro_props The constants used in the scheme.
  */
 __attribute__((always_inline)) INLINE static void hydro_convert_quantities(
     struct part *restrict p, struct xpart *restrict xp,
-    const struct cosmology *cosmo, const struct hydro_props *hydro_props) {}
+    const struct cosmology *cosmo, const struct hydro_props *hydro_props) {
+
+  /* Convert the physcial internal energy to the comoving one. */
+  /* u' = a^(3(g-1)) u */
+  const float factor = 1.f / cosmo->a_factor_internal_energy;
+  p->u *= factor;
+  xp->u_full = p->u;
+
+  /* Apply the minimal energy limit */
+  const float min_comoving_energy =
+      hydro_props->minimal_internal_energy / cosmo->a_factor_internal_energy;
+  if (xp->u_full < min_comoving_energy) {
+    xp->u_full = min_comoving_energy;
+    p->u = min_comoving_energy;
+    p->u_dt = 0.f;
+  }
+
+  /* Set the initial value of the artificial viscosity based on the non-variable
+     schemes for safety */
+
+  p->viscosity.alpha = hydro_props->viscosity.alpha;
+  /* Initialise this here to keep all the AV variables together */
+  p->viscosity.div_v_previous_step = 0.f;
+
+  /* Set the initial values for the thermal diffusion */
+  p->diffusion.alpha = hydro_props->diffusion.alpha;
+
+  const float pressure = gas_pressure_from_internal_energy(p->rho, p->u);
+  const float soundspeed = gas_soundspeed_from_internal_energy(p->rho, p->u);
+
+  p->force.pressure = pressure;
+  p->force.soundspeed = soundspeed;
+}
 
 /**
  * @brief Initialises the particles for the first time
  *
  * This function is called only once just after the ICs have been
- * read in to do some conversions.
+ * read in to do some conversions or assignments between the particle
+ * and extended particle fields.
  *
  * @param p The particle to act upon
  * @param xp The extended particle data to act upon
@@ -772,14 +1007,4 @@ hydro_set_init_internal_energy(struct part *p, float u_init) {
   p->u = u_init;
 }
 
-/**
- * @brief Operations performed when a particle gets removed from the
- * simulation volume.
- *
- * @param p The particle.
- * @param xp The extended particle data.
- */
-__attribute__((always_inline)) INLINE static void hydro_remove_part(
-    const struct part *p, const struct xpart *xp) {}
-
 #endif /* SWIFT_DEFAULT_HYDRO_H */
diff --git a/src/hydro/Default/hydro_debug.h b/src/hydro/Default/hydro_debug.h
index 68367beaee97c285057cb055c1fbdbba5c370085..e9083870151feb984dc9c95d8f4cd33d1a80235f 100644
--- a/src/hydro/Default/hydro_debug.h
+++ b/src/hydro/Default/hydro_debug.h
@@ -1,6 +1,7 @@
 /*******************************************************************************
  * This file is part of SWIFT.
- * Coypright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) &
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published
@@ -16,20 +17,31 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  ******************************************************************************/
+
 #ifndef SWIFT_DEFAULT_HYDRO_DEBUG_H
 #define SWIFT_DEFAULT_HYDRO_DEBUG_H
 
+/**
+ * @file Default/hydro_debug.h
+ * @brief Density-Energy conservative implementation of SPH,
+ *        with added diffusive physics (Cullen & Denhen 2011 AV,
+ *        Price 2017 (PHANTOM) diffusion) (Debugging routines)
+ */
+
 __attribute__((always_inline)) INLINE static void hydro_debug_particle(
     const struct part* p, const struct xpart* xp) {
   printf(
       "x=[%.3e,%.3e,%.3e], "
-      "v=[%.3e,%.3e,%.3e],v_full=[%.3e,%.3e,%.3e] \n a=[%.3e,%.3e,%.3e],\n "
-      "h=%.3e, "
-      "wcount=%d, m=%.3e, dh_drho=%.3e, rho=%.3e, time_bin=%d wakeup=%d\n",
+      "v=[%.3e,%.3e,%.3e],v_full=[%.3e,%.3e,%.3e] \n a=[%.3e,%.3e,%.3e], "
+      "u=%.3e, du/dt=%.3e v_sig=%.3e, P=%.3e\n"
+      "h=%.3e, dh/dt=%.3e wcount=%d, m=%.3e, dh_drho=%.3e, rho=%.3e, \n"
+      "alpha=%.3e \n"
+      "time_bin=%d\n",
       p->x[0], p->x[1], p->x[2], p->v[0], p->v[1], p->v[2], xp->v_full[0],
       xp->v_full[1], xp->v_full[2], p->a_hydro[0], p->a_hydro[1], p->a_hydro[2],
-      p->h, (int)p->density.wcount, p->mass, p->rho_dh, p->rho, p->time_bin,
-      p->wakeup);
+      p->u, p->u_dt, p->viscosity.v_sig, hydro_get_comoving_pressure(p), p->h,
+      p->force.h_dt, (int)p->density.wcount, p->mass, p->density.rho_dh, p->rho,
+      p->viscosity.alpha, p->time_bin);
 }
 
 #endif /* SWIFT_DEFAULT_HYDRO_DEBUG_H */
diff --git a/src/hydro/Default/hydro_iact.h b/src/hydro/Default/hydro_iact.h
index 8ce77b9e353bf38b31dbd7b7a5444c10f3f6b5bc..07c8f0edc3885376be828480492de10b35d857e3 100644
--- a/src/hydro/Default/hydro_iact.h
+++ b/src/hydro/Default/hydro_iact.h
@@ -1,6 +1,6 @@
 /*******************************************************************************
  * This file is part of SWIFT.
- * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) &
  *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
  *
  * This program is free software: you can redistribute it and/or modify
@@ -20,25 +20,18 @@
 #ifndef SWIFT_DEFAULT_HYDRO_IACT_H
 #define SWIFT_DEFAULT_HYDRO_IACT_H
 
+/**
+ * @file Default/hydro_iact.h
+ * @brief Density-Energy conservative implementation of SPH,
+ *        with added diffusive physics (Cullen & Denhen 2011 AV,
+ *        Price 2017 (PHANTOM) diffusion) (interaction routines)
+ */
+
 #include "adiabatic_index.h"
+#include "minmax.h"
 
 #include "./hydro_parameters.h"
 
-/**
- * @brief SPH interaction functions following the Gadget-2 version of SPH.
- *
- * The interactions computed here are the ones presented in the Gadget-2 paper
- * and use the same
- * numerical coefficients as the Gadget-2 code. When used with the Spline-3
- * kernel, the results
- * should be equivalent to the ones obtained with Gadget-2 up to the rounding
- * errors and interactions
- * missed by the Gadget-2 tree-code neighbours search.
- *
- * The code uses internal energy instead of entropy as a thermodynamical
- * variable.
- */
-
 /**
  * @brief Density interaction between two particles.
  *
@@ -46,66 +39,73 @@
  * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of particle i.
  * @param hj Comoving smoothing-length of particle j.
- * @param pi First particle.
- * @param pj Second particle.
+ * @param pi First part*icle.
+ * @param pj Second part*icle.
  * @param a Current scale factor.
  * @param H Current Hubble parameter.
  */
 __attribute__((always_inline)) INLINE static void runner_iact_density(
-    float r2, const float *dx, float hi, float hj, struct part *restrict pi,
-    struct part *restrict pj, float a, float H) {
+    float r2, const float* dx, float hi, float hj, struct part* pi,
+    struct part* pj, float a, float H) {
 
-  float r = sqrtf(r2), ri = 1.0f / r;
-  float xi, xj;
-  float h_inv;
   float wi, wj, wi_dx, wj_dx;
-  float mi, mj;
-  float dvdr;
   float dv[3], curlvr[3];
-  int k;
+
+  const float r = sqrtf(r2);
 
   /* Get the masses. */
-  mi = pi->mass;
-  mj = pj->mass;
+  const float mi = pi->mass;
+  const float mj = pj->mass;
+
+  /* Compute density of pi. */
+  const float hi_inv = 1.f / hi;
+  const float ui = r * hi_inv;
+
+  kernel_deval(ui, &wi, &wi_dx);
+
+  pi->rho += mj * wi;
+  pi->density.rho_dh -= mj * (hydro_dimension * wi + ui * wi_dx);
+
+  pi->density.wcount += wi;
+  pi->density.wcount_dh -= (hydro_dimension * wi + ui * wi_dx);
+
+  /* Compute density of pj. */
+  const float hj_inv = 1.f / hj;
+  const float uj = r * hj_inv;
+  kernel_deval(uj, &wj, &wj_dx);
+
+  pj->rho += mi * wj;
+  pj->density.rho_dh -= mi * (hydro_dimension * wj + uj * wj_dx);
+  pj->density.wcount += wj;
+  pj->density.wcount_dh -= (hydro_dimension * wj + uj * wj_dx);
+
+  /* Now we need to compute the div terms */
+  const float r_inv = 1.f / r;
+  const float faci = mj * wi_dx * r_inv;
+  const float facj = mi * wj_dx * r_inv;
 
   /* Compute dv dot r */
   dv[0] = pi->v[0] - pj->v[0];
   dv[1] = pi->v[1] - pj->v[1];
   dv[2] = pi->v[2] - pj->v[2];
-  dvdr = dv[0] * dx[0] + dv[1] * dx[1] + dv[2] * dx[2];
-  dvdr *= ri;
+  const float dvdr = dv[0] * dx[0] + dv[1] * dx[1] + dv[2] * dx[2];
+
+  pi->viscosity.div_v -= faci * dvdr;
+  pj->viscosity.div_v -= facj * dvdr;
 
   /* Compute dv cross r */
   curlvr[0] = dv[1] * dx[2] - dv[2] * dx[1];
   curlvr[1] = dv[2] * dx[0] - dv[0] * dx[2];
   curlvr[2] = dv[0] * dx[1] - dv[1] * dx[0];
-  for (k = 0; k < 3; k++) curlvr[k] *= ri;
-
-  /* Compute density of pi. */
-  h_inv = 1.0f / hi;
-  xi = r * h_inv;
-  kernel_deval(xi, &wi, &wi_dx);
 
-  pi->rho += mj * wi;
-  pi->rho_dh -= mj * (hydro_dimension * wi + xi * wi_dx);
-  pi->density.wcount += wi;
-  pi->density.wcount_dh -= xi * wi_dx;
-
-  pi->density.div_v -= mj * dvdr * wi_dx;
-  for (k = 0; k < 3; k++) pi->density.rot_v[k] += mj * curlvr[k] * wi_dx;
-
-  /* Compute density of pj. */
-  h_inv = 1.0f / hj;
-  xj = r * h_inv;
-  kernel_deval(xj, &wj, &wj_dx);
-
-  pj->rho += mi * wj;
-  pj->rho_dh -= mi * (hydro_dimension * wj + xj * wj_dx);
-  pj->density.wcount += wj;
-  pj->density.wcount_dh -= xj * wj_dx;
+  pi->density.rot_v[0] += faci * curlvr[0];
+  pi->density.rot_v[1] += faci * curlvr[1];
+  pi->density.rot_v[2] += faci * curlvr[2];
 
-  pj->density.div_v -= mi * dvdr * wj_dx;
-  for (k = 0; k < 3; k++) pj->density.rot_v[k] += mi * curlvr[k] * wj_dx;
+  /* Negative because of the change in sign of dx & dv. */
+  pj->density.rot_v[0] += facj * curlvr[0];
+  pj->density.rot_v[1] += facj * curlvr[1];
+  pj->density.rot_v[2] += facj * curlvr[2];
 }
 
 /**
@@ -113,57 +113,157 @@ __attribute__((always_inline)) INLINE static void runner_iact_density(
  *
  * @param r2 Comoving square distance between the two particles.
  * @param dx Comoving vector separating both particles (pi - pj).
- * @param hi Comoving smoothing-length of particle i.
- * @param hj Comoving smoothing-length of particle j.
- * @param pi First particle.
- * @param pj Second particle (not updated).
+ * @param hi Comoving smoothing-length of part*icle i.
+ * @param hj Comoving smoothing-length of part*icle j.
+ * @param pi First part*icle.
+ * @param pj Second part*icle (not updated).
  * @param a Current scale factor.
  * @param H Current Hubble parameter.
  */
 __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density(
-    float r2, const float *dx, float hi, float hj, struct part *restrict pi,
-    const struct part *restrict pj, float a, float H) {
+    float r2, const float* dx, float hi, float hj, struct part* pi,
+    const struct part* pj, float a, float H) {
 
-  float r, ri;
-  float xi;
-  float h_inv;
   float wi, wi_dx;
-  float mj;
-  float dvdr;
   float dv[3], curlvr[3];
-  int k;
 
   /* Get the masses. */
-  mj = pj->mass;
+  const float mj = pj->mass;
 
   /* Get r and r inverse. */
-  r = sqrtf(r2);
-  ri = 1.0f / r;
+  const float r = sqrtf(r2);
+
+  const float h_inv = 1.f / hi;
+  const float ui = r * h_inv;
+  kernel_deval(ui, &wi, &wi_dx);
+
+  pi->rho += mj * wi;
+  pi->density.rho_dh -= mj * (hydro_dimension * wi + ui * wi_dx);
+
+  pi->density.wcount += wi;
+  pi->density.wcount_dh -= (hydro_dimension * wi + ui * wi_dx);
+
+  const float r_inv = 1.f / r;
+  const float faci = mj * wi_dx * r_inv;
 
   /* Compute dv dot r */
   dv[0] = pi->v[0] - pj->v[0];
   dv[1] = pi->v[1] - pj->v[1];
   dv[2] = pi->v[2] - pj->v[2];
-  dvdr = dv[0] * dx[0] + dv[1] * dx[1] + dv[2] * dx[2];
-  dvdr *= ri;
+  const float dvdr = dv[0] * dx[0] + dv[1] * dx[1] + dv[2] * dx[2];
+
+  pi->viscosity.div_v -= faci * dvdr;
 
   /* Compute dv cross r */
   curlvr[0] = dv[1] * dx[2] - dv[2] * dx[1];
   curlvr[1] = dv[2] * dx[0] - dv[0] * dx[2];
   curlvr[2] = dv[0] * dx[1] - dv[1] * dx[0];
-  for (k = 0; k < 3; k++) curlvr[k] *= ri;
 
-  h_inv = 1.0f / hi;
-  xi = r * h_inv;
-  kernel_deval(xi, &wi, &wi_dx);
+  pi->density.rot_v[0] += faci * curlvr[0];
+  pi->density.rot_v[1] += faci * curlvr[1];
+  pi->density.rot_v[2] += faci * curlvr[2];
+}
 
-  pi->rho += mj * wi;
-  pi->rho_dh -= mj * (hydro_dimension * wi + xi * wi_dx);
-  pi->density.wcount += wi;
-  pi->density.wcount_dh -= xi * wi_dx;
+/**
+ * @brief Calculate the gradient interaction between particle i and particle j
+ *
+ * This method wraps around hydro_gradients_collect, which can be an empty
+ * method, in which case no gradients are used.
+ *
+ * @param r2 Comoving squared distance between particle i and particle j.
+ * @param dx Comoving distance vector between the particles (dx = pi->x -
+ * pj->x).
+ * @param hi Comoving smoothing-length of particle i.
+ * @param hj Comoving smoothing-length of particle j.
+ * @param pi Particle i.
+ * @param pj Particle j.
+ * @param a Current scale factor.
+ * @param H Current Hubble parameter.
+ */
+__attribute__((always_inline)) INLINE static void runner_iact_gradient(
+    float r2, const float* dx, float hi, float hj, struct part* restrict pi,
+    struct part* restrict pj, float a, float H) {
 
-  pi->density.div_v -= mj * dvdr * wi_dx;
-  for (k = 0; k < 3; k++) pi->density.rot_v[k] += mj * curlvr[k] * wi_dx;
+  /* We need to construct the maximal signal velocity between our particle
+   * and all of it's neighbours */
+
+  const float r = sqrtf(r2);
+  const float r_inv = 1.f / r;
+  const float ci = pi->force.soundspeed;
+  const float cj = pj->force.soundspeed;
+
+  /* Cosmology terms for the signal velocity */
+  const float fac_mu = pow_three_gamma_minus_five_over_two(a);
+  const float a2_Hubble = a * a * H;
+
+  const 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];
+
+  /* Add Hubble flow */
+
+  const float dvdr_Hubble = dvdr + a2_Hubble * r2;
+  /* Are the particles moving towards each others ? */
+  const float omega_ij = min(dvdr_Hubble, 0.f);
+  const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
+
+  /* Signal velocity */
+  const float new_v_sig = ci + cj - const_viscosity_beta * mu_ij;
+
+  /* Update if we need to */
+  pi->viscosity.v_sig = max(pi->viscosity.v_sig, new_v_sig);
+  pj->viscosity.v_sig = max(pj->viscosity.v_sig, new_v_sig);
+}
+
+/**
+ * @brief Calculate the gradient interaction between particle i and particle j:
+ * non-symmetric version
+ *
+ * This method wraps around hydro_gradients_nonsym_collect, which can be an
+ * empty method, in which case no gradients are used.
+ *
+ * @param r2 Comoving squared distance between particle i and particle j.
+ * @param dx Comoving distance vector between the particles (dx = pi->x -
+ * pj->x).
+ * @param hi Comoving smoothing-length of particle i.
+ * @param hj Comoving smoothing-length of particle j.
+ * @param pi Particle i.
+ * @param pj Particle j.
+ * @param a Current scale factor.
+ * @param H Current Hubble parameter.
+ */
+__attribute__((always_inline)) INLINE static void runner_iact_nonsym_gradient(
+    float r2, const float* dx, float hi, float hj, struct part* restrict pi,
+    struct part* restrict pj, float a, float H) {
+
+  /* We need to construct the maximal signal velocity between our particle
+   * and all of it's neighbours */
+
+  const float r = sqrtf(r2);
+  const float r_inv = 1.f / r;
+  const float ci = pi->force.soundspeed;
+  const float cj = pj->force.soundspeed;
+
+  /* Cosmology terms for the signal velocity */
+  const float fac_mu = pow_three_gamma_minus_five_over_two(a);
+  const float a2_Hubble = a * a * H;
+
+  const 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];
+
+  /* Add Hubble flow */
+
+  const float dvdr_Hubble = dvdr + a2_Hubble * r2;
+  /* Are the particles moving towards each others ? */
+  const float omega_ij = min(dvdr_Hubble, 0.f);
+  const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
+
+  /* Signal velocity */
+  const float new_v_sig = ci + cj - const_viscosity_beta * mu_ij;
+
+  /* Update if we need to */
+  pi->viscosity.v_sig = max(pi->viscosity.v_sig, new_v_sig);
 }
 
 /**
@@ -171,109 +271,129 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density(
  *
  * @param r2 Comoving square distance between the two particles.
  * @param dx Comoving vector separating both particles (pi - pj).
- * @param hi Comoving smoothing-length of particle i.
- * @param hj Comoving smoothing-length of particle j.
- * @param pi First particle.
- * @param pj Second particle.
+ * @param hi Comoving smoothing-length of part*icle i.
+ * @param hj Comoving smoothing-length of part*icle j.
+ * @param pi First part*icle.
+ * @param pj Second part*icle.
  * @param a Current scale factor.
  * @param H Current Hubble parameter.
  */
 __attribute__((always_inline)) INLINE static void runner_iact_force(
-    float r2, const float *dx, float hi, float hj, struct part *restrict pi,
-    struct part *restrict pj, float a, float H) {
-
-  float r = sqrtf(r2), ri = 1.0f / r;
-  float xi, xj;
-  float hi_inv, hid_inv;
-  float hj_inv, hjd_inv;
-  float wi, wj, wi_dx, wj_dx, wi_dr, wj_dr, w, dvdr;
-  float mi, mj, POrho2i, POrho2j, rhoi, rhoj;
-  float v_sig, omega_ij, Pi_ij, alpha_ij, tc, v_sig_u;
-  float f;
-  int k;
+    float r2, const float* dx, float hi, float hj, struct part* pi,
+    struct part* pj, float a, float H) {
 
   /* Cosmological factors entering the EoMs */
   const float fac_mu = pow_three_gamma_minus_five_over_two(a);
   const float a2_Hubble = a * a * H;
 
-  /* Get some values in local variables. */
-  mi = pi->mass;
-  mj = pj->mass;
-  rhoi = pi->rho;
-  rhoj = pj->rho;
-  POrho2i = pi->force.P_over_rho2;
-  POrho2j = pj->force.P_over_rho2;
+  const float r = sqrtf(r2);
+  const float r_inv = 1.0f / r;
+
+  /* Recover some data */
+  const float mj = pj->mass;
+  const float mi = pi->mass;
+
+  const float rhoi = pi->rho;
+  const float rhoj = pj->rho;
+
+  const float pressurei = pi->force.pressure;
+  const float pressurej = pj->force.pressure;
 
   /* Get the kernel for hi. */
-  hi_inv = 1.0f / hi;
-  hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */
-  xi = r * hi_inv;
+  const float hi_inv = 1.0f / hi;
+  const float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */
+  const float xi = r * hi_inv;
+  float wi, wi_dx;
   kernel_deval(xi, &wi, &wi_dx);
-  wi_dr = hid_inv * wi_dx;
+  const float wi_dr = hid_inv * wi_dx;
 
   /* Get the kernel for hj. */
-  hj_inv = 1.0f / hj;
-  hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */
-  xj = r * hj_inv;
+  const float hj_inv = 1.0f / hj;
+  const float hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */
+  const float xj = r * hj_inv;
+  float wj, wj_dx;
   kernel_deval(xj, &wj, &wj_dx);
-  wj_dr = hjd_inv * wj_dx;
+  const float wj_dr = hjd_inv * wj_dx;
 
   /* Compute dv dot r. */
-  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] + a2_Hubble * r2;
-  dvdr *= ri;
-
-  /* Compute the relative velocity. (This is 0 if the particles move away from
-   * each other and negative otherwise) */
-  omega_ij = min(fac_mu * dvdr, 0.f);
-
-  /* Compute signal velocity */
-  v_sig = pi->force.soundspeed + pj->force.soundspeed -
-          const_viscosity_beta * omega_ij;
-
-  /* Compute viscosity parameter */
-  alpha_ij = -0.5f * (pi->alpha + pj->alpha);
-
-  /* Compute viscosity tensor */
-  Pi_ij = alpha_ij * v_sig * omega_ij / (rhoi + rhoj);
-
-  /* Apply balsara switch */
-  Pi_ij *= (pi->force.balsara + pj->force.balsara);
-
-  /* Thermal conductivity */
-  v_sig_u = sqrtf(2.f * hydro_gamma_minus_one *
-                  fabs(rhoi * pi->u - rhoj * pj->u) / (rhoi + rhoj));
-  tc = pi->alpha_diff * v_sig_u / (rhoi + rhoj);
-  tc *= (wi_dr + wj_dr);
-
-  /* Get the common factor out. */
-  w = ri *
-      ((POrho2i * wi_dr + POrho2j * wj_dr) + 0.25f * Pi_ij * (wi_dr + wj_dr));
-
-  /* Use the force, Luke! */
-  for (k = 0; k < 3; k++) {
-    f = dx[k] * w;
-    pi->a_hydro[k] -= mj * f;
-    pj->a_hydro[k] += mi * f;
-  }
+  const 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];
+
+  /* Includes the hubble flow term; not used for du/dt */
+  const float dvdr_Hubble = dvdr + a2_Hubble * r2;
+
+  /* Are the particles moving towards each others ? */
+  const float omega_ij = min(dvdr_Hubble, 0.f);
+  const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
+
+  /* Compute sound speeds and signal velocity */
+  const float v_sig = pi->force.soundspeed + pj->force.soundspeed -
+                      const_viscosity_beta * mu_ij;
+
+  /* Balsara term */
+  const float balsara_i = pi->force.balsara;
+  const float balsara_j = pj->force.balsara;
+
+  /* Construct the full viscosity term */
+  /* Balsara includes the alphas */
+  const float visc = -0.125f * v_sig * mu_ij * (balsara_i + balsara_j);
+
+  /* Convolve with the kernel */
+  const float visc_acc_term =
+      0.5f * visc * (wi_dr * pi->force.f / rhoi + wj_dr * pj->force.f / rhoj) *
+      r_inv;
+
+  /* Compute gradient terms */
+  const float P_over_rho2_i = pressurei / (rhoi * rhoi) * pi->force.f;
+  const float P_over_rho2_j = pressurej / (rhoj * rhoj) * pj->force.f;
+
+  /* SPH acceleration term */
+  const float sph_acc_term =
+      (P_over_rho2_i * wi_dr + P_over_rho2_j * wj_dr) * r_inv;
+
+  /* Assemble the acceleration */
+  const float acc = sph_acc_term + visc_acc_term;
+
+  /* Use the force Luke ! */
+  pi->a_hydro[0] -= mj * acc * dx[0];
+  pi->a_hydro[1] -= mj * acc * dx[1];
+  pi->a_hydro[2] -= mj * acc * dx[2];
+
+  pj->a_hydro[0] += mi * acc * dx[0];
+  pj->a_hydro[1] += mi * acc * dx[1];
+  pj->a_hydro[2] += mi * acc * dx[2];
 
   /* Get the time derivative for u. */
-  pi->force.u_dt +=
-      mj * dvdr * (POrho2i * wi_dr + 0.125f * Pi_ij * (wi_dr + wj_dr));
-  pj->force.u_dt +=
-      mi * dvdr * (POrho2j * wj_dr + 0.125f * Pi_ij * (wi_dr + wj_dr));
+  const float sph_du_term_i = P_over_rho2_i * dvdr * r_inv * wi_dr;
+  const float sph_du_term_j = P_over_rho2_j * dvdr * r_inv * wj_dr;
 
-  /* Add the thermal conductivity */
-  pi->force.u_dt += mj * tc * (pi->u - pj->u);
-  pj->force.u_dt += mi * tc * (pj->u - pi->u);
+  /* Viscosity term */
+  const float visc_du_term = 0.5f * visc_acc_term * dvdr_Hubble;
 
-  /* Get the time derivative for h. */
-  pi->force.h_dt -= mj * dvdr / rhoj * wi_dr;
-  pj->force.h_dt -= mi * dvdr / rhoi * wj_dr;
+  /* Diffusion term */
+
+  const float v_diff =
+      sqrtf(2.0 * fabsf(pressurei - pressurej) / (rhoi + rhoj)) +
+      dvdr_Hubble * r_inv;
+
+  const float alpha_diff = 0.5f * (pi->diffusion.alpha + pj->diffusion.alpha);
+  /* wi_dx + wj_dx / 2 is F_ij */
+  const float diff_du_term =
+      alpha_diff * v_diff * (pi->u - pj->u) * 0.5f *
+      (wi_dr * pi->force.f / pi->rho + wj_dr * pi->force.f / pi->rho);
+
+  /* Assemble the energy equation term */
+  const float du_dt_i = sph_du_term_i + visc_du_term + diff_du_term;
+  const float du_dt_j = sph_du_term_j + visc_du_term - diff_du_term;
 
-  /* Update the signal velocity. */
-  pi->force.v_sig = max(pi->force.v_sig, v_sig);
-  pj->force.v_sig = max(pj->force.v_sig, v_sig);
+  /* Internal energy time derivative */
+  pi->u_dt += du_dt_i * mj;
+  pj->u_dt += du_dt_j * mi;
+
+  /* Get the time derivative for h. */
+  pi->force.h_dt -= mj * dvdr * pi->force.f * r_inv / rhoj * wi_dr;
+  pj->force.h_dt -= mi * dvdr * pj->force.f * r_inv / rhoi * wj_dr;
 }
 
 /**
@@ -281,124 +401,162 @@ __attribute__((always_inline)) INLINE static void runner_iact_force(
  *
  * @param r2 Comoving square distance between the two particles.
  * @param dx Comoving vector separating both particles (pi - pj).
- * @param hi Comoving smoothing-length of particle i.
- * @param hj Comoving smoothing-length of particle j.
- * @param pi First particle.
- * @param pj Second particle (not updated).
+ * @param hi Comoving smoothing-length of part*icle i.
+ * @param hj Comoving smoothing-length of part*icle j.
+ * @param pi First part*icle.
+ * @param pj Second part*icle (not updated).
  * @param a Current scale factor.
  * @param H Current Hubble parameter.
  */
 __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force(
-    float r2, const float *dx, float hi, float hj, struct part *restrict pi,
-    const struct part *restrict pj, float a, float H) {
-
-  float r = sqrtf(r2), ri = 1.0f / r;
-  float xi, xj;
-  float hi_inv, hid_inv;
-  float hj_inv, hjd_inv;
-  float wi, wj, wi_dx, wj_dx, wi_dr, wj_dr, w, dvdr;
-  float /*mi,*/ mj, POrho2i, POrho2j, rhoi, rhoj;
-  float v_sig, omega_ij, Pi_ij, alpha_ij, tc, v_sig_u;
-  float f;
-  int k;
+    float r2, const float* dx, float hi, float hj, struct part* pi,
+    const struct part* pj, float a, float H) {
 
   /* Cosmological factors entering the EoMs */
   const float fac_mu = pow_three_gamma_minus_five_over_two(a);
   const float a2_Hubble = a * a * H;
 
-  /* Get some values in local variables. */
-  // mi = pi->mass;
-  mj = pj->mass;
-  rhoi = pi->rho;
-  rhoj = pj->rho;
-  POrho2i = pi->force.P_over_rho2;
-  POrho2j = pj->force.P_over_rho2;
+  const float r = sqrtf(r2);
+  const float r_inv = 1.0f / r;
+
+  /* Recover some data */
+  // const float mi = pi->mass;
+  const float mj = pj->mass;
+
+  const float rhoi = pi->rho;
+  const float rhoj = pj->rho;
+
+  const float pressurei = pi->force.pressure;
+  const float pressurej = pj->force.pressure;
 
   /* Get the kernel for hi. */
-  hi_inv = 1.0f / hi;
-  hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */
-  xi = r * hi_inv;
+  const float hi_inv = 1.0f / hi;
+  const float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */
+  const float xi = r * hi_inv;
+  float wi, wi_dx;
   kernel_deval(xi, &wi, &wi_dx);
-  wi_dr = hid_inv * wi_dx;
+  const float wi_dr = hid_inv * wi_dx;
 
   /* Get the kernel for hj. */
-  hj_inv = 1.0f / hj;
-  hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */
-  xj = r * hj_inv;
+  const float hj_inv = 1.0f / hj;
+  const float hjd_inv = pow_dimension_plus_one(hj_inv); /* 1/h^(d+1) */
+  const float xj = r * hj_inv;
+  float wj, wj_dx;
   kernel_deval(xj, &wj, &wj_dx);
-  wj_dr = hjd_inv * wj_dx;
+  const float wj_dr = hjd_inv * wj_dx;
 
   /* Compute dv dot r. */
-  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] + a2_Hubble * r2;
-  dvdr *= ri;
+  const 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];
 
-  /* Compute the relative velocity. (This is 0 if the particles move away from
-   * each other and negative otherwise) */
-  omega_ij = min(fac_mu * dvdr, 0.f);
+  /* Includes the hubble flow term; not used for du/dt */
+  const float dvdr_Hubble = dvdr + a2_Hubble * r2;
 
-  /* Compute signal velocity */
-  v_sig = pi->force.soundspeed + pj->force.soundspeed -
-          const_viscosity_beta * omega_ij;
+  /* Are the particles moving towards each others ? */
+  const float omega_ij = min(dvdr_Hubble, 0.f);
+  const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
 
-  /* Compute viscosity parameter */
-  alpha_ij = -0.5f * (pi->alpha + pj->alpha);
+  /* Compute sound speeds and signal velocity */
+  const float v_sig = pi->force.soundspeed + pj->force.soundspeed -
+                      const_viscosity_beta * mu_ij;
 
-  /* Compute viscosity tensor */
-  Pi_ij = alpha_ij * v_sig * omega_ij / (rhoi + rhoj);
+  /* Balsara term */
+  const float balsara_i = pi->force.balsara;
+  const float balsara_j = pj->force.balsara;
 
-  /* Apply balsara switch */
-  Pi_ij *= (pi->force.balsara + pj->force.balsara);
+  /* Construct the full viscosity term */
+  /* Balsara includes the alphas */
+  const float visc = -0.125f * v_sig * mu_ij * (balsara_i + balsara_j);
 
-  /* Thermal conductivity */
-  v_sig_u = sqrtf(2.f * hydro_gamma_minus_one *
-                  fabs(rhoi * pi->u - rhoj * pj->u) / (rhoi + rhoj));
-  tc = pi->alpha_diff * v_sig_u / (rhoi + rhoj);
-  tc *= (wi_dr + wj_dr);
+  /* Convolve with the kernel */
+  const float visc_acc_term =
+      0.5f * visc * (wi_dr * pi->force.f / rhoi + wj_dr * pj->force.f / rhoj) *
+      r_inv;
 
-  /* Get the common factor out. */
-  w = ri *
-      ((POrho2i * wi_dr + POrho2j * wj_dr) + 0.25f * Pi_ij * (wi_dr + wj_dr));
+  /* Compute gradient terms */
+  const float P_over_rho2_i = pressurei / (rhoi * rhoi) * pi->force.f;
+  const float P_over_rho2_j = pressurej / (rhoj * rhoj) * pj->force.f;
 
-  /* Use the force, Luke! */
-  for (k = 0; k < 3; k++) {
-    f = dx[k] * w;
-    pi->a_hydro[k] -= mj * f;
-  }
+  /* SPH acceleration term */
+  const float sph_acc_term =
+      (P_over_rho2_i * wi_dr + P_over_rho2_j * wj_dr) * r_inv;
+
+  /* Assemble the acceleration */
+  const float acc = sph_acc_term + visc_acc_term;
+
+  /* Use the force Luke ! */
+  pi->a_hydro[0] -= mj * acc * dx[0];
+  pi->a_hydro[1] -= mj * acc * dx[1];
+  pi->a_hydro[2] -= mj * acc * dx[2];
 
   /* Get the time derivative for u. */
-  pi->force.u_dt +=
-      mj * dvdr * (POrho2i * wi_dr + 0.125f * Pi_ij * (wi_dr + wj_dr));
+  const float sph_du_term_i = P_over_rho2_i * dvdr * r_inv * wi_dr;
 
-  /* Add the thermal conductivity */
-  pi->force.u_dt += mj * tc * (pi->u - pj->u);
+  /* Viscosity term */
+  const float visc_du_term = 0.5f * visc_acc_term * dvdr_Hubble;
 
-  /* Get the time derivative for h. */
-  pi->force.h_dt -= mj * dvdr / rhoj * wi_dr;
+  /* Diffusion term */
+  const float v_diff =
+      sqrtf(2.0 * fabsf(pressurei - pressurej) / (rhoi + rhoj)) +
+      dvdr_Hubble * r_inv;
 
-  /* Update the signal velocity. */
-  pi->force.v_sig = max(pi->force.v_sig, v_sig);
+  const float alpha_diff = 0.5f * (pi->diffusion.alpha + pj->diffusion.alpha);
+  /* wi_dx + wj_dx / 2 is F_ij */
+  const float diff_du_term =
+      alpha_diff * v_diff * (pi->u - pj->u) * 0.5f *
+      (wi_dr * pi->force.f / pi->rho + wj_dr * pi->force.f / pi->rho);
+
+  /* Assemble the energy equation term */
+  const float du_dt_i = sph_du_term_i + visc_du_term + diff_du_term;
+
+  /* Internal energy time derivative */
+  pi->u_dt += du_dt_i * mj;
+
+  /* Get the time derivative for h. */
+  pi->force.h_dt -= mj * dvdr * pi->force.f * r_inv / rhoj * wi_dr;
 }
 
 /**
  * @brief Timestep limiter loop
+ *
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
+ * @param hi Comoving smoothing-length of part*icle i.
+ * @param hj Comoving smoothing-length of part*icle j.
+ * @param pi First part*icle.
+ * @param pj Second part*icle (not updated).
+ * @param a Current scale factor.
+ * @param H Current Hubble parameter.
+ *
  */
 __attribute__((always_inline)) INLINE static void runner_iact_limiter(
-    float r2, const float *dx, float hi, float hj, struct part *restrict pi,
-    struct part *restrict pj, float a, float H) {
+    float r2, const float* dx, float hi, float hj, struct part* restrict pi,
+    struct part* restrict pj, float a, float H) {
 
   /* Nothing to do here if both particles are active */
 }
 
 /**
  * @brief Timestep limiter loop (non-symmetric version)
+ *
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
+ * @param hi Comoving smoothing-length of part*icle i.
+ * @param hj Comoving smoothing-length of part*icle j.
+ * @param pi First part*icle.
+ * @param pj Second part*icle (not updated).
+ * @param a Current scale factor.
+ * @param H Current Hubble parameter.
+ *
  */
 __attribute__((always_inline)) INLINE static void runner_iact_nonsym_limiter(
-    float r2, const float *dx, float hi, float hj, struct part *restrict pi,
-    struct part *restrict pj, float a, float H) {
+    float r2, const float* dx, float hi, float hj, struct part* restrict pi,
+    struct part* restrict pj, float a, float H) {
 
   /* Wake up the neighbour? */
-  if (pi->force.v_sig > const_limiter_max_v_sig_ratio * pj->force.v_sig) {
+  if (pi->viscosity.v_sig >
+      const_limiter_max_v_sig_ratio * pj->viscosity.v_sig) {
 
     pj->wakeup = time_bin_awake;
   }
diff --git a/src/hydro/Default/hydro_io.h b/src/hydro/Default/hydro_io.h
index 858e7e02d8b2ab2a9458f74bb949a5a14faca2cf..7b668fac1700738fb83199900dbb171ac913084f 100644
--- a/src/hydro/Default/hydro_io.h
+++ b/src/hydro/Default/hydro_io.h
@@ -1,6 +1,7 @@
 /*******************************************************************************
  * This file is part of SWIFT.
- * Coypright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) &
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published
@@ -19,6 +20,13 @@
 #ifndef SWIFT_DEFAULT_HYDRO_IO_H
 #define SWIFT_DEFAULT_HYDRO_IO_H
 
+/**
+ * @file Default/hydro_io.h
+ * @brief Density-Energy conservative implementation of SPH,
+ *        with added diffusive physics (Cullen & Denhen 2011 AV,
+ *        Price 2017 (PHANTOM) diffusion) (i/o routines)
+ */
+
 #include "adiabatic_index.h"
 #include "hydro.h"
 #include "io_properties.h"
@@ -57,6 +65,7 @@ INLINE static void hydro_read_particles(struct part* parts,
   list[7] = io_make_input_field("Density", FLOAT, 1, OPTIONAL,
                                 UNIT_CONV_DENSITY, parts, rho);
 }
+
 INLINE static void convert_S(const struct engine* e, const struct part* p,
                              const struct xpart* xp, float* ret) {
 
@@ -122,13 +131,24 @@ INLINE static void convert_part_vel(const struct engine* e,
 INLINE static void convert_part_potential(const struct engine* e,
                                           const struct part* p,
                                           const struct xpart* xp, float* ret) {
-
   if (p->gpart != NULL)
     ret[0] = gravity_get_comoving_potential(p->gpart);
   else
     ret[0] = 0.f;
 }
 
+INLINE static void convert_viscosity(const struct engine* e,
+                                     const struct part* p,
+                                     const struct xpart* xp, float* ret) {
+  ret[0] = p->viscosity.alpha;
+}
+
+INLINE static void convert_diffusion(const struct engine* e,
+                                     const struct part* p,
+                                     const struct xpart* xp, float* ret) {
+  ret[0] = p->diffusion.alpha;
+}
+
 /**
  * @brief Specifies which particle fields to write to a dataset
  *
@@ -141,7 +161,7 @@ INLINE static void hydro_write_particles(const struct part* parts,
                                          struct io_props* list,
                                          int* num_fields) {
 
-  *num_fields = 10;
+  *num_fields = 12;
 
   /* List what we want to write */
   list[0] = io_make_output_field_convert_part("Coordinates", DOUBLE, 3,
@@ -159,15 +179,20 @@ INLINE static void hydro_write_particles(const struct part* parts,
                                  UNIT_CONV_NO_UNITS, parts, id);
   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,
+  list[7] = io_make_output_field_convert_part(
+      "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, xparts, convert_P);
+  list[8] = io_make_output_field_convert_part("Entropy", FLOAT, 1,
                                               UNIT_CONV_ENTROPY_PER_UNIT_MASS,
                                               parts, xparts, convert_S);
-  list[8] = io_make_output_field_convert_part(
-      "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, xparts, convert_P);
-
-  list[0] = io_make_output_field_convert_part("Potential", FLOAT, 1,
+  list[9] = io_make_output_field_convert_part("Potential", FLOAT, 1,
                                               UNIT_CONV_POTENTIAL, parts,
                                               xparts, convert_part_potential);
+  list[10] = io_make_output_field_convert_part("Viscosity", FLOAT, 1,
+                                               UNIT_CONV_NO_UNITS, parts,
+                                               xparts, convert_viscosity);
+  list[11] = io_make_output_field_convert_part("Diffusion", FLOAT, 1,
+                                               UNIT_CONV_NO_UNITS, parts,
+                                               xparts, convert_diffusion);
 }
 
 /**
@@ -177,13 +202,11 @@ INLINE static void hydro_write_particles(const struct part* parts,
 INLINE static void hydro_write_flavour(hid_t h_grpsph) {
 
   /* Viscosity and thermal conduction */
+  /* Nothing in this minimal model... */
   io_write_attribute_s(h_grpsph, "Thermal Conductivity Model",
-                       "Price (2008) without switch");
-
-  io_write_attribute_s(
-      h_grpsph, "Viscosity Model",
-      "Morris & Monaghan (1997), Rosswog, Davies, Thielemann & "
-      "Piran (2000) with additional Balsara (1995) switch");
+                       "Simple treatment as in Price (2017)");
+  io_write_attribute_s(h_grpsph, "Viscosity Model",
+                       "Simplified version of Cullen & Denhen (2011)");
 
   /* Time integration properties */
   io_write_attribute_f(h_grpsph, "Maximal Delta u change over dt",
diff --git a/src/hydro/Default/hydro_parameters.h b/src/hydro/Default/hydro_parameters.h
index 92010d29442be1cec88eec3caec901f7e38042de..1e492f4a8121dbabb73111e9139df6e8b7cbe6cb 100644
--- a/src/hydro/Default/hydro_parameters.h
+++ b/src/hydro/Default/hydro_parameters.h
@@ -36,36 +36,50 @@
 
 /**
  * @file Default/hydro_parameters.h
- * @brief Default implementation of SPH (default parameters)
+ * @brief Density-Energy conservative implementation of SPH,
+ *        with added diffusive physics (Cullen & Denhen 2011 AV,
+ *        Price 2017 (PHANTOM) diffusion) (default compile-time
+ *        parameters).
  *
  *        This file defines a number of things that are used in
  *        hydro_properties.c as defaults for run-time parameters
  *        as well as a number of compile-time parameters.
  */
 
-/* Viscosity parameters -- FIXED -- MUST BE DEFINED AT COMPILE-TIME */
+/*! Viscosity parameters -- FIXED -- MUST BE DEFINED AT COMPILE-TIME */
 
-/* Cosmology default beta=3.0.
+/*! Cosmology default beta=3.0.
  * Alpha can be set in the parameter file.
  * Beta is defined as in e.g. Price (2010) Eqn (103) */
 #define const_viscosity_beta 3.0f
 
-/* The viscosity that the particles are reset to after being hit by a
+/*! The viscosity that the particles are reset to after being hit by a
  * feedback event. This should be set to the same value as the
  * hydro_props_default_viscosity_alpha in fixed schemes, and likely
  * to hydro_props_default_viscosity_alpha_max in variable schemes. */
-#define hydro_props_default_viscosity_alpha_feedback_reset 0.8f
+#define hydro_props_default_viscosity_alpha_feedback_reset 2.0f
 
 /* Viscosity paramaters -- Defaults; can be changed at run-time */
 
-/* The "initial" hydro viscosity, or the fixed value for non-variable
+/*! The "initial" hydro viscosity, or the fixed value for non-variable
  * schemes. This usually takes the value 0.8. */
-#define hydro_props_default_viscosity_alpha 0.8f
+#define hydro_props_default_viscosity_alpha 0.1f
+
+/*! Minimal value for the viscosity alpha in variable schemes. */
+#define hydro_props_default_viscosity_alpha_min 0.0f
+
+/*! Maximal value for the viscosity alpha in variable schemes. */
+#define hydro_props_default_viscosity_alpha_max 2.0f
+
+/*! Decay length for the viscosity scheme. This is scheme dependent. In
+ * non-variable schemes this must be defined but is not used. This also
+ * sets the decay length for the diffusion. */
+#define hydro_props_default_viscosity_length 0.25f
 
 /* Diffusion parameters -- Defaults; can be changed at run-time */
 
-/* The "initial" diffusion, or the fixed value for non-variable
- * schemes. This usually takes the value 0.0. */
+/*! The "initial" diffusion, or the fixed value for non-variable
+ * schemes. For this fixed scheme, this just takes the value of unity. */
 #define hydro_props_default_diffusion_alpha 1.0f
 
 /* Structs that store the relevant variables */
@@ -75,6 +89,15 @@ struct viscosity_global_data {
   /*! For the fixed, simple case. Also used to set the initial AV
       coefficient for variable schemes. */
   float alpha;
+
+  /*! Artificial viscosity (max) for the variable case (e.g. M&M) */
+  float alpha_max;
+
+  /*! Artificial viscosity (min) for the variable case (e.g. M&M) */
+  float alpha_min;
+
+  /*! The decay length of the artificial viscosity (used in M&M, etc.) */
+  float length;
 };
 
 /*! Thermal diffusion parameters */
@@ -113,6 +136,17 @@ static INLINE void viscosity_init(struct swift_params* params,
 
   viscosity->alpha = parser_get_opt_param_float(
       params, "SPH:viscosity_alpha", hydro_props_default_viscosity_alpha);
+
+  viscosity->alpha_max =
+      parser_get_opt_param_float(params, "SPH:viscosity_alpha_max",
+                                 hydro_props_default_viscosity_alpha_max);
+
+  viscosity->alpha_min =
+      parser_get_opt_param_float(params, "SPH:viscosity_alpha_min",
+                                 hydro_props_default_viscosity_alpha_min);
+
+  viscosity->length = parser_get_opt_param_float(
+      params, "SPH:viscosity_length", hydro_props_default_viscosity_length);
 }
 
 /**
@@ -124,6 +158,9 @@ static INLINE void viscosity_init(struct swift_params* params,
 static INLINE void viscosity_init_no_hydro(
     struct viscosity_global_data* viscosity) {
   viscosity->alpha = hydro_props_default_viscosity_alpha;
+  viscosity->alpha_max = hydro_props_default_viscosity_alpha_max;
+  viscosity->alpha_min = hydro_props_default_viscosity_alpha_min;
+  viscosity->length = hydro_props_default_viscosity_length;
 }
 
 /**
@@ -134,8 +171,11 @@ static INLINE void viscosity_init_no_hydro(
  **/
 static INLINE void viscosity_print(
     const struct viscosity_global_data* viscosity) {
-  message("Artificial viscosity parameters set to alpha: %.3f",
-          viscosity->alpha);
+  message(
+      "Artificial viscosity parameters set to alpha: %.3f, max: %.3f, "
+      "min: %.3f, length: %.3f.",
+      viscosity->alpha, viscosity->alpha_max, viscosity->alpha_min,
+      viscosity->length);
 }
 
 #if defined(HAVE_HDF5)
@@ -149,6 +189,10 @@ static INLINE void viscosity_print_snapshot(
     hid_t h_grpsph, const struct viscosity_global_data* viscosity) {
 
   io_write_attribute_f(h_grpsph, "Alpha viscosity", viscosity->alpha);
+  io_write_attribute_f(h_grpsph, "Alpha viscosity (max)", viscosity->alpha_max);
+  io_write_attribute_f(h_grpsph, "Alpha viscosity (min)", viscosity->alpha_min);
+  io_write_attribute_f(h_grpsph, "Viscosity decay length [internal units]",
+                       viscosity->length);
   io_write_attribute_f(h_grpsph, "Beta viscosity", const_viscosity_beta);
 }
 #endif
@@ -192,7 +236,7 @@ static INLINE void diffusion_init_no_hydro(
  **/
 static INLINE void diffusion_print(
     const struct diffusion_global_data* diffusion) {
-  message("Artificial diffusion parameters set to alpha: %.3f",
+  message("Artificial diffusion parameters set to alpha: %.3f (fixed).",
           diffusion->alpha);
 }
 
diff --git a/src/hydro/Default/hydro_part.h b/src/hydro/Default/hydro_part.h
index c262a2db71048858231b9886977b2b8a8f98cf00..e5c8aab4e88dc4f2a6ffe38ea8931e8f7849e5de 100644
--- a/src/hydro/Default/hydro_part.h
+++ b/src/hydro/Default/hydro_part.h
@@ -1,6 +1,7 @@
 /*******************************************************************************
  * This file is part of SWIFT.
- * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
+ * Coypright (c) 2019 Josh Borrow (joshua.borrow@durham.ac.uk) &
+ *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published
@@ -19,131 +20,180 @@
 #ifndef SWIFT_DEFAULT_HYDRO_PART_H
 #define SWIFT_DEFAULT_HYDRO_PART_H
 
+/**
+ * @file Default/hydro_part.h
+ * @brief Density-Energy conservative implementation of SPH,
+ *        with added diffusive physics (Cullen & Denhen 2011 AV,
+ *        Price 2017 (PHANTOM) diffusion) (particle definition)
+ */
+
 #include "chemistry_struct.h"
 #include "cooling_struct.h"
 #include "star_formation_struct.h"
 #include "tracers_struct.h"
 
-/* Extra particle data not needed during the SPH loops over neighbours. */
+/**
+ * @brief Particle fields not needed during the SPH loops over neighbours.
+ *
+ * This structure contains the particle fields that are not used in the
+ * density or force loops. Quantities should be used in the kick, drift and
+ * potentially ghost tasks only.
+ */
 struct xpart {
 
-  /* Offset between current position and position at last tree rebuild. */
+  /*! Offset between current position and position at last tree rebuild. */
   float x_diff[3];
 
   /*! Offset between the current position and position at the last sort. */
   float x_diff_sort[3];
 
-  /* Velocity at the last full step. */
+  /*! Velocity at the last full step. */
   float v_full[3];
 
-  /* Gravitational acceleration at the last full step. */
+  /*! Gravitational acceleration at the last full step. */
   float a_grav[3];
 
-  /* Additional data used to record cooling information */
+  /*! Internal energy at the last full step. */
+  float u_full;
+
+  /*! Additional data used to record cooling information */
   struct cooling_xpart_data cooling_data;
 
   /* Additional data used by the tracers */
   struct tracers_xpart_data tracers_data;
 
-  /* Additional data used by the star formation */
+  /* Additional data used by the tracers */
   struct star_formation_xpart_data sf_data;
 
-  float u_full;
-
-  /* Old density. */
-  float omega;
-
 } SWIFT_STRUCT_ALIGN;
 
-/* Data of a single particle. */
+/**
+ * @brief Particle fields for the SPH particles
+ *
+ * The density and force substructures are used to contain variables only used
+ * within the density and force loops over neighbours. All more permanent
+ * variables should be declared in the main part of the part structure,
+ */
 struct part {
 
-  /* Particle ID. */
+  /*! Particle unique ID. */
   long long id;
 
-  /* Pointer to corresponding gravity part. */
+  /*! Pointer to corresponding gravity part. */
   struct gpart* gpart;
 
-  /* Particle position. */
+  /*! Particle position. */
   double x[3];
 
-  /* Particle predicted velocity. */
+  /*! Particle predicted velocity. */
   float v[3];
 
-  /* Particle acceleration. */
+  /*! Particle acceleration. */
   float a_hydro[3];
 
-  /* Particle cutoff radius. */
+  /*! Particle mass. */
+  float mass;
+
+  /*! Particle smoothing length. */
   float h;
 
-  /* Particle internal energy. */
+  /*! Particle internal energy. */
   float u;
 
-  /* Particle density. */
+  /*! Time derivative of the internal energy. */
+  float u_dt;
+
+  /*! Particle density. */
   float rho;
 
-  /* Derivative of the density with respect to this particle's smoothing length.
-   */
-  float rho_dh;
+  /* Store viscosity information in a separate struct. */
+  struct {
+
+    /*! Particle velocity divergence */
+    float div_v;
+
+    /*! Particle velocity divergence from previous step */
+    float div_v_previous_step;
+
+    /*! Artificial viscosity parameter */
+    float alpha;
 
-  /* Particle viscosity parameter */
-  float alpha;
+    /*! Signal velocity */
+    float v_sig;
 
-  /* Particle diffusion parameter */
-  float alpha_diff;
+  } viscosity;
+
+  /* Store thermal diffusion information in a separate struct. */
+  struct {
+
+    /*! del^2 u, a smoothed quantity */
+    float laplace_u;
+
+    /*! Thermal diffusion coefficient */
+    float alpha;
+
+  } diffusion;
 
   /* Store density/force specific stuff. */
   union {
 
+    /**
+     * @brief Structure for the variables only used in the density loop over
+     * neighbours.
+     *
+     * Quantities in this sub-structure should only be accessed in the density
+     * loop over neighbours and the ghost task.
+     */
     struct {
 
-      /* Particle velocity divergence. */
-      float div_v;
+      /*! Neighbour number count. */
+      float wcount;
 
-      /* Derivative of particle number density. */
+      /*! Derivative of the neighbour number with respect to h. */
       float wcount_dh;
 
-      /* Particle velocity curl. */
-      float rot_v[3];
+      /*! Derivative of density with respect to h */
+      float rho_dh;
 
-      /* Particle number density. */
-      float wcount;
+      /*! Particle velocity curl. */
+      float rot_v[3];
 
     } density;
 
+    /**
+     * @brief Structure for the variables only used in the force loop over
+     * neighbours.
+     *
+     * Quantities in this sub-structure should only be accessed in the force
+     * loop over neighbours and the ghost, drift and kick tasks.
+     */
     struct {
 
-      /* Balsara switch */
-      float balsara;
-
-      /* Aggregate quantities. */
-      float P_over_rho2;
+      /*! "Grad h" term -- only partial in P-U */
+      float f;
 
-      /* Change in particle energy over time. */
-      float u_dt;
+      /*! Particle pressure. */
+      float pressure;
 
-      /* Signal velocity */
-      float v_sig;
-
-      /* Sound speed */
+      /*! Particle soundspeed. */
       float soundspeed;
 
-      /* Change in smoothing length over time. */
+      /*! Time derivative of smoothing length  */
       float h_dt;
 
+      /*! Balsara switch */
+      float balsara;
+
     } force;
   };
 
-  /* Particle mass. */
-  float mass;
-
   /* Chemistry information */
   struct chemistry_part_data chemistry_data;
 
-  /* Particle time-bin */
+  /*! Time-step length */
   timebin_t time_bin;
 
-  /* Need waking-up ? */
+  /* Need waking up ? */
   timebin_t wakeup;
 
 #ifdef SWIFT_DEBUG_CHECKS
diff --git a/src/hydro/PressureEnergy/hydro_iact.h b/src/hydro/PressureEnergy/hydro_iact.h
index e2fc6e7e92423397278f95bd30fb1b3d5d6c93a4..b59fdbbe418d0442fd290b3596fd08531fae88e6 100644
--- a/src/hydro/PressureEnergy/hydro_iact.h
+++ b/src/hydro/PressureEnergy/hydro_iact.h
@@ -38,10 +38,10 @@
 #include "./hydro_parameters.h"
 
 /**
- * @brief Density interaction between two part*icles.
+ * @brief Density interaction between two particles.
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -120,10 +120,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_density(
 }
 
 /**
- * @brief Density interaction between two part*icles (non-symmetric).
+ * @brief Density interaction between two particles (non-symmetric).
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -180,10 +180,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density(
 }
 
 /**
- * @brief Force interaction between two part*icles.
+ * @brief Force interaction between two particles.
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -239,7 +239,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_force(
   /* Includes the hubble flow term; not used for du/dt */
   const float dvdr_Hubble = dvdr + a2_Hubble * r2;
 
-  /* Are the part*icles moving towards each others ? */
+  /* Are the particles moving towards each others ? */
   const float omega_ij = min(dvdr_Hubble, 0.f);
   const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
 
@@ -306,10 +306,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_force(
 }
 
 /**
- * @brief Force interaction between two part*icles (non-symmetric).
+ * @brief Force interaction between two particles (non-symmetric).
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -366,7 +366,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force(
   /* Includes the hubble flow term; not used for du/dt */
   const float dvdr_Hubble = dvdr + a2_Hubble * r2;
 
-  /* Are the part*icles moving towards each others ? */
+  /* Are the particles moving towards each others ? */
   const float omega_ij = min(dvdr_Hubble, 0.f);
   const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
 
diff --git a/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_iact.h b/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_iact.h
index d7521d3387afc97666e88780aa7894e3a1459b4a..3e0fec0459e7ac17b90d49007c7b38a18f4d8dbc 100644
--- a/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_iact.h
+++ b/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_iact.h
@@ -39,10 +39,10 @@
 #include "./hydro_parameters.h"
 
 /**
- * @brief Density interaction between two part*icles.
+ * @brief Density interaction between two particles.
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -121,10 +121,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_density(
 }
 
 /**
- * @brief Density interaction between two part*icles (non-symmetric).
+ * @brief Density interaction between two particles (non-symmetric).
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -181,10 +181,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_density(
 }
 
 /**
- * @brief Force interaction between two part*icles.
+ * @brief Force interaction between two particles.
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -240,7 +240,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_force(
   /* Includes the hubble flow term; not used for du/dt */
   const float dvdr_Hubble = dvdr + a2_Hubble * r2;
 
-  /* Are the part*icles moving towards each others ? */
+  /* Are the particles moving towards each others ? */
   const float omega_ij = min(dvdr_Hubble, 0.f);
   const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
 
@@ -309,10 +309,10 @@ __attribute__((always_inline)) INLINE static void runner_iact_force(
 }
 
 /**
- * @brief Force interaction between two part*icles (non-symmetric).
+ * @brief Force interaction between two particles (non-symmetric).
  *
- * @param r2 Comoving square distance between the two part*icles.
- * @param dx Comoving vector separating both part*icles (pi - pj).
+ * @param r2 Comoving square distance between the two particles.
+ * @param dx Comoving vector separating both particles (pi - pj).
  * @param hi Comoving smoothing-length of part*icle i.
  * @param hj Comoving smoothing-length of part*icle j.
  * @param pi First part*icle.
@@ -369,7 +369,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_force(
   /* Includes the hubble flow term; not used for du/dt */
   const float dvdr_Hubble = dvdr + a2_Hubble * r2;
 
-  /* Are the part*icles moving towards each others ? */
+  /* Are the particles moving towards each others ? */
   const float omega_ij = min(dvdr_Hubble, 0.f);
   const float mu_ij = fac_mu * r_inv * omega_ij; /* This is 0 or negative */
 
diff --git a/src/part.h b/src/part.h
index 253cec7b4edad08234a751ee20e6c05fcff7e6ec..820834d652cf53b3dce06192d7c552ec7681f2c7 100644
--- a/src/part.h
+++ b/src/part.h
@@ -61,6 +61,7 @@
 #define hydro_need_extra_init_loop 0
 #elif defined(DEFAULT_SPH)
 #include "./hydro/Default/hydro_part.h"
+#define EXTRA_HYDRO_LOOP
 #define hydro_need_extra_init_loop 0
 #elif defined(GIZMO_MFV_SPH)
 #include "./hydro/GizmoMFV/hydro_part.h"
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3407de7588dc297b072567a8b320c99e3ece0462..b75e4ae34a23a6e8c208529345d925a4dcc44623 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -20,9 +20,9 @@ AM_CFLAGS = -I$(top_srcdir)/src $(HDF5_CPPFLAGS) $(GSL_INCS) $(FFTW_INCS) $(NUMA
 AM_LDFLAGS = ../src/.libs/libswiftsim.a $(HDF5_LDFLAGS) $(HDF5_LIBS) $(FFTW_LIBS) $(NUMA_LIBS) $(TCMALLOC_LIBS) $(JEMALLOC_LIBS) $(TBBMALLOC_LIBS) $(GRACKLE_LIBS) $(GSL_LIBS) $(PROFILER_LIBS)
 
 # List of programs and scripts to run in the test suite
-TESTS = testGreetings testMaths testReading.sh testSingle testKernel \
+TESTS = testGreetings testMaths testReading.sh testKernel \
         testActivePair.sh test27cells.sh test27cellsPerturbed.sh  \
-        testParser.sh testSPHStep test125cells.sh test125cellsPerturbed.sh testFFT \
+        testParser.sh test125cells.sh test125cellsPerturbed.sh testFFT \
         testAdiabaticIndex testRandom \
         testMatrixInversion testThreadpool testDump testLogger testInteractions.sh \
         testVoronoi1D testVoronoi2D testVoronoi3D testGravityDerivatives \
@@ -32,8 +32,8 @@ TESTS = testGreetings testMaths testReading.sh testSingle testKernel \
 	test27cellsStars.sh test27cellsStarsPerturbed.sh
 
 # List of test programs to compile
-check_PROGRAMS = testGreetings testReading testSingle testTimeIntegration \
-		 testSPHStep testActivePair test27cells test27cells_subset test125cells testParser \
+check_PROGRAMS = testGreetings testReading testTimeIntegration \
+		 testActivePair test27cells test27cells_subset test125cells testParser \
                  testKernel testFFT testInteractions testMaths testRandom \
                  testSymmetry testThreadpool \
                  testAdiabaticIndex testRiemannExact testRiemannTRRS \
@@ -68,10 +68,6 @@ testSymmetry_CFLAGS = $(AM_CFLAGS) -fno-builtin-memcmp
 
 testTimeIntegration_SOURCES = testTimeIntegration.c
 
-testSPHStep_SOURCES = testSPHStep.c
-
-testSingle_SOURCES = testSingle.c
-
 testActivePair_SOURCES = testActivePair.c
 
 test27cells_SOURCES = test27cells.c
diff --git a/tests/test125cells.c b/tests/test125cells.c
index f05d3f83c41b5f26d7828f09aecd76685a5c55b6..725018316c8ff5834e94633a76a7a4a912446aab 100644
--- a/tests/test125cells.c
+++ b/tests/test125cells.c
@@ -113,7 +113,7 @@ void set_energy_state(struct part *part, enum pressure_field press, float size,
   part->u = pressure / (hydro_gamma_minus_one * density);
 #elif defined(MINIMAL_SPH) || defined(HOPKINS_PU_SPH) ||           \
     defined(HOPKINS_PU_SPH_MONAGHAN) || defined(ANARCHY_PU_SPH) || \
-    defined(ANARCHY_DU_SPH)
+    defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH)
   part->u = pressure / (hydro_gamma_minus_one * density);
 #elif defined(PLANETARY_SPH)
   part->u = pressure / (hydro_gamma_minus_one * density);
@@ -402,12 +402,11 @@ void dump_particle_fields(char *fileName, struct cell *main_cell,
             main_cell->hydro.parts[pid].v[0], main_cell->hydro.parts[pid].v[1],
             main_cell->hydro.parts[pid].v[2], main_cell->hydro.parts[pid].h,
             hydro_get_comoving_density(&main_cell->hydro.parts[pid]),
-#if defined(MINIMAL_SPH) || defined(PLANETARY_SPH) ||              \
-    defined(GIZMO_MFV_SPH) || defined(SHADOWFAX_SPH) ||            \
-    defined(HOPKINS_PU_SPH) || defined(HOPKINS_PU_SPH_MONAGHAN) || \
-    defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH)
+#if defined(MINIMAL_SPH) || defined(PLANETARY_SPH) ||   \
+    defined(GIZMO_MFV_SPH) || defined(SHADOWFAX_SPH) || \
+    defined(HOPKINS_PU_SPH) || defined(HOPKINS_PU_SPH_MONAGHAN)
             0.f,
-#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH)
+#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH)
             main_cell->hydro.parts[pid].viscosity.div_v,
 #else
             main_cell->hydro.parts[pid].density.div_v,
@@ -424,14 +423,11 @@ void dump_particle_fields(char *fileName, struct cell *main_cell,
 #if defined(GADGET2_SPH)
             main_cell->hydro.parts[pid].force.v_sig,
             main_cell->hydro.parts[pid].entropy_dt, 0.f
-#elif defined(DEFAULT_SPH)
-            main_cell->hydro.parts[pid].force.v_sig, 0.f,
-            main_cell->hydro.parts[pid].force.u_dt
 #elif defined(MINIMAL_SPH) || defined(HOPKINS_PU_SPH) || \
     defined(HOPKINS_PU_SPH_MONAGHAN)
             main_cell->hydro.parts[pid].force.v_sig, 0.f,
             main_cell->hydro.parts[pid].u_dt
-#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH)
+#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH)
             main_cell->hydro.parts[pid].viscosity.v_sig, 0.f,
             main_cell->hydro.parts[pid].u_dt
 #else
diff --git a/tests/test27cells.c b/tests/test27cells.c
index e7c87cfe76382ed33a36744087e40a9161b60bfa..e403cc1469cb53cdeea5e248bb8b16a301b70e0c 100644
--- a/tests/test27cells.c
+++ b/tests/test27cells.c
@@ -283,13 +283,13 @@ void dump_particle_fields(char *fileName, struct cell *main_cell,
 #endif
             main_cell->hydro.parts[pid].density.wcount,
             main_cell->hydro.parts[pid].density.wcount_dh,
-#if defined(GADGET2_SPH) || defined(DEFAULT_SPH) || defined(HOPKINS_PE_SPH) || \
+#if defined(GADGET2_SPH) || defined(HOPKINS_PE_SPH) || \
     defined(HOPKINS_PU_SPH) || defined(HOPKINS_PU_SPH_MONAGHAN)
             main_cell->hydro.parts[pid].density.div_v,
             main_cell->hydro.parts[pid].density.rot_v[0],
             main_cell->hydro.parts[pid].density.rot_v[1],
             main_cell->hydro.parts[pid].density.rot_v[2]
-#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH)
+#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH)
             /* this is required because of the variable AV scheme */
             main_cell->hydro.parts[pid].viscosity.div_v,
             main_cell->hydro.parts[pid].density.rot_v[0],
@@ -329,12 +329,12 @@ void dump_particle_fields(char *fileName, struct cell *main_cell,
 #endif
               cj->hydro.parts[pjd].density.wcount,
               cj->hydro.parts[pjd].density.wcount_dh,
-#if defined(GADGET2_SPH) || defined(DEFAULT_SPH) || defined(HOPKINS_PE_SPH)
+#if defined(GADGET2_SPH) || defined(HOPKINS_PE_SPH)
               cj->hydro.parts[pjd].density.div_v,
               cj->hydro.parts[pjd].density.rot_v[0],
               cj->hydro.parts[pjd].density.rot_v[1],
               cj->hydro.parts[pjd].density.rot_v[2]
-#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH)
+#elif defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH)
               /* this is required because of the variable AV scheme */
               cj->hydro.parts[pjd].viscosity.div_v,
               cj->hydro.parts[pjd].density.rot_v[0],
diff --git a/tests/testActivePair.c b/tests/testActivePair.c
index 36bc04b6ffc794bcac556f969c0f710e67c4b24b..ef613d5a68b847b6f379c5667447f1de8bf84c58 100644
--- a/tests/testActivePair.c
+++ b/tests/testActivePair.c
@@ -113,7 +113,7 @@ struct cell *make_cell(size_t n, double *offset, double size, double h,
         part->entropy = 1.f;
 #elif defined(MINIMAL_SPH) || defined(HOPKINS_PU_SPH) ||           \
     defined(HOPKINS_PU_SPH_MONAGHAN) || defined(ANARCHY_PU_SPH) || \
-    defined(ANARCHY_DU_SPH)
+    defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH)
         part->u = 1.f;
 #elif defined(HOPKINS_PE_SPH)
         part->entropy = 1.f;
@@ -197,7 +197,7 @@ void zero_particle_fields_force(struct cell *c, const struct cosmology *cosmo,
     p->density.rot_v[2] = 0.f;
     p->density.div_v = 0.f;
 #endif /* GADGET-2 */
-#if defined(MINIMAL_SPH) || defined(ANARCHY_DU_SPH)
+#if defined(MINIMAL_SPH) || defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH)
     p->rho = 1.f;
     p->density.rho_dh = 0.f;
     p->density.wcount = 48.f / (kernel_norm * pow_dimension(p->h));
diff --git a/tests/testInteractions.c b/tests/testInteractions.c
index 0b1fb081b89b82223c86836bef6b0f68714eae2a..ef4f0e4c69e7770b032af7c9fb5dc8335fc48c11 100644
--- a/tests/testInteractions.c
+++ b/tests/testInteractions.c
@@ -114,7 +114,8 @@ void prepare_force(struct part *parts, size_t count) {
 #if !defined(GIZMO_MFV_SPH) && !defined(SHADOWFAX_SPH) &&            \
     !defined(MINIMAL_SPH) && !defined(PLANETARY_SPH) &&              \
     !defined(HOPKINS_PU_SPH) && !defined(HOPKINS_PU_SPH_MONAGHAN) && \
-    !defined(ANARCHY_PU_SPH) && !defined(ANARCHY_DU_SPH)
+    !defined(ANARCHY_PU_SPH) && !defined(ANARCHY_DU_SPH) &&          \
+    !defined(DEFAULT_SPH)
   struct part *p;
   for (size_t i = 0; i < count; ++i) {
     p = &parts[i];
@@ -141,7 +142,8 @@ void dump_indv_particle_fields(char *fileName, struct part *p) {
           "%8.5f %8.5f %13e %13e %13e %13e %13e %8.5f %8.5f\n",
           p->id, p->x[0], p->x[1], p->x[2], p->v[0], p->v[1], p->v[2], p->h,
           hydro_get_comoving_density(p),
-#if defined(MINIMAL_SPH) || defined(PLANETARY_SPH) || defined(SHADOWFAX_SPH)
+#if defined(MINIMAL_SPH) || defined(PLANETARY_SPH) || \
+    defined(SHADOWFAX_SPH) || defined(DEFAULT_SPH)
           0.f,
 #else
           p->density.div_v,
@@ -156,7 +158,7 @@ void dump_indv_particle_fields(char *fileName, struct part *p) {
           p->force.v_sig, 0.f, p->force.u_dt
 #elif defined(MINIMAL_SPH) || defined(HOPKINS_PU_SPH) ||           \
     defined(HOPKINS_PU_SPH_MONAGHAN) || defined(ANARCHY_PU_SPH) || \
-    defined(ANARCHY_DU_SPH)
+    defined(ANARCHY_DU_SPH) || defined(DEFAULT_SPH)
           p->force.v_sig, 0.f, p->u_dt
 #else
           0.f, 0.f, 0.f
diff --git a/tests/testPeriodicBC.c b/tests/testPeriodicBC.c
index be83f20a58b17f9a5fdcf967cda9a678aab5b8a9..f19ec46620955d29b73113ddae1ab5680f7e7303 100644
--- a/tests/testPeriodicBC.c
+++ b/tests/testPeriodicBC.c
@@ -244,11 +244,16 @@ void dump_particle_fields(char *fileName, struct cell *main_cell, int i, int j,
 #endif
             main_cell->hydro.parts[pid].density.wcount,
             main_cell->hydro.parts[pid].density.wcount_dh,
-#if defined(GADGET2_SPH) || defined(DEFAULT_SPH) || defined(HOPKINS_PE_SPH)
+#if defined(GADGET2_SPH) || defined(HOPKINS_PE_SPH)
             main_cell->hydro.parts[pid].density.div_v,
             main_cell->hydro.parts[pid].density.rot_v[0],
             main_cell->hydro.parts[pid].density.rot_v[1],
             main_cell->hydro.parts[pid].density.rot_v[2]
+#elif defined(DEFAULT_SPH) || defined(ANARCHY_PU_SPH) || defined(ANARCHY_DU_SPH)
+            main_cell->hydro.parts[pid].viscosity.div_v,
+            main_cell->hydro.parts[pid].density.rot_v[0],
+            main_cell->hydro.parts[pid].density.rot_v[1],
+            main_cell->hydro.parts[pid].density.rot_v[2]
 #else
             0., 0., 0., 0.
 #endif
diff --git a/tests/testSPHStep.c b/tests/testSPHStep.c
deleted file mode 100644
index 41694872efbfc4d9611127eb1e6324b2b0fa5500..0000000000000000000000000000000000000000
--- a/tests/testSPHStep.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*******************************************************************************
- * This file is part of SWIFT.
- * Copyright (C) 2015 Matthieu Schaller (matthieu.schaller@durham.ac.uk).
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- ******************************************************************************/
-
-#include "swift.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/**
- * @brief Constructs a cell with N SPH particles
- */
-struct cell *make_cell(size_t N, float cellSize, int offset[3], int id_offset) {
-  size_t count = N * N * N;
-  struct cell *cell = (struct cell *)malloc(sizeof(struct cell));
-  bzero(cell, sizeof(struct cell));
-  struct part *part;
-  struct xpart *xpart;
-  float h;
-  size_t x, y, z, size;
-
-  size = count * sizeof(struct part);
-  if (posix_memalign((void **)&cell->hydro.parts, part_align, size) != 0) {
-    error("couldn't allocate particles");
-  }
-
-  size = count * sizeof(struct xpart);
-  if (posix_memalign((void **)&cell->hydro.xparts, xpart_align, size) != 0) {
-    error("couldn't allocate extended particles");
-  }
-
-  h = 1.2348 * cellSize / N;
-
-  part = cell->hydro.parts;
-  xpart = cell->hydro.xparts;
-  memset(part, 0, count * sizeof(struct part));
-  memset(xpart, 0, count * sizeof(struct xpart));
-  for (x = 0; x < N; ++x) {
-    for (y = 0; y < N; ++y) {
-      for (z = 0; z < N; ++z) {
-        part->x[0] =
-            offset[0] * cellSize + x * cellSize / N + cellSize / (2 * N);
-        part->x[1] =
-            offset[1] * cellSize + y * cellSize / N + cellSize / (2 * N);
-        part->x[2] =
-            offset[2] * cellSize + z * cellSize / N + cellSize / (2 * N);
-        part->h = h;
-        part->id = x * N * N + y * N + z + id_offset;
-        part->time_bin = 1;
-        ++part;
-      }
-    }
-  }
-
-  cell->split = 0;
-  cell->hydro.h_max = h;
-  cell->hydro.count = count;
-  cell->grav.count = 0;
-  cell->hydro.dx_max_part = 0.;
-  cell->hydro.dx_max_sort = 0.;
-  cell->width[0] = cellSize;
-  cell->width[1] = cellSize;
-  cell->width[2] = cellSize;
-
-  cell->hydro.ti_end_min = 1;
-  cell->hydro.ti_end_max = 1;
-
-  cell->hydro.sorted = 0;
-  for (int k = 0; k < 13; k++) cell->hydro.sort[k] = NULL;
-
-  return cell;
-}
-
-/* Just a forward declaration... */
-void runner_doself1_density(struct runner *r, struct cell *ci);
-void runner_doself2_force(struct runner *r, struct cell *ci);
-void runner_dopair1_density(struct runner *r, struct cell *ci, struct cell *cj);
-void runner_dopair2_force(struct runner *r, struct cell *ci, struct cell *cj);
-
-/* Run a full time step integration for one cell */
-int main(int argc, char *argv[]) {
-
-#ifndef DEFAULT_SPH
-  return 0;
-#else
-
-  int i, j, k, offset[3];
-  struct part *p;
-
-  int N = 10;
-  float dim = 1.;
-  float rho = 2.;
-  float P = 1.;
-
-  /* Initialize CPU frequency, this also starts time. */
-  unsigned long long cpufreq = 0;
-  clocks_set_cpufreq(cpufreq);
-
-  /* Get some randomness going */
-  srand(0);
-
-  /* Create cells */
-  struct cell *cells[27];
-  for (i = 0; i < 3; i++)
-    for (j = 0; j < 3; j++)
-      for (k = 0; k < 3; k++) {
-        offset[0] = i;
-        offset[1] = j;
-        offset[2] = k;
-        cells[i * 9 + j * 3 + k] =
-            make_cell(N, dim, offset, (i * 9 + j * 3 + k) * N * N * N);
-      }
-
-  /* Set particle properties */
-  for (j = 0; j < 27; ++j)
-    for (i = 0; i < cells[j]->hydro.count; ++i) {
-      cells[j]->hydro.parts[i].mass = dim * dim * dim * rho / (N * N * N);
-      cells[j]->hydro.parts[i].u = P / (hydro_gamma_minus_one * rho);
-    }
-
-  message("m=%f", dim * dim * dim * rho / (N * N * N));
-
-  /* Pick the central cell */
-  struct cell *ci = cells[13];
-
-  /* Create the infrastructure */
-  struct space space;
-  space.periodic = 0;
-  space.cell_min = 1.;
-
-  struct phys_const prog_const;
-  prog_const.const_newton_G = 1.f;
-
-  struct hydro_props hp;
-  hp.target_neighbours = 48.f;
-  hp.delta_neighbours = 2.;
-  hp.max_smoothing_iterations = 1;
-  hp.CFL_condition = 0.1;
-
-  struct engine e;
-  bzero(&e, sizeof(struct engine));
-  e.hydro_properties = &hp;
-  e.physical_constants = &prog_const;
-  e.s = &space;
-  e.time = 0.1f;
-  e.ti_current = 1;
-
-  struct runner r;
-  r.e = &e;
-
-  /* Simulation properties */
-  e.timeBegin = 0.;
-  e.timeEnd = 1.;
-  e.timeOld = 0.;
-  e.time = 0.1f;
-  e.ti_current = 1;
-
-  /* The tracked particle */
-  p = &(ci->hydro.parts[N * N * N / 2 + N * N / 2 + N / 2]);
-
-  message("Studying particle p->id=%lld", p->id);
-
-  /* Sort the particles */
-  for (j = 0; j < 27; ++j) {
-    runner_do_sort(&r, cells[j], 0x1FFF, 0);
-  }
-
-  message("Sorting done");
-
-  /* Initialise the particles */
-  for (j = 0; j < 27; ++j) {
-    runner_do_init(&r, cells[j], 0);
-  }
-
-  message("Init done");
-
-  /* Compute density */
-  runner_doself1_density(&r, ci);
-  message("Self done");
-  for (int j = 0; j < 27; ++j)
-    if (cells[j] != ci) runner_dopair1_density(&r, ci, cells[j]);
-
-  message("Density done");
-
-  /* Ghost task */
-  runner_do_ghost(&r, ci);
-
-  message("h=%f rho=%f N_ngb=%f", p->h, p->rho, p->density.wcount);
-  message("soundspeed=%f", p->force.soundspeed);
-
-  runner_doself2_force(&r, ci);
-  runner_do_kick(&r, ci, 1);
-
-  message("ti_end=%d", p->ti_end);
-
-  for (int j = 0; j < 27; ++j) {
-    free(cells[j]->hydro.parts);
-    free(cells[j]->hydro.xparts);
-    for (int k = 0; k < 13; k++)
-      if (cells[j]->hydro.sort[k] != NULL) free(cells[j]->hydro.sort[k]);
-    free(cells[j]);
-  }
-
-  return 0;
-#endif
-}
diff --git a/tests/testSingle.c b/tests/testSingle.c
deleted file mode 100644
index 52fe51c529b8c3b43f9c5f03fe44b5b742acfc07..0000000000000000000000000000000000000000
--- a/tests/testSingle.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*******************************************************************************
- * This file is part of SWIFT.
- * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk),
- *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- ******************************************************************************/
-
-/* Config parameters. */
-#include "../config.h"
-
-/* Some standard headers. */
-#include <fenv.h>
-#include <float.h>
-#include <limits.h>
-#include <math.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-/* Conditional headers. */
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
-
-/* Local headers. */
-#include "swift.h"
-
-/* Engine policy flags. */
-#ifndef ENGINE_POLICY
-#define ENGINE_POLICY engine_policy_none
-#endif
-
-#ifdef DEFAULT_SPH
-
-/**
- * @brief Main routine that loads a few particles and generates some output.
- *
- */
-
-int main(int argc, char *argv[]) {
-
-  int k, N = 100;
-  struct part p1, p2;
-  float x, w, dwdx, r2, dx[3] = {0.0f, 0.0f, 0.0f}, gradw[3];
-
-  /* Greeting message */
-  printf("This is %s\n", package_description());
-
-  /* Init the particles. */
-  for (k = 0; k < 3; k++) {
-    p1.a_hydro[k] = 0.0f;
-    p1.v[k] = 0.0f;
-    p1.x[k] = 0.0;
-    p2.a_hydro[k] = 0.0f;
-    p2.v[k] = 0.0f;
-    p2.x[k] = 0.0;
-  }
-  p1.v[0] = 100.0f;
-  p1.id = 0;
-  p2.id = 1;
-  p1.density.wcount = 48.0f;
-  p2.density.wcount = 48.0f;
-  p1.rho = 1.0f;
-  p1.mass = 9.7059e-4;
-  p1.h = 0.222871287 / 2;
-  p2.rho = 1.0f;
-  p2.mass = 9.7059e-4;
-  p2.h = 0.222871287 / 2;
-  p1.force.soundspeed = 0.0040824829f;
-  p1.force.balsara = 0.0f;
-  p2.force.soundspeed = 58.8972740361f;
-  p2.force.balsara = 0.0f;
-  p1.u = 1.e-5 / (hydro_gamma_minus_one * p1.rho);
-  p2.u = 1.e-5 / (hydro_gamma_minus_one * p2.rho) + 100.0f / (33 * p2.mass);
-  p1.force.P_over_rho2 = p1.u * hydro_gamma_minus_one / p1.rho;
-  p2.force.P_over_rho2 = p2.u * hydro_gamma_minus_one / p2.rho;
-
-  /* Dump a header. */
-  // printParticle_single(&p1, NULL);
-  // printParticle_single(&p2, NULL);
-  printf("# r a_1 udt_1 a_2 udt_2\n");
-
-  /* Loop over the different radii. */
-  for (k = 1; k <= N; k++) {
-
-    /* Set the distance/radius. */
-    dx[0] = -((float)k) / N * fmaxf(p1.h, p2.h) * kernel_gamma;
-    r2 = dx[0] * dx[0];
-
-    /* Clear the particle fields. */
-    p1.a_hydro[0] = 0.0f;
-    p1.force.u_dt = 0.0f;
-    p2.a_hydro[0] = 0.0f;
-    p2.force.u_dt = 0.0f;
-
-    /* Interact the particles. */
-    runner_iact_force(r2, dx, p1.h, p2.h, &p1, &p2);
-
-    /* Clear the particle fields. */
-    /* p1.rho = 0.0f; p1.density.wcount = 0.0f;
-    p2.rho = 0.0f; p2.density.wcount = 0.0f; */
-
-    /* Interact the particles. */
-    // runner_iact_density( r2 , dx , p1.h , p2.h , &p1 , &p2 );
-
-    /* Evaluate just the kernel. */
-    x = fabsf(dx[0]) / p1.h;
-    kernel_deval(x, &w, &dwdx);
-    gradw[0] = dwdx / (p1.h * p1.h * p1.h * p1.h) * dx[0] /
-               sqrtf(dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]);
-    gradw[1] = dwdx / (p1.h * p1.h * p1.h * p1.h) * dx[1] /
-               sqrtf(dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]);
-    gradw[2] = dwdx / (p1.h * p1.h * p1.h * p1.h) * dx[2] /
-               sqrtf(dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]);
-
-    /* Output the results. */
-    printf(
-        "%.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e %.3e\n", -dx[0],
-        p1.a_hydro[0], p1.a_hydro[1], p1.a_hydro[2], p1.force.u_dt,
-        /// -dx[0] , p1.rho , p1.density.wcount , p2.rho , p2.density.wcount ,
-        w, dwdx, gradw[0], gradw[1], gradw[2]);
-
-  } /* loop over radii. */
-
-  /* All is calm, all is bright. */
-  return 0;
-}
-#else
-
-int main(int argc, char *argv[]) { return 0; }
-
-#endif