space.c 156 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 "chemistry.h"
45
#include "const.h"
46
#include "cooling.h"
47
#include "debug.h"
48
#include "engine.h"
49
#include "error.h"
50
51
#include "gravity.h"
#include "hydro.h"
52
#include "kernel_hydro.h"
53
#include "lock.h"
54
#include "memswap.h"
55
#include "memuse.h"
56
#include "minmax.h"
57
#include "multipole.h"
58
#include "restart.h"
59
#include "sort_part.h"
Loic Hausammann's avatar
Loic Hausammann committed
60
#include "star_formation.h"
Loic Hausammann's avatar
Format    
Loic Hausammann committed
61
#include "stars.h"
62
#include "threadpool.h"
63
#include "tools.h"
64
#include "tracers.h"
Pedro Gonnet's avatar
Pedro Gonnet committed
65
66
67

/* Split size. */
int space_splitsize = space_splitsize_default;
68
69
70
int space_subsize_pair_hydro = space_subsize_pair_hydro_default;
int space_subsize_self_hydro = space_subsize_self_hydro_default;
int space_subsize_pair_grav = space_subsize_pair_grav_default;
71
int space_subsize_self_grav = space_subsize_self_grav_default;
72
int space_subdepth_diff_grav = space_subdepth_diff_grav_default;
73
int space_maxsize = space_maxsize_default;
74

75
76
77
/*! Number of extra #part we allocate memory for per top-level cell */
int space_extra_parts = space_extra_parts_default;

78
79
80
/*! Number of extra #spart we allocate memory for per top-level cell */
int space_extra_sparts = space_extra_sparts_default;

81
82
83
/*! Number of extra #gpart we allocate memory for per top-level cell */
int space_extra_gparts = space_extra_gparts_default;

84
85
/*! 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
86
#if defined(SWIFT_DEBUG_CHECKS) || defined(SWIFT_CELL_GRAPH)
87
88
int last_cell_id;
#endif
Pedro Gonnet's avatar
Pedro Gonnet committed
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**
 * @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;
106
  struct spart *sparts;
107
108
109
110
111
112
  int *ind;
  struct qstack *stack;
  unsigned int stack_size;
  volatile unsigned int first, last, waiting;
};

113
114
115
116
117
118
/**
 * @brief Information required to compute the particle cell indices.
 */
struct index_data {
  struct space *s;
  int *ind;
119
  int *cell_counts;
120
121
122
123
124
125
  size_t count_inhibited_part;
  size_t count_inhibited_gpart;
  size_t count_inhibited_spart;
  size_t count_extra_part;
  size_t count_extra_gpart;
  size_t count_extra_spart;
126
127
};

128
/**
129
 * @brief Recursively dismantle a cell tree.
130
 *
131
132
 * @param s The #space.
 * @param c The #cell to recycle.
Matthieu Schaller's avatar
Matthieu Schaller committed
133
134
135
136
137
138
 * @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.
139
 */
140
void space_rebuild_recycle_rec(struct space *s, struct cell *c,
141
142
                               struct cell **cell_rec_begin,
                               struct cell **cell_rec_end,
143
144
                               struct gravity_tensors **multipole_rec_begin,
                               struct gravity_tensors **multipole_rec_end) {
145
  if (c->split)
146
    for (int k = 0; k < 8; k++)
147
      if (c->progeny[k] != NULL) {
148
149
150
151
152
153
        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];
154

155
        if (s->with_self_gravity) {
156
157
          c->progeny[k]->grav.multipole->next = *multipole_rec_begin;
          *multipole_rec_begin = c->progeny[k]->grav.multipole;
158
        }
159
160

        if (*cell_rec_end == NULL) *cell_rec_end = *cell_rec_begin;
161
        if (s->with_self_gravity && *multipole_rec_end == NULL)
162
163
          *multipole_rec_end = *multipole_rec_begin;

164
        c->progeny[k]->grav.multipole = NULL;
165
166
167
168
        c->progeny[k] = NULL;
      }
}

169
170
171
172
173
174
175
176
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];
177
    struct cell *cell_rec_begin = NULL, *cell_rec_end = NULL;
