cell.h 18.3 KB
Newer Older
1
/*******************************************************************************
2
 * This file is part of SWIFT.
3
 * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk)
4
5
6
7
 *                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
 *               2015 Peter W. Draper (p.w.draper@durham.ac.uk)
 *               2016 John A. Regan (john.a.regan@durham.ac.uk)
 *                    Tom Theuns (tom.theuns@durham.ac.uk)
8
 *
9
10
11
12
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
13
 *
14
15
16
17
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
18
 *
19
20
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 ******************************************************************************/
23
24
#ifndef SWIFT_CELL_H
#define SWIFT_CELL_H
25

26
27
28
/* Config parameters. */
#include "../config.h"

29
/* Includes. */
30
31
32
#include <stddef.h>

/* Local includes. */
33
#include "align.h"
34
#include "kernel_hydro.h"
Pedro Gonnet's avatar
Pedro Gonnet committed
35
#include "lock.h"
36
#include "multipole.h"
37
#include "part.h"
38
#include "space.h"
39
#include "task.h"
40
#include "timeline.h"
41

42
/* Avoid cyclic inclusions */
43
struct engine;
44
struct scheduler;
45

46
47
48
/* Max tag size set to 2^29 to take into account some MPI implementations
 * that use 2^31 as the upper bound on MPI tags and the fact that
 * cell_next_tag is multiplied by 2 when passed to an MPI function.
49
50
 * The maximum was lowered by a further factor of 2 to be on the safe side.*/
#define cell_max_tag (1 << 29)
51

52
#define cell_align 128
53

54
55
56
/* Global variables. */
extern int cell_next_tag;

57
58
59
60
/* Struct to temporarily buffer the particle locations and bin id. */
struct cell_buff {
  double x[3];
  int ind;
61
} SWIFT_STRUCT_ALIGN;
62

63
64
65
66
67
68
69
70
71
72
/* Mini struct to link cells to tasks. Used as a linked list. */
struct link {

  /* The task pointer. */
  struct task *t;

  /* The next pointer. */
  struct link *next;
};

73
74
75
76
77
/**
 * @brief Packed cell for information correct at rebuild time.
 *
 * Contains all the information for a tree walk in a non-local cell.
 */
78
79
struct pcell {

80
  /*! Maximal smoothing length. */
81
  double h_max;
82

83
84
  /*! Minimal integer end-of-timestep in this cell for hydro tasks */
  integertime_t ti_hydro_end_min;
85

86
87
  /*! Maximal integer end-of-timestep in this cell for hydro tasks */
  integertime_t ti_hydro_end_max;
88

89
90
91
92
93
94
95
96
97
98
99
  /*! Maximal integer beginning-of-timestep in this cell for hydro tasks */
  integertime_t ti_hydro_beg_max;

  /*! Minimal integer end-of-timestep in this cell for gravity tasks */
  integertime_t ti_gravity_end_min;

  /*! Maximal integer end-of-timestep in this cell for gravity tasks */
  integertime_t ti_gravity_end_max;

  /*! Maximal integer beginning-of-timestep in this cell for gravity tasks */
  integertime_t ti_gravity_beg_max;
Pedro Gonnet's avatar
Pedro Gonnet committed
100

101
102
103
104
105
106
  /*! Integer time of the last drift of the #part in this cell */
  integertime_t ti_old_part;

  /*! Integer time of the last drift of the #gpart in this cell */
  integertime_t ti_old_gpart;

107
108
109
  /*! Integer time of the last drift of the #multipole in this cell */
  integertime_t ti_old_multipole;

110
111
112
113
114
115
116
117
118
119
  /*! Number of #part in this cell. */
  int count;

  /*! Number of #gpart in this cell. */
  int gcount;

  /*! Number of #spart in this cell. */
  int scount;

  /*! Relative indices of the cell's progeny. */
120
  int progeny[8];
121

122
123
124
125
126
#ifdef SWIFT_DEBUG_CHECKS
  /* Cell ID (for debugging) */
  int cellID;
#endif

127
} SWIFT_STRUCT_ALIGN;
128

129
130
131
132
133
/**
 * @brief Cell information at the end of a time-step.
 */
