cell.h 16.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
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
98
99
100
101
102
103
104
105
106
107
  /*! 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;

  /*! 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. */
108
  int tag;
109

110
  /*! Relative indices of the cell's progeny. */
111
  int progeny[8];
112
113

} SWIFT_STRUCT_ALIGN;
114

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
 * @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;
};

130
131
132
133
134
/**
 * @brief Cell within the tree structure.
 *
 * Contains particles, links to tasks, a multipole object and counters.
 */
135
136
struct cell {

137
  /*! The cell location on the grid. */
138
139
  double loc[3];

140
  /*! The cell dimensions. */
141
  double width[3];
142

143
  /*! Max smoothing length in this cell. */
144
145
  double h_max;

146
  /*! This cell's multipole. */
147
  struct gravity_tensors *multipole;
148

149
150
  /*! Linking pointer for "memory management". */
  struct cell *next;
151

152
  /*! Pointer to the #part data. */
153
154
  struct part *parts;

155
  /*! Pointer to the #xpart data. */
156
157
  struct xpart *xparts;

158
  /*! Pointer to the #gpart data. */
159
160
  struct gpart *gparts;

161
  /*! Pointer to the #spart data. */
162
  struct spart *sparts;
163

164
  /*! Pointer for the sorted indices. */
165
  struct entry *sort[13];
166

167
  /*! Pointers to the next level of cells. */
168
169
  struct cell *progeny[8];

170
  /*! Parent cell. */
171
172
  struct cell *parent;

173
  /*! Super cell, i.e. the highest-level parent cell that has pair/self tasks */
174
  struct cell *super;
175

176
177
  /*! Linked list of the tasks computing this cell's hydro density. */
  struct link *density;
178

179
180
  /* Linked list of the tasks computing this cell's hydro gradients. */
  struct link *gradient;
181

182
183
  /*! Linked list of the tasks computing this cell's hydro forces. */
  struct link *force;
184

185
186
  /*! Linked list of the tasks computing this cell's gravity forces. */
  struct link *grav;
187

188
189
190
  /*! The task computing this cell's sorts. */
  struct task *sorts;

191
192
193
  /*! The multipole initialistation task */
  struct task *init_grav;

194
  /*! Dependency implicit task for the ghost  (in->ghost->out)*/
195
  struct task *ghost_in;
196
197

  /*! Dependency implicit task for the ghost  (in->ghost->out)*/
198
  struct task *ghost_out;
199
200

  /*! The ghost task itself */
201
  struct task *ghost;
202

203
204
  /*! The extra ghost task for complex hydro schemes */
  struct task *extra_ghost;
205

206
207
208
209
210
  /*! The drift task for parts */
  struct task *drift_part;

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

212
213
214
215
216
  /*! The first kick task */
  struct task *kick1;

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

218
219
  /*! The task to compute time-steps */
  struct task *timestep;
220

221
222
223
  /*! Task linking the FFT mesh to the rest of gravity tasks */
  struct task *grav_ghost[2];

224
  /*! Task computing long range non-periodic gravity interactions */
225
  struct task *grav_long_range;
Tom Theuns's avatar
Tom Theuns committed
226

227
228
  /*! Task propagating the multipole to the particles */
  struct task *grav_down;
229

230
231
  /*! Task for cooling */
  struct task *cooling;
232

233
234
  /*! Task for source terms */
  struct task *sourceterms;
235

236
#ifdef WITH_MPI
237

238
  /* Task receiving hydro data (positions). */
239
  struct task *recv_xv;
240

241
  /* Task receiving hydro data (density). */
242
  struct task *recv_rho;
243

244
  /* Task receiving hydro data (gradient). */
245
  struct task *recv_gradient;
246

247
248
249
250
251
252
  /* Task receiving gpart data. */
  struct task *recv_grav;

  /* Task receiving multipole data. */
  struct task *recv_multipole;

253
254
  /* Task receiving data (time-step). */
  struct task *recv_ti;
255

256
  /* Linked list for sending hydro data (positions). */
257
  struct link *send_xv;
258

259
  /* Linked list for sending hydro data (density). */
260
  struct link *send_rho;
261

262
  /* Linked list for sending hydro data (gradient). */
263
264
  struct link *send_gradient;

265
266
267
268
269
270
  /* Linked list for sending gpart data. */
  struct link *send_grav;

  /* Linked list for sending multipole data. */
  struct link *send_multipole;

271
272
  /* Linked list for sending data (time-step). */
  struct link *send_ti;
273

274
  /*! Bit mask of the proxies this cell is registered with. */
275
276
  unsigned long long int sendto;

277
  /*! Pointer to this cell's packed representation. */
278
  struct pcell *pcell;
279
280

  /*! Size of the packed representation */
281
  int pcell_size;
282
283

