scheduler.c 65 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};
244
  int gravity_cluster[5] = {0};
245

246
  /* Check whether we need to construct a group of tasks */
247
248
249
250
251
252
253
254
255
256
257
258
  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;
259
260
          if (type == task_type_self + k && subtype == task_subtype_gradient)
            gradient_cluster[k] = 1;
261
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;
        }
266
        if (type == task_type_grav_mesh) gravity_cluster[2] = 1;
267
        if (type == task_type_grav_long_range) gravity_cluster[3] = 1;
268
        if (type == task_type_grav_mm) gravity_cluster[4] = 1;
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
      }
    }
  }

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

291
  /* Make a cluster for the gradient tasks */
292
293
  fprintf(f, "\t subgraph cluster2{\n");
  fprintf(f, "\t\t label=\"\";\n");
294
295
296
297
298
299
300
301
302
  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");
303
304
305
306
307
  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])
308
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_mesh]);
309
310
  if (gravity_cluster[3])
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_long_range]);
311
312
  if (gravity_cluster[4])
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_mm]);
313
314
  fprintf(f, "\t};\n");

Matthieu Schaller's avatar
Matthieu Schaller committed
315
  /* Be clean */
316
317
  fprintf(f, "}");
  fclose(f);
318
  free(table);
Matthieu Schaller's avatar
Matthieu Schaller committed
319

Matthieu Schaller's avatar
Matthieu Schaller committed
320
  if (verbose)
Matthieu Schaller's avatar
Matthieu Schaller committed
321
    message("Printing task graph took %.3f %s.",
Matthieu Schaller's avatar
Matthieu Schaller committed
322
            clocks_from_ticks(getticks() - tic), clocks_getunit());
323
324
}

325
/**
326
 * @brief Split a hydrodynamic task if too large.
327
 *
328
329
 * @param t The #task
 * @param s The #scheduler we are working in.
330
 */
