diff --git a/examples/analyse_tasks.py b/examples/analyse_tasks.py
index 853013a61b1d1c4d5dcfe12756fa3ac0f3d39dd8..a72ee0ce637b6ac2da4b8b95dac5bacab3d40a99 100755
--- a/examples/analyse_tasks.py
+++ b/examples/analyse_tasks.py
@@ -52,10 +52,10 @@ infile = args.input
 
 #  Tasks and subtypes. Indexed as in tasks.h.
 TASKTYPES = ["none", "sort", "self", "pair", "sub_self", "sub_pair",
-             "init_grav", "ghost_in", "ghost", "ghost_out", "extra_ghost", "drift_part", "drift_gpart",
-             "end_force", "kick1", "kick2", "timestep", "send", "recv", "grav_top_level",
-             "grav_long_range", "grav_ghost_in", "grav_ghost_out", "grav_mm", "grav_down", "cooling",
-             "sourceterms", "count"]
+             "init_grav", "init_grav_out", "ghost_in", "ghost", "ghost_out", "extra_ghost", "drift_part", "drift_gpart",
+             "end_force", "kick1", "kick2", "timestep", "send", "recv", "grav_long_range", "grav_mm", "grav_down_in", 
+             "grav_down", "grav_mesh", "cooling", "sourceterms", "count"]
+
 SUBTYPES = ["none", "density", "gradient", "force", "grav", "external_grav",
             "tend", "xv", "rho", "gpart", "multipole", "spart", "count"]
 
diff --git a/examples/plot_tasks.py b/examples/plot_tasks.py
index a123249dea8acf10e27a60a92065404f9cae77ea..9eecf6f4ca15148f544ea48cb65c97cd3802a48d 100755
--- a/examples/plot_tasks.py
+++ b/examples/plot_tasks.py
@@ -110,10 +110,9 @@ pl.rcParams.update(PLOT_PARAMS)
 
 #  Tasks and subtypes. Indexed as in tasks.h.
 TASKTYPES = ["none", "sort", "self", "pair", "sub_self", "sub_pair",
-             "init_grav", "ghost_in", "ghost", "ghost_out", "extra_ghost", "drift_part", "drift_gpart",
-             "end_force", "kick1", "kick2", "timestep", "send", "recv", "grav_top_level",
-             "grav_long_range", "grav_ghost_in", "grav_ghost_out", "grav_mm", "grav_down", "cooling",
-             "sourceterms", "count"]
+             "init_grav", "init_grav_out", "ghost_in", "ghost", "ghost_out", "extra_ghost", "drift_part", "drift_gpart",
+             "end_force", "kick1", "kick2", "timestep", "send", "recv", "grav_long_range", "grav_mm", "grav_down_in", 
+             "grav_down", "grav_mesh", "cooling", "sourceterms", "count"]
 
 SUBTYPES = ["none", "density", "gradient", "force", "grav", "external_grav",
             "tend", "xv", "rho", "gpart", "multipole", "spart", "count"]
diff --git a/src/cell.c b/src/cell.c
index 236114efe08b156fecd246f8117d0e76e0826cde..8c4dafd960b95e17f0d2bc773bafa412502d3faf 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -2303,11 +2303,13 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
   if (c->nodeID == nodeID && cell_is_active_gravity(c, e)) {
 
     if (c->init_grav != NULL) scheduler_activate(s, c->init_grav);
+    if (c->init_grav_out != NULL) scheduler_activate(s, c->init_grav_out);
     if (c->kick1 != NULL) scheduler_activate(s, c->kick1);
     if (c->kick2 != NULL) scheduler_activate(s, c->kick2);
     if (c->timestep != NULL) scheduler_activate(s, c->timestep);
     if (c->end_force != NULL) scheduler_activate(s, c->end_force);
     if (c->grav_down != NULL) scheduler_activate(s, c->grav_down);
+    if (c->grav_down_in != NULL) scheduler_activate(s, c->grav_down_in);
     if (c->grav_mesh != NULL) scheduler_activate(s, c->grav_mesh);
     if (c->grav_long_range != NULL) scheduler_activate(s, c->grav_long_range);
   }
