space.c 197 KB
Newer Older
1
/*******************************************************************************
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 * This file is part of SWIFT.
 * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
 *                    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)
 *
 * 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.
 *
 * 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.
 *
 * 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/>.
 *
 ******************************************************************************/
Pedro Gonnet's avatar
Pedro Gonnet committed
23
24
25
26
27
28
29
30

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

/* Some standard headers. */
#include <float.h>
#include <limits.h>
#include <math.h>
31
#include <stdlib.h>
32
#include <string.h>
Pedro Gonnet's avatar
Pedro Gonnet committed
33

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

39
40
41
/* This object's header. */
#include "space.h"

Pedro Gonnet's avatar
Pedro Gonnet committed
42
/* Local headers. */
43
#include "atomic.h"
44
#include "black_holes.h"
45
#include "chemistry.h"
46
#include "const.h"
47
#include "cooling.h"
48
#include "debug.h"
49
#include "engine.h"
50
#include "error.h"
51
52
#include "gravity.h"
#include "hydro.h"
53
#include "kernel_hydro.h"
54
#include "lock.h"
55
#include "memswap.h"
56
#include "memuse.h"
57
#include "minmax.h"
58
#include "multipole.h"
59
#include "pressure_floor.h"
60
#include "restart.h"
61
#include "sort_part.h"
62
#include "star_formation.h"
63
#include "star_formation_logger.h"
Loic Hausammann's avatar
Format    
Loic Hausammann committed
64
#include "stars.h"
65
#include "threadpool.h"
66
#include "tools.h"
67
#include "tracers.h"
Pedro Gonnet's avatar
Pedro Gonnet committed
68
69
70

/* Split size. */
int space_splitsize = space_splitsize_default;
71
72
int space_subsize_pair_hydro = space_subsize_pair_hydro_default;
int space_subsize_self_hydro = space_subsize_self_hydro_default;
73
74
int space_subsize_pair_stars = space_subsize_pair_stars_default;
int space_subsize_self_stars = space_subsize_self_stars_default;
75
int space_subsize_pair_grav = space_subsize_pair_grav_default;
76
int space_subsize_self_grav = space_subsize_self_grav_default;
77
int space_subdepth_diff_grav = space_subdepth_diff_grav_default;
78
int space_maxsize = space_maxsize_default;
79

80
81
82
/*! Number of extra #part we allocate memory for per top-level cell */
int space_extra_parts = space_extra_parts_default;

83
84
85
/*! Number of extra #spart we allocate memory for per top-level cell */
int space_extra_sparts = space_extra_sparts_default;

86
87
88
/*! Number of extra #bpart we allocate memory for per top-level cell */
int space_extra_bparts = space_extra_bparts_default;

89
90
91
/*! Number of extra #gpart we allocate memory for per top-level cell */
int space_extra_gparts = space_extra_gparts_default;

92
93
94
95
/*! Maximum number of particles per ghost */
int engine_max_parts_per_ghost = engine_max_parts_per_ghost_default;
int engine_max_sparts_per_ghost = engine_max_sparts_per_ghost_default;

96
/*! Maximal depth at which the stars resort task can be pushed */
97
int engine_star_resort_task_depth = engine_star_resort_task_depth_default;
98

99
100
/*! Expected maximal number of strays received at a rebuild */
int space_expected_max_nr_strays = space_expected_max_nr_strays_default;
Loic Hausammann's avatar
Loic Hausammann committed
101
#if defined(SWIFT_DEBUG_CHECKS) || defined(SWIFT_CELL_GRAPH)
102
103
int last_cell_id;
#endif
Pedro Gonnet's avatar
Pedro Gonnet committed
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
 * @brief Interval stack necessary for parallel particle sorting.
 */
struct qstack {
  volatile ptrdiff_t i, j;
  volatile int min, max;
  volatile int ready;
};

/**
 * @brief Parallel particle-sorting stack
 */
struct parallel_sort {
  struct part *parts;
  struct gpart *gparts;
  struct xpart *xparts;
121
  struct spart *sparts;
122
123
124
125
126
127
  int *ind;
  struct qstack *stack;
  unsigned int stack_size;
  volatile unsigned int first, last, waiting;
};

128
129
130
131
132
133
/**
 * @brief Information required to compute the particle cell indices.
 */
struct index_data {
  struct space *s;
  int *ind;
134
  int *cell_counts;
135
136
137
  size_t count_inhibited_part;
  size_t count_inhibited_gpart;
  size_t count_inhibited_spart;
138
  size_t count_inhibited_bpart;
139
140
141
  size_t count_extra_part;
  size_t count_extra_gpart;
  size_t count_extra_spart;
142
  size_t count_extra_bpart;
143
144
};

145
/**
146
 * @brief Recursively dismantle a cell tree.
147
 *
148
149
 * @param s The #space.
 * @param c The #cell to recycle.
Matthieu Schaller's avatar
Matthieu Schaller committed
150
151
152
153
154
155
 * @param cell_rec_begin Pointer to the start of the list of cells to recycle.
 * @param cell_rec_end Pointer to the end of the list of cells to recycle.
 * @param multipole_rec_begin Pointer to the start of the list of multipoles to
 * recycle.
 * @param multipole_rec_end Pointer to the end of the list of multipoles to
 * recycle.
156
 */
