task.c 21.3 KB
Newer Older
1
/*******************************************************************************
2
 * This file is part of SWIFT.
3
 * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
4
5
6
7
 *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
 *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
 *               2016 John A. Regan (john.a.regan@durham.ac.uk)
 *                    Tom Theuns (tom.theuns@durham.ac.uk)
8
 *
9
10
11
12
 * 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.
13
 *
14
15
16
17
 * 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.
18
 *
19
20
 * 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/>.
21
 *
22
23
24
25
26
27
28
29
30
 ******************************************************************************/

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

/* Some standard headers. */
#include <float.h>
#include <limits.h>
#include <sched.h>
31
32
33
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
34

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

40
41
42
/* This object's header. */
#include "task.h"

43
/* Local headers. */
Pedro Gonnet's avatar
Pedro Gonnet committed
44
#include "atomic.h"
45
#include "error.h"
46
#include "inline.h"
47
#include "lock.h"
48
49

/* Task type names. */
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
const char *taskID_names[task_type_count] = {"none",
                                             "sort",
                                             "self",
                                             "pair",
                                             "sub_self",
                                             "sub_pair",
                                             "init_grav",
                                             "init_grav_out",
                                             "ghost_in",
                                             "ghost",
                                             "ghost_out",
                                             "extra_ghost",
                                             "drift_part",
                                             "drift_gpart",
                                             "drift_gpart_out",
                                             "end_force",
                                             "kick1",
                                             "kick2",
                                             "timestep",
                                             "send",
                                             "recv",
                                             "grav_long_range",
                                             "grav_mm",
                                             "grav_down_in",
                                             "grav_down",
                                             "grav_mesh",
                                             "cooling",
                                             "star_formation",
                                             "logger",
                                             "stars_ghost_in",
                                             "stars_ghost",
Loic Hausammann's avatar
Loic Hausammann committed
81
82
                                             "stars_ghost_out",
                                             "stars_sort"};
83

84
/* Sub-task type names. */
85
const char *subtaskID_names[task_subtype_count] = {
Alexei Borissov's avatar
Alexei Borissov committed
86
87
88
89
    "none",          "density",       "gradient",  "force",
    "grav",          "external_grav", "tend",      "xv",
    "rho",           "gpart",         "multipole", "spart",
    "stars_density", "stars_feedback"};
90

91
92
93
94
95
#ifdef WITH_MPI
/* MPI communicators for the subtypes. */
MPI_Comm subtaskMPI_comms[task_subtype_count];
#endif

96
97
/**
 * @brief Computes the overlap between the parts array of two given cells.
98
 *
Matthieu Schaller's avatar
Matthieu Schaller committed
99
100
101
 * @param TYPE is the type of parts (e.g. #part, #gpart, #spart)
 * @param ARRAY is the array of this specific type.
 * @param COUNT is the number of elements in the array.
102
 */
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#define TASK_CELL_OVERLAP(TYPE, ARRAY, COUNT)                               \
  __attribute__((always_inline))                                            \
      INLINE static size_t task_cell_overlap_##TYPE(                        \
          const struct cell *restrict ci, const struct cell *restrict cj) { \
                                                                            \
    if (ci == NULL || cj == NULL) return 0;                                 \
                                                                            \
    if (ci->ARRAY <= cj->ARRAY &&                                           \
        ci->ARRAY + ci->COUNT >= cj->ARRAY + cj->COUNT) {                   \
      return cj->COUNT;                                                     \
    } else if (cj->ARRAY <= ci->ARRAY &&                                    \
               cj->ARRAY + cj->COUNT >= ci->ARRAY + ci->COUNT) {            \
      return ci->COUNT;                                                     \
    }                                                                       \
                                                                            \
    return 0;                                                               \
  }
120

121
TASK_CELL_OVERLAP(part, hydro.parts, hydro.count);
122
123
TASK_CELL_OVERLAP(gpart, grav.parts, grav.count);
TASK_CELL_OVERLAP(spart, stars.parts, stars.count);
Loic Hausammann's avatar
Loic Hausammann committed
124

125
126
127
128
129
/**
 * @brief Returns the #task_actions for a given task.
 *
 * @param t The #task.
 */
