diff --git a/src/cell.c b/src/cell.c
index a2e55e3c0194baf2ae6509317b243f5304bfdb70..44aec0b50a9158d9d5d0c29e48bfde4902e52e27 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -1850,6 +1850,26 @@ void cell_activate_subcell_hydro_tasks(struct cell *ci, struct cell *cj,
   } /* Otherwise, pair interation */
 }
 
+void cell_activate_grav_mm_task(struct cell *ci, struct cell *cj,
+                                struct scheduler *s) {
+  /* Some constants */
+  const struct engine *e = s->space->e;
+
+  /* Anything to do here? */
+  if (!cell_is_active_gravity(ci, e) && !cell_is_active_gravity(cj, e))
+    error("Inactive MM task being activated");
+
+  /* Atomically drift the multipole in ci */
+  lock_lock(&ci->mlock);
+  if (ci->ti_old_multipole < e->ti_current) cell_drift_multipole(ci, e);
+  if (lock_unlock(&ci->mlock) != 0) error("Impossible to unlock m-pole");
+
+  /* Atomically drift the multipole in cj */
+  lock_lock(&cj->mlock);
+  if (cj->ti_old_multipole < e->ti_current) cell_drift_multipole(cj, e);
+  if (lock_unlock(&cj->mlock) != 0) error("Impossible to unlock m-pole");
+}
+
 /**
  * @brief Traverse a sub-cell task and activate the gravity drift tasks that
  * are required by a self gravity task.
@@ -1863,9 +1883,6 @@ void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj,
   /* Some constants */
   const struct space *sp = s->space;
   const struct engine *e = sp->e;
-  const int periodic = sp->periodic;
-  const double dim[3] = {sp->dim[0], sp->dim[1], sp->dim[2]};
-  const double theta_crit2 = e->gravity_properties->theta_crit2;
 
   /* Self interaction? */
   if (cj == NULL) {
@@ -1911,27 +1928,8 @@ void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj,
     if (cj->ti_old_multipole < e->ti_current) cell_drift_multipole(cj, e);
     if (lock_unlock(&cj->mlock) != 0) error("Impossible to unlock m-pole");
 
-    /* Recover the multipole information */
-    struct gravity_tensors *const multi_i = ci->multipole;
-    struct gravity_tensors *const multi_j = cj->multipole;
-    const double ri_max = multi_i->r_max;
-    const double rj_max = multi_j->r_max;
-
-    /* Get the distance between the CoMs */
-    double dx = multi_i->CoM[0] - multi_j->CoM[0];
-    double dy = multi_i->CoM[1] - multi_j->CoM[1];
-    double dz = multi_i->CoM[2] - multi_j->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;
-
     /* Can we use multipoles ? */
-    if (gravity_M2L_accept(multi_i->r_max, multi_j->r_max, theta_crit2, r2)) {
+    if (cell_can_use_pair_mm(ci, cj, e, sp)) {
 
       /* Ok, no need to drift anything */
       return;
@@ -1948,6 +1946,12 @@ void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj,
     /* Ok, we can still recurse */
     else {
 
+      /* Recover the multipole information */
+      struct gravity_tensors *const multi_i = ci->multipole;
+      struct gravity_tensors *const multi_j = cj->multipole;
+      const double ri_max = multi_i->r_max;
+      const double rj_max = multi_j->r_max;
+
       if (ri_max > rj_max) {
         if (ci->split) {
 
@@ -2216,22 +2220,27 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
     struct task *t = l->t;
     struct cell *ci = t->ci;
     struct cell *cj = t->cj;
+    const int ci_nodeID = ci->nodeID;
+    const int cj_nodeID = (cj != NULL) ? cj->nodeID : -1;
     const int ci_active = cell_is_active_gravity(ci, e);
     const int cj_active = (cj != NULL) ? cell_is_active_gravity(cj, e) : 0;
 
     /* Only activate tasks that involve a local active cell. */
-    if ((ci_active && ci->nodeID == nodeID) ||
-        (cj_active && cj->nodeID == nodeID)) {
+    if ((ci_active && ci_nodeID == nodeID) ||
+        (cj_active && cj_nodeID == nodeID)) {
       scheduler_activate(s, t);
 
       /* Set the drifting flags */
       if (t->type == task_type_self &&
           t->subtype == task_subtype_external_grav) {
-        cell_activate_subcell_external_grav_tasks(t->ci, s);
+        cell_activate_subcell_external_grav_tasks(ci, s);
       } else if (t->type == task_type_self && t->subtype == task_subtype_grav) {
-        cell_activate_subcell_grav_tasks(t->ci, NULL, s);
+        cell_activate_subcell_grav_tasks(ci, NULL, s);
       } else if (t->type == task_type_pair) {
-        cell_activate_subcell_grav_tasks(t->ci, t->cj, s);
+        cell_activate_subcell_grav_tasks(ci, cj, s);
+      } else if (t->type == task_type_grav_mm) {
+        cell_activate_grav_mm_task(ci, cj, s);
+        scheduler_activate(s, t);
       }
     }
 
@@ -2239,7 +2248,7 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
 
 #ifdef WITH_MPI
       /* Activate the send/recv tasks. */
-      if (ci->nodeID != nodeID) {
+      if (ci_nodeID != nodeID) {
 
         /* If the local cell is active, receive data from the foreign cell. */
         if (cj_active) {
@@ -2252,7 +2261,7 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
         /* Is the foreign cell active and will need stuff from us? */
         if (ci_active) {
 
-          scheduler_activate_send(s, cj->send_grav, ci->nodeID);
+          scheduler_activate_send(s, cj->send_grav, ci_nodeID);
 
           /* Drift the cell which will be sent at the level at which it is
              sent, i.e. drift the cell specified in the send task (l->t)
@@ -2261,9 +2270,9 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
         }
 
         /* If the local cell is active, send its ti_end values. */
-        if (cj_active) scheduler_activate_send(s, cj->send_ti, ci->nodeID);
+        if (cj_active) scheduler_activate_send(s, cj->send_ti, ci_nodeID);
 
-      } else if (cj->nodeID != nodeID) {
+      } else if (cj_nodeID != nodeID) {
 
         /* If the local cell is active, receive data from the foreign cell. */
         if (ci_active) {
@@ -2276,7 +2285,7 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
         /* Is the foreign cell active and will need stuff from us? */
         if (cj_active) {
 
-          scheduler_activate_send(s, ci->send_grav, cj->nodeID);
+          scheduler_activate_send(s, ci->send_grav, cj_nodeID);
 
           /* Drift the cell which will be sent at the level at which it is
              sent, i.e. drift the cell specified in the send task (l->t)
@@ -2285,7 +2294,7 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
         }
 
         /* If the local cell is active, send its ti_end values. */
-        if (ci_active) scheduler_activate_send(s, ci->send_ti, cj->nodeID);
+        if (ci_active) scheduler_activate_send(s, ci->send_ti, cj_nodeID);
       }
 #endif
     }