scheduler.c 90.4 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 generate the dependency name for the tasks
 *
Matthieu Schaller's avatar
Matthieu Schaller committed
119
120
121
 * @param ta_type The #task type.
 * @param ta_subtype The #task type.
 * @param ta_name (return) The formatted string
122
 */
123
void scheduler_task_dependency_name(int ta_type, int ta_subtype,
124
                                    char *ta_name) {
125
126

  /* Check input */
127
128
  if ((ta_type < 0) || (ta_type >= task_type_count))
    error("Unknown task type %i", ta_type);
129

130
  if ((ta_subtype < 0) || (ta_subtype >= task_subtype_count))
131
    error("Unknown task subtype %i with type %s", ta_subtype,
132
133
          taskID_names[ta_type]);

134
135
136
137
138
  /* 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],
139
            subtaskID_names[ta_subtype]);
140
141
}

142
143
144
/**
 * @brief Write a dot file with the task dependencies.
 *
Matthieu Schaller's avatar
Matthieu Schaller committed
145
146
147
 * Run plot_task_dependencies.sh for an example of how to use it
 * to generate the figure.
 *
148
 * @param s The #scheduler we are working in.
Matthieu Schaller's avatar
Matthieu Schaller committed
149
 * @param verbose Are we verbose about this?
150
 */
Matthieu Schaller's avatar
Matthieu Schaller committed
151
void scheduler_write_dependencies(struct scheduler *s, int verbose) {
Matthieu Schaller's avatar
Matthieu Schaller committed
152

Matthieu Schaller's avatar
Matthieu Schaller committed
153
  const ticks tic = getticks();
154

Matthieu Schaller's avatar
Matthieu Schaller committed
155
156
  /* Conservative number of dependencies per task type */
  const int max_nber_dep = 128;
lhausamm's avatar
lhausamm committed
157

Peter W. Draper's avatar
Peter W. Draper committed
158
  /* Number of possible relations between tasks */
Matthieu Schaller's avatar
Matthieu Schaller committed
159
160
  const int nber_relation =
      2 * task_type_count * task_subtype_count * max_nber_dep;
161

Matthieu Schaller's avatar
Matthieu Schaller committed
162
163
164
165
  /* 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  */
166
  int *table = (int *)malloc(nber_relation * sizeof(int));
Matthieu Schaller's avatar
Matthieu Schaller committed
167
  if (table == NULL)
168
169
170
171
172
    error("Error allocating memory for task-dependency graph (table).");

  int *count_rel = (int *)malloc(nber_relation * sizeof(int) / 2);
  if (count_rel == NULL)
    error("Error allocating memory for task-dependency graph (count_rel).");
lhausamm's avatar
lhausamm committed
173

Matthieu Schaller's avatar
Matthieu Schaller committed
174
175
  /* Reset everything */
  for (int i = 0; i < nber_relation; i++) table[i] = -1;
176
  for (int i = 0; i < nber_relation / 2; i++) count_rel[i] = 0;
lhausamm's avatar
lhausamm committed
177

Matthieu Schaller's avatar
Matthieu Schaller committed
178
  /* Create file */
179
  char filename[200] = "dependency_graph.dot";
Matthieu Schaller's avatar
Matthieu Schaller committed
180
  FILE *f = fopen(filename, "w");
Peter W. Draper's avatar
Peter W. Draper committed
181
  if (f == NULL) error("Error opening dependency graph file.");
182

Matthieu Schaller's avatar
Matthieu Schaller committed
183
  /* Write header */
184
  fprintf(f, "digraph task_dep {\n");
185
  fprintf(f, "label=\"Task dependencies for SWIFT %s\";\n", git_revision());
186
187
188
189
190
  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
191
192
  for (int i = 0; i < s->nr_tasks; i++) {
    const struct task *ta = &s->tasks[i];
lhausamm's avatar
lhausamm committed
193

Peter W. Draper's avatar
Peter W. Draper committed
194
    /* and their dependencies */
Matthieu Schaller's avatar
Matthieu Schaller committed
195
196
    for (int j = 0; j < ta->nr_unlock_tasks; j++) {
      const struct task *tb = ta->unlock_tasks[j];
lhausamm's avatar
lhausamm committed
197
198

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

201
      /* Current index */
202
203
      int ind = ta->type * task_subtype_count + ta->subtype;
      ind *= 2 * max_nber_dep;
lhausamm's avatar
lhausamm committed
204

205
206
      int k = 0;
      int *cur = &table[ind];
lhausamm's avatar
lhausamm committed
207
      while (k < max_nber_dep) {
Matthieu Schaller's avatar
Matthieu Schaller committed
208

lhausamm's avatar
lhausamm committed
209
210
211
212
213
214
215
216
217
218
219
220
221
222
        /* 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;
223
        cur = &cur[2];
lhausamm's avatar
lhausamm committed
224
      }
225
226
227

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

230
      /* Increase counter of relation */
231
      count_rel[ind / 2 + k] += 1;
232

lhausamm's avatar
lhausamm committed
233
      /* Not written yet => write it */
234
      if (!written) {
Matthieu Schaller's avatar
Matthieu Schaller committed
235
236
237
238
239
240

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

        /* construct line */
241
242
        scheduler_task_dependency_name(ta->type, ta->subtype, ta_name);
        scheduler_task_dependency_name(tb->type, tb->subtype, tb_name);
243

Matthieu Schaller's avatar
Matthieu Schaller committed
244
245
        /* Change colour of implicit tasks */
        if (ta->implicit)
246
          fprintf(f, "\t %s [style = filled];\n\t %s [color = lightgrey];\n",
Matthieu Schaller's avatar
Matthieu Schaller committed
247
248
                  ta_name, ta_name);
        if (tb->implicit)
249
          fprintf(f, "\t %s [style = filled];\n\t %s [color = lightgrey];\n",
Matthieu Schaller's avatar
Matthieu Schaller committed
250
                  tb_name, tb_name);
251
252
253
254
255
256
257
258

        /* 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
259
      }
260
    }
lhausamm's avatar
lhausamm committed
261
  }
lhausamm's avatar
lhausamm committed
262

263
  int density_cluster[4] = {0};
264
  int gradient_cluster[4] = {0};
265
  int force_cluster[4] = {0};
Loic Hausammann's avatar
Loic Hausammann committed
266
267
  int gravity_cluster[5] = {0};
  int stars_density_cluster[4] = {0};
268

269
  /* Check whether we need to construct a group of tasks */
270
271
272
273
274
275
276
277
278
279
280
281
  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;
282
283
          if (type == task_type_self + k && subtype == task_subtype_gradient)
            gradient_cluster[k] = 1;
284
285
286
287
          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;
288
289
290
          if (type == task_type_self + k &&
              subtype == task_subtype_stars_density)
            stars_density_cluster[k] = 1;
291
        }
292
        if (type == task_type_grav_mesh) gravity_cluster[2] = 1;
293
        if (type == task_type_grav_long_range) gravity_cluster[3] = 1;
294
        if (type == task_type_grav_mm) gravity_cluster[4] = 1;
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
      }
    }
  }

  /* 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");

317
  /* Make a cluster for the gradient tasks */
318
319
  fprintf(f, "\t subgraph cluster2{\n");
  fprintf(f, "\t\t label=\"\";\n");
320
321
322
323
324
325
326
327
328
  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");
329
330
331
332
333
  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])
