diff --git a/src/cats/configuration/configuration.c b/src/cats/configuration/configuration.c index 00b2e74cdf9cd6b010c1cbba272639006d68560e..361d694d61bfab701de03cfa032302f2df07c8c7 100644 --- a/src/cats/configuration/configuration.c +++ b/src/cats/configuration/configuration.c @@ -60,7 +60,7 @@ void init_cats_configuration(struct cats_configuration *conf) log_message(LOG_ERROR, "conf is NULL in %s", __func__); exit(EXIT_FAILURE); } - + init_stats_registry(&conf->stats_registry); init_module_registry(&conf->modules); reset_overlay(&conf->overlays); zero_statistics_stats(&conf->global_stats); diff --git a/src/cats/configuration/configuration.h b/src/cats/configuration/configuration.h index 15542b32603c58d418b5d51d210939d9ec800738..1613e915be901baa179a281c2c8c9105a6dbcf7e 100644 --- a/src/cats/configuration/configuration.h +++ b/src/cats/configuration/configuration.h @@ -135,6 +135,8 @@ struct cats_configuration { bool debug_enabled; struct cats_ini *ini; + struct cats_stats_registry stats_registry; + // cats_stats cats_dt_population stats_populated_threshold; diff --git a/src/cats/grids/cats_grid.c b/src/cats/grids/cats_grid.c index e55be91ca49b16cd508e8835804d0ad288d5bfa5..912b4cf9bf19edae2bface737dde4c1c269fe2d7 100644 --- a/src/cats/grids/cats_grid.c +++ b/src/cats/grids/cats_grid.c @@ -187,7 +187,7 @@ void initialize_grid(struct cats_grid *grid, struct cats_configuration *conf, st // FIXME: SCALE FACTOR make this unnecessary and decouple scale factor calculations from **grids // Attention: we need to call finalize_grid() later if only partially initialised - init_statistics(&grid->stats); + init_statistics(&grid->stats, &conf->stats_registry); setup_grid_population_structures(grid); @@ -344,7 +344,7 @@ void do_all_grids(struct cats_grid **grids, struct cats_configuration *conf, gri void initialize_grid_stats(struct cats_grid *grid, struct cats_configuration *conf) { assert(grid != NULL); - init_statistics(&grid->stats); + init_statistics(&grid->stats, &conf->stats_registry); grid->stats.has_been_populated = (char **) new_raw_2d_array_from_dimension(grid->dimension, sizeof(char)); char *filename = get_grid_stat_filename(grid, conf); diff --git a/src/cats/stats/statistics.c b/src/cats/stats/statistics.c index e0c63deafe896b2fd7a5af4446a7629654b2e2dd..73e4c208f9c714d3a74a8c1c19b22a41849012b1 100644 --- a/src/cats/stats/statistics.c +++ b/src/cats/stats/statistics.c @@ -23,8 +23,11 @@ #include <assert.h> +#include <stdlib.h> #include "statistics.h" #include "cats_strings/cats_strings.h" +#include "memory/cats_memory.h" +#include "configuration/configuration.h" void zero_statistics_stats(struct statistics *stats) @@ -36,28 +39,71 @@ void zero_statistics_stats(struct statistics *stats) char **has_been_populated_ts = stats->has_been_populated_ts; int32_t *N = stats->populated_by_classes; struct string_array *header = stats->stats_header; - + int64_t *custom_stats = stats->custom_stats; + int64_t custom_stat_count = stats->custom_stat_count; // reset everything struct statistics empty = {0}; *stats = empty; + // restore some values stats->file = file; stats->has_been_populated = has_been_populated; stats->has_been_populated_ts = has_been_populated_ts; stats->populated_by_classes = N; stats->stats_header = header; + stats->custom_stats = custom_stats; + stats->custom_stat_count = custom_stat_count; + + for (int32_t i = 0; i < STAT_MAX; i++) { + stats->stats[i] = 0; + } + + for (int64_t i = 0; i < stats->custom_stat_count; i++) { + stats->custom_stats[i] = 0; + } + } -void init_statistics(struct statistics *stats) +void init_statistics(struct statistics *stats, struct cats_stats_registry *registry) { + if (stats->initialized) { + log_message(LOG_WARNING, "statistics are already initialised"); + } struct statistics empty = {0}; *stats = empty; + stats->custom_stat_count = registry->count; + stats->custom_stats = calloc_or_die(stats->custom_stat_count, sizeof(int64_t)); + stats->initialized = true; } void cleanup_statistics(struct statistics *stats) { if (stats->stats_header) free_string_array(&stats->stats_header); -} \ No newline at end of file + free(stats->custom_stats); +} + + +int64_t add_custom_stat(struct cats_stats_registry *registry, const char *name) +{ + int64_t count = registry->count; + string_array_add(registry->names, name); + registry->count += 1; + return count; +} + + +void init_stats_registry(struct cats_stats_registry *registry) +{ + registry->count = 0; + registry->names = new_string_array(); +} + +void cleanup_stats_registry(struct cats_stats_registry *registry) +{ + registry->count = 0; + free_string_array(®istry->names); + registry->names = NULL; +} diff --git a/src/cats/stats/statistics.h b/src/cats/stats/statistics.h index df0208d8300382553d6de9d67a803014e917963c..f5f9f5b3b08f6078ff1830487c01ad45e20021f9 100644 --- a/src/cats/stats/statistics.h +++ b/src/cats/stats/statistics.h @@ -23,10 +23,16 @@ #ifndef CATS_STATISTICS_H #define CATS_STATISTICS_H - +#include <stdbool.h> #include <stdio.h> #include <stdint.h> +struct cats_stats_registry { + int64_t count; + struct string_array *names; +}; + + // STAT_MIN and STAT_MAX are used for enumeration purposes // CS (CELL STATS) count the number of cells where the value of the specified stat is larger than zero // GS (GRID SUM) is the sum of the specified stat over the whole simulation area @@ -69,8 +75,10 @@ enum cats_stats { /// @brief data structure for collected statistics, both on a per-grid and global basis struct statistics { - + bool initialized; int64_t stats[STAT_MAX]; ///< individual cell stats, on for each \sa enum cats_stats + int64_t *custom_stats; + int64_t custom_stat_count; FILE *file; ///< file handle for output file int32_t *populated_by_classes; ///< only used for global stats: how many cells are populated by 1, 2, 3, ... N classes char **has_been_populated; ///< which cells have already been populated at least once? @@ -80,8 +88,9 @@ struct statistics { void zero_statistics_stats(struct statistics *stats); -void init_statistics(struct statistics *stats); +void init_statistics(struct statistics *stats, struct cats_stats_registry *registry); void cleanup_statistics(struct statistics *stats); - +void init_stats_registry(struct cats_stats_registry *registry); +int64_t add_custom_stat(struct cats_stats_registry *registry, const char *name); #endif //CATS_STATISTICS_H diff --git a/src/cats/stats/write_stats.c b/src/cats/stats/write_stats.c index b4e440dad9041af9531419b56420ff0d82a75fd9..b567bec652a7b6b3c399f26f1bffc026e11f7fa3 100644 --- a/src/cats/stats/write_stats.c +++ b/src/cats/stats/write_stats.c @@ -35,6 +35,8 @@ const char *get_stat_name(enum cats_stats which) { + + switch (which) { case CS_POPULATED: return "populated"; diff --git a/src/cats/threading/threading-helpers.c b/src/cats/threading/threading-helpers.c index 653006e2696072790bbde6ff99c920023d8ca0ae..1a8ff5d82ed210f7203b70324d1d29cca067b946 100644 --- a/src/cats/threading/threading-helpers.c +++ b/src/cats/threading/threading-helpers.c @@ -30,6 +30,13 @@ #include "misc/cats_random.h" #include "stats/grid_stats.h" #include "data/error.h" +#include "memory/cats_memory.h" + +void create_custom_stats_for_thread(struct statistics *thread_stats, struct statistics *grid_stats) +{ + thread_stats->custom_stat_count = grid_stats->custom_stat_count; + thread_stats->custom_stats = calloc_or_die(grid_stats->custom_stat_count, sizeof(int64_t)); +} void initialize_thread(struct cats_thread_info *thread, struct cats_grid *grid, struct cats_configuration *conf, int32_t id) @@ -37,7 +44,9 @@ initialize_thread(struct cats_thread_info *thread, struct cats_grid *grid, struc thread->rng = allocate_rng(); thread->rng_seed = conf->rng_seed; - for (int32_t i = 0; i < MAX_CLASSES; i++) { + for (int32_t i = 0; i < conf->grid_count; i++) { + + create_custom_stats_for_thread(&thread->stats[i], &grid->stats); zero_statistics_stats(&thread->stats[i]); } @@ -60,7 +69,11 @@ void cleanup_threads(struct cats_thread_info *threads, int32_t num_threads) gsl_rng_free(threads[i].rng); } - + for (int32_t i = 0; i < num_threads; i++) { + for (int32_t j = 0; j < threads[i].conf->grid_count; j++) { + free(threads[i].stats->custom_stats); + } + } free(threads); }