task.c 21.4 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
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",
69
                                             "timestep_limiter",
70
71
72
73
74
75
76
77
78
79
80
81
                                             "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
82
83
                                             "stars_ghost_out",
                                             "stars_sort"};
84

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

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

97
98
/**
 * @brief Computes the overlap between the parts array of two given cells.
99
 *
Matthieu Schaller's avatar
Matthieu Schaller committed
100
101
102
 * @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.
103
 */
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#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;                                                               \
  }
121

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

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

  switch (t->type) {

    case task_type_none:
      return task_action_none;
      break;

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

149
150
151
    case task_type_star_formation:
      return task_action_all;

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

157
158
159
160
161
162
163
    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:
164
        case task_subtype_gradient:
165
        case task_subtype_force:
166
        case task_subtype_limiter:
167
168
169
          return task_action_part;
          break;

170
        case task_subtype_stars_density:
Alexei Borissov's avatar
Alexei Borissov committed
171
        case task_subtype_stars_feedback:
172
173
          return task_action_all;
          break;
174

175
        case task_subtype_grav:
176
        case task_subtype_external_grav:
177
178
179
180
181
182
183
184
185
186
          return task_action_gpart;
          break;

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

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

204
    case task_type_init_grav:
205
    case task_type_grav_mm:
206
    case task_type_grav_long_range:
207
208
209
      return task_action_multipole;
      break;

210
    case task_type_drift_gpart:
211
    case task_type_grav_down:
212
    case task_type_grav_mesh:
213
      return task_action_gpart;
214
      break;
215

216
    default:
217
      error("Unknown task_action for task");
218
219
220
      return task_action_none;
      break;
  }
221

222
  /* Silence compiler warnings */
223
224
  error("Unknown task_action for task");
  return task_action_none;
225
226
}

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

  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);

242
243
  /* First check if any of the two tasks are of a type that don't
     use cells. */
244
245
246
247
248
  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);
249
250
  const int ta_spart =
      (ta_act == task_action_spart || ta_act == task_action_all);
251
252
253
  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);
254
255
  const int tb_spart =
      (tb_act == task_action_spart || tb_act == task_action_all);
256
257
258
259
260
261

  /* 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;
262
263
264
265
    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;
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280

    /* 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;
281
282
283
284
    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;
285
286
287
288
289
290
291
292
293

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

Loic Hausammann's avatar
Loic Hausammann committed
295
296
297
298
299
  /* 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;
300
301
302
303
    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
304
305
306
307
308
309
310
311
312
313

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

314
315
  /* Else, no overlap */
  return 0.f;
316
}
317

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

325
326
  const enum task_types type = t->type;
  const enum task_subtypes subtype = t->subtype;
327
328
  struct cell *ci = t->ci, *cj = t->cj;

329
  /* Act based on task type. */
330
331
  switch (type) {

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

341
    case task_type_drift_part:
342
    case task_type_sort:
343
    case task_type_timestep_limiter:
344
345
346
      cell_unlocktree(ci);
      break;

347
    case task_type_drift_gpart:
348
    case task_type_grav_mesh:
349
350
351
      cell_gunlocktree(ci);
      break;

Loic Hausammann's avatar
Loic Hausammann committed
352
353
354
355
    case task_type_stars_sort:
      cell_sunlocktree(ci);
      break;

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

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

392
    case task_type_grav_down:
393
      cell_gunlocktree(ci);
394
395
396
      cell_munlocktree(ci);
      break;

397
    case task_type_grav_long_range:
398
      cell_munlocktree(ci);
399
      break;
400

401
402
403
404
405
    case task_type_grav_mm:
      cell_munlocktree(ci);
      cell_munlocktree(cj);
      break;

406
407
408
409
    case task_type_star_formation:
      cell_unlocktree(ci);
      cell_sunlocktree(ci);
      cell_gunlocktree(ci);
410
      break;
411

412
413
414
415
    default:
      break;
  }
}
416
417
418
419
420
421

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

424
425
  const enum task_types type = t->type;
  const enum task_subtypes subtype = t->subtype;