157
void space_rebuild_recycle_rec(struct space *s, struct cell *c,
158
159
                               struct cell **cell_rec_begin,
                               struct cell **cell_rec_end,
160
161
                               struct gravity_tensors **multipole_rec_begin,
                               struct gravity_tensors **multipole_rec_end) {
162
  if (c->split)
163
    for (int k = 0; k < 8; k++)
164
      if (c->progeny[k] != NULL) {
165
166
167
168
169
170
        space_rebuild_recycle_rec(s, c->progeny[k], cell_rec_begin,
                                  cell_rec_end, multipole_rec_begin,
                                  multipole_rec_end);

        c->progeny[k]->next = *cell_rec_begin;
        *cell_rec_begin = c->progeny[k];
171

172
        if (s->with_self_gravity) {
173
174
          c->progeny[k]->grav.multipole->next = *multipole_rec_begin;
          *multipole_rec_begin = c->progeny[k]->grav.multipole;
175
        }
176
177

        if (*cell_rec_end == NULL) *cell_rec_end = *cell_rec_begin;
178
        if (s->with_self_gravity && *multipole_rec_end == NULL)
179
180
          *multipole_rec_end = *multipole_rec_begin;

181
        c->progeny[k]->grav.multipole = NULL;
182
183
184
185
        c->progeny[k] = NULL;
      }
}

186
187
188
189
190
191
192
193
void space_rebuild_recycle_mapper(void *map_data, int num_elements,
                                  void *extra_data) {

  struct space *s = (struct space *)extra_data;
  struct cell *cells = (struct cell *)map_data;

  for (int k = 0; k < num_elements; k++) {
    struct cell *c = &cells[k];
194
    struct cell *cell_rec_begin = NULL, *cell_rec_end = NULL;
195
196
    struct gravity_tensors *multipole_rec_begin = NULL,
                           *multipole_rec_end = NULL;
197
198
199
200
201
    space_rebuild_recycle_rec(s, c, &cell_rec_begin, &cell_rec_end,
                              &multipole_rec_begin, &multipole_rec_end);
    if (cell_rec_begin != NULL)
      space_recycle_list(s, cell_rec_begin, cell_rec_end, multipole_rec_begin,
                         multipole_rec_end);
202
    c->hydro.sorts = NULL;
Loic Hausammann's avatar
Loic Hausammann committed
203
    c->stars.sorts = NULL;
204
    c->nr_tasks = 0;
205
206
207
208
    c->grav.nr_mm_tasks = 0;
    c->hydro.density = NULL;
    c->hydro.gradient = NULL;
    c->hydro.force = NULL;
209
    c->hydro.limiter = NULL;
210
211
    c->grav.grav = NULL;
    c->grav.mm = NULL;
212
213
    c->hydro.dx_max_part = 0.0f;
    c->hydro.dx_max_sort = 0.0f;
Loic Hausammann's avatar
Loic Hausammann committed
214
    c->stars.dx_max_part = 0.f;
Loic Hausammann's avatar
Loic Hausammann committed
215
    c->stars.dx_max_sort = 0.f;
216
    c->black_holes.dx_max_part = 0.f;
217
    c->hydro.sorted = 0;
Loic Hausammann's avatar
Loic Hausammann committed
218
    c->stars.sorted = 0;
219
    c->hydro.count = 0;
220
    c->hydro.count_total = 0;
221
    c->hydro.updated = 0;
222
    c->grav.count = 0;
223
    c->grav.count_total = 0;
224
    c->grav.updated = 0;
225
    c->stars.count = 0;
226
    c->stars.count_total = 0;
227
    c->stars.updated = 0;
228
229
230
    c->black_holes.count = 0;
    c->black_holes.count_total = 0;
    c->black_holes.updated = 0;
231
232
233
234
235
236
    c->grav.init = NULL;
    c->grav.init_out = NULL;
    c->hydro.extra_ghost = NULL;
    c->hydro.ghost_in = NULL;
    c->hydro.ghost_out = NULL;
    c->hydro.ghost = NULL;
237
238
    c->hydro.star_formation = NULL;
    c->hydro.stars_resort = NULL;
239
240
    c->stars.ghost = NULL;
    c->stars.density = NULL;
Alexei Borissov's avatar
Alexei Borissov committed
241
    c->stars.feedback = NULL;
242
243
244
    c->black_holes.density_ghost = NULL;
    c->black_holes.swallow_ghost[0] = NULL;
    c->black_holes.swallow_ghost[1] = NULL;
245
    c->black_holes.swallow_ghost[2] = NULL;
246
    c->black_holes.density = NULL;
247
    c->black_holes.swallow = NULL;
248
249
    c->black_holes.do_gas_swallow = NULL;
    c->black_holes.do_bh_swallow = NULL;
250
    c->black_holes.feedback = NULL;
251
252
    c->kick1 = NULL;
    c->kick2 = NULL;
253
    c->timestep = NULL;
254
255
    c->hydro.limiter_in = NULL;
    c->hydro.limiter_out = NULL;
256
    c->timestep_limiter = NULL;
257
    c->hydro.end_force = NULL;
258
    c->hydro.drift = NULL;
259
    c->stars.drift = NULL;
260
261
    c->stars.stars_in = NULL;
    c->stars.stars_out = NULL;
262
    c->black_holes.drift = NULL;
263
264
    c->black_holes.black_holes_in = NULL;
    c->black_holes.black_holes_out = NULL;
265
    c->grav.drift = NULL;
266
    c->grav.drift_out = NULL;
267
268
269
270
271
    c->hydro.cooling = NULL;
    c->grav.long_range = NULL;
    c->grav.down_in = NULL;
    c->grav.down = NULL;
    c->grav.mesh = NULL;
272
    c->grav.end_force = NULL;
273
    c->top = c;
274
    c->super = c;
275
276
277
278
    c->hydro.super = c;
    c->grav.super = c;
    c->hydro.parts = NULL;
    c->hydro.xparts = NULL;
279
280
    c->grav.parts = NULL;
    c->stars.parts = NULL;
281
    c->stars.parts_rebuild = NULL;
282
    c->black_holes.parts = NULL;
283
    c->flags = 0;
284
285
286
287
    c->hydro.ti_end_min = -1;
    c->hydro.ti_end_max = -1;
    c->grav.ti_end_min = -1;
    c->grav.ti_end_max = -1;
Loic Hausammann's avatar
Loic Hausammann committed
288
    c->stars.ti_end_min = -1;
289
    c->stars.ti_end_max = -1;
290
291
    c->black_holes.ti_end_min = -1;
    c->black_holes.ti_end_max = -1;
292
    star_formation_logger_init(&c->stars.sfh);
Loic Hausammann's avatar
Loic Hausammann committed
293
#if defined(SWIFT_DEBUG_CHECKS) || defined(SWIFT_CELL_GRAPH)
294
295
    c->cellID = 0;
#endif
296
297
    if (s->with_self_gravity)
      bzero(c->grav.multipole, sizeof(struct gravity_tensors));
298

299
300
    cell_free_hydro_sorts(c);
    cell_free_stars_sorts(c);
301
#if WITH_MPI
302
    c->mpi.tag = -1;
303
    c->mpi.recv = NULL;
304
    c->mpi.send = NULL;
305
306
307
308
#endif
  }
}

