diff --git a/examples/main.c b/examples/main.c index 8ff44b2dd8d05109d516d27e4f9ff8074ce8ec8e..133b7a2e261ba633001144b748eb6769f35a0671 100644 --- a/examples/main.c +++ b/examples/main.c @@ -519,13 +519,12 @@ int main(int argc, char *argv[]) { #ifdef WITH_MPI if (with_mpole_reconstruction && nr_nodes > 1) error("Cannot reconstruct m-poles every step over MPI (yet)."); - if (with_star_formation && with_feedback) - error("Can't run with star formation and feedback over MPI (yet)"); if (with_limiter) error("Can't run with time-step limiter over MPI (yet)"); #endif /* Temporary early aborts for modes not supported with hand-vec. */ -#if defined(WITH_VECTORIZATION) && !defined(CHEMISTRY_NONE) +#if defined(WITH_VECTORIZATION) && defined(GADGET2_SPH) && \ + !defined(CHEMISTRY_NONE) error( "Cannot run with chemistry and hand-vectorization (yet). " "Use --disable-hand-vec at configure time."); diff --git a/src/active.h b/src/active.h index e7cd35fa570f15694ab8fa3011d6a02b65837886..f15a98fceeddc741b0f66009ff4a0c3b416b32f1 100644 --- a/src/active.h +++ b/src/active.h @@ -496,6 +496,28 @@ __attribute__((always_inline)) INLINE static int cell_is_starting_stars( return (c->stars.ti_beg_max == e->ti_current); } +/** + * @brief Does a cell contain any b-particle starting their time-step now ? + * + * @param c The #cell. + * @param e The #engine containing information about the current time. + * @return 1 if the #cell contains at least an active particle, 0 otherwise. + */ +__attribute__((always_inline)) INLINE static int cell_is_starting_black_holes( + const struct cell *c, const struct engine *e) { + +#ifdef SWIFT_DEBUG_CHECKS + if (c->black_holes.ti_beg_max > e->ti_current) + error( + "cell in an impossible time-zone! c->ti_beg_max=%lld (t=%e) and " + "e->ti_current=%lld (t=%e, a=%e)", + c->black_holes.ti_beg_max, c->black_holes.ti_beg_max * e->time_base, + e->ti_current, e->ti_current * e->time_base, e->cosmology->a); +#endif + + return (c->black_holes.ti_beg_max == e->ti_current); +} + /** * @brief Is this particle starting its time-step now ? * diff --git a/src/black_holes/EAGLE/black_holes.h b/src/black_holes/EAGLE/black_holes.h index 909057bb962cd9a21af9a708d8796f5cd18d6a8d..94962b7deea4900598a565dfd6ea90cfc6e17798 100644 --- a/src/black_holes/EAGLE/black_holes.h +++ b/src/black_holes/EAGLE/black_holes.h @@ -233,7 +233,7 @@ __attribute__((always_inline)) INLINE static void black_holes_prepare_feedback( 4. * M_PI * G * BH_mass * proton_mass / (epsilon_r * c * sigma_Thomson); /* Limit the accretion rate to the Eddington fraction */ - const double accr_rate = max(Bondi_rate, f_Edd * Eddington_rate); + const double accr_rate = min(Bondi_rate, f_Edd * Eddington_rate); bp->accretion_rate = accr_rate; /* Factor in the radiative efficiency */ diff --git a/src/cell.c b/src/cell.c index 4c6bc5b6fdb168c315f777600ea47ae19d021bb1..86a0bee9ee65499f7aa4fadd471e8f7a87ac0162 100644 --- a/src/cell.c +++ b/src/cell.c @@ -260,6 +260,7 @@ int cell_link_sparts(struct cell *c, struct spart *sparts) { #endif c->stars.parts = sparts; + c->stars.parts_rebuild = sparts; /* Fill the progeny recursively, depth-first. */ if (c->split) { @@ -1054,6 +1055,92 @@ int cell_unpack_multipoles(struct cell *restrict c, #endif } +/** + * @brief Pack the counts for star formation of the given cell and all it's + * sub-cells. + * + * @param c The #cell. + * @param pcells (output) The multipole information we pack into + * + * @return The number of packed cells. + */ +int cell_pack_sf_counts(struct cell *restrict c, + struct pcell_sf *restrict pcells) { + +#ifdef WITH_MPI + + /* Pack this cell's data. */ + pcells[0].stars.delta_from_rebuild = c->stars.parts - c->stars.parts_rebuild; + pcells[0].stars.count = c->stars.count; + pcells[0].stars.dx_max_part = c->stars.dx_max_part; + +#ifdef SWIFT_DEBUG_CHECKS + if (c->stars.parts_rebuild == NULL) + error("Star particles array at rebuild is NULL! c->depth=%d", c->depth); + + if (pcells[0].stars.delta_from_rebuild < 0) + error("Stars part pointer moved in the wrong direction!"); + + if (pcells[0].stars.delta_from_rebuild > 0 && c->depth == 0) + error("Shifting the top-level pointer is not allowed!"); +#endif + + /* Fill in the progeny, depth-first recursion. */ + int count = 1; + for (int k = 0; k < 8; k++) + if (c->progeny[k] != NULL) { + count += cell_pack_sf_counts(c->progeny[k], &pcells[count]); + } + + /* Return the number of packed values. */ + return count; + +#else + error("SWIFT was not compiled with MPI support."); + return 0; +#endif +} + +/** + * @brief Unpack the counts for star formation of a given cell and its + * sub-cells. + * + * @param c The #cell + * @param pcells The multipole information to unpack + * + * @return The number of cells created. + */ +int cell_unpack_sf_counts(struct cell *restrict c, + struct pcell_sf *restrict pcells) { + +#ifdef WITH_MPI + +#ifdef SWIFT_DEBUG_CHECKS + if (c->stars.parts_rebuild == NULL) + error("Star particles array at rebuild is NULL!"); +#endif + + /* Unpack this cell's data. */ + c->stars.count = pcells[0].stars.count; + c->stars.parts = c->stars.parts_rebuild + pcells[0].stars.delta_from_rebuild; + c->stars.dx_max_part = pcells[0].stars.dx_max_part; + + /* Fill in the progeny, depth-first recursion. */ + int count = 1; + for (int k = 0; k < 8; k++) + if (c->progeny[k] != NULL) { + count += cell_unpack_sf_counts(c->progeny[k], &pcells[count]); + } + + /* Return the number of packed values. */ + return count; + +#else + error("SWIFT was not compiled with MPI support."); + return 0; +#endif +} + /** * @brief Lock a cell for access to its array of #part and hold its parents. * @@ -1597,6 +1684,7 @@ void cell_split(struct cell *c, ptrdiff_t parts_offset, ptrdiff_t sparts_offset, c->progeny[k]->stars.count = bucket_count[k]; c->progeny[k]->stars.count_total = c->progeny[k]->stars.count; c->progeny[k]->stars.parts = &c->stars.parts[bucket_offset[k]]; + c->progeny[k]->stars.parts_rebuild = c->progeny[k]->stars.parts; } /* Now do the same song and dance for the bparts. */ @@ -2455,7 +2543,9 @@ void cell_activate_hydro_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->hydro.super) { + #ifdef SWIFT_DEBUG_CHECKS if (c->stars.sorts == NULL) error("Trying to activate un-existing c->stars.sorts"); @@ -2465,11 +2555,17 @@ void cell_activate_stars_sorts_up(struct cell *c, struct scheduler *s) { cell_activate_drift_spart(c, s); } } else { + + /* Climb up the tree and set the flags */ for (struct cell *parent = c->parent; parent != NULL && !cell_get_flag(parent, cell_flag_do_stars_sub_sort); parent = parent->parent) { + cell_set_flag(parent, cell_flag_do_stars_sub_sort); + + /* Reached the super-level? Activate the task and abort */ if (parent == c->hydro.super) { + #ifdef SWIFT_DEBUG_CHECKS if (parent->stars.sorts == NULL) error("Trying to activate un-existing parents->stars.sorts"); @@ -2486,8 +2582,10 @@ void cell_activate_stars_sorts_up(struct cell *c, struct scheduler *s) { * @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) { @@ -2559,12 +2657,12 @@ void cell_activate_subcell_hydro_tasks(struct cell *ci, struct cell *cj, /* Get the orientation of the pair. */ double shift[3]; - int sid = space_getsid(s->space, &ci, &cj, shift); + const int sid = space_getsid(s->space, &ci, &cj, shift); /* recurse? */ if (cell_can_recurse_in_pair_hydro_task(ci) && cell_can_recurse_in_pair_hydro_task(cj)) { - struct cell_split_pair *csp = &cell_split_pairs[sid]; + const struct cell_split_pair *csp = &cell_split_pairs[sid]; for (int k = 0; k < csp->count; k++) { const int pid = csp->pairs[k].pid; const int pjd = csp->pairs[k].pjd; @@ -2606,9 +2704,11 @@ void cell_activate_subcell_hydro_tasks(struct cell *ci, struct cell *cj, * @param ci The first #cell we recurse in. * @param cj The second #cell we recurse in. * @param s The task #scheduler. + * @param with_star_formation Are we running with star formation switched on? */ void cell_activate_subcell_stars_tasks(struct cell *ci, struct cell *cj, - struct scheduler *s) { + struct scheduler *s, + const int with_star_formation) { const struct engine *e = s->space->e; /* Store the current dx_max and h_max values. */ @@ -2626,9 +2726,13 @@ void cell_activate_subcell_stars_tasks(struct cell *ci, struct cell *cj, /* Self interaction? */ if (cj == NULL) { + + const int ci_active = cell_is_active_stars(ci, e) || + (with_star_formation && cell_is_active_hydro(ci, e)); + /* Do anything? */ - if (!cell_is_active_stars(ci, e) || ci->hydro.count == 0 || - ci->stars.count == 0) + if (!ci_active || ci->hydro.count == 0 || + (!with_star_formation && ci->stars.count == 0)) return; /* Recurse? */ @@ -2636,11 +2740,12 @@ void cell_activate_subcell_stars_tasks(struct cell *ci, struct cell *cj, /* Loop over all progenies and pairs of progenies */ for (int j = 0; j < 8; j++) { if (ci->progeny[j] != NULL) { - cell_activate_subcell_stars_tasks(ci->progeny[j], NULL, s); + cell_activate_subcell_stars_tasks(ci->progeny[j], NULL, s, + with_star_formation); for (int k = j + 1; k < 8; k++) if (ci->progeny[k] != NULL) cell_activate_subcell_stars_tasks(ci->progeny[j], ci->progeny[k], - s); + s, with_star_formation); } } } else { @@ -2652,29 +2757,38 @@ void cell_activate_subcell_stars_tasks(struct cell *ci, struct cell *cj, /* Otherwise, pair interation */ else { - /* Should we even bother? */ - if (!cell_is_active_stars(ci, e) && !cell_is_active_stars(cj, e)) return; /* Get the orientation of the pair. */ double shift[3]; - int sid = space_getsid(s->space, &ci, &cj, shift); + const int sid = space_getsid(s->space, &ci, &cj, shift); + + const int ci_active = cell_is_active_stars(ci, e) || + (with_star_formation && cell_is_active_hydro(ci, e)); + const int cj_active = cell_is_active_stars(cj, e) || + (with_star_formation && cell_is_active_hydro(cj, e)); + + /* Should we even bother? */ + if (!ci_active && !cj_active) return; /* recurse? */ if (cell_can_recurse_in_pair_stars_task(ci, cj) && cell_can_recurse_in_pair_stars_task(cj, ci)) { - struct cell_split_pair *csp = &cell_split_pairs[sid]; + + const struct cell_split_pair *csp = &cell_split_pairs[sid]; for (int k = 0; k < csp->count; k++) { const int pid = csp->pairs[k].pid; const int pjd = csp->pairs[k].pjd; if (ci->progeny[pid] != NULL && cj->progeny[pjd] != NULL) cell_activate_subcell_stars_tasks(ci->progeny[pid], cj->progeny[pjd], - s); + s, with_star_formation); } } /* Otherwise, activate the sorts and drifts. */ else { - if (cell_is_active_stars(ci, e)) { + + if (ci_active) { + /* 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); @@ -2691,7 +2805,8 @@ void cell_activate_subcell_stars_tasks(struct cell *ci, struct cell *cj, cell_activate_stars_sorts(ci, sid, s); } - if (cell_is_active_stars(cj, e)) { + if (cj_active) { + /* 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); @@ -2771,12 +2886,12 @@ void cell_activate_subcell_black_holes_tasks(struct cell *ci, struct cell *cj, /* Get the orientation of the pair. */ double shift[3]; - int sid = space_getsid(s->space, &ci, &cj, shift); + const int sid = space_getsid(s->space, &ci, &cj, shift); /* recurse? */ if (cell_can_recurse_in_pair_black_holes_task(ci, cj) && cell_can_recurse_in_pair_black_holes_task(cj, ci)) { - struct cell_split_pair *csp = &cell_split_pairs[sid]; + const struct cell_split_pair *csp = &cell_split_pairs[sid]; for (int k = 0; k < csp->count; k++) { const int pid = csp->pairs[k].pid; const int pjd = csp->pairs[k].pjd; @@ -2964,6 +3079,11 @@ int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s) { struct engine *e = s->space->e; const int nodeID = e->nodeID; const int with_limiter = (e->policy & engine_policy_limiter); + +#ifdef WITH_MPI + const int with_star_formation = e->policy & engine_policy_star_formation; + const int with_feedback = e->policy & engine_policy_feedback; +#endif int rebuild = 0; /* Un-skip the density tasks involved with this cell. */ @@ -3012,8 +3132,14 @@ int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s) { cell_activate_hydro_sorts(ci, t->flags, s); cell_activate_hydro_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) { + else if (t->type == task_type_sub_self) { + cell_activate_subcell_hydro_tasks(ci, NULL, s); + } + + /* Store current values of dx_max and h_max. */ + else if (t->type == task_type_sub_pair) { cell_activate_subcell_hydro_tasks(ci, cj, s); } } @@ -3076,6 +3202,20 @@ int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s) { scheduler_activate_send(s, cj->mpi.send, task_subtype_tend_part, ci_nodeID); + /* Propagating new star counts? */ + if (with_star_formation && with_feedback) { + if (ci_active && ci->hydro.count > 0) { + scheduler_activate_recv(s, ci->mpi.recv, task_subtype_sf_counts); + scheduler_activate_recv(s, ci->mpi.recv, task_subtype_tend_spart); + } + if (cj_active && cj->hydro.count > 0) { + scheduler_activate_send(s, cj->mpi.send, task_subtype_sf_counts, + ci_nodeID); + scheduler_activate_send(s, cj->mpi.send, task_subtype_tend_spart, + ci_nodeID); + } + } + } else if (cj_nodeID != nodeID) { /* If the local cell is active, receive data from the foreign cell. */ if (ci_active) { @@ -3126,6 +3266,20 @@ int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s) { if (ci_active || with_limiter) scheduler_activate_send(s, ci->mpi.send, task_subtype_tend_part, cj_nodeID); + + /* Propagating new star counts? */ + if (with_star_formation && with_feedback) { + if (cj_active && cj->hydro.count > 0) { + scheduler_activate_recv(s, cj->mpi.recv, task_subtype_sf_counts); + scheduler_activate_recv(s, cj->mpi.recv, task_subtype_tend_spart); + } + if (ci_active && ci->hydro.count > 0) { + scheduler_activate_send(s, ci->mpi.send, task_subtype_sf_counts, + cj_nodeID); + scheduler_activate_send(s, ci->mpi.send, task_subtype_tend_spart, + cj_nodeID); + } + } } #endif } @@ -3325,16 +3479,23 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) { * * @param c the #cell. * @param s the #scheduler. + * @param with_star_formation Are we running with star formation switched on? * * @return 1 If the space needs rebuilding. 0 otherwise. */ -int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s) { +int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s, + const int with_star_formation) { + struct engine *e = s->space->e; const int nodeID = e->nodeID; int rebuild = 0; - if (c->stars.drift != NULL && cell_is_active_stars(c, e)) { - cell_activate_drift_spart(c, s); + if (c->stars.drift != NULL) { + if (cell_is_active_stars(c, e) || + (with_star_formation && cell_is_active_hydro(c, e))) { + + cell_activate_drift_spart(c, s); + } } /* Un-skip the density tasks involved with this cell. */ @@ -3342,8 +3503,6 @@ int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s) { struct task *t = l->t; struct cell *ci = t->ci; struct cell *cj = t->cj; - const int ci_active = cell_is_active_stars(ci, e); - const int cj_active = (cj != NULL) ? cell_is_active_stars(cj, e) : 0; #ifdef WITH_MPI const int ci_nodeID = ci->nodeID; const int cj_nodeID = (cj != NULL) ? cj->nodeID : -1; @@ -3352,6 +3511,13 @@ int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s) { const int cj_nodeID = nodeID; #endif + const int ci_active = cell_is_active_stars(ci, e) || + (with_star_formation && cell_is_active_hydro(ci, e)); + + const int cj_active = + (cj != NULL) && (cell_is_active_stars(cj, e) || + (with_star_formation && cell_is_active_hydro(cj, e))); + /* Activate the drifts */ if (t->type == task_type_self && ci_active) { cell_activate_drift_part(ci, s); @@ -3403,8 +3569,12 @@ int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s) { } } - else if (t->type == task_type_sub_pair || t->type == task_type_sub_self) { - cell_activate_subcell_stars_tasks(ci, cj, s); + else if (t->type == task_type_sub_self) { + cell_activate_subcell_stars_tasks(ci, NULL, s, with_star_formation); + } + + else if (t->type == task_type_sub_pair) { + cell_activate_subcell_stars_tasks(ci, cj, s, with_star_formation); } } @@ -3487,8 +3657,6 @@ int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s) { struct task *t = l->t; struct cell *ci = t->ci; struct cell *cj = t->cj; - const int ci_active = cell_is_active_stars(ci, e); - const int cj_active = (cj != NULL) ? cell_is_active_stars(cj, e) : 0; #ifdef WITH_MPI const int ci_nodeID = ci->nodeID; const int cj_nodeID = (cj != NULL) ? cj->nodeID : -1; @@ -3497,6 +3665,13 @@ int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s) { const int cj_nodeID = nodeID; #endif + const int ci_active = cell_is_active_stars(ci, e) || + (with_star_formation && cell_is_active_hydro(ci, e)); + + const int cj_active = + (cj != NULL) && (cell_is_active_stars(cj, e) || + (with_star_formation && cell_is_active_hydro(cj, e))); + if (t->type == task_type_self && ci_active) { scheduler_activate(s, t); } @@ -3524,14 +3699,18 @@ int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s) { } /* Unskip all the other task types. */ - if (c->nodeID == nodeID && cell_is_active_stars(c, e)) { - if (c->stars.ghost != NULL) scheduler_activate(s, c->stars.ghost); - if (c->stars.stars_in != NULL) scheduler_activate(s, c->stars.stars_in); - if (c->stars.stars_out != NULL) scheduler_activate(s, c->stars.stars_out); - if (c->kick1 != NULL) scheduler_activate(s, c->kick1); - if (c->kick2 != NULL) scheduler_activate(s, c->kick2); - if (c->timestep != NULL) scheduler_activate(s, c->timestep); - if (c->logger != NULL) scheduler_activate(s, c->logger); + if (c->nodeID == nodeID) { + if (cell_is_active_stars(c, e) || + (with_star_formation && cell_is_active_hydro(c, e))) { + + if (c->stars.ghost != NULL) scheduler_activate(s, c->stars.ghost); + if (c->stars.stars_in != NULL) scheduler_activate(s, c->stars.stars_in); + if (c->stars.stars_out != NULL) scheduler_activate(s, c->stars.stars_out); + if (c->kick1 != NULL) scheduler_activate(s, c->kick1); + if (c->kick2 != NULL) scheduler_activate(s, c->kick2); + if (c->timestep != NULL) scheduler_activate(s, c->timestep); + if (c->logger != NULL) scheduler_activate(s, c->logger); + } } return rebuild; @@ -3599,7 +3778,11 @@ int cell_unskip_black_holes_tasks(struct cell *c, struct scheduler *s) { } } - else if (t->type == task_type_sub_pair || t->type == task_type_sub_self) { + else if (t->type == task_type_sub_self) { + cell_activate_subcell_black_holes_tasks(ci, NULL, s); + } + + else if (t->type == task_type_sub_pair) { cell_activate_subcell_black_holes_tasks(ci, cj, s); } } @@ -4556,19 +4739,68 @@ void cell_drift_multipole(struct cell *c, const struct engine *e) { * @brief Resets all the sorting properties for the stars in a given cell * hierarchy. * + * The clear_unused_flags argument can be used to additionally clean up all + * the flags demanding a sort for the given cell. This should be used with + * caution as it will prevent the sort tasks from doing anything on that cell + * until these flags are reset. + * * @param c The #cell to clean. + * @param clear_unused_flags Do we also clean the flags demanding a sort? */ -void cell_clear_stars_sort_flags(struct cell *c) { +void cell_clear_stars_sort_flags(struct cell *c, const int clear_unused_flags) { + + /* Clear the flags that have not been reset by the sort task? */ + if (clear_unused_flags) { + c->stars.requires_sorts = 0; + c->stars.do_sort = 0; + cell_clear_flag(c, cell_flag_do_stars_sub_sort); + } + + /* Indicate that the cell is not sorted and cancel the pointer sorting arrays. + */ + c->stars.sorted = 0; + cell_free_stars_sorts(c); + /* Recurse if possible */ if (c->split) { for (int k = 0; k < 8; k++) - if (c->progeny[k] != NULL) cell_clear_stars_sort_flags(c->progeny[k]); + if (c->progeny[k] != NULL) + cell_clear_stars_sort_flags(c->progeny[k], clear_unused_flags); + } +} + +/** + * @brief Resets all the sorting properties for the hydro in a given cell + * hierarchy. + * + * The clear_unused_flags argument can be used to additionally clean up all + * the flags demanding a sort for the given cell. This should be used with + * caution as it will prevent the sort tasks from doing anything on that cell + * until these flags are reset. + * + * @param c The #cell to clean. + * @param clear_unused_flags Do we also clean the flags demanding a sort? + */ +void cell_clear_hydro_sort_flags(struct cell *c, const int clear_unused_flags) { + + /* Clear the flags that have not been reset by the sort task? */ + if (clear_unused_flags) { + c->hydro.do_sort = 0; + c->hydro.requires_sorts = 0; + cell_clear_flag(c, cell_flag_do_hydro_sub_sort); } /* Indicate that the cell is not sorted and cancel the pointer sorting arrays. */ - c->stars.sorted = 0; - cell_free_stars_sorts(c); + c->hydro.sorted = 0; + cell_free_hydro_sorts(c); + + /* Recurse if possible */ + if (c->split) { + for (int k = 0; k < 8; k++) + if (c->progeny[k] != NULL) + cell_clear_hydro_sort_flags(c->progeny[k], clear_unused_flags); + } } /** @@ -4635,6 +4867,36 @@ void cell_check_spart_pos(const struct cell *c, #endif } +/** + * @brief Checks that a cell and all its progenies have cleared their sort + * flags. + * + * Should only be used for debugging purposes. + * + * @param c The #cell to check. + */ +void cell_check_sort_flags(const struct cell *c) { + +#ifdef SWIFT_DEBUG_CHECKS + const int do_hydro_sub_sort = cell_get_flag(c, cell_flag_do_hydro_sub_sort); + const int do_stars_sub_sort = cell_get_flag(c, cell_flag_do_stars_sub_sort); + + if (do_hydro_sub_sort) + error("cell %d has a hydro sub_sort flag set. Node=%d depth=%d maxdepth=%d", + c->cellID, c->nodeID, c->depth, c->maxdepth); + + if (do_stars_sub_sort) + error("cell %d has a stars sub_sort flag set. Node=%d depth=%d maxdepth=%d", + c->cellID, c->nodeID, c->depth, c->maxdepth); + + if (c->split) { + for (int k = 0; k < 8; ++k) { + if (c->progeny[k] != NULL) cell_check_sort_flags(c->progeny[k]); + } + } +#endif +} + /** * @brief Recursively update the pointer and counter for #spart after the * addition of a new particle. @@ -5024,6 +5286,11 @@ struct spart *cell_convert_part_to_spart(struct engine *e, struct cell *c, /* Did we run out of free spart slots? */ if (sp == NULL) return NULL; + /* Copy over the distance since rebuild */ + sp->x_diff[0] = xp->x_diff[0]; + sp->x_diff[1] = xp->x_diff[1]; + sp->x_diff[2] = xp->x_diff[2]; + /* Destroy the gas particle and get it's gpart friend */ struct gpart *gp = cell_convert_part_to_gpart(e, c, p, xp); diff --git a/src/cell.h b/src/cell.h index a98a1f6379e78ab23d5901269f8e90defbb1df09..4f8bed5fa5e337842bf37a0b382e3915a806a474 100644 --- a/src/cell.h +++ b/src/cell.h @@ -253,6 +253,26 @@ struct pcell_step_black_holes { float dx_max_part; }; +/** + * @brief Cell information to propagate the new counts of star particles. + */ +struct pcell_sf { + + /*! Stars variables */ + struct { + + /* Distance by which the stars pointer has moved since the last rebuild */ + ptrdiff_t delta_from_rebuild; + + /* Number of particles in the cell */ + int count; + + /*! Maximum part movement in this cell since last construction. */ + float dx_max_part; + + } stars; +}; + /** Bitmasks for the cell flags. Beware when adding flags that you don't exceed the size of the flags variable in the struct cell. */ enum cell_flags { @@ -521,6 +541,9 @@ struct cell { /*! Pointer to the #spart data. */ struct spart *parts; + /*! Pointer to the #spart data at rebuild time. */ + struct spart *parts_rebuild; + /*! The star ghost task itself */ struct task *ghost; @@ -802,6 +825,8 @@ int cell_unpack_end_step_black_holes(struct cell *c, struct pcell_step_black_holes *pcell); int cell_pack_multipoles(struct cell *c, struct gravity_tensors *m); int cell_unpack_multipoles(struct cell *c, struct gravity_tensors *m); +int cell_pack_sf_counts(struct cell *c, struct pcell_sf *pcell); +int cell_unpack_sf_counts(struct cell *c, struct pcell_sf *pcell); int cell_getsize(struct cell *c); int cell_link_parts(struct cell *c, struct part *parts); int cell_link_gparts(struct cell *c, struct gpart *gparts); @@ -822,7 +847,8 @@ void cell_check_spart_drift_point(struct cell *c, void *data); void cell_check_multipole_drift_point(struct cell *c, void *data); void cell_reset_task_counters(struct cell *c); int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s); -int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s); +int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s, + const int with_star_formation); int cell_unskip_black_holes_tasks(struct cell *c, struct scheduler *s); int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s); void cell_drift_part(struct cell *c, const struct engine *e, int force); @@ -838,7 +864,8 @@ void cell_activate_subcell_hydro_tasks(struct cell *ci, struct cell *cj, void cell_activate_subcell_grav_tasks(struct cell *ci, struct cell *cj, struct scheduler *s); void cell_activate_subcell_stars_tasks(struct cell *ci, struct cell *cj, - struct scheduler *s); + struct scheduler *s, + const int with_star_formation); void cell_activate_subcell_black_holes_tasks(struct cell *ci, struct cell *cj, struct scheduler *s); void cell_activate_subcell_external_grav_tasks(struct cell *ci, @@ -856,7 +883,9 @@ void cell_clear_limiter_flags(struct cell *c, void *data); void cell_set_super_mapper(void *map_data, int num_elements, void *extra_data); void cell_check_spart_pos(const struct cell *c, const struct spart *global_sparts); -void cell_clear_stars_sort_flags(struct cell *c); +void cell_check_sort_flags(const struct cell *c); +void cell_clear_stars_sort_flags(struct cell *c, const int unused_flags); +void cell_clear_hydro_sort_flags(struct cell *c, const int unused_flags); int cell_has_tasks(struct cell *c); void cell_remove_part(const struct engine *e, struct cell *c, struct part *p, struct xpart *xp); diff --git a/src/cooling/EAGLE/cooling.c b/src/cooling/EAGLE/cooling.c index 0b5fcde02e4005c1d8c6a3bc4ff830e435b35ad6..3fda0c80040b6ad139b9100064b937e695e6030f 100644 --- a/src/cooling/EAGLE/cooling.c +++ b/src/cooling/EAGLE/cooling.c @@ -316,11 +316,14 @@ INLINE static double bisection_iter( eagle_cooling_rate(log10(u_next_cgs), redshift, n_H_cgs, abundance_ratio, n_H_index, d_n_H, He_index, d_He, cooling); - - // Debugging +#ifdef SWIFT_DEBUG_CHECKS if (u_next_cgs <= 0) - error("u_next_cgs %.5e u_upper %.5e u_lower %.5e Lambda %.5e", u_next_cgs, - u_upper_cgs, u_lower_cgs, LambdaNet_cgs); + error( + "Got negative energy! u_next_cgs=%.5e u_upper=%.5e u_lower=%.5e " + "Lambda=%.5e", + u_next_cgs, u_upper_cgs, u_lower_cgs, LambdaNet_cgs); +#endif + /* Where do we go next? */ if (u_next_cgs - u_ini_cgs - LambdaNet_cgs * ratefact_cgs * dt_cgs > 0.0) { u_upper_cgs = u_next_cgs; diff --git a/src/engine.c b/src/engine.c index fe4be2a97d70802f37d6317109a0383a7a7f4e3e..253d8657ad0ac5231860452ff17cf68662d9a272 100644 --- a/src/engine.c +++ b/src/engine.c @@ -2117,7 +2117,8 @@ void engine_allocate_foreign_particles(struct engine *e) { } /* For stars, we just use the numbers in the top-level cells */ - count_sparts_in += e->proxies[k].cells_in[j]->stars.count; + count_sparts_in += + e->proxies[k].cells_in[j]->stars.count + space_extra_sparts; /* For black holes, we just use the numbers in the top-level cells */ count_bparts_in += e->proxies[k].cells_in[j]->black_holes.count; @@ -2208,7 +2209,8 @@ void engine_allocate_foreign_particles(struct engine *e) { /* For stars, we just use the numbers in the top-level cells */ cell_link_sparts(e->proxies[k].cells_in[j], sparts); - sparts = &sparts[e->proxies[k].cells_in[j]->stars.count]; + sparts = + &sparts[e->proxies[k].cells_in[j]->stars.count + space_extra_sparts]; /* For black holes, we just use the numbers in the top-level cells */ cell_link_bparts(e->proxies[k].cells_in[j], bparts); @@ -2563,6 +2565,8 @@ void engine_rebuild(struct engine *e, int repartitioned, for (int k = 0; k < e->s->nr_local_cells; k++) cell_check_foreign_multipole(&e->s->cells_top[e->s->local_cells_top[k]]); } + + space_check_sort_flags(e->s); #endif /* Run through the tasks and mark as skip or not. */ @@ -3333,7 +3337,8 @@ void engine_skip_force_and_kick(struct engine *e) { t->subtype == task_subtype_tend_gpart || t->subtype == task_subtype_tend_spart || t->subtype == task_subtype_tend_bpart || - t->subtype == task_subtype_rho || t->subtype == task_subtype_gpart) + t->subtype == task_subtype_rho || t->subtype == task_subtype_gpart || + t->subtype == task_subtype_sf_counts) t->skip = 1; } @@ -3850,6 +3855,7 @@ void engine_step(struct engine *e) { #ifdef SWIFT_DEBUG_CHECKS /* Make sure all woken-up particles have been processed */ space_check_limiter(e->s); + space_check_sort_flags(e->s); #endif /* Collect information about the next time-step */ diff --git a/src/engine_maketasks.c b/src/engine_maketasks.c index a9a9371a471ec58ec7f258dc87e72e94c6b45582..e1b1dcbbb2ceddbcf2dd26cc0ead72d694094990 100644 --- a/src/engine_maketasks.c +++ b/src/engine_maketasks.c @@ -232,11 +232,14 @@ void engine_addtasks_send_hydro(struct engine *e, struct cell *ci, * @param ci The sending #cell. * @param cj Dummy cell containing the nodeID of the receiving node. * @param t_feedback The send_feed #task, if it has already been created. + * @param t_sf_counts The send_sf_counts, if it has been created. * @param t_ti The recv_ti_end #task, if it has already been created. + * @param with_star_formation Are we running with star formation on? */ void engine_addtasks_send_stars(struct engine *e, struct cell *ci, struct cell *cj, struct task *t_feedback, - struct task *t_ti) { + struct task *t_sf_counts, struct task *t_ti, + const int with_star_formation) { #ifdef WITH_MPI @@ -244,6 +247,19 @@ void engine_addtasks_send_stars(struct engine *e, struct cell *ci, struct scheduler *s = &e->sched; const int nodeID = cj->nodeID; + if (t_sf_counts == NULL && with_star_formation && ci->hydro.count > 0) { +#ifdef SWIFT_DEBUG_CHECKS + if (ci->depth != 0) + error( + "Attaching a sf_count task at a non-top level c->depth=%d " + "c->count=%d", + ci->depth, ci->hydro.count); +#endif + t_sf_counts = scheduler_addtask(s, task_type_send, task_subtype_sf_counts, + ci->mpi.tag, 0, ci, cj); + scheduler_addunlock(s, ci->hydro.star_formation, t_sf_counts); + } + /* Check if any of the density tasks are for the target node. */ for (l = ci->stars.density; l != NULL; l = l->next) if (l->t->ci->nodeID == nodeID || @@ -279,13 +295,17 @@ void engine_addtasks_send_stars(struct engine *e, struct cell *ci, engine_addlink(e, &ci->mpi.send, t_feedback); engine_addlink(e, &ci->mpi.send, t_ti); + if (with_star_formation && ci->hydro.count > 0) { + engine_addlink(e, &ci->mpi.send, t_sf_counts); + } } /* Recurse? */ if (ci->split) for (int k = 0; k < 8; k++) if (ci->progeny[k] != NULL) - engine_addtasks_send_stars(e, ci->progeny[k], cj, t_feedback, t_ti); + engine_addtasks_send_stars(e, ci->progeny[k], cj, t_feedback, + t_sf_counts, t_ti, with_star_formation); #else error("SWIFT was not compiled with MPI support."); @@ -459,14 +479,30 @@ void engine_addtasks_recv_hydro(struct engine *e, struct cell *c, * @param e The #engine. * @param c The foreign #cell. * @param t_feedback The recv_feed #task, if it has already been created. + * @param t_sf_counts The recv_sf_counts, if it has been created. * @param t_ti The recv_ti_end #task, if it has already been created. + * @param with_star_formation Are we running with star formation on? */ void engine_addtasks_recv_stars(struct engine *e, struct cell *c, - struct task *t_feedback, struct task *t_ti) { + struct task *t_feedback, + struct task *t_sf_counts, struct task *t_ti, + const int with_star_formation) { #ifdef WITH_MPI struct scheduler *s = &e->sched; + if (t_sf_counts == NULL && with_star_formation && c->hydro.count > 0) { +#ifdef SWIFT_DEBUG_CHECKS + if (c->depth != 0) + error( + "Attaching a sf_count task at a non-top level c->depth=%d " + "c->count=%d", + c->depth, c->hydro.count); +#endif + t_sf_counts = scheduler_addtask(s, task_type_recv, task_subtype_sf_counts, + c->mpi.tag, 0, c, NULL); + } + /* Have we reached a level where there are any stars tasks ? */ if (t_feedback == NULL && c->stars.density != NULL) { @@ -481,11 +517,20 @@ void engine_addtasks_recv_stars(struct engine *e, struct cell *c, t_ti = scheduler_addtask(s, task_type_recv, task_subtype_tend_spart, c->mpi.tag, 0, c, NULL); + + if (with_star_formation && c->hydro.count > 0) { + + /* Receive the stars only once the counts have been received */ + scheduler_addunlock(s, t_sf_counts, t_feedback); + } } if (t_feedback != NULL) { engine_addlink(e, &c->mpi.recv, t_feedback); engine_addlink(e, &c->mpi.recv, t_ti); + if (with_star_formation && c->hydro.count > 0) { + engine_addlink(e, &c->mpi.recv, t_sf_counts); + } #ifdef SWIFT_DEBUG_CHECKS if (c->nodeID == e->nodeID) error("Local cell!"); @@ -507,7 +552,8 @@ void engine_addtasks_recv_stars(struct engine *e, struct cell *c, if (c->split) for (int k = 0; k < 8; k++) if (c->progeny[k] != NULL) - engine_addtasks_recv_stars(e, c->progeny[k], t_feedback, t_ti); + engine_addtasks_recv_stars(e, c->progeny[k], t_feedback, t_sf_counts, + t_ti, with_star_formation); #else error("SWIFT was not compiled with MPI support."); @@ -614,6 +660,7 @@ void engine_addtasks_recv_gravity(struct engine *e, struct cell *c, scheduler_addunlock(s, l->t, t_ti); } } + /* Recurse? */ if (c->split) for (int k = 0; k < 8; k++) @@ -2410,7 +2457,7 @@ void engine_addtasks_send_mapper(void *map_data, int num_elements, void *extra_data) { struct engine *e = (struct engine *)extra_data; - // const int with_limiter = (e->policy & engine_policy_limiter); + const int with_star_formation = (e->policy & engine_policy_star_formation); struct cell_type_pair *cell_type_pairs = (struct cell_type_pair *)map_data; for (int k = 0; k < num_elements; k++) { @@ -2428,7 +2475,9 @@ void engine_addtasks_send_mapper(void *map_data, int num_elements, /* Add the send tasks for the cells in the proxy that have a stars * connection. */ if ((e->policy & engine_policy_feedback) && (type & proxy_cell_type_hydro)) - engine_addtasks_send_stars(e, ci, cj, /*t_feedback=*/NULL, /*t_ti=*/NULL); + engine_addtasks_send_stars(e, ci, cj, /*t_feedback=*/NULL, + /*t_sf_counts=*/NULL, /*t_ti=*/NULL, + with_star_formation); /* Add the send tasks for the cells in the proxy that have a black holes * connection. */ @@ -2449,7 +2498,7 @@ void engine_addtasks_recv_mapper(void *map_data, int num_elements, void *extra_data) { struct engine *e = (struct engine *)extra_data; - // const int with_limiter = (e->policy & engine_policy_limiter); + const int with_star_formation = (e->policy & engine_policy_star_formation); struct cell_type_pair *cell_type_pairs = (struct cell_type_pair *)map_data; for (int k = 0; k < num_elements; k++) { @@ -2459,12 +2508,15 @@ void engine_addtasks_recv_mapper(void *map_data, int num_elements, /* Add the recv tasks for the cells in the proxy that have a hydro * connection. */ if ((e->policy & engine_policy_hydro) && (type & proxy_cell_type_hydro)) - engine_addtasks_recv_hydro(e, ci, NULL, NULL, NULL, NULL); + engine_addtasks_recv_hydro(e, ci, /*t_xv=*/NULL, /*t_rho=*/NULL, + /*t_gradient=*/NULL, /*t_ti=*/NULL); /* Add the recv tasks for the cells in the proxy that have a stars * connection. */ if ((e->policy & engine_policy_feedback) && (type & proxy_cell_type_hydro)) - engine_addtasks_recv_stars(e, ci, NULL, NULL); + engine_addtasks_recv_stars(e, ci, /*t_feedback=*/NULL, + /*t_sf_counts=*/NULL, /*t_ti=*/NULL, + with_star_formation); /* Add the recv tasks for the cells in the proxy that have a black holes * connection. */ @@ -2476,7 +2528,7 @@ void engine_addtasks_recv_mapper(void *map_data, int num_elements, * connection. */ if ((e->policy & engine_policy_self_gravity) && (type & proxy_cell_type_gravity)) - engine_addtasks_recv_gravity(e, ci, NULL, NULL); + engine_addtasks_recv_gravity(e, ci, /*t_grav=*/NULL, /*t_ti=*/NULL); } } diff --git a/src/engine_marktasks.c b/src/engine_marktasks.c index ba52dd48de43b1388735a440f2a6f842dfbc22c6..0971c95bab862326e6c45cfb664c5cccca9cc0f2 100644 --- a/src/engine_marktasks.c +++ b/src/engine_marktasks.c @@ -70,6 +70,10 @@ void engine_marktasks_mapper(void *map_data, int num_elements, struct engine *e = (struct engine *)((size_t *)extra_data)[0]; const int nodeID = e->nodeID; const int with_limiter = e->policy & engine_policy_limiter; + const int with_star_formation = e->policy & engine_policy_star_formation; +#ifdef WITH_MPI + const int with_feedback = e->policy & engine_policy_feedback; +#endif for (int ind = 0; ind < num_elements; ind++) { @@ -84,11 +88,18 @@ void engine_marktasks_mapper(void *map_data, int num_elements, /* Local pointer. */ struct cell *ci = t->ci; +#ifdef SWIFT_DEBUG_CHECKS if (ci->nodeID != nodeID) error("Non-local self task found"); +#endif + const int ci_active_hydro = cell_is_active_hydro(ci, e); + const int ci_active_gravity = cell_is_active_gravity(ci, e); + const int ci_active_black_holes = cell_is_active_black_holes(ci, e); + const int ci_active_stars = cell_is_active_stars(ci, e) || + (with_star_formation && ci_active_hydro); /* Activate the hydro drift */ if (t_type == task_type_self && t_subtype == task_subtype_density) { - if (cell_is_active_hydro(ci, e)) { + if (ci_active_hydro) { scheduler_activate(s, t); cell_activate_drift_part(ci, s); if (with_limiter) cell_activate_limiter(ci, s); @@ -98,7 +109,7 @@ void engine_marktasks_mapper(void *map_data, int num_elements, /* Store current values of dx_max and h_max. */ else if (t_type == task_type_sub_self && t_subtype == task_subtype_density) { - if (cell_is_active_hydro(ci, e)) { + if (ci_active_hydro) { scheduler_activate(s, t); cell_activate_subcell_hydro_tasks(ci, NULL, s); if (with_limiter) cell_activate_limiter(ci, s); @@ -106,37 +117,37 @@ void engine_marktasks_mapper(void *map_data, int num_elements, } else if (t_type == task_type_self && t_subtype == task_subtype_force) { - if (cell_is_active_hydro(ci, e)) scheduler_activate(s, t); + if (ci_active_hydro) scheduler_activate(s, t); } else if (t_type == task_type_sub_self && t_subtype == task_subtype_force) { - if (cell_is_active_hydro(ci, e)) scheduler_activate(s, t); + if (ci_active_hydro) scheduler_activate(s, t); } else if (t->type == task_type_self && t->subtype == task_subtype_limiter) { - if (cell_is_active_hydro(ci, e)) scheduler_activate(s, t); + if (ci_active_hydro) scheduler_activate(s, t); } else if (t->type == task_type_sub_self && t->subtype == task_subtype_limiter) { - if (cell_is_active_hydro(ci, e)) scheduler_activate(s, t); + if (ci_active_hydro) scheduler_activate(s, t); } else if (t_type == task_type_self && t_subtype == task_subtype_gradient) { - if (cell_is_active_hydro(ci, e)) scheduler_activate(s, t); + if (ci_active_hydro) scheduler_activate(s, t); } else if (t_type == task_type_sub_self && t_subtype == task_subtype_gradient) { - if (cell_is_active_hydro(ci, e)) scheduler_activate(s, t); + if (ci_active_hydro) scheduler_activate(s, t); } /* Activate the star density */ else if (t_type == task_type_self && t_subtype == task_subtype_stars_density) { - if (cell_is_active_stars(ci, e)) { + if (ci_active_stars) { scheduler_activate(s, t); cell_activate_drift_part(ci, s); cell_activate_drift_spart(ci, s); @@ -146,28 +157,28 @@ void engine_marktasks_mapper(void *map_data, int num_elements, /* Store current values of dx_max and h_max. */ else if (t_type == task_type_sub_self && t_subtype == task_subtype_stars_density) { - if (cell_is_active_stars(ci, e)) { + if (ci_active_stars) { scheduler_activate(s, t); - cell_activate_subcell_stars_tasks(ci, NULL, s); + cell_activate_subcell_stars_tasks(ci, NULL, s, with_star_formation); } } else if (t_type == task_type_self && t_subtype == task_subtype_stars_feedback) { - if (cell_is_active_stars(ci, e)) { + if (ci_active_stars) { scheduler_activate(s, t); } } else if (t_type == task_type_sub_self && t_subtype == task_subtype_stars_feedback) { - if (cell_is_active_stars(ci, e)) scheduler_activate(s, t); + if (ci_active_stars) scheduler_activate(s, t); } /* Activate the black hole density */ else if (t_type == task_type_self && t_subtype == task_subtype_bh_density) { - if (cell_is_active_black_holes(ci, e)) { + if (ci_active_black_holes) { scheduler_activate(s, t); cell_activate_drift_part(ci, s); cell_activate_drift_bpart(ci, s); @@ -177,7 +188,7 @@ void engine_marktasks_mapper(void *map_data, int num_elements, /* Store current values of dx_max and h_max. */ else if (t_type == task_type_sub_self && t_subtype == task_subtype_bh_density) { - if (cell_is_active_black_holes(ci, e)) { + if (ci_active_black_holes) { scheduler_activate(s, t); cell_activate_subcell_black_holes_tasks(ci, NULL, s); } @@ -185,19 +196,19 @@ void engine_marktasks_mapper(void *map_data, int num_elements, else if (t_type == task_type_self && t_subtype == task_subtype_bh_feedback) { - if (cell_is_active_black_holes(ci, e)) { + if (ci_active_black_holes) { scheduler_activate(s, t); } } else if (t_type == task_type_sub_self && t_subtype == task_subtype_bh_feedback) { - if (cell_is_active_black_holes(ci, e)) scheduler_activate(s, t); + if (ci_active_black_holes) scheduler_activate(s, t); } /* Activate the gravity drift */ else if (t_type == task_type_self && t_subtype == task_subtype_grav) { - if (cell_is_active_gravity(ci, e)) { + if (ci_active_gravity) { scheduler_activate(s, t); cell_activate_subcell_grav_tasks(t->ci, NULL, s); } @@ -206,7 +217,7 @@ void engine_marktasks_mapper(void *map_data, int num_elements, /* Activate the gravity drift */ else if (t_type == task_type_self && t_subtype == task_subtype_external_grav) { - if (cell_is_active_gravity(ci, e)) { + if (ci_active_gravity) { scheduler_activate(s, t); cell_activate_drift_gpart(t->ci, s); } @@ -238,12 +249,14 @@ void engine_marktasks_mapper(void *map_data, int num_elements, const int ci_active_gravity = cell_is_active_gravity(ci, e); const int cj_active_gravity = cell_is_active_gravity(cj, e); - const int ci_active_stars = cell_is_active_stars(ci, e); - const int cj_active_stars = cell_is_active_stars(cj, e); - const int ci_active_black_holes = cell_is_active_black_holes(ci, e); const int cj_active_black_holes = cell_is_active_black_holes(cj, e); + const int ci_active_stars = cell_is_active_stars(ci, e) || + (with_star_formation && ci_active_hydro); + const int cj_active_stars = cell_is_active_stars(cj, e) || + (with_star_formation && cj_active_hydro); + /* Only activate tasks that involve a local active cell. */ if ((t_subtype == task_subtype_density || t_subtype == task_subtype_gradient || @@ -338,7 +351,7 @@ void engine_marktasks_mapper(void *map_data, int num_elements, /* Store current values of dx_max and h_max. */ else if (t_type == task_type_sub_pair && t_subtype == task_subtype_stars_density) { - cell_activate_subcell_stars_tasks(ci, cj, s); + cell_activate_subcell_stars_tasks(ci, cj, s, with_star_formation); } } @@ -492,6 +505,20 @@ void engine_marktasks_mapper(void *map_data, int num_elements, scheduler_activate_send(s, cj->mpi.send, task_subtype_tend_part, ci_nodeID); + /* Propagating new star counts? */ + if (with_star_formation && with_feedback) { + if (ci_active_hydro && ci->hydro.count > 0) { + scheduler_activate_recv(s, ci->mpi.recv, task_subtype_sf_counts); + scheduler_activate_recv(s, ci->mpi.recv, task_subtype_tend_spart); + } + if (cj_active_hydro && cj->hydro.count > 0) { + scheduler_activate_send(s, cj->mpi.send, task_subtype_sf_counts, + ci_nodeID); + scheduler_activate_send(s, cj->mpi.send, task_subtype_tend_spart, + ci_nodeID); + } + } + } else if (cj_nodeID != nodeID) { /* If the local cell is active, receive data from the foreign cell. */ @@ -538,6 +565,20 @@ void engine_marktasks_mapper(void *map_data, int num_elements, if (ci_active_hydro) scheduler_activate_send(s, ci->mpi.send, task_subtype_tend_part, cj_nodeID); + + /* Propagating new star counts? */ + if (with_star_formation && with_feedback) { + if (cj_active_hydro && cj->hydro.count > 0) { + scheduler_activate_recv(s, cj->mpi.recv, task_subtype_sf_counts); + scheduler_activate_recv(s, cj->mpi.recv, task_subtype_tend_spart); + } + if (ci_active_hydro && ci->hydro.count > 0) { + scheduler_activate_send(s, ci->mpi.send, task_subtype_sf_counts, + cj_nodeID); + scheduler_activate_send(s, ci->mpi.send, task_subtype_tend_spart, + cj_nodeID); + } + } } #endif } @@ -830,12 +871,16 @@ void engine_marktasks_mapper(void *map_data, int num_elements, /* Star ghost tasks ? */ else if (t_type == task_type_stars_ghost) { - if (cell_is_active_stars(t->ci, e)) scheduler_activate(s, t); + if (cell_is_active_stars(t->ci, e) || + (with_star_formation && cell_is_active_hydro(t->ci, e))) + scheduler_activate(s, t); } /* Feedback implicit tasks? */ else if (t_type == task_type_stars_in || t_type == task_type_stars_out) { - if (cell_is_active_stars(t->ci, e)) scheduler_activate(s, t); + if (cell_is_active_stars(t->ci, e) || + (with_star_formation && cell_is_active_hydro(t->ci, e))) + scheduler_activate(s, t); } /* Black hole ghost tasks ? */ diff --git a/src/feedback/EAGLE/feedback.c b/src/feedback/EAGLE/feedback.c index c6bffce2cae2ca6b536cf7046076d38ef3ab544a..f7e714b21efdf6987e9a683a0873211eea8e13b7 100644 --- a/src/feedback/EAGLE/feedback.c +++ b/src/feedback/EAGLE/feedback.c @@ -138,14 +138,18 @@ INLINE static void compute_SNII_feedback( const float ngb_gas_mass, const struct feedback_props* feedback_props) { /* Time after birth considered for SNII feedback (internal units) */ - const float SNII_wind_delay = feedback_props->SNII_wind_delay; + const double SNII_wind_delay = feedback_props->SNII_wind_delay; /* Are we doing feedback this step? */ if (star_age <= SNII_wind_delay && (star_age + dt) > SNII_wind_delay) { + if (sp->f_E != -1.f) { #ifdef SWIFT_DEBUG_CHECKS - if (sp->f_E != -1.f) error("Star has already done feedback!"); + message("Star has already done feedback! sp->id=%lld age=%e d=%e", sp->id, + star_age, dt); #endif + return; + } /* Properties of the model (all in internal units) */ const double delta_T = @@ -685,8 +689,8 @@ INLINE static void evolve_AGB(const float log10_min_mass, float log10_max_mass, */ void compute_stellar_evolution(const struct feedback_props* feedback_props, const struct cosmology* cosmo, struct spart* sp, - const struct unit_system* us, const float age, - const float dt) { + const struct unit_system* us, const double age, + const double dt) { TIMER_TIC; @@ -843,9 +847,9 @@ void feedback_props_init(struct feedback_props* fp, /* Properties of the SNII energy feedback model ------------------------- */ /* Set the delay time before SNII occur */ - const float Gyr_in_cgs = 1e9 * 365 * 24 * 3600; + const double Gyr_in_cgs = 1.0e9 * 365. * 24. * 3600.; fp->SNII_wind_delay = - parser_get_param_float(params, "EAGLEFeedback:SNII_wind_delay_Gyr") * + parser_get_param_double(params, "EAGLEFeedback:SNII_wind_delay_Gyr") * Gyr_in_cgs / units_cgs_conversion_factor(us, UNIT_CONV_TIME); /* Read the temperature change to use in stochastic heating */ diff --git a/src/feedback/EAGLE/feedback.h b/src/feedback/EAGLE/feedback.h index 4f341a00fcc333190210ab446c738090647855ed..d6237adae9f87ce75b1a4f56f3d358fdc75d103d 100644 --- a/src/feedback/EAGLE/feedback.h +++ b/src/feedback/EAGLE/feedback.h @@ -30,8 +30,8 @@ void compute_stellar_evolution(const struct feedback_props* feedback_props, const struct cosmology* cosmo, struct spart* sp, - const struct unit_system* us, const float age, - const float dt); + const struct unit_system* us, const double age, + const double dt); /** * @brief Should we do feedback for this star? diff --git a/src/feedback/EAGLE/feedback_iact.h b/src/feedback/EAGLE/feedback_iact.h index 63d5332f4d7eed815d7e32119d3ce6db67eb3af6..f1096beec2e1beb92fcdd92ed3f47da49d9fe439 100644 --- a/src/feedback/EAGLE/feedback_iact.h +++ b/src/feedback/EAGLE/feedback_iact.h @@ -116,7 +116,8 @@ runner_iact_nonsym_feedback_apply(const float r2, const float *dx, #ifdef SWIFT_DEBUG_CHECKS if (Omega_frac < 0. || Omega_frac > 1.) - error("Invalid fraction of material to dsitribute."); + error("Invalid fraction of material to distribute. Omega_frac=%e", + Omega_frac); #endif /* Update particle mass */ diff --git a/src/feedback/EAGLE/feedback_properties.h b/src/feedback/EAGLE/feedback_properties.h index 3e6a90fb954ffaf2401bdd5bfe41a571b47254a7..931d5146b6d648a6b083830662bd6b1e57635b2a 100644 --- a/src/feedback/EAGLE/feedback_properties.h +++ b/src/feedback/EAGLE/feedback_properties.h @@ -201,7 +201,7 @@ struct feedback_props { float num_SNII_per_msun; /*! Wind delay time for SNII */ - float SNII_wind_delay; + double SNII_wind_delay; /*! Temperature increase induced by SNe feedback */ float SNe_deltaT_desired; diff --git a/src/runner.c b/src/runner.c index 19b837812bde3f73a291e44c8978b637c39c3a39..061698da118e3afb50467020a1d3494d9418ea16 100644 --- a/src/runner.c +++ b/src/runner.c @@ -171,6 +171,11 @@ void runner_do_stars_ghost(struct runner *r, struct cell *c, int timer) { TIMER_TIC; +#ifdef SWIFT_DEBUG_CHECKS + if (c->nodeID != e->nodeID) + error("Running the star ghost on a foreign node!"); +#endif + /* Anything to do here? */ if (c->stars.count == 0) return; if (!cell_is_active_stars(c, e)) return; @@ -1095,6 +1100,9 @@ void runner_do_star_formation(struct runner *r, struct cell *c, int timer) { /* Did we get a star? (Or did we run out of spare ones?) */ if (sp != NULL) { + /* message("We formed a star id=%lld cellID=%d", sp->id, + * c->cellID); */ + /* Copy the properties of the gas particle to the star particle */ star_formation_copy_properties(p, xp, sp, e, sf_props, cosmo, with_cosmology, phys_const, @@ -1128,7 +1136,7 @@ void runner_do_star_formation(struct runner *r, struct cell *c, int timer) { if (with_feedback && (c == c->top) && (current_stars_count != c->stars.count)) { - cell_clear_stars_sort_flags(c); + cell_clear_stars_sort_flags(c, /*clear_unused_flags=*/0); runner_do_all_stars_sort(r, c); } @@ -1303,15 +1311,25 @@ void runner_do_hydro_sort(struct runner *r, struct cell *c, int flags, float dx_max_sort = 0.0f; float dx_max_sort_old = 0.0f; for (int k = 0; k < 8; k++) { - if (c->progeny[k] != NULL && c->progeny[k]->hydro.count > 0) { - /* Only propagate cleanup if the progeny is stale. */ - runner_do_hydro_sort(r, c->progeny[k], flags, - cleanup && (c->progeny[k]->hydro.dx_max_sort_old > - space_maxreldx * c->progeny[k]->dmin), - 0); - dx_max_sort = max(dx_max_sort, c->progeny[k]->hydro.dx_max_sort); - dx_max_sort_old = - max(dx_max_sort_old, c->progeny[k]->hydro.dx_max_sort_old); + if (c->progeny[k] != NULL) { + + if (c->progeny[k]->hydro.count > 0) { + + /* Only propagate cleanup if the progeny is stale. */ + runner_do_hydro_sort( + r, c->progeny[k], flags, + cleanup && (c->progeny[k]->hydro.dx_max_sort_old > + space_maxreldx * c->progeny[k]->dmin), + 0); + dx_max_sort = max(dx_max_sort, c->progeny[k]->hydro.dx_max_sort); + dx_max_sort_old = + max(dx_max_sort_old, c->progeny[k]->hydro.dx_max_sort_old); + } else { + + /* We need to clean up the unused flags that were in case the + number of particles in the cell would change */ + cell_clear_hydro_sort_flags(c->progeny[k], /*clear_unused_flags=*/1); + } } } c->hydro.dx_max_sort = dx_max_sort; @@ -1526,15 +1544,24 @@ void runner_do_stars_sort(struct runner *r, struct cell *c, int flags, float dx_max_sort = 0.0f; float dx_max_sort_old = 0.0f; for (int k = 0; k < 8; k++) { - if (c->progeny[k] != NULL && c->progeny[k]->stars.count > 0) { - /* Only propagate cleanup if the progeny is stale. */ - const int cleanup_prog = - cleanup && (c->progeny[k]->stars.dx_max_sort_old > - space_maxreldx * c->progeny[k]->dmin); - runner_do_stars_sort(r, c->progeny[k], flags, cleanup_prog, 0); - dx_max_sort = max(dx_max_sort, c->progeny[k]->stars.dx_max_sort); - dx_max_sort_old = - max(dx_max_sort_old, c->progeny[k]->stars.dx_max_sort_old); + if (c->progeny[k] != NULL) { + + if (c->progeny[k]->stars.count > 0) { + + /* Only propagate cleanup if the progeny is stale. */ + const int cleanup_prog = + cleanup && (c->progeny[k]->stars.dx_max_sort_old > + space_maxreldx * c->progeny[k]->dmin); + runner_do_stars_sort(r, c->progeny[k], flags, cleanup_prog, 0); + dx_max_sort = max(dx_max_sort, c->progeny[k]->stars.dx_max_sort); + dx_max_sort_old = + max(dx_max_sort_old, c->progeny[k]->stars.dx_max_sort_old); + } else { + + /* We need to clean up the unused flags that were in case the + number of particles in the cell would change */ + cell_clear_stars_sort_flags(c->progeny[k], /*clear_unused_flags=*/1); + } } } c->stars.dx_max_sort = dx_max_sort; @@ -1694,6 +1721,8 @@ void runner_do_all_hydro_sort(struct runner *r, struct cell *c) { if (c->nodeID != engine_rank) error("Function called on a foreign cell!"); #endif + if (!cell_is_active_hydro(c, r->e)) return; + /* Shall we sort at this level? */ if (c->hydro.super == c) { @@ -2337,27 +2366,36 @@ static void runner_do_unskip_hydro(struct cell *c, struct engine *e) { * * @param c The cell. * @param e The engine. + * @param with_star_formation Are we running with star formation switched on? */ -static void runner_do_unskip_stars(struct cell *c, struct engine *e) { +static void runner_do_unskip_stars(struct cell *c, struct engine *e, + const int with_star_formation) { + + const int non_empty = + c->stars.count > 0 || (with_star_formation && c->hydro.count > 0); /* Ignore empty cells. */ - if (c->stars.count == 0) return; + if (!non_empty) return; + + const int ci_active = cell_is_active_stars(c, e) || + (with_star_formation && cell_is_active_hydro(c, e)); /* Skip inactive cells. */ - if (!cell_is_active_stars(c, e)) return; + if (!ci_active) return; /* Recurse */ if (c->split) { for (int k = 0; k < 8; k++) { if (c->progeny[k] != NULL) { struct cell *cp = c->progeny[k]; - runner_do_unskip_stars(cp, e); + runner_do_unskip_stars(cp, e, with_star_formation); } } } /* Unskip any active tasks. */ - const int forcerebuild = cell_unskip_stars_tasks(c, &e->sched); + const int forcerebuild = + cell_unskip_stars_tasks(c, &e->sched, with_star_formation); if (forcerebuild) atomic_inc(&e->forcerebuild); } @@ -2429,6 +2467,7 @@ void runner_do_unskip_mapper(void *map_data, int num_elements, void *extra_data) { struct engine *e = (struct engine *)extra_data; + const int with_star_formation = e->policy & engine_policy_star_formation; const int nodeID = e->nodeID; struct space *s = e->s; int *local_cells = (int *)map_data; @@ -2446,7 +2485,8 @@ void runner_do_unskip_mapper(void *map_data, int num_elements, runner_do_unskip_gravity(c, e); /* Stars tasks */ - if (e->policy & engine_policy_stars) runner_do_unskip_stars(c, e); + if (e->policy & engine_policy_stars) + runner_do_unskip_stars(c, e, with_star_formation); /* Black hole tasks */ if (e->policy & engine_policy_black_holes) @@ -2547,7 +2587,7 @@ void runner_do_kick1(struct runner *r, struct cell *c, int timer) { /* Anything to do here? */ if (!cell_is_starting_hydro(c, e) && !cell_is_starting_gravity(c, e) && - !cell_is_starting_stars(c, e)) + !cell_is_starting_stars(c, e) && !cell_is_starting_black_holes(c, e)) return; /* Recurse? */ @@ -2731,7 +2771,7 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { /* Anything to do here? */ if (!cell_is_active_hydro(c, e) && !cell_is_active_gravity(c, e) && - !cell_is_active_stars(c, e)) + !cell_is_active_stars(c, e) && !cell_is_active_black_holes(c, e)) return; /* Recurse? */ @@ -3818,14 +3858,15 @@ void runner_do_recv_spart(struct runner *r, struct cell *c, int clear_sorts, ti_stars_end_min = min(ti_stars_end_min, c->progeny[k]->stars.ti_end_min); ti_stars_end_max = - max(ti_stars_end_max, c->progeny[k]->grav.ti_end_max); + max(ti_stars_end_max, c->progeny[k]->stars.ti_end_max); h_max = max(h_max, c->progeny[k]->stars.h_max); } } } #ifdef SWIFT_DEBUG_CHECKS - if (ti_stars_end_min < ti_current) + if (ti_stars_end_min < ti_current && + !(r->e->policy & engine_policy_star_formation)) error( "Received a cell at an incorrect time c->ti_end_min=%lld, " "e->ti_current=%lld.", @@ -3904,7 +3945,7 @@ void runner_do_recv_bpart(struct runner *r, struct cell *c, int clear_sorts, ti_black_holes_end_min = min(ti_black_holes_end_min, c->progeny[k]->black_holes.ti_end_min); ti_black_holes_end_max = - max(ti_black_holes_end_max, c->progeny[k]->grav.ti_end_max); + max(ti_black_holes_end_max, c->progeny[k]->black_holes.ti_end_max); h_max = max(h_max, c->progeny[k]->black_holes.h_max); } } @@ -4162,14 +4203,13 @@ void *runner_main(void *data) { case task_type_send: if (t->subtype == task_subtype_tend_part) { free(t->buff); - } - if (t->subtype == task_subtype_tend_gpart) { + } else if (t->subtype == task_subtype_tend_gpart) { free(t->buff); - } - if (t->subtype == task_subtype_tend_spart) { + } else if (t->subtype == task_subtype_tend_spart) { free(t->buff); - } - if (t->subtype == task_subtype_tend_bpart) { + } else if (t->subtype == task_subtype_tend_bpart) { + free(t->buff); + } else if (t->subtype == task_subtype_sf_counts) { free(t->buff); } break; @@ -4187,6 +4227,10 @@ void *runner_main(void *data) { cell_unpack_end_step_black_holes( ci, (struct pcell_step_black_holes *)t->buff); free(t->buff); + } else if (t->subtype == task_subtype_sf_counts) { + cell_unpack_sf_counts(ci, (struct pcell_sf *)t->buff); + cell_clear_stars_sort_flags(ci, /*clear_unused_flags=*/0); + free(t->buff); } else if (t->subtype == task_subtype_xv) { runner_do_recv_part(r, ci, 1, 1); } else if (t->subtype == task_subtype_rho) { diff --git a/src/scheduler.c b/src/scheduler.c index 2c46fd87e4076e9628792504d6ce1ca5d0b738e7..6a58d657105a28e6882275c21b81125253db392c 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -1665,6 +1665,13 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) { err = MPI_Irecv(t->buff, t->ci->mpi.pcell_size, multipole_mpi_type, t->ci->nodeID, t->flags, subtaskMPI_comms[t->subtype], &t->req); + } else if (t->subtype == task_subtype_sf_counts) { + t->buff = (struct pcell_sf *)malloc(sizeof(struct pcell_sf) * + t->ci->mpi.pcell_size); + err = MPI_Irecv(t->buff, + t->ci->mpi.pcell_size * sizeof(struct pcell_sf), + MPI_BYTE, t->ci->nodeID, t->flags, + subtaskMPI_comms[t->subtype], &t->req); } else { error("Unknown communication sub-type"); } @@ -1800,6 +1807,14 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) { err = MPI_Isend(t->buff, t->ci->mpi.pcell_size, multipole_mpi_type, t->cj->nodeID, t->flags, subtaskMPI_comms[t->subtype], &t->req); + } else if (t->subtype == task_subtype_sf_counts) { + t->buff = (struct pcell_sf *)malloc(sizeof(struct pcell_sf) * + t->ci->mpi.pcell_size); + cell_pack_sf_counts(t->ci, (struct pcell_sf *)t->buff); + err = MPI_Isend(t->buff, + t->ci->mpi.pcell_size * sizeof(struct pcell_sf), + MPI_BYTE, t->cj->nodeID, t->flags, + subtaskMPI_comms[t->subtype], &t->req); } else { error("Unknown communication sub-type"); } diff --git a/src/space.c b/src/space.c index 1712e512e5b65bfbe71231fc2cbaba20447a5a8e..1c5023c3b79aab472b40756072c01870eb50dcd4 100644 --- a/src/space.c +++ b/src/space.c @@ -266,6 +266,7 @@ void space_rebuild_recycle_mapper(void *map_data, int num_elements, c->hydro.xparts = NULL; c->grav.parts = NULL; c->stars.parts = NULL; + c->stars.parts_rebuild = NULL; c->black_holes.parts = NULL; c->flags = 0; c->hydro.ti_end_min = -1; @@ -1874,6 +1875,9 @@ void space_rebuild(struct space *s, int repartitioned, int verbose) { c->stars.parts = sfinger; c->black_holes.parts = bfinger; + /* Store the state at rebuild time */ + c->stars.parts_rebuild = c->stars.parts; + c->hydro.count_total = c->hydro.count + space_extra_parts; c->grav.count_total = c->grav.count + space_extra_gparts; c->stars.count_total = c->stars.count + space_extra_sparts; @@ -3700,8 +3704,8 @@ void space_split_mapper(void *map_data, int num_cells, void *extra_data) { void space_recycle(struct space *s, struct cell *c) { /* Clear the cell. */ - if (lock_destroy(&c->lock) != 0 || lock_destroy(&c->grav.plock) != 0 || - lock_destroy(&c->mlock) != 0 || lock_destroy(&c->stars.lock) != 0 || + if (lock_destroy(&c->hydro.lock) != 0 || lock_destroy(&c->grav.plock) != 0 || + lock_destroy(&c->grav.mlock) != 0 || lock_destroy(&c->stars.lock) != 0 || lock_destroy(&c->black_holes.lock) != 0 || lock_destroy(&c->stars.star_formation_lock)) error("Failed to destroy spinlocks."); @@ -3751,8 +3755,10 @@ void space_recycle_list(struct space *s, struct cell *cell_list_begin, /* Clean up the list of cells. */ for (struct cell *c = cell_list_begin; c != NULL; c = c->next) { /* Clear the cell. */ - if (lock_destroy(&c->lock) != 0 || lock_destroy(&c->grav.plock) != 0 || - lock_destroy(&c->mlock) != 0 || lock_destroy(&c->stars.lock) != 0 || + if (lock_destroy(&c->hydro.lock) != 0 || + lock_destroy(&c->grav.plock) != 0 || + lock_destroy(&c->grav.mlock) != 0 || + lock_destroy(&c->stars.lock) != 0 || lock_destroy(&c->black_holes.lock) != 0 || lock_destroy(&c->stars.star_formation_lock)) error("Failed to destroy spinlocks."); @@ -3899,6 +3905,7 @@ void space_list_useful_top_level_cells(struct space *s) { const int has_particles = (c->hydro.count > 0) || (c->grav.count > 0) || (c->stars.count > 0) || + (c->black_holes.count > 0) || (c->grav.multipole != NULL && c->grav.multipole->m_pole.M_000 > 0.f); if (has_particles) { @@ -5185,6 +5192,41 @@ void space_check_limiter(struct space *s) { #endif } +void space_check_sort_flags_mapper(void *map_data, int nr_cells, + void *extra_data) { + +#ifdef SWIFT_DEBUG_CHECKS + + const struct space *s = (struct space *)extra_data; + int *local_cells_top = map_data; + + for (int ind = 0; ind < nr_cells; ++ind) { + const struct cell *c = &s->cells_top[local_cells_top[ind]]; + + cell_check_sort_flags(c); + } + +#endif +} + +/** + * @brief Checks that all cells have cleared their sort flags. + * + * Should only be used for debugging purposes. + * + * @param s The #space to check. + */ +void space_check_sort_flags(struct space *s) { +#ifdef SWIFT_DEBUG_CHECKS + + threadpool_map(&s->e->threadpool, space_check_sort_flags_mapper, + s->local_cells_with_tasks_top, s->nr_local_cells_with_tasks, + sizeof(int), 1, s); +#else + error("Calling debugging code without debugging flag activated."); +#endif +} + /** * @brief Resets all the individual cell task counters to 0. * diff --git a/src/space.h b/src/space.h index 4a2d5d8ce92d49ef129fc32c9332bc811e67f795..88f38209e7d8d82b021cd518dfa9806e4ec844eb 100644 --- a/src/space.h +++ b/src/space.h @@ -354,6 +354,7 @@ void space_check_top_multipoles_drift_point(struct space *s, integertime_t ti_drift); void space_check_timesteps(struct space *s); void space_check_limiter(struct space *s); +void space_check_sort_flags(struct space *s); void space_replicate(struct space *s, int replicate, int verbose); void space_generate_gas(struct space *s, const struct cosmology *cosmo, int periodic, const double dim[3], int verbose); diff --git a/src/task.c b/src/task.c index ee2f9eb6b9cc74a28d581c4e4c42157d38b2e2ba..77731ae02f8c84597565717319241997a77fadf7 100644 --- a/src/task.c +++ b/src/task.c @@ -101,8 +101,8 @@ const char *subtaskID_names[task_subtype_count] = { "limiter", "grav", "external_grav", "tend_part", "tend_gpart", "tend_spart", "tend_bpart", "xv", "rho", "gpart", "multipole", "spart", - "stars_density", "stars_feedback", "bpart", "bh_density", - "bh_feedback"}; + "stars_density", "stars_feedback", "sf_count", "bpart", + "bh_density", "bh_feedback"}; #ifdef WITH_MPI /* MPI communicators for the subtypes. */ @@ -407,9 +407,8 @@ void task_unlock(struct task *t) { if (subtype == task_subtype_grav) { cell_gunlocktree(ci); cell_munlocktree(ci); - } else if (subtype == task_subtype_stars_density) { - cell_sunlocktree(ci); - } else if (subtype == task_subtype_stars_feedback) { + } else if ((subtype == task_subtype_stars_density) || + (subtype == task_subtype_stars_feedback)) { cell_sunlocktree(ci); cell_unlocktree(ci); } else { @@ -424,10 +423,8 @@ void task_unlock(struct task *t) { cell_gunlocktree(cj); cell_munlocktree(ci); cell_munlocktree(cj); - } else if (subtype == task_subtype_stars_density) { - cell_sunlocktree(ci); - cell_sunlocktree(cj); - } else if (subtype == task_subtype_stars_feedback) { + } else if ((subtype == task_subtype_stars_density) || + (subtype == task_subtype_stars_feedback)) { cell_sunlocktree(ci); cell_sunlocktree(cj); cell_unlocktree(ci); @@ -544,10 +541,8 @@ int task_lock(struct task *t) { cell_gunlocktree(ci); return 0; } - } else if (subtype == task_subtype_stars_density) { - if (ci->stars.hold) return 0; - if (cell_slocktree(ci) != 0) return 0; - } else if (subtype == task_subtype_stars_feedback) { + } else if ((subtype == task_subtype_stars_density) || + (subtype == task_subtype_stars_feedback)) { if (ci->stars.hold) return 0; if (ci->hydro.hold) return 0; if (cell_slocktree(ci) != 0) return 0; @@ -580,14 +575,8 @@ int task_lock(struct task *t) { cell_munlocktree(ci); return 0; } - } else if (subtype == task_subtype_stars_density) { - if (ci->stars.hold || cj->stars.hold) return 0; - if (cell_slocktree(ci) != 0) return 0; - if (cell_slocktree(cj) != 0) { - cell_sunlocktree(ci); - return 0; - } - } else if (subtype == task_subtype_stars_feedback) { + } else if ((subtype == task_subtype_stars_density) || + (subtype == task_subtype_stars_feedback)) { /* Lock the stars and the gas particles in both cells */ if (ci->stars.hold || cj->stars.hold) return 0; if (ci->hydro.hold || cj->hydro.hold) return 0; diff --git a/src/task.h b/src/task.h index 14d1f8518dde3fa574d01a3d500b9dedf53b8825..eef0aca5fb075725fb1da51ccaf4033a3608e078 100644 --- a/src/task.h +++ b/src/task.h @@ -114,6 +114,7 @@ enum task_subtypes { task_subtype_spart, task_subtype_stars_density, task_subtype_stars_feedback, + task_subtype_sf_counts, task_subtype_bpart, task_subtype_bh_density, task_subtype_bh_feedback, diff --git a/tools/plot_task_dependencies.py b/tools/plot_task_dependencies.py index 9a8b63ab315215c2973187a026fc1a5e182cd47b..b835b04261cf54b361f347f88bbb27f230a6be16 100644 --- a/tools/plot_task_dependencies.py +++ b/tools/plot_task_dependencies.py @@ -162,6 +162,9 @@ def taskIsStars(name): """ if "stars" in name or "spart" in name: return True + if "sf_count" in name: + return True + return False def taskIsHydro(name): diff --git a/tools/task_plots/analyse_tasks.py b/tools/task_plots/analyse_tasks.py index 463f4f1e9d792ae2f4103d80b5dc45761e3755e4..fd07340940b8903bf09fe807f2741d9e65261129 100755 --- a/tools/task_plots/analyse_tasks.py +++ b/tools/task_plots/analyse_tasks.py @@ -131,6 +131,7 @@ SUBTYPES = [ "spart", "stars_density", "stars_feedback", + "sf_counts" "bpart", "bh_density", "bh_feedback", diff --git a/tools/task_plots/plot_tasks.py b/tools/task_plots/plot_tasks.py index ff12940e1788099dbd67cc11196f7a3e1261ab3c..070ae2f3c509d6ae8fef8bad9ffec6c316060a7c 100755 --- a/tools/task_plots/plot_tasks.py +++ b/tools/task_plots/plot_tasks.py @@ -216,6 +216,7 @@ SUBTYPES = [ "spart", "stars_density", "stars_feedback", + "sf_counts", "bpart", "bh_density", "bh_feedback", @@ -258,6 +259,8 @@ FULLTYPES = [ "send/gpart", "recv/spart", "send/spart", + "send/sf_counts", + "recv/sf_counts", "recv/bpart", "send/bpart", "self/stars_density",