cell.h 15 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
/* Packed cell. */
struct pcell {

76
  /* Stats on this cell's particles. */
77
  double h_max;
78
  integertime_t ti_end_min, ti_end_max, ti_beg_max, ti_old_part, ti_old_gpart;
79
80

  /* Number of particles in this cell. */
81
  int count, gcount, scount;
Pedro Gonnet's avatar
Pedro Gonnet committed
82

83
84
  /* tag used for MPI communication. */
  int tag;
85

86
87
  /* Relative indices of the cell's progeny. */
  int progeny[8];
88
89

} SWIFT_STRUCT_ALIGN;
90

91
92
93
94
95
/**
 * @brief Cell within the tree structure.
 *
 * Contains particles, links to tasks, a multipole object and counters.
 */
96
97
struct cell {

98
  /*! The cell location on the grid. */
99
100
  double loc[3];

101
  /*! The cell dimensions. */
102
  double width[3];
103

104
  /*! Max smoothing length in this cell. */
105
106
  double h_max;

107
  /*! This cell's multipole. */
108
  struct gravity_tensors *multipole;
109

110
111
  /*! Linking pointer for "memory management". */
  struct cell *next;
112

113
  /*! Pointer to the #part data. */
114
115
  struct part *parts;

116
  /*! Pointer to the #xpart data. */
117
118
  struct xpart *xparts;

119
  /*! Pointer to the #gpart data. */
120
121
  struct gpart *gparts;

122
  /*! Pointer to the #spart data. */
123
  struct spart *sparts;
124

125
  /*! Pointer for the sorted indices. */
126
  struct entry *sort[13];
127

128
  /*! Pointers to the next level of cells. */
129
130
  struct cell *progeny[8];

131
  /*! Parent cell. */
132
133
  struct cell *parent;

134
  /*! Super cell, i.e. the highest-level parent cell that has pair/self tasks */
135
  struct cell *super;
136

137
  /*! The task computing this cell's sorts. */
138
  struct task *sorts;
139

140
141
  /*! Linked list of the tasks computing this cell's hydro density. */
  struct link *density;
142

143
144
  /* Linked list of the tasks computing this cell's hydro gradients. */
  struct link *gradient;
145

146
147
  /*! Linked list of the tasks computing this cell's hydro forces. */
  struct link *force;
148

149
150
  /*! Linked list of the tasks computing this cell's gravity forces. */
  struct link *grav;
151

152
153
154
  /*! The multipole initialistation task */
  struct task *init_grav;

155
  /*! Dependency implicit task for the ghost  (in->ghost->out)*/
156
  struct task *ghost_in;
157
158

  /*! Dependency implicit task for the ghost  (in->ghost->out)*/
159
  struct task *ghost_out;
160
161

  /*! The ghost task itself */
162
  struct task *ghost;
163

164
165
  /*! The extra ghost task for complex hydro schemes */
  struct task *extra_ghost;
166

167
168
169
170
171
  /*! The drift task for parts */
  struct task *drift_part;

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

173
174
175
176
177
  /*! The first kick task */
  struct task *kick1;

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

179
180
  /*! The task to compute time-steps */
  struct task *timestep;
181

182
183
184
  /*! Task linking the FFT mesh to the rest of gravity tasks */
  struct task *grav_ghost[2];

185
  /*! Task computing long range non-periodic gravity interactions */
186
  struct task *grav_long_range;
Tom Theuns's avatar
Tom Theuns committed
187

188
189
  /*! Task propagating the multipole to the particles */
  struct task *grav_down;
190

191
192
  /*! Task for cooling */
  struct task *cooling;
193

194
195
  /*! Task for source terms */
  struct task *sourceterms;
196

197
#ifdef WITH_MPI
198

199
200
  /* Task receiving data (positions). */
  struct task *recv_xv;
201

202
203
  /* Task receiving data (density). */
  struct task *recv_rho;
204

205
206
  /* Task receiving data (gradient). */
  struct task *recv_gradient;
207

208
209
  /* Task receiving data (time-step). */
  struct task *recv_ti;
210

211
212
  /* Linked list for sending data (positions). */
  struct link *send_xv;
213

214
215
  /* Linked list for sending data (density). */
  struct link *send_rho;
216

217
218
219
220
221
  /* Linked list for sending data (gradient). */
  struct link *send_gradient;

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

223
  /*! Bit mask of the proxies this cell is registered with. */
224
225
  unsigned long long int sendto;

226
  /*! Pointer to this cell's packed representation. */
227
  struct pcell *pcell;
228
229

  /*! Size of the packed representation */
230
  int pcell_size;
231
232

