cell.h 27.5 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
81
  /*! Hydro variables */
  struct {
Matthieu Schaller's avatar
Matthieu Schaller committed
82

83
84
    /*! Maximal smoothing length. */
    double h_max;
85

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

89
90
    /*! Maximal integer end-of-timestep in this cell for hydro tasks */
    integertime_t ti_end_max;
91

92
93
    /*! Maximal integer beginning-of-timestep in this cell for hydro tasks */
    integertime_t ti_beg_max;
94

95
    /*! Integer time of the last drift of the #part in this cell */
96
    integertime_t ti_old_part;
97

98
99
    /*! Number of #part in this cell. */
    int count;
100

101
  } hydro;
102

103
104
  /*! Gravity variables */
  struct {
105

106
107
    /*! This cell's gravity-related tensors */
    struct multipole m_pole;
108

109
110
    /*! Centre of mass. */
    double CoM[3];
111

112
113
    /*! Centre of mass at rebuild time. */
    double CoM_rebuild[3];
114

115
116
    /*! Upper limit of the CoM<->gpart distance. */
    double r_max;
117

118
119
    /*! Upper limit of the CoM<->gpart distance at last rebuild. */
    double r_max_rebuild;
120

121
122
    /*! Minimal integer end-of-timestep in this cell for gravity tasks */
    integertime_t ti_end_min;
Pedro Gonnet's avatar
Pedro Gonnet committed
123

124
125
    /*! Maximal integer end-of-timestep in this cell for gravity tasks */
    integertime_t ti_end_max;
126

127
128
    /*! Maximal integer beginning-of-timestep in this cell for gravity tasks */
    integertime_t ti_beg_max;
129

130
    /*! Integer time of the last drift of the #gpart in this cell */
131
    integertime_t ti_old_part;
132

133
134
    /*! Integer time of the last drift of the #multipole in this cell */
    integertime_t ti_old_multipole;
135

136
    /*! Number of #gpart in this cell. */
137
    int count;
138
139
140

  } grav;

141
142
143
144
145
146
  /*! Stars variables */
  struct {

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

Loic Hausammann's avatar
Loic Hausammann committed
147
148
149
    /*! Maximal smoothing length. */
    double h_max;

150
151
  } stars;

152
153
  /*! Relative indices of the cell's progeny. */
  int progeny[8];
154

155
156
157
158
159
#ifdef SWIFT_DEBUG_CHECKS
  /* Cell ID (for debugging) */
  int cellID;
#endif

160
} SWIFT_STRUCT_ALIGN;
161

162
163
164
165
166
/**
 * @brief Cell information at the end of a time-step.
 */
struct pcell_step {

167
168
169
170
171
  /*! Hydro variables */
  struct {

    /*! Minimal integer end-of-timestep in this cell (hydro) */
    integertime_t ti_end_min;
172

173
174
    /*! Minimal integer end-of-timestep in this cell (hydro) */
    integertime_t ti_end_max;
175

176
    /*! Maximal distance any #part has travelled since last rebuild */
177
    float dx_max_part;
178

179
  } hydro;
180

181
182
183
184
185
186
187
188
  /*! Grav variables */
  struct {

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

    /*! Minimal integer end-of-timestep in this cell (gravity) */
    integertime_t ti_end_max;
189

190
  } grav;
191
192
193

  /*! Stars variables */
  struct {
Loic Hausammann's avatar
Loic Hausammann committed
194
195
196
197

    /*! Maximal distance any #part has travelled since last rebuild */
    float dx_max_part;

198
  } stars;
199
200
};

201
202
203
204
205
/**
 * @brief Cell within the tree structure.
 *
 * Contains particles, links to tasks, a multipole object and counters.
 */