130
131
__attribute__((always_inline)) INLINE static enum task_actions task_acts_on(
    const struct task *t) {
132
133
134
135
136
137
138

  switch (t->type) {

    case task_type_none:
      return task_action_none;
      break;

139
    case task_type_drift_part:
140
141
    case task_type_sort:
    case task_type_ghost:
142
    case task_type_extra_ghost:
Stefan Arridge's avatar
Stefan Arridge committed
143
    case task_type_cooling:
144
145
146
      return task_action_part;
      break;

147
148
149
    case task_type_star_formation:
      return task_action_all;

150
    case task_type_stars_ghost:
Loic Hausammann's avatar
Loic Hausammann committed
151
    case task_type_stars_sort:
Loic Hausammann's avatar
Loic Hausammann committed
152
153
154
      return task_action_spart;
      break;

155
156
157
158
159
160
161
    case task_type_self:
    case task_type_pair:
    case task_type_sub_self:
    case task_type_sub_pair:
      switch (t->subtype) {

        case task_subtype_density:
162
        case task_subtype_gradient:
163
164
165
166
        case task_subtype_force:
          return task_action_part;
          break;

167
        case task_subtype_stars_density:
Alexei Borissov's avatar
Alexei Borissov committed
168
        case task_subtype_stars_feedback:
169
170
          return task_action_all;
          break;
171

172
        case task_subtype_grav:
173
        case task_subtype_external_grav:
174
175
176
177
178
179
180
181
182
183
          return task_action_gpart;
          break;

        default:
          error("Unknow task_action for task");
          return task_action_none;
          break;
      }
      break;

184
    case task_type_end_force:
185
186
    case task_type_kick1:
    case task_type_kick2:
Loikki's avatar
Loikki committed
187
    case task_type_logger:
188
    case task_type_timestep:
189
190
    case task_type_send:
    case task_type_recv:
191
      if (t->ci->hydro.count > 0 && t->ci->grav.count > 0)
192
        return task_action_all;
193
      else if (t->ci->hydro.count > 0)
194
        return task_action_part;
195
      else if (t->ci->grav.count > 0)
196
197
198
        return task_action_gpart;
      else
        error("Task without particles");
199
200
      break;

201
    case task_type_init_grav:
202
    case task_type_grav_mm:
203
    case task_type_grav_long_range:
204
205
206
      return task_action_multipole;
      break;

207
    case task_type_drift_gpart:
208
    case task_type_grav_down:
209
    case task_type_grav_mesh:
210
      return task_action_gpart;
211
      break;
212

213
    default:
214
      error("Unknown task_action for task");
215
216
217
      return task_action_none;
      break;
  }
218

219
  /* Silence compiler warnings */
220
221
  error("Unknown task_action for task");
  return task_action_none;
222
223
}

224
225
226
227
228
229
230
/**
 * @brief Compute the Jaccard similarity of the data used by two
 *        different tasks.
 *
 * @param ta The first #task.
 * @param tb The second #task.
 */