  /*! MPI tag associated with this cell */
233
234
  int tag;

235
#endif
236

237
  /*! Minimum end of (integer) time step in this cell. */
238
  integertime_t ti_end_min;
239
240

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

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

246
247
248
249
250
251
  /*! 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;

252
253
254
  /*! Last (integer) time the cell's multipole was drifted forward in time. */
  integertime_t ti_old_multipole;

255
256
257
  /*! Minimum dimension, i.e. smallest edge of this cell (min(width)). */
  float dmin;

258
259
260
  /*! Maximum particle movement in this cell since the last sort. */
  float dx_max_sort;

261
262
263
264
265
266
  /*! 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;

267
268
269
270
271
272
  /*! Nr of #part in this cell. */
  int count;

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

273
274
275
  /*! Nr of #spart in this cell. */
  int scount;

276
277
278
279
280
281
282
283
284
  /*! 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;

285
286
287
  /*! Spin lock for various uses (#multipole case). */
  swift_lock_type mlock;

288
289
290
  /*! Spin lock for various uses (#spart case). */
  swift_lock_type slock;

291
292
293
294
295
296
297
298
299
  /*! 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;

300
301
302
  /*! Number of #spart updated in this cell. */
  int s_updated;

303
304
305
  /*! ID of the node this cell lives on. */
  int nodeID;

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

312
313
314
  /*! Is the #multipole data of this cell being used in a sub-cell? */
  int mhold;

315
316
317
  /*! Is the #spart data of this cell being used in a sub-cell? */
  int shold;

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
  /*! 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;

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

345
  /*! Does this cell need to be drifted (hydro)? */
346
  char do_drift;
347

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

351
352
353
354
355
356
  /*! 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;

357
358
  /*! Do any of this cell's sub-cells need to be sorted? */
  char do_sub_sort;
359

360
#ifdef SWIFT_DEBUG_CHECKS
361
362
363
  /*! Last (integer) time the cell's sort arrays were updated. */
  integertime_t ti_sort;

364
365
366
367
368
369
370
  /*! 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

371
} SWIFT_STRUCT_ALIGN;
372

373
374
375
376
/* Convert cell location to ID. */
#define cell_getid(cdim, i, j, k) \
  ((int)(k) + (cdim)[2] * ((int)(j) + (cdim)[1] * (int)(i)))

377
/* Function prototypes. */
378
379
void cell_split(struct cell *c, ptrdiff_t parts_offset, ptrdiff_t sparts_offset,
                struct cell_buff *buff, struct cell_buff *sbuff,
380
                struct cell_buff *gbuff);
381
void cell_sanitize(struct cell *c, int treated);
382
383
384
385
int cell_locktree(struct cell *c);
void cell_unlocktree(struct cell *c);
int cell_glocktree(struct cell *c);
void cell_gunlocktree(struct cell *c);
386
387
int cell_mlocktree(struct cell *c);
void cell_munlocktree(struct cell *c);
388
389
int cell_slocktree(struct cell *c);
void cell_sunlocktree(struct cell *c);
390
391
int cell_pack(struct cell *c, struct pcell *pc);
int cell_unpack(struct pcell *pc, struct cell *c, struct space *s);
392
393
int cell_pack_ti_ends(struct cell *c, integertime_t *ti_ends);
int cell_unpack_ti_ends(struct cell *c, integertime_t *ti_ends);
394
int cell_getsize(struct cell *c);
395
396
int cell_link_parts(struct cell *c, struct part *parts);
int cell_link_gparts(struct cell *c, struct gpart *gparts);
397
int cell_link_sparts(struct cell *c, struct spart *sparts);
398
void cell_convert_hydro(struct cell *c, void *data);
399
void cell_clean_links(struct cell *c, void *data);
400
void cell_make_multipoles(struct cell *c, integertime_t ti_current);
401
void cell_check_multipole(struct cell *c, void *data);
402
void cell_clean(struct cell *c);
403
404
void cell_check_part_drift_point(struct cell *c, void *data);
void cell_check_gpart_drift_point(struct cell *c, void *data);
405
void cell_check_multipole_drift_point(struct cell *c, void *data);
406
void cell_reset_task_counters(struct cell *c);
407
int cell_unskip_tasks(struct cell *c, struct scheduler *s);
408
void cell_set_super(struct cell *c, struct cell *super);
409
void cell_drift_part(struct cell *c, const struct engine *e, int force);
410
void cell_drift_gpart(struct cell *c, const struct engine *e, int force);
411
void cell_drift_multipole(struct cell *c, const struct engine *e);
412
void cell_drift_all_multipoles(struct cell *c, const struct engine *e);
413
void cell_check_timesteps(struct cell *c);
414
415
416
void cell_store_pre_drift_values(struct cell *c);
void cell_activate_subcell_tasks(struct cell *ci, struct cell *cj,
                                 struct scheduler *s);
417
418
void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj,
                                      struct scheduler *s);
419
420
void cell_activate_subcell_external_grav_tasks(struct cell *ci,
                                               struct scheduler *s);
421
void cell_activate_drift_part(struct cell *c, struct scheduler *s);
422
void cell_activate_drift_gpart(struct cell *c, struct scheduler *s);
423
void cell_activate_sorts(struct cell *c, int sid, struct scheduler *s);
424
void cell_clear_drift_flags(struct cell *c, void *data);
Pedro Gonnet's avatar
Pedro Gonnet committed
425
void cell_set_super_mapper(void *map_data, int num_elements, void *extra_data);
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491

/* 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 */
492
  return c->split && (space_stretch * kernel_gamma * c->h_max < 0.5f * c->dmin);
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
}

/**
 * @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);
}
512
513

#endif /* SWIFT_CELL_H */