diff --git a/doc/RTD/source/Task/adding_to_dependency_plotting_tool.rst b/doc/RTD/source/Task/adding_to_dependency_plotting_tool.rst
new file mode 100644
index 0000000000000000000000000000000000000000..0b1e6fbe3fb554a6a505eb08832bf64ea88d0ee9
--- /dev/null
+++ b/doc/RTD/source/Task/adding_to_dependency_plotting_tool.rst
@@ -0,0 +1,76 @@
+.. Dependency Plotting Additions for Tasks
+   Mladen Ivkovic, Sep 2020
+
+
+.. _task_adding_to_plotting_tool:
+.. highlight:: python
+
+
+
+Adding your Task to the Dependency Plotting Tool
+================================================
+
+How to create a task dependency graph is described in :ref:`Analysis_Tools`.
+By default, it should pick up and plot the new task. However, you might want to
+customize the plotting a bit, e.g. if you're introducing a new 'family' of tasks
+or you'd like them plotted as a cluster instead of individually. In both cases, we
+need to modify the ``tools/plot_task_dependencies.py`` script.
+
+
+
+Colouring in the Task Nodes
+---------------------------
+
+First, the script needs to identify the task types with which it is working.
+To do so, it will check the task names, which are generated following the scheme
+``taskname_subtaskname``, where ``taskname`` is defined in ``taskID_names`` and
+``subtasknbame`` is defined in ``subtaskID_names`` in ``task.c``. In 
+``tools/plot_task_dependencies.py``, you'll have to write a function that recognizes your 
+task by its name, like is done for example for gravity::
+
+    def taskIsGravity(name):
+        """
+        Does the task concern the gravity?
+
+        Parameters
+        ----------
+
+        name: str
+            Task name
+        """
+        if "gpart" in name:
+            return True
+        if "grav" in name:
+            return True
+    return False
+
+and add the check to the function ``writeTask()``::
+
+    if taskIsGravity(name):
+        txt += "color=red3,"
+
+Feel free to pick out a `nice color <http://graphviz.org/doc/info/colors.html>`_ for it :)
+
+
+
+
+
+
+
+
+Adding Clusters
+---------------
+
+In certain cases it makes sense to group some tasks together, for example the self 
+and pair tasks when computing hydro densities, gradients, or forces. To do this, 
+you'll need to modify the function ``task_get_group_name`` in ``src/task.c``. The group
+is determined by the task subtype, e.g.
+
+.. code-block:: c
+
+    case task_subtype_grav:
+      strcpy(cluster, "Gravity");
+      break;
+
+But since the task type itself is also passed to the function, you could use that
+as well if you really really need to. And that's it!
diff --git a/doc/RTD/source/Task/adding_your_own.rst b/doc/RTD/source/Task/adding_your_own.rst
index 6f6b37899b505a5bbf6a09d8757232e0b547a081..9850adc53da59f47f3d0b5ed085cbb92ac18bbad 100644
--- a/doc/RTD/source/Task/adding_your_own.rst
+++ b/doc/RTD/source/Task/adding_your_own.rst
@@ -8,16 +8,20 @@ Adding a Task
 =============
 
 First you will need to understand the dependencies between tasks
-using the file ``dependency_graph.dot`` generated by swift at the beginning of any simulation and then decide where it will fit (see :ref:`task`).
+using the file ``dependency_graph.dot`` generated by swift at the beginning of 
+any simulation and then decide where it will fit (see :ref:`task`).
 
-For the next paragraphs, let's assume that we want to implement the existing task ``cooling``.
+For the next paragraphs, let's assume that we want to implement the existing 
+task ``cooling``.
 
 Adding it to the Task List
 --------------------------
-First you will need to add it to the task list situated in ``task.h`` and ``task.c``.
+First you will need to add it to the task list situated in ``task.h`` and 
+``task.c``.
 
