diff --git a/src/cell.c b/src/cell.c index 50d3a441568acf8f20da905c0734965ed0a38993..509c822191b39637745e59704c140295b113a17c 100644 --- a/src/cell.c +++ b/src/cell.c @@ -974,6 +974,7 @@ int cell_unskip_tasks(struct cell *c, struct scheduler *s) { if (c->drift != NULL) scheduler_activate(s, c->drift); 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->cooling != NULL) scheduler_activate(s, c->cooling); if (c->sourceterms != NULL) scheduler_activate(s, c->sourceterms); diff --git a/src/cell.h b/src/cell.h index 783a1fa772b0c478c3565bdc07602ddaa1b373f2..c01594d4885067e63cab363718cc1559c3ff1034 100644 --- a/src/cell.h +++ b/src/cell.h @@ -156,6 +156,9 @@ struct cell { /*! The second kick task */ struct task *kick2; + /*! The task to compute time-steps */ + struct task *timestep; + /*! Task constructing the multipole from the particles */ struct task *grav_up; diff --git a/src/engine.c b/src/engine.c index baf4c52b6f7248ce0072ecf13a288367c5301383..10289cc73458c6b44fd4c33dba89af0778797f2e 100644 --- a/src/engine.c +++ b/src/engine.c @@ -147,6 +147,12 @@ void engine_make_hierarchical_tasks(struct engine *e, struct cell *c) { c->kick2 = scheduler_addtask(s, task_type_kick2, task_subtype_none, 0, 0, c, NULL, 0); + /* Add the time-step calculation task and its dependency */ + c->timestep = scheduler_addtask(s, task_type_timestep, task_subtype_none, + 0, 0, c, NULL, 0); + + scheduler_addunlock(s, c->kick2, c->timestep); + /* Add the drift task and its dependencies. */ c->drift = scheduler_addtask(s, task_type_drift, task_subtype_none, 0, 0, c, NULL, 0); @@ -2131,9 +2137,12 @@ void engine_marktasks_mapper(void *map_data, int num_elements, /* Kick? */ else if (t->type == task_type_kick1) { if (t->ci->ti_end_min <= ti_end) scheduler_activate(s, t); + } else if (t->type == task_type_kick2) { + if (t->ci->ti_end_min <= ti_end) scheduler_activate(s, t); } - else if (t->type == task_type_kick2) { + /* Time-step? */ + else if (t->type == task_type_timestep) { t->ci->updated = 0; t->ci->g_updated = 0; if (t->ci->ti_end_min <= ti_end) scheduler_activate(s, t); @@ -2365,7 +2374,7 @@ void engine_barrier(struct engine *e, int tid) { void engine_collect_kick(struct cell *c) { /* Skip super-cells (Their values are already set) */ - if (c->kick2 != NULL) return; + if (c->timestep != NULL) return; /* Counters for the different quantities. */ int updated = 0, g_updated = 0; diff --git a/src/runner.c b/src/runner.c index 94410adcb88c02a39e5e2fbf0f1e344004c2c8fe..50e72606b4c52a4146f849981d17d7fe47072398 100644 --- a/src/runner.c +++ b/src/runner.c @@ -896,8 +896,7 @@ void runner_do_kick1(struct runner *r, struct cell *c, int timer) { /** * @brief Perform the second half-kick on all the active particles in a cell. * - * Also computes the next time-step of all active particles, prepare them to be - * drifted and update the cell's statistics. + * Also prepares particles to be drifted. * * @param r The runner thread. * @param c The cell. @@ -918,17 +917,13 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { TIMER_TIC; /* Anything to do here? */ - if (!cell_is_active(c, e)) { - c->updated = 0; - c->g_updated = 0; - return; - } - - int updated = 0, g_updated = 0; - integertime_t ti_end_min = max_nr_timesteps, ti_end_max = 0; + if (!cell_is_active(c, e)) return; - /* No children? */ - if (!c->split) { + /* Recurse? */ + if (c->split) { + for (int k = 0; k < 8; k++) + if (c->progeny[k] != NULL) runner_do_kick2(r, c->progeny[k], 0); + } else { /* Loop over the particles in this cell. */ for (int k = 0; k < count; k++) { @@ -947,8 +942,6 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { const integertime_t ti_step = get_integer_timestep(p->time_bin); const integertime_t ti_begin = get_integer_time_begin(ti_current, p->time_bin); - const integertime_t ti_end = - get_integer_time_end(ti_current, p->time_bin); /* Finish the time-step with a second half-kick */ kick_part(p, xp, ti_begin + ti_step / 2, ti_begin + ti_step, ti_current, @@ -956,6 +949,82 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { /* Prepare the values to be drifted */ hydro_reset_predicted_values(p, xp); + } + } + + /* Loop over the g-particles in this cell. */ + for (int k = 0; k < gcount; k++) { + + /* Get a handle on the part. */ + struct gpart *restrict gp = &gparts[k]; + + /* If the g-particle has no counterpart */ + if (gp->id_or_neg_offset > 0) { + + /* need to be kicked ? */ + if (gpart_is_active(gp, e)) { + + /* First, finish the force loop */ + gravity_end_force(gp, const_G); + + const integertime_t ti_step = get_integer_timestep(gp->time_bin); + const integertime_t ti_begin = + get_integer_time_begin(ti_current, gp->time_bin); + + /* Finish the time-step with a second half-kick */ + kick_gpart(gp, ti_begin + ti_step / 2, ti_begin + ti_step, ti_current, + timeBase); + } + } + } + } + if (timer) TIMER_TOC(timer_kick2); +} + +/** + * @brief Computes the next time-step of all active particles in this cell + * and update the cell's statistics. + * + * @param r The runner thread. + * @param c The cell. + * @param timer Are we timing this ? + */ +void runner_do_timestep(struct runner *r, struct cell *c, int timer) { + + const struct engine *e = r->e; + const integertime_t ti_current = e->ti_current; + const int count = c->count; + const int gcount = c->gcount; + struct part *restrict parts = c->parts; + struct xpart *restrict xparts = c->xparts; + struct gpart *restrict gparts = c->gparts; + + TIMER_TIC; + + int updated = 0, g_updated = 0; + integertime_t ti_end_min = max_nr_timesteps, ti_end_max = 0; + + /* No children? */ + if (!c->split) { + + /* Loop over the particles in this cell. */ + for (int k = 0; k < count; k++) { + + /* Get a handle on the part. */ + struct part *restrict p = &parts[k]; + struct xpart *restrict xp = &xparts[k]; + + /* If particle needs updating */ + if (part_is_active(p, e)) { + +#ifdef SWIFT_DEBUG_CHECKS + /* Current end of time-step */ + const integertime_t ti_end = + get_integer_time_end(ti_current, p->time_bin); + + if (ti_end != ti_current) + error("Computing time-step of rogue particle."); +#endif /* Get new time-step */ const integertime_t ti_new_step = get_part_timestep(p, xp, e); @@ -969,8 +1038,8 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { if (p->gpart != NULL) g_updated++; /* What is the next sync-point ? */ - ti_end_min = min(ti_end + ti_new_step, ti_end_min); - ti_end_max = max(ti_end + ti_new_step, ti_end_max); + ti_end_min = min(ti_current + ti_new_step, ti_end_min); + ti_end_max = max(ti_current + ti_new_step, ti_end_max); } else { /* part is inactive */ @@ -993,21 +1062,17 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { /* If the g-particle has no counterpart */ if (gp->id_or_neg_offset > 0) { - /* need to be kicked ? */ + /* need to be updated ? */ if (gpart_is_active(gp, e)) { - /* First, finish the force loop */ - gravity_end_force(gp, const_G); - - const integertime_t ti_step = get_integer_timestep(gp->time_bin); - const integertime_t ti_begin = - get_integer_time_begin(ti_current, gp->time_bin); +#ifdef SWIFT_DEBUG_CHECKS + /* Current end of time-step */ const integertime_t ti_end = get_integer_time_end(ti_current, gp->time_bin); - /* Finish the time-step with a second half-kick */ - kick_gpart(gp, ti_begin + ti_step / 2, ti_begin + ti_step, ti_current, - timeBase); + if (ti_end != ti_current) + error("Computing time-step of rogue particle."); +#endif /* Get new time-step */ const integertime_t ti_new_step = get_gpart_timestep(gp, e); @@ -1019,8 +1084,8 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { g_updated++; /* What is the next sync-point ? */ - ti_end_min = min(ti_end + ti_new_step, ti_end_min); - ti_end_max = max(ti_end + ti_new_step, ti_end_max); + ti_end_min = min(ti_current + ti_new_step, ti_end_min); + ti_end_max = max(ti_current + ti_new_step, ti_end_max); } else { /* gpart is inactive */ const integertime_t ti_end = @@ -1032,10 +1097,7 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { } } } - } - - /* Otherwise, aggregate data from children. */ - else { + } else { /* Loop over the progeny. */ for (int k = 0; k < 8; k++) @@ -1043,7 +1105,7 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { struct cell *restrict cp = c->progeny[k]; /* Recurse */ - runner_do_kick2(r, cp, 0); + runner_do_timestep(r, cp, 0); /* And aggregate */ updated += cp->updated; @@ -1059,7 +1121,7 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { c->ti_end_min = ti_end_min; c->ti_end_max = ti_end_max; - if (timer) TIMER_TOC(timer_kick2); + if (timer) TIMER_TOC(timer_timestep); } /** @@ -1297,6 +1359,9 @@ void *runner_main(void *data) { case task_type_kick2: runner_do_kick2(r, ci, 1); break; + case task_type_timestep: + runner_do_timestep(r, ci, 1); + break; #ifdef WITH_MPI case task_type_send: if (t->subtype == task_subtype_tend) { diff --git a/src/space.c b/src/space.c index 055d4b769232fd9f95baad9db450a4ec7f465c3a..a0a36da641cac511fe39b7a35af8eeb6b29fc4e7 100644 --- a/src/space.c +++ b/src/space.c @@ -215,6 +215,7 @@ void space_rebuild_recycle_mapper(void *map_data, int num_elements, c->ghost = NULL; c->kick1 = NULL; c->kick2 = NULL; + c->timestep = NULL; c->drift = NULL; c->cooling = NULL; c->sourceterms = NULL; diff --git a/src/task.c b/src/task.c index a356299fa746587a2fd60318199c628a84c9e13c..ee4d92cf714aed2c23ae1795e053103aaf876e4e 100644 --- a/src/task.c +++ b/src/task.c @@ -48,10 +48,11 @@ /* Task type names. */ const char *taskID_names[task_type_count] = { - "none", "sort", "self", "pair", "sub_self", - "sub_pair", "init", "ghost", "extra_ghost", "drift", - "kick1", "kick2", "send", "recv", "grav_gather_m", - "grav_fft", "grav_mm", "grav_up", "cooling", "sourceterms"}; + "none", "sort", "self", "pair", "sub_self", + "sub_pair", "init", "ghost", "extra_ghost", "drift", + "kick1", "kick2", "timestep", "send", "recv", + "grav_gather_m", "grav_fft", "grav_mm", "grav_up", "cooling", + "sourceterms"}; const char *subtaskID_names[task_subtype_count] = { "none", "density", "gradient", "force", "grav", "external_grav", "tend"}; @@ -149,6 +150,7 @@ __attribute__((always_inline)) INLINE static enum task_actions task_acts_on( case task_type_init: case task_type_kick1: case task_type_kick2: + case task_type_timestep: case task_type_send: case task_type_recv: case task_type_drift: diff --git a/src/task.h b/src/task.h index 38b8e5c87fdfa4cb16f30980dafa13508d7d93cc..04aba60a1c631211e2191b0acc428f68c18568a7 100644 --- a/src/task.h +++ b/src/task.h @@ -48,6 +48,7 @@ enum task_types { task_type_drift, task_type_kick1, task_type_kick2, + task_type_timestep, task_type_send, task_type_recv, task_type_grav_gather_m, diff --git a/src/timers.h b/src/timers.h index 692bc0d5130e5fc712b32090d2f60595473d15e3..fa0d10d557b3155d3bb6444e489a6f08a964fb39 100644 --- a/src/timers.h +++ b/src/timers.h @@ -35,6 +35,7 @@ enum { timer_drift, timer_kick1, timer_kick2, + timer_timestep, timer_dosort, timer_doself_density, timer_doself_gradient,