334
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_mesh]);
335
336
  if (gravity_cluster[3])
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_long_range]);
337
338
  if (gravity_cluster[4])
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_mm]);
339
340
  fprintf(f, "\t};\n");

341
  /* Make a cluster for the density tasks */
342
  fprintf(f, "\t subgraph cluster4{\n");
343
344
  fprintf(f, "\t\t label=\"\";\n");
  for (int k = 0; k < 4; ++k)
Loic Hausammann's avatar
Loic Hausammann committed
345
    if (stars_density_cluster[k])
346
      fprintf(f, "\t\t \"%s %s\";\n", taskID_names[task_type_self + k],
Loic Hausammann's avatar
Loic Hausammann committed
347
              subtaskID_names[task_subtype_stars_density]);
348
349
  fprintf(f, "\t};\n");

Matthieu Schaller's avatar
Matthieu Schaller committed
350
  /* Write down the number of relation */
351
352
353
354
355
  for (int ta_type = 0; ta_type < task_type_count; ta_type++) {

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

      /* Get task indice */
356
357
      const int ind =
          (ta_type * task_subtype_count + ta_subtype) * max_nber_dep;
358
359
360
361

      /* Loop over dependencies */
      for (int k = 0; k < max_nber_dep; k++) {

362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
        if (count_rel[ind + k] == 0) continue;

        /* Get task type */
        const int i = 2 * (ind + k);
        int tb_type = table[i];
        int tb_subtype = table[i + 1];

        /* Get names */
        char ta_name[200];
        char tb_name[200];

        scheduler_task_dependency_name(ta_type, ta_subtype, ta_name);
        scheduler_task_dependency_name(tb_type, tb_subtype, tb_name);

        /* Write to the fle */
        fprintf(f, "\t %s->%s[label=%i];\n", ta_name, tb_name,
                count_rel[ind + k]);
379
380
381
382
      }
    }
  }

