scheduler.c 85.2 KB
Newer Older
1
2
/*******************************************************************************
 * This file is part of SWIFT.
3
 * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
4
 *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
5
 *               2016 Peter W. Draper (p.w.draper@durham.ac.uk)
6
 *
7
8
9
10
 * 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.
11
 *
12
13
14
15
 * 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.
16
 *
17
18
 * 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/>.
19
 *
20
21
22
23
24
25
 ******************************************************************************/

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

/* Some standard headers. */
26
27
28
#include <limits.h>
#include <math.h>
#include <pthread.h>
29
30
31
32
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

33
34
/* MPI headers. */
#ifdef WITH_MPI
35
#include <mpi.h>
36
37
#endif

38
39
40
/* This object's header. */
#include "scheduler.h"

41
42
/* Local headers. */
#include "atomic.h"
43
#include "cycle.h"
44
#include "engine.h"
45
#include "error.h"
46
#include "intrinsics.h"
47
#include "kernel_hydro.h"
48
#include "queue.h"
49
#include "sort_part.h"
50
#include "space.h"
51
#include "space_getsid.h"
52
#include "task.h"
53
#include "timers.h"
54
#include "version.h"
55

56
57
58
59
60
/**
 * @brief Re-set the list of active tasks.
 */
void scheduler_clear_active(struct scheduler *s) { s->active_count = 0; }

61
62
63
64
65
66
67
/**
 * @brief Add an unlock_task to the given task.
 *
 * @param s The #scheduler.
 * @param ta The unlocking #task.
 * @param tb The #task that will be unlocked.
 */
68
69
void scheduler_addunlock(struct scheduler *s, struct task *ta,
                         struct task *tb) {
70
71
72
73
74
#ifdef SWIFT_DEBUG_CHECKS
  if (ta == NULL) error("Unlocking task is NULL.");
  if (tb == NULL) error("Unlocked task is NULL.");
#endif

75
76
77
78
79
  /* Get an index at which to store this unlock. */
  const int ind = atomic_inc(&s->nr_unlocks);

  /* Does the buffer need to be grown? */
  if (ind == s->size_unlocks) {
80
    /* Allocate the new buffer. */
81
82
83
    struct task **unlocks_new;
    int *unlock_ind_new;
    const int size_unlocks_new = s->size_unlocks * 2;
84
85
    if ((unlocks_new = (struct task **)malloc(sizeof(struct task *) *
                                              size_unlocks_new)) == NULL ||
86
87
        (unlock_ind_new = (int *)malloc(sizeof(int) * size_unlocks_new)) ==
            NULL)
88
      error("Failed to re-allocate unlocks.");
89

90
    /* Wait for all writes to the old buffer to complete. */
91
92
93
    while (s->completed_unlock_writes < ind)
      ;

94
    /* Copy the buffers. */
95
96
97
98
99
100
    memcpy(unlocks_new, s->unlocks, sizeof(struct task *) * ind);
    memcpy(unlock_ind_new, s->unlock_ind, sizeof(int) * ind);
    free(s->unlocks);
    free(s->unlock_ind);
    s->unlocks = unlocks_new;
    s->unlock_ind = unlock_ind_new;
101

102
    /* Publish the new buffer size. */
103
104
    s->size_unlocks = size_unlocks_new;
  }
105

106
  /* Wait for there to actually be space at my index. */
107
108
  while (ind > s->size_unlocks)
    ;
109
110
111
112

  /* Write the unlock to the scheduler. */
  s->unlocks[ind] = tb;
  s->unlock_ind[ind] = ta - s->tasks;
113
  atomic_inc(&s->completed_unlock_writes);
114
115
}

116
117
118
/**
 * @brief Write a dot file with the task dependencies.
 *
Matthieu Schaller's avatar
Matthieu Schaller committed
119
120
121
 * Run plot_task_dependencies.sh for an example of how to use it
 * to generate the figure.
 *
122
 * @param s The #scheduler we are working in.
Matthieu Schaller's avatar
Matthieu Schaller committed
123
 * @param verbose Are we verbose about this?
124
 */
