cell.h 18.8 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;

  /*! tag used for MPI communication. */
120
  int tag;
121

122
  /*! Relative indices of the cell's progeny. */
123
  int progeny[8];
124

125
126
127
128
129
#ifdef SWIFT_DEBUG_CHECKS
  /* Cell ID (for debugging) */
  int cellID;
#endif

130
} SWIFT_STRUCT_ALIGN;
131

132
133
134
135
136
/**
 * @brief Cell information at the end of a time-step.
 */
struct pcell_step {

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

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

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

146
147
148
  /*! Minimal integer end-of-timestep in this cell (gravity) */
  integertime_t ti_gravity_end_max;

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

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
  /*! Linked list of the tasks computing this cell's gravity M-M forces. */
  struct link *grav_mm;

222
223
224
  /*! The task computing this cell's sorts. */
  struct task *sorts;

225
226
227
  /*! The multipole initialistation task */
  struct task *init_grav;

228
229
230
  /*! Implicit task for the gravity initialisation */
  struct task *init_grav_out;

231
  /*! Dependency implicit task for the ghost  (in->ghost->out)*/
232
  struct task *ghost_in;
233
234

  /*! Dependency implicit task for the ghost  (in->ghost->out)*/
235
  struct task *ghost_out;
236
237

  /*! The ghost task itself */
238
  struct task *ghost;
239

240
241
  /*! The extra ghost task for complex hydro schemes */
  struct task *extra_ghost;
242

243
244
245
246
247
  /*! The drift task for parts */
  struct task *drift_part;

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

249
250
251
252
253
  /*! The first kick task */
  struct task *kick1;

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

255
256
257
  /*! The task to end the force calculation */
  struct task *end_force;

258
259
  /*! The task to compute time-steps */
  struct task *timestep;
260

261
  /*! Task computing long range non-periodic gravity interactions */
262
  struct task *grav_long_range;
Tom Theuns's avatar
Tom Theuns committed
263

264
265
266
  /*! Implicit task for the down propagation */
  struct task *grav_down_in;

267
268
269
  /*! Task propagating the mesh forces to the particles */
  struct task *grav_mesh;

270
271
  /*! Task propagating the multipole to the particles */
  struct task *grav_down;
272

273
274
  /*! Task for cooling */
  struct task *cooling;
275

276
277
  /*! Task for source terms */
  struct task *sourceterms;
278

279
#ifdef WITH_MPI
280

281
  /* Task receiving hydro data (positions). */
282
  struct task *recv_xv;
283

284
  /* Task receiving hydro data (density). */
285
  struct task *recv_rho;
286

287
  /* Task receiving hydro data (gradient). */
288
  struct task *recv_gradient;
289

290
291
292
  /* Task receiving gpart data. */
  struct task *recv_grav;

293
294
  /* Task receiving data (time-step). */
  struct task *recv_ti;
295

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

299
  /* Linked list for sending hydro data (density). */
300
  struct link *send_rho;
301

302
  /* Linked list for sending hydro data (gradient). */
303
304
  struct link *send_gradient;

305
306
307
  /* Linked list for sending gpart data. */
  struct link *send_grav;

308
309
  /* Linked list for sending data (time-step). */
  struct link *send_ti;
310

311
  /*! Bit mask of the proxies this cell is registered with. */
312
313
  unsigned long long int sendto;

314
  /*! Pointer to this cell's packed representation. */
315
  struct pcell *pcell;
316
317

  /*! Size of the packed representation */
318
  int pcell_size;
319
320