178
179
    struct gravity_tensors *multipole_rec_begin = NULL,
                           *multipole_rec_end = NULL;
180
181
182
183
184
    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);
185
    c->hydro.sorts = NULL;
Loic Hausammann's avatar
Loic Hausammann committed
186
    c->stars.sorts = NULL;
187
    c->nr_tasks = 0;
188
189
190
191
    c->grav.nr_mm_tasks = 0;
    c->hydro.density = NULL;
    c->hydro.gradient = NULL;
    c->hydro.force = NULL;
192
    c->hydro.limiter = NULL;
193
194
    c->grav.grav = NULL;
    c->grav.mm = NULL;
195
196
    c->hydro.dx_max_part = 0.0f;
    c->hydro.dx_max_sort = 0.0f;
Loic Hausammann's avatar
Loic Hausammann committed
197
    c->stars.dx_max_part = 0.f;
Loic Hausammann's avatar
Loic Hausammann committed
198
    c->stars.dx_max_sort = 0.f;
199
    c->hydro.sorted = 0;
Loic Hausammann's avatar
Loic Hausammann committed
200
    c->stars.sorted = 0;
201
    c->hydro.count = 0;
202
    c->hydro.count_total = 0;
203
204
    c->hydro.updated = 0;
    c->hydro.inhibited = 0;
205
    c->grav.count = 0;
206
    c->grav.count_total = 0;
207
208
    c->grav.updated = 0;
    c->grav.inhibited = 0;
209
    c->stars.count = 0;
210
    c->stars.count_total = 0;
211
212
    c->stars.updated = 0;
    c->stars.inhibited = 0;
213
214
215
216
217
218
    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;
219
220
    c->stars.ghost = NULL;
    c->stars.density = NULL;
Alexei Borissov's avatar
Alexei Borissov committed
221
    c->stars.feedback = NULL;
222
223
    c->kick1 = NULL;
    c->kick2 = NULL;
224
    c->timestep = NULL;
225
    c->timestep_limiter = NULL;
226
    c->hydro.end_force = NULL;
227
    c->hydro.drift = NULL;
228
    c->stars.drift = NULL;
229
230
    c->stars.stars_in = NULL;
    c->stars.stars_out = NULL;
231
    c->grav.drift = NULL;
232
    c->grav.drift_out = NULL;
233
234
235
236
237
    c->hydro.cooling = NULL;
    c->grav.long_range = NULL;
    c->grav.down_in = NULL;
    c->grav.down = NULL;
    c->grav.mesh = NULL;
238
    c->grav.end_force = NULL;
239
    c->top = c;
240
    c->super = c;
241
242
243
244
    c->hydro.super = c;
    c->grav.super = c;
    c->hydro.parts = NULL;
    c->hydro.xparts = NULL;
245
246
    c->grav.parts = NULL;
    c->stars.parts = NULL;
247
    c->hydro.do_sub_sort = 0;
Loic Hausammann's avatar
Loic Hausammann committed
248
    c->stars.do_sub_sort = 0;
249
    c->hydro.do_sub_drift = 0;
250
251
    c->grav.do_sub_drift = 0;
    c->stars.do_sub_drift = 0;
252
253
    c->hydro.do_sub_limiter = 0;
    c->hydro.do_limiter = 0;
254
255
256
257
    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
258
    c->stars.ti_end_min = -1;
259
    c->stars.ti_end_max = -1;
Loic Hausammann's avatar
Loic Hausammann committed
260
#if defined(SWIFT_DEBUG_CHECKS) || defined(SWIFT_CELL_GRAPH)
261
262
    c->cellID = 0;
#endif
263
264
    if (s->with_self_gravity)
      bzero(c->grav.multipole, sizeof(struct gravity_tensors));
265

266
267
    cell_free_hydro_sorts(c);
    cell_free_stars_sorts(c);
268
#if WITH_MPI
269
270
    c->mpi.tag = -1;

271
    c->mpi.recv = NULL;
272
    c->mpi.stars.recv = NULL;