309
310
/**
 * @brief Free up any allocated cells.
311
312
 *
 * @param s The #space.
313
314
 */
void space_free_cells(struct space *s) {
315
316
317

  ticks tic = getticks();

Matthieu Schaller's avatar
Matthieu Schaller committed
318
319
  threadpool_map(&s->e->threadpool, space_rebuild_recycle_mapper, s->cells_top,
                 s->nr_cells, sizeof(struct cell), 0, s);
320
  s->maxdepth = 0;
321
322
323
324

  if (s->e->verbose)
    message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
            clocks_getunit());
325
326
}

327
328
329
330
331
332
333
334
335
/**
 * @brief Free any memory in use for foreign particles.
 *
 * @param s The #space.
 */
void space_free_foreign_parts(struct space *s) {

#ifdef WITH_MPI
  if (s->parts_foreign != NULL) {
Peter W. Draper's avatar
Peter W. Draper committed
336
    swift_free("parts_foreign", s->parts_foreign);
337
338
339
340
    s->size_parts_foreign = 0;
    s->parts_foreign = NULL;
  }
  if (s->gparts_foreign != NULL) {
Peter W. Draper's avatar
Peter W. Draper committed
341
    swift_free("gparts_foreign", s->gparts_foreign);
342
343
344
345
    s->size_gparts_foreign = 0;
    s->gparts_foreign = NULL;
  }
  if (s->sparts_foreign != NULL) {
Peter W. Draper's avatar
Peter W. Draper committed
346
    swift_free("sparts_foreign", s->sparts_foreign);
347
348
349
    s->size_sparts_foreign = 0;
    s->sparts_foreign = NULL;
  }
350
351
352
353
354
  if (s->bparts_foreign != NULL) {
    swift_free("bparts_foreign", s->bparts_foreign);
    s->size_bparts_foreign = 0;
    s->bparts_foreign = NULL;
  }
355
356
357
#endif
}

358
/**
359
 * @brief Re-build the top-level cell grid.
360
 *
361
 * @param s The #space.
362
 * @param verbose Print messages to stdout or not.
363
 */