231
232
float task_overlap(const struct task *restrict ta,
                   const struct task *restrict tb) {
233
234
235
236
237
238

  if (ta == NULL || tb == NULL) return 0.f;

  const enum task_actions ta_act = task_acts_on(ta);
  const enum task_actions tb_act = task_acts_on(tb);

239
240
  /* First check if any of the two tasks are of a type that don't
     use cells. */
241
242
243
244
245
  if (ta_act == task_action_none || tb_act == task_action_none) return 0.f;

  const int ta_part = (ta_act == task_action_part || ta_act == task_action_all);
  const int ta_gpart =
      (ta_act == task_action_gpart || ta_act == task_action_all);
246
247
  const int ta_spart =
      (ta_act == task_action_spart || ta_act == task_action_all);
248
249
250
  const int tb_part = (tb_act == task_action_part || tb_act == task_action_all);
  const int tb_gpart =
      (tb_act == task_action_gpart || tb_act == task_action_all);
251
252
  const int tb_spart =
      (tb_act == task_action_spart || tb_act == task_action_all);
253
254
255
256
257
258

  /* In the case where both tasks act on parts */
  if (ta_part && tb_part) {

    /* Compute the union of the cell data. */
    size_t size_union = 0;
259
260
261
262
    if (ta->ci != NULL) size_union += ta->ci->hydro.count;
    if (ta->cj != NULL) size_union += ta->cj->hydro.count;
    if (tb->ci != NULL) size_union += tb->ci->hydro.count;
    if (tb->cj != NULL) size_union += tb->cj->hydro.count;
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277

    /* Compute the intersection of the cell data. */
    const size_t size_intersect = task_cell_overlap_part(ta->ci, tb->ci) +
                                  task_cell_overlap_part(ta->ci, tb->cj) +
                                  task_cell_overlap_part(ta->cj, tb->ci) +
                                  task_cell_overlap_part(ta->cj, tb->cj);

    return ((float)size_intersect) / (size_union - size_intersect);
  }

  /* In the case where both tasks act on gparts */
  else if (ta_gpart && tb_gpart) {

    /* Compute the union of the cell data. */
    size_t size_union = 0;
278
279
280
281
    if (ta->ci != NULL) size_union += ta->ci->grav.count;
    if (ta->cj != NULL) size_union += ta->cj->grav.count;
    if (tb->ci != NULL) size_union += tb->ci->grav.count;
    if (tb->cj != NULL) size_union += tb->cj->grav.count;
282
283
284
285
286
287
288
289
290

    /* Compute the intersection of the cell data. */
    const size_t size_intersect = task_cell_overlap_gpart(ta->ci, tb->ci) +
                                  task_cell_overlap_gpart(ta->ci, tb->cj) +
                                  task_cell_overlap_gpart(ta->cj, tb->ci) +
                                  task_cell_overlap_gpart(ta->cj, tb->cj);

    return ((float)size_intersect) / (size_union - size_intersect);
  }
291

Loic Hausammann's avatar
Loic Hausammann committed
292
293
294
295
296
  /* In the case where both tasks act on sparts */
  else if (ta_spart && tb_spart) {

    /* Compute the union of the cell data. */
    size_t size_union = 0;
297
298
299
300
    if (ta->ci != NULL) size_union += ta->ci->stars.count;
    if (ta->cj != NULL) size_union += ta->cj->stars.count;
    if (tb->ci != NULL) size_union += tb->ci->stars.count;
    if (tb->cj != NULL) size_union += tb->cj->stars.count;
Loic Hausammann's avatar
Loic Hausammann committed
301
302
303
304
305
306
307
308
309
310

    /* Compute the intersection of the cell data. */
    const size_t size_intersect = task_cell_overlap_spart(ta->ci, tb->ci) +
                                  task_cell_overlap_spart(ta->ci, tb->cj) +
                                  task_cell_overlap_spart(ta->cj, tb->ci) +
                                  task_cell_overlap_spart(ta->cj, tb->cj);

    return ((float)size_intersect) / (size_union - size_intersect);
  }

311
312
  /* Else, no overlap */
  return 0.f;
313
}
314

315
316
/**
 * @brief Unlock the cell held by this task.
317
 *
318
319
 * @param t The #task.
 */