struct pcell_step {

134
135
136
  /*! Minimal integer end-of-timestep in this cell (hydro) */
  integertime_t ti_hydro_end_min;

137
138
139
  /*! Minimal integer end-of-timestep in this cell (hydro) */
  integertime_t ti_hydro_end_max;

140
141
  /*! Minimal integer end-of-timestep in this cell (gravity) */
  integertime_t ti_gravity_end_min;
142

143
144
145
  /*! Minimal integer end-of-timestep in this cell (gravity) */
  integertime_t ti_gravity_end_max;

146
147
148
149
150
151
152
  /*! Maximal distance any #part has travelled since last rebuild */
  float dx_max_part;

  /*! Maximal distance any #gpart has travelled since last rebuild */
  float dx_max_gpart;
};

153
154
155
156
157
/**
 * @brief Cell within the tree structure.
 *
 * Contains particles, links to tasks, a multipole object and counters.
 */
158
159
struct cell {

160
  /*! The cell location on the grid. */
161
162
  double loc[3];

163
  /*! The cell dimensions. */
164
  double width[3];
165

166
  /*! Max smoothing length in this cell. */
167
168
  double h_max;

169
  /*! This cell's multipole. */
170
  struct gravity_tensors *multipole;
171

172
173
  /*! Linking pointer for "memory management". */
  struct cell *next;
174

175
  /*! Pointer to the #part data. */
176
177
  struct part *parts;

178
  /*! Pointer to the #xpart data. */
179
180
  struct xpart *xparts;

181
  /*! Pointer to the #gpart data. */
182
183
  struct gpart *gparts;

184
  /*! Pointer to the #spart data. */
185
  struct spart *sparts;
186

187
  /*! Pointer for the sorted indices. */
188
  struct entry *sort[13];
189

190
  /*! Pointers to the next level of cells. */
191
192
  struct cell *progeny[8];

193
  /*! Parent cell. */
194
195
  struct cell *parent;

196
  /*! Super cell, i.e. the highest-level parent cell with *any* task */
197
  struct cell *super;
198

199
200
  /*! Super cell, i.e. the highest-level parent cell that has a hydro pair/self
   * tasks */
201
202
  struct cell *super_hydro;

203
204
  /*! Super cell, i.e. the highest-level parent cell that has a grav pair/self
   * tasks */
205
206
  struct cell *super_gravity;

207
208
  /*! Linked list of the tasks computing this cell's hydro density. */
  struct link *density;
209

210
211
  /* Linked list of the tasks computing this cell's hydro gradients. */
  struct link *gradient;
212

213
214
  /*! Linked list of the tasks computing this cell's hydro forces. */
  struct link *force;
215

216
217
  /*! Linked list of the tasks computing this cell's gravity forces. */
  struct link *grav;
218

219
220
221
  /*! The task computing this cell's sorts. */
  struct task *sorts;

222
223
224
  /*! The multipole initialistation task */
  struct task *init_grav;

225
  /*! Dependency implicit task for the ghost  (in->ghost->out)*/
226
  struct task *ghost_in;
227
228

  /*! Dependency implicit task for the ghost  (in->ghost->out)*/
229
  struct task *ghost_out;
230
231

  /*! The ghost task itself */
232
  struct task *ghost;
233

234
235
  /*! The extra ghost task for complex hydro schemes */
  struct task *extra_ghost;
236

237
238
239
240
241
  /*! The drift task for parts */
  struct task *drift_part;

  /*! The drift task for gparts */
  struct task *drift_gpart;
242

243
244
245
246
247
  /*! The first kick task */
  struct task *kick1;

  /*! The second kick task */
  struct task *kick2;
248

249
250
251
  /*! The task to end the force calculation */
  struct task *end_force;

252
253
  /*! The task to compute time-steps */
  struct task *timestep;
254

255
  /*! Task linking the FFT mesh to the rest of gravity tasks */
256
  struct task *grav_ghost_in, *grav_ghost_out;
257

258
  /*! Task computing long range non-periodic gravity interactions */
259
  struct task *grav_long_range;
Tom Theuns's avatar
Tom Theuns committed
260

261
262
263
  /*! Task propagating the mesh forces to the particles */
  struct task *grav_mesh;

264
265
  /*! Task propagating the multipole to the particles */
  struct task *grav_down;
266

267
268
  /*! Task for cooling */
  struct task *cooling;
269

270
271
  /*! Task for source terms */
  struct task *sourceterms;
272

273
#ifdef WITH_MPI
274

275
  /* Task receiving hydro data (positions). */
276
  struct task *recv_xv;
277

278
  /* Task receiving hydro data (density). */
279
  struct task *recv_rho;
280

281
  /* Task receiving hydro data (gradient). */
282
  struct task *recv_gradient;
283

284
285
286
  /* Task receiving gpart data. */
  struct task *recv_grav;

287
288
  /* Task receiving data (time-step). */
  struct task *recv_ti;
289

290
  /* Linked list for sending hydro data (positions). */
291
  struct link *send_xv;
292

293
  /* Linked list for sending hydro data (density). */
294
  struct link *send_rho;
295

296
  /* Linked list for sending hydro data (gradient). */
297
298
  struct link *send_gradient;

299
300
301
  /* Linked list for sending gpart data. */
  struct link *send_grav;

302
303
  /* Linked list for sending data (time-step). */
  struct link *send_ti;
304

305
  /*! Bit mask of the proxies this cell is registered with. */
306
307
  unsigned long long int sendto;

308
  /*! Pointer to this cell's packed representation. */
309
  struct pcell *pcell;
310
311

  /*! Size of the packed representation */
312
  int pcell_size;
313
314

  /*! MPI tag associated with this cell */
315
316
  int tag;

317
#endif
318

319
320
321
322
323
324
325
326
327
328
329
  /*! Minimum end of (integer) time step in this cell for hydro tasks. */
  integertime_t ti_hydro_end_min;

  /*! Maximum end of (integer) time step in this cell for hydro tasks. */
  integertime_t ti_hydro_end_max;

  /*! Maximum beginning of (integer) time step in this cell for hydro tasks. */
  integertime_t ti_hydro_beg_max;

  /*! Minimum end of (integer) time step in this cell for gravity tasks. */
  integertime_t ti_gravity_end_min;
330

331
332
  /*! Maximum end of (integer) time step in this cell for gravity tasks. */
  integertime_t ti_gravity_end_max;
333

334
335
336
  /*! Maximum beginning of (integer) time step in this cell for gravity tasks.
   */
  integertime_t ti_gravity_beg_max;
Matthieu Schaller's avatar
Matthieu Schaller committed
337

338
339
340
341
342
343
  /*! Last (integer) time the cell's part were drifted forward in time. */
  integertime_t ti_old_part;

  /*! Last (integer) time the cell's gpart were drifted forward in time. */
  integertime_t ti_old_gpart;

344
345
346
  /*! Last (integer) time the cell's multipole was drifted forward in time. */
  integertime_t ti_old_multipole;

347
348
349
  /*! Minimum dimension, i.e. smallest edge of this cell (min(width)). */
  float dmin;

350
351
352
  /*! Maximum particle movement in this cell since the last sort. */
  float dx_max_sort;

353
354
355
356
357
358
  /*! Maximum part movement in this cell since last construction. */
  float dx_max_part;

  /*! Maximum gpart movement in this cell since last construction. */
  float dx_max_gpart;

359
360
361
362
363
364
  /*! Nr of #part in this cell. */
  int count;

  /*! Nr of #gpart in this cell. */
  int gcount;

365
366
367
  /*! Nr of #spart in this cell. */
  int scount;

368
369
370
371
372
373
374
375
376
  /*! Bit-mask indicating the sorted directions */
  unsigned int sorted;

  /*! Spin lock for various uses (#part case). */
  swift_lock_type lock;

  /*! Spin lock for various uses (#gpart case). */
  swift_lock_type glock;

377
378
379
  /*! Spin lock for various uses (#multipole case). */
  swift_lock_type mlock;

380
381
382
  /*! Spin lock for various uses (#spart case). */
  swift_lock_type slock;

383
384
385
386
387
388
389
390
391
  /*! ID of the previous owner, e.g. runner. */
  int owner;

  /*! Number of #part updated in this cell. */
  int updated;

  /*! Number of #gpart updated in this cell. */
  int g_updated;

392
393
394
  /*! Number of #spart updated in this cell. */
  int s_updated;

395
396
397
  /*! ID of the node this cell lives on. */
  int nodeID;

398
399
400
401
402
403
  /*! Is the #part data of this cell being used in a sub-cell? */
  int hold;

  /*! Is the #gpart data of this cell being used in a sub-cell? */
  int ghold;

404
405
406
  /*! Is the #multipole data of this cell being used in a sub-cell? */
  int mhold;

407
408
409
  /*! Is the #spart data of this cell being used in a sub-cell? */
  int shold;

410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
  /*! Values of dx_max before the drifts, used for sub-cell tasks. */
  float dx_max_old;

  /*! Values of h_max before the drifts, used for sub-cell tasks. */
  float h_max_old;