206
207
struct cell {

Matthieu Schaller's avatar
Matthieu Schaller committed
208
209
210
211
  /* int num_hydro_proxies; */
  /* int num_grav_proxies; */
  /* int num_foreign_pair_hydro; */
  /* int num_foreign_pair_grav; */
212

213
  /*! The cell location on the grid. */
214
215
  double loc[3];

216
  /*! The cell dimensions. */
217
  double width[3];
218

219
220
  /*! Linking pointer for "memory management". */
  struct cell *next;
221

222
  /*! Pointers to the next level of cells. */
223
224
  struct cell *progeny[8];

225
  /*! Parent cell. */
226
227
  struct cell *parent;

228
  /*! Super cell, i.e. the highest-level parent cell with *any* task */
229
  struct cell *super;
230

231
232
  /*! Hydro variables */
  struct {
233

234
235
    /*! Pointer to the #part data. */
    struct part *parts;
236

237
238
    /*! Pointer to the #xpart data. */
    struct xpart *xparts;
239

240
241
    /*! Pointer for the sorted indices. */
    struct entry *sort[13];
242

243
244
    /*! Super cell, i.e. the highest-level parent cell that has a hydro
     * pair/self tasks */
245
    struct cell *super;
246

247
    /*! Last (integer) time the cell's part were drifted forward in time. */
248
    integertime_t ti_old_part;
249

250
    /*! Maximum part movement in this cell since last construction. */
251
    float dx_max_part;
252

253
254
    /*! Maximum particle movement in this cell since the last sort. */
    float dx_max_sort;
255

256
257
    /*! Max smoothing length in this cell. */
    double h_max;
258

259
260
    /*! Minimum end of (integer) time step in this cell for hydro tasks. */
    integertime_t ti_end_min;
261

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

265
266
    /*! Maximum beginning of (integer) time step in this cell for hydro tasks.
     */
267
    integertime_t ti_beg_max;
268

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

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

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

278
279
280
    /*! Number of #part inhibited in this cell. */
    int inhibited;

281
282
    /*! Is the #part data of this cell being used in a sub-cell? */
    int hold;
283

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

287
288
289
    /*! Values of dx_max before the drifts, used for sub-cell tasks. */
    float dx_max_part_old;

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

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

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

299
300
    /*! Does this cell need to be drifted (hydro)? */
    char do_drift;
301

302
303
    /*! Do any of this cell's sub-cells need to be drifted (hydro)? */
    char do_sub_drift;
Tom Theuns's avatar
Tom Theuns committed
304

305
306
    /*! Do any of this cell's sub-cells need to be sorted? */
    char do_sub_sort;
307

308
309
    /*! Bit-mask indicating the sorted directions */
    unsigned int sorted;
310

311
312
    /*! The task computing this cell's sorts. */
    struct task *sorts;
313

314
315
    /*! The drift task for parts */
    struct task *drift;
316

317
318
    /*! Linked list of the tasks computing this cell's hydro density. */
    struct link *density;
Loic Hausammann's avatar
Loic Hausammann committed
319

320
321
    /* Linked list of the tasks computing this cell's hydro gradients. */
    struct link *gradient;
Loic Hausammann's avatar
Loic Hausammann committed
322

323
324
    /*! Linked list of the tasks computing this cell's hydro forces. */
    struct link *force;
Loic Hausammann's avatar
Loic Hausammann committed
325

326
327
    /*! Dependency implicit task for the ghost  (in->ghost->out)*/
    struct task *ghost_in;
328

329
330
    /*! Dependency implicit task for the ghost  (in->ghost->out)*/
    struct task *ghost_out;
331

332
333
334
335
336
337
338
339
    /*! The ghost task itself */
    struct task *ghost;

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

