diff --git a/.gitignore b/.gitignore
index d69de3deae4cbe1dff23fd0f22704f6b4f5e40ed..14c768367ee9181c1459b57b93dd92d431ace981 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,6 +29,10 @@ tests/testGreetings
 tests/testReading
 tests/input.hdf5
 tests/testSingle
+tests/testTimeIntegration
+tests/testSPHStep
+
+theory/latex/swift.pdf
 
 m4/libtool.m4
 m4/ltoptions.m4
diff --git a/src/engine.c b/src/engine.c
index a5b2a842f38232bdc75d55d51ad0b8a97c21083f..bdf430646a7632da5b1a847b6b22710eae115e4b 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -362,7 +362,7 @@ void engine_repartition(struct engine *e) {
     if (t->type != task_type_self && t->type != task_type_pair &&
         t->type != task_type_sub && t->type != task_type_ghost &&
         t->type != task_type_drift && t->type != task_type_kick &&
-	t->type != task_type_init)
+        t->type != task_type_init)
       continue;
 
     /* Get the task weight. */
@@ -1370,16 +1370,45 @@ int engine_marktasks(struct engine *e) {
 }
 
 /**
- * @brief Rebuild the space and tasks.
+ * @brief Prints the number of tasks in the engine
  *
  * @param e The #engine.
  */
 
