engine_marktasks.c 35 KB
Newer Older
Pedro Gonnet's avatar
Pedro Gonnet committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*******************************************************************************
 * This file is part of SWIFT.
 * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
 *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
 *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
 *                    Angus Lepper (angus.lepper@ed.ac.uk)
 *               2016 John A. Regan (john.a.regan@durham.ac.uk)
 *                    Tom Theuns (tom.theuns@durham.ac.uk)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

/* Config parameters. */
#include "../config.h"

/* Some standard headers. */
#include <stdlib.h>
#include <unistd.h>

/* MPI headers. */
#ifdef WITH_MPI
#include <mpi.h>
#endif

/* Load the profiler header, if needed. */
#ifdef WITH_PROFILER
#include <gperftools/profiler.h>
#endif

/* This object's header. */
#include "engine.h"

/* Local headers. */
#include "active.h"
#include "atomic.h"
#include "cell.h"
#include "clocks.h"
#include "cycle.h"
#include "debug.h"
#include "error.h"
#include "proxy.h"
#include "timers.h"

/**
 * @brief Mark tasks to be un-skipped and set the sort flags accordingly.
 *        Threadpool mapper function.
 *
 * @param map_data pointer to the tasks
 * @param num_elements number of tasks
 * @param extra_data pointer to int that will define if a rebuild is needed.
 */