273
    c->mpi.stars.recv_ti = NULL;
274
    c->mpi.limiter.recv = NULL;
275

276
    c->mpi.send = NULL;
277
278
279
280
#endif
  }
}

281
282
/**
 * @brief Free up any allocated cells.
283
284
 *
 * @param s The #space.
285
286
 */
void space_free_cells(struct space *s) {
287
288
289

  ticks tic = getticks();

Matthieu Schaller's avatar
Matthieu Schaller committed
290
291
  threadpool_map(&s->e->threadpool, space_rebuild_recycle_mapper, s->cells_top,
                 s->nr_cells, sizeof(struct cell), 0, s);
292
  s->maxdepth = 0;
293
294
295
296

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

299
300
301
302
303
304
305
306
307
/**
 * @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
308
    swift_free("parts_foreign", s->parts_foreign);
309
310
311
312
    s->size_parts_foreign = 0;
    s->parts_foreign = NULL;
  }
  if (s->gparts_foreign != NULL) {
Peter W. Draper's avatar
Peter W. Draper committed
313
    swift_free("gparts_foreign", s->gparts_foreign);
314
315
316
317
    s->size_gparts_foreign = 0;
    s->gparts_foreign = NULL;
  }
  if (s->sparts_foreign != NULL) {
Peter W. Draper's avatar
Peter W. Draper committed
318
    swift_free("sparts_foreign", s->sparts_foreign);
319
320
321
322
323
324
    s->size_sparts_foreign = 0;
    s->sparts_foreign = NULL;
  }
#endif
}

325
/**
326
 * @brief Re-build the top-level cell grid.
327
 *
328
 * @param s The #space.
329
 * @param verbose Print messages to stdout or not.
330
 */
331
void space_regrid(struct space *s, int verbose) {
332

333
  const size_t nr_parts = s->nr_parts;
Loic Hausammann's avatar
Loic Hausammann committed
334
  const size_t nr_sparts = s->nr_sparts;
335
  const ticks tic = getticks();
336
  const integertime_t ti_current = (s->e != NULL) ? s->e->ti_current : 0;
337

338
  /* Run through the cells and get the current h_max. */
339
  // tic = getticks();
340
  float h_max = s->cell_min / kernel_gamma / space_stretch;
341
  if (nr_parts > 0) {
342
343
344
345
346
347

    /* 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]];
348
        if (c->hydro.h_max > h_max) {
349
          h_max = c->hydro.h_max;
350
        }
Loic Hausammann's avatar
Loic Hausammann committed
351
        if (c->stars.h_max > h_max) {
352
          h_max = c->stars.h_max;
Loic Hausammann's avatar
Loic Hausammann committed
353
        }
354
      }
355
356

      /* Can we instead use all the top-level cells? */
357
    } else if (s->cells_top != NULL) {
Tom Theuns's avatar
Tom Theuns committed
358
      for (int k = 0; k < s->nr_cells; k++) {
359
        const struct cell *c = &s->cells_top[k];
360
        if (c->nodeID == engine_rank && c->hydro.h_max > h_max) {
361
          h_max = c->hydro.h_max;
362
        }
Loic Hausammann's avatar
Loic Hausammann committed
363
        if (c->nodeID == engine_rank && c->stars.h_max > h_max) {
364
          h_max = c->stars.h_max;
Loic Hausammann's avatar
Loic Hausammann committed
365
        }
366
      }
367
368

      /* Last option: run through the particles */
369
    } else {
370
      for (size_t k = 0; k < nr_parts; k++) {
Matthieu Schaller's avatar
Matthieu Schaller committed
371
        if (s->parts[k].h > h_max) h_max = s->parts[k].h;
372
      }
Loic Hausammann's avatar
Loic Hausammann committed
373
374
375
      for (size_t k = 0; k < nr_sparts; k++) {
        if (s->sparts[k].h > h_max) h_max = s->sparts[k].h;
      }
376
377
378
379
380
381
382
383
384
385
    }
  }

/* 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)
386
      error("Failed to aggregate the rebuild flag across nodes.");
387
388
389
    h_max = buff;
  }
#endif
390
  if (verbose) message("h_max is %.3e (cell_min=%.3e).", h_max, s->cell_min);
391
392

  /* Get the new putative cell dimensions. */
393
  const int cdim[3] = {
394
395
396
397
398
399
      (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))};