364
void space_regrid(struct space *s, int verbose) {
365

366
  const size_t nr_parts = s->nr_parts;
Loic Hausammann's avatar
Loic Hausammann committed
367
  const size_t nr_sparts = s->nr_sparts;
368
  const size_t nr_bparts = s->nr_bparts;
369
  const ticks tic = getticks();
370
  const integertime_t ti_current = (s->e != NULL) ? s->e->ti_current : 0;
371

372
  /* Run through the cells and get the current h_max. */
373
  // tic = getticks();
374
  float h_max = s->cell_min / kernel_gamma / space_stretch;
375
  if (nr_parts > 0) {
376
377
378
379
380
381

    /* Can we use the list of local non-empty top-level cells? */
    if (s->local_cells_with_particles_top != NULL) {
      for (int k = 0; k < s->nr_local_cells_with_particles; ++k) {
        const struct cell *c =
            &s->cells_top[s->local_cells_with_particles_top[k]];
382
        if (c->hydro.h_max > h_max) {
383
          h_max = c->hydro.h_max;
384
        }
Loic Hausammann's avatar
Loic Hausammann committed
385
        if (c->stars.h_max > h_max) {
386
          h_max = c->stars.h_max;
Loic Hausammann's avatar
Loic Hausammann committed
387
        }
388
389
390
        if (c->black_holes.h_max > h_max) {
          h_max = c->black_holes.h_max;
        }
391
      }
392
393

      /* Can we instead use all the top-level cells? */
394
    } else if (s->cells_top != NULL) {
Tom Theuns's avatar
Tom Theuns committed
395
      for (int k = 0; k < s->nr_cells; k++) {
396
        const struct cell *c = &s->cells_top[k];
397
        if (c->nodeID == engine_rank && c->hydro.h_max > h_max) {
398
          h_max = c->hydro.h_max;
399
        }
Loic Hausammann's avatar
Loic Hausammann committed
400
        if (c->nodeID == engine_rank && c->stars.h_max > h_max) {
401
          h_max = c->stars.h_max;
Loic Hausammann's avatar
Loic Hausammann committed
402
        }
403
404
405
        if (c->nodeID == engine_rank && c->black_holes.h_max > h_max) {
          h_max = c->black_holes.h_max;
        }
406
      }
407
408

      /* Last option: run through the particles */
409
    } else {
410
      for (size_t k = 0; k < nr_parts; k++) {
Matthieu Schaller's avatar
Matthieu Schaller committed
411
        if (s->parts[k].h > h_max) h_max = s->parts[k].h;
412
      }
Loic Hausammann's avatar
Loic Hausammann committed
413
414
415
      for (size_t k = 0; k < nr_sparts; k++) {
        if (s->sparts[k].h > h_max) h_max = s->sparts[k].h;
      }
416
417
418
      for (size_t k = 0; k < nr_bparts; k++) {
        if (s->bparts[k].h > h_max) h_max = s->bparts[k].h;
      }
419
420
421
422
423
424
425
426
427
428
    }
  }

/* If we are running in parallel, make sure everybody agrees on
   how large the largest cell should be. */
#ifdef WITH_MPI
  {
    float buff;
    if (MPI_Allreduce(&h_max, &buff, 1, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD) !=
        MPI_SUCCESS)
429
      error("Failed to aggregate the rebuild flag across nodes.");
430
431
432
    h_max = buff;
  }
#endif
433
  if (verbose) message("h_max is %.3e (cell_min=%.3e).", h_max, s->cell_min);
434
435

  /* Get the new putative cell dimensions. */
436
  const int cdim[3] = {
437
438
439
440
441
442
      (int)floor(s->dim[0] /
                 fmax(h_max * kernel_gamma * space_stretch, s->cell_min)),
      (int)floor(s->dim[1] /
                 fmax(h_max * kernel_gamma * space_stretch, s->cell_min)),
      (int)floor(s->dim[2] /
                 fmax(h_max * kernel_gamma * space_stretch, s->cell_min))};
443
444
445
446
447

  /* Check if we have enough cells for periodicity. */
  if (s->periodic && (cdim[0] < 3 || cdim[1] < 3 || cdim[2] < 3))
    error(
        "Must have at least 3 cells in each spatial dimension when periodicity "
448
449
450
        "is switched on.\nThis error is often caused by any of the "
        "followings:\n"
        " - too few particles to generate a sensible grid,\n"
451
452
        " - the initial value of 'Scheduler:max_top_level_cells' is too "
        "small,\n"
453
        " - the (minimal) time-step is too large leading to particles with "
454
        "predicted smoothing lengths too large for the box size,\n"
455
        " - particles with velocities so large that they move by more than two "
456
        "box sizes per time-step.\n");
457

458
459
460
/* In MPI-Land, changing the top-level cell size requires that the
 * global partition is recomputed and the particles redistributed.
 * Be prepared to do that. */
461
#ifdef WITH_MPI
Matthieu Schaller's avatar
Matthieu Schaller committed
462
  double oldwidth[3];
463
464
465
466
467
468
469
470
  double oldcdim[3];
  int *oldnodeIDs = NULL;
  if (cdim[0] < s->cdim[0] || cdim[1] < s->cdim[1] || cdim[2] < s->cdim[2]) {

    /* Capture state of current space. */
    oldcdim[0] = s->cdim[0];
    oldcdim[1] = s->cdim[1];
    oldcdim[2] = s->cdim[2];
471
472
473
    oldwidth[0] = s->width[0];
    oldwidth[1] = s->width[1];
    oldwidth[2] = s->width[2];
474

475
476
    if ((oldnodeIDs =
             (int *)swift_malloc("nodeIDs", sizeof(int) * s->nr_cells)) == NULL)
477
478
479
480
481
482
483
      error("Failed to allocate temporary nodeIDs.");

    int cid = 0;
    for (int i = 0; i < s->cdim[0]; i++) {
      for (int j = 0; j < s->cdim[1]; j++) {
        for (int k = 0; k < s->cdim[2]; k++) {
          cid = cell_getid(oldcdim, i, j, k);
484
          oldnodeIDs[cid] = s->cells_top[cid].nodeID;
485
486
487
488
489
        }
      }
    }
  }

Peter W. Draper's avatar
Peter W. Draper committed
490
  /* Are we about to allocate new top level cells without a regrid?
Peter W. Draper's avatar
Peter W. Draper committed
491
   * Can happen when restarting the application. */
492
  const int no_regrid = (s->cells_top == NULL && oldnodeIDs == NULL);
493
494
495
496
#endif

  /* Do we need to re-build the upper-level cells? */
  // tic = getticks();
497
  if (s->cells_top == NULL || cdim[0] < s->cdim[0] || cdim[1] < s->cdim[1] ||
498
499
      cdim[2] < s->cdim[2]) {

500
501
/* Be verbose about this. */
#ifdef SWIFT_DEBUG_CHECKS
502
    message("(re)griding space cdim=(%d %d %d)", cdim[0], cdim[1], cdim[2]);
503
504
505
    fflush(stdout);
#endif

506
    /* Free the old cells, if they were allocated. */
507
    if (s->cells_top != NULL) {
508
      space_free_cells(s);
509
510
511
      swift_free("local_cells_with_tasks_top", s->local_cells_with_tasks_top);
      swift_free("local_cells_top", s->local_cells_top);
      swift_free("cells_with_particles_top", s->cells_with_particles_top);
512
513
      swift_free("local_cells_with_particles_top",
                 s->local_cells_with_particles_top);
514
515
      swift_free("cells_top", s->cells_top);
      swift_free("multipoles_top", s->multipoles_top);
516
517
    }

518
519
520
521
    /* Also free the task arrays, these will be regenerated and we can use the
     * memory while copying the particle arrays. */
    if (s->e != NULL) scheduler_free_tasks(&s->e->sched);

522
    /* Set the new cell dimensions only if smaller. */
523
    for (int k = 0; k < 3; k++) {
524
      s->cdim[k] = cdim[k];
525
526
      s->width[k] = s->dim[k] / cdim[k];
      s->iwidth[k] = 1.0 / s->width[k];
527
    }
528
    const float dmin = min3(s->width[0], s->width[1], s->width[2]);
529
530
531

    /* Allocate the highest level of cells. */
    s->tot_cells = s->nr_cells = cdim[0] * cdim[1] * cdim[2];
532

533
    if (swift_memalign("cells_top", (void **)&s->cells_top, cell_align,
534
                       s->nr_cells * sizeof(struct cell)) != 0)
535
      error("Failed to allocate top-level cells.");
536
    bzero(s->cells_top, s->nr_cells * sizeof(struct cell));
537

538
    /* Allocate the multipoles for the top-level cells. */
539
    if (s->with_self_gravity) {
540
541
      if (swift_memalign("multipoles_top", (void **)&s->multipoles_top,
                         multipole_align,
542
                         s->nr_cells * sizeof(struct gravity_tensors)) != 0)
543
        error("Failed to allocate top-level multipoles.");
544
      bzero(s->multipoles_top, s->nr_cells * sizeof(struct gravity_tensors));
545
546
    }

547
    /* Allocate the indices of local cells */
548
549
    if (swift_memalign("local_cells_top", (void **)&s->local_cells_top,
                       SWIFT_STRUCT_ALIGNMENT, s->nr_cells * sizeof(int)) != 0)
550
551
552
      error("Failed to allocate indices of local top-level cells.");
    bzero(s->local_cells_top, s->nr_cells * sizeof(int));

553
    /* Allocate the indices of local cells with tasks */
554
555
    if (swift_memalign("local_cells_with_tasks_top",
                       (void **)&s->local_cells_with_tasks_top,
556
                       SWIFT_STRUCT_ALIGNMENT, s->nr_cells * sizeof(int)) != 0)
557
      error("Failed to allocate indices of local top-level cells with tasks.");
558
559
    bzero(s->local_cells_with_tasks_top, s->nr_cells * sizeof(int));

560
    /* Allocate the indices of cells with particles */
561
562
    if (swift_memalign("cells_with_particles_top",
                       (void **)&s->cells_with_particles_top,
563
                       SWIFT_STRUCT_ALIGNMENT, s->nr_cells * sizeof(int)) != 0)
564
565
      error("Failed to allocate indices of top-level cells with particles.");
    bzero(s->cells_with_particles_top, s->nr_cells * sizeof(int));
566

567
    /* Allocate the indices of local cells with particles */
568
569
    if (swift_memalign("local_cells_with_particles_top",
                       (void **)&s->local_cells_with_particles_top,
570
571
572
573
574
575
                       SWIFT_STRUCT_ALIGNMENT, s->nr_cells * sizeof(int)) != 0)
      error(
          "Failed to allocate indices of local top-level cells with "
          "particles.");
    bzero(s->local_cells_with_particles_top, s->nr_cells * sizeof(int));

576
    /* Set the cells' locks */
577
    for (int k = 0; k < s->nr_cells; k++) {
578
      if (lock_init(&s->cells_top[k].hydro.lock) != 0)
579
        error("Failed to init spinlock for hydro.");
580
      if (lock_init(&s->cells_top[k].grav.plock) != 0)
581
        error("Failed to init spinlock for gravity.");
582
      if (lock_init(&s->cells_top[k].grav.mlock) != 0)
583
        error("Failed to init spinlock for multipoles.");
584
      if (lock_init(&s->cells_top[k].stars.lock) != 0)
585
        error("Failed to init spinlock for stars.");
Matthieu Schaller's avatar
Matthieu Schaller committed
586
587
      if (lock_init(&s->cells_top[k].black_holes.lock) != 0)
        error("Failed to init spinlock for black holes.");
588
589
      if (lock_init(&s->cells_top[k].stars.star_formation_lock) != 0)
        error("Failed to init spinlock for star formation.");
590
    }
591
592

    /* Set the cell location and sizes. */
593
594
595
    for (int i = 0; i < cdim[0]; i++)
      for (int j = 0; j < cdim[1]; j++)
        for (int k = 0; k < cdim[2]; k++) {
596
597
          const size_t cid = cell_getid(cdim, i, j, k);
          struct cell *restrict c = &s->cells_top[cid];
598
599
600
601
602
603
          c->loc[0] = i * s->width[0];
          c->loc[1] = j * s->width[1];
          c->loc[2] = k * s->width[2];
          c->width[0] = s->width[0];
          c->width[1] = s->width[1];
          c->width[2] = s->width[2];
604
605
          c->dmin = dmin;
          c->depth = 0;
606
          c->split = 0;
607
          c->hydro.count = 0;
608
609
          c->grav.count = 0;
          c->stars.count = 0;
610
          c->top = c;
611
          c->super = c;
612
613
          c->hydro.super = c;
          c->grav.super = c;
614
615
          c->hydro.ti_old_part = ti_current;
          c->grav.ti_old_part = ti_current;
616
          c->stars.ti_old_part = ti_current;
617
          c->black_holes.ti_old_part = ti_current;
618
          c->grav.ti_old_multipole = ti_current;
Pedro Gonnet's avatar
Pedro Gonnet committed
619
#ifdef WITH_MPI
620
          c->mpi.tag = -1;
621
          c->mpi.recv = NULL;
622
          c->mpi.send = NULL;
Pedro Gonnet's avatar
Pedro Gonnet committed
623
#endif  // WITH_MPI
624
          if (s->with_self_gravity) c->grav.multipole = &s->multipoles_top[cid];
Loic Hausammann's avatar
Loic Hausammann committed
625
#if defined(SWIFT_DEBUG_CHECKS) || defined(SWIFT_CELL_GRAPH)
Matthieu Schaller's avatar
Matthieu Schaller committed
626
627
          c->cellID = -last_cell_id;
          last_cell_id++;
628
#endif
Pedro Gonnet's avatar
Pedro Gonnet committed
629
        }
630
631

    /* Be verbose about the change. */
632
633
634
    if (verbose)
      message("set cell dimensions to [ %i %i %i ].", cdim[0], cdim[1],
              cdim[2]);
635

636
#ifdef WITH_MPI
637
638
639
640
641
    if (oldnodeIDs != NULL) {
      /* We have changed the top-level cell dimension, so need to redistribute
       * cells around the nodes. We repartition using the old space node
       * positions as a grid to resample. */
      if (s->e->nodeID == 0)
642
643
644
        message(
            "basic cell dimensions have increased - recalculating the "
            "global partition.");
645

Matthieu Schaller's avatar
Matthieu Schaller committed
646
      if (!partition_space_to_space(oldwidth, oldcdim, oldnodeIDs, s)) {
647
648
649
650

        /* Failed, try another technique that requires no settings. */
        message("Failed to get a new partition, trying less optimal method");
        struct partition initial_partition;
651
#if defined(HAVE_PARMETIS) || defined(HAVE_METIS)
652
653
654
655
656
657
658
659
660
661
662
663
664
        initial_partition.type = INITPART_METIS_NOWEIGHT;
#else
        initial_partition.type = INITPART_VECTORIZE;
#endif
        partition_initial_partition(&initial_partition, s->e->nodeID,
                                    s->e->nr_nodes, s);
      }

      /* Re-distribute the particles to their new nodes. */
      engine_redistribute(s->e);

      /* Make the proxies. */
      engine_makeproxies(s->e);
665

666
      /* Finished with these. */
667
      swift_free("nodeIDs", oldnodeIDs);
Peter W. Draper's avatar
Peter W. Draper committed
668
669

    } else if (no_regrid && s->e != NULL) {
Peter W. Draper's avatar
Peter W. Draper committed
670
671
672
673
674
675
676
677
678
679
680
681
682
      /* If we have created the top-levels cells and not done an initial
       * partition (can happen when restarting), then the top-level cells
       * are not assigned to a node, we must do that and then associate the
       * particles with the cells. Note requires that
       * partition_store_celllist() was called once before, or just before
       * dumping the restart files.*/
      partition_restore_celllist(s, s->e->reparttype);

      /* Now re-distribute the particles, should just add to cells? */
      engine_redistribute(s->e);

      /* Make the proxies. */
      engine_makeproxies(s->e);
683
    }
Pedro Gonnet's avatar
Pedro Gonnet committed
684
#endif /* WITH_MPI */
685
686
687
688

    // message( "rebuilding upper-level cells took %.3f %s." ,
    // clocks_from_ticks(double)(getticks() - tic), clocks_getunit());

689
  }      /* re-build upper-level cells? */
690
  else { /* Otherwise, just clean up the cells. */
691
692

    /* Free the old cells, if they were allocated. */
693
    space_free_cells(s);
694
  }
695
696
697
698

  if (verbose)
    message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
            clocks_getunit());
