diff --git a/src/engine.c b/src/engine.c
index 827778100fcdea0a89afb210677bf26fc9acd8b8..14dd0f068518264fe03d348aae5b019941e67353 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -1639,8 +1639,10 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts,
 
 /**
  * @brief Constructs the top-level tasks for the short-range gravity
- * interactions.
+ * and long-range gravity interactions.
  *
+ * - One FTT task per MPI rank.
+ * - Multiple gravity ghosts for dependencies.
  * - All top-cells get a self task.
  * - All pairs within range according to the multipole acceptance
  *   criterion get a pair task.
@@ -1653,6 +1655,7 @@ void engine_make_self_gravity_tasks(struct engine *e) {
   struct scheduler *sched = &e->sched;
   const int nodeID = e->nodeID;
   const int periodic = s->periodic;
+  const double dim[3] = {s->dim[0], s->dim[1], s->dim[2]};
   const int cdim[3] = {s->cdim[0], s->cdim[1], s->cdim[2]};
   const int cdim_ghost[3] = {s->cdim[0] / 4 + 1, s->cdim[1] / 4 + 1,
                              s->cdim[2] / 4 + 1};
@@ -1704,7 +1707,7 @@ void engine_make_self_gravity_tasks(struct engine *e) {
         scheduler_addtask(sched, task_type_self, task_subtype_grav, 0, 0, ci,
                           NULL);
 
-        /* Deal with periodicity dependencies */
+        /* Deal with dependencies of the FFT mesh calculation */
         const int ghost_id = cell_getid(cdim_ghost, i / 4, j / 4, k / 4);
         if (ghost_id > n_ghosts) error("Invalid ghost_id");
         if (periodic) {
@@ -1731,8 +1734,9 @@ void engine_make_self_gravity_tasks(struct engine *e) {
               if (cj->nodeID != nodeID) continue;  // MATTHIEU
 
               /* Are the cells to close for a MM interaction ? */
-              if (!gravity_multipole_accept(ci->multipole, cj->multipole,
-                                            theta_crit_inv, 1)) {
+              if (!gravity_multipole_accept_rebuild(
+                      ci->multipole, cj->multipole, theta_crit_inv, periodic,
+                      dim)) {
 
                 scheduler_addtask(sched, task_type_pair, task_subtype_grav, 0,
                                   0, ci, cj);
@@ -1746,6 +1750,11 @@ void engine_make_self_gravity_tasks(struct engine *e) {
   if (periodic) free(ghosts);
 }
 
+/**
+ * @brief Constructs the top-level tasks for the external gravity.
+ *
+ * @param e The #engine.
+ */
 void engine_make_external_gravity_tasks(struct engine *e) {
 
   struct space *s = e->s;
diff --git a/src/multipole.h b/src/multipole.h
index 23f5194a30b7316aac15073cba36dc404efa21c1..8e8ecae54e5dedde1a789d2a5469b6e39d853b18 100644
--- a/src/multipole.h
+++ b/src/multipole.h
@@ -2636,29 +2636,75 @@ INLINE static void gravity_L2P(const struct grav_tensor *lb,
 
 /**
  * @brief Checks whether a cell-cell interaction can be appromixated by a M-M
- * interaction.
+ * interaction using the CoM and cell radius at rebuild.
+ *
+ * We use the multipole acceptance criterion of Dehnen, 2002, JCoPh, Volume 179,
+ * Issue 1, pp.27-42, equation 10.
+ *
+ * @param ma The #multipole of the first #cell.
+ * @param mb The #multipole of the second #cell.
+ * @param theta_crit_inv The inverse of the critical opening angle.
+ * @param periodic Are we using periodic boundary conditions ?
+ * @param dim The dimensions of the box.
+ */
+__attribute__((always_inline)) INLINE static int
+gravity_multipole_accept_rebuild(const struct gravity_tensors *ma,
+                                 const struct gravity_tensors *mb,
+                                 double theta_crit_inv, int periodic,
+                                 const double dim[3]) {
+
+  const double r_crit_a = ma->r_max_rebuild * theta_crit_inv;
+  const double r_crit_b = mb->r_max_rebuild * theta_crit_inv;
+
+  double dx = ma->CoM_rebuild[0] - mb->CoM_rebuild[0];
+  double dy = ma->CoM_rebuild[1] - mb->CoM_rebuild[1];
+  double dz = ma->CoM_rebuild[2] - mb->CoM_rebuild[2];
+
+  /* Apply BC */
+  if (periodic) {
+    dx = nearest(dx, dim[0]);
+    dy = nearest(dy, dim[1]);
+    dz = nearest(dz, dim[2]);
+  }
+
+  const double r2 = dx * dx + dy * dy + dz * dz;
+
+  // MATTHIEU: Make this mass-dependent ?
+
+  /* Multipole acceptance criterion (Dehnen 2002, eq.10) */
+  return (r2 > (r_crit_a + r_crit_b) * (r_crit_a + r_crit_b));
+}
+
+/**
+ * @brief Checks whether a cell-cell interaction can be appromixated by a M-M
+ * interaction using the CoM and cell radius at the current time.
+ *
+ * We use the multipole acceptance criterion of Dehnen, 2002, JCoPh, Volume 179,
+ * Issue 1, pp.27-42, equation 10.
  *
  * @param ma The #multipole of the first #cell.
  * @param mb The #multipole of the second #cell.
  * @param theta_crit_inv The inverse of the critical opening angle.
- * @param rebuild Are we using the current value of CoM or the ones from
- * the last rebuild ?
+ * @param periodic Are we using periodic boundary conditions ?
+ * @param dim The dimensions of the box.
  */
 __attribute__((always_inline)) INLINE static int gravity_multipole_accept(
     const struct gravity_tensors *ma, const struct gravity_tensors *mb,
-    double theta_crit_inv, int rebuild) {
-
-  const double r_crit_a =
-      (rebuild ? ma->r_max_rebuild : ma->r_max) * theta_crit_inv;
-  const double r_crit_b =
-      (rebuild ? mb->r_max_rebuild : mb->r_max) * theta_crit_inv;
-
-  const double dx = rebuild ? ma->CoM_rebuild[0] - mb->CoM_rebuild[0]
-                            : ma->CoM[0] - mb->CoM[0];
-  const double dy = rebuild ? ma->CoM_rebuild[1] - mb->CoM_rebuild[1]
-                            : ma->CoM[1] - mb->CoM[1];
-  const double dz = rebuild ? ma->CoM_rebuild[2] - mb->CoM_rebuild[2]
-                            : ma->CoM[2] - mb->CoM[2];
+    double theta_crit_inv, int periodic, const double dim[3]) {
+
+  const double r_crit_a = ma->r_max * theta_crit_inv;
+  const double r_crit_b = mb->r_max * theta_crit_inv;
+
+  double dx = ma->CoM[0] - mb->CoM[0];
+  double dy = ma->CoM[1] - mb->CoM[1];
+  double dz = ma->CoM[2] - mb->CoM[2];
+
+  /* Apply BC */
+  if (periodic) {
+    dx = nearest(dx, dim[0]);
+    dy = nearest(dy, dim[1]);
+    dz = nearest(dz, dim[2]);
+  }
 
   const double r2 = dx * dx + dy * dy + dz * dz;
 
diff --git a/src/runner_doiact_grav.h b/src/runner_doiact_grav.h
index a66cc5e0c9ed241aba3bb1b4329016b8e505e280..0a5915cd10a170171378d708f3f0cda54c34e9b0 100644
--- a/src/runner_doiact_grav.h
+++ b/src/runner_doiact_grav.h
@@ -415,6 +415,9 @@ void runner_dopair_grav(struct runner *r, struct cell *ci, struct cell *cj,
 
   /* Some constants */
   const struct engine *e = r->e;
+  const struct space *s = e->s;
+  const int periodic = s->periodic;
+  const double dim[3] = {s->dim[0], s->dim[1], s->dim[2]};
   const struct gravity_props *props = e->gravity_properties;
   const double theta_crit_inv = props->theta_crit_inv;
 
@@ -464,7 +467,8 @@ void runner_dopair_grav(struct runner *r, struct cell *ci, struct cell *cj,
 
   /* Can we use M-M interactions ? */
   if (gravity_multipole_accept(ci->multipole, cj->multipole, theta_crit_inv,
-                               0)) {
+                               periodic, dim)) {
+
     /* MATTHIEU: make a symmetric M-M interaction function ! */
     runner_dopair_grav_mm(r, ci, cj);
     runner_dopair_grav_mm(r, cj, ci);
@@ -617,6 +621,9 @@ void runner_do_grav_long_range(struct runner *r, struct cell *ci, int timer) {
 
   /* Some constants */
   const struct engine *e = r->e;
+  const struct space *s = e->s;
+  const int periodic = s->periodic;
+  const double dim[3] = {s->dim[0], s->dim[1], s->dim[2]};
   const struct gravity_props *props = e->gravity_properties;
   const double theta_crit_inv = props->theta_crit_inv;
 
@@ -627,7 +634,7 @@ void runner_do_grav_long_range(struct runner *r, struct cell *ci, int timer) {
   const int nr_cells = e->s->nr_cells;
 
   /* Anything to do here? */
-  if (!cell_is_active(ci, e)) return;  // MATTHIEU (should never happen)
+  if (!cell_is_active(ci, e)) return;
 
   /* Check multipole has been drifted */
   if (ci->ti_old_multipole != e->ti_current)
@@ -645,14 +652,14 @@ void runner_do_grav_long_range(struct runner *r, struct cell *ci, int timer) {
 
     /* Check the multipole acceptance criterion */
     if (gravity_multipole_accept(ci->multipole, cj->multipole, theta_crit_inv,
-                                 0)) {
+                                 periodic, dim)) {
 
       /* Go for a (non-symmetric) M-M calculation */
       runner_dopair_grav_mm(r, ci, cj);
     }
     /* Is the criterion violated now but was OK at the last rebuild ? */
-    else if (gravity_multipole_accept(ci->multipole, cj->multipole,
-                                      theta_crit_inv, 1)) {
+    else if (gravity_multipole_accept_rebuild(ci->multipole, cj->multipole,
+                                              theta_crit_inv, periodic, dim)) {
 
       /* Alright, we have to take charge of that pair in a different way. */
       // MATTHIEU: We should actually open the tree-node here and recurse.
diff --git a/src/scheduler.c b/src/scheduler.c
index b07c403e4ecd960b22b51f24372ca0a3420a453f..76db1f2a279828800862629340598857c99e306f 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -682,7 +682,7 @@ static void scheduler_splittask_gravity(struct task *t, struct scheduler *s) {
           /* convert to a self-subtask. */
           t->type = task_type_sub_self;
 
-          /* Make sure we have a drift task (MATTHIEU temp. fix) */
+          /* Make sure we have a drift task */
           lock_lock(&ci->lock);
           if (ci->drift_gpart == NULL)
             ci->drift_gpart = scheduler_addtask(