  /*! MPI tag associated with this cell */
284
285
  int tag;

286
#endif
287

288
  /*! Minimum end of (integer) time step in this cell. */
289
  integertime_t ti_end_min;
290
291

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

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

297
298
299
300
301
302
  /*! 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;

303
304
305
  /*! Last (integer) time the cell's multipole was drifted forward in time. */
  integertime_t ti_old_multipole;

306
307
308
  /*! Minimum dimension, i.e. smallest edge of this cell (min(width)). */
  float dmin;

309
310
311
  /*! Maximum particle movement in this cell since the last sort. */
  float dx_max_sort;

312
313
314
315
316
317
  /*! 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;

318
319
320
321
322
323
  /*! Nr of #part in this cell. */
  int count;

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

324
325
326
  /*! Nr of #spart in this cell. */
  int scount;

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

336
337
338
  /*! Spin lock for various uses (#multipole case). */
  swift_lock_type mlock;

339
340
341
  /*! Spin lock for various uses (#spart case). */
  swift_lock_type slock;

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

351
352
353
  /*! Number of #spart updated in this cell. */
  int s_updated;

354
355
356
  /*! ID of the node this cell lives on. */
  int nodeID;

357
358
359
360
361
362
  /*! 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;

363
364
365
  /*! Is the #multipole data of this cell being used in a sub-cell? */
  int mhold;

366
367
368
  /*! Is the #spart data of this cell being used in a sub-cell? */
  int shold;

369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
  /*! 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;

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

396
  /*! Does this cell need to be drifted (hydro)? */
397
  char do_drift;
398

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

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

408
409
  /*! Do any of this cell's sub-cells need to be sorted? */
  char do_sub_sort;
410

411
#ifdef SWIFT_DEBUG_CHECKS
412
413
414
  /*! Last (integer) time the cell's sort arrays were updated. */
  integertime_t ti_sort;

415
416
417
418
419
420
421
  /*! 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

422
} SWIFT_STRUCT_ALIGN;
423

424
425
426
427
/* Convert cell location to ID. */
#define cell_getid(cdim, i, j, k) \
  ((int)(k) + (cdim)[2] * ((int)(j) + (cdim)[1] * (int)(i)))

428
/* Function prototypes. */
429
430
void cell_split(struct cell *c, ptrdiff_t parts_offset, ptrdiff_t sparts_offset,
                struct cell_buff *buff, struct cell_buff *sbuff,
431
                struct cell_buff *gbuff);
432
void cell_sanitize(struct cell *c, int treated);
433
434
435
436
int cell_locktree(struct cell *c);
void cell_unlocktree(struct cell *c);
int cell_glocktree(struct cell *c);
void cell_gunlocktree(struct cell *c);
437
438
int cell_mlocktree(struct cell *c);
void cell_munlocktree(struct cell *c);
439
440
int cell_slocktree(struct cell *c);
void cell_sunlocktree(struct cell *c);
441
442
int cell_pack(struct cell *c, struct pcell *pc);
int cell_unpack(struct pcell *pc, struct cell *c, struct space *s);
443
444
int cell_pack_end_step(struct cell *c, struct pcell_step *pcell);
int cell_unpack_end_step(struct cell *c, struct pcell_step *pcell);
445
446
int cell_pack_multipoles(struct cell *c, struct gravity_tensors *m);
int cell_unpack_multipoles(struct cell *c, struct gravity_tensors *m);
447
int cell_getsize(struct cell *c);
448
449
int cell_link_parts(struct cell *c, struct part *parts);
int cell_link_gparts(struct cell *c, struct gpart *gparts);
450
int cell_link_sparts(struct cell *c, struct spart *sparts);
451
void cell_convert_hydro(struct cell *c, void *data);
452
void cell_clean_links(struct cell *c, void *data);
453
void cell_make_multipoles(struct cell *c, integertime_t ti_current);
454
void cell_check_multipole(struct cell *c, void *data);
455
void cell_clean(struct cell *c);
456
457
void cell_check_part_drift_point(struct cell *c, void *data);
void cell_check_gpart_drift_point(struct cell *c, void *data);
458
void cell_check_multipole_drift_point(struct cell *c, void *data);
459
void cell_reset_task_counters(struct cell *c);
460
int cell_unskip_tasks(struct cell *c, struct scheduler *s);
461
void cell_set_super(struct cell *c, struct cell *super);
462
void cell_drift_part(struct cell *c, const struct engine *e, int force);
463
void cell_drift_gpart(struct cell *c, const struct engine *e, int force);
464
void cell_drift_multipole(struct cell *c, const struct engine *e);
465
void cell_drift_all_multipoles(struct cell *c, const struct engine *e);
466
void cell_check_timesteps(struct cell *c);
467
468
469
void cell_store_pre_drift_values(struct cell *c);
void cell_activate_subcell_tasks(struct cell *ci, struct cell *cj,
                                 struct scheduler *s);
470
471
void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj,
                                      struct scheduler *s);
472
473
void cell_activate_subcell_external_grav_tasks(struct cell *ci,
                                               struct scheduler *s);
474
void cell_activate_drift_part(struct cell *c, struct scheduler *s);
475
void cell_activate_drift_gpart(struct cell *c, struct scheduler *s);
476
void cell_activate_sorts(struct cell *c, int sid, struct scheduler *s);
477
void cell_clear_drift_flags(struct cell *c, void *data);
Pedro Gonnet's avatar
Pedro Gonnet committed
478
void cell_set_super_mapper(void *map_data, int num_elements, void *extra_data);
479
480
481
482
483
484
485
486
487
488
489
490
491
492
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

/* 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 */
545
  return c->split && (space_stretch * kernel_gamma * c->h_max < 0.5f * c->dmin);
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
}

/**
 * @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);
}
565
566

#endif /* SWIFT_CELL_H */