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

Create the M-M gravity task one level higher. The task itself recurses on its...

Create the M-M gravity task one level higher. The task itself recurses on its progenies. We can run with a rebuild every time-step. More work required on the unskip.
parent 79c022ee
......@@ -2028,20 +2028,31 @@ void cell_activate_grav_mm_task(struct cell *ci, struct cell *cj,
struct scheduler *s) {
/* Some constants */
const struct engine *e = s->space->e;
const integertime_t ti_current = e->ti_current;
/* Anything to do here? */
if (!cell_is_active_gravity_mm(ci, e) && !cell_is_active_gravity_mm(cj, e))
error("Inactive MM task being activated");
/* Atomically drift the multipole in ci */
lock_lock(&ci->mlock);
if (ci->ti_old_multipole < e->ti_current) cell_drift_multipole(ci, e);
if (lock_unlock(&ci->mlock) != 0) error("Impossible to unlock m-pole");
/* Atomically drift the multipoles in the progenies of ci */
for (int i = 0; i < 8; i++) {
struct cell *cpi = ci->progeny[i];
if (cpi != NULL) {
lock_lock(&cpi->mlock);
if (cpi->ti_old_multipole < ti_current) cell_drift_multipole(cpi, e);
if (lock_unlock(&cpi->mlock) != 0) error("Impossible to unlock m-pole");
}
}
/* Atomically drift the multipole in cj */
lock_lock(&cj->mlock);
if (cj->ti_old_multipole < e->ti_current) cell_drift_multipole(cj, e);
if (lock_unlock(&cj->mlock) != 0) error("Impossible to unlock m-pole");
/* Atomically drift the multipoles in the progenies of cj */
for (int j = 0; j < 8; j++) {
struct cell *cpj = cj->progeny[j];
if (cpj != NULL) {
lock_lock(&cpj->mlock);
if (cpj->ti_old_multipole < ti_current) cell_drift_multipole(cpj, e);
if (lock_unlock(&cpj->mlock) != 0) error("Impossible to unlock m-pole");
}
}
}
/**
......@@ -2490,7 +2501,7 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
struct cell *ci = t->ci;
struct cell *cj = t->cj;
const int ci_active = cell_is_active_gravity_mm(ci, e);
const int cj_active = (cj != NULL) ? cell_is_active_gravity_mm(cj, e) : 0;
const int cj_active = cell_is_active_gravity_mm(cj, e);
#ifdef WITH_MPI
const int ci_nodeID = ci->nodeID;
const int cj_nodeID = (cj != NULL) ? cj->nodeID : -1;
......
......@@ -2674,9 +2674,29 @@ void engine_count_and_link_tasks_mapper(void *map_data, int num_elements,
}
#endif
/* Note that we do not need to link the M-M tasks */
/* since we already did so when splitting the gravity */
/* tasks. */
/* Multipole-multipole interaction of progenies */
} else if (t_type == task_type_grav_mm) {
atomic_inc(&ci->nr_mm_tasks);
atomic_inc(&cj->nr_mm_tasks);
engine_addlink(e, &ci->grav_mm, t);
engine_addlink(e, &cj->grav_mm, t);
/* for (int i = 0; i < 8; i++) { */
/* struct cell *cpi = ci->progeny[i]; */
/* if (cpi != NULL) { */
/* atomic_inc(&cpi->nr_mm_tasks); */
/* engine_addlink(e, &cpi->grav_mm, t); */
/* } */
/* } */
/* for (int j = 0; j < 8; j++) { */
/* struct cell *cpj = cj->progeny[j]; */
/* if (cpj != NULL) { */
/* atomic_inc(&cpj->nr_mm_tasks); */
/* engine_addlink(e, &cpj->grav_mm, t); */
/* } */
/* } */
}
}
}
......
......@@ -2273,7 +2273,7 @@ void *runner_main(void *data) {
runner_do_grav_long_range(r, t->ci, 1);
break;
case task_type_grav_mm:
runner_dopair_grav_mm(r, t->ci, t->cj);
runner_dopair_grav_mm_progenies(r, t->ci, t->cj);
break;
case task_type_cooling:
runner_do_cooling(r, t->ci, 1);
......
......@@ -1300,8 +1300,35 @@ static INLINE void runner_dopair_grav_mm(struct runner *r,
runner_dopair_grav_mm_nonsym(r, ci, cj);
else if (do_j)
runner_dopair_grav_mm_nonsym(r, cj, ci);
else
error("Running M-M task with two inactive cells.");
/* else */
/* error("Running M-M task with two inactive cells."); */
}
static INLINE void runner_dopair_grav_mm_progenies(struct runner *r,
struct cell *restrict ci,
struct cell *restrict cj) {
const struct engine *e = r->e;
const struct space *s = e->s;
/* Loop over all pairs of progenies */
for (int i = 0; i < 8; i++) {
if (ci->progeny[i] != NULL) {
for (int j = 0; j < 8; j++) {
if (cj->progeny[j] != NULL) {
struct cell *cpi = ci->progeny[i];
struct cell *cpj = cj->progeny[j];
/* Did we agree to use an M-M interaction here at the last rebuild? */
if (cell_can_use_pair_mm_rebuild(cpi, cpj, e, s)) {
runner_dopair_grav_mm(r, cpi, cpj);
}
}
}
}
}
}
static INLINE void runner_dopair_recursive_grav_pm(struct runner *r,
......@@ -1631,13 +1658,13 @@ static INLINE void runner_do_grav_long_range(struct runner *r, struct cell *ci,
if (ci->ti_old_multipole != e->ti_current)
error("Interacting un-drifted multipole");
/* Get this cell's multipole information */
struct gravity_tensors *const multi_i = ci->multipole;
/* Find this cell's top-level (great-)parent */
struct cell *top = ci;
while (top->parent != NULL) top = top->parent;
/* Flag that contributions will be recieved */
struct gravity_tensors *const multi_i = ci->multipole;
/* Recover the top-level multipole (for distance checks) */
struct gravity_tensors *const multi_top = top->multipole;
const double CoM_rebuild_top[3] = {multi_top->CoM_rebuild[0],
......
......@@ -888,20 +888,6 @@ static void scheduler_splittask_gravity(struct task *t, struct scheduler *s) {
break;
}
/* Should we replace it with an M-M task? */
if (cell_can_use_pair_mm_rebuild(ci, cj, e, sp)) {
t->type = task_type_grav_mm;
t->subtype = task_subtype_none;
/* Since this task will not be split, we can already link it */
atomic_inc(&ci->nr_mm_tasks);
atomic_inc(&cj->nr_mm_tasks);
engine_addlink(e, &ci->grav_mm, t);
engine_addlink(e, &cj->grav_mm, t);
break;
}
/* Should this task be split-up? */
if (cell_can_split_pair_gravity_task(ci) &&
cell_can_split_pair_gravity_task(cj)) {
......@@ -910,37 +896,33 @@ static void scheduler_splittask_gravity(struct task *t, struct scheduler *s) {
const long long gcount_j = cj->gcount;
/* Replace by a single sub-task? */
if (scheduler_dosub && /* Use division to avoid integer overflow. */
if (scheduler_dosub &&
gcount_i * gcount_j < ((long long)space_subsize_pair_grav)) {
/* Otherwise, split it. */
} else {
/* Take a step back (we're going to recycle the current task)... */
redo = 1;
/* Find the first non-empty childrens of the cells */
int first_ci_child = 0, first_cj_child = 0;
while (ci->progeny[first_ci_child] == NULL) first_ci_child++;
while (cj->progeny[first_cj_child] == NULL) first_cj_child++;
/* Recycle the current pair */
t->ci = ci->progeny[first_ci_child];
t->cj = cj->progeny[first_cj_child];
/* Turn the task into a M-M task that will take care of all the
* progeny pairs */
t->type = task_type_grav_mm;
t->subtype = task_subtype_none;
/* Make a task for every other pair of progeny */
for (int i = first_ci_child; i < 8; i++) {
for (int i = 0; i < 8; i++) {
if (ci->progeny[i] != NULL) {
for (int j = first_cj_child; j < 8; j++) {
for (int j = 0; j < 8; j++) {
if (cj->progeny[j] != NULL) {
/* Skip the recycled pair */
if (i == first_ci_child && j == first_cj_child) continue;
/* But only for pairs that cannot be replaced by a M-M
* interaction */
if (!cell_can_use_pair_mm_rebuild(ci->progeny[i],
cj->progeny[j], e, sp)) {
scheduler_splittask_gravity(
scheduler_addtask(s, task_type_pair, t->subtype, 0, 0,
ci->progeny[i], cj->progeny[j]),
s);
scheduler_splittask_gravity(
scheduler_addtask(s, task_type_pair, task_subtype_grav,
0, 0, ci->progeny[i], cj->progeny[j]),
s);
}
}
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment