From 0569cb3b746708a9cd8e635b3bc41cb1f623b51a Mon Sep 17 00:00:00 2001 From: loikki <loic_hausammann@hotmail.com> Date: Wed, 23 Jan 2019 12:24:46 +0100 Subject: [PATCH] Implement time step critierion for stars h --- src/drift.h | 4 ++++ src/engine_maketasks.c | 22 ++++++++++++++++++++++ src/runner.c | 2 +- src/scheduler.c | 2 -- src/stars/Default/stars.h | 30 ++++++++++++++++++++++++++++-- src/stars/Default/stars_iact.h | 21 +++++++++++++++++++++ src/stars/Default/stars_part.h | 6 ++++++ src/timestep.h | 10 +++++++++- 8 files changed, 91 insertions(+), 6 deletions(-) diff --git a/src/drift.h b/src/drift.h index a4bdf9be74..7e874fe0ce 100644 --- a/src/drift.h +++ b/src/drift.h @@ -28,6 +28,7 @@ #include "dimension.h" #include "hydro.h" #include "part.h" +#include "stars.h" /** * @brief Perform the 'drift' operation on a #gpart. @@ -138,6 +139,9 @@ __attribute__((always_inline)) INLINE static void drift_spart( sp->x[1] += sp->v[1] * dt_drift; sp->x[2] += sp->v[2] * dt_drift; + /* Predict the values of the extra fields */ + stars_predict_extra(sp, dt_drift); + /* Compute offsets since last cell construction */ for (int k = 0; k < 3; k++) { const float dx = sp->v[k] * dt_drift; diff --git a/src/engine_maketasks.c b/src/engine_maketasks.c index cff4ba42f8..ff0baeff69 100644 --- a/src/engine_maketasks.c +++ b/src/engine_maketasks.c @@ -269,6 +269,9 @@ void engine_addtasks_send_stars(struct engine *e, struct cell *ci, t_feed = scheduler_addtask(s, task_type_send, task_subtype_spart, ci->mpi.tag, 0, ci, cj); + /* The send_stars task should unlock the super_cell's kick task. */ + scheduler_addunlock(s, t_feed, ci->super->end_force); + /* Ghost before you send */ scheduler_addunlock(s, ci->super->stars.ghost_out, t_feed); } @@ -492,10 +495,19 @@ void engine_addtasks_recv_stars(struct engine *e, struct cell *c, scheduler_addunlock(s, l->t, t_feed); } + struct task *recv_rho = NULL; + if (c->mpi.hydro.recv_rho != NULL) + recv_rho = c->mpi.hydro.recv_rho; + for (struct link *l = c->stars.feedback; l != NULL; l = l->next) { scheduler_addunlock(s, t_feed, l->t); + + /* Need gas density before feedback */ + if (recv_rho != NULL) + scheduler_addunlock(s, c->mpi.hydro.recv_rho, l->t); } + /* Recurse? */ if (c->split) for (int k = 0; k < 8; k++) @@ -964,6 +976,16 @@ void engine_make_hierarchical_tasks_stars(struct engine *e, struct cell *c) { scheduler_addtask(s, task_type_stars_ghost_out, task_subtype_none, 0, /* implicit = */ 1, c, NULL); engine_add_stars_ghosts(e, c, c->stars.ghost_in, c->stars.ghost_out); + + /* Need to compute the gas density before moving to the feedback */ + struct task *hydro_ghost = NULL; + if (c->hydro.super) + hydro_ghost = c->hydro.super->hydro.ghost_out; + + if (hydro_ghost) { + scheduler_addunlock(s, hydro_ghost, + c->super->stars.ghost_out); + } } } else { /* We are above the super-cell so need to go deeper */ diff --git a/src/runner.c b/src/runner.c index bf3c457fff..a7cdd14292 100644 --- a/src/runner.c +++ b/src/runner.c @@ -2664,7 +2664,7 @@ void runner_do_end_force(struct runner *r, struct cell *c, int timer) { if (spart_is_active(sp, e)) { /* Finish the force loop */ - stars_end_force(sp); + stars_end_feedback(sp); } } } diff --git a/src/scheduler.c b/src/scheduler.c index 9763d6f9a2..f443ec8724 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -1147,7 +1147,6 @@ static void scheduler_splittask_stars(struct task *t, struct scheduler *s) { /* Otherwise, split it. */ } else { - /* Take a step back (we're going to recycle the current task)... */ redo = 1; @@ -1710,7 +1709,6 @@ void scheduler_splittasks_mapper(void *map_data, int num_elements, * @param s The #scheduler. */ void scheduler_splittasks(struct scheduler *s) { - /* Call the mapper on each current task. */ threadpool_map(s->threadpool, scheduler_splittasks_mapper, s->tasks, s->nr_tasks, sizeof(struct task), 0, s); diff --git a/src/stars/Default/stars.h b/src/stars/Default/stars.h index 7a60ed6339..deb0f67149 100644 --- a/src/stars/Default/stars.h +++ b/src/stars/Default/stars.h @@ -65,6 +65,26 @@ __attribute__((always_inline)) INLINE static void stars_init_spart( sp->density.wcount_dh = 0.f; } +/** + * @brief Predict additional particle fields forward in time when drifting + * + * @param p The particle + * @param dt_drift The drift time-step for positions. + */ +__attribute__((always_inline)) INLINE static void stars_predict_extra( + struct spart *restrict sp, float dt_drift) { + + const float h_inv = 1.f / sp->h; + + /* Predict smoothing length */ + const float w1 = sp->feedback.h_dt * h_inv * dt_drift; + if (fabsf(w1) < 0.2f) + sp->h *= approx_expf(w1); /* 4th order expansion of exp(w) */ + else + sp->h *= expf(w1); + +} + /** * @brief Sets the values to be predicted in the drifts to their values at a * kick time @@ -75,12 +95,14 @@ __attribute__((always_inline)) INLINE static void stars_reset_predicted_values( struct spart* restrict sp) {} /** - * @brief Finishes the calculation of the feedback + * @brief Finishes the calculation of (non-gravity) forces acting on stars * * @param sp The particle to act upon */ __attribute__((always_inline)) INLINE static void stars_end_feedback( - struct spart* sp) {} + struct spart* sp) { + sp->feedback.h_dt *= sp->h * hydro_dimension_inv; +} /** * @brief Kick the additional variables @@ -155,6 +177,10 @@ __attribute__((always_inline)) INLINE static void stars_evolve_spart( */ __attribute__((always_inline)) INLINE static void stars_reset_acceleration( struct spart* restrict p) { + + /* Reset time derivative */ + p->feedback.h_dt = 0.f; + #ifdef DEBUG_INTERACTIONS_STARS for (int i = 0; i < MAX_NUM_OF_NEIGHBOURS_STARS; ++i) p->ids_ngbs_force[i] = -1; diff --git a/src/stars/Default/stars_iact.h b/src/stars/Default/stars_iact.h index 09c6f16c79..a99b4ade72 100644 --- a/src/stars/Default/stars_iact.h +++ b/src/stars/Default/stars_iact.h @@ -58,6 +58,27 @@ runner_iact_nonsym_stars_feedback(float r2, const float *dx, float hi, float hj, struct spart *restrict si, struct part *restrict pj, float a, float H) { + const float mj = pj->mass; + const float rhoj = pj->rho; + const float r = sqrtf(r2); + const float ri = 1.f / r; + + /* Get the kernel for hi. */ + float hi_inv = 1.0f / hi; + float hid_inv = pow_dimension_plus_one(hi_inv); /* 1/h^(d+1) */ + float xi = r * hi_inv; + float wi, wi_dx; + kernel_deval(xi, &wi, &wi_dx); + float wi_dr = hid_inv * wi_dx; + + /* Compute dv dot r */ + float dvdr = (si->v[0] - pj->v[0]) * dx[0] + + (si->v[1] - pj->v[1]) * dx[1] + + (si->v[2] - pj->v[2]) * dx[2]; + + /* Get the time derivative for h. */ + si->feedback.h_dt -= mj * dvdr * ri / rhoj * wi_dr; + #ifdef DEBUG_INTERACTIONS_STARS /* Update ngb counters */ if (si->num_ngb_force < MAX_NUM_OF_NEIGHBOURS_STARS) diff --git a/src/stars/Default/stars_part.h b/src/stars/Default/stars_part.h index 25342ae9a9..49a95a2d40 100644 --- a/src/stars/Default/stars_part.h +++ b/src/stars/Default/stars_part.h @@ -65,6 +65,12 @@ struct spart { } density; + struct { + /* Change in smoothing length over time. */ + float h_dt; + + } feedback; + #ifdef SWIFT_DEBUG_CHECKS /* Time of the last drift */ diff --git a/src/timestep.h b/src/timestep.h index e9943a41a0..9430104668 100644 --- a/src/timestep.h +++ b/src/timestep.h @@ -201,8 +201,15 @@ __attribute__((always_inline)) INLINE static integertime_t get_spart_timestep( new_dt_self = gravity_compute_timestep_self( sp->gpart, a_hydro, e->gravity_properties, e->cosmology); + /* Limit change in smoothing length */ + const float dt_h_change = + (sp->feedback.h_dt != 0.0f) + ? fabsf(e->stars_properties->log_max_h_change * sp->h / sp->feedback.h_dt) + : FLT_MAX; + /* Take the minimum of all */ float new_dt = min3(new_dt_stars, new_dt_self, new_dt_ext); + new_dt = min(new_dt, dt_h_change); /* Apply the maximal displacement constraint (FLT_MAX if non-cosmological)*/ new_dt = min(new_dt, e->dt_max_RMS_displacement); @@ -212,9 +219,10 @@ __attribute__((always_inline)) INLINE static integertime_t get_spart_timestep( /* Limit timestep within the allowed range */ new_dt = min(new_dt, e->dt_max); - if (new_dt < e->dt_min) + if (new_dt < e->dt_min) { error("spart (id=%lld) wants a time-step (%e) below dt_min (%e)", sp->id, new_dt, e->dt_min); + } /* Convert to integer time */ const integertime_t new_dti = make_integer_timestep( -- GitLab