Matthieu Schaller's avatar
Matthieu Schaller committed
125
void scheduler_write_dependencies(struct scheduler *s, int verbose) {
Matthieu Schaller's avatar
Matthieu Schaller committed
126

Matthieu Schaller's avatar
Matthieu Schaller committed
127
  const ticks tic = getticks();
128

Matthieu Schaller's avatar
Matthieu Schaller committed
129
130
  /* Conservative number of dependencies per task type */
  const int max_nber_dep = 128;
lhausamm's avatar
lhausamm committed
131

Peter W. Draper's avatar
Peter W. Draper committed
132
  /* Number of possible relations between tasks */
Matthieu Schaller's avatar
Matthieu Schaller committed
133
134
  const int nber_relation =
      2 * task_type_count * task_subtype_count * max_nber_dep;
135

Matthieu Schaller's avatar
Matthieu Schaller committed
136
137
138
139
  /* To get the table of max_nber_dep for a task:
   * ind = (ta * task_subtype_count + sa) * max_nber_dep * 2
   * where ta is the value of task_type and sa is the value of
   * task_subtype  */
140
  int *table = (int *)malloc(nber_relation * sizeof(int));
Matthieu Schaller's avatar
Matthieu Schaller committed
141
142
  if (table == NULL)
    error("Error allocating memory for task-dependency graph.");
lhausamm's avatar
lhausamm committed
143

Matthieu Schaller's avatar
Matthieu Schaller committed
144
145
  /* Reset everything */
  for (int i = 0; i < nber_relation; i++) table[i] = -1;
lhausamm's avatar
lhausamm committed
146

Matthieu Schaller's avatar
Matthieu Schaller committed
147
  /* Create file */
148
  char filename[200] = "dependency_graph.dot";
Matthieu Schaller's avatar
Matthieu Schaller committed
149
  FILE *f = fopen(filename, "w");
Peter W. Draper's avatar
Peter W. Draper committed
150
  if (f == NULL) error("Error opening dependency graph file.");
151

Matthieu Schaller's avatar
Matthieu Schaller committed
152
  /* Write header */
153
  fprintf(f, "digraph task_dep {\n");
154
  fprintf(f, "label=\"Task dependencies for SWIFT %s\";\n", git_revision());
155
156
157
158
159
  fprintf(f, "\t compound=true;\n");
  fprintf(f, "\t ratio=0.66;\n");
  fprintf(f, "\t node[nodesep=0.15];\n");

  /* loop over all tasks */
Matthieu Schaller's avatar
Matthieu Schaller committed
160
161
  for (int i = 0; i < s->nr_tasks; i++) {
    const struct task *ta = &s->tasks[i];
lhausamm's avatar
lhausamm committed
162

Peter W. Draper's avatar
Peter W. Draper committed
163
    /* and their dependencies */
Matthieu Schaller's avatar
Matthieu Schaller committed
164
165
    for (int j = 0; j < ta->nr_unlock_tasks; j++) {
      const struct task *tb = ta->unlock_tasks[j];
lhausamm's avatar
lhausamm committed
166
167

      /* check if dependency already written */
168
      int written = 0;
lhausamm's avatar
lhausamm committed
169

170
      /* Current index */
171
172
      int ind = ta->type * task_subtype_count + ta->subtype;
      ind *= 2 * max_nber_dep;
lhausamm's avatar
lhausamm committed
173

174
175
      int k = 0;
      int *cur = &table[ind];
lhausamm's avatar
lhausamm committed
176
      while (k < max_nber_dep) {
Matthieu Schaller's avatar
Matthieu Schaller committed
177

lhausamm's avatar
lhausamm committed
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
        /* not written yet */
        if (cur[0] == -1) {
          cur[0] = tb->type;
          cur[1] = tb->subtype;
          break;
        }

        /* already written */
        if (cur[0] == tb->type && cur[1] == tb->subtype) {
          written = 1;
          break;
        }

        k += 1;
        cur = &cur[3];
      }
194
195
196

      /* max_nber_dep is too small */
      if (k == max_nber_dep)
lhausamm's avatar
lhausamm committed
197
198
        error("Not enough memory, please increase max_nber_dep");

lhausamm's avatar
lhausamm committed
199
      /* Not written yet => write it */
200
      if (!written) {
Matthieu Schaller's avatar
Matthieu Schaller committed
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

        /* text to write */
        char ta_name[200];
        char tb_name[200];

        /* construct line */
        if (ta->subtype == task_subtype_none)
          sprintf(ta_name, "%s", taskID_names[ta->type]);
        else
          sprintf(ta_name, "\"%s %s\"", taskID_names[ta->type],
                  subtaskID_names[ta->subtype]);

        if (tb->subtype == task_subtype_none)
          sprintf(tb_name, "%s", taskID_names[tb->type]);
        else
          sprintf(tb_name, "\"%s %s\"", taskID_names[tb->type],
                  subtaskID_names[tb->subtype]);

        /* Write to the ffile */
        fprintf(f, "\t %s->%s;\n", ta_name, tb_name);
221

Matthieu Schaller's avatar
Matthieu Schaller committed
222
223
        /* Change colour of implicit tasks */
        if (ta->implicit)
224
          fprintf(f, "\t %s [style = filled];\n\t %s [color = lightgrey];\n",
Matthieu Schaller's avatar
Matthieu Schaller committed
225
226
                  ta_name, ta_name);
        if (tb->implicit)
227
          fprintf(f, "\t %s [style = filled];\n\t %s [color = lightgrey];\n",
Matthieu Schaller's avatar
Matthieu Schaller committed
228
                  tb_name, tb_name);
229
230
231
232
233
234
235
236

        /* Change shape of MPI communications */
        if (ta->type == task_type_send || ta->type == task_type_recv)
          fprintf(f, "\t \"%s %s\" [shape = diamond];\n",
                  taskID_names[ta->type], subtaskID_names[ta->subtype]);
        if (tb->type == task_type_send || tb->type == task_type_recv)
          fprintf(f, "\t \"%s %s\" [shape = diamond];\n",
                  taskID_names[tb->type], subtaskID_names[tb->subtype]);
lhausamm's avatar
lhausamm committed
237
      }
238
    }
lhausamm's avatar
lhausamm committed
239
  }
lhausamm's avatar
lhausamm committed
240

241
  int density_cluster[4] = {0};
242
  int gradient_cluster[4] = {0};
243
  int force_cluster[4] = {0};
Loic Hausammann's avatar
Loic Hausammann committed
244
245
  int gravity_cluster[5] = {0};
  int stars_density_cluster[4] = {0};
246

247
  /* Check whether we need to construct a group of tasks */
248
249
250
251
252
253
254
255
256
257
258
259
  for (int type = 0; type < task_type_count; ++type) {

    for (int subtype = 0; subtype < task_subtype_count; ++subtype) {

      const int ind = 2 * (type * task_subtype_count + subtype) * max_nber_dep;

      /* Does this task/sub-task exist? */
      if (table[ind] != -1) {

        for (int k = 0; k < 4; ++k) {
          if (type == task_type_self + k && subtype == task_subtype_density)
            density_cluster[k] = 1;
260
261
          if (type == task_type_self + k && subtype == task_subtype_gradient)
            gradient_cluster[k] = 1;
262
263
264
265
          if (type == task_type_self + k && subtype == task_subtype_force)
            force_cluster[k] = 1;
          if (type == task_type_self + k && subtype == task_subtype_grav)
            gravity_cluster[k] = 1;
Loic Hausammann's avatar
Loic Hausammann committed
266
267
	  if (type == task_type_self + k && subtype == task_subtype_stars_density)
	    stars_density_cluster[k] = 1;
268
        }
269
        if (type == task_type_grav_mesh) gravity_cluster[2] = 1;
270
        if (type == task_type_grav_long_range) gravity_cluster[3] = 1;
271
        if (type == task_type_grav_mm) gravity_cluster[4] = 1;
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
      }
    }
  }

  /* Make a cluster for the density tasks */
  fprintf(f, "\t subgraph cluster0{\n");
  fprintf(f, "\t\t label=\"\";\n");
  for (int k = 0; k < 4; ++k)
    if (density_cluster[k])
      fprintf(f, "\t\t \"%s %s\";\n", taskID_names[task_type_self + k],
              subtaskID_names[task_subtype_density]);
  fprintf(f, "\t};\n");

  /* Make a cluster for the force tasks */
  fprintf(f, "\t subgraph cluster1{\n");
  fprintf(f, "\t\t label=\"\";\n");
  for (int k = 0; k < 4; ++k)
    if (force_cluster[k])
      fprintf(f, "\t\t \"%s %s\";\n", taskID_names[task_type_self + k],
              subtaskID_names[task_subtype_force]);
  fprintf(f, "\t};\n");

294
  /* Make a cluster for the gradient tasks */
295
296
  fprintf(f, "\t subgraph cluster2{\n");
  fprintf(f, "\t\t label=\"\";\n");
297
298
299
300
301
302
303
304
305
  for (int k = 0; k < 4; ++k)
    if (gradient_cluster[k])
      fprintf(f, "\t\t \"%s %s\";\n", taskID_names[task_type_self + k],
              subtaskID_names[task_subtype_gradient]);
  fprintf(f, "\t};\n");

  /* Make a cluster for the gravity tasks */
  fprintf(f, "\t subgraph cluster3{\n");
  fprintf(f, "\t\t label=\"\";\n");
306
307
308
309
310
  for (int k = 0; k < 2; ++k)
    if (gravity_cluster[k])
      fprintf(f, "\t\t \"%s %s\";\n", taskID_names[task_type_self + k],
              subtaskID_names[task_subtype_grav]);
  if (gravity_cluster[2])
311
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_mesh]);
312
313
  if (gravity_cluster[3])
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_long_range]);
314
315
  if (gravity_cluster[4])
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_mm]);
316
317
  fprintf(f, "\t};\n");