320
321
void task_unlock(struct task *t) {

322
323
  const enum task_types type = t->type;
  const enum task_subtypes subtype = t->subtype;
324
325
  struct cell *ci = t->ci, *cj = t->cj;

326
  /* Act based on task type. */
327
328
  switch (type) {

329
    case task_type_end_force:
330
331
    case task_type_kick1:
    case task_type_kick2:
332
    case task_type_logger:
333
    case task_type_timestep:
334
335
336
      cell_unlocktree(ci);
      cell_gunlocktree(ci);
      break;
Matthieu Schaller's avatar
Matthieu Schaller committed
337

338
    case task_type_drift_part:
339
    case task_type_sort:
340
341
342
      cell_unlocktree(ci);
      break;

343
    case task_type_drift_gpart:
344
    case task_type_grav_mesh:
345
346
347
      cell_gunlocktree(ci);
      break;

Loic Hausammann's avatar
Loic Hausammann committed
348
349
350
351
    case task_type_stars_sort:
      cell_sunlocktree(ci);
      break;

352
    case task_type_self:
353
    case task_type_sub_self:
354
355
      if (subtype == task_subtype_grav) {
        cell_gunlocktree(ci);
356
        cell_munlocktree(ci);
Loic Hausammann's avatar
Loic Hausammann committed
357
358
      } else if (subtype == task_subtype_stars_density) {
        cell_sunlocktree(ci);
Alexei Borissov's avatar
Alexei Borissov committed
359
360
361
      } else if (subtype == task_subtype_stars_feedback) {
        cell_sunlocktree(ci);
        cell_unlocktree(ci);
362
363
364
      } else {
        cell_unlocktree(ci);
      }
365
      break;
366

367
    case task_type_pair:
368
    case task_type_sub_pair:
369
370
371
      if (subtype == task_subtype_grav) {
        cell_gunlocktree(ci);
        cell_gunlocktree(cj);
372
373
        cell_munlocktree(ci);
        cell_munlocktree(cj);
Loic Hausammann's avatar
Loic Hausammann committed
374
375
376
      } else if (subtype == task_subtype_stars_density) {
        cell_sunlocktree(ci);
        cell_sunlocktree(cj);
Alexei Borissov's avatar
Alexei Borissov committed
377
378
379
380
381
      } else if (subtype == task_subtype_stars_feedback) {
        cell_sunlocktree(ci);
        cell_sunlocktree(cj);
        cell_unlocktree(ci);
        cell_unlocktree(cj);
382
383
384
385
386
387
      } else {
        cell_unlocktree(ci);
        cell_unlocktree(cj);
      }
      break;

388
    case task_type_grav_down:
389
      cell_gunlocktree(ci);
390
391
392
      cell_munlocktree(ci);
      break;

393
    case task_type_grav_long_range:
394
      cell_munlocktree(ci);
395
      break;
396

397
398
399
400
401
    case task_type_grav_mm:
      cell_munlocktree(ci);
      cell_munlocktree(cj);
      break;

402
403
404
405
    case task_type_star_formation:
      cell_unlocktree(ci);
      cell_sunlocktree(ci);
      cell_gunlocktree(ci);
406
      break;
407

408
409
410
411
    default:
      break;
  }
}
412
413
414
415
416
417

/**
 * @brief Try to lock the cells associated with this task.
 *
 * @param t the #task.
 */
