From a3386ca74814d1b066f1315d5220c4fd97da8b99 Mon Sep 17 00:00:00 2001 From: Loikki <loic_hausammann@hotmail.com> Date: Wed, 2 Aug 2017 11:32:53 +0200 Subject: [PATCH] Start working on logger --- examples/main.c | 3 + examples/parameter_example.yml | 1 + src/active.h | 40 ++++++++++ src/cell.c | 1 + src/cell.h | 6 ++ src/engine.c | 69 ++++++++++++++++-- src/engine.h | 13 +++- src/gravity/Default/gravity.h | 5 ++ src/gravity/Default/gravity_part.h | 8 ++ src/hydro/Gadget2/hydro.h | 2 + src/hydro/Gadget2/hydro_part.h | 6 ++ src/runner.c | 113 +++++++++++++++++++++++++++++ src/runner.h | 1 + src/scheduler.c | 1 + src/stars/Default/stars_part.h | 3 + src/task.c | 6 +- src/task.h | 1 + src/timers.c | 1 + src/timers.h | 1 + 19 files changed, 273 insertions(+), 8 deletions(-) diff --git a/examples/main.c b/examples/main.c index e5ab33b7e5..d885fd1944 100644 --- a/examples/main.c +++ b/examples/main.c @@ -85,6 +85,8 @@ void print_help_message(void) { printf(" %2s %14s %s\n", "-g", "", "Run with an external gravitational potential."); printf(" %2s %14s %s\n", "-G", "", "Run with self-gravity."); + printf(" %2s %14s %s\n", "-l", "", "Use logger for the output " + "(Optimized binary snapshot)."); printf(" %2s %14s %s\n", "-M", "", "Reconstruct the multipoles every time-step."); printf(" %2s %14s %s\n", "-n", "{int}", @@ -188,6 +190,7 @@ int main(int argc, char *argv[]) { int nsteps = -2; int restart = 0; int with_cosmology = 0; + int with_logger = 0; int with_external_gravity = 0; int with_sourceterms = 0; int with_cooling = 0; diff --git a/examples/parameter_example.yml b/examples/parameter_example.yml index 19579522ce..85661a9eda 100644 --- a/examples/parameter_example.yml +++ b/examples/parameter_example.yml @@ -90,6 +90,7 @@ Snapshots: UnitTemp_in_cgs: 1 # (Optional) Unit system for the outputs (Kelvin) output_list_on: 0 # (Optional) Enable the output list output_list: snaplist.txt # (Optional) File containing the output times (see documentation in "Parameter File" section) + logger_max_steps: 10 # (Optional) Number of particle steps between two chunk writing if using logger # Parameters governing the conserved quantities statistics Statistics: diff --git a/src/active.h b/src/active.h index 2ea8a6d9cc..08979f5052 100644 --- a/src/active.h +++ b/src/active.h @@ -443,4 +443,44 @@ __attribute__((always_inline)) INLINE static int spart_is_starting( return (spart_bin <= max_active_bin); } + +/** + * @brief Should this particle write its data now ? + * + * @param p The #part. + * @param e The #engine containing information about the current time. + * @return 1 if the #part should write, 0 otherwise. + */ +__attribute__((always_inline)) INLINE static int part_should_write( + const struct part *p, const struct engine *e) { + + return (p->last_output > e->logger_max_steps); +} + +/** + * @brief Should this particle write its data now ? + * + * @param p The #gpart. + * @param e The #engine containing information about the current time. + * @return 1 if the #gpart should write, 0 otherwise. + */ +__attribute__((always_inline)) INLINE static int gpart_should_write( + const struct gpart *p, const struct engine *e) { + + return (p->last_output > e->logger_max_steps); +} + +/** + * @brief Should this particle write its data now ? + * + * @param p The #spart. + * @param e The #engine containing information about the current time. + * @return 1 if the #spart should write, 0 otherwise. + */ +__attribute__((always_inline)) INLINE static int spart_should_write( + const struct spart *p, const struct engine *e) { + + return (p->last_output > e->logger_max_steps); +} + #endif /* SWIFT_ACTIVE_H */ diff --git a/src/cell.c b/src/cell.c index 60e2e9393f..3e70b7687f 100644 --- a/src/cell.c +++ b/src/cell.c @@ -2904,6 +2904,7 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) { if (c->grav.down_in != NULL) scheduler_activate(s, c->grav.down_in); if (c->grav.mesh != NULL) scheduler_activate(s, c->grav.mesh); if (c->grav.long_range != NULL) scheduler_activate(s, c->grav.long_range); + if (c->logger != NULL) scheduler_activate(s, c->logger); } return rebuild; diff --git a/src/cell.h b/src/cell.h index a01f2eaaaf..a95e0f2226 100644 --- a/src/cell.h +++ b/src/cell.h @@ -279,6 +279,12 @@ struct cell { /*! Values of h_max before the drifts, used for sub-cell tasks. */ float h_max_old; + /*! The logger task */ + struct task *logger; + + /*! The task to compute time-steps */ + struct task *timestep; + /*! Values of dx_max before the drifts, used for sub-cell tasks. */ float dx_max_part_old; diff --git a/src/engine.c b/src/engine.c index 6d32ce4362..ef477b2d48 100644 --- a/src/engine.c +++ b/src/engine.c @@ -112,7 +112,9 @@ const char *engine_policy_names[] = {"none", "stars", "structure finding", "star formation", - "feedback"}; + "feedback", + "logger" +}; /** The rank of the engine as a global variable (for messages). */ int engine_rank; @@ -217,6 +219,7 @@ void engine_make_hierarchical_tasks_common(struct engine *e, struct cell *c) { struct scheduler *s = &e->sched; const int is_with_cooling = (e->policy & engine_policy_cooling); const int is_with_star_formation = (e->policy & engine_policy_star_formation); + const int is_logger = (e->policy & engine_policy_logger); /* Are we in a super-cell ? */ if (c->super == c) { @@ -228,6 +231,11 @@ void engine_make_hierarchical_tasks_common(struct engine *e, struct cell *c) { c->kick1 = scheduler_addtask(s, task_type_kick1, task_subtype_none, 0, 0, c, NULL); + if (is_logger) + c->logger = scheduler_addtask(s, task_type_logger, task_subtype_none, 0, 0, + c, NULL); + + c->kick2 = scheduler_addtask(s, task_type_kick2, task_subtype_none, 0, 0, c, NULL); @@ -5589,7 +5597,10 @@ void engine_check_for_dumps(struct engine *e) { /* Dump everything */ engine_print_stats(e); - engine_dump_snapshot(e); + if (e->policy & engine_policy_logger) + engine_dump_index(e); + else + engine_dump_snapshot(e); } else if (e->ti_next_stats < e->ti_next_snapshot) { @@ -5619,7 +5630,10 @@ void engine_check_for_dumps(struct engine *e) { engine_drift_all(e); /* Dump snapshot */ - engine_dump_snapshot(e); + if (e->policy & engine_policy_logger) + engine_dump_index(e); + else + engine_dump_snapshot(e); } else if (e->ti_next_stats > e->ti_next_snapshot) { @@ -5637,7 +5651,10 @@ void engine_check_for_dumps(struct engine *e) { engine_drift_all(e); /* Dump snapshot */ - engine_dump_snapshot(e); + if (e->policy & engine_policy_logger) + engine_dump_index(e); + else + engine_dump_snapshot(e); /* Let's fake that we are at the stats dump time */ e->ti_current = e->ti_next_stats; @@ -5672,7 +5689,10 @@ void engine_check_for_dumps(struct engine *e) { engine_drift_all(e); /* Dump... */ - engine_dump_snapshot(e); + if (e->policy & engine_policy_logger) + engine_dump_index(e); + else + engine_dump_snapshot(e); /* ... and find the next output time */ engine_compute_next_snapshot_time(e); @@ -6447,6 +6467,30 @@ void engine_dump_snapshot(struct engine *e) { (float)clocks_diff(&time1, &time2), clocks_getunit()); } +/** + * @brief Writes an index file with the current state of the engine + * + * @param e The #engine. + */ +void engine_dump_index(struct engine *e) { + + struct clocks_time time1, time2; + clocks_gettime(&time1); + + if (e->verbose) message("writing index at t=%e.", e->time); + + /* Dump... */ + /* Should use snapshotBaseName for the index name */ + message("I am dumping an index file..."); + + e->dump_snapshot = 0; + + clocks_gettime(&time2); + if (e->verbose) + message("writing particle properties took %.3f %s.", + (float)clocks_diff(&time1, &time2), clocks_getunit()); +} + #ifdef HAVE_SETAFFINITY /** * @brief Returns the initial affinity the main thread is using. @@ -6517,6 +6561,7 @@ void engine_unpin(void) { * @param Nstars total number of star particles in the simulation. * @param policy The queuing policy to use. * @param verbose Is this #engine talkative ? + * @param logger_max_steps Max number of particle steps before writing with logger * @param reparttype What type of repartition algorithm are we using ? * @param internal_units The system of units used internally. * @param physical_constants The #phys_const used for this run. @@ -6612,6 +6657,14 @@ void engine_init(struct engine *e, struct space *s, struct swift_params *params, e->last_repartition = 0; #endif + + /* Logger params */ + char logger_name_file[PARSER_MAX_LINE_SIZE]; + e->logger_max_steps = parser_get_opt_param_int(params, "Snapshots:logger_max_steps", 10); + parser_get_opt_param_string(params, "Snapshots:dump_file", logger_name_file, "dump.smew"); + e->logger_dump = malloc(sizeof(struct dump)); + dump_init(e->logger_dump, logger_name_file, 1024 * 1024 * 10); + /* Make the space link back to the engine. */ s->e = e; @@ -7069,6 +7122,11 @@ void engine_config(int restart, struct engine *e, struct swift_params *params, #endif /* Find the time of the first snapshot output */ + if (e->policy & engine_policy_logger) + if (e->nodeID == 0) + message("Expected output of over 9000\n Should write a real message..."); + + /* Find the time of the first output */ engine_compute_next_snapshot_time(e); /* Find the time of the first statistics output */ @@ -7631,6 +7689,7 @@ void engine_clean(struct engine *e) { free(e->links); free(e->cell_loc); + free(e->logger_dump); scheduler_clean(&e->sched); space_clean(e->s); threadpool_clean(&e->threadpool); diff --git a/src/engine.h b/src/engine.h index d81346d323..5037cdc60a 100644 --- a/src/engine.h +++ b/src/engine.h @@ -38,6 +38,7 @@ #include "clocks.h" #include "collectgroup.h" #include "cooling_struct.h" +#include "dump.h" #include "gravity_properties.h" #include "mesh_gravity.h" #include "parser.h" @@ -74,9 +75,10 @@ enum engine_policy { engine_policy_stars = (1 << 15), engine_policy_structure_finding = (1 << 16), engine_policy_star_formation = (1 << 17), - engine_policy_feedback = (1 << 18) + engine_policy_feedback = (1 << 18), + engine_policy_logger = (1 << 19) }; -#define engine_maxpolicy 18 +#define engine_maxpolicy 19 extern const char *engine_policy_names[]; /** @@ -312,6 +314,12 @@ struct engine { int forcerepart; struct repartition *reparttype; + /* Number of particle steps between dumping a chunk of data */ + int logger_max_steps; + + /* File name of the dump file */ + struct dump *logger_dump; + /* How many steps have we done with the same set of tasks? */ int tasks_age; @@ -415,6 +423,7 @@ void engine_init(struct engine *e, struct space *s, struct swift_params *params, void engine_config(int restart, struct engine *e, struct swift_params *params, int nr_nodes, int nodeID, int nr_threads, int with_aff, int verbose, const char *restart_file); +void engine_dump_index(struct engine *e); void engine_launch(struct engine *e); void engine_prepare(struct engine *e); void engine_init_particles(struct engine *e, int flag_entropy_ICs, diff --git a/src/gravity/Default/gravity.h b/src/gravity/Default/gravity.h index 83decb0cfb..c99c7ac8c8 100644 --- a/src/gravity/Default/gravity.h +++ b/src/gravity/Default/gravity.h @@ -227,6 +227,11 @@ __attribute__((always_inline)) INLINE static void gravity_first_init_gpart( gp->time_bin = 0; gravity_init_gpart(gp); + +#ifdef WITH_LOGGER + gp->last_output = 0; + gp->last_offset = 0; +#endif } #endif /* SWIFT_DEFAULT_GRAVITY_H */ diff --git a/src/gravity/Default/gravity_part.h b/src/gravity/Default/gravity_part.h index f065e6d3a2..4e357f8e86 100644 --- a/src/gravity/Default/gravity_part.h +++ b/src/gravity/Default/gravity_part.h @@ -75,6 +75,14 @@ struct gpart { double potential_exact; #endif +#ifdef WITH_LOGGER + /* Number of time step since last output */ + short int last_output; + + /* offset at last writing */ + size_t last_offset; +#endif + } SWIFT_STRUCT_ALIGN; #endif /* SWIFT_DEFAULT_GRAVITY_PART_H */ diff --git a/src/hydro/Gadget2/hydro.h b/src/hydro/Gadget2/hydro.h index 9765ced22b..84742a0e38 100644 --- a/src/hydro/Gadget2/hydro.h +++ b/src/hydro/Gadget2/hydro.h @@ -743,6 +743,8 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part( struct part *restrict p, struct xpart *restrict xp) { p->time_bin = 0; + p->last_output = 0; + p->last_offset = 0; xp->v_full[0] = p->v[0]; xp->v_full[1] = p->v[1]; xp->v_full[2] = p->v[2]; diff --git a/src/hydro/Gadget2/hydro_part.h b/src/hydro/Gadget2/hydro_part.h index 90f7357170..c6f1046105 100644 --- a/src/hydro/Gadget2/hydro_part.h +++ b/src/hydro/Gadget2/hydro_part.h @@ -90,6 +90,12 @@ struct part { /* Entropy time derivative */ float entropy_dt; + /* Number of time step since last output */ + short int last_output; + + /* offset at last writing */ + size_t last_offset; + union { struct { diff --git a/src/runner.c b/src/runner.c index 7659867f31..444a4b6312 100644 --- a/src/runner.c +++ b/src/runner.c @@ -53,6 +53,7 @@ #include "hydro.h" #include "hydro_properties.h" #include "kick.h" +#include "logger.h" #include "minmax.h" #include "runner_doiact_vec.h" #include "scheduler.h" @@ -2610,6 +2611,9 @@ void *runner_main(void *data) { case task_type_end_force: runner_do_end_force(r, ci, 1); break; + case task_type_logger: + runner_do_logger(r, ci, 1); + break; case task_type_timestep: runner_do_timestep(r, ci, 1); break; @@ -2688,3 +2692,112 @@ void *runner_main(void *data) { /* Be kind, rewind. */ return NULL; } + + +/** + * @brief Write the required particles through the logger. + * + * @param r The runner thread. + * @param c The cell. + * @param timer Are we timing this ? + */ +void runner_do_logger(struct runner *r, struct cell *c, int timer) { + + const struct engine *e = r->e; + struct part *restrict parts = c->parts; + //struct xpart *restrict xparts = c->xparts; + struct gpart *restrict gparts = c->gparts; + struct spart *restrict sparts = c->sparts; + const int count = c->count; + const int gcount = c->gcount; + const int scount = c->scount; + //const integertime_t ti_current = e->ti_current; + //const double timeBase = e->timeBase; + + TIMER_TIC; + + /* Anything to do here? */ + if (!cell_is_starting(c, e)) return; + + /* Recurse? */ + if (c->split) { + for (int k = 0; k < 8; k++) + if (c->progeny[k] != NULL) runner_do_logger(r, c->progeny[k], 0); + } else { + + /* Loop over the parts 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 to be kicked */ + if (part_is_starting(p, e)) { + + if (part_should_write(p, e)) + { + /* Write particle */ + logger_log_part(p, logger_mask_x | logger_mask_v | logger_mask_a | + logger_mask_u | logger_mask_h | logger_mask_rho | + logger_mask_consts, + &p->last_offset, e->logger_dump); + message("Offset: %lu", p->last_offset); + /* Set counter back to zero */ + p->last_output = 0; + } + else + /* Update counter */ + p->last_output += 1; + } + } + + /* Loop over the gparts in this cell. */ + for (int k = 0; k < gcount; k++) { + + /* Get a handle on the part. */ + struct gpart *restrict gp = &gparts[k]; + + /* If particle needs to be kicked */ + if (gpart_is_starting(gp, e)) { + + if (gpart_should_write(gp, e)) + { + /* Write particle */ + logger_log_gpart(gp, logger_mask_x | logger_mask_v | logger_mask_a | + logger_mask_h | logger_mask_consts, + &gp->last_offset, e->logger_dump); + /* Set counter back to zero */ + gp->last_output = 0; + } + else + { + /* Update counter */ + gp->last_output += 1; + } + } + } + + /* Loop over the star particles in this cell. */ + for (int k = 0; k < scount; k++) { + + /* Get a handle on the s-part. */ + struct spart *restrict sp = &sparts[k]; + + /* If particle needs to be kicked */ + if (spart_is_starting(sp, e)) { + + if (spart_should_write(sp, e)) + { + message("I am writing sparticle %lli", sp->id); + error("Not implemented"); + sp->last_output = 0; + } + else + sp->last_output += 1; + } + } + } + + if (timer) TIMER_TOC(timer_logger); +} diff --git a/src/runner.h b/src/runner.h index e33a3e380e..29c42da405 100644 --- a/src/runner.h +++ b/src/runner.h @@ -80,6 +80,7 @@ void runner_do_init(struct runner *r, struct cell *c, int timer); void runner_do_cooling(struct runner *r, struct cell *c, int timer); void runner_do_grav_external(struct runner *r, struct cell *c, int timer); void runner_do_grav_fft(struct runner *r, int timer); +void runner_do_logger(struct runner *r, struct cell *c, int timer); void *runner_main(void *data); void runner_do_unskip_mapper(void *map_data, int num_elements, void *extra_data); diff --git a/src/scheduler.c b/src/scheduler.c index 4c1c46a2c8..28fb414698 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -2123,6 +2123,7 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) { case task_type_kick1: case task_type_kick2: case task_type_stars_ghost: + case task_type_logger: case task_type_timestep: qid = t->ci->super->owner; break; diff --git a/src/stars/Default/stars_part.h b/src/stars/Default/stars_part.h index 1922cc0e26..43161dd8ed 100644 --- a/src/stars/Default/stars_part.h +++ b/src/stars/Default/stars_part.h @@ -62,6 +62,9 @@ struct spart { } density; + /* Number of time step since last output */ + short int last_output; + #ifdef SWIFT_DEBUG_CHECKS /* Time of the last drift */ diff --git a/src/task.c b/src/task.c index bfd4de9347..9aeca8cd7e 100644 --- a/src/task.c +++ b/src/task.c @@ -58,7 +58,8 @@ const char *taskID_names[task_type_count] = { "grav_mm", "grav_down_in", "grav_down", "grav_mesh", "cooling", "star_formation", "sourceterms", "stars_ghost_in", "stars_ghost", - "stars_ghost_out"}; + "stars_ghost_out","logger" +}; /* Sub-task type names. */ const char *subtaskID_names[task_subtype_count] = { @@ -161,6 +162,7 @@ __attribute__((always_inline)) INLINE static enum task_actions task_acts_on( case task_type_end_force: case task_type_kick1: case task_type_kick2: + case task_type_logger: case task_type_timestep: case task_type_send: case task_type_recv: @@ -304,6 +306,7 @@ void task_unlock(struct task *t) { case task_type_end_force: case task_type_kick1: + case task_type_logger: case task_type_kick2: case task_type_timestep: cell_unlocktree(ci); @@ -400,6 +403,7 @@ int task_lock(struct task *t) { case task_type_end_force: case task_type_kick1: case task_type_kick2: + case task_type_logger: case task_type_timestep: if (ci->hydro.hold || ci->grav.phold) return 0; if (cell_locktree(ci) != 0) return 0; diff --git a/src/task.h b/src/task.h index e38cfe87ea..d2bcfa2d55 100644 --- a/src/task.h +++ b/src/task.h @@ -70,6 +70,7 @@ enum task_types { task_type_stars_ghost_in, task_type_stars_ghost, task_type_stars_ghost_out, + task_type_logger, task_type_count } __attribute__((packed)); diff --git a/src/timers.c b/src/timers.c index 88496af8bc..dae35f3029 100644 --- a/src/timers.c +++ b/src/timers.c @@ -94,6 +94,7 @@ const char* timers_names[timer_count] = { "dopair_subset_stars_density", "dosubpair_stars_density", "dosub_self_stars_density", + "logger" }; /* File to store the timers */ diff --git a/src/timers.h b/src/timers.h index 4eb14242df..c43f0154d2 100644 --- a/src/timers.h +++ b/src/timers.h @@ -95,6 +95,7 @@ enum { timer_dopair_subset_stars_density, timer_dosubpair_stars_density, timer_dosub_self_stars_density, + timer_logger, timer_count, }; -- GitLab