Commit fd900519 authored by Matthieu Schaller's avatar Matthieu Schaller
Browse files

Merge branch 'rebuild_criteria' into 'master'

Rebuild criteria

Instead of rebuilding whenever the cell constraints or sort indices are violated, just re-sort in case of the latter.

This lead to some other changes:

 * Init tasks are gone, particle initialization is now handled in the drift tasks,
 * Drift tasks no longer act on the super-cell, but exist at every level similar to the sort tasks,
 * Fixed several dependency issues with sort and drift tasks,
 * Only drift/sort on-demand in the sub-cell tasks.

Marked as [WIP] as this has not yet been tested for MPI runs, or with gravity.

See merge request !327
parents 5144801d 95610eb8
...@@ -637,7 +637,7 @@ int main(int argc, char *argv[]) { ...@@ -637,7 +637,7 @@ int main(int argc, char *argv[]) {
for (int k = 0; k < timer_count; k++) for (int k = 0; k < timer_count; k++)
printf("%.3f\t", clocks_from_ticks(timers[k])); printf("%.3f\t", clocks_from_ticks(timers[k]));
printf("\n"); printf("\n");
timers_reset(0xFFFFFFFFllu); timers_reset(timers_mask_all);
} }
#ifdef SWIFT_DEBUG_TASKS #ifdef SWIFT_DEBUG_TASKS
......
...@@ -129,6 +129,7 @@ int cell_unpack(struct pcell *pc, struct cell *c, struct space *s) { ...@@ -129,6 +129,7 @@ int cell_unpack(struct pcell *pc, struct cell *c, struct space *s) {
temp->depth = c->depth + 1; temp->depth = c->depth + 1;
temp->split = 0; temp->split = 0;
temp->dx_max = 0.f; temp->dx_max = 0.f;
temp->dx_max_sort = 0.f;
temp->nodeID = c->nodeID; temp->nodeID = c->nodeID;
temp->parent = c; temp->parent = c;
c->progeny[k] = temp; c->progeny[k] = temp;
...@@ -1306,28 +1307,45 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) { ...@@ -1306,28 +1307,45 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) {
/* Un-skip the density tasks involved with this cell. */ /* Un-skip the density tasks involved with this cell. */
for (struct link *l = c->density; l != NULL; l = l->next) { for (struct link *l = c->density; l != NULL; l = l->next) {
struct task *t = l->t; struct task *t = l->t;
const struct cell *ci = t->ci; struct cell *ci = t->ci;
const struct cell *cj = t->cj; struct cell *cj = t->cj;
scheduler_activate(s, t); scheduler_activate(s, t);
/* Set the correct sorting flags */ /* Set the correct sorting flags */
if (t->type == task_type_pair) { if (t->type == task_type_pair) {
if (ci->dx_max_sort > space_maxreldx * ci->dmin) {
for (struct cell *finger = ci; finger != NULL; finger = finger->parent)
finger->sorted = 0;
}
if (cj->dx_max_sort > space_maxreldx * cj->dmin) {
for (struct cell *finger = cj; finger != NULL; finger = finger->parent)
finger->sorted = 0;
}
if (!(ci->sorted & (1 << t->flags))) { if (!(ci->sorted & (1 << t->flags))) {
atomic_or(&ci->sorts->flags, (1 << t->flags)); #ifdef SWIFT_DEBUG_CHECKS
if (!(ci->sorts->flags & (1 << t->flags)))
error("bad flags in sort task.");
#endif
scheduler_activate(s, ci->sorts); scheduler_activate(s, ci->sorts);
if (ci->nodeID == engine_rank) scheduler_activate(s, ci->drift);
} }
if (!(cj->sorted & (1 << t->flags))) { if (!(cj->sorted & (1 << t->flags))) {
atomic_or(&cj->sorts->flags, (1 << t->flags)); #ifdef SWIFT_DEBUG_CHECKS
if (!(cj->sorts->flags & (1 << t->flags)))
error("bad flags in sort task.");
#endif
scheduler_activate(s, cj->sorts); scheduler_activate(s, cj->sorts);
if (cj->nodeID == engine_rank) scheduler_activate(s, cj->drift);
} }
} }
/* Check whether there was too much particle motion */ /* Only interested in pair interactions as of here. */
if (t->type == task_type_pair || t->type == task_type_sub_pair) { if (t->type == task_type_pair || t->type == task_type_sub_pair) {
/* Check whether there was too much particle motion, i.e. the
cell neighbour conditions were violated. */
if (t->tight && if (t->tight &&
(max(ci->h_max, cj->h_max) + ci->dx_max + cj->dx_max > cj->dmin || max(ci->h_max, cj->h_max) + ci->dx_max + cj->dx_max > cj->dmin)
ci->dx_max > space_maxreldx * ci->h_max ||
cj->dx_max > space_maxreldx * cj->h_max))
rebuild = 1; rebuild = 1;
#ifdef WITH_MPI #ifdef WITH_MPI
...@@ -1349,10 +1367,12 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) { ...@@ -1349,10 +1367,12 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) {
if (l == NULL) error("Missing link to send_xv task."); if (l == NULL) error("Missing link to send_xv task.");
scheduler_activate(s, l->t); scheduler_activate(s, l->t);
if (cj->super->drift) /* Drift both cells, the foreign one at the level which it is sent. */
scheduler_activate(s, cj->super->drift); if (l->t->ci->drift)
scheduler_activate(s, l->t->ci->drift);
else else
error("Drift task missing !"); error("Drift task missing !");
if (t->type == task_type_pair) scheduler_activate(s, cj->drift);
if (cell_is_active(cj, e)) { if (cell_is_active(cj, e)) {
for (l = cj->send_rho; l != NULL && l->t->cj->nodeID != ci->nodeID; for (l = cj->send_rho; l != NULL && l->t->cj->nodeID != ci->nodeID;
...@@ -1385,10 +1405,12 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) { ...@@ -1385,10 +1405,12 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) {
if (l == NULL) error("Missing link to send_xv task."); if (l == NULL) error("Missing link to send_xv task.");
scheduler_activate(s, l->t); scheduler_activate(s, l->t);
if (ci->super->drift) /* Drift both cells, the foreign one at the level which it is sent. */
scheduler_activate(s, ci->super->drift); if (l->t->ci->drift)
scheduler_activate(s, l->t->ci->drift);
else else
error("Drift task missing !"); error("Drift task missing !");
if (t->type == task_type_pair) scheduler_activate(s, ci->drift);
if (cell_is_active(ci, e)) { if (cell_is_active(ci, e)) {
for (l = ci->send_rho; l != NULL && l->t->cj->nodeID != cj->nodeID; for (l = ci->send_rho; l != NULL && l->t->cj->nodeID != cj->nodeID;
...@@ -1403,6 +1425,14 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) { ...@@ -1403,6 +1425,14 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) {
if (l == NULL) error("Missing link to send_ti task."); if (l == NULL) error("Missing link to send_ti task.");
scheduler_activate(s, l->t); scheduler_activate(s, l->t);
} }
} else if (t->type == task_type_pair) {
scheduler_activate(s, ci->drift);
scheduler_activate(s, cj->drift);
}
#else
if (t->type == task_type_pair) {
scheduler_activate(s, ci->drift);
scheduler_activate(s, cj->drift);
} }
#endif #endif
} }
...@@ -1417,7 +1447,6 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) { ...@@ -1417,7 +1447,6 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) {
scheduler_activate(s, l->t); scheduler_activate(s, l->t);
if (c->extra_ghost != NULL) scheduler_activate(s, c->extra_ghost); if (c->extra_ghost != NULL) scheduler_activate(s, c->extra_ghost);
if (c->ghost != NULL) scheduler_activate(s, c->ghost); if (c->ghost != NULL) scheduler_activate(s, c->ghost);
if (c->init != NULL) scheduler_activate(s, c->init);
if (c->init_grav != NULL) scheduler_activate(s, c->init_grav); if (c->init_grav != NULL) scheduler_activate(s, c->init_grav);
if (c->drift != NULL) scheduler_activate(s, c->drift); if (c->drift != NULL) scheduler_activate(s, c->drift);
if (c->kick1 != NULL) scheduler_activate(s, c->kick1); if (c->kick1 != NULL) scheduler_activate(s, c->kick1);
...@@ -1471,7 +1500,9 @@ void cell_drift_particles(struct cell *c, const struct engine *e) { ...@@ -1471,7 +1500,9 @@ void cell_drift_particles(struct cell *c, const struct engine *e) {
/* Drift from the last time the cell was drifted to the current time */ /* Drift from the last time the cell was drifted to the current time */
const double dt = (ti_current - ti_old) * timeBase; const double dt = (ti_current - ti_old) * timeBase;
float dx_max = 0.f, dx2_max = 0.f, cell_h_max = 0.f; float dx_max = 0.f, dx2_max = 0.f;
float dx_max_sort = 0.0f, dx2_max_sort = 0.f;
float cell_h_max = 0.f;
/* Check that we are actually going to move forward. */ /* Check that we are actually going to move forward. */
if (ti_current < ti_old) error("Attempt to drift to the past"); if (ti_current < ti_old) error("Attempt to drift to the past");
...@@ -1483,8 +1514,13 @@ void cell_drift_particles(struct cell *c, const struct engine *e) { ...@@ -1483,8 +1514,13 @@ void cell_drift_particles(struct cell *c, const struct engine *e) {
for (int k = 0; k < 8; k++) for (int k = 0; k < 8; k++)
if (c->progeny[k] != NULL) { if (c->progeny[k] != NULL) {
struct cell *cp = c->progeny[k]; struct cell *cp = c->progeny[k];
/* Collect */
cell_drift_particles(cp, e); cell_drift_particles(cp, e);
/* Update */
dx_max = max(dx_max, cp->dx_max); dx_max = max(dx_max, cp->dx_max);
dx_max_sort = max(dx_max_sort, cp->dx_max_sort);
cell_h_max = max(cell_h_max, cp->h_max); cell_h_max = max(cell_h_max, cp->h_max);
} }
...@@ -1505,6 +1541,11 @@ void cell_drift_particles(struct cell *c, const struct engine *e) { ...@@ -1505,6 +1541,11 @@ void cell_drift_particles(struct cell *c, const struct engine *e) {
gp->x_diff[1] * gp->x_diff[1] + gp->x_diff[1] * gp->x_diff[1] +
gp->x_diff[2] * gp->x_diff[2]; gp->x_diff[2] * gp->x_diff[2];
dx2_max = max(dx2_max, dx2); dx2_max = max(dx2_max, dx2);
/* Init gravity force fields. */
if (gpart_is_active(gp, e)) {
gravity_init_gpart(gp);
}
} }
/* Loop over all the gas particles in the cell */ /* Loop over all the gas particles in the cell */
...@@ -1526,9 +1567,18 @@ void cell_drift_particles(struct cell *c, const struct engine *e) { ...@@ -1526,9 +1567,18 @@ void cell_drift_particles(struct cell *c, const struct engine *e) {
xp->x_diff[1] * xp->x_diff[1] + xp->x_diff[1] * xp->x_diff[1] +
xp->x_diff[2] * xp->x_diff[2]; xp->x_diff[2] * xp->x_diff[2];
dx2_max = max(dx2_max, dx2); dx2_max = max(dx2_max, dx2);
const float dx2_sort = xp->x_diff_sort[0] * xp->x_diff_sort[0] +
xp->x_diff_sort[1] * xp->x_diff_sort[1] +
xp->x_diff_sort[2] * xp->x_diff_sort[2];
dx2_max_sort = max(dx2_max_sort, dx2_sort);
/* Maximal smoothing length */ /* Maximal smoothing length */
cell_h_max = max(cell_h_max, p->h); cell_h_max = max(cell_h_max, p->h);
/* Get ready for a density calculation */
if (part_is_active(p, e)) {
hydro_init_part(p, &e->s->hs);
}
} }
/* Loop over all the star particles in the cell */ /* Loop over all the star particles in the cell */
...@@ -1546,16 +1596,19 @@ void cell_drift_particles(struct cell *c, const struct engine *e) { ...@@ -1546,16 +1596,19 @@ void cell_drift_particles(struct cell *c, const struct engine *e) {
/* Now, get the maximal particle motion from its square */ /* Now, get the maximal particle motion from its square */
dx_max = sqrtf(dx2_max); dx_max = sqrtf(dx2_max);
dx_max_sort = sqrtf(dx2_max_sort);
} else { } else {
cell_h_max = c->h_max; cell_h_max = c->h_max;
dx_max = c->dx_max; dx_max = c->dx_max;
dx_max_sort = c->dx_max_sort;
} }
/* Store the values */ /* Store the values */
c->h_max = cell_h_max; c->h_max = cell_h_max;
c->dx_max = dx_max; c->dx_max = dx_max;
c->dx_max_sort = dx_max_sort;
/* Update the time of the last drift */ /* Update the time of the last drift */
c->ti_old = ti_current; c->ti_old = ti_current;
......
...@@ -148,9 +148,6 @@ struct cell { ...@@ -148,9 +148,6 @@ struct cell {
/*! Linked list of the tasks computing this cell's gravity forces. */ /*! Linked list of the tasks computing this cell's gravity forces. */
struct link *grav; struct link *grav;
/*! The particle initialistation task */
struct task *init;
/*! The multipole initialistation task */ /*! The multipole initialistation task */
struct task *init_grav; struct task *init_grav;
...@@ -239,6 +236,9 @@ struct cell { ...@@ -239,6 +236,9 @@ struct cell {
/*! Last (integer) time the cell's particle was drifted forward in time. */ /*! Last (integer) time the cell's particle was drifted forward in time. */
integertime_t ti_old; integertime_t ti_old;
/*! Last (integer) time the cell's sort arrays were updated. */
integertime_t ti_sort;
/*! Last (integer) time the cell's multipole was drifted forward in time. */ /*! Last (integer) time the cell's multipole was drifted forward in time. */
integertime_t ti_old_multipole; integertime_t ti_old_multipole;
...@@ -248,6 +248,9 @@ struct cell { ...@@ -248,6 +248,9 @@ struct cell {
/*! Maximum particle movement in this cell since last construction. */ /*! Maximum particle movement in this cell since last construction. */
float dx_max; float dx_max;
/*! Maximum particle movement in this cell since the last sort. */
float dx_max_sort;
/*! Nr of #part in this cell. */ /*! Nr of #part in this cell. */
int count; int count;
......
...@@ -101,10 +101,12 @@ __attribute__((always_inline)) INLINE static void drift_part( ...@@ -101,10 +101,12 @@ __attribute__((always_inline)) INLINE static void drift_part(
/* Predict the values of the extra fields */ /* Predict the values of the extra fields */
hydro_predict_extra(p, xp, dt); hydro_predict_extra(p, xp, dt);
/* Compute offset since last cell construction */ /* Compute offsets since last cell construction */
xp->x_diff[0] -= xp->v_full[0] * dt; for (int k = 0; k < 3; k++) {
xp->x_diff[1] -= xp->v_full[1] * dt; const float dx = xp->v_full[k] * dt;
xp->x_diff[2] -= xp->v_full[2] * dt; xp->x_diff[k] -= dx;
xp->x_diff_sort[k] -= dx;
}
} }
/** /**
......
...@@ -144,10 +144,6 @@ void engine_make_hierarchical_tasks(struct engine *e, struct cell *c) { ...@@ -144,10 +144,6 @@ void engine_make_hierarchical_tasks(struct engine *e, struct cell *c) {
/* Local tasks only... */ /* Local tasks only... */
if (c->nodeID == e->nodeID) { if (c->nodeID == e->nodeID) {
/* Add the init task. */
c->init = scheduler_addtask(s, task_type_init, task_subtype_none, 0, 0, c,
NULL, 0);
/* Add the two half kicks */ /* Add the two half kicks */
c->kick1 = scheduler_addtask(s, task_type_kick1, task_subtype_none, 0, 0, c->kick1 = scheduler_addtask(s, task_type_kick1, task_subtype_none, 0, 0,
c, NULL, 0); c, NULL, 0);
...@@ -162,12 +158,6 @@ void engine_make_hierarchical_tasks(struct engine *e, struct cell *c) { ...@@ -162,12 +158,6 @@ void engine_make_hierarchical_tasks(struct engine *e, struct cell *c) {
scheduler_addunlock(s, c->kick2, c->timestep); scheduler_addunlock(s, c->kick2, c->timestep);
scheduler_addunlock(s, c->timestep, c->kick1); scheduler_addunlock(s, c->timestep, c->kick1);
/* Add the drift task and its dependencies. */
c->drift = scheduler_addtask(s, task_type_drift, task_subtype_none, 0, 0,
c, NULL, 0);
scheduler_addunlock(s, c->drift, c->init);
if (is_self_gravity) { if (is_self_gravity) {
/* Initialisation of the multipoles */ /* Initialisation of the multipoles */
...@@ -1020,10 +1010,6 @@ void engine_addtasks_send(struct engine *e, struct cell *ci, struct cell *cj, ...@@ -1020,10 +1010,6 @@ void engine_addtasks_send(struct engine *e, struct cell *ci, struct cell *cj,
/* Create the tasks and their dependencies? */ /* Create the tasks and their dependencies? */
if (t_xv == NULL) { if (t_xv == NULL) {
if (ci->super->drift == NULL)
ci->super->drift = scheduler_addtask(
s, task_type_drift, task_subtype_none, 0, 0, ci->super, NULL, 0);
t_xv = scheduler_addtask(s, task_type_send, task_subtype_xv, 4 * ci->tag, t_xv = scheduler_addtask(s, task_type_send, task_subtype_xv, 4 * ci->tag,
0, ci, cj, 0); 0, ci, cj, 0);
t_rho = scheduler_addtask(s, task_type_send, task_subtype_rho, t_rho = scheduler_addtask(s, task_type_send, task_subtype_rho,
...@@ -1063,7 +1049,10 @@ void engine_addtasks_send(struct engine *e, struct cell *ci, struct cell *cj, ...@@ -1063,7 +1049,10 @@ void engine_addtasks_send(struct engine *e, struct cell *ci, struct cell *cj,
#endif #endif
/* Drift before you send */ /* Drift before you send */
scheduler_addunlock(s, ci->super->drift, t_xv); if (ci->drift == NULL)
ci->drift = scheduler_addtask(s, task_type_drift, task_subtype_none, 0,
0, ci, NULL, 0);
scheduler_addunlock(s, ci->drift, t_xv);
/* The super-cell's timestep task should unlock the send_ti task. */ /* The super-cell's timestep task should unlock the send_ti task. */
scheduler_addunlock(s, ci->super->timestep, t_ti); scheduler_addunlock(s, ci->super->timestep, t_ti);
...@@ -1816,15 +1805,22 @@ void engine_count_and_link_tasks(struct engine *e) { ...@@ -1816,15 +1805,22 @@ void engine_count_and_link_tasks(struct engine *e) {
struct cell *const ci = t->ci; struct cell *const ci = t->ci;
struct cell *const cj = t->cj; struct cell *const cj = t->cj;
/* Link sort tasks together. */ /* Link sort tasks to the next-higher sort task. */
if (t->type == task_type_sort && ci->split) if (t->type == task_type_sort) {
for (int j = 0; j < 8; j++) struct cell *finger = t->ci->parent;
if (ci->progeny[j] != NULL && ci->progeny[j]->sorts != NULL) { while (finger != NULL && finger->sorts == NULL) finger = finger->parent;
scheduler_addunlock(sched, ci->progeny[j]->sorts, t); if (finger != NULL) scheduler_addunlock(sched, t, finger->sorts);
} }
/* Link drift tasks to the next-higher drift task. */
else if (t->type == task_type_drift) {
struct cell *finger = ci->parent;
while (finger != NULL && finger->drift == NULL) finger = finger->parent;
if (finger != NULL) scheduler_addunlock(sched, t, finger->drift);
}
/* Link self tasks to cells. */ /* Link self tasks to cells. */
if (t->type == task_type_self) { else if (t->type == task_type_self) {
atomic_inc(&ci->nr_tasks); atomic_inc(&ci->nr_tasks);
if (t->subtype == task_subtype_density) { if (t->subtype == task_subtype_density) {
engine_addlink(e, &ci->density, t); engine_addlink(e, &ci->density, t);
...@@ -1895,7 +1891,6 @@ static inline void engine_make_self_gravity_dependencies( ...@@ -1895,7 +1891,6 @@ static inline void engine_make_self_gravity_dependencies(
struct scheduler *sched, struct task *gravity, struct cell *c) { struct scheduler *sched, struct task *gravity, struct cell *c) {
/* init --> gravity --> grav_down --> kick */ /* init --> gravity --> grav_down --> kick */
scheduler_addunlock(sched, c->super->init, gravity);
scheduler_addunlock(sched, c->super->init_grav, gravity); scheduler_addunlock(sched, c->super->init_grav, gravity);
scheduler_addunlock(sched, gravity, c->super->grav_down); scheduler_addunlock(sched, gravity, c->super->grav_down);
} }
...@@ -1912,7 +1907,7 @@ static inline void engine_make_external_gravity_dependencies( ...@@ -1912,7 +1907,7 @@ static inline void engine_make_external_gravity_dependencies(
struct scheduler *sched, struct task *gravity, struct cell *c) { struct scheduler *sched, struct task *gravity, struct cell *c) {
/* init --> external gravity --> kick */ /* init --> external gravity --> kick */
scheduler_addunlock(sched, c->super->init, gravity); scheduler_addunlock(sched, c->drift, gravity);
scheduler_addunlock(sched, gravity, c->super->kick2); scheduler_addunlock(sched, gravity, c->super->kick2);
} }
...@@ -2008,9 +2003,8 @@ static inline void engine_make_hydro_loops_dependencies( ...@@ -2008,9 +2003,8 @@ static inline void engine_make_hydro_loops_dependencies(
struct scheduler *sched, struct task *density, struct task *gradient, struct scheduler *sched, struct task *density, struct task *gradient,
struct task *force, struct cell *c, int with_cooling) { struct task *force, struct cell *c, int with_cooling) {
/* init --> density loop --> ghost --> gradient loop --> extra_ghost */ /* density loop --> ghost --> gradient loop --> extra_ghost */
/* extra_ghost --> force loop */ /* extra_ghost --> force loop */
scheduler_addunlock(sched, c->super->init, density);
scheduler_addunlock(sched, density, c->super->ghost); scheduler_addunlock(sched, density, c->super->ghost);
scheduler_addunlock(sched, c->super->ghost, gradient); scheduler_addunlock(sched, c->super->ghost, gradient);
scheduler_addunlock(sched, gradient, c->super->extra_ghost); scheduler_addunlock(sched, gradient, c->super->extra_ghost);
...@@ -2041,8 +2035,7 @@ static inline void engine_make_hydro_loops_dependencies(struct scheduler *sched, ...@@ -2041,8 +2035,7 @@ static inline void engine_make_hydro_loops_dependencies(struct scheduler *sched,
struct task *force, struct task *force,
struct cell *c, struct cell *c,
int with_cooling) { int with_cooling) {
/* init --> density loop --> ghost --> force loop */ /* density loop --> ghost --> force loop */
scheduler_addunlock(sched, c->super->init, density);
scheduler_addunlock(sched, density, c->super->ghost); scheduler_addunlock(sched, density, c->super->ghost);
scheduler_addunlock(sched, c->super->ghost, force); scheduler_addunlock(sched, c->super->ghost, force);
...@@ -2078,8 +2071,16 @@ void engine_make_extra_hydroloop_tasks(struct engine *e) { ...@@ -2078,8 +2071,16 @@ void engine_make_extra_hydroloop_tasks(struct engine *e) {
for (int ind = 0; ind < nr_tasks; ind++) { for (int ind = 0; ind < nr_tasks; ind++) {
struct task *t = &sched->tasks[ind]; struct task *t = &sched->tasks[ind];
/* Sort tasks depend on the drift of the cell. */
if (t->type == task_type_sort && t->ci->nodeID == engine_rank) {
scheduler_addunlock(sched, t->ci->drift, t);
}
/* Self-interaction? */ /* Self-interaction? */
if (t->type == task_type_self && t->subtype == task_subtype_density) { else if (t->type == task_type_self && t->subtype == task_subtype_density) {
/* Make all density tasks depend on the drift. */
scheduler_addunlock(sched, t->ci->drift, t);
#ifdef EXTRA_HYDRO_LOOP #ifdef EXTRA_HYDRO_LOOP
/* Start by constructing the task for the second and third hydro loop */ /* Start by constructing the task for the second and third hydro loop */
...@@ -2113,6 +2114,12 @@ void engine_make_extra_hydroloop_tasks(struct engine *e) { ...@@ -2113,6 +2114,12 @@ void engine_make_extra_hydroloop_tasks(struct engine *e) {
/* Otherwise, pair interaction? */ /* Otherwise, pair interaction? */
else if (t->type == task_type_pair && t->subtype == task_subtype_density) { else if (t->type == task_type_pair && t->subtype == task_subtype_density) {
/* Make all density tasks depend on the drift. */
if (t->ci->nodeID == engine_rank)
scheduler_addunlock(sched, t->ci->drift, t);
if (t->cj->nodeID == engine_rank)
scheduler_addunlock(sched, t->cj->drift, t);
#ifdef EXTRA_HYDRO_LOOP #ifdef EXTRA_HYDRO_LOOP
/* Start by constructing the task for the second and third hydro loop */ /* Start by constructing the task for the second and third hydro loop */
struct task *t2 = scheduler_addtask( struct task *t2 = scheduler_addtask(
...@@ -2290,6 +2297,21 @@ void engine_make_gravityrecursive_tasks(struct engine *e) { ...@@ -2290,6 +2297,21 @@ void engine_make_gravityrecursive_tasks(struct engine *e) {
/* } */ /* } */
} }
void engine_check_sort_tasks(struct engine *e, struct cell *c) {
/* Find the parent sort task, if any, and copy its flags. */
if (c->sorts != NULL) {
struct cell *parent = c->parent;
while (parent != NULL && parent->sorts == NULL) parent = parent->parent;
if (parent != NULL) c->sorts->flags |= parent->sorts->flags;
}
/* Recurse? */
if (c->split)
for (int k = 0; k < 8; k++)
if (c->progeny[k] != NULL) engine_check_sort_tasks(e, c->progeny[k]);
}
/** /**
* @brief Fill the #space's task list. * @brief Fill the #space's task list.
* *
...@@ -2350,10 +2372,13 @@ void engine_maketasks(struct engine *e) { ...@@ -2350,10 +2372,13 @@ void engine_maketasks(struct engine *e) {
* pointers. */ * pointers. */
for (int k = 0; k < nr_cells; k++) cell_set_super(&cells[k], NULL); for (int k = 0; k < nr_cells; k++) cell_set_super(&cells[k], NULL);
/* Append hierarchical tasks to each cells */ /* Append hierarchical tasks to each cell. */
for (int k = 0; k < nr_cells; k++) for (int k = 0; k < nr_cells; k++)
engine_make_hierarchical_tasks(e, &cells[k]); engine_make_hierarchical_tasks(e, &cells[k]);
/* Append hierarchical tasks to each cell. */
for (int k = 0; k < nr_cells; k++) engine_check_sort_tasks(e, &cells[k]);
/* Run through the tasks and make force tasks for each density task. /* Run through the tasks and make force tasks for each density task.
Each force task depends on the cell ghosts and unlocks the kick task Each force task depends on the cell ghosts and unlocks the kick task
of its super-cell. */ of its super-cell. */
...@@ -2437,14 +2462,12 @@ void engine_marktasks_mapper(void *map_data, int num_elements, ...@@ -2437,14 +2462,12 @@ void engine_marktasks_mapper(void *map_data, int num_elements,
else if (t->type == task_type_pair || t->type == task_type_sub_pair) { else if (t->type == task_type_pair || t->type == task_type_sub_pair) {
/* Local pointers. */ /* Local pointers. */
const struct cell *ci = t->ci; struct cell *ci = t->ci;
const struct cell *cj = t->cj; struct cell *cj = t->cj;
/* Too much particle movement? */ /* Too much particle movement? */
if (t->tight && if (t->tight &&
(max(ci->h_max, cj->h_max) + ci->dx_max + cj->dx_max > cj->dmin || max(ci->h_max, cj->h_max) + ci->dx_max + cj->dx_max > cj->dmin)
ci->dx_max > space_maxreldx * ci->h_max ||