318
  /* Make a cluster for the density tasks */
319
  fprintf(f, "\t subgraph cluster4{\n");
320
321
  fprintf(f, "\t\t label=\"\";\n");
  for (int k = 0; k < 4; ++k)
Loic Hausammann's avatar
Loic Hausammann committed
322
    if (stars_density_cluster[k])
323
      fprintf(f, "\t\t \"%s %s\";\n", taskID_names[task_type_self + k],
Loic Hausammann's avatar
Loic Hausammann committed
324
              subtaskID_names[task_subtype_stars_density]);
325
326
  fprintf(f, "\t};\n");

Matthieu Schaller's avatar
Matthieu Schaller committed
327
  /* Be clean */
328
329
  fprintf(f, "}");
  fclose(f);
330
  free(table);
Matthieu Schaller's avatar
Matthieu Schaller committed
331

Matthieu Schaller's avatar
Matthieu Schaller committed
332
  if (verbose)
Matthieu Schaller's avatar
Matthieu Schaller committed
333
    message("Printing task graph took %.3f %s.",
Matthieu Schaller's avatar
Matthieu Schaller committed
334
            clocks_from_ticks(getticks() - tic), clocks_getunit());
335
336
}

337
/**
338
 * @brief Split a hydrodynamic task if too large.
339
 *
340
341
 * @param t The #task
 * @param s The #scheduler we are working in.
342
 */
