scheduler.c 61.8 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
51
#include "space.h"
#include "task.h"
52
#include "timers.h"
53
#include "version.h"
54

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

60
61
62
63
64
65
66
/**
 * @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.
 */
67
68
void scheduler_addunlock(struct scheduler *s, struct task *ta,
                         struct task *tb) {
69
70
71
72
73
#ifdef SWIFT_DEBUG_CHECKS
  if (ta == NULL) error("Unlocking task is NULL.");
  if (tb == NULL) error("Unlocked task is NULL.");
#endif

74
75
76
77
78
  /* 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) {
79
    /* Allocate the new buffer. */
80
81
82
    struct task **unlocks_new;
    int *unlock_ind_new;
    const int size_unlocks_new = s->size_unlocks * 2;
83
84
    if ((unlocks_new = (struct task **)malloc(sizeof(struct task *) *
                                              size_unlocks_new)) == NULL ||
85
86
        (unlock_ind_new = (int *)malloc(sizeof(int) * size_unlocks_new)) ==
            NULL)
87
      error("Failed to re-allocate unlocks.");
88

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

93
    /* Copy the buffers. */
94
95
96
97
98
99
    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;
100

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

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

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

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

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

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

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

Matthieu Schaller's avatar
Matthieu Schaller committed
135
136
137
138
  /* 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  */
139
  int *table = (int *)malloc(nber_relation * sizeof(int));
Matthieu Schaller's avatar
Matthieu Schaller committed
140
141
  if (table == NULL)
    error("Error allocating memory for task-dependency graph.");
lhausamm's avatar
lhausamm committed
142

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

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

Matthieu Schaller's avatar
Matthieu Schaller committed
151
  /* Write header */
152
  fprintf(f, "digraph task_dep {\n");
153
  fprintf(f, "label=\"Task dependencies for SWIFT %s\";\n", git_revision());
154
155
156
157
158
  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
159
160
  for (int i = 0; i < s->nr_tasks; i++) {
    const struct task *ta = &s->tasks[i];
lhausamm's avatar
lhausamm committed
161

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

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

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

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

lhausamm's avatar
lhausamm committed
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
        /* 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];
      }
193
194
195

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

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

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

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

        /* 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
236
      }
237
    }
lhausamm's avatar
lhausamm committed
238
  }
lhausamm's avatar
lhausamm committed
239

240
  int density_cluster[4] = {0};
241
  int gradient_cluster[4] = {0};
242
243
244
  int force_cluster[4] = {0};
  int gravity_cluster[4] = {0};

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

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

289
  /* Make a cluster for the gradient tasks */
290
291
  fprintf(f, "\t subgraph cluster2{\n");
  fprintf(f, "\t\t label=\"\";\n");
292
293
294
295
296
297
298
299
300
  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");
301
302
303
304
305
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])
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_top_level]);
  if (gravity_cluster[3])
    fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_long_range]);
  fprintf(f, "\t};\n");

Matthieu Schaller's avatar
Matthieu Schaller committed
311
  /* Be clean */
312
313
  fprintf(f, "}");
  fclose(f);
314
  free(table);
Matthieu Schaller's avatar
Matthieu Schaller committed
315

Matthieu Schaller's avatar
Matthieu Schaller committed
316
  if (verbose)
Matthieu Schaller's avatar
Matthieu Schaller committed
317
    message("Printing task graph took %.3f %s.",
Matthieu Schaller's avatar
Matthieu Schaller committed
318
            clocks_from_ticks(getticks() - tic), clocks_getunit());
319
320
}

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

329
330
331
  /* Iterate on this task until we're done with it. */
  int redo = 1;
  while (redo) {
332

333
334
    /* Reset the redo flag. */
    redo = 0;
335

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

346
347
    /* Self-interaction? */
    if (t->type == task_type_self) {
348

349
350
351
352
353
      /* Get a handle on the cell involved. */
      struct cell *ci = t->ci;

      /* Foreign task? */
      if (ci->nodeID != s->nodeID) {
354
        t->skip = 1;
355
        break;
356
357
      }

358
      /* Is this cell even split and the task does not violate h ? */
359
      if (cell_can_split_self_task(ci)) {
360

361
        /* Make a sub? */
362
        if (scheduler_dosub && ci->count < space_subsize_self_hydro) {
363

364
365
366
367
368
          /* convert to a self-subtask. */
          t->type = task_type_sub_self;

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

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

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

397
    } /* Self interaction */
398

399
400
    /* Pair interaction? */
    else if (t->type == task_type_pair) {
401

402
403
404
      /* Get a handle on the cells involved. */
      struct cell *ci = t->ci;
      struct cell *cj = t->cj;
405

406
407
408
409
410
      /* Foreign task? */
      if (ci->nodeID != s->nodeID && cj->nodeID != s->nodeID) {
        t->skip = 1;
        break;
      }
411

412
413
414
      /* 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
415
      const int sid = space_getsid(s->space, &ci, &cj, shift);
416

417
      /* Should this task be split-up? */
418
      if (cell_can_split_pair_task(ci) && cell_can_split_pair_task(cj)) {
419
420

        /* Replace by a single sub-task? */
421
        if (scheduler_dosub && /* Use division to avoid integer overflow. */
422
            ci->count * sid_scale[sid] < space_subsize_pair_hydro / cj->count &&
423
            !sort_is_corner(sid)) {
424
425
426
427
428

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

          /* Otherwise, split it. */
429
430
        } else {

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

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

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

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

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

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

769
770
771
772
773
774
775
776
777
778
779
        /* Otherwise, break it up if it is too large? */
      } else if (scheduler_doforcesplit && ci->split && cj->split &&
                 (ci->count > space_maxsize / cj->count)) {

        // message( "force splitting pair with %i and %i parts." , ci->count ,
        // cj->count );

        /* Replace the current task. */
        t->type = task_type_none;

        for (int j = 0; j < 8; j++)
780
          if (ci->progeny[j] != NULL && ci->progeny[j]->count)
781
            for (int k = 0; k < 8; k++)
782
              if (cj->progeny[k] != NULL && cj->progeny[k]->count) {