diff --git a/src/cell.h b/src/cell.h
index 62ac0d0535b49d3e0b3a3affdc645522c0b53659..05cc8d0eef7839526866411b0adf5a16c3113854 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -225,6 +225,9 @@ struct cell {
   /*! The multipole initialistation task */
   struct task *init_grav;
 
+  /*! Implicit task for the gravity initialisation */
+  struct task *init_grav_out;
+
   /*! Dependency implicit task for the ghost  (in->ghost->out)*/
   struct task *ghost_in;
 
@@ -258,6 +261,9 @@ struct cell {
   /*! Task computing long range non-periodic gravity interactions */
   struct task *grav_long_range;
 
+  /*! Implicit task for the down propagation */
+  struct task *grav_down_in;
+
   /*! Task propagating the mesh forces to the particles */
   struct task *grav_mesh;
 
diff --git a/src/engine.c b/src/engine.c
index 66de36764ac59b1f4a2c91d5dc3eb731bd101904..e90b662caeaea439890e40356c2e991f495b9e43 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -334,6 +334,12 @@ void engine_make_hierarchical_tasks_gravity(struct engine *e, struct cell *c) {
         c->grav_down = scheduler_addtask(s, task_type_grav_down,
                                          task_subtype_none, 0, 0, c, NULL);
 
+        /* Implicit tasks for the up and down passes */
+        c->init_grav_out = scheduler_addtask(s, task_type_init_grav_out,
+                                             task_subtype_none, 0, 1, c, NULL);
+        c->grav_down_in = scheduler_addtask(s, task_type_grav_down_in,
+                                            task_subtype_none, 0, 1, c, NULL);
+
         /* Gravity mesh force propagation */
         if (periodic)
           c->grav_mesh = scheduler_addtask(s, task_type_grav_mesh,
@@ -344,17 +350,41 @@ void engine_make_hierarchical_tasks_gravity(struct engine *e, struct cell *c) {
         scheduler_addunlock(s, c->init_grav, c->grav_long_range);
         scheduler_addunlock(s, c->grav_long_range, c->grav_down);
         scheduler_addunlock(s, c->grav_down, c->super->end_force);
+
+        scheduler_addunlock(s, c->init_grav, c->init_grav_out);
+        scheduler_addunlock(s, c->grav_down_in, c->grav_down);
       }
     }
 
-  } else { /* We are above the super-cell so need to go deeper */
+  }
 
-    /* Recurse. */
-    if (c->split)
-      for (int k = 0; k < 8; k++)
-        if (c->progeny[k] != NULL)
-          engine_make_hierarchical_tasks_gravity(e, c->progeny[k]);
+  /* We are below the super-cell */
+  else if (c->super_gravity != NULL) {
+
+    // MATTHIEU stop the recursion below the level where there are tasks
+
+    /* Local tasks only... */
+    if (c->nodeID == e->nodeID) {
+
+      if (is_self_gravity) {
+
+        c->init_grav_out = scheduler_addtask(s, task_type_init_grav_out,
+                                             task_subtype_none, 0, 1, c, NULL);
+
+        c->grav_down_in = scheduler_addtask(s, task_type_grav_down_in,
+                                            task_subtype_none, 0, 1, c, NULL);
+
+        scheduler_addunlock(s, c->parent->init_grav_out, c->init_grav_out);
+        scheduler_addunlock(s, c->grav_down_in, c->parent->grav_down_in);
+      }
+    }
   }
+
+  /* Recurse. */
+  if (c->split)
+    for (int k = 0; k < 8; k++)
+      if (c->progeny[k] != NULL)
+        engine_make_hierarchical_tasks_gravity(e, c->progeny[k]);
 }
 
 void engine_make_hierarchical_tasks_mapper(void *map_data, int num_elements,
@@ -2648,38 +2678,6 @@ void engine_count_and_link_tasks_mapper(void *map_data, int num_elements,
   }
 }
 
-/**
- * @brief Creates the dependency network for the gravity tasks of a given cell.
- *
- * @param sched The #scheduler.
- * @param gravity The gravity task to link.
- * @param c The cell.
- */
-static inline void engine_make_self_gravity_dependencies(
-    struct scheduler *sched, struct task *gravity, struct cell *c) {
-
-  /* init --> gravity --> grav_down --> kick */
-  scheduler_addunlock(sched, c->super_gravity->drift_gpart, gravity);
-  scheduler_addunlock(sched, c->super_gravity->init_grav, gravity);
-  scheduler_addunlock(sched, gravity, c->super_gravity->grav_down);
-}
-
-/**
- * @brief Creates the dependency network for the external gravity tasks of a
- * given cell.
- *
- * @param sched The #scheduler.
- * @param gravity The gravity task to link.
- * @param c The cell.
- */
-static inline void engine_make_external_gravity_dependencies(
-    struct scheduler *sched, struct task *gravity, struct cell *c) {
-
-  /* init --> external gravity --> kick */
-  scheduler_addunlock(sched, c->super_gravity->drift_gpart, gravity);
-  scheduler_addunlock(sched, gravity, c->super->end_force);
-}
-
 /**
  * @brief Creates all the task dependencies for the gravity
  *
@@ -2699,77 +2697,119 @@ void engine_link_gravity_tasks(struct engine *e) {
     /* Get the cells we act on */
     struct cell *ci = t->ci;
     struct cell *cj = t->cj;
+    const enum task_types t_type = t->type;
+    const enum task_subtypes t_subtype = t->subtype;
 
     /* Self-interaction for self-gravity? */
-    if (t->type == task_type_self && t->subtype == task_subtype_grav) {
+    if (t_type == task_type_self && t_subtype == task_subtype_grav) {
+
+#ifdef SWIFT_DEBUG_CHECKS
+      if (ci->nodeID != nodeID) error("Non-local self task");
+#endif
 
-      engine_make_self_gravity_dependencies(sched, t, ci);
+      /* drift ---+-> gravity --> grav_down */
+      /* init  --/    */
+      scheduler_addunlock(sched, ci->super_gravity->drift_gpart, t);
+      scheduler_addunlock(sched, ci->init_grav_out, t);
+      scheduler_addunlock(sched, t, ci->grav_down_in);
     }
 
     /* Self-interaction for external gravity ? */
-    if (t->type == task_type_self && t->subtype == task_subtype_external_grav) {
+    if (t_type == task_type_self && t_subtype == task_subtype_external_grav) {
 
-      engine_make_external_gravity_dependencies(sched, t, ci);
+#ifdef SWIFT_DEBUG_CHECKS
+      if (ci->nodeID != nodeID) error("Non-local self task");
+#endif
 
+      /* drift -----> gravity --> end_force */
+      scheduler_addunlock(sched, ci->super_gravity->drift_gpart, t);
+      scheduler_addunlock(sched, t, ci->end_force);
     }
 
     /* Otherwise, pair interaction? */
-    else if (t->type == task_type_pair && t->subtype == task_subtype_grav) {
+    else if (t_type == task_type_pair && t_subtype == task_subtype_grav) {
 
       if (ci->nodeID == nodeID) {
 
-        engine_make_self_gravity_dependencies(sched, t, ci);
+        /* drift ---+-> gravity --> grav_down */
+        /* init  --/    */
+        scheduler_addunlock(sched, ci->super_gravity->drift_gpart, t);
+        scheduler_addunlock(sched, ci->init_grav_out, t);
+        scheduler_addunlock(sched, t, ci->grav_down_in);
       }
-
-      if (cj->nodeID == nodeID && ci->super_gravity != cj->super_gravity) {
-
-        engine_make_self_gravity_dependencies(sched, t, cj);
+      if (cj->nodeID == nodeID) {
+
+        /* drift ---+-> gravity --> grav_down */
+        /* init  --/    */
+        if (ci->super_gravity != cj->super_gravity) /* Avoid double unlock */
+          scheduler_addunlock(sched, cj->super_gravity->drift_gpart, t);
+        scheduler_addunlock(sched, cj->init_grav_out, t);
+        scheduler_addunlock(sched, t, cj->grav_down_in);
       }
-
     }
 
     /* Otherwise, sub-self interaction? */
-    else if (t->type == task_type_sub_self && t->subtype == task_subtype_grav) {
+    else if (t_type == task_type_sub_self && t_subtype == task_subtype_grav) {
 
-      if (ci->nodeID == nodeID) {
-        engine_make_self_gravity_dependencies(sched, t, ci);
-      }
+#ifdef SWIFT_DEBUG_CHECKS
+      if (ci->nodeID != nodeID) error("Non-local sub-self task");
+#endif
+      /* drift ---+-> gravity --> grav_down */
+      /* init  --/    */
+      scheduler_addunlock(sched, ci->super_gravity->drift_gpart, t);
+      scheduler_addunlock(sched, ci->init_grav_out, t);
+      scheduler_addunlock(sched, t, ci->grav_down_in);
     }
 
     /* Sub-self-interaction for external gravity ? */
-    else if (t->type == task_type_sub_self &&
-             t->subtype == task_subtype_external_grav) {
+    else if (t_type == task_type_sub_self &&
+             t_subtype == task_subtype_external_grav) {
 
-      if (ci->nodeID == nodeID) {
-        engine_make_external_gravity_dependencies(sched, t, ci);
-      }
+#ifdef SWIFT_DEBUG_CHECKS
+      if (ci->nodeID != nodeID) error("Non-local sub-self task");
+#endif
+
+      /* drift -----> gravity --> end_force */
+      scheduler_addunlock(sched, ci->super_gravity->drift_gpart, t);
+      scheduler_addunlock(sched, t, ci->end_force);
     }
 
     /* Otherwise, sub-pair interaction? */
-    else if (t->type == task_type_sub_pair && t->subtype == task_subtype_grav) {
+    else if (t_type == task_type_sub_pair && t_subtype == task_subtype_grav) {
 
       if (ci->nodeID == nodeID) {
 
-        engine_make_self_gravity_dependencies(sched, t, ci);
+        /* drift ---+-> gravity --> grav_down */
+        /* init  --/    */
+        scheduler_addunlock(sched, ci->super_gravity->drift_gpart, t);
+        scheduler_addunlock(sched, ci->init_grav_out, t);
+        scheduler_addunlock(sched, t, ci->grav_down_in);
       }
-      if (cj->nodeID == nodeID && ci->super_gravity != cj->super_gravity) {
-
-        engine_make_self_gravity_dependencies(sched, t, cj);
+      if (cj->nodeID == nodeID) {
+
+        /* drift ---+-> gravity --> grav_down */
+        /* init  --/    */
+        if (ci->super_gravity != cj->super_gravity) /* Avoid double unlock */
+          scheduler_addunlock(sched, cj->super_gravity->drift_gpart, t);
+        scheduler_addunlock(sched, cj->init_grav_out, t);
+        scheduler_addunlock(sched, t, cj->grav_down_in);
       }
     }
 
     /* Otherwise M-M interaction? */
-    else if (t->type == task_type_grav_mm) {
+    else if (t_type == task_type_grav_mm) {
 
       if (ci->nodeID == nodeID) {
 
-        scheduler_addunlock(sched, ci->super_gravity->init_grav, t);
-        scheduler_addunlock(sched, t, ci->super_gravity->grav_down);
+        /* init -----> gravity --> grav_down */
+        scheduler_addunlock(sched, ci->init_grav_out, t);
+        scheduler_addunlock(sched, t, ci->grav_down_in);
       }
-      if (cj->nodeID == nodeID && ci->super_gravity != cj->super_gravity) {
+      if (cj->nodeID == nodeID) {
 
-        scheduler_addunlock(sched, cj->super_gravity->init_grav, t);
-        scheduler_addunlock(sched, t, cj->super_gravity->grav_down);
+        /* init -----> gravity --> grav_down */
+        scheduler_addunlock(sched, cj->init_grav_out, t);
+        scheduler_addunlock(sched, t, cj->grav_down_in);
       }
     }
   }
@@ -3571,7 +3611,9 @@ void engine_marktasks_mapper(void *map_data, int num_elements,
     /* Gravity stuff ? */
     else if (t->type == task_type_grav_down || t->type == task_type_grav_mesh ||
              t->type == task_type_grav_long_range ||
-             t->type == task_type_init_grav) {
+             t->type == task_type_init_grav ||
+             t->type == task_type_init_grav_out ||
+             t->type == task_type_grav_down_in) {
       if (cell_is_active_gravity(t->ci, e)) scheduler_activate(s, t);
     }
 
diff --git a/src/space.c b/src/space.c
index 3d15973d0ea4c04b09a928c05f07cba7a6529141..b4001919a6bd13d41877eec5600fb53b91ff6d12 100644
--- a/src/space.c
+++ b/src/space.c
@@ -175,6 +175,7 @@ void space_rebuild_recycle_mapper(void *map_data, int num_elements,
     c->gcount = 0;
     c->scount = 0;
     c->init_grav = NULL;
+    c->init_grav_out = NULL;
     c->extra_ghost = NULL;
     c->ghost_in = NULL;
     c->ghost_out = NULL;
@@ -188,6 +189,7 @@ void space_rebuild_recycle_mapper(void *map_data, int num_elements,
     c->cooling = NULL;
     c->sourceterms = NULL;
     c->grav_long_range = NULL;
+    c->grav_down_in = NULL;
     c->grav_down = NULL;
     c->super = c;
     c->super_hydro = c;
diff --git a/src/task.c b/src/task.c
index 03566868a5400582a01e9d3d88520009b7e77cdc..2782dabfc1369dedd43e9b42855a8b43acf2f1b7 100644
--- a/src/task.c
+++ b/src/task.c
@@ -48,11 +48,15 @@
 
 /* Task type names. */
 const char *taskID_names[task_type_count] = {
-    "none",        "sort",       "self",        "pair",      "sub_self",
-    "sub_pair",    "init_grav",  "ghost_in",    "ghost",     "ghost_out",
-    "extra_ghost", "drift_part", "drift_gpart", "end_force", "kick1",
-    "kick2",       "timestep",   "send",        "recv",      "grav_long_range",
-    "grav_mm",     "grav_down",  "grav_mesh",   "cooling",   "sourceterms"};
+    "none",       "sort",          "self",
+    "pair",       "sub_self",      "sub_pair",
+    "init_grav",  "init_grav_out", "ghost_in",
+    "ghost",      "ghost_out",     "extra_ghost",
+    "drift_part", "drift_gpart",   "end_force",
+    "kick1",      "kick2",         "timestep",
+    "send",       "recv",          "grav_long_range",
+    "grav_mm",    "grav_down_in",  "grav_down",
+    "grav_mesh",  "cooling",       "sourceterms"};
 
 /* Sub-task type names. */
 const char *subtaskID_names[task_subtype_count] = {
diff --git a/src/task.h b/src/task.h
index a353ff76a8419cf728b50999aa86e6deb9660ef3..072d3979ce04990aaef46c5cc5eb0b8c62fdc860 100644
--- a/src/task.h
+++ b/src/task.h
@@ -46,9 +46,10 @@ enum task_types {
   task_type_sub_self,
   task_type_sub_pair,
   task_type_init_grav,
-  task_type_ghost_in,
+  task_type_init_grav_out, /* Implicit */
+  task_type_ghost_in,      /* Implicit */
   task_type_ghost,
-  task_type_ghost_out,
+  task_type_ghost_out, /* Implicit */
   task_type_extra_ghost,
   task_type_drift_part,
   task_type_drift_gpart,
@@ -60,6 +61,7 @@ enum task_types {
   task_type_recv,
   task_type_grav_long_range,
   task_type_grav_mm,
+  task_type_grav_down_in, /* Implicit */
   task_type_grav_down,
   task_type_grav_mesh,
   task_type_cooling,