    /*! Task for cooling */
    struct task *cooling;
340

Matthieu Schaller's avatar
Matthieu Schaller committed
341
342
343
    /*! Task for star formation */
    struct task *star_formation;

344
#ifdef SWIFT_DEBUG_CHECKS
345

346
347
    /*! Last (integer) time the cell's sort arrays were updated. */
    integertime_t ti_sort;
348

349
#endif
350

351
  } hydro;
352

353
354
  /*! Grav variables */
  struct {
355

356
    /*! Pointer to the #gpart data. */
357
    struct gpart *parts;
358

359
360
    /*! This cell's multipole. */
    struct gravity_tensors *multipole;
361

362
363
364
    /*! Super cell, i.e. the highest-level parent cell that has a grav pair/self
     * tasks */
    struct cell *super;
365

366
367
    /*! Minimum end of (integer) time step in this cell for gravity tasks. */
    integertime_t ti_end_min;
368

369
370
    /*! Maximum end of (integer) time step in this cell for gravity tasks. */
    integertime_t ti_end_max;
371

372
373
374
    /*! Maximum beginning of (integer) time step in this cell for gravity tasks.
     */
    integertime_t ti_beg_max;
375

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

379
380
    /*! Last (integer) time the cell's multipole was drifted forward in time. */
    integertime_t ti_old_multipole;
381

382
    /*! Nr of #gpart in this cell. */
383
    int count;
384

385
    /*! Spin lock for various uses (#gpart case). */
386
    swift_lock_type plock;
387

388
389
    /*! Spin lock for various uses (#multipole case). */
    swift_lock_type mlock;
390

391
    /*! Number of #gpart updated in this cell. */
392
    int updated;
393

394
395
396
    /*! Number of #gpart inhibited in this cell. */
    int inhibited;

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

400
401
    /*! Is the #multipole data of this cell being used in a sub-cell? */
    int mhold;
402

403
404
    /*! Does this cell need to be drifted (gravity)? */
    char do_drift;
405

406
407
    /*! Do any of this cell's sub-cells need to be drifted (gravity)? */
    char do_sub_drift;
Matthieu Schaller's avatar
Matthieu Schaller committed
408

409
    /*! The drift task for gparts */
410
    struct task *drift;
411

412
413
    /*! Linked list of the tasks computing this cell's gravity forces. */
    struct link *grav;
414

415
416
    /*! Linked list of the tasks computing this cell's gravity M-M forces. */
    struct link *mm;
417

418
419
    /*! The multipole initialistation task */
    struct task *init;
420

421
422
    /*! Implicit task for the gravity initialisation */
    struct task *init_out;
423

424
425
    /*! Task computing long range non-periodic gravity interactions */
    struct task *long_range;
426

427
428
    /*! Implicit task for the down propagation */
    struct task *down_in;
429

430
431
    /*! Task propagating the mesh forces to the particles */
    struct task *mesh;
432

433
434
    /*! Task propagating the multipole to the particles */
    struct task *down;
435

436
437
    /*! Number of M-M tasks that are associated with this cell. */
    short int nr_mm_tasks;
438

439
  } grav;
440

441
442
  /*! Stars variables */
  struct {
443

444
445
    /*! Pointer to the #spart data. */
    struct spart *parts;
446

447
448
    /*! Nr of #spart in this cell. */
    int count;
449

Loic Hausammann's avatar
Loic Hausammann committed
450
451
452
453
454
455
456
457
458
459
460
461
    /*! Max smoothing length in this cell. */
    double h_max;

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

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

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

462
463
    /*! Dependency implicit task for the star ghost  (in->ghost->out)*/
    struct task *ghost_in;
464

465
466
    /*! Dependency implicit task for the star ghost  (in->ghost->out)*/
    struct task *ghost_out;
467

468
469
    /*! The star ghost task itself */
    struct task *ghost;
470

471
472
    /*! Linked list of the tasks computing this cell's star density. */
    struct link *density;
473

474
475
    /*! Number of #spart updated in this cell. */
    int updated;
476

477
478
479
    /*! Number of #spart inhibited in this cell. */
    int inhibited;

480
481
    /*! Is the #spart data of this cell being used in a sub-cell? */
    int hold;
482

483
484
    /*! Spin lock for various uses (#spart case). */
    swift_lock_type lock;
485

486
  } stars;
487

488
489
490
#ifdef WITH_MPI
  /*! MPI variables */
  struct {
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

