cell.h 16.7 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
85
86
87
88
89
90
  /*! Minimal integer end-of-timestep in this cell */
  integertime_t ti_end_min;

  /*! Maximal integer end-of-timestep in this cell */
  integertime_t ti_end_max;

  /*! Maximal integer beginning-of-timestep in this cell */
  integertime_t ti_beg_max;
Pedro Gonnet's avatar
Pedro Gonnet committed
91

92
93
94
95
96
97
  /*! 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;

98
99
100
  /*! Integer time of the last drift of the #multipole in this cell */
  integertime_t ti_old_multipole;

101
102
103
104
105
106
107
108
109
110
  /*! 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. */
111
  int tag;
112

113
  /*! Relative indices of the cell's progeny. */
114
  int progeny[8];
115

116
117
118
119
120
#ifdef SWIFT_DEBUG_CHECKS
  /* Cell ID (for debugging) */
  int cellID;
#endif

121
} SWIFT_STRUCT_ALIGN;
122

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
 * @brief Cell information at the end of a time-step.
 */
struct pcell_step {

  /*! Minimal integer end-of-timestep in this cell */
  integertime_t ti_end_min;

  /*! 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;
};

138
139
140
141
142
/**
 * @brief Cell within the tree structure.
 *
 * Contains particles, links to tasks, a multipole object and counters.
 */
143
144
struct cell {

145
  /*! The cell location on the grid. */
146
147
  double loc[3];

148
  /*! The cell dimensions. */
149
  double width[3];
150

151
  /*! Max smoothing length in this cell. */
152
153
  double h_max;

154
  /*! This cell's multipole. */
155
  struct gravity_tensors *multipole;
156

157
158
  /*! Linking pointer for "memory management". */
  struct cell *next;
159

160
  /*! Pointer to the #part data. */
161
162
  struct part *parts;

163
  /*! Pointer to the #xpart data. */
164
165
  struct xpart *xparts;

166
  /*! Pointer to the #gpart data. */
167
168
  struct gpart *gparts;

169
  /*! Pointer to the #spart data. */
170
  struct spart *sparts;
171

172
  /*! Pointer for the sorted indices. */
173
  struct entry *sort[13];
174

175
  /*! Pointers to the next level of cells. */
176
177
  struct cell *progeny[8];

178
  /*! Parent cell. */
179
180
  struct cell *parent;

181
  /*! Super cell, i.e. the highest-level parent cell with *any* task */
182
  struct cell *super;
183

184
185
  /*! Super cell, i.e. the highest-level parent cell that has a hydro pair/self
   * tasks */
186
187
  struct cell *super_hydro;

188
189
  /*! Super cell, i.e. the highest-level parent cell that has a grav pair/self
   * tasks */
190
191
  struct cell *super_gravity;

192
193
  /*! Linked list of the tasks computing this cell's hydro density. */
  struct link *density;
194

195
196
  /* Linked list of the tasks computing this cell's hydro gradients. */
  struct link *gradient;
197

198
199
  /*! Linked list of the tasks computing this cell's hydro forces. */
  struct link *force;
200

201
202
  /*! Linked list of the tasks computing this cell's gravity forces. */
  struct link *grav;
203

204
205
206
  /*! The task computing this cell's sorts. */
  struct task *sorts;

207
208
209
  /*! The multipole initialistation task */
  struct task *init_grav;

210
  /*! Dependency implicit task for the ghost  (in->ghost->out)*/
211
  struct task *ghost_in;
212
213

  /*! Dependency implicit task for the ghost  (in->ghost->out)*/
214
  struct task *ghost_out;
215
216

