space.c 48.9 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 "const.h"
45
#include "engine.h"
46
#include "error.h"
47
48
#include "gravity.h"
#include "hydro.h"
49
#include "kernel_hydro.h"
50
#include "lock.h"
51
#include "minmax.h"
52
#include "runner.h"
53
#include "tools.h"
Pedro Gonnet's avatar
Pedro Gonnet committed
54

55
56
57
/* Shared sort structure. */
struct parallel_sort space_sort_struct;

Pedro Gonnet's avatar
Pedro Gonnet committed
58
59
/* Split size. */
int space_splitsize = space_splitsize_default;
60
int space_subsize = space_subsize_default;
61
int space_maxsize = space_maxsize_default;
Pedro Gonnet's avatar
Pedro Gonnet committed
62
63
64

/* Map shift vector to sortlist. */
const int sortlistID[27] = {
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    /* ( -1 , -1 , -1 ) */ 0,
    /* ( -1 , -1 ,  0 ) */ 1,
    /* ( -1 , -1 ,  1 ) */ 2,
    /* ( -1 ,  0 , -1 ) */ 3,
    /* ( -1 ,  0 ,  0 ) */ 4,
    /* ( -1 ,  0 ,  1 ) */ 5,
    /* ( -1 ,  1 , -1 ) */ 6,
    /* ( -1 ,  1 ,  0 ) */ 7,
    /* ( -1 ,  1 ,  1 ) */ 8,
    /* (  0 , -1 , -1 ) */ 9,
    /* (  0 , -1 ,  0 ) */ 10,
    /* (  0 , -1 ,  1 ) */ 11,
    /* (  0 ,  0 , -1 ) */ 12,
    /* (  0 ,  0 ,  0 ) */ 0,
    /* (  0 ,  0 ,  1 ) */ 12,
    /* (  0 ,  1 , -1 ) */ 11,
    /* (  0 ,  1 ,  0 ) */ 10,
    /* (  0 ,  1 ,  1 ) */ 9,
    /* (  1 , -1 , -1 ) */ 8,
    /* (  1 , -1 ,  0 ) */ 7,
    /* (  1 , -1 ,  1 ) */ 6,
    /* (  1 ,  0 , -1 ) */ 5,
    /* (  1 ,  0 ,  0 ) */ 4,
    /* (  1 ,  0 ,  1 ) */ 3,
    /* (  1 ,  1 , -1 ) */ 2,
    /* (  1 ,  1 ,  0 ) */ 1,
    /* (  1 ,  1 ,  1 ) */ 0};

93
94
95
96
97
98
99
100
101
102
103
104
/**
 * @brief Get the shift-id of the given pair of cells, swapping them
 *      if need be.
 *
 * @param s The space
 * @param ci Pointer to first #cell.
 * @param cj Pointer second #cell.
 * @param shift Vector from ci to cj.
 *
 * @return The shift ID and set shift, may or may not swap ci and cj.
 */

105
106
107
108
int space_getsid(struct space *s, struct cell **ci, struct cell **cj,
                 double *shift) {

  /* Get the relative distance between the pairs, wrapping. */
109
110
111
  const int periodic = s->periodic;
  double dx[3];
  for (int k = 0; k < 3; k++) {
112
113
114
115
116
117
118
119
120
121
122
    dx[k] = (*cj)->loc[k] - (*ci)->loc[k];
    if (periodic && dx[k] < -s->dim[k] / 2)
      shift[k] = s->dim[k];
    else if (periodic && dx[k] > s->dim[k] / 2)
      shift[k] = -s->dim[k];
    else
      shift[k] = 0.0;
    dx[k] += shift[k];
  }

  /* Get the sorting index. */
123
  int sid = 0;
124
  for (int k = 0; k < 3; k++)
125
126
127
128
    sid = 3 * sid + ((dx[k] < 0.0) ? 0 : ((dx[k] > 0.0) ? 2 : 1));

  /* Switch the cells around? */
  if (runner_flip[sid]) {
129
    struct cell *temp = *ci;
130
131
    *ci = *cj;
    *cj = temp;
132
    for (int k = 0; k < 3; k++) shift[k] = -shift[k];
133
134
135
136
137
138
  }
  sid = sortlistID[sid];

  /* Return the sort ID. */
  return sid;
}
139

140
/**
141
 * @brief Recursively dismantle a cell tree.
142
143
 *
 */
144
145
146
147

void space_rebuild_recycle(struct space *s, struct cell *c) {

  if (c->split)
148
    for (int k = 0; k < 8; k++)
149
150
151
152
153
154
155
      if (c->progeny[k] != NULL) {
        space_rebuild_recycle(s, c->progeny[k]);
        space_recycle(s, c->progeny[k]);
        c->progeny[k] = NULL;
      }
}

156
/**
157
 * @brief Re-build the cell grid.
158
 *
159
160
 * @param s The #space.
 * @param cell_max Maximum cell edge length.
161
 * @param verbose Print messages to stdout or not.
162
 */
