From a6aaf48ca5327df495024038ef17cfb5dad80e3c Mon Sep 17 00:00:00 2001
From: Matthieu Schaller <matthieu.schaller@durham.ac.uk>
Date: Mon, 5 Dec 2016 18:39:12 +0000
Subject: [PATCH] Created the task and dependencies

---
 src/cell.c      |  7 +++++++
 src/cell.h      |  3 +++
 src/engine.c    |  7 +++++++
 src/runner.c    | 22 +++++++++++++++-------
 src/scheduler.c | 37 ++++++++++++++++++++++++++++++++-----
 src/task.c      |  3 ++-
 src/task.h      |  1 +
 7 files changed, 67 insertions(+), 13 deletions(-)

diff --git a/src/cell.c b/src/cell.c
index e2767cdaa9..fcbbfe4ae1 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -878,6 +878,12 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) {
       }
     }
 
+    /* Activate the drift on both sides */
+    if (t->type == task_type_pair || t->type == task_type_sub_pair) {
+      scheduler_activate(s, ci->drift);
+      scheduler_activate(s, cj->drift);
+    }
+
     /* Check whether there was too much particle motion */
     if (t->type == task_type_pair || t->type == task_type_sub_pair) {
       if (t->tight &&
@@ -956,6 +962,7 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) {
   if (c->ghost != NULL) scheduler_activate(s, c->ghost);
   if (c->init != NULL) scheduler_activate(s, c->init);
   if (c->kick != NULL) scheduler_activate(s, c->kick);
+  if (c->drift != NULL) scheduler_activate(s, c->drift);
   if (c->cooling != NULL) scheduler_activate(s, c->cooling);
   if (c->sourceterms != NULL) scheduler_activate(s, c->sourceterms);
 
diff --git a/src/cell.h b/src/cell.h
index 2cd13cf2ab..d978de71f7 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -147,6 +147,9 @@ struct cell {
   /*! The extra ghost task for complex hydro schemes */
   struct task *extra_ghost;
 
+  /*! The drift task */
+  struct task *drift;
+
   /*! The kick task */
   struct task *kick;
 
diff --git a/src/engine.c b/src/engine.c
index e989aefd53..111f0a230a 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -139,6 +139,9 @@ void engine_make_hierarchical_tasks(struct engine *e, struct cell *c) {
       c->init = scheduler_addtask(s, task_type_init, task_subtype_none, 0, 0, c,
                                   NULL, 0);
 
+      /* c->drift = scheduler_addtask(s, task_type_drift, task_subtype_none, 0, 0, */
+      /*                              c, NULL, 0); */
+
       c->kick = scheduler_addtask(s, task_type_kick, task_subtype_none, 0, 0, c,
                                   NULL, 0);
 
@@ -1990,6 +1993,10 @@ void engine_marktasks_mapper(void *map_data, int num_elements,
       const struct cell *ci = t->ci;
       const struct cell *cj = t->cj;
 
+      /* Activate the drift on both sides */
+      if(ci->drift) scheduler_activate(s, ci->drift);
+      if(ci->drift) scheduler_activate(s, cj->drift);
+
       /* Too much particle movement? */
       if (t->tight &&
           (max(ci->h_max, cj->h_max) + ci->dx_max + cj->dx_max > cj->dmin ||
diff --git a/src/runner.c b/src/runner.c
index 2d6da4e4ae..a62fb87a8c 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -752,7 +752,7 @@ void runner_do_ghost(struct runner *r, struct cell *c, int timer) {
  * @param drift whether to actually drift the particles, will not be
  *              necessary for non-local cells.
  */
-static void runner_do_drift(struct cell *c, struct engine *e, int drift) {
+static void runner_do_unskip(struct cell *c, struct engine *e, int drift) {
 
   /* Unskip any active tasks. */
   if (cell_is_active(c, e)) {
@@ -770,7 +770,7 @@ static void runner_do_drift(struct cell *c, struct engine *e, int drift) {
       for (int k = 0; k < 8; k++) {
         if (c->progeny[k] != NULL) {
           struct cell *cp = c->progeny[k];
-          runner_do_drift(cp, e, 0);
+          runner_do_unskip(cp, e, 0);
         }
       }
     }
@@ -778,7 +778,6 @@ static void runner_do_drift(struct cell *c, struct engine *e, int drift) {
   }
 
   /* Now, we can drift */
-
   /* Get some information first */
   const double timeBase = e->timeBase;
   const int ti_old = c->ti_old;
@@ -856,7 +855,7 @@ static void runner_do_drift(struct cell *c, struct engine *e, int drift) {
         struct cell *cp = c->progeny[k];
 
         /* Recurse. */
-        runner_do_drift(cp, e, drift);
+        runner_do_unskip(cp, e, drift);
         dx_max = max(dx_max, cp->dx_max);
         h_max = max(h_max, cp->h_max);
       }
@@ -887,13 +886,15 @@ void runner_do_drift_mapper(void *map_data, int num_elements,
   for (int ind = 0; ind < num_elements; ind++) {
     struct cell *c = &cells[ind];
 #ifdef WITH_MPI
-    if (c != NULL) runner_do_drift(c, e, (c->nodeID == e->nodeID));
+    if (c != NULL) runner_do_unskip(c, e, (c->nodeID == e->nodeID));
 #else
-    if (c != NULL) runner_do_drift(c, e, 1);
+    if (c != NULL) runner_do_unskip(c, e, 1);
 #endif
   }
 }
 
+void runner_do_drift(struct runner *r, struct cell *c, int timer) {}
+
 /**
  * @brief Kick particles in momentum space and collect statistics (floating
  * time-step case)
@@ -1126,7 +1127,7 @@ void *runner_main(void *data) {
 /* Check that we haven't scheduled an inactive task */
 #ifdef SWIFT_DEBUG_CHECKS
       if (cj == NULL) { /* self */
-        if (!cell_is_active(ci, e) && t->type != task_type_sort)
+        if (!cell_is_active(ci, e) && t->type != task_type_sort && t->type != task_type_drift)
           error(
               "Task (type='%s/%s') should have been skipped ti_current=%d "
               "c->ti_end_min=%d",
@@ -1142,6 +1143,10 @@ void *runner_main(void *data) {
               taskID_names[t->type], subtaskID_names[t->subtype], e->ti_current,
               ci->ti_end_min, t->flags);
 
+	/* Special treatement for drifts */
+	if (!cell_is_active(ci, e) && t->type == task_type_drift)
+	  {;}
+	
       } else { /* pair */
         if (!cell_is_active(ci, e) && !cell_is_active(cj, e))
           error(
@@ -1231,6 +1236,9 @@ void *runner_main(void *data) {
           runner_do_extra_ghost(r, ci, 1);
           break;
 #endif
+        case task_type_drift:
+          // runner_do_drift(r, ci, 1);
+          break;
         case task_type_kick:
           runner_do_kick(r, ci, 1);
           break;
diff --git a/src/scheduler.c b/src/scheduler.c
index 0d7c8c4754..4574d4a1d9 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -133,6 +133,7 @@ static void scheduler_splittask(struct task *t, struct scheduler *s) {
     /* Non-splittable task? */
     if ((t->ci == NULL || (t->type == task_type_pair && t->cj == NULL)) ||
         ((t->type == task_type_kick) && t->ci->nodeID != s->nodeID) ||
+ 	((t->type == task_type_drift) && t->ci->nodeID != s->nodeID) ||
         ((t->type == task_type_init) && t->ci->nodeID != s->nodeID)) {
       t->type = task_type_none;
       t->skip = 1;
@@ -603,7 +604,7 @@ static void scheduler_splittask(struct task *t, struct scheduler *s) {
                 tl->flags = space_getsid(s->space, &t->ci, &t->cj, shift);
               }
 
-        /* Otherwise, if not spilt, stitch-up the sorting. */
+        /* Otherwise, if not spilt, stitch-up the sorting and drift. */
       } else {
 
         /* Create the sort for ci. */
@@ -613,9 +614,19 @@ static void scheduler_splittask(struct task *t, struct scheduler *s) {
                                         1 << sid, 0, ci, NULL, 0);
         else
           ci->sorts->flags |= (1 << sid);
+	
+	scheduler_addunlock(s, ci->sorts, t);
+
+	/* Create the drift for ci. */
+	if (ci->drift == NULL) {
+	  ci->drift = scheduler_addtask(s, task_type_drift, task_subtype_none,
+                                        0, 0, ci, NULL, 0);
+	  scheduler_addunlock(s, ci->drift, ci->sorts);
+	}
         lock_unlock_blind(&ci->lock);
-        scheduler_addunlock(s, ci->sorts, t);
 
+
+	
         /* Create the sort for cj. */
         lock_lock(&cj->lock);
         if (cj->sorts == NULL)
@@ -623,8 +634,16 @@ static void scheduler_splittask(struct task *t, struct scheduler *s) {
                                         1 << sid, 0, cj, NULL, 0);
         else
           cj->sorts->flags |= (1 << sid);
-        lock_unlock_blind(&cj->lock);
+
         scheduler_addunlock(s, cj->sorts, t);
+
+	/* Create the drift for cj. */
+	if (cj->drift == NULL) {
+	  cj->drift = scheduler_addtask(s, task_type_drift, task_subtype_none,
+                                        0, 0, cj, NULL, 0);
+	  scheduler_addunlock(s, cj->drift, cj->sorts);
+	}
+	lock_unlock_blind(&cj->lock);
       }
 
     } /* pair interaction? */
@@ -782,7 +801,9 @@ void scheduler_set_unlocks(struct scheduler *s) {
     for (int i = 0; i < t->nr_unlock_tasks; i++) {
       for (int j = i + 1; j < t->nr_unlock_tasks; j++) {
         if (t->unlock_tasks[i] == t->unlock_tasks[j])
-          error("duplicate unlock!");
+          error("duplicate unlock! t->type=%s/%s unlocking type=%s/%s",
+		taskID_names[t->type], subtaskID_names[t->subtype],
+		taskID_names[t->unlock_tasks[i]->type], subtaskID_names[t->unlock_tasks[i]->subtype]);
       }
     }
   }
@@ -1065,7 +1086,7 @@ void scheduler_start(struct scheduler *s) {
       if (cj == NULL) { /* self */
 
         if (ci->ti_end_min == ti_current && t->skip &&
-            t->type != task_type_sort)
+            t->type != task_type_sort && t->type != task_type_drift)
           error(
               "Task (type='%s/%s') should not have been skipped ti_current=%d "
               "c->ti_end_min=%d",
@@ -1081,6 +1102,11 @@ void scheduler_start(struct scheduler *s) {
               taskID_names[t->type], subtaskID_names[t->subtype], ti_current,
               ci->ti_end_min, t->flags);
 
+	/* Special treatement for drifts */
+        if (ci->ti_end_min == ti_current && t->skip &&
+            t->type == task_type_drift)
+	  {;}
+
       } else { /* pair */
 
         if ((ci->ti_end_min == ti_current || cj->ti_end_min == ti_current) &&
@@ -1148,6 +1174,7 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) {
       case task_type_sort:
       case task_type_ghost:
       case task_type_kick:
+    case task_type_drift:
       case task_type_init:
         qid = t->ci->super->owner;
         break;
diff --git a/src/task.c b/src/task.c
index ea97fdd1bb..19a8959153 100644
--- a/src/task.c
+++ b/src/task.c
@@ -49,7 +49,7 @@
 /* Task type names. */
 const char *taskID_names[task_type_count] = {
     "none",     "sort",    "self",          "pair",        "sub_self",
-    "sub_pair", "init",    "ghost",         "extra_ghost", "kick",
+    "sub_pair", "init",    "ghost",         "extra_ghost", "drift", "kick",
     "send",     "recv",    "grav_gather_m", "grav_fft",    "grav_mm",
     "grav_up",  "cooling", "sourceterms"};
 
@@ -150,6 +150,7 @@ __attribute__((always_inline)) INLINE static enum task_actions task_acts_on(
     case task_type_kick:
     case task_type_send:
     case task_type_recv:
+    case task_type_drift:
       if (t->ci->count > 0 && t->ci->gcount > 0)
         return task_action_all;
       else if (t->ci->count > 0)
diff --git a/src/task.h b/src/task.h
index c9425fdd13..b4767f036c 100644
--- a/src/task.h
+++ b/src/task.h
@@ -45,6 +45,7 @@ enum task_types {
   task_type_init,
   task_type_ghost,
   task_type_extra_ghost,
+  task_type_drift,
   task_type_kick,
   task_type_send,
   task_type_recv,
-- 
GitLab