diff --git a/examples/EAGLE_12/eagle_12.yml b/examples/EAGLE_12/eagle_12.yml
index e4eb43672a2e80da2f7ee558cebbebe92a28e269..6afffed0f9d39b34588b89569a85ab56223fc548 100644
--- a/examples/EAGLE_12/eagle_12.yml
+++ b/examples/EAGLE_12/eagle_12.yml
@@ -31,8 +31,6 @@ Gravity:
   eta:                   0.025    # Constant dimensionless multiplier for time integration.
   theta:                 0.7      # Opening angle (Multipole acceptance criterion)
   epsilon:               0.0001   # Softening length (in internal units).
-  a_smooth:              1000.
-  r_cut:                 4.
   
 # Parameters for the hydrodynamics scheme
 SPH:
diff --git a/examples/UniformDMBox/uniformBox.yml b/examples/UniformDMBox/uniformBox.yml
index 8d9ec300164a7bf8f3df257c34ee44d4f77fe94e..1572e55662d2ba6b113ab5f21ba357db1bc811d4 100644
--- a/examples/UniformDMBox/uniformBox.yml
+++ b/examples/UniformDMBox/uniformBox.yml
@@ -14,7 +14,7 @@ TimeIntegration:
   dt_max:     1e-3  # The maximal time-step size of the simulation (in internal units).
 
 Scheduler:
-  max_top_level_cells: 8
+  max_top_level_cells: 16
   cell_split_size:     50
   
 # Parameters governing the snapshots
@@ -35,4 +35,4 @@ Statistics:
 
 # Parameters related to the initial conditions
 InitialConditions:
-  file_name:  ./uniformDMBox_100.hdf5     # The file to read
+  file_name:  ./uniformDMBox_50.hdf5     # The file to read
diff --git a/src/cell.c b/src/cell.c
index aa5f3687ae02f1b88ffc7d351e42d4dfc1ff1468..1c20add31d8bb07c2cbc015e4dff3cfa98b2310d 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -1453,7 +1453,6 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) {
   if (c->timestep != NULL) scheduler_activate(s, c->timestep);
   if (c->grav_down != NULL) scheduler_activate(s, c->grav_down);
   if (c->grav_long_range != NULL) scheduler_activate(s, c->grav_long_range);
-  if (c->grav_top_level != NULL) scheduler_activate(s, c->grav_top_level);
   if (c->cooling != NULL) scheduler_activate(s, c->cooling);
   if (c->sourceterms != NULL) scheduler_activate(s, c->sourceterms);
 
diff --git a/src/cell.h b/src/cell.h
index c89e70960e84bb027f5e99a3cb362f2e0722b9bd..d04e20ca33cd1f0ffff5759977f9fc52eab630fc 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -169,10 +169,7 @@ struct cell {
   /*! The task to compute time-steps */
   struct task *timestep;
 
-  /*! Task constructing the multipole from the particles */
-  struct task *grav_top_level;
-
-  /*! Task constructing the multipole from the particles */
+  /*! Task computing long range non-periodic gravity interactions */
   struct task *grav_long_range;
 
   /*! Task propagating the multipole to the particles */
diff --git a/src/engine.c b/src/engine.c
index ab14af5c2e3fee19fcf2ec5963788aa8338d0568..03d5b4be461bbe9667c2963559df62a81ca17dc5 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -168,18 +168,12 @@ void engine_make_hierarchical_tasks(struct engine *e, struct cell *c) {
         c->grav_long_range = scheduler_addtask(
             s, task_type_grav_long_range, task_subtype_none, 0, 0, c, NULL);
 
-        /* Gravity top-level periodic calculation */
-        c->grav_top_level = scheduler_addtask(s, task_type_grav_top_level,
-                                              task_subtype_none, 0, 0, c, NULL);
-
         /* Gravity recursive down-pass */
         c->grav_down = scheduler_addtask(s, task_type_grav_down,
                                          task_subtype_none, 0, 0, c, NULL);
 
         scheduler_addunlock(s, c->init_grav, c->grav_long_range);
-        scheduler_addunlock(s, c->init_grav, c->grav_top_level);
         scheduler_addunlock(s, c->grav_long_range, c->grav_down);
-        scheduler_addunlock(s, c->grav_top_level, c->grav_down);
         scheduler_addunlock(s, c->grav_down, c->kick2);
       }
 
@@ -1655,6 +1649,10 @@ void engine_make_self_gravity_tasks(struct engine *e) {
   struct cell *cells = s->cells_top;
   const int nr_cells = s->nr_cells;
 
+  /* Create the FFT task for this MPI rank */
+  struct task *fft = scheduler_addtask(sched, task_type_grav_top_level,
+                                       task_type_none, 0, 0, NULL, NULL);
+
   for (int cid = 0; cid < nr_cells; ++cid) {
 
     struct cell *ci = &cells[cid];
@@ -1666,7 +1664,10 @@ void engine_make_self_gravity_tasks(struct engine *e) {
     if (ci->nodeID != nodeID) continue;
 
     /* If the cells is local build a self-interaction */
-    scheduler_addtask(sched, task_type_self, task_subtype_grav, 0, 0, ci, NULL);
+    struct task *self = scheduler_addtask(sched, task_type_self,
+                                          task_subtype_grav, 0, 0, ci, NULL);
+
+    scheduler_addunlock(sched, fft, self);
 
     /* Loop over every other cell */
     for (int cjd = cid + 1; cjd < nr_cells; ++cjd) {
@@ -1681,9 +1682,12 @@ void engine_make_self_gravity_tasks(struct engine *e) {
 
       /* Are the cells to close for a MM interaction ? */
       if (!gravity_multipole_accept(ci->multipole, cj->multipole,
-                                    theta_crit_inv, 1))
+                                    theta_crit_inv, 1)) {
         scheduler_addtask(sched, task_type_pair, task_subtype_grav, 0, 0, ci,
                           cj);
+
+        // scheduler_addunlock(sched, fft, pair);
+      }
     }
   }
 }
@@ -2605,11 +2609,15 @@ void engine_marktasks_mapper(void *map_data, int num_elements,
 
     /* Gravity ? */
     else if (t->type == task_type_grav_down ||
-             t->type == task_type_grav_long_range ||
-             t->type == task_type_grav_top_level) {
+             t->type == task_type_grav_long_range) {
       if (cell_is_active(t->ci, e)) scheduler_activate(s, t);
     }
 
+    /* Periodic gravity ? */
+    else if (t->type == task_type_grav_top_level) {
+      scheduler_activate(s, t);
+    }
+
     /* Time-step? */
     else if (t->type == task_type_timestep) {
       t->ci->updated = 0;
diff --git a/src/gravity_properties.c b/src/gravity_properties.c
index 7b9b8cd7c35f8fa9b21ff34ce2589b5d45ce8393..b1098888b96cdef2205ed513e60a3799c63e8b9f 100644
--- a/src/gravity_properties.c
+++ b/src/gravity_properties.c
@@ -69,11 +69,9 @@ void gravity_props_print(const struct gravity_props *p) {
   message("Self-gravity softening:    epsilon=%.4f (Plummer equivalent: %.4f)",
           p->epsilon, p->epsilon / 3.);
 
-  if (p->a_smooth != gravity_props_default_a_smooth)
-    message("Self-gravity MM smoothing-scale: a_smooth=%f", p->a_smooth);
+  message("Self-gravity MM smoothing-scale: a_smooth=%f", p->a_smooth);
 
-  if (p->r_cut != gravity_props_default_r_cut)
-    message("Self-gravity MM cut-off: r_cut=%f", p->r_cut);
+  message("Self-gravity MM cut-off: r_cut=%f", p->r_cut);
 }
 
 #if defined(HAVE_HDF5)
diff --git a/src/runner.c b/src/runner.c
index 8d54dc07c89754f14caf39583f1123f620b03547..ca94d410bd739f439091326e336ff1f9820e489b 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -1728,10 +1728,12 @@ void *runner_main(void *data) {
 #ifdef SWIFT_DEBUG_CHECKS
       t->ti_run = e->ti_current;
 #ifndef WITH_MPI
-      if (ci == NULL && cj == NULL) {
+      if (t->type == task_type_grav_top_level) {
+        if (ci != NULL || cj != NULL)
+          error("Top-level gravity task associated with a cell");
+      } else if (ci == NULL && cj == NULL) {
 
         error("Task not associated with cells!");
-
       } else if (cj == NULL) { /* self */
 
         if (!cell_is_active(ci, e) && t->type != task_type_sort &&
diff --git a/src/runner_doiact_fft.c b/src/runner_doiact_fft.c
index 1e9a4d3be684a6fdec921a4b1ef345895a41d5a9..f0d49a6d3a4c643eb319c08bd2c21af1e2031465 100644
--- a/src/runner_doiact_fft.c
+++ b/src/runner_doiact_fft.c
@@ -47,7 +47,7 @@
  */
 __attribute__((always_inline)) INLINE static int row_major_id(int i, int j,
                                                               int k, int N) {
-  return (i * N * N + j * N + k);
+  return ((i % N) * N * N + (j % N) * N + (k % N));
 }
 
 /**
@@ -76,6 +76,12 @@ __attribute__((always_inline)) INLINE static void multipole_to_mesh_CIC(
   const double dz = fac * m->CoM[2] - k;
   const double tz = 1. - dz;
 
+#ifdef SWIFT_DEBUG_CHECKS
+  if (i < 0 || i >= N) error("Invalid multipole position in x");
+  if (j < 0 || j >= N) error("Invalid multipole position in y");
+  if (k < 0 || k >= N) error("Invalid multipole position in z");
+#endif
+
   /* CIC ! */
   rho[row_major_id(i + 0, j + 0, k + 0, N)] += m->m_pole.M_000 * tx * ty * tz;
   rho[row_major_id(i + 0, j + 0, k + 1, N)] += m->m_pole.M_000 * tx * ty * dz;
@@ -114,6 +120,12 @@ __attribute__((always_inline)) INLINE static void mesh_to_multipole_CIC(
   const double dz = fac * m->CoM[2] - k;
   const double tz = 1. - dz;
 
+#ifdef SWIFT_DEBUG_CHECKS
+  if (i < 0 || i >= N) error("Invalid multipole position in x");
+  if (j < 0 || j >= N) error("Invalid multipole position in y");
+  if (k < 0 || k >= N) error("Invalid multipole position in z");
+#endif
+
   /* CIC ! */
   m->pot.F_000 += pot[row_major_id(i + 0, j + 0, k + 0, N)] * tx * ty * tz;
   m->pot.F_000 += pot[row_major_id(i + 0, j + 0, k + 1, N)] * tx * ty * dz;
@@ -149,7 +161,6 @@ void runner_do_grav_fft(struct runner* r, int timer) {
   /* Some useful constants */
   const int N = cdim[0];
   const int N_half = N / 2;
-  const int Ncells = N * N * N;
   const double cell_fac = N / box_size;
 
   /* Recover the list of top-level multipoles */
@@ -164,7 +175,7 @@ void runner_do_grav_fft(struct runner* r, int timer) {
   }
 
   /* Allocates some memory for the density mesh */
-  double* restrict rho = fftw_alloc_real(Ncells);
+  double* restrict rho = fftw_alloc_real(N * N * N);
   if (rho == NULL) error("Error allocating memory for density mesh");
 
   /* Allocates some memory for the mesh in Fourier space */
@@ -179,7 +190,7 @@ void runner_do_grav_fft(struct runner* r, int timer) {
       N, N, N, frho, rho, FFTW_ESTIMATE | FFTW_DESTROY_INPUT);
 
   /* Do a CIC mesh assignment of the multipoles */
-  bzero(rho, Ncells * sizeof(double));
+  bzero(rho, N * N * N * sizeof(double));
   for (int i = 0; i < nr_cells; ++i)
     multipole_to_mesh_CIC(&multipoles[i], rho, N, cell_fac);
 
diff --git a/src/scheduler.c b/src/scheduler.c
index e1074a32e9459d0b4c6439055fcc92ac41e6e514..2d1e0093cc2b61fe2485c2295f7a3ff41de30cf6 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -137,7 +137,8 @@ static void scheduler_splittask(struct task *t, struct scheduler *s) {
     redo = 0;
 
     /* Non-splittable task? */
-    if ((t->ci == NULL || (t->type == task_type_pair && t->cj == NULL)) ||
+    if ((t->ci == NULL && t->type != task_type_grav_top_level) ||
+        ((t->type == task_type_pair && t->cj == NULL)) ||
         ((t->type == task_type_kick1) && t->ci->nodeID != s->nodeID) ||
         ((t->type == task_type_kick2) && t->ci->nodeID != s->nodeID) ||
         ((t->type == task_type_drift) && t->ci->nodeID != s->nodeID) ||
@@ -1133,6 +1134,9 @@ void scheduler_start(struct scheduler *s) {
       /* Don't check MPI stuff */
       if (t->type == task_type_send || t->type == task_type_recv) continue;
 
+      /* Don't check the FFT task */
+      if (t->type == task_type_grav_top_level) continue;
+
       if (ci == NULL && cj == NULL) {
 
         error("Task not associated with cells!");
diff --git a/src/space.c b/src/space.c
index 0c67fe27ac1c7b2cae3672e7f0b1ce82be5fb804..1d957e7e72461185b0ddbbe60da3cb2b5b8832b1 100644
--- a/src/space.c
+++ b/src/space.c
@@ -26,6 +26,7 @@
 
 /* Some standard headers. */
 #include <float.h>
+#include <hdf5.h>
 #include <limits.h>
 #include <math.h>
 #include <stdlib.h>
@@ -220,7 +221,6 @@ void space_rebuild_recycle_mapper(void *map_data, int num_elements,
     c->drift = NULL;
     c->cooling = NULL;
     c->sourceterms = NULL;
-    c->grav_top_level = NULL;
     c->grav_long_range = NULL;
     c->grav_down = NULL;
     c->super = c;
@@ -2943,3 +2943,47 @@ void space_clean(struct space *s) {
   free(s->gparts);
   free(s->sparts);
 }
+
+void space_dump_multipoles(struct space *s) {
+
+  hid_t h_file =
+      H5Fcreate("multipoles.hdf5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+  hid_t h_grp =
+      H5Gcreate(h_file, "/Multipoles", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+
+  const hid_t h_space = H5Screate(H5S_SIMPLE);
+  const hid_t h_space2 = H5Screate(H5S_SIMPLE);
+  hsize_t shape[2] = {s->nr_cells, 3};
+  hsize_t shape2[1] = {s->nr_cells};
+  H5Sset_extent_simple(h_space, 2, shape, NULL);
+  H5Sset_extent_simple(h_space2, 1, shape2, NULL);
+
+  const hid_t h_data =
+      H5Dcreate(h_grp, "Coordinates", H5T_NATIVE_DOUBLE, h_space, H5P_DEFAULT,
+                H5P_DEFAULT, H5P_DEFAULT);
+
+  const hid_t h_data2 =
+      H5Dcreate(h_grp, "Potential", H5T_NATIVE_DOUBLE, h_space2, H5P_DEFAULT,
+                H5P_DEFAULT, H5P_DEFAULT);
+
+  double *temp = malloc(s->nr_cells * 3 * sizeof(double));
+  double *temp2 = malloc(s->nr_cells * 1 * sizeof(double));
+  for (int i = 0; i < s->nr_cells; ++i) {
+    temp[i * 3 + 0] = s->multipoles_top[i].CoM[0];
+    temp[i * 3 + 1] = s->multipoles_top[i].CoM[1];
+    temp[i * 3 + 2] = s->multipoles_top[i].CoM[2];
+    temp2[i] = s->multipoles_top[i].pot.F_000;
+  }
+
+  H5Dwrite(h_data, H5T_NATIVE_DOUBLE, h_space, H5S_ALL, H5P_DEFAULT, temp);
+  H5Dwrite(h_data2, H5T_NATIVE_DOUBLE, h_space2, H5S_ALL, H5P_DEFAULT, temp2);
+
+  free(temp);
+  free(temp2);
+  H5Dclose(h_data);
+  H5Dclose(h_data2);
+  H5Sclose(h_space);
+  H5Sclose(h_space2);
+  H5Gclose(h_grp);
+  H5Fclose(h_file);
+}
diff --git a/src/space.h b/src/space.h
index c5f588563e5a9fb4b6cb73ac1446514f8149794f..86dc6ed5d56a5328e9e49555ac7d4b2bf5990c5e 100644
--- a/src/space.h
+++ b/src/space.h
@@ -221,5 +221,6 @@ void space_check_timesteps(struct space *s);
 void space_replicate(struct space *s, int replicate, int verbose);
 void space_reset_task_counters(struct space *s);
 void space_clean(struct space *s);
+void space_dump_multipoles(struct space *s);
 
 #endif /* SWIFT_SPACE_H */
diff --git a/src/task.c b/src/task.c
index e8c35e49a57595a6415c60ce7071ae1c0e3f09b7..1bb3df7ea9817488f6391ef2bff7686835deed46 100644
--- a/src/task.c
+++ b/src/task.c
@@ -323,7 +323,6 @@ void task_unlock(struct task *t) {
       cell_munlocktree(ci);
       break;
 
-    case task_type_grav_top_level:
     case task_type_grav_long_range:
     case task_type_grav_mm:
       cell_munlocktree(ci);
@@ -442,7 +441,6 @@ int task_lock(struct task *t) {
       }
       break;
 
-    case task_type_grav_top_level:
     case task_type_grav_long_range:
     case task_type_grav_mm:
       /* Lock the m-poles */