163

164
void space_regrid(struct space *s, double cell_max, int verbose) {
165

166
  const size_t nr_parts = s->nr_parts;
167
  struct cell *restrict c;
168
  ticks tic = getticks();
169
170
171

  /* Run through the parts and get the current h_max. */
  // tic = getticks();
172
  float h_max = s->cell_min / kernel_gamma / space_stretch;
173
  if (nr_parts > 0) {
174
    if (s->cells != NULL) {
Tom Theuns's avatar
Tom Theuns committed
175
      for (int k = 0; k < s->nr_cells; k++) {
Matthieu Schaller's avatar
Matthieu Schaller committed
176
        if (s->cells[k].h_max > h_max) h_max = s->cells[k].h_max;
177
178
      }
    } else {
179
      for (size_t k = 0; k < nr_parts; k++) {
Matthieu Schaller's avatar
Matthieu Schaller committed
180
        if (s->parts[k].h > h_max) h_max = s->parts[k].h;
181
182
      }
      s->h_max = h_max;
183
184
185
186
187
188
189
190
191
192
    }
  }

/* 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)
193
      error("Failed to aggregate the rebuild flag across nodes.");
194
195
196
    h_max = buff;
  }
#endif
197
  if (verbose) message("h_max is %.3e (cell_max=%.3e).", h_max, cell_max);
198
199

  /* Get the new putative cell dimensions. */
200
  int cdim[3];
201
  for (int k = 0; k < 3; k++)
202
203
204
205
206
207
208
209
210
    cdim[k] =
        floor(s->dim[k] / fmax(h_max * kernel_gamma * space_stretch, cell_max));

  /* 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 "
        "is switched on.");

211
212
213
214
215
216
  /* Check if we have enough cells for gravity. */
  if (s->gravity && (cdim[0] < 8 || cdim[1] < 8 || cdim[2] < 8))
    error(
        "Must have at least 8 cells in each spatial dimension when gravity "
        "is switched on.");

217
218
219
/* 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. */
220
#ifdef WITH_MPI
Matthieu Schaller's avatar
Matthieu Schaller committed
221
  double oldwidth[3];
222
223
224
225
226
227
228
229
  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];
230
231
232
    oldwidth[0] = s->width[0];
    oldwidth[1] = s->width[1];
    oldwidth[2] = s->width[2];
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

    if ((oldnodeIDs = (int *)malloc(sizeof(int) * s->nr_cells)) == NULL)
      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);
          oldnodeIDs[cid] = s->cells[cid].nodeID;
        }
      }
    }
  }

248
249
250
251
252
253
254
255
256
#endif

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

    /* Free the old cells, if they were allocated. */
    if (s->cells != NULL) {
257
      for (int k = 0; k < s->nr_cells; k++) {
258
259
260
261
262
263
264
265
        space_rebuild_recycle(s, &s->cells[k]);
        if (s->cells[k].sort != NULL) free(s->cells[k].sort);
      }
      free(s->cells);
      s->maxdepth = 0;
    }

    /* Set the new cell dimensions only if smaller. */
266
    for (int k = 0; k < 3; k++) {
267
      s->cdim[k] = cdim[k];
268
269
      s->width[k] = s->dim[k] / cdim[k];
      s->iwidth[k] = 1.0 / s->width[k];
270
    }
271
    const float dmin = fminf(s->width[0], fminf(s->width[1], s->width[2]));
272
273
274
275
276
277
278

    /* Allocate the highest level of cells. */
    s->tot_cells = s->nr_cells = cdim[0] * cdim[1] * cdim[2];
    if (posix_memalign((void *)&s->cells, 64,
                       s->nr_cells * sizeof(struct cell)) != 0)
      error("Failed to allocate cells.");
    bzero(s->cells, s->nr_cells * sizeof(struct cell));
279
    for (int k = 0; k < s->nr_cells; k++)
280
281
282
      if (lock_init(&s->cells[k].lock) != 0) error("Failed to init spinlock.");

    /* Set the cell location and sizes. */
283
284
285
    for (int i = 0; i < cdim[0]; i++)
      for (int j = 0; j < cdim[1]; j++)
        for (int k = 0; k < cdim[2]; k++) {
286
          c = &s->cells[cell_getid(cdim, i, j, k)];
287
288
289
290
291
292
          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];
293
294
295
296
297
298
          c->dmin = dmin;
          c->depth = 0;
          c->count = 0;
          c->gcount = 0;
          c->super = c;
          lock_init(&c->lock);
Pedro Gonnet's avatar
Pedro Gonnet committed
299
        }
300
301

    /* Be verbose about the change. */
302
303
304
    if (verbose)
      message("set cell dimensions to [ %i %i %i ].", cdim[0], cdim[1],
              cdim[2]);
305
306
    fflush(stdout);