426
  struct cell *ci = t->ci, *cj = t->cj;
427
428
429
430
#ifdef WITH_MPI
  int res = 0, err = 0;
  MPI_Status stat;
#endif
431

432
  switch (type) {
433

434
435
436
    /* Communication task? */
    case task_type_recv:
    case task_type_send:
437
#ifdef WITH_MPI
438
439
440
441
442
      /* 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);
443
444
445
446
        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);
447
448
      }
      return res;
449
#else
450
      error("SWIFT was not compiled with MPI support.");
451
#endif
452
      break;
453

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

467
    case task_type_drift_part:
468
    case task_type_sort:
469
    case task_type_timestep_limiter:
470
      if (ci->hydro.hold) return 0;
471
472
      if (cell_locktree(ci) != 0) return 0;
      break;
473

Loic Hausammann's avatar
Loic Hausammann committed
474
475
476
477
478
    case task_type_stars_sort:
      if (ci->stars.hold) return 0;
      if (cell_slocktree(ci) != 0) return 0;
      break;

479
    case task_type_drift_gpart:
480
    case task_type_grav_mesh:
481
      if (ci->grav.phold) return 0;
482
483
484
      if (cell_glocktree(ci) != 0) return 0;
      break;

485
    case task_type_self:
486
    case task_type_sub_self:
487
      if (subtype == task_subtype_grav) {
488
        /* Lock the gparts and the m-pole */
489
        if (ci->grav.phold || ci->grav.mhold) return 0;
490
491
492
493
494
495
        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
496
497
498
      } 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
499
500
501
502
503
504
505
506
507
      } 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
508
        if (ci->hydro.hold) return 0;
509
510
511
        if (cell_locktree(ci) != 0) return 0;
      }
      break;
512

513
    case task_type_pair:
514
    case task_type_sub_pair:
515
      if (subtype == task_subtype_grav) {
516
        /* Lock the gparts and the m-pole in both cells */
517
        if (ci->grav.phold || cj->grav.phold) return 0;
518
519
520
521
        if (cell_glocktree(ci) != 0) return 0;
        if (cell_glocktree(cj) != 0) {
          cell_gunlocktree(ci);
          return 0;
522
523
524
525
526
527
528
529
530
        } 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;
531
        }
Loic Hausammann's avatar
Loic Hausammann committed
532
533
534
535
536
537
538
      } 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
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
      } 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 */
560
        /* Lock the parts in both cells */
561
        if (ci->hydro.hold || cj->hydro.hold) return 0;
562
563
564
565
566
567
568
        if (cell_locktree(ci) != 0) return 0;
        if (cell_locktree(cj) != 0) {
          cell_unlocktree(ci);
          return 0;
        }
      }
      break;
569

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

581
    case task_type_grav_long_range:
582
      /* Lock the m-poles */
583
      if (ci->grav.mhold) return 0;
584
      if (cell_mlocktree(ci) != 0) return 0;
Matthieu Schaller's avatar
Matthieu Schaller committed
585
586
      break;

587
588
    case task_type_grav_mm:
      /* Lock both m-poles */
589
      if (ci->grav.mhold || cj->grav.mhold) return 0;
590
591
592
593
594
      if (cell_mlocktree(ci) != 0) return 0;
      if (cell_mlocktree(cj) != 0) {
        cell_munlocktree(ci);
        return 0;
      }
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
      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;
      }
610

611
612
    default:
      break;
613
614
615
616
617
  }

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

619
620
621
622
623
624
625
626
627
628
629
/**
 * @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);
}
630

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

643
644
  if (type == task_type_grav_long_range || type == task_type_grav_mm ||
      type == task_type_grav_mesh) {
645
646
647
648
649

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

650
  switch (subtype) {
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
 */
679
void task_get_full_name(int type, int subtype, char *name) {
680
681
682

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

685
  if (subtype >= task_subtype_count)
686
687
688
689
690
691
692
693
694
695
    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]);
}

696
697
698
699
700
701
702
703
704
705
#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