    struct {
      /* Task receiving hydro data (positions). */
      struct task *recv_xv;

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

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

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

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

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

    } hydro;

    struct {

      /* Task receiving gpart data. */
      struct task *recv;

      /* Linked list for sending gpart data. */
      struct link *send;
    } grav;

522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
    /* Task receiving data (time-step). */
    struct task *recv_ti;

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

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

    /*! Pointer to this cell's packed representation. */
    struct pcell *pcell;

    /*! Size of the packed representation */
    int pcell_size;

    /*! MPI tag associated with this cell */
    int tag;
539

540
541
  } mpi;
#endif
542

543
544
545
  /*! The task to end the force calculation */
  struct task *end_force;

546
547
  /*! The first kick task */
  struct task *kick1;
548

549
550
  /*! The second kick task */
  struct task *kick2;
551

552
553
554
555
556
557
  /*! The task to compute time-steps */
  struct task *timestep;

  /*! Task for source terms */
  struct task *sourceterms;

Loic Hausammann's avatar
Format    
Loic Hausammann committed
558
559
560
  /*! The logger task */
  struct task *logger;

561
562
  /*! Minimum dimension, i.e. smallest edge of this cell (min(width)). */
  float dmin;
563

564
565
566
567
568
569
  /*! ID of the previous owner, e.g. runner. */
  int owner;

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

570
571
572
573
574
575
576
577
578
579
580
581
  /*! 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;

582
#ifdef SWIFT_DEBUG_CHECKS
583
584
585
  /* Cell ID (for debugging) */
  int cellID;

586
587
588
589
590
591
592
  /*! 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

593
} SWIFT_STRUCT_ALIGN;
594

595
596
597
598
/* Convert cell location to ID. */
#define cell_getid(cdim, i, j, k) \
  ((int)(k) + (cdim)[2] * ((int)(j) + (cdim)[1] * (int)(i)))

599
/* Function prototypes. */
600
601
void cell_split(struct cell *c, ptrdiff_t parts_offset, ptrdiff_t sparts_offset,
                struct cell_buff *buff, struct cell_buff *sbuff,
602
                struct cell_buff *gbuff);
603
void cell_sanitize(struct cell *c, int treated);
604
605
606
607
int cell_locktree(struct cell *c);
void cell_unlocktree(struct cell *c);
int cell_glocktree(struct cell *c);
void cell_gunlocktree(struct cell *c);
608
609
int cell_mlocktree(struct cell *c);
void cell_munlocktree(struct cell *c);
610
611
int cell_slocktree(struct cell *c);
void cell_sunlocktree(struct cell *c);
612
int cell_pack(struct cell *c, struct pcell *pc, const int with_gravity);
Matthieu Schaller's avatar
Matthieu Schaller committed
613
614
int cell_unpack(struct pcell *pc, struct cell *c, struct space *s,
                const int with_gravity);
615
616
int cell_pack_tags(const struct cell *c, int *tags);
int cell_unpack_tags(const int *tags, struct cell *c);
617
618
int cell_pack_end_step(struct cell *c, struct pcell_step *pcell);
int cell_unpack_end_step(struct cell *c, struct pcell_step *pcell);
619
620
int cell_pack_multipoles(struct cell *c, struct gravity_tensors *m);
int cell_unpack_multipoles(struct cell *c, struct gravity_tensors *m);
621
int cell_getsize(struct cell *c);
622
623
int cell_link_parts(struct cell *c, struct part *parts);
int cell_link_gparts(struct cell *c, struct gpart *gparts);
624
int cell_link_sparts(struct cell *c, struct spart *sparts);
625
void cell_clean_links(struct cell *c, void *data);
626
void cell_make_multipoles(struct cell *c, integertime_t ti_current);
627
628
void cell_check_multipole(struct cell *c);
void cell_check_foreign_multipole(const struct cell *c);
629
void cell_clean(struct cell *c);
630
631
void cell_check_part_drift_point(struct cell *c, void *data);
void cell_check_gpart_drift_point(struct cell *c, void *data);
632
void cell_check_multipole_drift_point(struct cell *c, void *data);
633
void cell_reset_task_counters(struct cell *c);
634
int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s);
635
int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s);
636
int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s);
637
void cell_set_super(struct cell *c, struct cell *super);
638
void cell_drift_part(struct cell *c, const struct engine *e, int force);
639
void cell_drift_gpart(struct cell *c, const struct engine *e, int force);
640
void cell_drift_multipole(struct cell *c, const struct engine *e);
641
void cell_drift_all_multipoles(struct cell *c, const struct engine *e);
642
void cell_check_timesteps(struct cell *c);
643
void cell_store_pre_drift_values(struct cell *c);
644
645
void cell_activate_subcell_hydro_tasks(struct cell *ci, struct cell *cj,
                                       struct scheduler *s);