343
static void scheduler_splittask_hydro(struct task *t, struct scheduler *s) {
344

345
346
347
  /* Iterate on this task until we're done with it. */
  int redo = 1;
  while (redo) {
348

349
350
    /* Reset the redo flag. */
    redo = 0;
351

352
    /* Non-splittable task? */
353
354
    if ((t->ci == NULL) || (t->type == task_type_pair && t->cj == NULL) ||
        t->ci->count == 0 || (t->cj != NULL && t->cj->count == 0)) {
355
      t->type = task_type_none;
356
357
      t->subtype = task_subtype_none;
      t->cj = NULL;
358
359
360
      t->skip = 1;
      break;
    }
361

362
363
    /* Self-interaction? */
    if (t->type == task_type_self) {
364

365
366
367
368
369
      /* Get a handle on the cell involved. */
      struct cell *ci = t->ci;

      /* Foreign task? */
      if (ci->nodeID != s->nodeID) {
370
        t->skip = 1;
371
        break;
372
373
      }

374
      /* Is this cell even split and the task does not violate h ? */
375
      if (cell_can_split_self_hydro_task(ci)) {
376

377
        /* Make a sub? */
378
        if (scheduler_dosub && ci->count < space_subsize_self_hydro) {
379

380
381
382
383
384
          /* convert to a self-subtask. */
          t->type = task_type_sub_self;

          /* Otherwise, make tasks explicitly. */
        } else {
385

386
387
388
389
390
391
392
393
          /* Take a step back (we're going to recycle the current task)... */
          redo = 1;

          /* Add the self tasks. */
          int first_child = 0;
          while (ci->progeny[first_child] == NULL) first_child++;
          t->ci = ci->progeny[first_child];
          for (int k = first_child + 1; k < 8; k++)
394
            if (ci->progeny[k] != NULL && ci->progeny[k]->count)
395
              scheduler_splittask_hydro(
396
                  scheduler_addtask(s, task_type_self, t->subtype, 0, 0,
397
                                    ci->progeny[k], NULL),
398
399
                  s);

400
401
          /* Make a task for each pair of progeny */
          for (int j = 0; j < 8; j++)
402
            if (ci->progeny[j] != NULL && ci->progeny[j]->count)
403
              for (int k = j + 1; k < 8; k++)
404
                if (ci->progeny[k] != NULL && ci->progeny[k]->count)
405
406
                  scheduler_splittask_hydro(
                      scheduler_addtask(s, task_type_pair, t->subtype,
407
                                        sub_sid_flag[j][k], 0, ci->progeny[j],
408
409
                                        ci->progeny[k]),
                      s);
410
        }
411
      } /* Cell is split */
412

413
    } /* Self interaction */
414

415
416
    /* Pair interaction? */
    else if (t->type == task_type_pair) {
417

418
419
420
      /* Get a handle on the cells involved. */
      struct cell *ci = t->ci;
      struct cell *cj = t->cj;
421

422
423
424
425
426
      /* Foreign task? */
      if (ci->nodeID != s->nodeID && cj->nodeID != s->nodeID) {
        t->skip = 1;
        break;
      }
427

428
429
430
      /* Get the sort ID, use space_getsid and not t->flags
         to make sure we get ci and cj swapped if needed. */
      double shift[3];
Matthieu Schaller's avatar
Matthieu Schaller committed
431
      const int sid = space_getsid(s->space, &ci, &cj, shift);
432

433
      /* Should this task be split-up? */
Matthieu Schaller's avatar
Matthieu Schaller committed
434
435
      if (cell_can_split_pair_hydro_task(ci) &&
          cell_can_split_pair_hydro_task(cj)) {
436
437

        /* Replace by a single sub-task? */
438
        if (scheduler_dosub && /* Use division to avoid integer overflow. */
439
            ci->count * sid_scale[sid] < space_subsize_pair_hydro / cj->count &&
440
            !sort_is_corner(sid)) {
441
442
443
444
445

          /* Make this task a sub task. */
          t->type = task_type_sub_pair;

          /* Otherwise, split it. */
446
447
        } else {

448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
          /* Take a step back (we're going to recycle the current task)... */
          redo = 1;

          /* For each different sorting type... */
          switch (sid) {

            case 0: /* (  1 ,  1 ,  1 ) */
              t->ci = ci->progeny[7];
              t->cj = cj->progeny[0];
              t->flags = 0;
              break;

            case 1: /* (  1 ,  1 ,  0 ) */
              t->ci = ci->progeny[6];
              t->cj = cj->progeny[0];
              t->flags = 1;
464
              scheduler_splittask_hydro(
465
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
466
                                    ci->progeny[7], cj->progeny[1]),
467
                  s);
468
              scheduler_splittask_hydro(
469
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
470
                                    ci->progeny[6], cj->progeny[1]),
471
                  s);
472
              scheduler_splittask_hydro(
473
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
474
                                    ci->progeny[7], cj->progeny[0]),
475
476
477
478
479
480
481
482
483
484
485
486
487
                  s);
              break;

            case 2: /* (  1 ,  1 , -1 ) */
              t->ci = ci->progeny[6];
              t->cj = cj->progeny[1];
              t->flags = 2;
              break;

            case 3: /* (  1 ,  0 ,  1 ) */
              t->ci = ci->progeny[5];
              t->cj = cj->progeny[0];
              t->flags = 3;
488
              scheduler_splittask_hydro(
489
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
490
                                    ci->progeny[7], cj->progeny[2]),
491
                  s);
492
              scheduler_splittask_hydro(
493
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
494
                                    ci->progeny[5], cj->progeny[2]),
495
                  s);
496
              scheduler_splittask_hydro(
497
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
498
                                    ci->progeny[7], cj->progeny[0]),
499
500
501
502
503
504
505
                  s);
              break;

            case 4: /* (  1 ,  0 ,  0 ) */
              t->ci = ci->progeny[4];
              t->cj = cj->progeny[0];
              t->flags = 4;