418
419
int task_lock(struct task *t) {

420
421
  const enum task_types type = t->type;
  const enum task_subtypes subtype = t->subtype;
422
  struct cell *ci = t->ci, *cj = t->cj;
423
424
425
426
#ifdef WITH_MPI
  int res = 0, err = 0;
  MPI_Status stat;
#endif
427

428
  switch (type) {
429

430
431
432
    /* Communication task? */
    case task_type_recv:
    case task_type_send:
433
#ifdef WITH_MPI
434
435
436
437
438
      /* Check the status of the MPI request. */
      if ((err = MPI_Test(&t->req, &res, &stat)) != MPI_SUCCESS) {
        char buff[MPI_MAX_ERROR_STRING];
        int len;
        MPI_Error_string(err, buff, &len);
439
440
441
442
        error(
            "Failed to test request on send/recv task (type=%s/%s tag=%lld, "
            "%s).",
            taskID_names[t->type], subtaskID_names[t->subtype], t->flags, buff);
443
444
      }
      return res;
445
#else
446
      error("SWIFT was not compiled with MPI support.");
447
#endif
448
      break;
449

450
    case task_type_end_force:
451
452
    case task_type_kick1:
    case task_type_kick2:
Loikki's avatar
Loikki committed
453
    case task_type_logger:
454
    case task_type_timestep:
455
      if (ci->hydro.hold || ci->grav.phold) return 0;
456
457
      if (cell_locktree(ci) != 0) return 0;
      if (cell_glocktree(ci) != 0) {
Matthieu Schaller's avatar
Matthieu Schaller committed
458
459
        cell_unlocktree(ci);
        return 0;
460
461
462
      }
      break;

463
    case task_type_drift_part:
464
    case task_type_sort:
465
      if (ci->hydro.hold) return 0;
466
467
      if (cell_locktree(ci) != 0) return 0;
      break;
468

Loic Hausammann's avatar
Loic Hausammann committed
469
470
471
472
473
    case task_type_stars_sort:
      if (ci->stars.hold) return 0;
      if (cell_slocktree(ci) != 0) return 0;
      break;

474
    case task_type_drift_gpart:
475
    case task_type_grav_mesh:
476
      if (ci->grav.phold) return 0;
477
478
479
      if (cell_glocktree(ci) != 0) return 0;
      break;

480
    case task_type_self:
481
    case task_type_sub_self:
482
      if (subtype == task_subtype_grav) {
483
        /* Lock the gparts and the m-pole */
484
        if (ci->grav.phold || ci->grav.mhold) return 0;
485
486
487
488
489
490
        if (cell_glocktree(ci) != 0)
          return 0;
        else if (cell_mlocktree(ci) != 0) {
          cell_gunlocktree(ci);
          return 0;
        }
Loic Hausammann's avatar
Loic Hausammann committed
491
492
493
      } else if (subtype == task_subtype_stars_density) {
        if (ci->stars.hold) return 0;
        if (cell_slocktree(ci) != 0) return 0;
Alexei Borissov's avatar
Alexei Borissov committed
494
495
496
497
498
499
500
501
502
      } else if (subtype == task_subtype_stars_feedback) {
        if (ci->stars.hold) return 0;
        if (ci->hydro.hold) return 0;
        if (cell_slocktree(ci) != 0) return 0;
        if (cell_locktree(ci) != 0) {
          cell_sunlocktree(ci);
          return 0;
        }
      } else { /* subtype == hydro */
Loic Hausammann's avatar
Loic Hausammann committed
503
        if (ci->hydro.hold) return 0;
504
505
506
        if (cell_locktree(ci) != 0) return 0;
      }
      break;
507

508
    case task_type_pair:
509
    case task_type_sub_pair:
510
      if (subtype == task_subtype_grav) {
511
        /* Lock the gparts and the m-pole in both cells */
512
        if (ci->grav.phold || cj->grav.phold) return 0;
513
514
515
516
        if (cell_glocktree(ci) != 0) return 0;
        if (cell_glocktree(cj) != 0) {
          cell_gunlocktree(ci);
          return 0;
517
518
519
520
521
522
523
524
525
        } else if (cell_mlocktree(ci) != 0) {
          cell_gunlocktree(ci);
          cell_gunlocktree(cj);
          return 0;
        } else if (cell_mlocktree(cj) != 0) {
          cell_gunlocktree(ci);
          cell_gunlocktree(cj);
          cell_munlocktree(ci);
          return 0;
526
        }
Loic Hausammann's avatar
Loic Hausammann committed
527
528
529
530
531
532
533
      } else if (subtype == task_subtype_stars_density) {
        if (ci->stars.hold || cj->stars.hold) return 0;
        if (cell_slocktree(ci) != 0) return 0;
        if (cell_slocktree(cj) != 0) {
          cell_sunlocktree(ci);
          return 0;
        }
Alexei Borissov's avatar
Alexei Borissov committed
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
      } else if (subtype == task_subtype_stars_feedback) {
        /* Lock the stars and the gas particles in both cells */
        if (ci->stars.hold || cj->stars.hold) return 0;
        if (ci->hydro.hold || cj->hydro.hold) return 0;
        if (cell_slocktree(ci) != 0) return 0;
        if (cell_slocktree(cj) != 0) {
          cell_sunlocktree(ci);
          return 0;
        }
        if (cell_locktree(ci) != 0) {
          cell_sunlocktree(ci);
          cell_sunlocktree(cj);
          return 0;
        }
        if (cell_locktree(cj) != 0) {
          cell_sunlocktree(ci);
          cell_sunlocktree(cj);
          cell_unlocktree(ci);
          return 0;
        }
      } else { /* subtype == hydro */
555
        /* Lock the parts in both cells */
556
        if (ci->hydro.hold || cj->hydro.hold) return 0;
557
558
559
560
561
562
563
        if (cell_locktree(ci) != 0) return 0;
        if (cell_locktree(cj) != 0) {
          cell_unlocktree(ci);
          return 0;
        }
      }
      break;
564

565
566
    case task_type_grav_down:
      /* Lock the gparts and the m-poles */
567
      if (ci->grav.phold || ci->grav.mhold) return 0;
568
569
570
571
572
573
574
575
      if (cell_glocktree(ci) != 0)
        return 0;
      else if (cell_mlocktree(ci) != 0) {
        cell_gunlocktree(ci);
        return 0;
      }
      break;

576
    case task_type_grav_long_range:
577
      /* Lock the m-poles */
578
      if (ci->grav.mhold) return 0;
579
      if (cell_mlocktree(ci) != 0) return 0;
Matthieu Schaller's avatar
Matthieu Schaller committed
580
581
      break;

582
583
    case task_type_grav_mm:
      /* Lock both m-poles */
584
      if (ci->grav.mhold || cj->grav.mhold) return 0;
585
586
587
588
589
      if (cell_mlocktree(ci) != 0) return 0;
      if (cell_mlocktree(cj) != 0) {
        cell_munlocktree(ci);
        return 0;
      }
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
      break;

    case task_type_star_formation:
      /* Lock the gas, gravity and star particles */
      if (ci->hydro.hold || ci->stars.hold || ci->grav.phold) return 0;
      if (cell_locktree(ci) != 0) return 0;
      if (cell_slocktree(ci) != 0) {
        cell_unlocktree(ci);
        return 0;
      }
      if (cell_glocktree(ci) != 0) {
        cell_unlocktree(ci);
        cell_sunlocktree(ci);
        return 0;
      }
605

606
607
    default:
      break;
608
609
610
611
612
  }

  /* If we made it this far, we've got a lock. */
  return 1;
}
613