646
647
void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj,
                                      struct scheduler *s);
648
649
void cell_activate_subcell_stars_tasks(struct cell *ci, struct cell *cj,
                                       struct scheduler *s);
650
651
void cell_activate_subcell_external_grav_tasks(struct cell *ci,
                                               struct scheduler *s);
652
void cell_activate_drift_part(struct cell *c, struct scheduler *s);
653
void cell_activate_drift_gpart(struct cell *c, struct scheduler *s);
654
void cell_activate_sorts(struct cell *c, int sid, struct scheduler *s);
655
void cell_clear_drift_flags(struct cell *c, void *data);
Pedro Gonnet's avatar
Pedro Gonnet committed
656
void cell_set_super_mapper(void *map_data, int num_elements, void *extra_data);
657
int cell_has_tasks(struct cell *c);
658
659
void cell_remove_part(const struct engine *e, struct cell *c, struct part *p,
                      struct xpart *xp);
660
661
662
663
void cell_remove_gpart(const struct engine *e, struct cell *c,
                       struct gpart *gp);
void cell_remove_spart(const struct engine *e, struct cell *c,
                       struct spart *sp);
664
665
666
void cell_convert_part_to_gpart(const struct engine *e, struct cell *c,
                                struct part *p, struct xpart *xp);
void cell_convert_spart_to_gpart(const struct engine *e, struct cell *c,
667
                                 struct spart *sp);
668
669
int cell_can_use_pair_mm(const struct cell *ci, const struct cell *cj,
                         const struct engine *e, const struct space *s);
670
int cell_can_use_pair_mm_rebuild(const struct cell *ci, const struct cell *cj,
Matthieu Schaller's avatar
Matthieu Schaller committed
671
                                 const struct engine *e, const struct space *s);
672

673
/**
Matthieu Schaller's avatar
Matthieu Schaller committed
674
675
 * @brief Compute the sqaure of the minimal distance between any two points in
 * two cells of the same size
676
677
678
679
680
681
 *
 * @param ci The first #cell.
 * @param cj The second #cell.
 * @param periodic Are we using periodic BCs?
 * @param dim The dimensions of the simulation volume
 */