506
              scheduler_splittask_hydro(
507
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
508
                                    ci->progeny[5], cj->progeny[0]),
509
                  s);
510
              scheduler_splittask_hydro(
511
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
512
                                    ci->progeny[6], cj->progeny[0]),
513
                  s);
514
              scheduler_splittask_hydro(
515
                  scheduler_addtask(s, task_type_pair, t->subtype, 8, 0,
516
                                    ci->progeny[7], cj->progeny[0]),
517
                  s);
518
              scheduler_splittask_hydro(
519
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
520
                                    ci->progeny[4], cj->progeny[1]),
521
                  s);
522
              scheduler_splittask_hydro(
523
                  scheduler_addtask(s, task_type_pair, t->subtype, 4, 0,
524
                                    ci->progeny[5], cj->progeny[1]),
525
                  s);
526
              scheduler_splittask_hydro(
527
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
528
                                    ci->progeny[6], cj->progeny[1]),
529
                  s);
530
              scheduler_splittask_hydro(
531
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
532
                                    ci->progeny[7], cj->progeny[1]),
533
                  s);
534
              scheduler_splittask_hydro(
535
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
536
                                    ci->progeny[4], cj->progeny[2]),
537
                  s);
538
              scheduler_splittask_hydro(
539
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
540
                                    ci->progeny[5], cj->progeny[2]),