  /*! MPI tag associated with this cell */
321
322
  int tag;

323
#endif
324

325
326
327
328
329
330
331
332
333
334
335
  /*! 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;
336

337
338
  /*! Maximum end of (integer) time step in this cell for gravity tasks. */
  integertime_t ti_gravity_end_max;
339

340
341
342
  /*! 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
343

344
345
346
347
348
349
  /*! 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;

350
351
352
  /*! Last (integer) time the cell's multipole was drifted forward in time. */
  integertime_t ti_old_multipole;

353
354
355
  /*! Minimum dimension, i.e. smallest edge of this cell (min(width)). */
  float dmin;

356
357
358
  /*! Maximum particle movement in this cell since the last sort. */
  float dx_max_sort;

359
360
361
  /*! Maximum part movement in this cell since last construction. */
  float dx_max_part;

362
363
364
365
366
367
  /*! Nr of #part in this cell. */
  int count;

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

368
369
370
  /*! Nr of #spart in this cell. */
  int scount;

371
372
373
374
375
376
377
378
379
  /*! 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;

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

383
384
385
  /*! Spin lock for various uses (#spart case). */
  swift_lock_type slock;

386
387
388
389
390
391
392
393
394
  /*! 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;

395
396
397
  /*! Number of #spart updated in this cell. */
  int s_updated;

398
399
400
  /*! ID of the node this cell lives on. */
  int nodeID;

401
402
403
404
405
406
  /*! 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;

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

410
411
412
  /*! Is the #spart data of this cell being used in a sub-cell? */
  int shold;

413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
  /*! 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;

428
429
430
  /*! Number of tasks that are associated with this cell. */
  short int nr_tasks;

431
432
433
  /*! Number of M-M tasks that are associated with this cell. */
  short int nr_mm_tasks;

434
435
436
437
438
439
440
441
442
  /*! 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;

443
  /*! Does this cell need to be drifted (hydro)? */
444
  char do_drift;
445

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

449
450
451
452
453
454
  /*! 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;

455
456
  /*! Do any of this cell's sub-cells need to be sorted? */
  char do_sub_sort;
457

458
#ifdef SWIFT_DEBUG_CHECKS
459
460
461
  /* Cell ID (for debugging) */
  int cellID;

462
463
464
  /*! Last (integer) time the cell's sort arrays were updated. */
  integertime_t ti_sort;

465
466
467
468
469
470
471
  /*! 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

472
} SWIFT_STRUCT_ALIGN;
473

474
475
476
477
/* Convert cell location to ID. */
#define cell_getid(cdim, i, j, k) \
  ((int)(k) + (cdim)[2] * ((int)(j) + (cdim)[1] * (int)(i)))

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

/* 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.
 */
Matthieu Schaller's avatar
Matthieu Schaller committed
541
542
__attribute__((always_inline)) INLINE static int
cell_can_recurse_in_pair_hydro_task(const struct cell *c) {
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557

  /* 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.
 */
Matthieu Schaller's avatar
Matthieu Schaller committed
558
559
__attribute__((always_inline)) INLINE static int
cell_can_recurse_in_self_hydro_task(const struct cell *c) {
560

561
  /* Is the cell split and not smaller than the smoothing length? */
562
  return c->split && (kernel_gamma * c->h_max_old < 0.5f * c->dmin);
563
564
565
}

/**
566
 * @brief Can a pair hydro task associated with a cell be split into smaller
567
568
569
570
 * sub-tasks.
 *
 * @param c The #cell.
 */
571
__attribute__((always_inline)) INLINE static int cell_can_split_pair_hydro_task(
572
573
574
575
576
577
578
579
580
581
582
    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);
}

/**
583
 * @brief Can a self hydro task associated with a cell be split into smaller
584
585
586
587
 * sub-tasks.
 *
 * @param c The #cell.
 */
588
__attribute__((always_inline)) INLINE static int cell_can_split_self_hydro_task(
589
590
591
    const struct cell *c) {

  /* Is the cell split ? */
592
593
  /* If so, is the cut-off radius with some leeway smaller than */
  /* the sub-cell sizes ? */
594
595
  /* 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 */
596
  return c->split && (space_stretch * kernel_gamma * c->h_max < 0.5f * c->dmin);
597
598
}

599
600
601
602
603
604
/**
 * @brief Can a pair gravity task associated with a cell be split into smaller
 * sub-tasks.
 *
 * @param c The #cell.
 */
Matthieu Schaller's avatar
Matthieu Schaller committed
605
606
__attribute__((always_inline)) INLINE static int
cell_can_split_pair_gravity_task(const struct cell *c) {
607
608

  /* Is the cell split ? */
609
  return c->split && c->depth < space_subdepth_grav;
610
611
612
613
614
615
616
617
}

/**
 * @brief Can a self gravity task associated with a cell be split into smaller
 * sub-tasks.
 *
 * @param c The #cell.
 */
Matthieu Schaller's avatar
Matthieu Schaller committed
618
619
__attribute__((always_inline)) INLINE static int
cell_can_split_self_gravity_task(const struct cell *c) {
620
621

  /* Is the cell split ? */
622
  return c->split && c->depth < space_subdepth_grav;
623
624
}

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
/**
 * @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);
}
642
643

#endif /* SWIFT_CELL_H */