331
static void scheduler_splittask_hydro(struct task *t, struct scheduler *s) {
332

333
334
335
  /* Iterate on this task until we're done with it. */
  int redo = 1;
  while (redo) {
336

337
338
    /* Reset the redo flag. */
    redo = 0;
339

340
    /* Non-splittable task? */
341
342
    if ((t->ci == NULL) || (t->type == task_type_pair && t->cj == NULL) ||
        t->ci->count == 0 || (t->cj != NULL && t->cj->count == 0)) {
343
      t->type = task_type_none;
344
345
      t->subtype = task_subtype_none;
      t->cj = NULL;
346
347
348
      t->skip = 1;
      break;
    }
349

350
351
    /* Self-interaction? */
    if (t->type == task_type_self) {
352

353
354
355
356
357
      /* Get a handle on the cell involved. */
      struct cell *ci = t->ci;

      /* Foreign task? */
      if (ci->nodeID != s->nodeID) {
358
        t->skip = 1;
359
        break;
360
361
      }

362
      /* Is this cell even split and the task does not violate h ? */
363
      if (cell_can_split_self_hydro_task(ci)) {
364

365
        /* Make a sub? */
366
        if (scheduler_dosub && ci->count < space_subsize_self_hydro) {
367

368
369
370
371
372
          /* convert to a self-subtask. */
          t->type = task_type_sub_self;

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

374
375
376
377
378
379
380
381
          /* 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++)
382
            if (ci->progeny[k] != NULL && ci->progeny[k]->count)
383
              scheduler_splittask_hydro(
384
                  scheduler_addtask(s, task_type_self, t->subtype, 0, 0,
385
                                    ci->progeny[k], NULL),
386
387
                  s);

388
389
          /* Make a task for each pair of progeny */
          for (int j = 0; j < 8; j++)
390
            if (ci->progeny[j] != NULL && ci->progeny[j]->count)
391
              for (int k = j + 1; k < 8; k++)
392
                if (ci->progeny[k] != NULL && ci->progeny[k]->count)
393
394
                  scheduler_splittask_hydro(
                      scheduler_addtask(s, task_type_pair, t->subtype,
395
                                        sub_sid_flag[j][k], 0, ci->progeny[j],
396
397
                                        ci->progeny[k]),
                      s);
398
        }
399
      } /* Cell is split */
400

401
    } /* Self interaction */
402

403
404
    /* Pair interaction? */
    else if (t->type == task_type_pair) {
405

406
407
408
      /* Get a handle on the cells involved. */
      struct cell *ci = t->ci;
      struct cell *cj = t->cj;
409

410
411
412
413
414
      /* Foreign task? */
      if (ci->nodeID != s->nodeID && cj->nodeID != s->nodeID) {
        t->skip = 1;
        break;
      }
415

416
417
418
      /* 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
419
      const int sid = space_getsid(s->space, &ci, &cj, shift);
420

421
      /* Should this task be split-up? */
Matthieu Schaller's avatar
Matthieu Schaller committed
422
423
      if (cell_can_split_pair_hydro_task(ci) &&
          cell_can_split_pair_hydro_task(cj)) {
424
425

        /* Replace by a single sub-task? */
426
        if (scheduler_dosub && /* Use division to avoid integer overflow. */
427
            ci->count * sid_scale[sid] < space_subsize_pair_hydro / cj->count &&
428
            !sort_is_corner(sid)) {
429
430
431
432
433

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

          /* Otherwise, split it. */
434
435
        } else {

436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
          /* 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;
452
              scheduler_splittask_hydro(
453
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
454
                                    ci->progeny[7], cj->progeny[1]),
455
                  s);
456
              scheduler_splittask_hydro(
457
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
458
                                    ci->progeny[6], cj->progeny[1]),
459
                  s);
460
              scheduler_splittask_hydro(
461
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
462
                                    ci->progeny[7], cj->progeny[0]),
463
464
465
466
467
468
469
470
471
472
473
474
475
                  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;
476
              scheduler_splittask_hydro(
477
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
478
                                    ci->progeny[7], cj->progeny[2]),
479
                  s);
480
              scheduler_splittask_hydro(
481
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
482
                                    ci->progeny[5], cj->progeny[2]),
483
                  s);
484
              scheduler_splittask_hydro(
485
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
486
                                    ci->progeny[7], cj->progeny[0]),
487
488
489
490
491
492
493
                  s);
              break;

            case 4: /* (  1 ,  0 ,  0 ) */
              t->ci = ci->progeny[4];
              t->cj = cj->progeny[0];
              t->flags = 4;
494
              scheduler_splittask_hydro(
495
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
496
                                    ci->progeny[5], cj->progeny[0]),
497
                  s);
498
              scheduler_splittask_hydro(
499
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
500
                                    ci->progeny[6], cj->progeny[0]),
501
                  s);
502
              scheduler_splittask_hydro(
503
                  scheduler_addtask(s, task_type_pair, t->subtype, 8, 0,
504
                                    ci->progeny[7], cj->progeny[0]),
505
                  s);
506
              scheduler_splittask_hydro(
507
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
508
                                    ci->progeny[4], cj->progeny[1]),
509
                  s);
510
              scheduler_splittask_hydro(
511
                  scheduler_addtask(s, task_type_pair, t->subtype, 4, 0,
512
                                    ci->progeny[5], cj->progeny[1]),
513
                  s);
514
              scheduler_splittask_hydro(
515
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
516
                                    ci->progeny[6], cj->progeny[1]),
517
                  s);
518
              scheduler_splittask_hydro(
519
                  scheduler_addtask(s, task_type_pair, t->subtype, 7, 0,
520
                                    ci->progeny[7], cj->progeny[1]),
521
                  s);
522
              scheduler_splittask_hydro(
523
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
524
                                    ci->progeny[4], cj->progeny[2]),
525
                  s);
526
              scheduler_splittask_hydro(
527
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
528
                                    ci->progeny[5], cj->progeny[2]),
529
                  s);
530
              scheduler_splittask_hydro(
531
                  scheduler_addtask(s, task_type_pair, t->subtype, 4, 0,
532
                                    ci->progeny[6], cj->progeny[2]),
533
                  s);
