diff --git a/src/cell.c b/src/cell.c index aa5f3687ae02f1b88ffc7d351e42d4dfc1ff1468..fb01154db741a4fa285886b77a6713fc08e2e97d 100644 --- a/src/cell.c +++ b/src/cell.c @@ -1287,6 +1287,292 @@ int cell_is_drift_needed(struct cell *c, const struct engine *e) { return 0; } +/** + * @brief Traverse a sub-cell task and activate the sort tasks along the way. + */ +void cell_activate_subcell_tasks(struct cell *ci, struct cell *cj, + struct scheduler *s) { + const struct engine *e = s->space->e; + + /* Store the current dx_max and h_max values. */ + ci->dx_max_old = ci->dx_max; + ci->h_max_old = ci->h_max; + if (cj != NULL) { + cj->dx_max_old = cj->dx_max; + cj->h_max_old = cj->h_max; + } + + /* Self interaction? */ + if (cj == NULL) { + /* Do anything? */ + if (!cell_is_active(ci, e)) return; + + /* Recurse? */ + if (ci->split) { + for (int j = 0; j < 8; j++) + if (ci->progeny[j] != NULL) { + cell_activate_subcell_tasks(ci->progeny[j], NULL, s); + for (int k = j + 1; k < 8; k++) + if (ci->progeny[k] != NULL) + cell_activate_subcell_tasks(ci->progeny[j], ci->progeny[k], s); + } + + /* Activate drift task, if it is present. */ + if (ci->drift != NULL) scheduler_activate(s, ci->drift); + } + } + + /* Otherwise, pair interation, recurse? */ + else if (ci->split && cj->split && + 2.f * kernel_gamma * space_stretch * + (ci->h_max_old + ci->dx_max_old) < + ci->dmin && + 2.f * kernel_gamma * space_stretch * + (cj->h_max_old + cj->dx_max_old) < + ci->dmin) { + + /* Get the type of pair if not specified explicitly. */ + double shift[3]; + int sid = space_getsid(s->space, &ci, &cj, shift); + + /* Different types of flags. */ + switch (sid) { + + /* Regular sub-cell interactions of a single cell. */ + case 0: /* ( 1 , 1 , 1 ) */ + if (ci->progeny[7] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[0], s); + break; + + case 1: /* ( 1 , 1 , 0 ) */ + if (ci->progeny[6] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[0], s); + if (ci->progeny[6] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[1], s); + if (ci->progeny[7] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[0], s); + if (ci->progeny[7] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[1], s); + break; + + case 2: /* ( 1 , 1 , -1 ) */ + if (ci->progeny[6] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[1], s); + break; + + case 3: /* ( 1 , 0 , 1 ) */ + if (ci->progeny[5] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[0], s); + if (ci->progeny[5] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[2], s); + if (ci->progeny[7] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[0], s); + if (ci->progeny[7] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[2], s); + break; + + case 4: /* ( 1 , 0 , 0 ) */ + if (ci->progeny[4] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[4], cj->progeny[0], s); + if (ci->progeny[4] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[4], cj->progeny[1], s); + if (ci->progeny[4] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[4], cj->progeny[2], s); + if (ci->progeny[4] != NULL && cj->progeny[3] != NULL) + cell_activate_subcell_tasks(ci->progeny[4], cj->progeny[3], s); + if (ci->progeny[5] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[0], s); + if (ci->progeny[5] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[1], s); + if (ci->progeny[5] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[2], s); + if (ci->progeny[5] != NULL && cj->progeny[3] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[3], s); + if (ci->progeny[6] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[0], s); + if (ci->progeny[6] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[1], s); + if (ci->progeny[6] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[2], s); + if (ci->progeny[6] != NULL && cj->progeny[3] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[3], s); + if (ci->progeny[7] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[0], s); + if (ci->progeny[7] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[1], s); + if (ci->progeny[7] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[2], s); + if (ci->progeny[7] != NULL && cj->progeny[3] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[3], s); + break; + + case 5: /* ( 1 , 0 , -1 ) */ + if (ci->progeny[4] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[4], cj->progeny[1], s); + if (ci->progeny[4] != NULL && cj->progeny[3] != NULL) + cell_activate_subcell_tasks(ci->progeny[4], cj->progeny[3], s); + if (ci->progeny[6] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[1], s); + if (ci->progeny[6] != NULL && cj->progeny[3] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[3], s); + break; + + case 6: /* ( 1 , -1 , 1 ) */ + if (ci->progeny[5] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[2], s); + break; + + case 7: /* ( 1 , -1 , 0 ) */ + if (ci->progeny[4] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[4], cj->progeny[2], s); + if (ci->progeny[4] != NULL && cj->progeny[3] != NULL) + cell_activate_subcell_tasks(ci->progeny[4], cj->progeny[3], s); + if (ci->progeny[5] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[2], s); + if (ci->progeny[5] != NULL && cj->progeny[3] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[3], s); + break; + + case 8: /* ( 1 , -1 , -1 ) */ + if (ci->progeny[4] != NULL && cj->progeny[3] != NULL) + cell_activate_subcell_tasks(ci->progeny[4], cj->progeny[3], s); + break; + + case 9: /* ( 0 , 1 , 1 ) */ + if (ci->progeny[3] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[3], cj->progeny[0], s); + if (ci->progeny[3] != NULL && cj->progeny[4] != NULL) + cell_activate_subcell_tasks(ci->progeny[3], cj->progeny[4], s); + if (ci->progeny[7] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[0], s); + if (ci->progeny[7] != NULL && cj->progeny[4] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[4], s); + break; + + case 10: /* ( 0 , 1 , 0 ) */ + if (ci->progeny[2] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[2], cj->progeny[0], s); + if (ci->progeny[2] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[2], cj->progeny[1], s); + if (ci->progeny[2] != NULL && cj->progeny[4] != NULL) + cell_activate_subcell_tasks(ci->progeny[2], cj->progeny[4], s); + if (ci->progeny[2] != NULL && cj->progeny[5] != NULL) + cell_activate_subcell_tasks(ci->progeny[2], cj->progeny[5], s); + if (ci->progeny[3] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[3], cj->progeny[0], s); + if (ci->progeny[3] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[3], cj->progeny[1], s); + if (ci->progeny[3] != NULL && cj->progeny[4] != NULL) + cell_activate_subcell_tasks(ci->progeny[3], cj->progeny[4], s); + if (ci->progeny[3] != NULL && cj->progeny[5] != NULL) + cell_activate_subcell_tasks(ci->progeny[3], cj->progeny[5], s); + if (ci->progeny[6] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[0], s); + if (ci->progeny[6] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[1], s); + if (ci->progeny[6] != NULL && cj->progeny[4] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[4], s); + if (ci->progeny[6] != NULL && cj->progeny[5] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[5], s); + if (ci->progeny[7] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[0], s); + if (ci->progeny[7] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[1], s); + if (ci->progeny[7] != NULL && cj->progeny[4] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[4], s); + if (ci->progeny[7] != NULL && cj->progeny[5] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[5], s); + break; + + case 11: /* ( 0 , 1 , -1 ) */ + if (ci->progeny[2] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[2], cj->progeny[1], s); + if (ci->progeny[2] != NULL && cj->progeny[5] != NULL) + cell_activate_subcell_tasks(ci->progeny[2], cj->progeny[5], s); + if (ci->progeny[6] != NULL && cj->progeny[1] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[1], s); + if (ci->progeny[6] != NULL && cj->progeny[5] != NULL) + cell_activate_subcell_tasks(ci->progeny[6], cj->progeny[5], s); + break; + + case 12: /* ( 0 , 0 , 1 ) */ + if (ci->progeny[1] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[1], cj->progeny[0], s); + if (ci->progeny[1] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[1], cj->progeny[2], s); + if (ci->progeny[1] != NULL && cj->progeny[4] != NULL) + cell_activate_subcell_tasks(ci->progeny[1], cj->progeny[4], s); + if (ci->progeny[1] != NULL && cj->progeny[6] != NULL) + cell_activate_subcell_tasks(ci->progeny[1], cj->progeny[6], s); + if (ci->progeny[3] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[3], cj->progeny[0], s); + if (ci->progeny[3] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[3], cj->progeny[2], s); + if (ci->progeny[3] != NULL && cj->progeny[4] != NULL) + cell_activate_subcell_tasks(ci->progeny[3], cj->progeny[4], s); + if (ci->progeny[3] != NULL && cj->progeny[6] != NULL) + cell_activate_subcell_tasks(ci->progeny[3], cj->progeny[6], s); + if (ci->progeny[5] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[0], s); + if (ci->progeny[5] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[2], s); + if (ci->progeny[5] != NULL && cj->progeny[4] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[4], s); + if (ci->progeny[5] != NULL && cj->progeny[6] != NULL) + cell_activate_subcell_tasks(ci->progeny[5], cj->progeny[6], s); + if (ci->progeny[7] != NULL && cj->progeny[0] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[0], s); + if (ci->progeny[7] != NULL && cj->progeny[2] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[2], s); + if (ci->progeny[7] != NULL && cj->progeny[4] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[4], s); + if (ci->progeny[7] != NULL && cj->progeny[6] != NULL) + cell_activate_subcell_tasks(ci->progeny[7], cj->progeny[6], s); + break; + } + + } + + /* Otherwise, activate the sorts. */ + else if (cell_is_active(ci, e) || cell_is_active(cj, e)) { + + /* Get the type of pair if not specified explicitly. */ + double shift[3]; + int sid = space_getsid(s->space, &ci, &cj, shift); + + if (ci->dx_max_sort > space_maxreldx * ci->dmin) { + for (struct cell *finger = ci; finger != NULL; finger = finger->parent) + finger->sorted = 0; + } + if (!(ci->sorted & (1 << sid))) { + atomic_or(&ci->sorts->flags, 1 << sid); + scheduler_activate(s, ci->sorts); + if (ci->nodeID == engine_rank) scheduler_activate(s, ci->drift); + } + + if (cj->dx_max_sort > space_maxreldx * cj->dmin) { + for (struct cell *finger = cj; finger != NULL; finger = finger->parent) + finger->sorted = 0; + } + if (!(cj->sorted & (1 << sid))) { + atomic_or(&cj->sorts->flags, 1 << sid); + scheduler_activate(s, cj->sorts); + if (cj->nodeID == engine_rank) scheduler_activate(s, cj->drift); + } + } +} + +/** + * @brief Recursively store the values for dx_max_old and h_max_old. + */ +void cell_store_pre_drift_values(struct cell *c) { + c->h_max_old = c->h_max; + c->dx_max_old = c->dx_max; + if (c->split) + for (int i = 0; i < 8; i++) + if (c->progeny[i] != NULL) cell_store_pre_drift_values(c->progeny[i]); +} + /** * @brief Un-skips all the tasks associated with a given cell and checks * if the space needs to be rebuilt. @@ -1298,9 +1584,8 @@ int cell_is_drift_needed(struct cell *c, const struct engine *e) { */ int cell_unskip_tasks(struct cell *c, struct scheduler *s) { -#ifdef WITH_MPI struct engine *e = s->space->e; -#endif + const integertime_t ti_current = e->ti_current; int rebuild = 0; @@ -1314,12 +1599,12 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) { /* Set the correct sorting flags */ 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) + for (struct cell *finger = ci; finger != NULL; + finger = finger->parent) { finger->sorted = 0; + if (finger->requires_sorts == ti_current) + scheduler_activate(s, finger->sorts); + } } if (!(ci->sorted & (1 << t->flags))) { #ifdef SWIFT_DEBUG_CHECKS @@ -1329,6 +1614,14 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) { scheduler_activate(s, ci->sorts); if (ci->nodeID == engine_rank) scheduler_activate(s, ci->drift); } + if (cj->dx_max_sort > space_maxreldx * cj->dmin) { + for (struct cell *finger = cj; finger != NULL; + finger = finger->parent) { + finger->sorted = 0; + if (finger->requires_sorts == ti_current) + scheduler_activate(s, finger->sorts); + } + } if (!(cj->sorted & (1 << t->flags))) { #ifdef SWIFT_DEBUG_CHECKS if (!(cj->sorts->flags & (1 << t->flags))) @@ -1337,6 +1630,14 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) { scheduler_activate(s, cj->sorts); if (cj->nodeID == engine_rank) scheduler_activate(s, cj->drift); } + ci->requires_sorts = ti_current; + cj->requires_sorts = ti_current; + ci->dx_max_sort_old = ci->dx_max_sort; + cj->dx_max_sort_old = cj->dx_max_sort; + } + /* Store current values of dx_max and h_max. */ + else if (t->type == task_type_sub_pair || t->type == task_type_sub_self) { + cell_activate_subcell_tasks(t->ci, t->cj, s); } /* Only interested in pair interactions as of here. */ diff --git a/src/cell.h b/src/cell.h index c89e70960e84bb027f5e99a3cb362f2e0722b9bd..fc3d90bb246e6805b342e1b7c4fcb4691025f892 100644 --- a/src/cell.h +++ b/src/cell.h @@ -260,9 +260,6 @@ struct cell { /*! Nr of #spart in this cell. */ int scount; - /*! The size of the sort array */ - int sortsize; - /*! Bit-mask indicating the sorted directions */ unsigned int sorted; @@ -317,6 +314,14 @@ struct cell { /*! The maximal depth of this cell and its progenies */ char maxdepth; + /*! Values of dx_max and h_max before the drifts, used for sub-cell tasks. */ + float dx_max_old; + float h_max_old; + float dx_max_sort_old; + + /* Will this cell do anything that relies on its sorts being set correctly? */ + integertime_t requires_sorts; + #ifdef SWIFT_DEBUG_CHECKS /*! The list of tasks that have been executed on this cell */ char tasks_executed[64]; @@ -367,5 +372,8 @@ void cell_drift_particles(struct cell *c, const struct engine *e); void cell_drift_multipole(struct cell *c, const struct engine *e); void cell_drift_all_multipoles(struct cell *c, const struct engine *e); void cell_check_timesteps(struct cell *c); +void cell_store_pre_drift_values(struct cell *c); +void cell_activate_subcell_tasks(struct cell *ci, struct cell *cj, + struct scheduler *s); #endif /* SWIFT_CELL_H */