699
}
700

701
702
703
704
705
706
/**
 * @brief Allocate memory for the extra particles used for on-the-fly creation.
 *
 * This rarely actually allocates memory. Most of the time, we convert
 * pre-allocated memory inot extra particles.
 *
707
708
 * This function also sets the extra particles' location to their top-level
 * cells. They can then be sorted into their correct memory position later on.
709
710
711
712
 *
 * @param s The current #space.
 * @param verbose Are we talkative?
 */
713
714
715
716
void space_allocate_extras(struct space *s, int verbose) {

  const int local_nodeID = s->e->nodeID;

717
718
719
720
721
  /* Anything to do here? (Abort if we don't want extras)*/
  if (space_extra_parts == 0 && space_extra_gparts == 0 &&
      space_extra_sparts == 0)
    return;

722
723
724
725
726
727
  /* The top-level cells */
  const struct cell *cells = s->cells_top;
  const double half_cell_width[3] = {0.5 * cells[0].width[0],
                                     0.5 * cells[0].width[1],
                                     0.5 * cells[0].width[2]};

728
  /* The current number of particles (including spare ones) */
729
730
731
  size_t nr_parts = s->nr_parts;
  size_t nr_gparts = s->nr_gparts;
  size_t nr_sparts = s->nr_sparts;
732
  size_t nr_bparts = s->nr_bparts;
733

734
735
736
737
  /* The current number of actual particles */
  size_t nr_actual_parts = nr_parts - s->nr_extra_parts;
  size_t nr_actual_gparts = nr_gparts - s->nr_extra_gparts;
  size_t nr_actual_sparts = nr_sparts - s->nr_extra_sparts;
738
  size_t nr_actual_bparts = nr_bparts - s->nr_extra_bparts;
739

740
741
742
743
  /* The number of particles we allocated memory for (MPI overhead) */
  size_t size_parts = s->size_parts;
  size_t size_gparts = s->size_gparts;
  size_t size_sparts = s->size_sparts;
744
  size_t size_bparts = s->size_bparts;
745

746
747
748
749
750
751
752
753
754
755
756
757
  int *local_cells = (int *)malloc(sizeof(int) * s->nr_cells);
  if (local_cells == NULL)
    error("Failed to allocate list of local top-level cells");

  /* List the local cells */
  int nr_local_cells = 0;
  for (int i = 0; i < s->nr_cells; ++i) {
    if (s->cells_top[i].nodeID == local_nodeID) {
      local_cells[nr_local_cells] = i;
      ++nr_local_cells;
    }
  }
758

759
  /* Number of extra particles we want for each type */
760
761
762
  const size_t expected_num_extra_parts = nr_local_cells * space_extra_parts;
  const size_t expected_num_extra_gparts = nr_local_cells * space_extra_gparts;
  const size_t expected_num_extra_sparts = nr_local_cells * space_extra_sparts;
763
  const size_t expected_num_extra_bparts = nr_local_cells * space_extra_bparts;
764

765
  if (verbose) {
766
767
768
769
770
771
772
773
774
    message("Currently have %zd/%zd/%zd/%zd real particles.", nr_actual_parts,
            nr_actual_gparts, nr_actual_sparts, nr_actual_bparts);
    message("Currently have %zd/%zd/%zd/%zd spaces for extra particles.",
            s->nr_extra_parts, s->nr_extra_gparts, s->nr_extra_sparts,
            s->nr_extra_bparts);
    message(
        "Requesting space for future %zd/%zd/%zd/%zd part/gpart/sparts/bparts.",
        expected_num_extra_parts, expected_num_extra_gparts,
        expected_num_extra_sparts, expected_num_extra_bparts);
775
  }
776

777
778
779
780
781
782
783
  if (expected_num_extra_parts < s->nr_extra_parts)
    error("Reduction in top-level cells number not handled.");
  if (expected_num_extra_gparts < s->nr_extra_gparts)
    error("Reduction in top-level cells number not handled.");
  if (expected_num_extra_sparts < s->nr_extra_sparts)
    error("Reduction in top-level cells number not handled.");

784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
  /* Do we have enough space for the extra gparts (i.e. we haven't used up any)
   * ? */
  if (nr_gparts + expected_num_extra_gparts > size_gparts) {

    /* Ok... need to put some more in the game */

    /* Do we need to reallocate? */
    if (nr_actual_gparts + expected_num_extra_gparts > size_gparts) {

      size_gparts = (nr_actual_gparts + expected_num_extra_gparts) *
                    engine_redistribute_alloc_margin;

      if (verbose)
        message("Re-allocating gparts array from %zd to %zd", s->size_gparts,
                size_gparts);

      /* Create more space for parts */
      struct gpart *gparts_new = NULL;
802
      if (swift_memalign("gparts", (void **)&gparts_new, gpart_align,
803
804
805
806
                         sizeof(struct gpart) * size_gparts) != 0)
        error("Failed to allocate new gpart data");
      const ptrdiff_t delta = gparts_new - s->gparts;
      memcpy(gparts_new, s->gparts, sizeof(struct gpart) * s->size_gparts);
807
      swift_free("gparts", s->gparts);
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
      s->gparts = gparts_new;

      /* Update the counter */
      s->size_gparts = size_gparts;

      /* We now need to reset all the part and spart pointers */
      for (size_t i = 0; i < nr_parts; ++i) {
        if (s->parts[i].time_bin != time_bin_not_created)
          s->parts[i].gpart += delta;
      }
      for (size_t i = 0; i < nr_sparts; ++i) {
        if (s->sparts[i].time_bin != time_bin_not_created)
          s->sparts[i].gpart += delta;
      }
    }

    /* Turn some of the allocated spares into particles we can use */
    for (size_t i = nr_gparts; i < nr_actual_gparts + expected_num_extra_gparts;
         ++i) {
      bzero(&s->gparts[i], sizeof(struct gpart));
      s->gparts[i].time_bin = time_bin_not_created;
      s->gparts[i].type = swift_type_dark_matter;
      s->gparts[i].id_or_neg_offset = -1;
    }

833
834
835
836
    /* Put the spare particles in their correct cell */
    int local_cell_id = 0;
    int current_cell = local_cells[local_cell_id];
    int count_in_cell = 0;
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
    size_t count_extra_gparts = 0;
    for (size_t i = 0; i < nr_actual_gparts + expected_num_extra_gparts; ++i) {

#ifdef SWIFT_DEBUG_CHECKS
      if (current_cell == s->nr_cells)
        error("Cell counter beyond the maximal nr. cells.");
#endif

      if (s->gparts[i].time_bin == time_bin_not_created) {

        /* We want the extra particles to be at the centre of their cell */
        s->gparts[i].x[0] = cells[current_cell].loc[0] + half_cell_width[0];
        s->gparts[i].x[1] = cells[current_cell].loc[1] + half_cell_width[1];
        s->gparts[i].x[2] = cells[current_cell].loc[2] + half_cell_width[2];
        ++count_in_cell;
        count_extra_gparts++;
      }

      /* Once we have reached the number of extra gpart per cell, we move to the
       * next */
      if (count_in_cell == space_extra_gparts) {
858
859
860
861
862
        ++local_cell_id;

        if (local_cell_id == nr_local_cells) break;

        current_cell = local_cells[local_cell_id];
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
        count_in_cell = 0;
      }
    }

#ifdef SWIFT_DEBUG_CHECKS
    if (count_extra_gparts != expected_num_extra_gparts)
      error("Constructed the wrong number of extra gparts (%zd vs. %zd)",
            count_extra_gparts, expected_num_extra_gparts);
#endif

    /* Update the counters */
    s->nr_gparts = nr_actual_gparts + expected_num_extra_gparts;
    s->nr_extra_gparts = expected_num_extra_gparts;
  }

878
879
  /* Do we have enough space for the extra parts (i.e. we haven't used up any) ?
   */
880
881
  if (expected_num_extra_parts > s->nr_extra_parts) {

882
883
    /* Ok... need to put some more in the game */

884
885
886
887
888
889
890
891
892
893
894
895
    /* Do we need to reallocate? */
    if (nr_actual_parts + expected_num_extra_parts > size_parts) {

      size_parts = (nr_actual_parts + expected_num_extra_parts) *
                   engine_redistribute_alloc_margin;

      if (verbose)
        message("Re-allocating parts array from %zd to %zd", s->size_parts,
                size_parts);

      /* Create more space for parts */
      struct part *parts_new = NULL;
896
      if (swift_memalign("parts", (void **)&parts_new, part_align,
897
898
899
                         sizeof(struct part) * size_parts) != 0)
        error("Failed to allocate new part data");
      memcpy(parts_new, s->parts, sizeof(struct part) * s->size_parts);
900
      swift_free("parts", s->parts);
901
902
903
904
      s->parts = parts_new;

      /* Same for xparts */
      struct xpart *xparts_new = NULL;
905
      if (swift_memalign("xparts", (void **)&xparts_new, xpart_align,
906
907
908
                         sizeof(struct xpart) * size_parts) != 0)
        error("Failed to allocate new xpart data");
      memcpy(xparts_new, s->xparts, sizeof(struct xpart) * s->size_parts);
909
      swift_free("xparts", s->xparts);
910
911
912
913
914
915
      s->xparts = xparts_new;

      /* Update the counter */
      s->size_parts = size_parts;
    }

916
    /* Turn some of the allocated spares into particles we can use */
917
918
919
920
921
    for (size_t i = nr_parts; i < nr_actual_parts + expected_num_extra_parts;
         ++i) {
      bzero(&s->parts[i], sizeof(struct part));
      bzero(&s->xparts[i], sizeof(struct xpart));
      s->parts[i].time_bin = time_bin_not_created;
922
      s->parts[i].id = -1;
923
924
    }

925
926
927
928
    /* Put the spare particles in their correct cell */
    int local_cell_id = 0;
    int current_cell = local_cells[local_cell_id];
    int count_in_cell = 0;
929
930
    size_t count_extra_parts = 0;
    for (size_t i = 0; i < nr_actual_parts + expected_num_extra_parts; ++i) {
931
932
933
934
935
936

#ifdef SWIFT_DEBUG_CHECKS
      if (current_cell == s->nr_cells)
        error("Cell counter beyond the maximal nr. cells.");
#endif

937
938
939
940
941
942
943
944
945
946
947
948