Commit 8f6ecbe0 authored by Loic Hausammann's avatar Loic Hausammann
Browse files

Implement stars sort

parent 10d0e160
......@@ -7,5 +7,5 @@ then
./getIC.sh
fi
../swift -b -G -s -S -t 8 dwarf_galaxy.yml 2>&1 | tee output.log
../swift -b -G -s -S -t 8 $@ dwarf_galaxy.yml 2>&1 | tee output.log
......@@ -74,6 +74,20 @@ __attribute__((always_inline)) INLINE static int cell_are_gpart_drifted(
return (c->grav.ti_old_part == e->ti_current);
}
/**
* @brief Check that the #spart in a #cell have been drifted to the current
* time.
*
* @param c The #cell.
* @param e The #engine containing information about the current time.
* @return 1 if the #cell has been drifted to the current time, 0 otherwise.
*/
__attribute__((always_inline)) INLINE static int cell_are_spart_drifted(
const struct cell *c, const struct engine *e) {
return cell_are_gpart_drifted(c, e);
}
/* Are cells / particles active for regular tasks ? */
/**
......@@ -185,9 +199,16 @@ __attribute__((always_inline)) INLINE static int cell_is_all_active_gravity(
__attribute__((always_inline)) INLINE static int cell_is_active_stars(
const struct cell *c, const struct engine *e) {
// LOIC: Need star-specific implementation
#ifdef SWIFT_DEBUG_CHECKS
if (c->stars.ti_end_min < e->ti_current)
error(
"cell in an impossible time-zone! c->ti_end_min=%lld (t=%e) and "
"e->ti_current=%lld (t=%e, a=%e)",
c->stars.ti_end_min, c->stars.ti_end_min * e->time_base, e->ti_current,
e->ti_current * e->time_base, e->cosmology->a);
#endif
return cell_is_active_gravity(c, e);
return (c->stars.ti_end_min == e->ti_current);
}
/**
......
......@@ -342,6 +342,7 @@ int cell_unpack(struct pcell *restrict pc, struct cell *restrict c,
temp->hydro.dx_max_part = 0.f;
temp->hydro.dx_max_sort = 0.f;
temp->stars.dx_max_part = 0.f;
temp->stars.dx_max_sort = 0.f;
temp->nodeID = c->nodeID;
temp->parent = c;
c->progeny[k] = temp;
......@@ -1561,12 +1562,20 @@ void cell_check_multipole(struct cell *c) {
*/
void cell_clean(struct cell *c) {
/* Hydro */
for (int i = 0; i < 13; i++)
if (c->hydro.sort[i] != NULL) {
free(c->hydro.sort[i]);
c->hydro.sort[i] = NULL;
}
/* Stars */
for (int i = 0; i < 13; i++)
if (c->stars.sort[i] != NULL) {
free(c->stars.sort[i]);
c->stars.sort[i] = NULL;
}
/* Recurse */
for (int k = 0; k < 8; k++)
if (c->progeny[k]) cell_clean(c->progeny[k]);
......@@ -1724,6 +1733,68 @@ void cell_activate_sorts(struct cell *c, int sid, struct scheduler *s) {
}
}
/**
* @brief Activate the sorts up a cell hierarchy.
*/
void cell_activate_stars_sorts_up(struct cell *c, struct scheduler *s) {
if (c == c->super) {
#ifdef SWIFT_DEBUG_CHECKS
if (c->stars.sorts == NULL)
error("Trying to activate un-existing c->stars.sorts");
#endif
scheduler_activate(s, c->stars.sorts);
if (c->nodeID == engine_rank) {
cell_activate_drift_part(c, s);
cell_activate_drift_spart(c, s);
}
} else {
for (struct cell *parent = c->parent;
parent != NULL && !parent->stars.do_sub_sort;
parent = parent->parent) {
parent->stars.do_sub_sort = 1;
if (parent == c->super) {
#ifdef SWIFT_DEBUG_CHECKS
if (parent->stars.sorts == NULL)
error("Trying to activate un-existing parents->hydro.sorts");
#endif
scheduler_activate(s, parent->stars.sorts);
if (parent->nodeID == engine_rank) {
cell_activate_drift_part(parent, s);
cell_activate_drift_spart(parent, s);
}
break;
}
}
}
}
/**
* @brief Activate the sorts on a given cell, if needed.
*/
void cell_activate_stars_sorts(struct cell *c, int sid, struct scheduler *s) {
/* Do we need to re-sort? */
if (c->stars.dx_max_sort > space_maxreldx * c->dmin) {
/* Climb up the tree to active the sorts in that direction */
for (struct cell *finger = c; finger != NULL; finger = finger->parent) {
if (finger->stars.requires_sorts) {
atomic_or(&finger->stars.do_sort, finger->stars.requires_sorts);
cell_activate_stars_sorts_up(finger, s);
}
finger->stars.sorted = 0;
}
}
/* Has this cell been sorted at all for the given sid? */
if (!(c->stars.sorted & (1 << sid)) || c->nodeID != engine_rank) {
atomic_or(&c->stars.do_sort, (1 << sid));
cell_activate_stars_sorts_up(c, s);
}
}
/**
* @brief Traverse a sub-cell task and activate the hydro drift tasks that are
* required by a hydro task
......@@ -2105,7 +2176,9 @@ void cell_activate_subcell_stars_tasks(struct cell *ci, struct cell *cj,
if (cj == NULL) {
/* Do anything? */
if (ci->stars.count == 0 || !cell_is_active_stars(ci, e)) return;
if (!cell_is_active_stars(ci, e) || ci->hydro.count == 0 ||
ci->stars.count == 0)
return;
/* Recurse? */
if (cell_can_recurse_in_self_stars_task(ci)) {
......@@ -2133,7 +2206,10 @@ void cell_activate_subcell_stars_tasks(struct cell *ci, struct cell *cj,
/* Should we even bother? */
if (!cell_is_active_stars(ci, e) && !cell_is_active_stars(cj, e)) return;
if (ci->stars.count == 0 || cj->stars.count == 0) return;
int should_do = ci->stars.count != 0 && cj->hydro.count != 0;
should_do |= cj->stars.count != 0 && ci->hydro.count != 0;
if (!should_do) return;
/* Get the orientation of the pair. */
double shift[3];
......@@ -2418,23 +2494,43 @@ void cell_activate_subcell_stars_tasks(struct cell *ci, struct cell *cj,
}
/* Otherwise, activate the sorts and drifts. */
else if (cell_is_active_stars(ci, e) || cell_is_active_stars(cj, e)) {
else {
/* We are going to interact this pair, so store some values. */
atomic_or(&ci->hydro.requires_sorts, 1 << sid);
atomic_or(&cj->hydro.requires_sorts, 1 << sid);
ci->hydro.dx_max_sort_old = ci->hydro.dx_max_sort;
cj->hydro.dx_max_sort_old = cj->hydro.dx_max_sort;
if (cell_is_active_stars(ci, e) && cj->hydro.count != 0 &&
ci->stars.count != 0) {
/* We are going to interact this pair, so store some values. */
atomic_or(&cj->hydro.requires_sorts, 1 << sid);
atomic_or(&ci->stars.requires_sorts, 1 << sid);
/* Activate the drifts if the cells are local. */
if (ci->nodeID == engine_rank) cell_activate_drift_part(ci, s);
if (ci->nodeID == engine_rank) cell_activate_drift_spart(ci, s);
if (cj->nodeID == engine_rank) cell_activate_drift_part(cj, s);
if (cj->nodeID == engine_rank) cell_activate_drift_spart(cj, s);
cj->hydro.dx_max_sort_old = cj->hydro.dx_max_sort;
ci->stars.dx_max_sort_old = ci->stars.dx_max_sort;
/* Do we need to sort the cells? */
cell_activate_sorts(ci, sid, s);
cell_activate_sorts(cj, sid, s);
/* Activate the drifts if the cells are local. */
if (ci->nodeID == engine_rank) cell_activate_drift_spart(ci, s);
if (cj->nodeID == engine_rank) cell_activate_drift_part(cj, s);
/* Do we need to sort the cells? */
cell_activate_sorts(cj, sid, s);
cell_activate_stars_sorts(ci, sid, s);
}
if (cell_is_active_stars(cj, e) && ci->hydro.count != 0 &&
cj->stars.count != 0) {
/* We are going to interact this pair, so store some values. */
atomic_or(&cj->stars.requires_sorts, 1 << sid);
atomic_or(&ci->hydro.requires_sorts, 1 << sid);
ci->hydro.dx_max_sort_old = ci->hydro.dx_max_sort;
cj->stars.dx_max_sort_old = cj->stars.dx_max_sort;
/* Activate the drifts if the cells are local. */
if (ci->nodeID == engine_rank) cell_activate_drift_part(ci, s);
if (cj->nodeID == engine_rank) cell_activate_drift_spart(cj, s);
/* Do we need to sort the cells? */
cell_activate_sorts(ci, sid, s);
cell_activate_stars_sorts(cj, sid, s);
}
}
} /* Otherwise, pair interation */
}
......@@ -2965,25 +3061,48 @@ int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s) {
/* Activate drifts */
if (t->type == task_type_self) {
if (ci->nodeID == nodeID) cell_activate_drift_part(ci, s);
if (ci->nodeID == nodeID) cell_activate_drift_gpart(ci, s);
if (ci->nodeID == nodeID) {
cell_activate_drift_part(ci, s);
cell_activate_drift_spart(ci, s);
}
}
/* Set the correct sorting flags and activate hydro drifts */
else if (t->type == task_type_pair) {
/* Store some values. */
atomic_or(&ci->hydro.requires_sorts, 1 << t->flags);
/* Do ci */
/* stars for ci */
atomic_or(&ci->stars.requires_sorts, 1 << t->flags);
ci->stars.dx_max_sort_old = ci->stars.dx_max_sort;
/* hydro for cj */
atomic_or(&cj->hydro.requires_sorts, 1 << t->flags);
ci->hydro.dx_max_sort_old = ci->hydro.dx_max_sort;
cj->hydro.dx_max_sort_old = cj->hydro.dx_max_sort;
/* Activate the drift tasks. */
if (ci->nodeID == nodeID) cell_activate_drift_part(ci, s);
if (ci->nodeID == nodeID) cell_activate_drift_spart(ci, s);
if (cj->nodeID == nodeID) cell_activate_drift_part(cj, s);
/* Check the sorts and activate them if needed. */
cell_activate_sorts(ci, t->flags, s);
cell_activate_stars_sorts(ci, t->flags, s);
cell_activate_sorts(cj, t->flags, s);
/* Do cj */
/* hydro for ci */
atomic_or(&ci->hydro.requires_sorts, 1 << t->flags);
ci->hydro.dx_max_sort_old = ci->hydro.dx_max_sort;
/* stars for cj */
atomic_or(&cj->stars.requires_sorts, 1 << t->flags);
cj->stars.dx_max_sort_old = cj->stars.dx_max_sort;
/* Activate the drift tasks. */
if (cj->nodeID == nodeID) cell_activate_drift_spart(cj, s);
if (ci->nodeID == nodeID) cell_activate_drift_part(ci, s);
/* Check the sorts and activate them if needed. */
cell_activate_sorts(ci, t->flags, s);
cell_activate_stars_sorts(cj, t->flags, s);
}
/* Store current values of dx_max and h_max. */
else if (t->type == task_type_sub_pair || t->type == task_type_sub_self) {
......@@ -3402,6 +3521,7 @@ void cell_drift_gpart(struct cell *c, const struct engine *e, int force) {
struct spart *const sparts = c->stars.parts;
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;
/* Drift irrespective of cell flags? */
......@@ -3428,6 +3548,7 @@ void cell_drift_gpart(struct cell *c, const struct engine *e, int force) {
/* Update */
dx_max = max(dx_max, cp->stars.dx_max_part);
dx_max_sort = max(dx_max_sort, cp->stars.dx_max_sort);
cell_h_max = max(cell_h_max, cp->stars.h_max);
}
}
......@@ -3435,6 +3556,7 @@ void cell_drift_gpart(struct cell *c, const struct engine *e, int force) {
/* Store the values */
c->stars.h_max = cell_h_max;
c->stars.dx_max_part = dx_max;
c->stars.dx_max_sort = dx_max_sort;
/* Update the time of the last drift */
c->grav.ti_old_part = ti_current;
......@@ -3528,6 +3650,12 @@ void cell_drift_gpart(struct cell *c, const struct engine *e, int force) {
sp->x_diff[2] * sp->x_diff[2];
dx2_max = max(dx2_max, dx2);
const float dx2_sort = sp->x_diff_sort[0] * sp->x_diff_sort[0] +
sp->x_diff_sort[1] * sp->x_diff_sort[1] +
sp->x_diff_sort[2] * sp->x_diff_sort[2];
dx2_max_sort = max(dx2_max_sort, dx2_sort);
/* Maximal smoothing length */
cell_h_max = max(cell_h_max, sp->h);
......@@ -3535,10 +3663,12 @@ void cell_drift_gpart(struct cell *c, const struct engine *e, int force) {
/* Now, get the maximal particle motion from its square */
dx_max = sqrtf(dx2_max);
dx_max_sort = sqrtf(dx2_max_sort);
/* Store the values */
c->stars.h_max = cell_h_max;
c->stars.dx_max_part = dx_max;
c->stars.dx_max_sort = dx_max_sort;
/* Update the time of the last drift */
c->grav.ti_old_part = ti_current;
......@@ -3627,7 +3757,8 @@ void cell_drift_multipole(struct cell *c, const struct engine *e) {
void cell_check_timesteps(struct cell *c) {
#ifdef SWIFT_DEBUG_CHECKS
if (c->hydro.ti_end_min == 0 && c->grav.ti_end_min == 0 && c->nr_tasks > 0)
if (c->hydro.ti_end_min == 0 && c->grav.ti_end_min == 0 &&
c->stars.ti_end_min == 0 && c->nr_tasks > 0)
error("Cell without assigned time-step");
if (c->split) {
......
......@@ -460,6 +460,30 @@ struct cell {
/*! Values of dx_max before the drifts, used for sub-cell tasks. */
float dx_max_part_old;
/*! Maximum particle movement in this cell since the last sort. */
float dx_max_sort;
/*! 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;
/*! Pointer for the sorted indices. */
struct entry *sort[13];
/*! Bit-mask indicating the sorted directions */
unsigned int sorted;
/*! Bit mask of sorts that need to be computed for this cell. */
unsigned int do_sort;
/*! Do any of this cell's sub-cells need to be sorted? */
char do_sub_sort;
/*! Maximum end of (integer) time step in this cell for gravity tasks. */
integertime_t ti_end_min;
/*! Dependency implicit task for the star ghost (in->ghost->out)*/
struct task *ghost_in;
......@@ -469,6 +493,9 @@ struct cell {
/*! The star ghost task itself */
struct task *ghost;
/*! The task computing this cell's sorts. */
struct task *sorts;
/*! Linked list of the tasks computing this cell's star density. */
struct link *density;
......@@ -484,6 +511,11 @@ struct cell {
/*! Spin lock for various uses (#spart case). */
swift_lock_type lock;
#ifdef SWIFT_DEBUG_CHECKS
/*! Last (integer) time the cell's sort arrays were updated. */
integertime_t ti_sort;
#endif
} stars;
#ifdef WITH_MPI
......@@ -652,7 +684,9 @@ void cell_activate_subcell_external_grav_tasks(struct cell *ci,
struct scheduler *s);
void cell_activate_drift_part(struct cell *c, struct scheduler *s);
void cell_activate_drift_gpart(struct cell *c, struct scheduler *s);
void cell_activate_drift_spart(struct cell *c, struct scheduler *s);
void cell_activate_sorts(struct cell *c, int sid, struct scheduler *s);
void cell_activate_stars_sorts(struct cell *c, int sid, struct scheduler *s);
void cell_clear_drift_flags(struct cell *c, void *data);
void cell_set_super_mapper(void *map_data, int num_elements, void *extra_data);
int cell_has_tasks(struct cell *c);
......
......@@ -142,6 +142,7 @@ __attribute__((always_inline)) INLINE static void drift_spart(
for (int k = 0; k < 3; k++) {
const float dx = sp->v[k] * dt_drift;
sp->x_diff[k] -= dx;
sp->x_diff_sort[k] -= dx;
}
}
......
......@@ -128,6 +128,7 @@ struct end_of_step_data {
size_t inhibited, g_inhibited, s_inhibited;
integertime_t ti_hydro_end_min, ti_hydro_end_max, ti_hydro_beg_max;
integertime_t ti_gravity_end_min, ti_gravity_end_max, ti_gravity_beg_max;
integertime_t ti_stars_end_min;
struct engine *e;
};
......@@ -1924,7 +1925,8 @@ int engine_estimate_nr_tasks(struct engine *e) {
n1 += 2;
}
if (e->policy & engine_policy_stars) {
n1 += 2;
/* 1 self, 1 sort, 26/2 pairs */
n1 += 15;
}
#if defined(WITH_LOGGER)
n1 += 1;
......@@ -2214,6 +2216,7 @@ void engine_collect_end_of_step_recurse(struct cell *c,
ti_hydro_beg_max = 0;
integertime_t ti_gravity_end_min = max_nr_timesteps, ti_gravity_end_max = 0,
ti_gravity_beg_max = 0;
integertime_t ti_stars_end_min = max_nr_timesteps;
/* Collect the values from the progeny. */
for (int k = 0; k < 8; k++) {
......@@ -2233,6 +2236,8 @@ void engine_collect_end_of_step_recurse(struct cell *c,
ti_gravity_end_max = max(ti_gravity_end_max, cp->grav.ti_end_max);
ti_gravity_beg_max = max(ti_gravity_beg_max, cp->grav.ti_beg_max);
ti_stars_end_min = min(ti_stars_end_min, cp->stars.ti_end_min);
updated += cp->hydro.updated;
g_updated += cp->grav.updated;
s_updated += cp->stars.updated;
......@@ -2255,6 +2260,7 @@ void engine_collect_end_of_step_recurse(struct cell *c,
c->grav.ti_end_min = ti_gravity_end_min;
c->grav.ti_end_max = ti_gravity_end_max;
c->grav.ti_beg_max = ti_gravity_beg_max;
c->stars.ti_end_min = ti_stars_end_min;
c->hydro.updated = updated;
c->grav.updated = g_updated;
c->stars.updated = s_updated;
......@@ -2289,6 +2295,7 @@ void engine_collect_end_of_step_mapper(void *map_data, int num_elements,
ti_hydro_beg_max = 0;
integertime_t ti_gravity_end_min = max_nr_timesteps, ti_gravity_end_max = 0,
ti_gravity_beg_max = 0;
integertime_t ti_stars_end_min = max_nr_timesteps;
for (int ind = 0; ind < num_elements; ind++) {
struct cell *c = &s->cells_top[local_cells[ind]];
......@@ -2309,6 +2316,9 @@ void engine_collect_end_of_step_mapper(void *map_data, int num_elements,
ti_gravity_end_max = max(ti_gravity_end_max, c->grav.ti_end_max);
ti_gravity_beg_max = max(ti_gravity_beg_max, c->grav.ti_beg_max);
if (c->stars.ti_end_min > e->ti_current)
ti_stars_end_min = min(ti_stars_end_min, c->stars.ti_end_min);
updated += c->hydro.updated;
g_updated += c->grav.updated;
s_updated += c->stars.updated;
......@@ -2347,6 +2357,9 @@ void engine_collect_end_of_step_mapper(void *map_data, int num_elements,
max(ti_gravity_end_max, data->ti_gravity_end_max);
data->ti_gravity_beg_max =
max(ti_gravity_beg_max, data->ti_gravity_beg_max);
if (ti_stars_end_min > e->ti_current)
data->ti_stars_end_min = min(ti_stars_end_min, data->ti_stars_end_min);
}
if (lock_unlock(&s->lock) != 0) error("Failed to unlock the space");
......
......@@ -733,6 +733,10 @@ void engine_make_hierarchical_tasks_stars(struct engine *e, struct cell *c) {
/* Are we in a super-cell ? */
if (c->super == c) {
/* Add the sort task. */
c->stars.sorts = scheduler_addtask(s, task_type_stars_sort,
task_subtype_none, 0, 0, c, NULL);
/* Local tasks only... */
if (c->nodeID == e->nodeID) {
......@@ -1010,6 +1014,14 @@ void engine_count_and_link_tasks_mapper(void *map_data, int num_elements,
scheduler_addunlock(sched, t, finger->hydro.sorts);
}
/* Link stars sort tasks to all the higher sort task. */
if (t_type == task_type_stars_sort) {
for (struct cell *finger = t->ci->parent; finger != NULL;
finger = finger->parent)
if (finger->stars.sorts != NULL)
scheduler_addunlock(sched, t, finger->stars.sorts);
}
/* Link self tasks to cells. */
else if (t_type == task_type_self) {
atomic_inc(&ci->nr_tasks);
......@@ -1576,6 +1588,11 @@ void engine_link_stars_tasks_mapper(void *map_data, int num_elements,
for (int ind = 0; ind < num_elements; ind++) {
struct task *t = &((struct task *)map_data)[ind];
/* Sort tasks depend on the drift of the cell. */
if (t->type == task_type_stars_sort && t->ci->nodeID == engine_rank) {
scheduler_addunlock(sched, t->ci->super->grav.drift, t);
}
/* Self-interaction? */
if (t->type == task_type_self && t->subtype == task_subtype_stars_density) {
......@@ -1596,13 +1613,18 @@ void engine_link_stars_tasks_mapper(void *map_data, int num_elements,
t->subtype == task_subtype_stars_density) {
/* Make all density tasks depend on the drift and the sorts. */
if (t->ci->nodeID == engine_rank)
scheduler_addunlock(sched, t->ci->super->hydro.drift, t);
scheduler_addunlock(sched, t->ci->super->hydro.sorts, t);
if (t->cj->nodeID == engine_rank)
scheduler_addunlock(sched, t->cj->super->hydro.drift, t);
scheduler_addunlock(sched, t->cj->super->hydro.sorts, t);
scheduler_addunlock(sched, t->ci->super->stars.sorts, t);
if (t->ci->super != t->cj->super) {
if (t->cj->nodeID == engine_rank)
scheduler_addunlock(sched, t->cj->super->hydro.drift, t);
scheduler_addunlock(sched, t->cj->super->hydro.sorts, t);
if (t->ci->nodeID == engine_rank)
scheduler_addunlock(sched, t->ci->super->hydro.drift, t);
scheduler_addunlock(sched, t->ci->super->hydro.sorts, t);
scheduler_addunlock(sched, t->cj->super->stars.sorts, t);
}
/* Now, build all the dependencies for the stars for the cells */
......@@ -1624,6 +1646,7 @@ void engine_link_stars_tasks_mapper(void *map_data, int num_elements,
/* Make all density tasks depend on the drift and sorts. */
scheduler_addunlock(sched, t->ci->super->hydro.drift, t);
scheduler_addunlock(sched, t->ci->super->hydro.sorts, t);
scheduler_addunlock(sched, t->ci->super->stars.sorts, t);
/* Now, build all the dependencies for the stars for the cells */
/* that are local and are not descendant of the same super-cells */
......@@ -1638,13 +1661,18 @@ void engine_link_stars_tasks_mapper(void *map_data, int num_elements,
t->subtype == task_subtype_stars_density) {
/* Make all density tasks depend on the drift. */
if (t->ci->nodeID == engine_rank)
scheduler_addunlock(sched, t->ci->super->hydro.drift, t);
scheduler_addunlock(sched, t->ci->super->hydro.sorts, t);
if (t->cj->nodeID == engine_rank)
scheduler_addunlock(sched, t->cj->super->hydro.drift, t);
scheduler_addunlock(sched, t->cj->super->hydro.sorts, t);
scheduler_addunlock(sched, t->ci->super->stars.sorts, t);
if (t->ci->super != t->cj->super) {
if (t->cj->nodeID == engine_rank)
scheduler_addunlock(sched, t->cj->super->hydro.drift, t);
scheduler_addunlock(sched, t->cj->super->hydro.sorts, t);
if (t->ci->nodeID == engine_rank)
scheduler_addunlock(sched, t->ci->super->hydro.drift, t);
scheduler_addunlock(sched, t->ci->super->hydro.sorts, t);
scheduler_addunlock(sched, t->cj->super->stars.sorts, t);
}
/* Now, build all the dependencies for the stars for the cells */
......@@ -1697,8 +1725,8 @@ void engine_make_starsloop_tasks_mapper(void *map_data, int num_elements,
/* Get the cell */
struct cell *ci = &cells[cid];
/* Skip cells without star particles */
if (ci->stars.count == 0) continue;
/* Skip cells without particles */
if (ci->stars.count == 0 && ci->hydro.count == 0) continue;
/* If the cells is local build a self-interaction */
if (ci->nodeID == nodeID)
......@@ -1724,7 +1752,7 @@ void engine_make_starsloop_tasks_mapper(void *map_data, int num_elements,
struct cell *cj = &cells[cjd];
/* Is that neighbour local and does it have particles ? */
if (cid >= cjd || cj->hydro.count == 0 ||
if (cid >= cjd || (cj->stars.count == 0 && cj->hydro.count == 0) ||
(ci->nodeID != nodeID && cj->nodeID != nodeID))
continue;
......@@ -1851,6 +1879,12 @@ void engine_maketasks(struct engine *e) {
s->nr_cells, 1, 0, e);
}
if (e->verbose)
message("Making stars tasks took %.3f %s.",
clocks_from_ticks(getticks() - tic2), clocks_getunit());
tic2 = getticks();
/* Add the self gravity tasks. */
if (e->policy & engine_policy_self_gravity) engine_make_self_gravity_tasks(e);
......@@ -1881,7 +1915,7 @@ void engine_maketasks(struct engine *e) {
#endif
const size_t self_grav_tasks_per_cell = 125;
const size_t ext_grav_tasks_per_cell = 1;
const size_t stars_tasks_per_cell = 15;
const size_t stars_tasks_per_cell = 27;
if (e->policy & engine_policy_hydro)