void engine_marktasks_mapper(void *map_data, int num_elements,
                             void *extra_data) {
  /* Unpack the arguments. */
  struct task *tasks = (struct task *)map_data;
  size_t *rebuild_space = &((size_t *)extra_data)[1];
  struct scheduler *s = (struct scheduler *)(((size_t *)extra_data)[2]);
  struct engine *e = (struct engine *)((size_t *)extra_data)[0];
  const int nodeID = e->nodeID;
72
  const int with_limiter = e->policy & engine_policy_limiter;
73
  const int with_star_formation = e->policy & engine_policy_star_formation;
74
#ifdef WITH_MPI
75
76
  const int with_feedback = e->policy & engine_policy_feedback;
#endif
Pedro Gonnet's avatar
Pedro Gonnet committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90

  for (int ind = 0; ind < num_elements; ind++) {

    /* Get basic task information */
    struct task *t = &tasks[ind];
    const enum task_types t_type = t->type;
    const enum task_subtypes t_subtype = t->subtype;

    /* Single-cell task? */
    if (t_type == task_type_self || t_type == task_type_sub_self) {

      /* Local pointer. */
      struct cell *ci = t->ci;

91
#ifdef SWIFT_DEBUG_CHECKS
92
      if (ci->nodeID != nodeID) error("Non-local self task found");
93
94
95
96
#endif
      const int ci_active_hydro = cell_is_active_hydro(ci, e);
      const int ci_active_gravity = cell_is_active_gravity(ci, e);
      const int ci_active_black_holes = cell_is_active_black_holes(ci, e);
97
98
99
      const int ci_active_stars = cell_is_active_stars(ci, e) ||
                                  (with_star_formation && ci_active_hydro);

Pedro Gonnet's avatar
Pedro Gonnet committed
100
101
      /* Activate the hydro drift */
      if (t_type == task_type_self && t_subtype == task_subtype_density) {
102
        if (ci_active_hydro) {
Pedro Gonnet's avatar
Pedro Gonnet committed
103
104
          scheduler_activate(s, t);
          cell_activate_drift_part(ci, s);
105
          if (with_limiter) cell_activate_limiter(ci, s);
Pedro Gonnet's avatar
Pedro Gonnet committed
106
107
108
109
110
111
        }
      }

      /* Store current values of dx_max and h_max. */
      else if (t_type == task_type_sub_self &&
               t_subtype == task_subtype_density) {
112
        if (ci_active_hydro) {
Pedro Gonnet's avatar
Pedro Gonnet committed
113
114
          scheduler_activate(s, t);
          cell_activate_subcell_hydro_tasks(ci, NULL, s);
115
          if (with_limiter) cell_activate_limiter(ci, s);
Pedro Gonnet's avatar
Pedro Gonnet committed
116
117
118
119
        }
      }

      else if (t_type == task_type_self && t_subtype == task_subtype_force) {
120
        if (ci_active_hydro) scheduler_activate(s, t);
Pedro Gonnet's avatar
Pedro Gonnet committed
121
122
123
124
      }

      else if (t_type == task_type_sub_self &&
               t_subtype == task_subtype_force) {
125
        if (ci_active_hydro) scheduler_activate(s, t);
Pedro Gonnet's avatar
Pedro Gonnet committed
126
127
      }

128
129
      else if (t->type == task_type_self &&
               t->subtype == task_subtype_limiter) {
130
        if (ci_active_hydro) scheduler_activate(s, t);
131
132
133
134
      }

      else if (t->type == task_type_sub_self &&
               t->subtype == task_subtype_limiter) {
135
        if (ci_active_hydro) scheduler_activate(s, t);
136
137
      }

Pedro Gonnet's avatar
Pedro Gonnet committed
138
      else if (t_type == task_type_self && t_subtype == task_subtype_gradient) {
139
        if (ci_active_hydro) scheduler_activate(s, t);
Pedro Gonnet's avatar
Pedro Gonnet committed
140
141
142
143
      }

      else if (t_type == task_type_sub_self &&
               t_subtype == task_subtype_gradient) {
144
        if (ci_active_hydro) scheduler_activate(s, t);
Pedro Gonnet's avatar
Pedro Gonnet committed
145
146
147
148
149
      }

      /* Activate the star density */
      else if (t_type == task_type_self &&
               t_subtype == task_subtype_stars_density) {
150
        if (ci_active_stars) {
Pedro Gonnet's avatar
Pedro Gonnet committed
151
152
          scheduler_activate(s, t);
          cell_activate_drift_part(ci, s);
Loic Hausammann's avatar
Loic Hausammann committed
153
          cell_activate_drift_spart(ci, s);
Pedro Gonnet's avatar
Pedro Gonnet committed
154
155
156
157
158
159
        }
      }

      /* Store current values of dx_max and h_max. */
      else if (t_type == task_type_sub_self &&
               t_subtype == task_subtype_stars_density) {
160
        if (ci_active_stars) {
Pedro Gonnet's avatar
Pedro Gonnet committed
161
          scheduler_activate(s, t);
162
          cell_activate_subcell_stars_tasks(ci, NULL, s, with_star_formation);
Pedro Gonnet's avatar
Pedro Gonnet committed
163
164
165
        }
      }

Alexei Borissov's avatar
Alexei Borissov committed
166
167
      else if (t_type == task_type_self &&
               t_subtype == task_subtype_stars_feedback) {
168
        if (ci_active_stars) {
Alexei Borissov's avatar
Alexei Borissov committed
169
170
171
172
173
174
          scheduler_activate(s, t);
        }
      }

      else if (t_type == task_type_sub_self &&
               t_subtype == task_subtype_stars_feedback) {
175
        if (ci_active_stars) scheduler_activate(s, t);
Alexei Borissov's avatar
Alexei Borissov committed
176
177
      }

178
179
180
      /* Activate the black hole density */
      else if (t_type == task_type_self &&
               t_subtype == task_subtype_bh_density) {
181
        if (ci_active_black_holes) {
182
183
184
185
186
187
188
189
190
          scheduler_activate(s, t);
          cell_activate_drift_part(ci, s);
          cell_activate_drift_bpart(ci, s);
        }
      }

      /* Store current values of dx_max and h_max. */
      else if (t_type == task_type_sub_self &&
               t_subtype == task_subtype_bh_density) {
191
        if (ci_active_black_holes) {
192
          scheduler_activate(s, t);
193
          cell_activate_subcell_black_holes_tasks(ci, NULL, s);
194
195
196
        }
      }

197
198
199
200
201
202
203
204
205
206
207
208
209
      else if (t_type == task_type_self &&
               t_subtype == task_subtype_bh_swallow) {
        if (ci_active_black_holes) {
          scheduler_activate(s, t);
        }
      }

      else if (t_type == task_type_sub_self &&
               t_subtype == task_subtype_bh_swallow) {
        if (ci_active_black_holes) scheduler_activate(s, t);
      }

      else if (t_type == task_type_self &&
210
               t_subtype == task_subtype_do_gas_swallow) {
211
212
213
214
215
216
        if (ci_active_black_holes) {
          scheduler_activate(s, t);
        }
      }

      else if (t_type == task_type_sub_self &&
217
218
219
220
221
222
223
224
225
226
227
228
229
               t_subtype == task_subtype_do_gas_swallow) {
        if (ci_active_black_holes) scheduler_activate(s, t);
      }

      else if (t_type == task_type_self &&
               t_subtype == task_subtype_do_bh_swallow) {
        if (ci_active_black_holes) {
          scheduler_activate(s, t);
        }
      }

      else if (t_type == task_type_sub_self &&
               t_subtype == task_subtype_do_bh_swallow) {
230
231
232
        if (ci_active_black_holes) scheduler_activate(s, t);
      }

233
234
      else if (t_type == task_type_self &&
               t_subtype == task_subtype_bh_feedback) {
235
        if (ci_active_black_holes) {
236
237
238
239
240
241
          scheduler_activate(s, t);
        }
      }

      else if (t_type == task_type_sub_self &&
               t_subtype == task_subtype_bh_feedback) {
242
        if (ci_active_black_holes) scheduler_activate(s, t);
243
244
      }

Pedro Gonnet's avatar
Pedro Gonnet committed
245
246
      /* Activate the gravity drift */
      else if (t_type == task_type_self && t_subtype == task_subtype_grav) {
247
        if (ci_active_gravity) {
Pedro Gonnet's avatar
Pedro Gonnet committed
248
249
250
251
252
253
254
255
          scheduler_activate(s, t);
          cell_activate_subcell_grav_tasks(t->ci, NULL, s);
        }
      }

      /* Activate the gravity drift */
      else if (t_type == task_type_self &&
               t_subtype == task_subtype_external_grav) {
256
        if (ci_active_gravity) {
Pedro Gonnet's avatar
Pedro Gonnet committed
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
          scheduler_activate(s, t);
          cell_activate_drift_gpart(t->ci, s);
        }
      }

#ifdef SWIFT_DEBUG_CHECKS
      else {
        error("Invalid task type / sub-type encountered");
      }
#endif
    }

    /* Pair? */
    else if (t_type == task_type_pair || t_type == task_type_sub_pair) {

      /* Local pointers. */
      struct cell *ci = t->ci;
      struct cell *cj = t->cj;
#ifdef WITH_MPI
      const int ci_nodeID = ci->nodeID;
      const int cj_nodeID = cj->nodeID;
#else
      const int ci_nodeID = nodeID;
      const int cj_nodeID = nodeID;
#endif
      const int ci_active_hydro = cell_is_active_hydro(ci, e);
      const int cj_active_hydro = cell_is_active_hydro(cj, e);
284

Pedro Gonnet's avatar
Pedro Gonnet committed
285
286
      const int ci_active_gravity = cell_is_active_gravity(ci, e);
      const int cj_active_gravity = cell_is_active_gravity(cj, e);
287

288
289
290
      const int ci_active_black_holes = cell_is_active_black_holes(ci, e);
      const int cj_active_black_holes = cell_is_active_black_holes(cj, e);

291
292
293
294
295
      const int ci_active_stars = cell_is_active_stars(ci, e) ||
                                  (with_star_formation && ci_active_hydro);
      const int cj_active_stars = cell_is_active_stars(cj, e) ||
                                  (with_star_formation && cj_active_hydro);

Pedro Gonnet's avatar
Pedro Gonnet committed
296
297
298
      /* Only activate tasks that involve a local active cell. */
      if ((t_subtype == task_subtype_density ||
           t_subtype == task_subtype_gradient ||
299
           t_subtype == task_subtype_limiter ||
Pedro Gonnet's avatar
Pedro Gonnet committed
300
301
302
303
304
305
306
           t_subtype == task_subtype_force) &&
          ((ci_active_hydro && ci_nodeID == nodeID) ||
           (cj_active_hydro && cj_nodeID == nodeID))) {

        scheduler_activate(s, t);

        /* Set the correct sorting flags */
Loic Hausammann's avatar
Loic Hausammann committed
307
        if (t_type == task_type_pair && t_subtype == task_subtype_density) {
Pedro Gonnet's avatar
Pedro Gonnet committed
308
309
310
311
312
313
314
315
316
317
318

          /* Store some values. */
          atomic_or(&ci->hydro.requires_sorts, 1 << t->flags);
          atomic_or(&cj->hydro.requires_sorts, 1 << t->flags);
          ci->hydro.dx_max_sort_old = ci->hydro.dx_max_sort;
          cj->hydro.dx_max_sort_old = cj->hydro.dx_max_sort;

          /* Activate the hydro drift tasks. */
          if (ci_nodeID == nodeID) cell_activate_drift_part(ci, s);
          if (cj_nodeID == nodeID) cell_activate_drift_part(cj, s);

319
          /* And the limiter */
320
321
          if (ci_nodeID == nodeID && with_limiter) cell_activate_limiter(ci, s);
          if (cj_nodeID == nodeID && with_limiter) cell_activate_limiter(cj, s);
322

Pedro Gonnet's avatar
Pedro Gonnet committed
323
          /* Check the sorts and activate them if needed. */
324
325
          cell_activate_hydro_sorts(ci, t->flags, s);
          cell_activate_hydro_sorts(cj, t->flags, s);
Pedro Gonnet's avatar
Pedro Gonnet committed
326
327
328
329
330

        }

        /* Store current values of dx_max and h_max. */
        else if (t_type == task_type_sub_pair &&
Loic Hausammann's avatar
Loic Hausammann committed
331
                 t_subtype == task_subtype_density) {
Pedro Gonnet's avatar
Pedro Gonnet committed
332
333
334
335
          cell_activate_subcell_hydro_tasks(t->ci, t->cj, s);
        }
      }

336
337
      /* Stars density */
      else if ((t_subtype == task_subtype_stars_density) &&
338
339
340
               (ci_active_stars || cj_active_stars) &&
               (ci_nodeID == nodeID || cj_nodeID == nodeID)) {

loikki's avatar
loikki committed
341
        scheduler_activate(s, t);
342

Pedro Gonnet's avatar
Pedro Gonnet committed
343
344
345
        /* Set the correct sorting flags */
        if (t_type == task_type_pair) {

Loic Hausammann's avatar
Loic Hausammann committed
346
          /* Do ci */
loikki's avatar
loikki committed
347
          if (ci_active_stars) {
348

349
            /* stars for ci */
350
            atomic_or(&ci->stars.requires_sorts, 1 << t->flags);
351
            ci->stars.dx_max_sort_old = ci->stars.dx_max_sort;
Loic Hausammann's avatar
Loic Hausammann committed
352

353
            /* hydro for cj */
354
            atomic_or(&cj->hydro.requires_sorts, 1 << t->flags);
355
            cj->hydro.dx_max_sort_old = cj->hydro.dx_max_sort;
Pedro Gonnet's avatar
Pedro Gonnet committed
356

357
            /* Activate the drift tasks. */
358
359
            if (ci_nodeID == nodeID) cell_activate_drift_spart(ci, s);
            if (cj_nodeID == nodeID) cell_activate_drift_part(cj, s);
Pedro Gonnet's avatar
Pedro Gonnet committed
360

361
362
363
364
            /* Check the sorts and activate them if needed. */
            cell_activate_hydro_sorts(cj, t->flags, s);
            cell_activate_stars_sorts(ci, t->flags, s);
          }
Loic Hausammann's avatar
Loic Hausammann committed
365
366

          /* Do cj */
loikki's avatar
loikki committed
367
          if (cj_active_stars) {
Loic Hausammann's avatar
Loic Hausammann committed
368

369
            /* hydro for ci */
370
            atomic_or(&ci->hydro.requires_sorts, 1 << t->flags);
371
            ci->hydro.dx_max_sort_old = ci->hydro.dx_max_sort;
372

373
            /* stars for cj */
374
            atomic_or(&cj->stars.requires_sorts, 1 << t->flags);
375
            cj->stars.dx_max_sort_old = cj->stars.dx_max_sort;
Loic Hausammann's avatar
Loic Hausammann committed
376

377
            /* Activate the drift tasks. */
378
379
            if (ci_nodeID == nodeID) cell_activate_drift_part(ci, s);
            if (cj_nodeID == nodeID) cell_activate_drift_spart(cj, s);
Loic Hausammann's avatar
Loic Hausammann committed
380

381
382
383
384
            /* Check the sorts and activate them if needed. */
            cell_activate_hydro_sorts(ci, t->flags, s);
            cell_activate_stars_sorts(cj, t->flags, s);
          }
Pedro Gonnet's avatar
Pedro Gonnet committed
385
386
387
        }

        /* Store current values of dx_max and h_max. */
388
        else if (t_type == task_type_sub_pair &&
389
                 t_subtype == task_subtype_stars_density) {
390
          cell_activate_subcell_stars_tasks(ci, cj, s, with_star_formation);
Pedro Gonnet's avatar
Pedro Gonnet committed
391
392
393
        }
      }

394
      /* Stars feedback */
395
      else if (t_subtype == task_subtype_stars_feedback) {
396

397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
        /* We only want to activate the task if the cell is active and is
           going to update some gas on the *local* node */
        if ((ci_nodeID == nodeID && cj_nodeID == nodeID) &&
            (ci_active_stars || cj_active_stars)) {

          scheduler_activate(s, t);

        } else if ((ci_nodeID == nodeID && cj_nodeID != nodeID) &&
                   (cj_active_stars)) {

          scheduler_activate(s, t);

        } else if ((ci_nodeID != nodeID && cj_nodeID == nodeID) &&
                   (ci_active_stars)) {

          scheduler_activate(s, t);
        }
414
      }
415

416
      /* Black_Holes density */
417
418
      else if ((t_subtype == task_subtype_bh_density ||
                t_subtype == task_subtype_bh_swallow ||
419
                t_subtype == task_subtype_do_gas_swallow ||
420
                t_subtype == task_subtype_bh_feedback) &&
421
422
423
424
425
426
               (ci_active_black_holes || cj_active_black_holes) &&
               (ci_nodeID == nodeID || cj_nodeID == nodeID)) {

        scheduler_activate(s, t);

        /* Set the correct sorting flags */
427
428
429
        if (t_type == task_type_pair && t_subtype == task_subtype_bh_density) {
          if (ci_nodeID == nodeID) cell_activate_drift_bpart(ci, s);
          if (ci_nodeID == nodeID) cell_activate_drift_part(ci, s);
430

431
432
          if (cj_nodeID == nodeID) cell_activate_drift_part(cj, s);
          if (cj_nodeID == nodeID) cell_activate_drift_bpart(cj, s);
433
434
435
436
437
438
439
440
441
        }

        /* Store current values of dx_max and h_max. */
        else if (t_type == task_type_sub_pair &&
                 t_subtype == task_subtype_bh_density) {
          cell_activate_subcell_black_holes_tasks(ci, cj, s);
        }
      }

442
      /* Gravity */
443
      else if ((t_subtype == task_subtype_grav) &&
444
445
               ((ci_active_gravity && ci_nodeID == nodeID) ||
                (cj_active_gravity && cj_nodeID == nodeID))) {
Pedro Gonnet's avatar
Pedro Gonnet committed
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465

        scheduler_activate(s, t);

        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);
        }

#ifdef SWIFT_DEBUG_CHECKS
        else if (t_type == task_type_sub_pair &&
                 t_subtype == task_subtype_grav) {
          error("Invalid task sub-type encountered");
        }
#endif
      }

      /* Only interested in density tasks as of here. */
      if (t_subtype == task_subtype_density) {

        /* Too much particle movement? */
Alexei Borissov's avatar
Alexei Borissov committed
466
        if (cell_need_rebuild_for_hydro_pair(ci, cj)) *rebuild_space = 1;
Pedro Gonnet's avatar
Pedro Gonnet committed
467
468
469
470
471
472
473

#ifdef WITH_MPI
        /* Activate the send/recv tasks. */
        if (ci_nodeID != nodeID) {

          /* If the local cell is active, receive data from the foreign cell. */
          if (cj_active_hydro) {
474
            scheduler_activate_recv(s, ci->mpi.recv, task_subtype_xv);
Pedro Gonnet's avatar
Pedro Gonnet committed
475
            if (ci_active_hydro) {
476
              scheduler_activate_recv(s, ci->mpi.recv, task_subtype_rho);
Pedro Gonnet's avatar
Pedro Gonnet committed
477
#ifdef EXTRA_HYDRO_LOOP
478
              scheduler_activate_recv(s, ci->mpi.recv, task_subtype_gradient);
Pedro Gonnet's avatar
Pedro Gonnet committed
479
480
481
482
483
#endif
            }
          }

          /* If the foreign cell is active, we want its ti_end values. */
484
485
          if (ci_active_hydro)
            scheduler_activate_recv(s, ci->mpi.recv, task_subtype_tend_part);
Pedro Gonnet's avatar
Pedro Gonnet committed
486
487
488

          /* Is the foreign cell active and will need stuff from us? */
          if (ci_active_hydro) {
489
            struct link *l = scheduler_activate_send(
490
                s, cj->mpi.send, task_subtype_xv, ci_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
491
492
493
494
495
496
497
498

            /* Drift the cell which will be sent at the level at which it is
               sent, i.e. drift the cell specified in the send task (l->t)
               itself. */
            cell_activate_drift_part(l->t->ci, s);

            /* If the local cell is also active, more stuff will be needed. */
            if (cj_active_hydro) {
499
500
              scheduler_activate_send(s, cj->mpi.send, task_subtype_rho,
                                      ci_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
501
502

#ifdef EXTRA_HYDRO_LOOP
503
504
              scheduler_activate_send(s, cj->mpi.send, task_subtype_gradient,
                                      ci_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
505
506
507
508
509
510
#endif
            }
          }

          /* If the local cell is active, send its ti_end values. */
          if (cj_active_hydro)
511
512
            scheduler_activate_send(s, cj->mpi.send, task_subtype_tend_part,
                                    ci_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
513

514
515
516
517
          /* Propagating new star counts? */
          if (with_star_formation && with_feedback) {
            if (ci_active_hydro && ci->hydro.count > 0) {
              scheduler_activate_recv(s, ci->mpi.recv, task_subtype_sf_counts);
518
              scheduler_activate_recv(s, ci->mpi.recv, task_subtype_tend_spart);
519
520
521
522
            }
            if (cj_active_hydro && cj->hydro.count > 0) {
              scheduler_activate_send(s, cj->mpi.send, task_subtype_sf_counts,
                                      ci_nodeID);
523
524
              scheduler_activate_send(s, cj->mpi.send, task_subtype_tend_spart,
                                      ci_nodeID);
525
526
527
            }
          }

Pedro Gonnet's avatar
Pedro Gonnet committed
528
529
530
531
        } else if (cj_nodeID != nodeID) {

          /* If the local cell is active, receive data from the foreign cell. */
          if (ci_active_hydro) {
532

533
            scheduler_activate_recv(s, cj->mpi.recv, task_subtype_xv);
Pedro Gonnet's avatar
Pedro Gonnet committed
534
            if (cj_active_hydro) {
535
              scheduler_activate_recv(s, cj->mpi.recv, task_subtype_rho);
Pedro Gonnet's avatar
Pedro Gonnet committed
536
#ifdef EXTRA_HYDRO_LOOP
537
              scheduler_activate_recv(s, cj->mpi.recv, task_subtype_gradient);
Pedro Gonnet's avatar
Pedro Gonnet committed
538
539
540
541
542
#endif
            }
          }

          /* If the foreign cell is active, we want its ti_end values. */
543
544
          if (cj_active_hydro)
            scheduler_activate_recv(s, cj->mpi.recv, task_subtype_tend_part);
Pedro Gonnet's avatar
Pedro Gonnet committed
545
546
547
548

          /* Is the foreign cell active and will need stuff from us? */
          if (cj_active_hydro) {

549
            struct link *l = scheduler_activate_send(
550
                s, ci->mpi.send, task_subtype_xv, cj_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
551
552
553
554
555
556
557
558
559

            /* Drift the cell which will be sent at the level at which it is
               sent, i.e. drift the cell specified in the send task (l->t)
               itself. */
            cell_activate_drift_part(l->t->ci, s);

            /* If the local cell is also active, more stuff will be needed. */
            if (ci_active_hydro) {

560
561
              scheduler_activate_send(s, ci->mpi.send, task_subtype_rho,
                                      cj_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
562
563

#ifdef EXTRA_HYDRO_LOOP
564
565
              scheduler_activate_send(s, ci->mpi.send, task_subtype_gradient,
                                      cj_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
566
567
568
569
570
571
#endif
            }
          }

          /* If the local cell is active, send its ti_end values. */
          if (ci_active_hydro)
572
573
            scheduler_activate_send(s, ci->mpi.send, task_subtype_tend_part,
                                    cj_nodeID);
574
575
576
577
578

          /* Propagating new star counts? */
          if (with_star_formation && with_feedback) {
            if (cj_active_hydro && cj->hydro.count > 0) {
              scheduler_activate_recv(s, cj->mpi.recv, task_subtype_sf_counts);
579
              scheduler_activate_recv(s, cj->mpi.recv, task_subtype_tend_spart);
580
581
582
583
            }
            if (ci_active_hydro && ci->hydro.count > 0) {
              scheduler_activate_send(s, ci->mpi.send, task_subtype_sf_counts,
                                      cj_nodeID);
584
585
              scheduler_activate_send(s, ci->mpi.send, task_subtype_tend_spart,
                                      cj_nodeID);
586
587
            }
          }
Pedro Gonnet's avatar
Pedro Gonnet committed
588
589
590
591
592
        }
#endif
      }

      /* Only interested in stars_density tasks as of here. */
593
      else if (t->subtype == task_subtype_stars_density) {
594
595
596
597
598

        /* Too much particle movement? */
        if (cell_need_rebuild_for_stars_pair(ci, cj)) *rebuild_space = 1;
        if (cell_need_rebuild_for_stars_pair(cj, ci)) *rebuild_space = 1;

599
#ifdef WITH_MPI
600
601
602
603
        /* Activate the send/recv tasks. */
        if (ci_nodeID != nodeID) {

          if (cj_active_stars) {
604
            scheduler_activate_recv(s, ci->mpi.recv, task_subtype_xv);
605
            scheduler_activate_recv(s, ci->mpi.recv, task_subtype_rho);
606
607

            /* If the local cell is active, more stuff will be needed. */
608
            scheduler_activate_send(s, cj->mpi.send, task_subtype_spart,
609
                                    ci_nodeID);
610
611
612
            cell_activate_drift_spart(cj, s);

            /* If the local cell is active, send its ti_end values. */
613
614
            scheduler_activate_send(s, cj->mpi.send, task_subtype_tend_spart,
                                    ci_nodeID);
615
616
617
          }

          if (ci_active_stars) {
618
            scheduler_activate_recv(s, ci->mpi.recv, task_subtype_spart);
619
620

            /* If the foreign cell is active, we want its ti_end values. */
621
            scheduler_activate_recv(s, ci->mpi.recv, task_subtype_tend_spart);
622
623

            /* Is the foreign cell active and will need stuff from us? */
624
            scheduler_activate_send(s, cj->mpi.send, task_subtype_xv,
625
                                    ci_nodeID);
626
            scheduler_activate_send(s, cj->mpi.send, task_subtype_rho,
627
                                    ci_nodeID);
628
629
630
631
632
633
634
635
636
637

            /* Drift the cell which will be sent; note that not all sent
               particles will be drifted, only those that are needed. */
            cell_activate_drift_part(cj, s);
          }

        } else if (cj_nodeID != nodeID) {

          /* If the local cell is active, receive data from the foreign cell. */
          if (ci_active_stars) {
638
            scheduler_activate_recv(s, cj->mpi.recv, task_subtype_xv);
639
            scheduler_activate_recv(s, cj->mpi.recv, task_subtype_rho);
640
641

            /* If the local cell is active, more stuff will be needed. */
642
            scheduler_activate_send(s, ci->mpi.send, task_subtype_spart,
643
                                    cj_nodeID);
644
645
646
            cell_activate_drift_spart(ci, s);

            /* If the local cell is active, send its ti_end values. */
647
648
            scheduler_activate_send(s, ci->mpi.send, task_subtype_tend_spart,
                                    cj_nodeID);
649
650
651
          }

          if (cj_active_stars) {
652
            scheduler_activate_recv(s, cj->mpi.recv, task_subtype_spart);
653
654

            /* If the foreign cell is active, we want its ti_end values. */
655
            scheduler_activate_recv(s, cj->mpi.recv, task_subtype_tend_spart);
656
657

            /* Is the foreign cell active and will need stuff from us? */
658
            scheduler_activate_send(s, ci->mpi.send, task_subtype_xv,
659
                                    cj_nodeID);
660
            scheduler_activate_send(s, ci->mpi.send, task_subtype_rho,
661
                                    cj_nodeID);
662
663
664
665
666
667

            /* Drift the cell which will be sent; note that not all sent
               particles will be drifted, only those that are needed. */
            cell_activate_drift_part(ci, s);
          }
        }
668
#endif
Pedro Gonnet's avatar
Pedro Gonnet committed
669
      }
670

671
      /* Only interested in black hole density tasks as of here. */
672
673
674
675
676
677
      else if (t->subtype == task_subtype_bh_density) {

        /* Too much particle movement? */
        if (cell_need_rebuild_for_black_holes_pair(ci, cj)) *rebuild_space = 1;
        if (cell_need_rebuild_for_black_holes_pair(cj, ci)) *rebuild_space = 1;

678
679
680
        scheduler_activate(s, ci->hydro.super->black_holes.swallow_ghost[0]);
        scheduler_activate(s, cj->hydro.super->black_holes.swallow_ghost[0]);

681
682
683
684
#ifdef WITH_MPI
        /* Activate the send/recv tasks. */
        if (ci_nodeID != nodeID) {

685
686
687
688
          /* Receive the foreign parts to compute BH accretion rates and do the
           * swallowing */
          scheduler_activate_recv(s, ci->mpi.recv, task_subtype_rho);
          scheduler_activate_recv(s, ci->mpi.recv, task_subtype_part_swallow);
689

690
691
692
693
694
695
          /* Send the local BHs to tag the particles to swallow and to do
           * feedback */
          scheduler_activate_send(s, cj->mpi.send, task_subtype_bpart_rho,
                                  ci_nodeID);
          scheduler_activate_send(s, cj->mpi.send, task_subtype_bpart_feedback,
                                  ci_nodeID);
696

697
698
          /* Drift before you send */
          cell_activate_drift_bpart(cj, s);
699

700
701
702
          /* Send the new BH time-steps */
          scheduler_activate_send(s, cj->mpi.send, task_subtype_tend_bpart,
                                  ci_nodeID);
703

704
705
706
707
          /* Receive the foreign BHs to tag particles to swallow and for
           * feedback */
          scheduler_activate_recv(s, ci->mpi.recv, task_subtype_bpart_rho);
          scheduler_activate_recv(s, ci->mpi.recv, task_subtype_bpart_feedback);
708

709
710
          /* Receive the foreign BH time-steps */
          scheduler_activate_recv(s, ci->mpi.recv, task_subtype_tend_bpart);
711

712
713
714
715
716
717
718
719
          /* Send the local part information */
          scheduler_activate_send(s, cj->mpi.send, task_subtype_rho, ci_nodeID);
          scheduler_activate_send(s, cj->mpi.send, task_subtype_part_swallow,
                                  ci_nodeID);

          /* Drift the cell which will be sent; note that not all sent
             particles will be drifted, only those that are needed. */
          cell_activate_drift_part(cj, s);
720
721
722

        } else if (cj_nodeID != nodeID) {

723
724
725
726
          /* Receive the foreign parts to compute BH accretion rates and do the
           * swallowing */
          scheduler_activate_recv(s, cj->mpi.recv, task_subtype_rho);
          scheduler_activate_recv(s, cj->mpi.recv, task_subtype_part_swallow);
727

728
729
730
731
732
733
          /* Send the local BHs to tag the particles to swallow and to do
           * feedback */
          scheduler_activate_send(s, ci->mpi.send, task_subtype_bpart_rho,
                                  cj_nodeID);
          scheduler_activate_send(s, ci->mpi.send, task_subtype_bpart_feedback,
                                  cj_nodeID);
734

735
736
          /* Drift before you send */
          cell_activate_drift_bpart(ci, s);
737

738
739
740
          /* Send the new BH time-steps */
          scheduler_activate_send(s, ci->mpi.send, task_subtype_tend_bpart,
                                  cj_nodeID);
741

742
743
744
745
          /* Receive the foreign BHs to tag particles to swallow and for
           * feedback */
          scheduler_activate_recv(s, cj->mpi.recv, task_subtype_bpart_rho);
          scheduler_activate_recv(s, cj->mpi.recv, task_subtype_bpart_feedback);
746

747
748
          /* Receive the foreign BH time-steps */
          scheduler_activate_recv(s, cj->mpi.recv, task_subtype_tend_bpart);
749

750
751
752
753
754
755
756
757
          /* Send the local part information */
          scheduler_activate_send(s, ci->mpi.send, task_subtype_rho, cj_nodeID);
          scheduler_activate_send(s, ci->mpi.send, task_subtype_part_swallow,
                                  cj_nodeID);

          /* Drift the cell which will be sent; note that not all sent
             particles will be drifted, only those that are needed. */
          cell_activate_drift_part(ci, s);
758
759
760
761
        }
#endif
      }

Pedro Gonnet's avatar
Pedro Gonnet committed
762
      /* Only interested in gravity tasks as of here. */
763
      else if (t_subtype == task_subtype_grav) {
Pedro Gonnet's avatar
Pedro Gonnet committed
764
765
766
767
768
769

#ifdef WITH_MPI
        /* Activate the send/recv tasks. */
        if (ci_nodeID != nodeID) {

          /* If the local cell is active, receive data from the foreign cell. */
770
771
          if (cj_active_gravity)
            scheduler_activate_recv(s, ci->mpi.recv, task_subtype_gpart);
Pedro Gonnet's avatar
Pedro Gonnet committed
772
773

          /* If the foreign cell is active, we want its ti_end values. */
774
775
          if (ci_active_gravity)
            scheduler_activate_recv(s, ci->mpi.recv, task_subtype_tend_gpart);
Pedro Gonnet's avatar
Pedro Gonnet committed
776
777
778
779

          /* Is the foreign cell active and will need stuff from us? */
          if (ci_active_gravity) {

780
            struct link *l = scheduler_activate_send(
781
                s, cj->mpi.send, task_subtype_gpart, ci_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
782
783
784
785
786
787
788
789
790

            /* Drift the cell which will be sent at the level at which it is
               sent, i.e. drift the cell specified in the send task (l->t)
               itself. */
            cell_activate_drift_gpart(l->t->ci, s);
          }

          /* If the local cell is active, send its ti_end values. */
          if (cj_active_gravity)
791
792
            scheduler_activate_send(s, cj->mpi.send, task_subtype_tend_gpart,
                                    ci_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
793
794
795
796

        } else if (cj_nodeID != nodeID) {

          /* If the local cell is active, receive data from the foreign cell. */
797
798
          if (ci_active_gravity)
            scheduler_activate_recv(s, cj->mpi.recv, task_subtype_gpart);
Pedro Gonnet's avatar
Pedro Gonnet committed
799
800

          /* If the foreign cell is active, we want its ti_end values. */
801
802
          if (cj_active_gravity)
            scheduler_activate_recv(s, cj->mpi.recv, task_subtype_tend_gpart);
Pedro Gonnet's avatar
Pedro Gonnet committed
803
804
805
806

          /* Is the foreign cell active and will need stuff from us? */
          if (cj_active_gravity) {

807
            struct link *l = scheduler_activate_send(
808
                s, ci->mpi.send, task_subtype_gpart, cj_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
809
810
811
812
813
814
815
816
817

            /* Drift the cell which will be sent at the level at which it is
               sent, i.e. drift the cell specified in the send task (l->t)
               itself. */
            cell_activate_drift_gpart(l->t->ci, s);
          }

          /* If the local cell is active, send its ti_end values. */
          if (ci_active_gravity)
818
819
            scheduler_activate_send(s, ci->mpi.send, task_subtype_tend_gpart,
                                    cj_nodeID);
Pedro Gonnet's avatar
Pedro Gonnet committed
820
821
822
823
824
        }
#endif
      }
    }

825
826
    /* End force for hydro ? */
    else if (t_type == task_type_end_hydro_force) {
Pedro Gonnet's avatar
Pedro Gonnet committed
827

828
829
830
831
832
833
834
      if (cell_is_active_hydro(t->ci, e)) scheduler_activate(s, t);
    }

    /* End force for gravity ? */
    else if (t_type == task_type_end_grav_force) {

      if (cell_is_active_gravity(t->ci, e)) scheduler_activate(s, t);
Pedro Gonnet's avatar
Pedro Gonnet committed
835
836
837
838
839
    }

    /* Kick ? */
    else if (t_type == task_type_kick1 || t_type == task_type_kick2) {

840
841
842
      if (cell_is_active_hydro(t->ci, e) || cell_is_active_gravity(t->ci, e) ||
          cell_is_active_stars(t->ci, e) ||
          cell_is_active_black_holes(t->ci, e))
Pedro Gonnet's avatar
Pedro Gonnet committed
843
844
845
846
847
848
849
850
851
852
853
854
        scheduler_activate(s, t);
    }

    /* Hydro ghost tasks ? */
    else if (t_type == task_type_ghost || t_type == task_type_extra_ghost ||
             t_type == task_type_ghost_in || t_type == task_type_ghost_out) {
      if (cell_is_active_hydro(t->ci, e)) scheduler_activate(s, t);
    }

    /* logger tasks ? */
    else if (t->type == task_type_logger) {
      if (cell_is_active_hydro(t->ci, e) || cell_is_active_gravity(t->ci, e) ||
855
          cell_is_active_stars(t->ci, e))
Pedro Gonnet's avatar
Pedro Gonnet committed
856
857
858
859
860
861
862
863
        scheduler_activate(s, t);
    }

    /* 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_out ||
864
             t_type == task_type_drift_gpart_out ||
Pedro Gonnet's avatar
Pedro Gonnet committed
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
             t_type == task_type_grav_down_in) {
      if (cell_is_active_gravity(t->ci, e)) scheduler_activate(s, t);
    }

    /* Multipole - Multipole interaction task */
    else if (t_type == task_type_grav_mm) {

      /* Local pointers. */
      const struct cell *ci = t->ci;
      const struct cell *cj = t->cj;
#ifdef WITH_MPI
      const int ci_nodeID = ci->nodeID;
      const int cj_nodeID = (cj != NULL) ? cj->nodeID : -1;
#else
      const int ci_nodeID = nodeID;
      const int cj_nodeID = nodeID;
#endif
      const int ci_active_gravity = cell_is_active_gravity_mm(ci, e);
      const int cj_active_gravity = cell_is_active_gravity_mm(cj, e);

      if ((ci_active_gravity && ci_nodeID == nodeID) ||
          (cj_active_gravity && cj_nodeID == nodeID))
        scheduler_activate(s, t);
    }

    /* Star ghost tasks ? */
891
    else if (t_type == task_type_stars_ghost) {
892
893
894
      if (cell_is_active_stars(t->ci, e) ||
          (with_star_formation && cell_is_active_hydro(t->ci, e)))
        scheduler_activate(s, t);
895
896
897
898
    }

    /* Feedback implicit tasks? */
    else if (t_type == task_type_stars_in || t_type == task_type_stars_out) {
899
900
901
      if (cell_is_active_stars(t->ci, e) ||
          (with_star_formation && cell_is_active_hydro(t->ci, e)))
        scheduler_activate(s, t);
Pedro Gonnet's avatar
Pedro Gonnet committed
902
903
    }

904
    /* Black hole ghost tasks ? */
905
906
    else if (t_type == task_type_bh_density_ghost ||
             t_type == task_type_bh_swallow_ghost1 ||
907
908
             t_type == task_type_bh_swallow_ghost2 ||
             t_type == task_type_bh_swallow_ghost3) {
909
910
911
912
913
914
915
916
      if (cell_is_active_black_holes(t->ci, e)) scheduler_activate(s, t);
    }

    /* Black holes implicit tasks? */
    else if (t_type == task_type_bh_in || t_type == task_type_bh_out) {
      if (cell_is_active_black_holes(t->ci, e)) scheduler_activate(s, t);
    }

Pedro Gonnet's avatar
Pedro Gonnet committed
917
918
919
920
921
    /* Time-step? */
    else if (t_type == task_type_timestep) {
      t->ci->hydro.updated = 0;
      t->ci->grav.updated = 0;
      t->ci->stars.updated = 0;
922
923
924
925
      t->ci->black_holes.updated = 0;
      if (cell_is_active_hydro(t->ci, e) || cell_is_active_gravity(t->ci, e) ||
          cell_is_active_stars(t->ci, e) ||
          cell_is_active_black_holes(t->ci, e))
Pedro Gonnet's avatar
Pedro Gonnet committed
926
927
928
        scheduler_activate(s, t);
    }

929
    /* Subgrid tasks: cooling */
Pedro Gonnet's avatar
Pedro Gonnet committed
930
    else if (t_type == task_type_cooling) {
931
932
933
934
935
936
      if (cell_is_active_hydro(t->ci, e)) scheduler_activate(s, t);
    }

    /* Subgrid tasks: star formation */
    else if (t_type == task_type_star_formation) {
      if (cell_is_active_hydro(t->ci, e)) {
Pedro Gonnet's avatar
Pedro Gonnet committed
937
        scheduler_activate(s, t);
938
        cell_activate_super_spart_drifts(t->ci, s);
939
      }
Pedro Gonnet's avatar
Pedro Gonnet committed
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
    }
  }
}

/**
 * @brief Mark tasks to be un-skipped and set the sort flags accordingly.
 *
 * @return 1 if the space has to be rebuilt, 0 otherwise.
 */
int engine_marktasks(struct engine *e) {

  struct scheduler *s = &e->sched;
  const ticks tic = getticks();
  int rebuild_space = 0;

  /* Run through the tasks and mark as skip or not. */
  size_t extra_data[3] = {(size_t)e, (size_t)rebuild_space, (size_t)&e->sched};
  threadpool_map(&e->threadpool, engine_marktasks_mapper, s->tasks, s->nr_tasks,
                 sizeof(struct task), 0, extra_data);
  rebuild_space = extra_data[1];

  if (e->verbose)
    message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
            clocks_getunit());

  /* All is well... */
  return rebuild_space;
}