614
615
616
617
618
619
620
621
622
623
624
/**
 * @brief Print basic information about a task.
 *
 * @param t The #task.
 */
void task_print(const struct task *t) {

  message("Type:'%s' sub_type:'%s' wait=%d nr_unlocks=%d skip=%d",
          taskID_names[t->type], subtaskID_names[t->subtype], t->wait,
          t->nr_unlock_tasks, t->skip);
}
625

626
627
628
629
630
631
/**
 * @brief Get the group name of a task.
 *
 * This is used to group tasks with similar actions in the task dependency
 * graph.
 *
632
633
634
 * @param type The #task type.
 * @param subtype The #subtask type.
 * @param cluster (return) The group name (should be allocated)
635
 */
636
void task_get_group_name(int type, int subtype, char *cluster) {
637

638
639
  if (type == task_type_grav_long_range || type == task_type_grav_mm ||
      type == task_type_grav_mesh) {
640
641
642
643
644

    strcpy(cluster, "Gravity");
    return;
  }

645
  switch (subtype) {
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
    case task_subtype_density:
      strcpy(cluster, "Density");
      break;
    case task_subtype_gradient:
      strcpy(cluster, "Gradient");
      break;
    case task_subtype_force:
      strcpy(cluster, "Force");
      break;
    case task_subtype_grav:
      strcpy(cluster, "Gravity");
      break;
    case task_subtype_stars_density:
      strcpy(cluster, "Stars");
      break;
    default:
      strcpy(cluster, "None");
      break;
  }
}

/**
 * @brief Generate the full name of a #task.
 *
 * @param type The #task type.
 * @param subtype The #task type.
 * @param name (return) The formatted string
 */
void task_get_full_name(enum task_types type, enum task_subtypes subtype,
                        char *name) {

#ifdef SWIFT_DEBUG_CHECKS
  /* Check input */
679
  if (type >= task_type_count) error("Unknown task type %i", type);
680

681
  if (subtype >= task_subtype_count)
682
683
684
685
686
687
688
689
690
691
    error("Unknown task subtype %i with type %s", subtype, taskID_names[type]);
#endif

  /* Full task name */
  if (subtype == task_subtype_none)
    sprintf(name, "%s", taskID_names[type]);
  else
    sprintf(name, "%s_%s", taskID_names[type], subtaskID_names[subtype]);
}

692
693
694
695
696
697
698
699
700
701
#ifdef WITH_MPI
/**
 * @brief Create global communicators for each of the subtasks.
 */
void task_create_mpi_comms(void) {
  for (int i = 0; i < task_subtype_count; i++) {
    MPI_Comm_dup(MPI_COMM_WORLD, &subtaskMPI_comms[i]);
  }
}
#endif