541
                  s);
542
              scheduler_splittask_hydro(
543
                  scheduler_addtask(s, task_type_pair, t->subtype, 4, 0,
544
                                    ci->progeny[6], cj->progeny[2]),
545
                  s);
546
              scheduler_splittask_hydro(
547
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
548
                                    ci->progeny[7], cj->progeny[2]),
549
                  s);
550
              scheduler_splittask_hydro(
551
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
552
                                    ci->progeny[4], cj->progeny[3]),
553
                  s);
554
              scheduler_splittask_hydro(
555
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
556
                                    ci->progeny[5], cj->progeny[3]),
557
                  s);
558
              scheduler_splittask_hydro(
559
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
560
                                    ci->progeny[6], cj->progeny[3]),
561
                  s);
562
              scheduler_splittask_hydro(
563
                  scheduler_addtask(s, task_type_pair, t->subtype, 4, 0,
564
                                    ci->progeny[7], cj->progeny[3]),
565
566
567
568
569
570
571
                  s);
              break;

            case 5: /* (  1 ,  0 , -1 ) */
              t->ci = ci->progeny[4];
              t->cj = cj->progeny[1];
              t->flags = 5;
572
              scheduler_splittask_hydro(
573
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
574
                                    ci->progeny[6], cj->progeny[3]),