307
#ifdef WITH_MPI
308
309
310
311
312
    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)
313
314
315
        message(
            "basic cell dimensions have increased - recalculating the "
            "global partition.");
316

Matthieu Schaller's avatar
Matthieu Schaller committed
317
      if (!partition_space_to_space(oldwidth, oldcdim, oldnodeIDs, s)) {
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335

        /* Failed, try another technique that requires no settings. */
        message("Failed to get a new partition, trying less optimal method");
        struct partition initial_partition;
#ifdef HAVE_METIS
        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);
336

337
338
      /* Finished with these. */
      free(oldnodeIDs);
339
340
    }
#endif
341
  } /* re-build upper-level cells? */
342
343
  // message( "rebuilding upper-level cells took %.3f %s." ,
  // clocks_from_ticks(double)(getticks() - tic), clocks_getunit());
344
345
346
347
348

  /* Otherwise, just clean up the cells. */
  else {

    /* Free the old cells, if they were allocated. */
349
    for (int k = 0; k < s->nr_cells; k++) {
350
351
352
353
354
355
356
357
358
359
360
      space_rebuild_recycle(s, &s->cells[k]);
      s->cells[k].sorts = NULL;
      s->cells[k].nr_tasks = 0;
      s->cells[k].nr_density = 0;
      s->cells[k].nr_force = 0;
      s->cells[k].density = NULL;
      s->cells[k].force = NULL;
      s->cells[k].dx_max = 0.0f;
      s->cells[k].sorted = 0;
      s->cells[k].count = 0;
      s->cells[k].gcount = 0;
Matthieu Schaller's avatar
Matthieu Schaller committed
361
      s->cells[k].init = NULL;
Matthieu Schaller's avatar
Matthieu Schaller committed
362
      s->cells[k].ghost = NULL;
Matthieu Schaller's avatar
Matthieu Schaller committed
363
364
      s->cells[k].drift = NULL;
      s->cells[k].kick = NULL;
365
      s->cells[k].super = &s->cells[k];
366
    }
367
368
    s->maxdepth = 0;
  }
369
370
371
372

  if (verbose)
    message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
            clocks_getunit());
373
}
374
375
376
377
378
379

/**
 * @brief Re-build the cells as well as the tasks.
 *
 * @param s The #space in which to update the cells.
 * @param cell_max Maximal cell size.
380
 * @param verbose Print messages to stdout or not
381
382
 *
 */
383