Matthieu Schaller's avatar
Matthieu Schaller committed
682
683
684
__attribute__((always_inline)) INLINE static double cell_min_dist2_same_size(
    const struct cell *restrict ci, const struct cell *restrict cj,
    const int periodic, const double dim[3]) {
685
686

#ifdef SWIFT_DEBUG_CHECKS
Matthieu Schaller's avatar
Matthieu Schaller committed
687
688
689
  if (ci->width[0] != cj->width[0]) error("Cells of different size!");
  if (ci->width[1] != cj->width[1]) error("Cells of different size!");
  if (ci->width[2] != cj->width[2]) error("Cells of different size!");
690
691
#endif

Matthieu Schaller's avatar
Matthieu Schaller committed
692
693
694
695
696
697
698
699
700
701
702
703
  const double cix_min = ci->loc[0];
  const double ciy_min = ci->loc[1];
  const double ciz_min = ci->loc[2];
  const double cjx_min = cj->loc[0];
  const double cjy_min = cj->loc[1];
  const double cjz_min = cj->loc[2];

  const double cix_max = ci->loc[0] + ci->width[0];
  const double ciy_max = ci->loc[1] + ci->width[1];
  const double ciz_max = ci->loc[2] + ci->width[2];
  const double cjx_max = cj->loc[0] + cj->width[0];
  const double cjy_max = cj->loc[1] + cj->width[1];
704
705
706
707
708
  const double cjz_max = cj->loc[2] + cj->width[2];

  if (periodic) {

    const double dx = min4(fabs(nearest(cix_min - cjx_min, dim[0])),
Matthieu Schaller's avatar
Matthieu Schaller committed
709
710
711
712
                           fabs(nearest(cix_min - cjx_max, dim[0])),
                           fabs(nearest(cix_max - cjx_min, dim[0])),
                           fabs(nearest(cix_max - cjx_max, dim[0])));

713
    const double dy = min4(fabs(nearest(ciy_min - cjy_min, dim[1])),
Matthieu Schaller's avatar
Matthieu Schaller committed
714
715
716
717
                           fabs(nearest(ciy_min - cjy_max, dim[1])),
                           fabs(nearest(ciy_max - cjy_min, dim[1])),
                           fabs(nearest(ciy_max - cjy_max, dim[1])));

718
    const double dz = min4(fabs(nearest(ciz_min - cjz_min, dim[2])),
Matthieu Schaller's avatar
Matthieu Schaller committed
719
720
721
722
                           fabs(nearest(ciz_min - cjz_max, dim[2])),
                           fabs(nearest(ciz_max - cjz_min, dim[2])),
                           fabs(nearest(ciz_max - cjz_max, dim[2])));

723
724
725
726
    return dx * dx + dy * dy + dz * dz;

  } else {

Matthieu Schaller's avatar
Matthieu Schaller committed
727
728
729
    const double dx = min(fabs(cix_max - cjx_min), fabs(cix_min - cjx_max));
    const double dy = min(fabs(ciy_max - cjy_min), fabs(ciy_min - cjy_max));
    const double dz = min(fabs(ciz_max - cjz_min), fabs(ciz_min - cjz_max));
730
731
732
733
734

    return dx * dx + dy * dy + dz * dz;
  }
}

735
736
737
738
739
740
741
742
/* 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
743
744
__attribute__((always_inline)) INLINE static int
cell_can_recurse_in_pair_hydro_task(const struct cell *c) {
745
746
747
748
749

  /* 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 */
750
  return c->split && ((kernel_gamma * c->hydro.h_max_old +
751
                       c->hydro.dx_max_part_old) < 0.5f * c->dmin);
752
753
754
755
756
757
758
759
}

/**
 * @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
760
761
__attribute__((always_inline)) INLINE static int
cell_can_recurse_in_self_hydro_task(const struct cell *c) {
762

763
  /* Is the cell split and not smaller than the smoothing length? */
764
  return c->split && (kernel_gamma * c->hydro.h_max_old < 0.5f * c->dmin);
765
766
}

767
768
769
770
771
772
773
774
775
/**
 * @brief Can a sub-pair star 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_stars_task(const struct cell *c) {

Loic Hausammann's avatar
Loic Hausammann committed
776
777
778
779
780
781
  /* 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->stars.h_max_old +
                       c->stars.dx_max_part_old) < 0.5f * c->dmin);
782
783
784
785
786
787
788
789
790
791
792
}

/**
 * @brief Can a sub-self stars 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_stars_task(const struct cell *c) {

Loic Hausammann's avatar
Loic Hausammann committed
793
794
  /* Is the cell split and not smaller than the smoothing length? */
  return c->split && (kernel_gamma * c->stars.h_max_old < 0.5f * c->dmin);