  /*! The ghost task itself */
217
  struct task *ghost;
218

219
220
  /*! The extra ghost task for complex hydro schemes */
  struct task *extra_ghost;
221

222
223
224
225
226
  /*! The drift task for parts */
  struct task *drift_part;

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

228
229
230
231
232
  /*! The first kick task */
  struct task *kick1;

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

234
235
  /*! The task to compute time-steps */
  struct task *timestep;
236

237
  /*! Task linking the FFT mesh to the rest of gravity tasks */
238
  struct task *grav_ghost_in, *grav_ghost_out;
239

240
  /*! Task computing long range non-periodic gravity interactions */
241
  struct task *grav_long_range;
Tom Theuns's avatar
Tom Theuns committed
242

243
244
  /*! Task propagating the multipole to the particles */
  struct task *grav_down;
245

246
247
  /*! Task for cooling */
  struct task *cooling;
248

249
250
  /*! Task for source terms */
  struct task *sourceterms;
251

252
#ifdef WITH_MPI
253

254
  /* Task receiving hydro data (positions). */
255
  struct task *recv_xv;
256

257
  /* Task receiving hydro data (density). */
258
  struct task *recv_rho;
259

260
  /* Task receiving hydro data (gradient). */
261
  struct task *recv_gradient;
262

263
264
265
  /* Task receiving gpart data. */
  struct task *recv_grav;

266
267
  /* Task receiving data (time-step). */
  struct task *recv_ti;
268

269
  /* Linked list for sending hydro data (positions). */
270
  struct link *send_xv;
271

272
  /* Linked list for sending hydro data (density). */
273
  struct link *send_rho;
274

275
  /* Linked list for sending hydro data (gradient). */
276
277
  struct link *send_gradient;

278
279
280
  /* Linked list for sending gpart data. */
  struct link *send_grav;

281
282
  /* Linked list for sending data (time-step). */
  struct link *send_ti;
283

284
  /*! Bit mask of the proxies this cell is registered with. */
285
286
  unsigned long long int sendto;

287
  /*! Pointer to this cell's packed representation. */
288
  struct pcell *pcell;
289
290

  /*! Size of the packed representation */
291
  int pcell_size;
292
293

  /*! MPI tag associated with this cell */
294
295
  int tag;

296
#endif
297

298
  /*! Minimum end of (integer) time step in this cell. */
299
  integertime_t ti_end_min;
300
301