  /*! Values of dx_max_sort before the drifts, used for sub-cell tasks. */
  float dx_max_sort_old;

  /*! Bit mask of sort directions that will be needed in the next timestep. */
  unsigned int requires_sorts;

  /*! Bit mask of sorts that need to be computed for this cell. */
  unsigned int do_sort;

425
426
427
428
429
430
431
432
433
434
435
436
  /*! Number of tasks that are associated with this cell. */
  short int nr_tasks;

  /*! The depth of this cell in the tree. */
  char depth;

  /*! Is this cell split ? */
  char split;

  /*! The maximal depth of this cell and its progenies */
  char maxdepth;

437
  /*! Does this cell need to be drifted (hydro)? */
438
  char do_drift;
439

440
  /*! Do any of this cell's sub-cells need to be drifted (hydro)? */
441
  char do_sub_drift;
Pedro Gonnet's avatar
Pedro Gonnet committed
442

443
444
445
446
447
448
  /*! Does this cell need to be drifted (gravity)? */
  char do_grav_drift;

  /*! Do any of this cell's sub-cells need to be drifted (gravity)? */
  char do_grav_sub_drift;

449
450
  /*! Do any of this cell's sub-cells need to be sorted? */
  char do_sub_sort;
451

452
#ifdef SWIFT_DEBUG_CHECKS
453
454
455
  /* Cell ID (for debugging) */
  int cellID;

456
457
458
  /*! Last (integer) time the cell's sort arrays were updated. */
  integertime_t ti_sort;

459
460
461
462
463
464
465
  /*! The list of tasks that have been executed on this cell */
  char tasks_executed[64];

  /*! The list of sub-tasks that have been executed on this cell */
  char subtasks_executed[64];
#endif

466
} SWIFT_STRUCT_ALIGN;
467

468
469
470
471
/* Convert cell location to ID. */
#define cell_getid(cdim, i, j, k) \
  ((int)(k) + (cdim)[2] * ((int)(j) + (cdim)[1] * (int)(i)))

472
/* Function prototypes. */
473
474
void cell_split(struct cell *c, ptrdiff_t parts_offset, ptrdiff_t sparts_offset,
                struct cell_buff *buff, struct cell_buff *sbuff,
475
                struct cell_buff *gbuff);
476
void cell_sanitize(struct cell *c, int treated);
477
478
479
480
int cell_locktree(struct cell *c);
void cell_unlocktree(struct cell *c);
int cell_glocktree(struct cell *c);
void cell_gunlocktree(struct cell *c);
481
482
int cell_mlocktree(struct cell *c);
void cell_munlocktree(struct cell *c);
483
484
int cell_slocktree(struct cell *c);
void cell_sunlocktree(struct cell *c);
485
486
int cell_pack(struct cell *c, struct pcell *pc);
int cell_unpack(struct pcell *pc, struct cell *c, struct space *s);
487
488
int cell_pack_tags(const struct cell *c, int *tags);
int cell_unpack_tags(const int *tags, struct cell *c);
489
490
int cell_pack_end_step(struct cell *c, struct pcell_step *pcell);
int cell_unpack_end_step(struct cell *c, struct pcell_step *pcell);
491
492
int cell_pack_multipoles(struct cell *c, struct gravity_tensors *m);
int cell_unpack_multipoles(struct cell *c, struct gravity_tensors *m);
493
int cell_getsize(struct cell *c);
494
495
int cell_link_parts(struct cell *c, struct part *parts);
int cell_link_gparts(struct cell *c, struct gpart *gparts);
496
int cell_link_sparts(struct cell *c, struct spart *sparts);
497
void cell_clean_links(struct cell *c, void *data);
498
void cell_make_multipoles(struct cell *c, integertime_t ti_current);
499
void cell_check_multipole(struct cell *c, void *data);
500
void cell_clean(struct cell *c);
501
502
void cell_check_part_drift_point(struct cell *c, void *data);
void cell_check_gpart_drift_point(struct cell *c, void *data);
503
void cell_check_multipole_drift_point(struct cell *c, void *data);
504
void cell_reset_task_counters(struct cell *c);
505
506
int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s);
int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s);
507
void cell_set_super(struct cell *c, struct cell *super);
508
void cell_drift_part(struct cell *c, const struct engine *e, int force);
509
void cell_drift_gpart(struct cell *c, const struct engine *e, int force);
510
void cell_drift_multipole(struct cell *c, const struct engine *e);
511
void cell_drift_all_multipoles(struct cell *c, const struct engine *e);
512
void cell_check_timesteps(struct cell *c);
513
void cell_store_pre_drift_values(struct cell *c);
514
515
void cell_activate_subcell_hydro_tasks(struct cell *ci, struct cell *cj,
                                       struct scheduler *s);