383
  /* Close the file */
384
385
  fprintf(f, "}");
  fclose(f);
386
387

  /* Be clean */
388
  free(table);
389
  free(count_rel);
Matthieu Schaller's avatar
Matthieu Schaller committed
390

Matthieu Schaller's avatar
Matthieu Schaller committed
391
  if (verbose)
Matthieu Schaller's avatar
Matthieu Schaller committed
392
    message("Printing task graph took %.3f %s.",
Matthieu Schaller's avatar
Matthieu Schaller committed
393
            clocks_from_ticks(getticks() - tic), clocks_getunit());
394
395
}

396
/**
397
 * @brief Split a hydrodynamic task if too large.
398
 *
399
400
 * @param t The #task
 * @param s The #scheduler we are working in.
401
 */
402
static void scheduler_splittask_hydro(struct task *t, struct scheduler *s) {
403

404
405
406
  /* Iterate on this task until we're done with it. */
  int redo = 1;
  while (redo) {
407

408
409
    /* Reset the redo flag. */
    redo = 0;
410

411
    /* Non-splittable task? */
412
    if ((t->ci == NULL) || (t->type == task_type_pair && t->cj == NULL) ||
413
        t->ci->hydro.count == 0 || (t->cj != NULL && t->cj->hydro.count == 0)) {
414
      t->type = task_type_none;
415
416
      t->subtype = task_subtype_none;
      t->cj = NULL;
417
418
419
      t->skip = 1;
      break;
    }
420

421
422
    /* Self-interaction? */
    if (t->type == task_type_self) {
423

424
425
426
427
428
      /* Get a handle on the cell involved. */
      struct cell *ci = t->ci;

      /* Foreign task? */
      if (ci->nodeID != s->nodeID) {
429
        t->skip = 1;
430
        break;
431
432
      }

433
      /* Is this cell even split and the task does not violate h ? */
434
      if (cell_can_split_self_hydro_task(ci)) {
435

436
        /* Make a sub? */
437
        if (scheduler_dosub && ci->hydro.count < space_subsize_self_hydro) {
438

439
440
441
442
443
          /* convert to a self-subtask. */
          t->type = task_type_sub_self;

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

445
446
447
448
449
450
451
452
          /* 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++)
453
            if (ci->progeny[k] != NULL && ci->progeny[k]->hydro.count)
454
              scheduler_splittask_hydro(
455
                  scheduler_addtask(s, task_type_self, t->subtype, 0, 0,
456
                                    ci->progeny[k], NULL),
457
458
                  s);

459
460
          /* Make a task for each pair of progeny */
          for (int j = 0; j < 8; j++)
461
            if (ci->progeny[j] != NULL && ci->progeny[j]->hydro.count)
462
              for (int k = j + 1; k < 8; k++)
463
                if (ci->progeny[k] != NULL && ci->progeny[k]->hydro.count)
464
465
                  scheduler_splittask_hydro(
                      scheduler_addtask(s, task_type_pair, t->subtype,
466
                                        sub_sid_flag[j][k], 0, ci->progeny[j],
467
468
                                        ci->progeny[k]),
                      s);
469
        }
470
      } /* Cell is split */
471

472
    } /* Self interaction */
473

474
475
    /* Pair interaction? */
    else if (t->type == task_type_pair) {
476

477
478
479
      /* Get a handle on the cells involved. */
      struct cell *ci = t->ci;
      struct cell *cj = t->cj;
480

481
482
483
484
485
      /* Foreign task? */
      if (ci->nodeID != s->nodeID && cj->nodeID != s->nodeID) {
        t->skip = 1;
        break;
      }
486

487
488
489
      /* 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
490
      const int sid = space_getsid(s->space, &ci, &cj, shift);
491

492
      /* Should this task be split-up? */
Matthieu Schaller's avatar
Matthieu Schaller committed
493
494
      if (cell_can_split_pair_hydro_task(ci) &&
          cell_can_split_pair_hydro_task(cj)) {
495
496

        /* Replace by a single sub-task? */
497
        if (scheduler_dosub && /* Use division to avoid integer overflow. */
498
499
            ci->hydro.count * sid_scale[sid] <
                space_subsize_pair_hydro / cj->hydro.count &&
500
            !sort_is_corner(sid)) {
501
502
503
504
505

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

          /* Otherwise, split it. */
506
507
        } else {

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

            case 4: /* (  1 ,  0 ,  0 ) */
              t->ci = ci->progeny[4];
              t->cj = cj->progeny[0];
              t->flags = 4;
566
              scheduler_splittask_hydro(
567
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
568
                                    ci->progeny[5], cj->progeny[0]),
569
                  s);
570
              scheduler_splittask_hydro(
571
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
572
                                    ci->progeny[6], cj->progeny[0]),
573
                  s);
574
              scheduler_splittask_hydro(
575
                  scheduler_addtask(s, task_type_pair, t->subtype, 8, 0,
576
                                    ci->progeny[7], cj->progeny[0]),
577
                  s);
578
              scheduler_splittask_hydro(
579
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
580
                                    ci->progeny[4], cj->progeny[1]),
581
                  s);
582
              scheduler_splittask_hydro(
583
                  scheduler_addtask(s, task_type_pair, t->subtype, 4, 0,
584
                                    ci->progeny[5], cj->progeny[1]),
585
                  s);
586
              scheduler_splittask_hydro(
587
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
588
                                    ci->progeny[6], cj->progeny[1]),
589
                  s);
590
              scheduler_splittask_hydro(
591
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
592
                                    ci->progeny[7], cj->progeny[1]),
593
                  s);