384
void space_rebuild(struct space *s, double cell_max, int verbose) {
385

Matthieu Schaller's avatar
Matthieu Schaller committed
386
  const ticks tic = getticks();
387
388

  /* Be verbose about this. */
389
  // message("re)building space..."); fflush(stdout);
390
391

  /* Re-grid if necessary, or just re-set the cell data. */
392
  space_regrid(s, cell_max, verbose);
393

Pedro Gonnet's avatar
Pedro Gonnet committed
394
395
  size_t nr_parts = s->nr_parts;
  size_t nr_gparts = s->nr_gparts;
396
397
  struct cell *restrict cells = s->cells;

398
  const double ih[3] = {s->iwidth[0], s->iwidth[1], s->iwidth[2]};
Matthieu Schaller's avatar
Matthieu Schaller committed
399
400
  const double dim[3] = {s->dim[0], s->dim[1], s->dim[2]};
  const int cdim[3] = {s->cdim[0], s->cdim[1], s->cdim[2]};
401
402
403
404

  /* Run through the particles and get their cell index. */
  // tic = getticks();
  const size_t ind_size = s->size_parts;
405
406
  int *ind;
  if ((ind = (int *)malloc(sizeof(int) * ind_size)) == NULL)
407
    error("Failed to allocate temporary particle indices.");
Pedro Gonnet's avatar
Pedro Gonnet committed
408
  for (size_t k = 0; k < nr_parts; k++) {
409
410
    struct part *restrict p = &s->parts[k];
    for (int j = 0; j < 3; j++)
411
412
413
414
      if (p->x[j] < 0.0)
        p->x[j] += dim[j];
      else if (p->x[j] >= dim[j])
        p->x[j] -= dim[j];
415
    ind[k] =
416
        cell_getid(cdim, p->x[0] * ih[0], p->x[1] * ih[1], p->x[2] * ih[2]);
417
    cells[ind[k]].count++;
418
  }
Pedro Gonnet's avatar
Pedro Gonnet committed
419
420
  // message( "getting particle indices took %.3f %s." ,
  // clocks_from_ticks(getticks() - tic), clocks_getunit()):
421

422
423
424
425
426
427
428
  /* Run through the gravity particles and get their cell index. */
  // tic = getticks();
  const size_t gind_size = s->size_gparts;
  int *gind;
  if ((gind = (int *)malloc(sizeof(int) * gind_size)) == NULL)
    error("Failed to allocate temporary g-particle indices.");
  for (int k = 0; k < nr_gparts; k++) {
Matthieu Schaller's avatar
Matthieu Schaller committed
429
    struct gpart *restrict gp = &s->gparts[k];
430
431
432
433
434
435
436
437
438
    for (int j = 0; j < 3; j++)
      if (gp->x[j] < 0.0)
        gp->x[j] += dim[j];
      else if (gp->x[j] >= dim[j])
        gp->x[j] -= dim[j];
    gind[k] =
        cell_getid(cdim, gp->x[0] * ih[0], gp->x[1] * ih[1], gp->x[2] * ih[2]);
    cells[gind[k]].gcount++;
  }
Matthieu Schaller's avatar
Matthieu Schaller committed
439
// message( "getting particle indices took %.3f %s." ,
440
// clocks_from_ticks(getticks() - tic), clocks_getunit());
441
442

#ifdef WITH_MPI
443

444
  /* Move non-local parts to the end of the list. */
445
  const int local_nodeID = s->e->nodeID;
446
  for (size_t k = 0; k < nr_parts;) {
447
    if (cells[ind[k]].nodeID != local_nodeID) {
448
449
      cells[ind[k]].count -= 1;
      nr_parts -= 1;
Matthieu Schaller's avatar
Bug fix    
Matthieu Schaller committed
450
      const struct part tp = s->parts[k];
451
452
      s->parts[k] = s->parts[nr_parts];
      s->parts[nr_parts] = tp;
453
      if (s->parts[k].gpart != NULL) {
454
        s->parts[k].gpart->id_or_neg_offset = -k;
455
456
      }
      if (s->parts[nr_parts].gpart != NULL) {
457
        s->parts[nr_parts].gpart->id_or_neg_offset = -nr_parts;
458
      }
Matthieu Schaller's avatar
Bug fix    
Matthieu Schaller committed
459
      const struct xpart txp = s->xparts[k];
460
461
      s->xparts[k] = s->xparts[nr_parts];
      s->xparts[nr_parts] = txp;
Matthieu Schaller's avatar
Bug fix    
Matthieu Schaller committed
462
      const int t = ind[k];
463
464
      ind[k] = ind[nr_parts];
      ind[nr_parts] = t;
Matthieu Schaller's avatar
Matthieu Schaller committed
465
    } else {
466
467
468
469
      /* Increment when not exchanging otherwise we need to retest "k".*/
      k++;
    }
  }
470

471
#ifdef SWIFT_DEBUG_CHECKS
Peter W. Draper's avatar
Peter W. Draper committed
472
  /* Check that all parts are in the correct places. */
473
  for (size_t k = 0; k < nr_parts; k++) {
474
475
476
477
478
479
480
    if (cells[ind[k]].nodeID != local_nodeID) {
      error("Failed to move all non-local parts to send list");
    }
  }
  for (size_t k = nr_parts; k < s->nr_parts; k++) {
    if (cells[ind[k]].nodeID == local_nodeID) {
      error("Failed to remove local parts from send list");
481
    }
482
483
  }
#endif
484

485
  /* Move non-local gparts to the end of the list. */
486
  for (int k = 0; k < nr_gparts;) {
Matthieu Schaller's avatar
Bug fix    
Matthieu Schaller committed
487
488
    if (cells[gind[k]].nodeID != local_nodeID) {
      cells[gind[k]].gcount -= 1;
489
      nr_gparts -= 1;
Matthieu Schaller's avatar
Bug fix    
Matthieu Schaller committed
490
      const struct gpart tp = s->gparts[k];
491
492
      s->gparts[k] = s->gparts[nr_gparts];
      s->gparts[nr_gparts] = tp;
493
494
      if (s->gparts[k].id_or_neg_offset <= 0) {
        s->parts[-s->gparts[k].id_or_neg_offset].gpart = &s->gparts[k];
495
      }
496
497
498
      if (s->gparts[nr_gparts].id_or_neg_offset <= 0) {
        s->parts[-s->gparts[nr_gparts].id_or_neg_offset].gpart =
            &s->gparts[nr_gparts];
499
      }
Matthieu Schaller's avatar
Bug fix    
Matthieu Schaller committed
500
501
502
      const int t = gind[k];
      gind[k] = gind[nr_gparts];
      gind[nr_gparts] = t;
Matthieu Schaller's avatar
Matthieu Schaller committed
503
    } else {
504
505
506
507
      /* Increment when not exchanging otherwise we need to retest "k".*/
      k++;
    }
  }
508

509
#ifdef SWIFT_DEBUG_CHECKS
510
511
512
513
514
515
516
517
518
  /* Check that all gparts are in the correct place (untested). */
  for (size_t k = 0; k < nr_gparts; k++) {
    if (cells[gind[k]].nodeID != local_nodeID) {
      error("Failed to move all non-local gparts to send list");
    }
  }
  for (size_t k = nr_gparts; k < s->nr_gparts; k++) {
    if (cells[gind[k]].nodeID == local_nodeID) {
      error("Failed to remove local gparts from send list");
519
    }
520
521
  }
#endif
522

523
524
  /* Exchange the strays, note that this potentially re-allocates
     the parts arrays. */
525
  size_t nr_parts_exchanged = s->nr_parts - nr_parts;
526
  size_t nr_gparts_exchanged = s->nr_gparts - nr_gparts;
Pedro Gonnet's avatar
Pedro Gonnet committed
527
528
529
530
  engine_exchange_strays(s->e, nr_parts, &ind[nr_parts], &nr_parts_exchanged,
                         nr_gparts, &gind[nr_gparts], &nr_gparts_exchanged);

  /* Set the new particle counts. */
531
  s->nr_parts = nr_parts + nr_parts_exchanged;
532
  s->nr_gparts = nr_gparts + nr_gparts_exchanged;
533
534

  /* Re-allocate the index array if needed.. */
535
  if (s->nr_parts > ind_size) {
536
537
    int *ind_new;
    if ((ind_new = (int *)malloc(sizeof(int) * s->nr_parts)) == NULL)
538
      error("Failed to allocate temporary particle indices.");
539
    memcpy(ind_new, ind, sizeof(int) * nr_parts);
540
541
    free(ind);
    ind = ind_new;
542
543
544
  }

  /* Assign each particle to its cell. */
Pedro Gonnet's avatar
Pedro Gonnet committed
545
  for (size_t k = nr_parts; k < s->nr_parts; k++) {
Matthieu Schaller's avatar
Matthieu Schaller committed
546
    const struct part *const p = &s->parts[k];
547
    ind[k] =
548
        cell_getid(cdim, p->x[0] * ih[0], p->x[1] * ih[1], p->x[2] * ih[2]);
549
    cells[ind[k]].count += 1;
550
551
552
553
554
#ifdef SWIFT_DEBUG_CHECKS
    if (cells[ind[k]].nodeID != local_nodeID)
      error("Received part that does not belong to me (nodeID=%i).",
            cells[ind[k]].nodeID);
#endif
555
  }
556
  nr_parts = s->nr_parts;
557
558

#endif /* WITH_MPI */
559
560

  /* Sort the parts according to their cells. */
561
  space_parts_sort(s, ind, nr_parts, 0, s->nr_cells - 1, verbose);
562
563

  /* Re-link the gparts. */
564
  part_relink_gparts(s->parts, nr_parts, 0);
565

566
#ifdef SWIFT_DEBUG_CHECKS
567
  /* Verify space_sort_struct. */
568
569
570
571
572
573
574
575
576
577
  for (size_t k = 1; k < nr_parts; k++) {
    if (ind[k - 1] > ind[k]) {
      error("Sort failed!");
    } else if (ind[k] != cell_getid(cdim, s->parts[k].x[0] * ih[0],
                                    s->parts[k].x[1] * ih[1],
                                    s->parts[k].x[2] * ih[2])) {
      error("Incorrect indices!");
    }
  }
#endif
578
579

  /* We no longer need the indices as of here. */
580
  free(ind);
581

582
583
584
585
#ifdef WITH_MPI

  /* Re-allocate the index array if needed.. */
  if (s->nr_gparts > gind_size) {
586
587
    int *gind_new;
    if ((gind_new = (int *)malloc(sizeof(int) * s->nr_gparts)) == NULL)
588
      error("Failed to allocate temporary g-particle indices.");
589
    memcpy(gind_new, gind, sizeof(int) * nr_gparts);
590
591
592
593
594
    free(gind);
    gind = gind_new;
  }

  /* Assign each particle to its cell. */
595
  for (int k = nr_gparts; k < s->nr_gparts; k++) {
Matthieu Schaller's avatar
Matthieu Schaller committed
596
    const struct gpart *const p = &s->gparts[k];
597
598
    gind[k] =
        cell_getid(cdim, p->x[0] * ih[0], p->x[1] * ih[1], p->x[2] * ih[2]);
Matthieu Schaller's avatar
Typo    
Matthieu Schaller committed
599
    cells[gind[k]].gcount += 1;
600
601
602
603
604
605
606
    /* if ( cells[ ind[k] ].nodeID != nodeID )
        error( "Received part that does not belong to me (nodeID=%i)." , cells[
       ind[k] ].nodeID ); */
  }
  nr_gparts = s->nr_gparts;

#endif
607
608

  /* Sort the parts according to their cells. */
Matthieu Schaller's avatar
Matthieu Schaller committed
609
  space_gparts_sort(s, gind, nr_gparts, 0, s->nr_cells - 1, verbose);
610
611

  /* Re-link the parts. */
612
  part_relink_parts(s->gparts, nr_gparts, s->parts);
613
614

  /* We no longer need the indices as of here. */
615
  free(gind);
616

617
#ifdef SWIFT_DEBUG_CHECKS
618
619
620
  /* Verify that the links are correct */
  for (size_t k = 0; k < nr_gparts; ++k) {

621
    if (s->gparts[k].id_or_neg_offset < 0) {
622

623
      const struct part *part = &s->parts[-s->gparts[k].id_or_neg_offset];
624

625
626
627
628
      if (part->gpart != &s->gparts[k]) error("Linking problem !");

      if (s->gparts[k].x[0] != part->x[0] || s->gparts[k].x[1] != part->x[1] ||
          s->gparts[k].x[2] != part->x[2])
629
630
631
632
633
        error("Linked particles are not at the same position !");
    }
  }
  for (size_t k = 0; k < nr_parts; ++k) {

634
635
636
    if (s->parts[k].gpart != NULL &&
        s->parts[k].gpart->id_or_neg_offset != -k) {
      error("Linking problem !");
637
638
    }
  }
639
#endif
640

641
642
  /* Hook the cells up to the parts. */
  // tic = getticks();
643
644
645
  struct part *finger = s->parts;
  struct xpart *xfinger = s->xparts;
  struct gpart *gfinger = s->gparts;
646
647
  for (int k = 0; k < s->nr_cells; k++) {
    struct cell *restrict c = &cells[k];
648
649
650
651
652
653
654
    c->parts = finger;
    c->xparts = xfinger;
    c->gparts = gfinger;
    finger = &finger[c->count];
    xfinger = &xfinger[c->count];
    gfinger = &gfinger[c->gcount];
  }
655
  // message( "hooking up cells took %.3f %s." ,
Matthieu Schaller's avatar
Matthieu Schaller committed
656
  // clocks_from_ticks(getticks() - tic), clocks_getunit());
657
658
659

  /* At this point, we have the upper-level cells, old or new. Now make
     sure that the parts in each cell are ok. */
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  space_split(s, cells, verbose);

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

/**
 * @brief Split particles between cells of a hierarchy
 *
 * @param s The #space.
 * @param cells The cell hierarchy
 * @param verbose Are we talkative ?
 */
void space_split(struct space *s, struct cell *cells, int verbose) {

Matthieu Schaller's avatar
Matthieu Schaller committed
676
  const ticks tic = getticks();
677
678

  for (int k = 0; k < s->nr_cells; k++)
679
680
    scheduler_addtask(&s->e->sched, task_type_split_cell, task_subtype_none, k,
                      0, &cells[k], NULL, 0);
681
  engine_launch(s->e, s->e->nr_threads, 1 << task_type_split_cell, 0);
682

683
684
685
  if (verbose)
    message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
            clocks_getunit());
686
}
687

