diff --git a/examples/main.c b/examples/main.c
index ee1253062409ec2e787e064a5fb50da2c830d35d..672683f13c3c53e1b456f6eb65330dcf38233f2e 100644
--- a/examples/main.c
+++ b/examples/main.c
@@ -504,6 +504,8 @@ int main(int argc, char *argv[]) {
     fflush(stdout);
   }
 
+  periodic = 0;
+
 #ifdef SWIFT_DEBUG_CHECKS
   /* Check once and for all that we don't have unwanted links */
   if (!with_stars) {
diff --git a/src/cell.c b/src/cell.c
index f85e4dbd2a71033b10852bc65a97b8eec6bf75f9..e619ddf246d46d4258dd66e6f9301eaf2dca7b94 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -1290,41 +1290,14 @@ void cell_clean(struct cell *c) {
     if (c->progeny[k]) cell_clean(c->progeny[k]);
 }
 
-/**
- * @brief Checks whether a given cell needs drifting or not.
- *
- * @param c the #cell.
- * @param e The #engine (holding current time information).
- *
- * @return 1 If the cell needs drifting, 0 otherwise.
- */
-int cell_is_drift_needed(struct cell *c, const struct engine *e) {
-
-  /* Do we have at least one active particle in the cell ?*/
-  if (cell_is_active(c, e)) return 1;
-
-  /* Loop over the pair tasks that involve this cell */
-  for (struct link *l = c->density; l != NULL; l = l->next) {
-
-    if (l->t->type != task_type_pair && l->t->type != task_type_sub_pair)
-      continue;
-
-    /* Is the other cell in the pair active ? */
-    if ((l->t->ci == c && cell_is_active(l->t->cj, e)) ||
-        (l->t->cj == c && cell_is_active(l->t->ci, e)))
-      return 1;
-  }
-
-  /* No neighbouring cell has active particles. Drift not necessary */
-  return 0;
-}
-
 /**
  * @brief Clear the drift flags on the given cell.
  */
 void cell_clear_drift_flags(struct cell *c, void *data) {
   c->do_drift = 0;
   c->do_sub_drift = 0;
+  c->do_grav_drift = 0;
+  c->do_grav_sub_drift = 0;
 }
 
 /**
@@ -1359,13 +1332,32 @@ void cell_activate_drift_part(struct cell *c, struct scheduler *s) {
  */
 void cell_activate_drift_gpart(struct cell *c, struct scheduler *s) {
 
-  scheduler_activate(s, c->super->drift_gpart);
+  /* If this cell is already marked for drift, quit early. */
+  if (c->do_grav_drift) return;
+
+  /* Mark this cell for drifting. */
+  c->do_grav_drift = 1;
+
+  /* Set the do_grav_sub_drifts all the way up and activate the super drift
+     if this has not yet been done. */
+  if (c == c->super) {
+    scheduler_activate(s, c->drift_gpart);
+  } else {
+    for (struct cell *parent = c->parent;
+         parent != NULL && !parent->do_grav_sub_drift;
+         parent = parent->parent) {
+      parent->do_grav_sub_drift = 1;
+      if (parent == c->super) {
+        scheduler_activate(s, parent->drift_gpart);
+        break;
+      }
+    }
+  }
 }
 
 /**
  * @brief Activate the sorts up a cell hierarchy.
  */
-
 void cell_activate_sorts_up(struct cell *c, struct scheduler *s) {
   if (c == c->super) {
     scheduler_activate(s, c->sorts);
@@ -1409,7 +1401,8 @@ void cell_activate_sorts(struct cell *c, int sid, struct scheduler *s) {
 }
 
 /**
- * @brief Traverse a sub-cell task and activate the sort tasks along the way.
+ * @brief Traverse a sub-cell task and activate the drift and sort tasks along
+ * the way.
  */
 void cell_activate_subcell_tasks(struct cell *ci, struct cell *cj,
                                  struct scheduler *s) {
@@ -1676,6 +1669,132 @@ void cell_activate_subcell_tasks(struct cell *ci, struct cell *cj,
   }
 }
 
+/**
+ * @brief Traverse a sub-cell task and activate the gravity drift tasks
+ */
+void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj,
+                                      struct scheduler *s) {
+  /* 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_crit = e->gravity_properties->theta_crit;
+
+  /* Self interaction? */
+  if (cj == NULL) {
+
+    /* Do anything? */
+    if (!cell_is_active(ci, e)) return;
+
+    /* Recurse? */
+    if (ci->split) {
+
+      /* Loop over all progenies and pairs of progenies */
+      for (int j = 0; j < 8; j++) {
+        if (ci->progeny[j] != NULL) {
+          cell_activate_subcell_grav_tasks(ci->progeny[j], NULL, s);
+          for (int k = j + 1; k < 8; k++)
+            if (ci->progeny[k] != NULL)
+              cell_activate_subcell_grav_tasks(ci->progeny[j], ci->progeny[k],
+                                               s);
+        }
+      }
+    } else {
+
+      /* We have reached the bottom of the tree: activate gpart drift */
+      cell_activate_drift_gpart(ci, s);
+    }
+  }
+
+  /* Pair interaction */
+  else {
+
+    /* Anything to do here? */
+    if (!cell_is_active(ci, e) && !cell_is_active(cj, e)) return;
+
+    /* 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_multipole_accept(multi_i, multi_j, theta_crit, r2)) {
+
+      /* Ok, no need to drift anything */
+      return;
+    }
+    /* Otherwise, activate the gpart drifts if we are at the bottom. */
+    else if (!ci->split && !cj->split) {
+
+      /* Activate the drifts if the cells are local. */
+      if (cell_is_active(ci, e) || cell_is_active(cj, e)) {
+        if (ci->nodeID == engine_rank) cell_activate_drift_gpart(ci, s);
+        if (cj->nodeID == engine_rank) cell_activate_drift_gpart(cj, s);
+      }
+    }
+    /* Ok, we can still recurse */
+    else {
+
+      if (ri_max > rj_max) {
+        if (ci->split) {
+
+          /* Loop over ci's children */
+          for (int k = 0; k < 8; k++) {
+            if (ci->progeny[k] != NULL)
+              cell_activate_subcell_grav_tasks(ci->progeny[k], cj, s);
+          }
+
+        } else if (cj->split) {
+
+          /* Loop over cj's children */
+          for (int k = 0; k < 8; k++) {
+            if (cj->progeny[k] != NULL)
+              cell_activate_subcell_grav_tasks(ci, cj->progeny[k], s);
+          }
+
+        } else {
+          error("Fundamental error in the logic");
+        }
+      } else if (rj_max >= ri_max) {
+        if (cj->split) {
+
+          /* Loop over cj's children */
+          for (int k = 0; k < 8; k++) {
+            if (cj->progeny[k] != NULL)
+              cell_activate_subcell_grav_tasks(ci, cj->progeny[k], s);
+          }
+
+        } else if (ci->split) {
+
+          /* Loop over ci's children */
+          for (int k = 0; k < 8; k++) {
+            if (ci->progeny[k] != NULL)
+              cell_activate_subcell_grav_tasks(ci->progeny[k], cj, s);
+          }
+
+        } else {
+          error("Fundamental error in the logic");
+        }
+      }
+    }
+  }
+}
+
 /**
  * @brief Un-skips all the tasks associated with a given cell and checks
  * if the space needs to be rebuilt.
@@ -1701,8 +1820,13 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) {
         (cj != NULL && cell_is_active(cj, e) && cj->nodeID == engine_rank)) {
       scheduler_activate(s, t);
 
-      /* Set the correct sorting flags */
-      if (t->type == task_type_pair) {
+      /* Activate hydro drift */
+      if (t->type == task_type_self) {
+        if (ci->nodeID == engine_rank) cell_activate_drift_part(ci, s);
+      }
+
+      /* Set the correct sorting flags and activate hydro drifts */
+      else if (t->type == task_type_pair) {
         /* Store some values. */
         atomic_or(&ci->requires_sorts, 1 << t->flags);
         atomic_or(&cj->requires_sorts, 1 << t->flags);
@@ -1863,9 +1987,10 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) {
       scheduler_activate(s, t);
 
       /* Set the drifting flags */
-      if (t->type == task_type_pair) {
-        cell_activate_drift_gpart(ci, s);
-        cell_activate_drift_gpart(cj, s);
+      if (t->type == task_type_self) {
+        cell_activate_subcell_grav_tasks(t->ci, NULL, s);
+      } else if (t->type == task_type_pair) {
+        cell_activate_subcell_grav_tasks(t->ci, t->cj, s);
       }
     }
   }
@@ -1955,7 +2080,7 @@ void cell_drift_part(struct cell *c, const struct engine *e, int force) {
 
   /* Check that we are actually going to move forward. */
   if (ti_current < ti_old_part) error("Attempt to drift to the past");
-#endif  // SWIFT_DEBUG_CHECKS
+#endif
 
   /* Are we not in a leaf ? */
   if (c->split && (force || c->do_sub_drift)) {
@@ -2040,8 +2165,9 @@ void cell_drift_part(struct cell *c, const struct engine *e, int force) {
  *
  * @param c The #cell.
  * @param e The #engine (to get ti_current).
+ * @param force Drift the particles irrespective of the #cell flags.
  */
-void cell_drift_gpart(struct cell *c, const struct engine *e) {
+void cell_drift_gpart(struct cell *c, const struct engine *e, int force) {
 
   const double timeBase = e->timeBase;
   const integertime_t ti_old_gpart = c->ti_old_gpart;
@@ -2053,11 +2179,19 @@ void cell_drift_gpart(struct cell *c, const struct engine *e) {
   const double dt = (ti_current - ti_old_gpart) * timeBase;
   float dx_max = 0.f, dx2_max = 0.f;
 
+  /* Drift irrespective of cell flags? */
+  force |= c->do_grav_drift;
+
+#ifdef SWIFT_DEBUG_CHECKS
+  /* Check that we only drift local cells. */
+  if (c->nodeID != engine_rank) error("Drifting a foreign cell is nope.");
+
   /* Check that we are actually going to move forward. */
   if (ti_current < ti_old_gpart) error("Attempt to drift to the past");
+#endif
 
   /* Are we not in a leaf ? */
-  if (c->split) {
+  if (c->split && (force || c->do_grav_sub_drift)) {
 
     /* Loop over the progeny and collect their data. */
     for (int k = 0; k < 8; k++)
@@ -2065,13 +2199,19 @@ void cell_drift_gpart(struct cell *c, const struct engine *e) {
         struct cell *cp = c->progeny[k];
 
         /* Recurse */
-        cell_drift_gpart(cp, e);
+        cell_drift_gpart(cp, e, force);
 
         /* Update */
         dx_max = max(dx_max, cp->dx_max_gpart);
       }
 
-  } else if (ti_current > ti_old_gpart) {
+    /* Store the values */
+    c->dx_max_gpart = dx_max;
+
+    /* Update the time of the last drift */
+    c->ti_old_gpart = ti_current;
+
+  } else if (!c->split && force && ti_current > ti_old_gpart) {
 
     /* Loop over all the g-particles in the cell */
     const size_t nr_gparts = c->gcount;
@@ -2111,16 +2251,16 @@ void cell_drift_gpart(struct cell *c, const struct engine *e) {
     /* Now, get the maximal particle motion from its square */
     dx_max = sqrtf(dx2_max);
 
-  } else {
+    /* Store the values */
+    c->dx_max_gpart = dx_max;
 
-    dx_max = c->dx_max_gpart;
+    /* Update the time of the last drift */
+    c->ti_old_gpart = ti_current;
   }
 
-  /* Store the values */
-  c->dx_max_gpart = dx_max;
-
-  /* Update the time of the last drift */
-  c->ti_old_gpart = ti_current;
+  /* Clear the drift flags. */
+  c->do_grav_drift = 0;
+  c->do_grav_sub_drift = 0;
 }
 
 /**
diff --git a/src/cell.h b/src/cell.h
index 82cda87444e60fde9eb4b9a6914c2ed1ba3a470d..657ff737ed8e1e53c2addb88a7e80961a11dbd8e 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -331,12 +331,18 @@ struct cell {
   /* Bit mask of sort directions that will be needed in the next timestep. */
   unsigned int requires_sorts;
 
-  /*! Does this cell need to be drifted? */
+  /*! Does this cell need to be drifted (hydro)? */
   char do_drift;
 
-  /*! Do any of this cell's sub-cells need to be drifted? */
+  /*! Do any of this cell's sub-cells need to be drifted (hydro)? */
   char do_sub_drift;
 
+  /*! Does this cell need to be drifted (gravity)? */
+  char do_grav_drift;
+
+  /*! Do any of this cell's sub-cells need to be drifted (gravity)? */
+  char do_grav_sub_drift;
+
   /*! Bit mask of sorts that need to be computed for this cell. */
   unsigned int do_sort;
 
@@ -390,17 +396,18 @@ void cell_check_part_drift_point(struct cell *c, void *data);
 void cell_check_gpart_drift_point(struct cell *c, void *data);
 void cell_check_multipole_drift_point(struct cell *c, void *data);
 void cell_reset_task_counters(struct cell *c);
-int cell_is_drift_needed(struct cell *c, const struct engine *e);
 int cell_unskip_tasks(struct cell *c, struct scheduler *s);
 void cell_set_super(struct cell *c, struct cell *super);
 void cell_drift_part(struct cell *c, const struct engine *e, int force);
-void cell_drift_gpart(struct cell *c, const struct engine *e);
+void cell_drift_gpart(struct cell *c, const struct engine *e, int force);
 void cell_drift_multipole(struct cell *c, const struct engine *e);
 void cell_drift_all_multipoles(struct cell *c, const struct engine *e);
 void cell_check_timesteps(struct cell *c);
 void cell_store_pre_drift_values(struct cell *c);
 void cell_activate_subcell_tasks(struct cell *ci, struct cell *cj,
                                  struct scheduler *s);
+void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj,
+                                      struct scheduler *s);
 void cell_activate_drift_part(struct cell *c, struct scheduler *s);
 void cell_activate_drift_gpart(struct cell *c, struct scheduler *s);
 void cell_activate_sorts(struct cell *c, int sid, struct scheduler *s);
diff --git a/src/engine.c b/src/engine.c
index 41b9ad4fa87b438f3179a83a1523ae5c70bd493b..8a66b56007811e2a1327f9b64fddfb478b9e650f 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -2653,16 +2653,32 @@ void engine_marktasks_mapper(void *map_data, int num_elements,
     struct task *t = &tasks[ind];
 
     /* Single-cell task? */
-    if (t->type == task_type_self || t->type == task_type_ghost ||
-        t->type == task_type_extra_ghost || t->type == task_type_cooling ||
-        t->type == task_type_sourceterms || t->type == task_type_sub_self) {
+    if (t->type == task_type_self || t->type == task_type_sub_self) {
+
+      /* Local pointer. */
+      struct cell *ci = t->ci;
+
+      if (ci->nodeID != engine_rank) error("Non-local self task found");
 
       /* Set this task's skip. */
-      if (cell_is_active(t->ci, e)) scheduler_activate(s, t);
+      if (cell_is_active(ci, e)) scheduler_activate(s, t);
 
+      /* Activate the hydro drift */
+      if (t->type == task_type_self && t->subtype == task_subtype_density) {
+        cell_activate_drift_part(ci, s);
+      }
+      /* Activate the gravity drift */
+      else if (t->type == task_type_self && t->subtype == task_subtype_grav) {
+        cell_activate_subcell_grav_tasks(t->ci, NULL, s);
+      }
       /* Store current values of dx_max and h_max. */
-      if (t->type == task_type_sub_self && t->subtype == task_subtype_density) {
-        cell_activate_subcell_tasks(t->ci, NULL, s);
+      else if (t->type == task_type_sub_self &&
+               t->subtype == task_subtype_density) {
+        cell_activate_subcell_tasks(ci, NULL, s);
+
+      } else if (t->type == task_type_sub_self &&
+                 t->subtype == task_subtype_grav) {
+        error("Invalid task sub-type encountered");
       }
     }
 
@@ -2673,34 +2689,42 @@ void engine_marktasks_mapper(void *map_data, int num_elements,
       struct cell *ci = t->ci;
       struct cell *cj = t->cj;
 
-      /* If this task does not involve any active cells, skip it. */
-      if (!cell_is_active(t->ci, e) && !cell_is_active(t->cj, e)) continue;
-
       /* Only activate tasks that involve a local active cell. */
       if ((cell_is_active(ci, e) && ci->nodeID == engine_rank) ||
-          (cj != NULL && cell_is_active(cj, e) && cj->nodeID == engine_rank)) {
+          (cell_is_active(cj, e) && cj->nodeID == engine_rank)) {
         scheduler_activate(s, t);
 
         /* Set the correct sorting flags */
         if (t->type == task_type_pair && t->subtype == task_subtype_density) {
+
           /* Store some values. */
           atomic_or(&ci->requires_sorts, 1 << t->flags);
           atomic_or(&cj->requires_sorts, 1 << t->flags);
           ci->dx_max_sort_old = ci->dx_max_sort;
           cj->dx_max_sort_old = cj->dx_max_sort;
 
-          /* Activate the drift tasks. */
+          /* Activate the hydro drift tasks. */
           if (ci->nodeID == engine_rank) cell_activate_drift_part(ci, s);
           if (cj->nodeID == engine_rank) cell_activate_drift_part(cj, s);
 
           /* Check the sorts and activate them if needed. */
           cell_activate_sorts(ci, t->flags, s);
           cell_activate_sorts(cj, t->flags, s);
+
+        } else if (t->type == task_type_pair &&
+                   t->subtype == task_subtype_grav) {
+          /* Activate the gravity drift */
+          cell_activate_subcell_grav_tasks(t->ci, t->cj, s);
         }
+
         /* Store current values of dx_max and h_max. */
         else if (t->type == task_type_sub_pair &&
                  t->subtype == task_subtype_density) {
           cell_activate_subcell_tasks(t->ci, t->cj, s);
+
+        } else if (t->type == task_type_sub_pair &&
+                   t->subtype == task_subtype_grav) {
+          error("Invalid task sub-type encountered");
         }
       }
 
@@ -2833,20 +2857,24 @@ void engine_marktasks_mapper(void *map_data, int num_elements,
       }
     }
 
-    /* Kick/Drift/init ? */
-    if (t->type == task_type_kick1 || t->type == task_type_kick2 ||
-        t->type == task_type_drift_part || t->type == task_type_drift_gpart ||
-        t->type == task_type_init_grav) {
+    /* Kick/init ? */
+    else if (t->type == task_type_kick1 || t->type == task_type_kick2 ||
+             t->type == task_type_init_grav) {
       if (cell_is_active(t->ci, e)) scheduler_activate(s, t);
     }
 
-    /* Gravity ? */
+    /* Hydro ghost tasks ? */
+    else if (t->type == task_type_ghost || t->type == task_type_extra_ghost) {
+      if (cell_is_active(t->ci, e)) scheduler_activate(s, t);
+    }
+
+    /* Gravity stuff ? */
     else if (t->type == task_type_grav_down ||
              t->type == task_type_grav_long_range) {
       if (cell_is_active(t->ci, e)) scheduler_activate(s, t);
     }
 
-    /* Periodic gravity ? */
+    /* Periodic gravity stuff (Note this is not linked to a cell) ? */
     else if (t->type == task_type_grav_top_level ||
              t->type == task_type_grav_ghost) {
       scheduler_activate(s, t);
@@ -2859,6 +2887,11 @@ void engine_marktasks_mapper(void *map_data, int num_elements,
       t->ci->s_updated = 0;
       if (cell_is_active(t->ci, e)) scheduler_activate(s, t);
     }
+
+    /* Subgrid tasks */
+    else if (t->type == task_type_cooling || t->type == task_type_sourceterms) {
+      if (cell_is_active(t->ci, e)) scheduler_activate(s, t);
+    }
   }
 }
 
@@ -3723,7 +3756,7 @@ void engine_do_drift_all_mapper(void *map_data, int num_elements,
       cell_drift_part(c, e, 1);
 
       /* Drift all the g-particles */
-      cell_drift_gpart(c, e);
+      cell_drift_gpart(c, e, 1);
 
       /* Drift the multipoles */
       if (e->policy & engine_policy_self_gravity)
diff --git a/src/multipole.h b/src/multipole.h
index 255be3e538dcf50ced1a62a5fa9fef2a93f917da..03b6d134c865ed217f1c2fe82453de9f4a3406a5 100644
--- a/src/multipole.h
+++ b/src/multipole.h
@@ -213,18 +213,18 @@ INLINE static void gravity_reset(struct gravity_tensors *m) {
  */
 INLINE static void gravity_drift(struct gravity_tensors *m, double dt) {
 
-  const double dx = m->m_pole.vel[0] * dt;
-  const double dy = m->m_pole.vel[1] * dt;
-  const double dz = m->m_pole.vel[2] * dt;
+  /* const double dx = m->m_pole.vel[0] * dt; */
+  /* const double dy = m->m_pole.vel[1] * dt; */
+  /* const double dz = m->m_pole.vel[2] * dt; */
 
   /* Move the whole thing according to bulk motion */
-  m->CoM[0] += dx;
-  m->CoM[1] += dy;
-  m->CoM[2] += dz;
+  /* m->CoM[0] += dx; */
+  /* m->CoM[1] += dy; */
+  /* m->CoM[2] += dz; */
 
   /* Conservative change in maximal radius containing all gpart */
   /* MATTHIEU: Use gpart->x_diff here ? */
-  m->r_max += sqrt(dx * dx + dy * dy + dz * dz);
+  /* m->r_max += sqrt(dx * dx + dy * dy + dz * dz); */
 }
 
 /**
diff --git a/src/runner.c b/src/runner.c
index bb5c5cb91c7ca0ab0040f1ff637e124b1c673aeb..eb968f58440e678df4ac4df1e83ee734100b65f5 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -903,7 +903,7 @@ void runner_do_drift_gpart(struct runner *r, struct cell *c, int timer) {
 
   TIMER_TIC;
 
-  cell_drift_gpart(c, r->e);
+  cell_drift_gpart(c, r->e, 0);
 
   if (timer) TIMER_TOC(timer_drift_gpart);
 }