400
401
402
403
404

  /* 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 "
405
406
407
        "is switched on.\nThis error is often caused by any of the "
        "followings:\n"
        " - too few particles to generate a sensible grid,\n"
408
409
        " - the initial value of 'Scheduler:max_top_level_cells' is too "
        "small,\n"
410
        " - the (minimal) time-step is too large leading to particles with "
411
        "predicted smoothing lengths too large for the box size,\n"
412
        " - particles with velocities so large that they move by more than two "
413
        "box sizes per time-step.\n");
414

415
416
417
/* 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. */
418
#ifdef WITH_MPI
Matthieu Schaller's avatar
Matthieu Schaller committed
419
  double oldwidth[3];
420
421
422
423
424
425
426
427
  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];
428
429
430
    oldwidth[0] = s->width[0];
    oldwidth[1] = s->width[1];
    oldwidth[2] = s->width[2];
431

432
433
    if ((oldnodeIDs =
             (int *)swift_malloc("nodeIDs", sizeof(int) * s->nr_cells)) == NULL)
434
435
436
437
438
439
440
      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);
441
          oldnodeIDs[cid] = s->cells_top[cid].nodeID;
442
443
444
445
446
        }
      }
    }
  }

Peter W. Draper's avatar
Peter W. Draper committed
447
  /* Are we about to allocate new top level cells without a regrid?
Peter W. Draper's avatar
Peter W. Draper committed
448
   * Can happen when restarting the application. */
449
  const int no_regrid = (s->cells_top == NULL && oldnodeIDs == NULL);
450
451
452
453
#endif

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

457
458
/* Be verbose about this. */
#ifdef SWIFT_DEBUG_CHECKS
459
    message("(re)griding space cdim=(%d %d %d)", cdim[0], cdim[1], cdim[2]);
460
461
462
    fflush(stdout);
#endif

463
    /* Free the old cells, if they were allocated. */
464
    if (s->cells_top != NULL) {
465
      space_free_cells(s);
466
467
468
      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);
469
470
      swift_free("local_cells_with_particles_top",
                 s->local_cells_with_particles_top);
471
472
      swift_free("cells_top", s->cells_top);
      swift_free("multipoles_top", s->multipoles_top);
473
474
    }

475
476
477
478
    /* 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);

479
    /* Set the new cell dimensions only if smaller. */
480
    for (int k = 0; k < 3; k++) {
481
      s->cdim[k] = cdim[k];
482
483
      s->width[k] = s->dim[k] / cdim[k];
      s->iwidth[k] = 1.0 / s->width[k];
484
    }
485
    const float dmin = min3(s->width[0], s->width[1], s->width[2]);
486
487
488

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

490
    if (swift_memalign("cells_top", (void **)&s->cells_top, cell_align,
491
                       s->nr_cells * sizeof(struct cell)) != 0)
492
      error("Failed to allocate top-level cells.");
493
    bzero(s->cells_top, s->nr_cells * sizeof(struct cell));
494

495
    /* Allocate the multipoles for the top-level cells. */
496
    if (s->with_self_gravity) {
497
498
      if (swift_memalign("multipoles_top", (void **)&s->multipoles_top,
                         multipole_align,
499
                         s->nr_cells * sizeof(struct gravity_tensors)) != 0)
500
        error("Failed to allocate top-level multipoles.");
501
      bzero(s->multipoles_top, s->nr_cells * sizeof(struct gravity_tensors));
502
503
    }

504
    /* Allocate the indices of local cells */
505
506
    if (swift_memalign("local_cells_top", (void **)&s->local_cells_top,
                       SWIFT_STRUCT_ALIGNMENT, s->nr_cells * sizeof(int)) != 0)
507
508
509
      error("Failed to allocate indices of local top-level cells.");
    bzero(s->local_cells_top, s->nr_cells * sizeof(int));