594
              scheduler_splittask_hydro(
595
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
596
                                    ci->progeny[4], cj->progeny[2]),
597
                  s);
598
              scheduler_splittask_hydro(
599
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
600
                                    ci->progeny[5], cj->progeny[2]),
601
                  s);
602
              scheduler_splittask_hydro(
603
                  scheduler_addtask(s, task_type_pair, t->subtype, 4, 0,
604
                                    ci->progeny[6], cj->progeny[2]),
605
                  s);
606
              scheduler_splittask_hydro(
607
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
608
                                    ci->progeny[7], cj->progeny[2]),
609
                  s);
610
              scheduler_splittask_hydro(
611
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
612
                                    ci->progeny[4], cj->progeny[3]),
613
                  s);
614
              scheduler_splittask_hydro(
615
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
616
                                    ci->progeny[5], cj->progeny[3]),
617
                  s);
618
              scheduler_splittask_hydro(
619
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
620
                                    ci->progeny[6], cj->progeny[3]),
621
                  s);
622
              scheduler_splittask_hydro(
623
                  scheduler_addtask(s, task_type_pair, t->subtype, 4, 0,
624
                                    ci->progeny[7], cj->progeny[3]),
625
626
627
628
629
630
631
                  s);
              break;

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

            case 10: /* (  0 ,  1 ,  0 ) */
              t->ci = ci->progeny[2];
              t->cj = cj->progeny[0];
              t->flags = 10;
