diff --git a/src/task.c b/src/task.c
index 4769aa6605ee58b30bb56b7f59755a6cfdd93017..e9404ab00df4f757f49d6d186f28dc40c49cfa01 100644
--- a/src/task.c
+++ b/src/task.c
@@ -59,7 +59,7 @@ const char *subtaskID_names[task_type_count] = {"none", "density", "force",
 /**
  * @brief Computes the overlap between the parts array of two given cells.
  */
-size_t task_cell_overlap(const struct cell *ci, const struct cell *cj) {
+size_t task_cell_overlap_part(const struct cell *ci, const struct cell *cj) {
   if (ci == NULL || cj == NULL) return 0;
   if (ci->parts <= cj->parts &&
       ci->parts + ci->count >= cj->parts + cj->count) {
@@ -71,6 +71,95 @@ size_t task_cell_overlap(const struct cell *ci, const struct cell *cj) {
   return 0;
 }
 
+/**
+ * @brief Computes the overlap between the gparts array of two given cells.
+ */
+size_t task_cell_overlap_gpart(const struct cell *ci, const struct cell *cj) {
+  if (ci == NULL || cj == NULL) return 0;
+  if (ci->gparts <= cj->gparts &&
+      ci->gparts + ci->gcount >= cj->gparts + cj->gcount) {
+    return cj->gcount;
+  } else if (cj->gparts <= ci->gparts &&
+             cj->gparts + cj->gcount >= ci->gparts + ci->gcount) {
+    return ci->gcount;
+  }
+  return 0;
+}
+
+/**
+ * @brief Returns the #task_actions for a given task.
+ *
+ * @param t The #task.
+ */
+enum task_actions task_acts_on(const struct task *t) {
+
+  switch (t->type) {
+
+    case task_type_none:
+      return task_action_none;
+      break;
+
+    case task_type_sort:
+    case task_type_ghost:
+      return task_action_part;
+      break;
+
+    case task_type_self:
+    case task_type_pair:
+    case task_type_sub_self:
+    case task_type_sub_pair:
+      switch (t->subtype) {
+
+        case task_subtype_density:
+        case task_subtype_force:
+          return task_action_part;
+          break;
+
+        case task_subtype_grav:
+          return task_action_gpart;
+          break;
+
+        default:
+          error("Unknow task_action for task");
+          return task_action_none;
+          break;
+      }
+      break;
+
+    case task_type_init:
+    case task_type_drift:
+    case task_type_kick:
+    case task_type_kick_fixdt:
+    case task_type_send:
+    case task_type_recv:
+      return task_action_all;
+      break;
+
+    case task_type_grav_gather_m:
+    case task_type_grav_fft:
+    case task_type_grav_mm:
+    case task_type_grav_up:
+      return task_action_multipole;
+      break;
+
+    case task_type_grav_external:
+      return task_action_gpart;
+      break;
+
+    case task_type_part_sort:
+    case task_type_gpart_sort:
+    case task_type_split_cell:
+    case task_type_rewait:
+      return task_action_none;
+      break;
+
+    default:
+      error("Unknow task_action for task");
+      return task_action_none;
+      break;
+  }
+}
+
 /**
  * @brief Compute the Jaccard similarity of the data used by two
  *        different tasks.
@@ -79,29 +168,63 @@ size_t task_cell_overlap(const struct cell *ci, const struct cell *cj) {
  * @param tb The second #task.
  */
 float task_overlap(const struct task *ta, const struct task *tb) {
+
+  if (ta == NULL || tb == NULL) return 0.f;
+
+  const enum task_actions ta_act = task_acts_on(ta);
+  const enum task_actions tb_act = task_acts_on(tb);
+
   /* First check if any of the two tasks are of a type that don't
      use cells. */
-  if (ta == NULL || tb == NULL || ta->type == task_type_none ||
-      ta->type == task_type_part_sort || ta->type == task_type_gpart_sort ||
-      ta->type == task_type_split_cell || ta->type == task_type_rewait ||
-      tb->type == task_type_none || tb->type == task_type_part_sort ||
-      tb->type == task_type_gpart_sort || tb->type == task_type_split_cell ||
-      tb->type == task_type_rewait)
-    return 0.0f;
-
-  /* Compute the union of the cell data. */
-  size_t size_union = 0;
-  if (ta->ci != NULL) size_union += ta->ci->count;
-  if (ta->cj != NULL) size_union += ta->cj->count;
-  if (tb->ci != NULL) size_union += tb->ci->count;
-  if (tb->cj != NULL) size_union += tb->cj->count;
-
-  /* Compute the intersection of the cell data. */
-  const size_t size_intersect =
-      task_cell_overlap(ta->ci, tb->ci) + task_cell_overlap(ta->ci, tb->cj) +
-      task_cell_overlap(ta->cj, tb->ci) + task_cell_overlap(ta->cj, tb->cj);
-
-  return ((float)size_intersect) / (size_union - size_intersect);
+  if (ta_act == task_action_none || tb_act == task_action_none) return 0.f;
+
+  const int ta_part = (ta_act == task_action_part || ta_act == task_action_all);
+  const int ta_gpart =
+      (ta_act == task_action_gpart || ta_act == task_action_all);
+  const int tb_part = (tb_act == task_action_part || tb_act == task_action_all);
+  const int tb_gpart =
+      (tb_act == task_action_gpart || tb_act == task_action_all);
+
+  /* In the case where both tasks act on parts */
+  if (ta_part && tb_part) {
+
+    /* Compute the union of the cell data. */
+    size_t size_union = 0;
+    if (ta->ci != NULL) size_union += ta->ci->count;
+    if (ta->cj != NULL) size_union += ta->cj->count;
+    if (tb->ci != NULL) size_union += tb->ci->count;
+    if (tb->cj != NULL) size_union += tb->cj->count;
+
+    /* Compute the intersection of the cell data. */
+    const size_t size_intersect = task_cell_overlap_part(ta->ci, tb->ci) +
+                                  task_cell_overlap_part(ta->ci, tb->cj) +
+                                  task_cell_overlap_part(ta->cj, tb->ci) +
+                                  task_cell_overlap_part(ta->cj, tb->cj);
+
+    return ((float)size_intersect) / (size_union - size_intersect);
+  }
+
+  /* In the case where both tasks act on gparts */
+  else if (ta_gpart && tb_gpart) {
+
+    /* Compute the union of the cell data. */
+    size_t size_union = 0;
+    if (ta->ci != NULL) size_union += ta->ci->gcount;
+    if (ta->cj != NULL) size_union += ta->cj->gcount;
+    if (tb->ci != NULL) size_union += tb->ci->gcount;
+    if (tb->cj != NULL) size_union += tb->cj->gcount;
+
+    /* Compute the intersection of the cell data. */
+    const size_t size_intersect = task_cell_overlap_gpart(ta->ci, tb->ci) +
+                                  task_cell_overlap_gpart(ta->ci, tb->cj) +
+                                  task_cell_overlap_gpart(ta->cj, tb->ci) +
+                                  task_cell_overlap_gpart(ta->cj, tb->cj);
+
+    return ((float)size_intersect) / (size_union - size_intersect);
+  }
+
+  /* Else, no overlap */
+  return 0.f;
 }
 
 /**
diff --git a/src/task.h b/src/task.h
index 581af55e561fb61fad788c78c20ccc986c27821b..ee49568b143282b9e3025f6d2bc81ded04ffee41 100644
--- a/src/task.h
+++ b/src/task.h
@@ -70,6 +70,16 @@ enum task_subtypes {
   task_subtype_count
 };
 
+/* The kind of action the task perform */
+enum task_actions {
+  task_action_none,
+  task_action_part,
+  task_action_gpart,
+  task_action_all,
+  task_action_multipole,
+  task_action_count
+};
+
 extern const char *subtaskID_names[];
 
 /* Data of a task. */
@@ -102,5 +112,6 @@ int task_lock(struct task *t);
 void task_print_mask(unsigned int mask);
 void task_print_submask(unsigned int submask);
 void task_do_rewait(struct task *t);
+enum task_actions task_acts_on(const struct task *t);
 
 #endif /* SWIFT_TASK_H */