-In ``task.h``, you need to provide an additional entry to the enum ``task_types`` (e.g. ``task_type_cooling``).
-The last entry ``task_type_count`` should always stay at the end as it is a counter of the number of elements.
+In ``task.h``, you need to provide an additional entry to the enum 
+``task_types`` (e.g. ``task_type_cooling``). The last entry ``task_type_count`` 
+should always stay at the end as it is a counter of the number of elements.
 For example::
 
     enum task_types {
@@ -43,8 +47,9 @@ For example::
     } __attribute__((packed));
 
 
-In ``task.c``, you will find an array containing the name of each task and need to add your own (e.g. ``cooling``).
-Be careful with the order that should be the same than in the previous list.
+In ``task.c``, you will find an array containing the name of each task and need
+to add your own (e.g. ``cooling``).  Be careful with the order that should be the
+same than in the previous list.
 For example::
 
   /* Task type names. */
@@ -59,10 +64,12 @@ For example::
 Adding it to the Cells
 ----------------------
 
-Each cell contains a list to its tasks and therefore you need to provide a link for it.
+Each cell contains a list to its tasks and therefore you need to provide a link
+for it.
 
 In ``cell.h``, add a pointer to a task in the structure.
-In order to stay clean, please put the new task in the same group than the other tasks.
+In order to stay clean, please put the new task in the same group than the other
+tasks.
 For example::
 
   struct cell {
@@ -183,11 +190,16 @@ Adding your Task to the System
 ------------------------------
 
 Now the tricky part happens.
-SWIFT is able to deal automatically with the conflicts between tasks, but unfortunately cannot understand the dependencies.
+SWIFT is able to deal automatically with the conflicts between tasks, but 
+unfortunately cannot understand the dependencies.
 
-To implement your new task in the task system, you will need to modify a few functions in ``engine.c``.
+To implement your new task in the task system, you will need to modify a 
+few functions in ``engine_maketasks.c``.
 
-First, you will need to add mainly two functions: ``scheduler_addtask`` and ``scheduler_addunlocks`` in the ``engine_make_hierarchical_tasks_*`` functions (depending on the type of task you implement, you will need to write it to a different function).
+First, you will need to add mainly two functions: ``scheduler_addtask`` and 
+``scheduler_addunlocks`` in the ``engine_make_hierarchical_tasks_*`` functions
+(depending on the type of task you implement, you will need to write it to a 
+different function).
 
 In ``engine_make_hierarchical_tasks_hydro``,
 we add the task through the following call::
@@ -205,21 +217,34 @@ and the second kick cannot be done before the cooling::
 
 
 The next step is to activate your task
-in ``engine_marktasks_mapper``::
+in ``engine_marktasks_mapper`` in ``engine_marktasks.c``::
 
   else if (t->type == task_type_cooling || t->type == task_type_sourceterms) {
     if (cell_is_active_hydro(t->ci, e)) scheduler_activate(s, t);
   }
 
-Then you will need to update the estimate for the number of tasks in ``engine_estimate_nr_tasks`` by modifying ``n1`` or ``n2``.
+Then you will need to update the estimate for the number of tasks in 
+``engine_estimate_nr_tasks`` in ``engine.c`` by modifying ``n1`` or ``n2``,
+and give the task an estimate of the computational cost that it will have in 
+``scheduler_reweight`` in  ``scheduler.c``::
+
+      case task_type_cooling:
+        cost = wscale * count_i;
+        break;
 
 Initially, the engine will need to skip the task that updates the particles.
-It is the case for the cooling, therefore you will need to add it in ``engine_skip_force_and_kick``.
+It is the case for the cooling, therefore you will need to add it in 
+``engine_skip_force_and_kick``.
+
+Finally, you also need to initialize your new variables and pointers in 
+``space_rebuild_recycle_mapper`` in ``space.c``.
+
+
 
 Implementing your Task
 ----------------------
 
-The last part is situated in ``runner.c``.
+The last part is situated in ``runner_main.c``.
 
 You will need to implement a function ``runner_do_cooling``
 (do not forget to time it)::
@@ -255,8 +280,22 @@ in the switch::
     break;
 
 
+Adding your task to the analysis tools
+--------------------------------------
+
+To produce the task graphs, the analysis scripts need to know about
+the new task. You will need to edit the python script in the
+``tools/task_plots`` directory. At the start of each of
+``analyse_tasks.py``, ``plot_tasks.py`` and ``iplot_tasks.py`` you
+will find a long list of task names. You will need to add the name of
+the new task to that list. *The order of this list needs to be the
+same as the enum type in the task.h file!*
+
+
 Finalizing your Task
 --------------------
 
-Now that you have done the easiest part, you can start debugging by implementing a test and/or an example.
-Before creating your merge request with your new task, do not forget the most funny part that consists in writing a nice and beautiful documentation ;)
+Now that you have done the easiest part, you can start debugging by implementing
+a test and/or an example. Before creating your merge request with your new task,
+do not forget the most funny part that consists in writing a nice and beautiful
+documentation ;)
diff --git a/doc/RTD/source/Task/adding_your_own_neighbour_loop.rst b/doc/RTD/source/Task/adding_your_own_neighbour_loop.rst
new file mode 100644
index 0000000000000000000000000000000000000000..7e4ed2e641f1f3771b98bafb0a0bd5d57ed6522d
--- /dev/null
+++ b/doc/RTD/source/Task/adding_your_own_neighbour_loop.rst
@@ -0,0 +1,533 @@
+.. Neighbour Loop Task
+   Mladen Ivkovic Sep 2020
+
+.. _task_adding_your_own_neighbour_loop:
+.. highlight:: c
+
+Adding a Particle Interaction/Neighbour Loop Task
+=================================================
+
+There are quite a few subtle and not so subtle differences when adding tasks that include
+particle neighbour loops and/or particle interactions compared to "independent" tasks, where
+no particles interact with each other, but work is done on them individually.
+
+Particle interactions are handled on a cell basis. If only particles of one cell
+interact with each other, the task is referred to as a  ``self`` task. When particles of
+two different cells interact with each other, we call the task type ``pair``. For a 
+particle neighbour loop, one typically requires both ``self`` and ``pair`` tasks.
+Furthermore, sometimes interaction tasks which have too much of a workload can get split 
+into smaller units of work with tasks of the type ``sub_self`` and ``sub_pair``.
+
+For the next paragraphs, let's assume that we want to implement the task ``new_iact``.
+
+
+
+
+Adding it to the Task List
+--------------------------
+First you will need to add it to the task list situated in ``task.h`` and ``task.c``.
+Here we aren't adding a task **type**, as the type will always be a ``pair`` or a 
+``self``, but **subtypes**.
+
+In ``task.h``, you need to provide an additional entry to the enum ``task_subtypes`` 
+(e.g. ``task_subtype_new_iact``). The last entry ``task_subtype_count`` should always 
+stay at the end as it is a counter of the number of elements.
+For example::
+
+    enum task_subtypes {
+      task_subtype_none = 0,        task_subtype_density,           task_subtype_gradient,
+      task_subtype_force,           task_subtype_limiter,           task_subtype_grav,
+      task_subtype_external_grav,   task_subtype_tend_part,         task_subtype_tend_gpart,
+      task_subtype_tend_spart,      task_subtype_tend_sink,         task_subtype_tend_bpart,
+      task_subtype_xv,              task_subtype_rho,               task_subtype_part_swallow,
+      task_subtype_bpart_merger,    task_subtype_gpart,             task_subtype_multipole,
+      task_subtype_spart,           task_subtype_stars_density,     task_subtype_stars_feedback,
+      task_subtype_new_iact,        task_subtype_count
+    } __attribute__((packed));
+
+
+In ``task.c``, you will find an array containing the name of each task and need to add your own (e.g. ``new_iact``).
+Be careful with the order that should be the same than in the previous list.
+For example::
+
+    const char *subtaskID_names[task_subtype_count] = {
+            "none",         "density",      "gradient",         "force", 
+            "limiter",      "grav",         "external_grav",    "tend_part",
+            "tend_gpart",   "tend_spart",   "tend_sink",        "tend_bpart",
+            "xv",           "rho",          "part_swallow",     "bpart_merger",
+            "gpart",        "multipole",    "spart",            "stars_density",
+            "stars_feedback","sf_count",    "bpart_rho",        "sink",
+            "new_iact"
+   };
+
+
+
+Adding it to the Cells
+----------------------
+
+Each cell contains a list to its tasks and therefore you need to provide a link for it.
+
+In ``cell.h``, add a pointer to a task in the ``struct cell``.  In order to stay clean, 
+please put the new task in the same group (e.g. ``struct hydro{...}`` inside ``struct cell``)
+than the other tasks.
+We won't be adding just one task though, but an entire (linked) list of them, since we're
+going to need a ``self`` type task and multiple ``pair`` type tasks to have a complete
+neighbour loop. So instead of pointing to a single task, we store a struct ``link`` in
+the cell struct.  For example::
+
+  struct cell {
+    /* Lot of stuff before. */
+    
+    /*! Hydro variables */
+    struct {
+        /*! Pointer to the #part data. */
+        struct part *parts;
+
+        /*! Pointer to the #xpart data. */
+        struct xpart *xparts;
+
+        /* Lot of stuff */
+
+        /*! Task for sorting the stars again after a SF event */
+        struct task *stars_resort;
+
+        /*! My new interaction task */
+        struct link *new_iact;
+
+        /* Lot of stuff after */
+
+    } hydro;
+
+    /* Lot of stuff after */
+  }
+
+
+Adding a new Timer
+------------------
+
+As SWIFT is HPC oriented, any new task need to be optimized.
+It cannot be done without timing the function.
+
+In ``timers.h``, you will find an enum that contains all the tasks.
+You will need to add yours inside it.
+For example::
+
+  enum {
+    timer_none = 0,
+    timer_prepare,
+    timer_init,
+    timer_drift_part,
+    timer_drift_gpart,
+    timer_kick1,
+    timer_kick2,
+    timer_timestep,
+    timer_endforce,
+    timer_dosort,
+    timer_doself_density,
+    timer_doself_gradient,
+    timer_doself_force,
+    timer_dopair_density,
+    timer_dopair_gradient,
+    timer_dopair_force,
+    timer_dosub_self_density,
+    timer_dosub_self_gradient,
+    timer_dosub_self_force,
+    timer_dosub_pair_density,
+    timer_dosub_pair_gradient,
+    timer_dosub_pair_force,
+    timer_doself_subset,
+    timer_dopair_subset,
+    timer_dopair_subset_naive,
+    timer_dosub_subset,
+    timer_do_ghost,
+    timer_do_extra_ghost,
+    timer_dorecv_part,
+    timer_do_cooling,
+    timer_gettask,
+    timer_qget,
+    timer_qsteal,
+    timer_locktree,
+    timer_runners,
+    timer_step,
+    timer_cooling,
+    timer_new_iact,
+    timer_count,
+  };
+
+As for ``task.h``,
+you will need to give a name to your timer in ``timers.c``::
+
+  const char* timers_names[timer_count] = {
+    "none",
+    "prepare",
+    "init",
+    "drift_part",
+    "kick1",
+    "kick2",
+    "timestep",
+    "endforce",
+    "dosort",
+    "doself_density",
+    "doself_gradient",
+    "doself_force",
+    "dopair_density",
+    "dopair_gradient",
+    "dopair_force",
+    "dosub_self_density",
+    "dosub_self_gradient",
+    "dosub_self_force",
+    "dosub_pair_density",
+    "dosub_pair_gradient",
+    "dosub_pair_force",
+    "doself_subset",
+    "dopair_subset",
+    "dopair_subset_naive",
+    "dosub_subset",
+    "do_ghost",
+    "do_extra_ghost",
+    "dorecv_part",
+    "gettask",
+    "qget",
+    "qsteal",
+    "locktree",
+    "runners",
+    "step",
+    "cooling",
+    "new_iact",
+  };
+
+
+You can now easily time
+your functions by using::
+
+  TIMER_TIC;
+  /* Your complicated functions */
+  if (timer) TIMER_TOC(timer_new_iact);
+
+
+Adding your Task to the System
+------------------------------
+
+Now the tricky part happens.
+SWIFT is able to deal automatically with the conflicts between tasks, but unfortunately 
+cannot understand the dependencies.
+
+To implement your new task in the task system, you will need to modify a few functions 
+in ``engine_maketasks.c``.
+
+First, you will need to add mainly three functions: ``scheduler_addtask``, ``engine_addlink``,
+``scheduler_addunlocks`` in the ``engine_make_extra_hydroloop_tasks_mapper`` functions 
+(depending on the type of task you implement, you will need to write it to a different 
+function). The (hydro) particle interaction tasks are first created only for the density 
+loop, and then replicated in ``engine_make_extra_hydroloop_tasks_mapper`` for everything
+else.
+
+In ``engine_make_extra_hydroloop_tasks_mapper``, we add the task through the following 
+call::
+
+
+    struct task *t_new_iact = NULL;
+
+    /* ... lots of stuff ... */
+
+    /* Self-interaction? */
+    else if (t_type == task_type_self && t_subtype == task_subtype_density) {
+
+      /* ... lots of stuff ... */
+
+      t_new_iact = scheduler_addtask(sched, task_type_self, task_subtype_new_iact, 
+                                     flags, 0, ci, NULL);
+
+      /* Link the tasks to the cells */
+      engine_addlink(e, &ci->new_iact, t_new_iact);
+
+      /* Create the task dependencies */
+      scheduler_addunlock(sched, ci->task_that_unlocks_this_one, t_new_iact);
+      scheduler_addunlock(sched, t_new_iact, ci->task_that_will_be_unlocked_by_this_one);
+    }
+
+    /* Otherwise, pair interaction? */
+    else if (t_type == task_type_pair && t_subtype == task_subtype_density) {
+
+      /* ... lots of stuff ... */
+
+      t_new_iact = 
+        scheduler_addtask(sched, task_type_pair, task_subtype_new_iact, 
+                          flags, 0, ci, cj);
+      engine_addlink(e, &ci->new_iact, t_new_iact);
+      engine_addlink(e, &cj->new_iact, t_new_iact);
+
+      /* ... lots of stuff ... */
+
+      if (ci->nodeID == nodeID) {
+
+        /* ... lots of stuff ... */
+
+        scheduler_addunlock(sched, ci->task_that_unlocks_this_one, t_new_iact);
+        scheduler_addunlock(sched, t_new_iact, ci->task_that_will_be_unlocked_by_this_one);
+      }
+
+      if (cj->nodeID == nodeID) {
+
+        if (ci->hydro.super != cj->hydro.super) {
+
+          /* ... lots of stuff ... */
+
+          scheduler_addunlock(sched, cj->task_that_unlocks_this_one, t_new_iact);
+          scheduler_addunlock(sched, t_new_iact, cj->task_that_will_be_unlocked_by_this_one);
+
+        }
+      }
+    }
+
+    /* Otherwise, sub-self interaction? */
+    else if (t_type == task_type_sub_self &&
+             t_subtype == task_subtype_density) {
+
+        /* You need to do the same as for task_type_self above */
+    }
+
+    /* Otherwise, sub-pair interaction? */
+    else if (t_type == task_type_sub_pair &&
+             t_subtype == task_subtype_density) {
+
+        /* You need to do the same as for task_type_pair above */
+    }
+
+
+
+
+
+The next step is to activate your task
+in ``engine_marktasks_mapper`` in ``engine_marktasks.c``::
+
+
+  /* Single-cell task? */
+  if (t_type == task_type_self || t_type == task_type_sub_self) {
+
+    /* ... lots of stuff ...  */
+
+    else if (t_subtype == task_subtype_new_iact) {
+      scheduler_activate(s, t);
+    }
+  }
+
+  /* Pair? */
+  else if (t_type == task_type_pair || t_type == task_type_sub_pair) {
+
+    /* ... lots of stuff ...  */
+
+    else if (t_subtype == task_subtype_new_iact) {
+      scheduler_activate(s, t);
+    }
+  }
+
+
+Then you will need to update the estimate for the number of tasks in 
+``engine_estimate_nr_tasks`` in ``engine.c`` by modifying ``n1`` or ``n2``.
+``n1`` is the expected maximal number of tasks per top-level/super cell. ``n2``
+``n2`` is the expected maximum number of tasks for all other cells, independent
+of the depth of the tree. Most likely ``n2`` won't need updating, and you will
+only need to update ``n1``. As to how to update ``n1``, you just need to count
+the number of tasks that you will be adding, e.g. 1 self + (3^3-1)/2 = 13 pair 
+tasks + 1 ghost, etc... All these numbers can be overwritten at run time by 
+the user anyway in the parameter file (``Scheduler: tasks_per_cell``).
+
+and give the task an estimate of the computational cost that it will have in 
+``scheduler_reweight`` in  ``scheduler.c``::
+
+      case task_type_self:
+        if (t->subtype == task_subtype_grav) {
+          cost = 1.f * (wscale * gcount_i) * gcount_i;
+        /* ... lots of stuff ... */
+        else if (t->subtype == task_subtype_new_iact)
+          cost = 1.f * wscale * scount_i * count_i;
+        else
+          error("Untreated sub-type for selfs: %s",
+                subtaskID_names[t->subtype]);
+        break;
+
+Similarly, you'll need to update ``case task_type_sub_self``, ``task_type_pair``, 
+and ``task_type_sub_pair`` as well.
+
+
+
+Initially, the engine will need to skip the task that updates the particles.
+If this is the case for your task, you will need to add it in ``engine_skip_force_and_kick``.
+
+Finally, you also need to initialize your new variables and pointers in 
+``space_rebuild_recycle_mapper`` in ``space.c``. Additionally, you need to 
+initialize the ``link`` structs in ``cell_clean_links`` in ``cell.c``.
+
+
+
+
+Implementing your Task
+----------------------
+
+The last part is situated in ``runner_main.c``, where the actual functions executed
+by the task are called inside the function in ``runner_main`` in the switch::
+
+    /* Different types of tasks... */
+    switch (t->type) {
+      case task_type_self:
+        if (t->subtype == task_subtype_density)
+          runner_doself1_branch_density(r, ci);
+        /* ... lots of stuff ... */
+        else if (t->subtype == task_subtype_new_iact)
+          runner_doself_branch_new_iact(r, ci, 1);
+        else
+          error("Unknown/invalid task subtype (%s).",
+                subtaskID_names[t->subtype]);
+        break;
+        
+      case task_type_pair:
+        /* ... lots of stuff ... */
+        else if (t->subtype == task_subtype_new_iact)
+          runner_dopair_branch_new_iact(r, ci, cj, 1);
+        else
+          error("Unknown/invalid task subtype (%s/%s).",
+                taskID_names[t->type], subtaskID_names[t->subtype]);
+        break;
+
+      case task_type_sub_self:
+        /* ... lots of stuff ... */
+        else if (t->subtype == task_subtype_new_iact)
+          runner_dosub_self_new_iact(r, ci, 1);
+        else
+          error("Unknown/invalid task subtype (%s/%s).",
+                taskID_names[t->type], subtaskID_names[t->subtype]);
+        break;
+
+      case task_type_sub_pair:
+        /* ... lots of stuff ... */
+        else if (t->subtype == task_subtype_new_iact)
+          runner_dosub_pair_new_iact(r, ci, cj, 1);
+        else
+          error("Unknown/invalid task subtype (%s/%s).",
+                taskID_names[t->type], subtaskID_names[t->subtype]);
+        break;
+
+
+
+The functions ``runner_doself1_branch_density``, ``runner_dopair_branch_new_iact``,
+``runner_dosub_self_new_iact``,  and ``runner_dosub_pair_new_iact`` still need to be
+implemented by you. If you only plan on doing this type of particle interaction once
+per time step, you can get away with directly implementing these functions and call 
+it a day. But if you intend to use the same kind of particle loop more than once, as 
+it's done in e.g. the hydro density and force loops, it's better to construct the
+functions using macros.
+For example, you could have a file ``runner_doiact_my_stuff.h``::
+
+    /* File runner_doiact_my_stuff.h */
+
+    #define PASTE(x, y) x##_##y
+
+    #define _DOSELF1_BRANCH_NEW(f) PASTE(runner_doself_branch, f)
+    #define DOSELF1_BRANCH_NEW _DOSELF1_BRANCH_NEW(FUNCTION)
+
+    #define _DOPAIR1_BRANCH_NEW(f) PASTE(runner_dopair_branch, f)
+    #define DOPAIR1_BRANCH_NEW _DOPAIR1_BRANCH_NEW(FUNCTION)
+
+    #define _DOSUB_PAIR1_NEW(f) PASTE(runner_dosub_pair, f)
+    #define DOSUB_PAIR1_NEW _DOSUB_PAIR1_NEW(FUNCTION)
+
+    #define _DOSUB_SELF1_NEW(f) PASTE(runner_dosub_self, f)
+    #define DOSUB_SELF1_NEW _DOSUB_SELF1_NEW(FUNCTION)
+
+    #define _IACT_NEW(f) PASTE(runner_iact, f)
+    #define IACT_NEW _IACT_NEW(FUNCTION)
+
+    void DOSELF1_BRANCH_NEW(struct runner *r, struct cell *c, int timer);
+    void DOPAIR1_BRANCH_NEW(struct runner *r, struct cell *ci, struct cell *cj, 
+                           int timer);
+
+    void DOSUB_SELF1_NEW(struct runner *r, struct cell *ci, int timer);
+    void DOSUB_PAIR1_NEW(struct runner *r, struct cell *ci, struct cell *cj,
+                           int timer);
+
+
+
+And a second file, ``runner_doiact_function_my_stuff.h``, where you define those
+functions which have been declared using the macros, e.g. ::
+
+
+    #include "runner_doiact_my_stuff.h"
+
+    void DOSELF1_BRANCH_NEW(struct runner *r, struct cell *c, int timer) {
+      /* do your stuff, call IACT_NEW(...) at some point...*/
+    }
+
+    void DOPAIR1_BRANCH_NEW(struct runner *r, struct cell *ci, struct cell *cj, int timer) {
+      /* do your stuff, call IACT_NEW(...) at some point...*/
+    }
+
+    void DOSUB_SELF1_NEW(struct runner *r, struct cell *c, int timer) {
+      /* do your stuff, call IACT_NEW(...) at some point...*/
+    }
+
+    void DOSUB_PAIR1_NEW(struct runner *r, struct cell *ci, struct cell *cj, int timer) {
+      /* do your stuff, call IACT_NEW(...) at some point...*/
+    }
+
+
+Then we also need a ``runner_doiact_my_suff.c`` file where the functions declared in
+``runner_doiact_my_suff.h`` are defined by including them with ``FUNCTION`` defined::
+
+
+    #include "../config.h"
+    /* other includes too... */
+
+    /* Import the new interaction loop functions. */
+    #define FUNCTION new_iact
+    #include "runner_doiact_functions_my_stuff.h"
+    #undef FUNCTION
+
+
+
+
+Finally, we include them in ``runner_main.c`` as follows::
+
+    /* ... lots of includes and stuff ... */
+
+    /* Import new interaction loop functions. */
+    #define FUNCTION new_iact
+    #include "runner_doiact_my_suff.h"
+    #undef FUNCTION
+
+    /**
+     * @brief The #runner main thread routine.
+     *
+     * @param data A pointer to this thread's data.
+     */
+    void *runner_main(void *data) {
+        /* ... */
+    }
+
+
+The functions ``runner_doself_branch_density``, ``runner_dopair_branch_new_iact``,
+``runner_dosub_self_new_iact``,  and ``runner_dosub_pair_new_iact`` will be properly
+found and linked this way. All that's left for you to do is to write the function
+into which ``IACT_NEW`` will expand, in the above case it would be ``runner_iact_new_iact``.
+
+
+
+
+
+Finalizing your Task
+--------------------
+
+Now that you have done the easiest part, you can start debugging by implementing a 
+test and/or an example. Before creating your merge request with your new task, do 
+not forget the most funny part that consists in writing a nice and beautiful 
+documentation ;)
+
+
+Things to Keep in Mind
+----------------------
+
+- If you are inserting a new neighbour loop in between existing loops, or want to
+  insert more than one neighbour loop, usually a new ghost task in between them is
+  also needed.
+
+- Neighbour loops may also require MPI communication tasks.
diff --git a/doc/RTD/source/Task/index.rst b/doc/RTD/source/Task/index.rst
index 2c95ab9a5a72b169f39a4421ecc95a3f99053e87..2f64f8eb9ed31abc709a0d2b01f8d88a251119ba 100644
--- a/doc/RTD/source/Task/index.rst
+++ b/doc/RTD/source/Task/index.rst
@@ -18,3 +18,5 @@ Everything is described in :ref:`Analysis_Tools`.
    :caption: Contents:
 
    adding_your_own
+   adding_your_own_neighbour_loop
+   adding_to_dependency_plotting_tool
diff --git a/tools/task_plots/analyse_tasks.py b/tools/task_plots/analyse_tasks.py
index ffa0f6d5e5ae7669d149ed45215156d500085947..b72e342e9a9066c05a69f4c01e813d161474bcc0 100755
--- a/tools/task_plots/analyse_tasks.py
+++ b/tools/task_plots/analyse_tasks.py
@@ -85,6 +85,7 @@ TASKTYPES = [
     "extra_ghost",
     "drift_part",
     "drift_spart",
+    "drift_sink",
     "drift_bpart",
     "drift_gpart",
     "drift_gpart_out",
diff --git a/tools/task_plots/iplot_tasks.py b/tools/task_plots/iplot_tasks.py
index faa8c534deff7428ef037f29f27e88fc46a1a100..9e8759e1f35a32b143e5da622eb85230fb5630ab 100755
--- a/tools/task_plots/iplot_tasks.py
+++ b/tools/task_plots/iplot_tasks.py
@@ -139,6 +139,7 @@ TASKTYPES = [
     "extra_ghost",
     "drift_part",
     "drift_spart",
+    "drift_sink",
     "drift_bpart",
     "drift_gpart",
     "drift_gpart_out",
diff --git a/tools/task_plots/plot_tasks.py b/tools/task_plots/plot_tasks.py
index 45f5feb03d4cad88bcb1af7c2b65b77247f1df1a..8d2134887d636ada6febe29428e91c127f3f79a2 100755
--- a/tools/task_plots/plot_tasks.py
+++ b/tools/task_plots/plot_tasks.py
@@ -162,6 +162,7 @@ TASKTYPES = [
     "extra_ghost",
     "drift_part",
     "drift_spart",
+    "drift_sink",
     "drift_bpart",
     "drift_gpart",
     "drift_gpart_out",