510
    /* Allocate the indices of local cells with tasks */
511
512
    if (swift_memalign("local_cells_with_tasks_top",
                       (void **)&s->local_cells_with_tasks_top,
513
                       SWIFT_STRUCT_ALIGNMENT, s->nr_cells * sizeof(int)) != 0)
514
      error("Failed to allocate indices of local top-level cells with tasks.");
515
516
    bzero(s->local_cells_with_tasks_top, s->nr_cells * sizeof(int));

517
    /* Allocate the indices of cells with particles */
518
519
    if (swift_memalign("cells_with_particles_top",
                       (void **)&s->cells_with_particles_top,
520
                       SWIFT_STRUCT_ALIGNMENT, s->nr_cells * sizeof(int)) != 0)
521
522
      error("Failed to allocate indices of top-level cells with particles.");
    bzero(s->cells_with_particles_top, s->nr_cells * sizeof(int));
523

524
    /* Allocate the indices of local cells with particles */
525
526
    if (swift_memalign("local_cells_with_particles_top",
                       (void **)&s->local_cells_with_particles_top,
527
528
529
530
531
532
                       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));

533
    /* Set the cells' locks */
534
    for (int k = 0; k < s->nr_cells; k++) {
535
      if (lock_init(&s->cells_top[k].hydro.lock) != 0)
536
        error("Failed to init spinlock for hydro.");
537
      if (lock_init(&s->cells_top[k].grav.plock) != 0)
538
        error("Failed to init spinlock for gravity.");
539
      if (lock_init(&s->cells_top[k].grav.mlock) != 0)
540
        error("Failed to init spinlock for multipoles.");
541
      if (lock_init(&s->cells_top[k].stars.lock) != 0)
542
        error("Failed to init spinlock for stars.");
543
544
      if (lock_init(&s->cells_top[k].stars.star_formation_lock) != 0)
        error("Failed to init spinlock for star formation.");
545
    }
546
547

    /* Set the cell location and sizes. */
548
549
550
    for (int i = 0; i < cdim[0]; i++)
      for (int j = 0; j < cdim[1]; j++)
        for (int k = 0; k < cdim[2]; k++) {
551
552
          const size_t cid = cell_getid(cdim, i, j, k);
          struct cell *restrict c = &s->cells_top[cid];
553
554
555
556
557
558
          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];
559
560
          c->dmin = dmin;
          c->depth = 0;
561
          c->split = 0;
562
          c->hydro.count = 0;
563
564
          c->grav.count = 0;
          c->stars.count = 0;
565
          c->top = c;
566
          c->super = c;
567
568
          c->hydro.super = c;
          c->grav.super = c;
569
570
          c->hydro.ti_old_part = ti_current;
          c->grav.ti_old_part = ti_current;
571
          c->stars.ti_old_part = ti_current;
572
          c->grav.ti_old_multipole = ti_current;
Pedro Gonnet's avatar
Pedro Gonnet committed
573
#ifdef WITH_MPI
574
          c->mpi.tag = -1;
575
          c->mpi.recv = NULL;
576
          c->mpi.send = NULL;
Pedro Gonnet's avatar
Pedro Gonnet committed
577
#endif  // WITH_MPI
578
          if (s->with_self_gravity) c->grav.multipole = &s->multipoles_top[cid];
Loic Hausammann's avatar
Loic Hausammann committed
579
#if defined(SWIFT_DEBUG_CHECKS) || defined(SWIFT_CELL_GRAPH)
Matthieu Schaller's avatar
Matthieu Schaller committed
580
581
          c->cellID = -last_cell_id;
          last_cell_id++;
582
#endif
Pedro Gonnet's avatar
Pedro Gonnet committed
583
        }
584
585

    /* Be verbose about the change. */
586
587
588
    if (verbose)
      message("set cell dimensions to [ %i %i %i ].", cdim[0], cdim[1],
              cdim[2]);
589

590
#ifdef WITH_MPI
591
592
593
594
595
    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)
596
597
598
        message(
            "basic cell dimensions have increased - recalculating the "
            "global partition.");