698
              scheduler_splittask_hydro(
699
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
700
                                    ci->progeny[3], cj->progeny[0]),
701
                  s);
702
              scheduler_splittask_hydro(
703
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
704
                                    ci->progeny[6], cj->progeny[0]),
705
                  s);
706
              scheduler_splittask_hydro(
707
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
708
                                    ci->progeny[7], cj->progeny[0]),
709
                  s);
710
              scheduler_splittask_hydro(
711
                  scheduler_addtask(s, task_type_pair, t->subtype, 9, 0,
712
                                    ci->progeny[2], cj->progeny[1]),
713
                  s);
714
              scheduler_splittask_hydro(
715
                  scheduler_addtask(s, task_type_pair, t->subtype, 10, 0,
716
                                    ci->progeny[3], cj->progeny[1]),
717
                  s);
718
              scheduler_splittask_hydro(
719
                  scheduler_addtask(s, task_type_pair, t->subtype, 8, 0,
720
                                    ci->progeny[6], cj->progeny[1]),
721
                  s);
722
              scheduler_splittask_hydro(
723
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
724
                                    ci->progeny[7], cj->progeny[1]),
725
                  s);
726
              scheduler_splittask_hydro(
727
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
728
                                    ci->progeny[2], cj->progeny[4]),
729
                  s);
730
              scheduler_splittask_hydro(
731
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
732
                                    ci->progeny[3], cj->progeny[4]),
733
                  s);
734
              scheduler_splittask_hydro(
735
                  scheduler_addtask(s, task_type_pair, t->subtype, 10, 0,
736
                                    ci->progeny[6], cj->progeny[4]),
737
                  s);
738
              scheduler_splittask_hydro(
739
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
740
                                    ci->progeny[7], cj->progeny[4]),
741
                  s);
742
              scheduler_splittask_hydro(
743
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
744
                                    ci->progeny[2], cj->progeny[5]),
745
                  s);
746
              scheduler_splittask_hydro(
747
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
748
                                    ci->progeny[3], cj->progeny[5]),
749
                  s);
750
              scheduler_splittask_hydro(
751
                  scheduler_addtask(s, task_type_pair, t->subtype, 9, 0,
752
                                    ci->progeny[6], cj->progeny[5]),
753
                  s);
754
              scheduler_splittask_hydro(
755
                  scheduler_addtask(s, task_type_pair, t->subtype, 10, 0,
756
                                    ci->progeny[7], cj->progeny[5]),
757
758
759
760
761
762
763
                  s);
              break;

            case 11: /* (  0 ,  1 , -1 ) */
              t->ci = ci->progeny[2];
              t->cj = cj->progeny[1];
              t->flags = 11;
764
              scheduler_splittask_hydro(
765
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
766
                                    ci->progeny[6], cj->progeny[5]),
767
                  s);
768
              scheduler_splittask_hydro(
769
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
770
                                    ci->progeny[2], cj->progeny[5]),
771
                  s);
772
              scheduler_splittask_hydro(
773
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
774
                                    ci->progeny[6], cj->progeny[1]),
775
776
777
778
779
780
781
                  s);
              break;

            case 12: /* (  0 ,  0 ,  1 ) */
              t->ci = ci->progeny[1];
              t->cj = cj->progeny[0];
              t->flags = 12;
782
              scheduler_splittask_hydro(
783
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
784
                                    ci->progeny[3], cj->progeny[0]),
785
                  s);
786
              scheduler_splittask_hydro(
787
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
788
                                    ci->progeny[5], cj->progeny[0]),
789
                  s);