688
/**
689
690
 * @brief Sort the particles and condensed particles according to the given
 *indices.
691
 *
Matthieu Schaller's avatar
Matthieu Schaller committed
692
 * @param s The #space.
693
694
695
696
 * @param ind The indices with respect to which the parts are sorted.
 * @param N The number of parts
 * @param min Lowest index.
 * @param max highest index.
697
 * @param verbose Are we talkative ?
698
 */
699

700
void space_parts_sort(struct space *s, int *ind, size_t N, int min, int max,
701
702
                      int verbose) {

Matthieu Schaller's avatar
Matthieu Schaller committed
703
  const ticks tic = getticks();
704
705

  /*Populate the global parallel_sort structure with the input data */
706
707
708
  space_sort_struct.parts = s->parts;
  space_sort_struct.xparts = s->xparts;
  space_sort_struct.ind = ind;
709
  space_sort_struct.stack_size = 2 * (max - min + 1) + 10 + s->e->nr_threads;
710
711
712
713
714
715
  if ((space_sort_struct.stack = malloc(sizeof(struct qstack) *
                                        space_sort_struct.stack_size)) == NULL)
    error("Failed to allocate sorting stack.");
  for (int i = 0; i < space_sort_struct.stack_size; i++)
    space_sort_struct.stack[i].ready = 0;

716
  /* Add the first interval. */
717
718
719
720
721
722
723
724
725
  space_sort_struct.stack[0].i = 0;
  space_sort_struct.stack[0].j = N - 1;
  space_sort_struct.stack[0].min = min;
  space_sort_struct.stack[0].max = max;
  space_sort_struct.stack[0].ready = 1;
  space_sort_struct.first = 0;
  space_sort_struct.last = 1;
  space_sort_struct.waiting = 1;

726
  /* Launch the sorting tasks. */
727
  engine_launch(s->e, s->e->nr_threads, (1 << task_type_part_sort), 0);
728

729
#ifdef SWIFT_DEBUG_CHECKS
730
  /* Verify space_sort_struct. */
731
  for (int i = 1; i < N; i++)
732
    if (ind[i - 1] > ind[i])
733
      error("Sorting failed (ind[%i]=%i,ind[%i]=%i), min=%i, max=%i.", i - 1,
734
735
736
            ind[i - 1], i, ind[i], min, max);
  message("Sorting succeeded.");
#endif
737

738
  /* Clean up. */
739
  free(space_sort_struct.stack);
740
741
742
743

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

746
void space_do_parts_sort() {
747

748
  /* Pointers to the sorting data. */
749
  int *ind = space_sort_struct.ind;
750
751
  struct part *parts = space_sort_struct.parts;
  struct xpart *xparts = space_sort_struct.xparts;
752

753
  /* Main loop. */
754
  while (space_sort_struct.waiting) {
755

756
    /* Grab an interval off the queue. */
757
758
    int qid =
        atomic_inc(&space_sort_struct.first) % space_sort_struct.stack_size;
759

760
    /* Wait for the entry to be ready, or for the sorting do be done. */
761
762
    while (!space_sort_struct.stack[qid].ready)
      if (!space_sort_struct.waiting) return;
763

764
    /* Get the stack entry. */
765
766
    ptrdiff_t i = space_sort_struct.stack[qid].i;
    ptrdiff_t j = space_sort_struct.stack[qid].j;
767
768
    int min = space_sort_struct.stack[qid].min;
    int max = space_sort_struct.stack[qid].max;
769
    space_sort_struct.stack[qid].ready = 0;
770

771
772
    /* Loop over sub-intervals. */
    while (1) {
773

774
      /* Bring beer. */
775
      const int pivot = (min + max) / 2;
776
777
      /* message("Working on interval [%i,%i] with min=%i, max=%i, pivot=%i.",
              i, j, min, max, pivot); */
778
779

      /* One pass of QuickSort's partitioning. */
780
781
      ptrdiff_t ii = i;
      ptrdiff_t jj = j;
782
783
784
785
      while (ii < jj) {
        while (ii <= j && ind[ii] <= pivot) ii++;
        while (jj >= i && ind[jj] > pivot) jj--;
        if (ii < jj) {
786
          size_t temp_i = ind[ii];
787
788
          ind[ii] = ind[jj];
          ind[jj] = temp_i;
789
          struct part temp_p = parts[ii];
790
791
          parts[ii] = parts[jj];
          parts[jj] = temp_p;
792
          struct xpart temp_xp = xparts[ii];
793
794
795
796
          xparts[ii] = xparts[jj];
          xparts[jj] = temp_xp;
        }
      }
797

798
#ifdef SWIFT_DEBUG_CHECKS
799
      /* Verify space_sort_struct. */
800
      for (int k = i; k <= jj; k++)
801
        if (ind[k] > pivot) {
802
803
          message("sorting failed at k=%i, ind[k]=%i, pivot=%i, i=%li, j=%li.",
                  k, ind[k], pivot, i, j);
804
805
806
807
          error("Partition failed (<=pivot).");
        }
      for (int k = jj + 1; k <= j; k++)
        if (ind[k] <= pivot) {
808
809
          message("sorting failed at k=%i, ind[k]=%i, pivot=%i, i=%li, j=%li.",
                  k, ind[k], pivot, i, j);
810
          error("Partition failed (>pivot).");
811
812
        }
#endif
813
814
815
816
817
818

      /* Split-off largest interval. */
      if (jj - i > j - jj + 1) {

        /* Recurse on the left? */
        if (jj > i && pivot > min) {
819
820
          qid = atomic_inc(&space_sort_struct.last) %
                space_sort_struct.stack_size;
821
822
          while (space_sort_struct.stack[qid].ready)
            ;
823
824
825
826
827
828
829
          space_sort_struct.stack[qid].i = i;
          space_sort_struct.stack[qid].j = jj;
          space_sort_struct.stack[qid].min = min;
          space_sort_struct.stack[qid].max = pivot;
          if (atomic_inc(&space_sort_struct.waiting) >=
              space_sort_struct.stack_size)
            error("Qstack overflow.");
830
          space_sort_struct.stack[qid].ready = 1;
831
        }
832

833
834
835
836
837
838
839
840
841
842
        /* Recurse on the right? */
        if (jj + 1 < j && pivot + 1 < max) {
          i = jj + 1;
          min = pivot + 1;
        } else
          break;

      } else {

        /* Recurse on the right? */
843
        if (pivot + 1 < max) {
844
845
          qid = atomic_inc(&space_sort_struct.last) %
                space_sort_struct.stack_size;
846
847
          while (space_sort_struct.stack[qid].ready)
            ;
848
849
850
851
852
853
854
          space_sort_struct.stack[qid].i = jj + 1;
          space_sort_struct.stack[qid].j = j;
          space_sort_struct.stack[qid].min = pivot + 1;
          space_sort_struct.stack[qid].max = max;
          if (atomic_inc(&space_sort_struct.waiting) >=
              space_sort_struct.stack_size)
            error("Qstack overflow.");
855
          space_sort_struct.stack[qid].ready = 1;
856
        }
857

858
859
860
861
862
863
864
        /* Recurse on the left? */
        if (jj > i && pivot > min) {
          j = jj;
          max = pivot;
        } else
          break;
      }
865

866
867
    } /* loop over sub-intervals. */

868
    atomic_dec(&space_sort_struct.waiting);
869
870

  } /* main loop. */
871
872
}

873
874
875
876
877
/**
 * @brief Sort the g-particles and condensed particles according to the given
 *indices.
 *
 * @param s The #space.
Matthieu Schaller's avatar
Matthieu Schaller committed
878
879
 * @param ind The indices with respect to which the gparts are sorted.
 * @param N The number of gparts
880
881
882
883
 * @param min Lowest index.
 * @param max highest index.
 * @param verbose Are we talkative ?
 */
Matthieu Schaller's avatar
Matthieu Schaller committed
884
void space_gparts_sort(struct space *s, int *ind, size_t N, int min, int max,
885
886
                       int verbose) {

Matthieu Schaller's avatar
Matthieu Schaller committed
887
  const ticks tic = getticks();
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911

  /*Populate the global parallel_sort structure with the input data */
  space_sort_struct.gparts = s->gparts;
  space_sort_struct.ind = ind;
  space_sort_struct.stack_size = 2 * (max - min + 1) + 10 + s->e->nr_threads;
  if ((space_sort_struct.stack = malloc(sizeof(struct qstack) *
                                        space_sort_struct.stack_size)) == NULL)
    error("Failed to allocate sorting stack.");
  for (int i = 0; i < space_sort_struct.stack_size; i++)
    space_sort_struct.stack[i].ready = 0;

  /* Add the first interval. */
  space_sort_struct.stack[0].i = 0;
  space_sort_struct.stack[0].j = N - 1;
  space_sort_struct.stack[0].min = min;
  space_sort_struct.stack[0].max = max;
  space_sort_struct.stack[0].ready = 1;
  space_sort_struct.first = 0;
  space_sort_struct.last = 1;
  space_sort_struct.waiting = 1;

  /* Launch the sorting tasks. */
  engine_launch(s->e, s->e->nr_threads, (1 << task_type_gpart_sort), 0);

912
#ifdef SWIFT_DEBUG_CHECKS
913
  /* Verify space_sort_struct. */
914
  for (int i = 1; i < N; i++)
915
916
    if (ind[i - 1] > ind[i])
      error("Sorting failed (ind[%i]=%i,ind[%i]=%i), min=%i, max=%i.", i - 1,
917
918
919
            ind[i - 1], i, ind[i], min, max);
  message("Sorting succeeded.");
#endif
920
921
922
923
924
925
926
927
928
929
930
931

  /* Clean up. */
  free(space_sort_struct.stack);

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

void space_do_gparts_sort() {

  /* Pointers to the sorting data. */
Matthieu Schaller's avatar
Matthieu Schaller committed
932
  int *ind = space_sort_struct.ind;
933
  struct gpart *gparts = space_sort_struct.gparts;
934

935
  /* Main loop. */
936
  while (space_sort_struct.waiting) {
937

938
    /* Grab an interval off the queue. */
939
940
941
942
943
944
    int qid =
        atomic_inc(&space_sort_struct.first) % space_sort_struct.stack_size;

    /* Wait for the entry to be ready, or for the sorting do be done. */
    while (!space_sort_struct.stack[qid].ready)
      if (!space_sort_struct.waiting) return;
945

946
    /* Get the stack entry. */
947
948
949
950
951
    ptrdiff_t i = space_sort_struct.stack[qid].i;
    ptrdiff_t j = space_sort_struct.stack[qid].j;
    int min = space_sort_struct.stack[qid].min;
    int max = space_sort_struct.stack[qid].max;
    space_sort_struct.stack[qid].ready = 0;
952
953
954

    /* Loop over sub-intervals. */
    while (1) {
955

956
      /* Bring beer. */
957
958
959
      const int pivot = (min + max) / 2;
      /* message("Working on interval [%i,%i] with min=%i, max=%i, pivot=%i.",
              i, j, min, max, pivot); */
960
961

      /* One pass of QuickSort's partitioning. */
962
963
      ptrdiff_t ii = i;
      ptrdiff_t jj = j;
964
965
966
967
      while (ii < jj) {
        while (ii <= j && ind[ii] <= pivot) ii++;
        while (jj >= i && ind[jj] > pivot) jj--;
        if (ii < jj) {
968
          size_t temp_i = ind[ii];
969
970
          ind[ii] = ind[jj];
          ind[jj] = temp_i;
971
          struct gpart temp_p = gparts[ii];
972
973
974
975
          gparts[ii] = gparts[jj];
          gparts[jj] = temp_p;
        }
      }
976

977
#ifdef SWIFT_DEBUG_CHECKS
978
      /* Verify space_sort_struct. */