  /*! Maximum end of (integer) time step in this cell. */
302
  integertime_t ti_end_max;
303

304
305
  /*! Maximum beginning of (integer) time step in this cell. */
  integertime_t ti_beg_max;
Matthieu Schaller's avatar
Matthieu Schaller committed
306

307
308
309
310
311
312
  /*! 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;

313
314
315
  /*! Last (integer) time the cell's multipole was drifted forward in time. */
  integertime_t ti_old_multipole;

316
317
318
  /*! Minimum dimension, i.e. smallest edge of this cell (min(width)). */
  float dmin;

319
320
321
  /*! Maximum particle movement in this cell since the last sort. */
  float dx_max_sort;

322
323
324
325
326
327
  /*! 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;

328
329
330
331
332
333
  /*! Nr of #part in this cell. */
  int count;

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

334
335
336
  /*! Nr of #spart in this cell. */
  int scount;

337
338
339
340
341
342
343
344
345
  /*! 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;

346
347
348
  /*! Spin lock for various uses (#multipole case). */
  swift_lock_type mlock;

349
350
351
  /*! Spin lock for various uses (#spart case). */
  swift_lock_type slock;

352
353
354
355
356
357
358
359
360
  /*! 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;

361
362
363
  /*! Number of #spart updated in this cell. */
  int s_updated;

364
365
366
  /*! ID of the node this cell lives on. */
  int nodeID;

367
368
369
370
371
372
  /*! 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;

373
374
375
  /*! Is the #multipole data of this cell being used in a sub-cell? */
  int mhold;

376
377
378
  /*! Is the #spart data of this cell being used in a sub-cell? */
  int shold;

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
  /*! 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;

394
395
396
397
398
399
400
401
402
403
404
405
  /*! 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;

406
  /*! Does this cell need to be drifted (hydro)? */
407
  char do_drift;
408

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

412
413
414
415
416
417
  /*! 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;

418
419
  /*! Do any of this cell's sub-cells need to be sorted? */
  char do_sub_sort;
420

421
#ifdef SWIFT_DEBUG_CHECKS
422
423
424
  /* Cell ID (for debugging) */
  int cellID;

425
426
427
  /*! Last (integer) time the cell's sort arrays were updated. */
  integertime_t ti_sort;

428
429
430
431
432
433
434
  /*! 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

435
} SWIFT_STRUCT_ALIGN;
436

437
438
439
440
/* Convert cell location to ID. */
#define cell_getid(cdim, i, j, k) \
  ((int)(k) + (cdim)[2] * ((int)(j) + (cdim)[1] * (int)(i)))

441
/* Function prototypes. */
442
443
void cell_split(struct cell *c, ptrdiff_t parts_offset, ptrdiff_t sparts_offset,
                struct cell_buff *buff, struct cell_buff *sbuff,
444
                struct cell_buff *gbuff);
445
void cell_sanitize(struct cell *c, int treated);
446
447
448
449
int cell_locktree(struct cell *c);
void cell_unlocktree(struct cell *c);
int cell_glocktree(struct cell *c);
void cell_gunlocktree(struct cell *c);
450
451
int cell_mlocktree(struct cell *c);
void cell_munlocktree(struct cell *c);
452
453
int cell_slocktree(struct cell *c);
void cell_sunlocktree(struct cell *c);
454
455
int cell_pack(struct cell *c, struct pcell *pc);
int cell_unpack(struct pcell *pc, struct cell *c, struct space *s);
456
457
int cell_pack_end_step(struct cell *c, struct pcell_step *pcell);
int cell_unpack_end_step(struct cell *c, struct pcell_step *pcell);
458
459
int cell_pack_multipoles(struct cell *c, struct gravity_tensors *m);
int cell_unpack_multipoles(struct cell *c, struct gravity_tensors *m);
460
int cell_getsize(struct cell *c);
461
462
int cell_link_parts(struct cell *c, struct part *parts);
int cell_link_gparts(struct cell *c, struct gpart *gparts);
463
int cell_link_sparts(struct cell *c, struct spart *sparts);
464
void cell_convert_hydro(struct cell *c, void *data);
465
void cell_clean_links(struct cell *c, void *data);
466
void cell_make_multipoles(struct cell *c, integertime_t ti_current);
467
void cell_check_multipole(struct cell *c, void *data);
468
void cell_clean(struct cell *c);
469
470
void cell_check_part_drift_point(struct cell *c, void *data);
void cell_check_gpart_drift_point(struct cell *c, void *data);
471
void cell_check_multipole_drift_point(struct cell *c, void *data);
472
void cell_reset_task_counters(struct cell *c);
473
int cell_unskip_tasks(struct cell *c, struct scheduler *s);
474
void cell_set_super(struct cell *c, struct cell *super);
475
void cell_drift_part(struct cell *c, const struct engine *e, int force);
476
void cell_drift_gpart(struct cell *c, const struct engine *e, int force);
477
void cell_drift_multipole(struct cell *c, const struct engine *e);
478
void cell_drift_all_multipoles(struct cell *c, const struct engine *e);
479
void cell_check_timesteps(struct cell *c);
480
481
482
void cell_store_pre_drift_values(struct cell *c);
void cell_activate_subcell_tasks(struct cell *ci, struct cell *cj,
                                 struct scheduler *s);
483
484
void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj,
                                      struct scheduler *s);
485
486
void cell_activate_subcell_external_grav_tasks(struct cell *ci,
                                               struct scheduler *s);
487
void cell_activate_drift_part(struct cell *c, struct scheduler *s);
488
void cell_activate_drift_gpart(struct cell *c, struct scheduler *s);
489
void cell_activate_sorts(struct cell *c, int sid, struct scheduler *s);
490
void cell_clear_drift_flags(struct cell *c, void *data);
Pedro Gonnet's avatar
Pedro Gonnet committed
491
void cell_set_super_mapper(void *map_data, int num_elements, void *extra_data);
492
int cell_has_tasks(struct cell *c);
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
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
555
556
557
558

/* 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) {

  /* Is the cell split ? */
  /* Note: No need for more checks here as all the sub-pairs and sub-self */
  /* operations will be executed. So no need for the particle to be at exactly
   */
  /* the right place. */
  return c->split;
}

/**
 * @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 */
559
  return c->split && (space_stretch * kernel_gamma * c->h_max < 0.5f * c->dmin);
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
}

/**
 * @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);
}
579
580

#endif /* SWIFT_CELL_H */