534
              scheduler_splittask_hydro(
535
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
536
                                    ci->progeny[7], cj->progeny[2]),
537
                  s);
538
              scheduler_splittask_hydro(
539
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
540
                                    ci->progeny[4], cj->progeny[3]),
541
                  s);
542
              scheduler_splittask_hydro(
543
                  scheduler_addtask(s, task_type_pair, t->subtype, 1, 0,
544
                                    ci->progeny[5], cj->progeny[3]),
545
                  s);
546
              scheduler_splittask_hydro(
547
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
548
                                    ci->progeny[6], cj->progeny[3]),
549
                  s);
550
              scheduler_splittask_hydro(
551
                  scheduler_addtask(s, task_type_pair, t->subtype, 4, 0,
552
                                    ci->progeny[7], cj->progeny[3]),
553
554
555
556
557
558
559
                  s);
              break;

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

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

            case 11: /* (  0 ,  1 , -1 ) */
              t->ci = ci->progeny[2];
              t->cj = cj->progeny[1];
              t->flags = 11;
692
              scheduler_splittask_hydro(
693
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
694
                                    ci->progeny[6], cj->progeny[5]),
695
                  s);
696
              scheduler_splittask_hydro(
697
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
698
                                    ci->progeny[2], cj->progeny[5]),
699
                  s);
700
              scheduler_splittask_hydro(
701
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
702
                                    ci->progeny[6], cj->progeny[1]),
703
704
705
706
707
708
709
                  s);
              break;

            case 12: /* (  0 ,  0 ,  1 ) */
              t->ci = ci->progeny[1];
              t->cj = cj->progeny[0];
              t->flags = 12;
710
              scheduler_splittask_hydro(
711
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
712
                                    ci->progeny[3], cj->progeny[0]),
713
                  s);
714
              scheduler_splittask_hydro(
715
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
716
                                    ci->progeny[5], cj->progeny[0]),
717
                  s);
718
              scheduler_splittask_hydro(
719
                  scheduler_addtask(s, task_type_pair, t->subtype, 2, 0,
720
                                    ci->progeny[7], cj->progeny[0]),
721
                  s);
722
              scheduler_splittask_hydro(
723
                  scheduler_addtask(s, task_type_pair, t->subtype, 9, 0,
724
                                    ci->progeny[1], cj->progeny[2]),
725
                  s);
726
              scheduler_splittask_hydro(
727
                  scheduler_addtask(s, task_type_pair, t->subtype, 12, 0,
728
                                    ci->progeny[3], cj->progeny[2]),
729
                  s);
730
              scheduler_splittask_hydro(
731
                  scheduler_addtask(s, task_type_pair, t->subtype, 8, 0,
732
                                    ci->progeny[5], cj->progeny[2]),
733
                  s);
734
              scheduler_splittask_hydro(
735
                  scheduler_addtask(s, task_type_pair, t->subtype, 5, 0,
736
                                    ci->progeny[7], cj->progeny[2]),
737
                  s);
738
              scheduler_splittask_hydro(
739
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
740
                                    ci->progeny[1], cj->progeny[4]),
741
                  s);
742
              scheduler_splittask_hydro(
743
                  scheduler_addtask(s, task_type_pair, t->subtype, 6, 0,
744
                                    ci->progeny[3], cj->progeny[4]),
745
                  s);
746
              scheduler_splittask_hydro(
747
                  scheduler_addtask(s, task_type_pair, t->subtype, 12, 0,
748
                                    ci->progeny[5], cj->progeny[4]),
749
                  s);
750
              scheduler_splittask_hydro(
751
                  scheduler_addtask(s, task_type_pair, t->subtype, 11, 0,
752
                                    ci->progeny[7], cj->progeny[4]),
753
                  s);
754
              scheduler_splittask_hydro(
755
                  scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
756
                                    ci->progeny[1], cj->progeny[6]),
757
                  s);
758
              scheduler_splittask_hydro(
759
                  scheduler_addtask(s, task_type_pair, t->subtype, 3, 0,
760
                                    ci->progeny[3], cj->progeny[6]),
Peter W. Draper's avatar