-void engine_rebuild(struct engine *e) {
+void engine_print(struct engine *e) {
 
   int k;
   struct scheduler *sched = &e->sched;
 
+  /* Count and print the number of each task type. */
+  int counts[task_type_count + 1];
+  for (k = 0; k <= task_type_count; k++) counts[k] = 0;
+  for (k = 0; k < sched->nr_tasks; k++)
+    if (!sched->tasks[k].skip)
+      counts[(int)sched->tasks[k].type] += 1;
+    else
+      counts[task_type_count] += 1;
+#ifdef WITH_MPI
+  printf("[%03i] engine_print: task counts are [ %s=%i", e->nodeID,
+         taskID_names[0], counts[0]);
+#else
+  printf("engine_print: task counts are [ %s=%i", taskID_names[0], counts[0]);
+#endif
+  for (k = 1; k < task_type_count; k++)
+    printf(" %s=%i", taskID_names[k], counts[k]);
+  printf(" skipped=%i ]\n", counts[task_type_count]);
+  fflush(stdout);
+  message("nr_parts = %i.", e->s->nr_parts);
+}
+
+/**
+ * @brief Rebuild the space and tasks.
+ *
+ * @param e The #engine.
+ */
+
+void engine_rebuild(struct engine *e) {
+
   /* Clear the forcerebuild flag, whatever it was. */
   e->forcerebuild = 0;
 
@@ -1410,25 +1439,8 @@ void engine_rebuild(struct engine *e) {
   // message( "engine_marktasks took %.3f ms." , (double)(getticks() -
   // tic)/CPU_TPS*1000 );
 
-  /* Count and print the number of each task type. */
-  int counts[task_type_count + 1];
-  for (k = 0; k <= task_type_count; k++) counts[k] = 0;
-  for (k = 0; k < sched->nr_tasks; k++)
-    if (!sched->tasks[k].skip)
-      counts[(int)sched->tasks[k].type] += 1;
-    else
-      counts[task_type_count] += 1;
-#ifdef WITH_MPI
-  printf("[%03i] engine_rebuild: task counts are [ %s=%i", e->nodeID,
-         taskID_names[0], counts[0]);
-#else
-  printf("engine_rebuild: task counts are [ %s=%i", taskID_names[0], counts[0]);
-#endif
-  for (k = 1; k < task_type_count; k++)
-    printf(" %s=%i", taskID_names[k], counts[k]);
-  printf(" skipped=%i ]\n", counts[task_type_count]);
-  fflush(stdout);
-  message("nr_parts = %i.", e->s->nr_parts);
+  /* Print the status of the system */
+  engine_print(e);
 }
 
 /**
@@ -1746,9 +1758,9 @@ void engine_step(struct engine *e) {
   struct cell *c;
   struct space *s = e->s;
 
-  TIMER_TIC2
-
+  TIMER_TIC2;
 
+  message("Begin step: %d", e->step);
 
   /* Re-distribute the particles amongst the nodes? */
   if (e->forcerepart) engine_repartition(e);
@@ -1756,33 +1768,20 @@ void engine_step(struct engine *e) {
   /* Prepare the space. */
   engine_prepare(e);
 
-  // engine_single_density( e->s->dim , 3392063069037 , e->s->parts ,
-  // e->s->nr_parts , e->s->periodic );
+  engine_print(e);
 
   /* Send off the runners. */
-  TIMER_TIC
-  engine_launch(
-      e, e->nr_threads,
-      (1 << task_type_sort) | (1 << task_type_self) | (1 << task_type_pair) |
-          (1 << task_type_sub) | (1 << task_type_ghost) |
-          (1 << task_type_kick) | (1 << task_type_send) |
-          (1 << task_type_recv) |
-          /* (1 << task_type_grav_pp) | (1 << task_type_grav_mm) | */
-          /* (1 << task_type_grav_up) | (1 << task_type_grav_down) | */
-          (1 << task_type_link));
+  TIMER_TIC;
+  engine_launch(e, e->nr_threads,
+                (1 << task_type_sort) | (1 << task_type_self) |
+                    (1 << task_type_pair) | (1 << task_type_sub) |
+                    (1 << task_type_init) | (1 << task_type_ghost) |
+                    (1 << task_type_kick) | (1 << task_type_send) |
+                    (1 << task_type_recv) | (1 << task_type_link));
 
   TIMER_TOC(timer_runners);
 
-  // engine_single_force( e->s->dim , 8328423931905 , e->s->parts ,
-  // e->s->nr_parts , e->s->periodic );
-
-  // for(k=0; k<10; ++k)
-  //   printParticle(parts, k);
-  // printParticle( parts , 432626 );
-  // printParticle( e->s->parts , 3392063069037 , e->s->nr_parts );
-  // printParticle( e->s->parts , 8328423931905 , e->s->nr_parts );
-
-  /* Collect the cell data from the second kick. */
+  /* Collect the cell data from the kick. */
   for (k = 0; k < s->nr_cells; k++)
     if (s->cells[k].nodeID == e->nodeID) {
       c = &s->cells[k];
@@ -1806,12 +1805,12 @@ void engine_step(struct engine *e) {
   out[0] = t_end_min;
   if (MPI_Allreduce(out, in, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD) !=
       MPI_SUCCESS)
-    error("Failed to aggregate dt_min.");
+    error("Failed to aggregate t_end_min.");
   t_end_min = in[0];
   out[0] = t_end_max;
   if (MPI_Allreduce(out, in, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD) !=
       MPI_SUCCESS)
-    error("Failed to aggregate dt_max.");
+    error("Failed to aggregate t_end_max.");
   t_end_max = in[0];
   out[0] = count;
   out[1] = ekin;
@@ -1830,71 +1829,16 @@ if ( e->nodeID == 0 )
     message( "nr_parts=%i." , nr_parts ); */
 #endif
 
-  e->count_step = count;
-  e->ekin = ekin;
-  e->epot = epot;
-  // printParticle( e->s->parts , 382557 , e->s->nr_parts );
-  // message( "dt_min/dt_max is %e/%e." , dt_min , dt_max ); fflush(stdout);
-  // message( "etot is %e (ekin=%e, epot=%e)." , ekin+epot , ekin , epot );
-  // fflush(stdout);
-  // message( "total momentum is [ %e , %e , %e ]." , mom[0] , mom[1] , mom[2]
-  // ); fflush(stdout);
-  // message( "total angular momentum is [ %e , %e , %e ]." , ang[0] , ang[1] ,
-  // ang[2] ); fflush(stdout);
-  // message( "updated %i parts (dt_step=%.3e)." , count , dt_step );
-  // fflush(stdout);
-
-  /* Increase the step. */
+  /* Move forward in time */
+  e->timeOld = e->time;
+  e->time = t_end_min;
   e->step += 1;
 
-  /* /\* Does the time step need adjusting? *\/ */
-  /* if (e->policy & engine_policy_fixdt) { */
-  /*   dt = e->dt_orig; */
-  /* } else { */
-  /*   if (dt == 0) { */
-  /*     e->nullstep += 1; */
-  /*     if (e->dt_orig > 0.0) { */
-  /*       dt = e->dt_orig; */
-  /*       while (dt_min < dt) dt *= 0.5; */
-  /*       while (dt_min > 2 * dt) dt *= 2.0; */
-  /*     } else */
-  /*       dt = dt_min; */
-  /*     for (k = 0; k < s->nr_parts; k++) { */
-  /*       /\* struct part *p = &s->parts[k]; */
-  /*       struct xpart *xp = &s->xparts[k]; */
-  /*       float dt_curr = dt; */
-  /*       for ( int j = (int)( p->dt / dt ) ; j > 1 ; j >>= 1 ) */
-  /*           dt_curr *= 2.0f; */
-  /*       xp->dt_curr = dt_curr; *\/ */
-  /*       s->parts[k].dt = dt; */
-  /*       s->xparts[k].dt_curr = dt; */
-  /*     } */
-  /*     // message( "dt_min=%.3e, adjusting time step to dt=%e." , dt_min ,
-   * e->dt */
-  /*     // ); */
-  /*   } else { */
-  /*     while (dt_min < dt) { */
-  /*       dt *= 0.5; */
-  /*       e->step *= 2; */
-  /*       e->nullstep *= 2; */
-  /*       // message( "dt_min dropped below time step, adjusting to dt=%e." ,
-   */
-  /*       // e->dt ); */
-  /*     } */
-  /*     while (dt_min > 2 * dt && (e->step & 1) == 0) { */
-  /*       dt *= 2.0; */
-  /*       e->step /= 2; */
-  /*       e->nullstep /= 2; */
-  /*       // message( "dt_min is larger than twice the time step, adjusting to
-   */
-  /*       // dt=%e." , e->dt ); */
-  /*     } */
-  /*   } */
-  /* } */
-  /* e->dt = dt; */
+  message("e->time=%f", e->time);
+  message("Ready to drift");
 
-  /* /\* Set the system time. *\/ */
-  /* e->time = dt * (e->step - e->nullstep); */
+  /* Drift all particles */
+  engine_launch(e, e->nr_threads, (1 << task_type_drift));
 
   TIMER_TOC2(timer_step);
 }
@@ -2067,7 +2011,6 @@ void engine_init(struct engine *e, struct space *s, float dt, int nr_threads,
                  float timeBegin, float timeEnd) {
 
   int k;
-  float dt_min = dt;
 #if defined(HAVE_SETAFFINITY)
   int nr_cores = sysconf(_SC_NPROCESSORS_ONLN);
   int i, j, cpuid[nr_cores];
diff --git a/src/engine.h b/src/engine.h
index 6ef59767a358ce950a2222201e1087352e995ec8..afc2f9ad157b5895c84811d6b61a9e7288131b7b 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -137,6 +137,7 @@ void engine_init(struct engine *e, struct space *s, float dt, int nr_threads,
                  int nr_queues, int nr_nodes, int nodeID, int policy,
                  float timeBegin, float timeEnd);
 void engine_prepare(struct engine *e);
+void engine_print(struct engine *e);
 void engine_step(struct engine *e);
 void engine_maketasks(struct engine *e);
 void engine_split(struct engine *e, int *grid);
diff --git a/src/map.h b/src/map.h
index 0fe04ad0158499626a16a0b18637ff190cf59c97..0753c2641af6deb050c1dcef6bcd3ae4621ae6aa 100644
--- a/src/map.h
+++ b/src/map.h
@@ -18,7 +18,6 @@
  *
  ******************************************************************************/
 
-
 /* Includes. */
 #ifndef SWIFT_MAP_H
 #define SWIFT_MAP_H
diff --git a/src/parallel_io.c b/src/parallel_io.c
index 3fff596718ef41caba9c81a71e912b9d19ac192a..f48aaa04e59cb084f6d1a4af0a904a7476b470ac 100644
--- a/src/parallel_io.c
+++ b/src/parallel_io.c
@@ -441,7 +441,8 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name,
  * @param N_total Total number of particles across all cores
  * @param mpi_rank The MPI task rank calling the function
  * @param offset Offset in the array where this mpi task starts writing
- * @param part A (char*) pointer on the first occurrence of the field of interest
+ * @param part A (char*) pointer on the first occurrence of the field of
+ *interest
  *in the parts array
  * @param field The name (code name) of the field to read from.
  * @param us The UnitSystem currently in use
@@ -582,7 +583,8 @@ void write_output_parallel(struct engine* e, struct UnitSystem* us,
              N_total, mpi_rank, offset, u, us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
   writeArray(h_grp, fileName, xmfFile, "ParticleIDs", ULONGLONG, N, 1, parts,
              N_total, mpi_rank, offset, id, us, UNIT_CONV_NO_UNITS);
-  /* writeArray(h_grp, fileName, xmfFile, "TimeStep", FLOAT, N, 1, parts, N_total, */
+  /* writeArray(h_grp, fileName, xmfFile, "TimeStep", FLOAT, N, 1, parts,
+   * N_total, */
   /*            mpi_rank, offset, dt, us, UNIT_CONV_TIME); */
   writeArray(h_grp, fileName, xmfFile, "Acceleration", FLOAT, N, 3, parts,
              N_total, mpi_rank, offset, a, us, UNIT_CONV_ACCELERATION);
diff --git a/src/part.h b/src/part.h
index 97977dadc988f361c7c6aae5b512ca857ad384da..2b5a28a897a59ec8984cef7941e6f9a8fb34e8f6 100644
--- a/src/part.h
+++ b/src/part.h
@@ -40,9 +40,6 @@ struct xpart {
   /* Old density. */
   float omega;
 
-  /* particle's current time-step. */
-  float dt_curr;
-
 } __attribute__((aligned(32)));
 
 /* Gravity particle. */
@@ -115,46 +112,46 @@ struct part {
 #endif
 
   /* Store density/force specific stuff. */
-  union {
+  // union {
 
-    struct {
+  struct {
 
-      /* Particle velocity divergence. */
-      float div_v;
+    /* Particle velocity divergence. */
+    float div_v;
 
-      /* Derivative of particle number density. */
-      float wcount_dh;
+    /* Derivative of particle number density. */
+    float wcount_dh;
 
-      /* Particle velocity curl. */
-      float curl_v[3];
+    /* Particle velocity curl. */
+    float curl_v[3];
 
-      /* Particle number density. */
-      float wcount;
+    /* Particle number density. */
+    float wcount;
 
-    } density;
+  } density;
 
-    struct {
+  struct {
 
-      /* Balsara switch */
-      float balsara;
+    /* Balsara switch */
+    float balsara;
 
-      /* Aggregate quantities. */
-      float POrho2;
+    /* Aggregate quantities. */
+    float POrho2;
 
-      /* Change in particle energy over time. */
-      float u_dt;
+    /* Change in particle energy over time. */
+    float u_dt;
 
-      /* Change in smoothing length over time. */
-      float h_dt;
+    /* Change in smoothing length over time. */
+    float h_dt;
 
-      /* Signal velocity */
-      float v_sig;
+    /* Signal velocity */
+    float v_sig;
 
-      /* Sound speed */
-      float c;
+    /* Sound speed */
+    float c;
 
-    } force;
-  };
+  } force;
+  //};
 
   /* Particle pressure. */
   // float P;
diff --git a/src/runner.c b/src/runner.c
index 2e8a13dbcb024ba0ffc6ab9a3359f64e63d836ff..9544450cd1de0446b125a3e01a880cf67bb8eb04 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -518,8 +518,6 @@ void runner_doinit(struct runner *r, struct cell *c) {
     /* Get a direct pointer on the part. */
     p = &parts[i];
 
-    if (p->id == 0) message("init!");
-
     if (p->t_end <= t_end) {
 
       /* Get ready for a density calculation */
@@ -593,8 +591,8 @@ void runner_doghost(struct runner *r, struct cell *c) {
         /* Final operation on the density. */
         p->rho = rho = ih * ih2 * (p->rho + p->mass * kernel_root);
         p->rho_dh = rho_dh = (p->rho_dh - 3.0f * p->mass * kernel_root) * ih4;
-        wcount = (p->density.wcount + kernel_root) *
-                 (4.0f / 3.0 * M_PI * kernel_gamma3);
+        p->density.wcount = wcount = (p->density.wcount + kernel_root) *
+                                     (4.0f / 3.0 * M_PI * kernel_gamma3);
         wcount_dh =
             p->density.wcount_dh * ih * (4.0f / 3.0 * M_PI * kernel_gamma3);
 
@@ -610,20 +608,12 @@ void runner_doghost(struct runner *r, struct cell *c) {
           h_corr = fmaxf(h_corr, -h / 2.f);
         }
 
-        if (p->id == 0)
-          message("ghost! h=%f dh=%f wcount=%f rho=%f", p->h, h_corr, wcount,
-                  p->rho);
-
-        /* Apply the correction to p->h and to the compact part. */
-        h = p->h += h_corr;
-
         /* Did we get the right number density? */
         if (wcount > kernel_nwneigh + const_delta_nwneigh ||
             wcount < kernel_nwneigh - const_delta_nwneigh) {
-          // message( "particle %lli (h=%e,depth=%i) has bad wcount=%.3f." ,
-          // p->id , p->h , c->depth , wcount ); fflush(stdout);
-          // p->h += ( p->density.wcount + kernel_root - kernel_nwneigh ) /
-          // p->density.wcount_dh;
+          h = p->h += h_corr;
+          p->h += (p->density.wcount + kernel_root - kernel_nwneigh) /
+                  p->density.wcount_dh;
           pid[redo] = pid[i];
           redo += 1;
           p->density.wcount = 0.0;
@@ -672,7 +662,7 @@ void runner_doghost(struct runner *r, struct cell *c) {
                     (const_viscosity_alpha_max - p->alpha) * S;
 
         /* Update particle's viscosity paramter */
-        p->alpha += alpha_dot * 1;  // p->dt;
+        p->alpha += alpha_dot * (p->t_end - p->t_begin);
 #endif
 
         /* Reset the acceleration. */
@@ -768,8 +758,6 @@ void runner_dodrift(struct runner *r, struct cell *c, int timer) {
       p = &parts[k];
       xp = &xparts[k];
 
-      if (p->id == 0) message("drift !");
-
       /* Get local copies of particle data. */
       h = p->h;
       ih = 1.0f / h;
@@ -816,11 +804,9 @@ void runner_dodrift(struct runner *r, struct cell *c, int timer) {
 
       /* Predict gradient term */
       p->force.POrho2 = u * (const_hydro_gamma - 1.0f) / (rho * xp->omega);
-
     }
   }
 
-
   if (timer) {
 #ifdef TIMER_VERBOSE
     message("runner %02i: %i parts at depth %i took %.3f ms.", r->id, c->count,
@@ -830,11 +816,8 @@ void runner_dodrift(struct runner *r, struct cell *c, int timer) {
     TIMER_TOC(timer_drift);
 #endif
   }
-
-  
 }
 
-
 /**
  * @brief Combined second and first kick for fixed dt.
  *
@@ -879,15 +862,13 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) {
       m = p->mass;
       x[0] = p->x[0], x[1] = p->x[1], x[2] = p->x[2];
 
-      if (p->id == 0)
-        message("Kick ! t_beg=%f t_end=%f t_cur=%f", p->t_begin, p->t_end,
-                t_current);
+      /* if (p->id == 0) */
+      /*   message("Kick ! t_beg=%f t_end=%f t_cur=%f", p->t_begin, p->t_end, */
+      /*           t_current); */
 
       /* If particle needs to be kicked */
       if (p->t_end <= t_current) {
 
-        if (p->id == 0) message("Kicking like a boss");
-
         /* First, finish the force loop */
         p->force.h_dt *= p->h * 0.333333333f;
 
@@ -919,16 +900,10 @@ void runner_dokick(struct runner *r, struct cell *c, int timer) {
         t_end = p->t_end + 0.5f * new_dt;
         dt = t_end - t_start;
 
-        if (p->id == 0)
-          message("Kick ! dt=%f t_beg=%f t_end=%f", dt, p->t_begin, p->t_end);
-
         /* Move particle forward in time */
         p->t_begin = p->t_end;
         p->t_end = p->t_begin + dt;
 
-        if (p->id == 0)
-          message("Kick ! dt=%f t_beg=%f t_end=%f", dt, p->t_begin, p->t_end);
-
         /* Kick particles in momentum space */
         xp->v_full[0] += p->a[0] * dt;
         xp->v_full[1] += p->a[1] * dt;
diff --git a/src/serial_io.c b/src/serial_io.c
index c61774fed2e5991e5a1ed06bac572224b09ade9c..0feda5adfd1ac702014e00fb0c5adae89d2e6868 100644
--- a/src/serial_io.c
+++ b/src/serial_io.c
@@ -314,7 +314,8 @@ void read_ic_serial(char* fileName, double dim[3], struct part** parts, int* N,
                 u, COMPULSORY);
       readArray(h_grp, "ParticleIDs", ULONGLONG, *N, 1, *parts, N_total, offset,
                 id, COMPULSORY);
-      /* readArray(h_grp, "TimeStep", FLOAT, *N, 1, *parts, N_total, offset, dt, */
+      /* readArray(h_grp, "TimeStep", FLOAT, *N, 1, *parts, N_total, offset, dt,
+       */
       /*           OPTIONAL); */
       readArray(h_grp, "Acceleration", FLOAT, *N, 3, *parts, N_total, offset, a,
                 OPTIONAL);
@@ -487,7 +488,8 @@ void writeArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N,
  * @param type The #DATA_TYPE of the array.
  * @param N The number of particles to write.
  * @param dim The dimension of the data (1 for scalar, 3 for vector)
- * @param part A (char*) pointer on the first occurrence of the field of interest
+ * @param part A (char*) pointer on the first occurrence of the field of
+ *interest
  *in the parts array
  * @param field The name (code name) of the field to read from.
  * @param us The UnitSystem currently in use
@@ -627,7 +629,8 @@ void write_output_serial(struct engine* e, struct UnitSystem* us, int mpi_rank,
                  us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
     prepareArray(h_grp, fileName, xmfFile, "ParticleIDs", ULONGLONG, N_total, 1,
                  us, UNIT_CONV_NO_UNITS);
-    /* prepareArray(h_grp, fileName, xmfFile, "TimeStep", FLOAT, N_total, 1, us, */
+    /* prepareArray(h_grp, fileName, xmfFile, "TimeStep", FLOAT, N_total, 1, us,
+     */
     /*              UNIT_CONV_TIME); */
     prepareArray(h_grp, fileName, xmfFile, "Acceleration", FLOAT, N_total, 3,
                  us, UNIT_CONV_ACCELERATION);
diff --git a/src/single_io.c b/src/single_io.c
index 7e92949e24f6618861050597e2e9335c26c8e1b8..10b84afeeeef77e72031536876ff9ebb4f37ca70 100644
--- a/src/single_io.c
+++ b/src/single_io.c
@@ -353,7 +353,8 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name,
  * @param type The #DATA_TYPE of the array.
  * @param N The number of particles to write.
  * @param dim The dimension of the data (1 for scalar, 3 for vector)
- * @param part A (char*) pointer on the first occurrence of the field of interest
+ * @param part A (char*) pointer on the first occurrence of the field of
+ *interest
  *in the parts array
  * @param field The name (code name) of the field to read from.
  * @param us The UnitSystem currently in use
diff --git a/src/task.c b/src/task.c
index 642e6833c48236395f20c20b8e83f93d74757ea0..f736a1b30e14955fff070f586ebea0c54df403dd 100644
--- a/src/task.c
+++ b/src/task.c
@@ -43,9 +43,9 @@
 
 /* Task type names. */
 const char *taskID_names[task_type_count] = {
-    "none",  "sort",    "self",    "pair",    "sub",
-    "ghost", "kick1",   "kick2",   "send",    "recv",
-    "link",  "grav_pp", "grav_mm", "grav_up", "grav_down"};
+    "none",    "sort",    "self",    "pair",     "sub",  "init",
+    "ghost",   "drift",   "kick",    "send",     "recv", "link",
+    "grav_pp", "grav_mm", "grav_up", "grav_down"};
 
 /**
  * @brief Unlock the cell held by this task.
diff --git a/src/tools.c b/src/tools.c
index 5f8abcbeb6d339bedc3df71e5ccf651535b8bc0c..3973696b98954e17c8e6c4ee6535f1be8016ee58 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -19,7 +19,6 @@
  *
  ******************************************************************************/
 
-
 #include <math.h>
 #include <stdlib.h>
 #include <stddef.h>
@@ -31,7 +30,6 @@
 #include "tools.h"
 #include "swift.h"
 
-
 /**
  *  Factorize a given integer, attempts to keep larger pair of factors.
  */
@@ -49,8 +47,6 @@ void factor(int value, int *f1, int *f2) {
   }
 }
 
-
-
 /**
  * @brief Compute the average number of pairs per particle using
  *      a brute-force O(N^2) computation.
@@ -234,7 +230,6 @@ void pairs_single_grav(double *dim, long long int pid,
       pi.part->id, a[0], a[1], a[2], aabs[0], aabs[1], aabs[2]);
 }
 
-
 /**
  * @brief Test the density function by dumping it for two random parts.
  *
diff --git a/src/tools.h b/src/tools.h
index 7354a51030fef3a1fc8445afce770f56d5866fd6..ea7138672a3d2a037f1da98368c185bc4633fe08 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -24,9 +24,7 @@ void density_dump(int N);
 void pairs_single_grav(double *dim, long long int pid,
                        struct gpart *__restrict__ parts, int N, int periodic);
 void pairs_single_density(double *dim, long long int pid,
-                          struct part *__restrict__ parts, int N,
-                          int periodic);
+                          struct part *__restrict__ parts, int N, int periodic);
 
 void pairs_n2(double *dim, struct part *__restrict__ parts, int N,
               int periodic);
-
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9ab592e6ccde6194ffcc85c510554d195e7da9c4..2fc5e37578414d83c9858bd7da7c20fb98ff11cf 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -20,10 +20,10 @@ AM_CFLAGS = -I../src -DCPU_TPS=2.67e9 $(HDF5_CPPFLAGS)
 AM_LDFLAGS = ../src/.libs/libswiftsim.a $(HDF5_LDFLAGS) $(HDF5_LIBS)
 
 # List of programs and scripts to run in the test suite
-TESTS = testGreetings testReading.sh testSingle testTimeIntegration
+TESTS = testGreetings testReading.sh testSingle testTimeIntegration testSPHStep
 
 # List of test programs to compile
-check_PROGRAMS = testGreetings testReading testSingle testTimeIntegration
+check_PROGRAMS = testGreetings testReading testSingle testTimeIntegration testSPHStep
 
 # Sources for the individual programs
 testGreetings_SOURCES = testGreetings.c
@@ -32,7 +32,8 @@ testReading_SOURCES = testReading.c
 
 testTimeIntegration_SOURCES = testTimeIntegration.c
 
-# Sources for test_single
+testSPHStep_SOURCES = testSPHStep.c
+
 testSingle_SOURCES = testSingle.c
 testSingle_CFLAGS = $(MYFLAGS) $(AM_CFLAGS)
 testSingle_LDADD =  ../src/.libs/libswiftsim.a $(HDF5_LDFLAGS) $(HDF5_LIBS)
diff --git a/tests/testSPHStep.c b/tests/testSPHStep.c
new file mode 100644
index 0000000000000000000000000000000000000000..0f33c9829bd9763d84bb528bca76c792e2720c86
--- /dev/null
+++ b/tests/testSPHStep.c
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * 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 = malloc(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->parts, 32, size) != 0) {
+    error("couldn't allocate particles");
+  }
+
+  size = count*sizeof(struct xpart);
+  if (posix_memalign((void**)&cell->xparts, 32, size) != 0) {
+    error("couldn't allocate extended particles");
+  }
+
+  
+  h = 1.127 * cellSize / N;
+  
+  part = cell->parts;
+  xpart = cell->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;
+      }
+    }
+  }
+
+  cell->split = 0;
+  cell->h_max = h;
+  cell->count = count;
+  cell->h[0] = cellSize;
+  cell->h[1] = cellSize;
+  cell->h[2] = cellSize;
+  
+  return cell;
+}
+
+
+
+/* Run a full time step integration for one cell */
+int main() {
+
+  int i,j,k, offset[3];
+  struct part *p;
+
+  int N = 10;
+  float dim = 1.;
+  float rho = 2.;
+  float P = 1.;
+  
+  /* 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]->count; ++i) {
+      cells[j]->parts[i].mass =  dim * dim * dim * rho / (N * N * N);
+      cells[j]->parts[i].u = P / ((const_hydro_gamma - 1.)*rho);
+    }
+
+  message("m=%f", dim * dim * dim * rho / (N * N * N));
+
+  /* Pick the central cell */
+  struct cell *ci = cells[13];
+    
+  /* Create the infrastructure */
+  struct engine e;
+  struct runner r;
+  r.e = &e;
+
+  /* Simulation properties */
+  e.timeBegin = 0.;
+  e.timeEnd = 1.;
+  e.timeOld = 0.;
+  e.time = 0.;
+  e.dt_min = 0.;
+  e.dt_max = 1e10;
+
+  /* The tracked particle */
+  p = &(ci->parts[N*N*N / 2 + N*N / 2 + N / 2]);
+
+  message("Studying particle p->id=%lld", p->id);
+
+  
+  /* Initialise the particles */
+  for (j=0 ; j<27; ++j)
+    {
+      runner_doinit(&r, cells[j]);
+    }
+  
+  /* Compute density */
+  runner_doself1_density(&r, ci);
+  runner_doghost(&r, ci);
+  
+  message("h=%f rho=%f N_ngb=%f", p->h, p->rho, p->density.wcount);
+  message("c=%f", p->force.c);
+
+  runner_doself2_force(&r, ci);
+  runner_dokick(&r, ci, 1);
+  
+  message("t_end=%f", p->t_end);
+  
+  free(ci->parts);
+  free(ci->xparts);
+  
+  return 0;
+}