599

Matthieu Schaller's avatar
Matthieu Schaller committed
600
      if (!partition_space_to_space(oldwidth, oldcdim, oldnodeIDs, s)) {
601
602
603
604

        /* Failed, try another technique that requires no settings. */
        message("Failed to get a new partition, trying less optimal method");
        struct partition initial_partition;
605
#if defined(HAVE_PARMETIS) || defined(HAVE_METIS)
606
607
608
609
610
611
612
613
614
615
616
617
618
        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);
619

620
      /* Finished with these. */
621
      swift_free("nodeIDs", oldnodeIDs);
Peter W. Draper's avatar
Peter W. Draper committed
622
623

    } else if (no_regrid && s->e != NULL) {
Peter W. Draper's avatar
Peter W. Draper committed
624
625
626
627
628
629
630
631
632
633
634
635
636
      /* 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);
637
    }
Pedro Gonnet's avatar
Pedro Gonnet committed
638
#endif /* WITH_MPI */
639
640
641
642

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

643
  }      /* re-build upper-level cells? */
644
  else { /* Otherwise, just clean up the cells. */
645
646

    /* Free the old cells, if they were allocated. */
647
    space_free_cells(s);
648
  }
649
650
651
652

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

655
656
657
658
659
660
/**
 * @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.
 *
661
662
 * 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.
663
664
665
666
 *
 * @param s The current #space.
 * @param verbose Are we talkative?
 */
667
668
669
670
void space_allocate_extras(struct space *s, int verbose) {

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

671
672
673
674
675
  /* 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;

676
677
678
679
680
681
  /* 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]};

682
  /* The current number of particles (including spare ones) */
683
684
685
686
  size_t nr_parts = s->nr_parts;
  size_t nr_gparts = s->nr_gparts;
  size_t nr_sparts = s->nr_sparts;

687
688
689
690
691
  /* 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;

692
693
694
695
696
  /* 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;

697
698
699
700
701
702
703
704
705
706
707
708
  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;
    }
  }
709

710
  /* Number of extra particles we want for each type */
711
712
713
  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;
714

715
716
717
  if (verbose) {
    message("Currently have %zd/%zd/%zd real particles.", nr_actual_parts,
            nr_actual_gparts, nr_actual_sparts);
718
    message("Currently have %zd/%zd/%zd spaces for extra particles.",
719
            s->nr_extra_parts, s->nr_extra_gparts, s->nr_extra_sparts);
720
    message("Requesting space for future %zd/%zd/%zd part/gpart/sparts.",
721
722
723
            expected_num_extra_parts, expected_num_extra_gparts,
            expected_num_extra_sparts);
  }
724

725
726
727
728
729
730
731
  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.");

732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
  /* 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;
750
      if (swift_memalign("gparts", (void **)&gparts_new, gpart_align,
751
752
753
754
                         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);
755
      swift_free("gparts", s->gparts);
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
      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;
    }

781
782
783
784
    /* 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;
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
    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) {
806
807
808
809
810
        ++local_cell_id;

        if (local_cell_id == nr_local_cells) break;

        current_cell = local_cells[local_cell_id];
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
        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;
  }

826
827
  /* Do we have enough space for the extra parts (i.e. we haven't used up any) ?
   */
828
829
  if (expected_num_extra_parts > s->nr_extra_parts) {

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

832
833
834
835
836
837
838
839
840
841
842
843
    /* 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;
844
      if (swift_memalign("parts", (void **)&parts_new, part_align,
845
846
847
                         sizeof(struct part) * size_parts) != 0)
        error("Failed to allocate new part data");
      memcpy(parts_new, s->parts, sizeof(struct part) * s->size_parts);
848
      swift_free("parts", s->parts);
849
850
851
852
      s->parts = parts_new;

      /* Same for xparts */
      struct xpart *xparts_new = NULL;
853
      if (swift_memalign("xparts", (void **)&xparts_new, xpart_align,
854
855
856
                         sizeof(struct xpart) * size_parts) != 0)
        error("Failed to allocate new xpart data");
      memcpy(xparts_new, s->xparts, sizeof(struct xpart) * s->size_parts);
857
      swift_free("xparts", s->xparts);
858
859
860
861
862
863
      s->xparts = xparts_new;

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

864
    /* Turn some of the allocated spares into particles we can use */
865
866
867
868
869
    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;
870
      s->parts[i].id = -1;
871
872
    }

873
874
875
876
    /* 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;
877
878
    size_t count_extra_parts = 0;
    for (size_t i = 0; i < nr_actual_parts + expected_num_extra_parts; ++i) {
879
880
881
882
883
884

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

885
886
887
888
889
890
891
892
893
894
895
896
897
      if (s->parts[i].time_bin == time_bin_not_created) {

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

      /* Once we have reached the number of extra part per cell, we move to the
       * next */
      if (count_in_cell == space_extra_parts) {
898
899
900
901
902
        ++local_cell_id;

        if (local_cell_id == nr_local_cells) break;

        current_cell = local_cells[local_cell_id];
903
904
905
906
907
908
909
910
911
912
        count_in_cell = 0;
      }
    }