575
                  s);
576
              scheduler_splittask_hydro(
577
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
578
                                    ci->progeny[4], cj->progeny[3]),
579
                  s);
580
              scheduler_splittask_hydro(
581
                  scheduler_addtask(s, task_type_pair, t->subtype, 8, 0,
582
                                    ci->progeny[6], cj->progeny[1]),
583
584
585
586
587
588
589
590
591
592
593
594
595
                  s);
              break;

            case 6: /* (  1 , -1 ,  1 ) */
              t->ci = ci->progeny[5];
              t->cj = cj->progeny[2];
              t->flags = 6;
              break;

            case 7: /* (  1 , -1 ,  0 ) */
              t->ci = ci->progeny[4];
              t->cj = cj->progeny[3];
              t->flags = 6;
596
              scheduler_splittask_hydro(
597
                  scheduler_addtask(s, task_type_pair, t->subtype, 8, 0,
598
                                    ci->progeny[5], cj->progeny[2]),
599
                  s);
600
              scheduler_splittask_hydro(
601
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
602
                                    ci->progeny[4], cj->progeny[2]),
603
                  s);
604
              scheduler_splittask_hydro(
605
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
606
                                    ci->progeny[5], cj->progeny[3]),
607
608
609
610
611
612
613
614
615
616
617
618
619
                  s);
              break;

            case 8: /* (  1 , -1 , -1 ) */
              t->ci = ci->progeny[4];
              t->cj = cj->progeny[3];
              t->flags = 8;
              break;

            case 9: /* (  0 ,  1 ,  1 ) */
              t->ci = ci->progeny[3];
              t->cj = cj->progeny[0];
              t->flags = 9;
620
              scheduler_splittask_hydro(
621
                  scheduler_addtask(s, task_type_pair, t->subtype, 9, 0,
622
                                    ci->progeny[7], cj->progeny[4]),
623
                  s);
624
              scheduler_splittask_hydro(
625
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
626
                                    ci->progeny[3], cj->progeny[4]),
627
                  s);
628
              scheduler_splittask_hydro(
629
                  scheduler_addtask(s, task_type_pair, t->subtype, 8, 0,
630
                                    ci->progeny[7], cj->progeny[0]),
631
632
633
634
635
636
637
                  s);
              break;

            case 10: /* (  0 ,  1 ,  0 ) */
              t->ci = ci->progeny[2];
              t->cj = cj->progeny[0];
              t->flags = 10;
638
              scheduler_splittask_hydro(
639
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
640
                                    ci->progeny[3], cj->progeny[0]),
641
                  s);
642
              scheduler_splittask_hydro(
643
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
644
                                    ci->progeny[6], cj->progeny[0]),
645
                  s);
646
              scheduler_splittask_hydro(
647
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
648
                                    ci->progeny[7], cj->progeny[0]),
649
                  s);
650
              scheduler_splittask_hydro(
651
                  scheduler_addtask(s, task_type_pair, t->subtype, 9, 0,
652
                                    ci->progeny[2], cj->progeny[1]),
653
                  s);
654
              scheduler_splittask_hydro(
655
                  scheduler_addtask(s, task_type_pair, t->subtype, 10, 0,
656
                                    ci->progeny[3], cj->progeny[1]),
657
                  s);
658
              scheduler_splittask_hydro(
659
                  scheduler_addtask(s, task_type_pair, t->subtype, 8, 0,
660
                                    ci->progeny[6], cj->progeny[1]),
661
                  s);