516
517
void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj,
                                      struct scheduler *s);
518
519
void cell_activate_subcell_external_grav_tasks(struct cell *ci,
                                               struct scheduler *s);
520
void cell_activate_drift_part(struct cell *c, struct scheduler *s);
521
void cell_activate_drift_gpart(struct cell *c, struct scheduler *s);
522
void cell_activate_sorts(struct cell *c, int sid, struct scheduler *s);
523
void cell_clear_drift_flags(struct cell *c, void *data);
Pedro Gonnet's avatar
Pedro Gonnet committed
524
void cell_set_super_mapper(void *map_data, int num_elements, void *extra_data);
525
int cell_has_tasks(struct cell *c);
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554

/* Inlined functions (for speed). */

/**
 * @brief Can a sub-pair hydro task recurse to a lower level based
 * on the status of the particles in the cell.
 *
 * @param c The #cell.
 */
__attribute__((always_inline)) INLINE static int cell_can_recurse_in_pair_task(
    const struct cell *c) {

  /* Is the cell split ? */
  /* If so, is the cut-off radius plus the max distance the parts have moved */
  /* smaller than the sub-cell sizes ? */
  /* Note: We use the _old values as these might have been updated by a drift */
  return c->split &&
         ((kernel_gamma * c->h_max_old + c->dx_max_old) < 0.5f * c->dmin);
}

/**
 * @brief Can a sub-self hydro task recurse to a lower level based
 * on the status of the particles in the cell.
 *
 * @param c The #cell.
 */
__attribute__((always_inline)) INLINE static int cell_can_recurse_in_self_task(
    const struct cell *c) {

555
  /* Is the cell split and not smaller than the smoothing length? */
556
  return c->split && (kernel_gamma * c->h_max_old < 0.5f * c->dmin);
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
}

/**
 * @brief Can a pair task associated with a cell be split into smaller
 * sub-tasks.
 *
 * @param c The #cell.
 */
__attribute__((always_inline)) INLINE static int cell_can_split_pair_task(
    const struct cell *c) {

  /* Is the cell split ? */
  /* If so, is the cut-off radius with some leeway smaller than */
  /* the sub-cell sizes ? */
  /* Note that since tasks are create after a rebuild no need to take */
  /* into account any part motion (i.e. dx_max == 0 here) */
  return c->split && (space_stretch * kernel_gamma * c->h_max < 0.5f * c->dmin);
}

/**
 * @brief Can a self task associated with a cell be split into smaller
 * sub-tasks.
 *
 * @param c The #cell.
 */
__attribute__((always_inline)) INLINE static int cell_can_split_self_task(
    const struct cell *c) {

  /* Is the cell split ? */
  /* Note: No need for more checks here as all the sub-pairs and sub-self */
  /* tasks will be created. So no need to check for h_max */
588
  return c->split && (space_stretch * kernel_gamma * c->h_max < 0.5f * c->dmin);
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
}

/**
 * @brief Have particles in a pair of cells moved too much and require a rebuild
 * ?
 *
 * @param ci The first #cell.
 * @param cj The second #cell.
 */
__attribute__((always_inline)) INLINE static int cell_need_rebuild_for_pair(
    const struct cell *ci, const struct cell *cj) {

  /* Is the cut-off radius plus the max distance the parts in both cells have */
  /* moved larger than the cell size ? */
  /* Note ci->dmin == cj->dmin */
  return (kernel_gamma * max(ci->h_max, cj->h_max) + ci->dx_max_part +
              cj->dx_max_part >
          cj->dmin);
}
608

609
610
611
612
613
614
615
616
617
618
619
620
/**
 * @brief Add a unique tag to a cell.
 */
__attribute((always_inline)) INLINE static void cell_tag(struct cell *c) {
#ifdef WITH_MPI
  if (c->tag < 0 && (c->tag = atomic_inc(&cell_next_tag)) > cell_max_tag)
    error("Ran out of cell tags.");
#else
  error("SWIFT was not compiled with MPI enabled.");
#endif  // WITH_MPI
}

621
#endif /* SWIFT_CELL_H */