#ifdef SWIFT_DEBUG_CHECKS
    if (count_extra_parts != expected_num_extra_parts)
      error("Constructed the wrong number of extra parts (%zd vs. %zd)",
            count_extra_parts, expected_num_extra_parts);
#endif

913
914
915
    /* Update the counters */
    s->nr_parts = nr_actual_parts + expected_num_extra_parts;
    s->nr_extra_parts = expected_num_extra_parts;
916
  }
917

918
919
  /* Do we have enough space for the extra sparts (i.e. we haven't used up any)
   * ? */
920
  if (nr_actual_sparts + expected_num_extra_sparts > nr_sparts) {
921

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

924
925
926
927
928
929
930
931
932
933
934
935
    /* Do we need to reallocate? */
    if (nr_actual_sparts + expected_num_extra_sparts > size_sparts) {

      size_sparts = (nr_actual_sparts + expected_num_extra_sparts) *
                    engine_redistribute_alloc_margin;

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

      /* Create more space for parts */
      struct spart *sparts_new = NULL;
936
      if (swift_memalign("sparts", (void **)&sparts_new, spart_align,
937
938
939
                         sizeof(struct spart) * size_sparts) != 0)
        error("Failed to allocate new spart data");
      memcpy(sparts_new, s->sparts, sizeof(struct spart) * s->size_sparts);
940
      swift_free("sparts", s->sparts);
941
942
943
944
945
946
947
948
949
950
951
      s->sparts = sparts_new;

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

    /* Turn some of the allocated spares into particles we can use */
    for (size_t i = nr_sparts; i < nr_actual_sparts + expected_num_extra_sparts;
         ++i) {
      bzero(&s->sparts[i], sizeof(struct spart));
      s->sparts[i].time_bin = time_bin_not_created;
952
      s->sparts[i].id = -42;
953
954
    }

955
956
957
958
    /* 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;
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
    size_t count_extra_sparts = 0;
    for (size_t i = 0; i < nr_actual_sparts + expected_num_extra_sparts; ++i) {

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

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

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

      /* Once we have reached the number of extra spart per cell, we move to the
       * next */
      if (count_in_cell == space_extra_sparts) {
980
981
982
983
984
        ++local_cell_id;

        if (local_cell_id == nr_local_cells) break;

        current_cell = local_cells[local_cell_id];
985
986
987
988
989
990
991
992
993
994
995
996
997
        count_in_cell = 0;
      }
    }

#ifdef SWIFT_DEBUG_CHECKS
    if (count_extra_sparts != expected_num_extra_sparts)
      error("Constructed the wrong number of extra sparts (%zd vs. %zd)",
            count_extra_sparts, expected_num_extra_sparts);
#endif

    /* Update the counters */
    s->nr_sparts = nr_actual_sparts + expected_num_extra_sparts;
    s->nr_extra_sparts = expected_num_extra_sparts;
998
  }
999
1000

#ifdef SWIFT_DEBUG_CHECKS