795
796
}

797
/**
798
 * @brief Can a pair hydro task associated with a cell be split into smaller
799
800
801
802
 * sub-tasks.
 *
 * @param c The #cell.
 */
803
__attribute__((always_inline)) INLINE static int cell_can_split_pair_hydro_task(
804
805
806
807
808
809
810
    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) */
811
812
  return c->split &&
         (space_stretch * kernel_gamma * c->hydro.h_max < 0.5f * c->dmin);
813
814
815
}

/**
816
 * @brief Can a self hydro task associated with a cell be split into smaller
817
818
819
820
 * sub-tasks.
 *
 * @param c The #cell.
 */
821
__attribute__((always_inline)) INLINE static int cell_can_split_self_hydro_task(
822
823
824
    const struct cell *c) {

  /* Is the cell split ? */
825
826
  /* If so, is the cut-off radius with some leeway smaller than */
  /* the sub-cell sizes ? */
827
828
  /* 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 */
829
830
  return c->split &&
         (space_stretch * kernel_gamma * c->hydro.h_max < 0.5f * c->dmin);
831
832
}

833
834
835
836
837
838
839
840
841
/**
 * @brief Can a pair stars 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_stars_task(
    const struct cell *c) {

Loic Hausammann's avatar
Loic Hausammann committed
842
843
844
845
846
847
848
  /* 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->stars.h_max < 0.5f * c->dmin);
849
850
851
852
853
854
855
856
857
858
859
}

/**
 * @brief Can a self stars 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_stars_task(
    const struct cell *c) {

Loic Hausammann's avatar
Loic Hausammann committed
860
861
862
863
864
865
866
  /* Is the cell split ? */
  /* If so, is the cut-off radius with some leeway smaller than */
  /* the sub-cell sizes ? */
  /* 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 */
  return c->split &&
         (space_stretch * kernel_gamma * c->stars.h_max < 0.5f * c->dmin);
867
868
}

869
870
871
872
873
874
/**
 * @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
875
876
__attribute__((always_inline)) INLINE static int
cell_can_split_pair_gravity_task(const struct cell *c) {
877
878

  /* Is the cell split ? */
879
  return c->split && c->depth < space_subdepth_grav;
880
881
882
883
884
885
886
887
}

/**
 * @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
888
889
__attribute__((always_inline)) INLINE static int
cell_can_split_self_gravity_task(const struct cell *c) {
890
891

  /* Is the cell split ? */
892
  return c->split && c->depth < space_subdepth_grav;
893
894
}

895
896
897
898
899
900
901
902
903
904
905
906
907
/**
 * @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 */
908
  return (kernel_gamma * max(ci->hydro.h_max, cj->hydro.h_max) +
909
              ci->hydro.dx_max_part + cj->hydro.dx_max_part >
910
911
          cj->dmin);
}
912

913
/**
914
915
916
 * @brief Add a unique tag to a cell mostly for MPI communications.
 *
 * @param c The #cell to tag.
917
 */
918
__attribute__((always_inline)) INLINE static void cell_tag(struct cell *c) {
919
#ifdef WITH_MPI
920
921

#ifdef SWIFT_DEBUG_CHECKS
922
  if (c->mpi.tag > 0) error("setting tag for already tagged cell");
923
924
#endif

925
926
  if (c->mpi.tag < 0 &&
      (c->mpi.tag = atomic_inc(&cell_next_tag)) > cell_max_tag)
927
928
929
930
931
932
    error("Ran out of cell tags.");
#else
  error("SWIFT was not compiled with MPI enabled.");
#endif  // WITH_MPI
}

933
#endif /* SWIFT_CELL_H */