662
              scheduler_splittask_hydro(
663
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
664
                                    ci->progeny[7], cj->progeny[1]),
665
                  s);
666
              scheduler_splittask_hydro(
667
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
668
                                    ci->progeny[2], cj->progeny[4]),
669
                  s);
670
              scheduler_splittask_hydro(
671
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
672
                                    ci->progeny[3], cj->progeny[4]),
673
                  s);
674
              scheduler_splittask_hydro(
675
                  scheduler_addtask(s, task_type_pair, t->subtype, 10, 0,
676
                                    ci->progeny[6], cj->progeny[4]),
677
                  s);
678
              scheduler_splittask_hydro(
679
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
680
                                    ci->progeny[7], cj->progeny[4]),
681
                  s);
682
              scheduler_splittask_hydro(
683
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
684
                                    ci->progeny[2], cj->progeny[5]),
685
                  s);
686
              scheduler_splittask_hydro(
687
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
688
                                    ci->progeny[3], cj->progeny[5]),
689
                  s);
690
              scheduler_splittask_hydro(
691
                  scheduler_addtask(s, task_type_pair, t->subtype, 9, 0,
692
                                    ci->progeny[6], cj->progeny[5]),
693
                  s);
694
              scheduler_splittask_hydro(
695
                  scheduler_addtask(s, task_type_pair, t->subtype, 10, 0,
696
                                    ci->progeny[7], cj->progeny[5]),
697
698
699
700
701
702
703
                  s);
              break;

            case 11: /* (  0 ,  1 , -1 ) */
              t->ci = ci->progeny[2];
              t->cj = cj->progeny[1];
              t->flags = 11;
704
              scheduler_splittask_hydro(
705
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
706
                                    ci->progeny[6], cj->progeny[5]),
707
                  s);
708
              scheduler_splittask_hydro(
709
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
710
                                    ci->progeny[2], cj->progeny[5]),
711
                  s);
712
              scheduler_splittask_hydro(
713
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
714
                                    ci->progeny[6], cj->progeny[1]),
715
716
717
718
719
720
721
                  s);
              break;

            case 12: /* (  0 ,  0 ,  1 ) */
              t->ci = ci->progeny[1];
              t->cj = cj->progeny[0];
              t->flags = 12;
722
              scheduler_splittask_hydro(
723
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
724
                                    ci->progeny[3], cj->progeny[0]),
725
                  s);
726
              scheduler_splittask_hydro(
727
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
728
                                    ci->progeny[5], cj->progeny[0]),
729
                  s);
730
              scheduler_splittask_hydro(
731
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
732
                                    ci->progeny[7], cj->progeny[0]),
733
                  s);
734
              scheduler_splittask_hydro(
735
                  scheduler_addtask(s, task_type_pair, t->subtype, 9, 0,
736
                                    ci->progeny[1], cj->progeny[2]),
737
                  s);
738
              scheduler_splittask_hydro(
739
                  scheduler_addtask(s, task_type_pair, t->subtype, 12, 0,
740
                                    ci->progeny[3], cj->progeny[2]),
741
                  s);
742
              scheduler_splittask_hydro(
743
                  scheduler_addtask(s, task_type_pair, t->subtype, 8, 0,
744
                                    ci->progeny[5], cj->progeny[2]),
745
                  s);
746
              scheduler_splittask_hydro(
747
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
748
                                    ci->progeny[7], cj->progeny[2]),
749
                  s);
750
              scheduler_splittask_hydro(
751
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
752
                                    ci->progeny[1], cj->progeny[4]),
753
                  s);
754
              scheduler_splittask_hydro(
755
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
756
                                    ci->progeny[3], cj->progeny[4]),
757
                  s);
758
              scheduler_splittask_hydro(
759
                  scheduler_addtask(s, task_type_pair, t->subtype, 12, 0,
760
                                    ci->progeny[5], cj->progeny[4]),
761
                  s);
762
              scheduler_splittask_hydro(
763
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,