diff --git a/src/cats/actions/action_population_grid_output.c b/src/cats/actions/action_population_grid_output.c index 97c931fef5beaca85745fae598e16b0138afaf11..de1be016e963b45c90687ff3910cb2f8360dccbf 100644 --- a/src/cats/actions/action_population_grid_output.c +++ b/src/cats/actions/action_population_grid_output.c @@ -52,7 +52,7 @@ enum action_status action_save_adults(struct cats_grid *grid, struct cats_config save_population_to_gdal(grid, conf); - if (conf->write_all) { + if (conf->output.write_all) { save_juveniles_to_gdal(grid, conf); save_seeds_to_gdal(grid, conf); } diff --git a/src/cats/actions/process_inter_period_survival.c b/src/cats/actions/process_inter_period_survival.c index cf10c16cc8c17c8c9f4e08ee3ac5949469121e54..479385a710b9537fb919d1156d0de5ce54e15fdb 100644 --- a/src/cats/actions/process_inter_period_survival.c +++ b/src/cats/actions/process_inter_period_survival.c @@ -88,14 +88,14 @@ enum action_status inter_period_survival_action(struct cats_grid *grid, struct c if (conf->command_line_options.lambda_test) { - write_stats(grid, conf, conf->lambda_stat_file, "pre-trans"); + write_stats(grid, conf, conf->output.lambda_stat_file, "pre-trans"); } threaded_action(&area_inter_period_survival, grid, conf, TS_DEFAULT); if (conf->command_line_options.lambda_test) { - write_stats(grid, conf, conf->lambda_stat_file, "post-trans"); + write_stats(grid, conf, conf->output.lambda_stat_file, "post-trans"); } diff --git a/src/cats/actions/process_seed_dispersal.c b/src/cats/actions/process_seed_dispersal.c index 3ccce3d455e11f5fd01c9924665d0f6045f6ef17..13c3c6eb74fa1ccf6a9c5cafa84d124aacf7994b 100644 --- a/src/cats/actions/process_seed_dispersal.c +++ b/src/cats/actions/process_seed_dispersal.c @@ -131,7 +131,7 @@ enum action_status process_disperse_seeds(struct cats_grid *grid, struct cats_co } #endif - if (conf->write_all && is_output_year(&conf->time)) { + if (conf->output.write_all && is_output_year(&conf->time)) { save_dispersed_seeds_to_gdal(grid, conf); } diff --git a/src/cats/actions/setup.c b/src/cats/actions/setup.c index 9b01c39d39bcf54f83d243c44c1ae89e5f8f6aff..d88079d3b9f4f5fe416fee6c3f9d6d6b7c425dc1 100644 --- a/src/cats/actions/setup.c +++ b/src/cats/actions/setup.c @@ -68,8 +68,8 @@ void setup_lambda_test_simulation(struct cats_configuration *conf, struct cats_g } conf->lambda_burn_in_time = conf->time.simulation_length / 5; - conf->lambda_stat_file = create_and_initialize_lambda_stat_file(conf, NULL, grid); - write_stats(grid, conf, conf->lambda_stat_file, "initial"); + conf->output.lambda_stat_file = create_and_initialize_lambda_stat_file(conf, NULL, grid); + write_stats(grid, conf, conf->output.lambda_stat_file, "initial"); } @@ -123,8 +123,8 @@ void setup_lambda_gradient_simulation(struct cats_configuration *conf, struct ca } conf->lambda_burn_in_time = conf->time.simulation_length / 5; - conf->lambda_stat_file = create_and_initialize_lambda_stat_file(conf, "gradient", grid); - write_stats(grid, conf, conf->lambda_stat_file, "initial"); + conf->output.lambda_stat_file = create_and_initialize_lambda_stat_file(conf, "gradient", grid); + write_stats(grid, conf, conf->output.lambda_stat_file, "initial"); } diff --git a/src/cats/cats.c b/src/cats/cats.c index c033e18140c789c88123c666957e81eec8981a55..c3950e5d22aad84f74bf4f19e89657df2d55e51d 100644 --- a/src/cats/cats.c +++ b/src/cats/cats.c @@ -187,6 +187,7 @@ struct cats_configuration *load_main_configuration(const struct program_options load_modules(conf); + setup_module_directories(conf); print_modules(conf); setup_simulation_actions(conf); diff --git a/src/cats/configuration/configuration.c b/src/cats/configuration/configuration.c index 361d694d61bfab701de03cfa032302f2df07c8c7..303469a03d7781b4f16a8779c6c4a351d5aac9be 100644 --- a/src/cats/configuration/configuration.c +++ b/src/cats/configuration/configuration.c @@ -72,17 +72,20 @@ void init_cats_configuration(struct cats_configuration *conf) conf->cycle.action_counter = 0; conf->environment.count = 0; - conf->output_directory = strdup(DEFAULT_OUTPUT_DIRECTORY); + conf->output.output_directory = strdup(DEFAULT_OUTPUT_DIRECTORY); conf->stats_populated_threshold = DEFAULT_POPULATED_THRESHOLD; conf->param_max_threads = 1; - conf->performance_file = NULL; + conf->output.performance_file = NULL; conf->grid_count = 1; conf->overlays.custom_overlay_count = 0; conf->overlays.custom_overlays = NULL; conf->overlays.registered_custom_overlay_names = new_string_array(); - + conf->output.needed_output_directories = new_string_array(); + conf->output.needed_module_output_directories = new_string_array(); + conf->output.have_glm = false; + conf->output.write_all = false; #ifdef USEMPI conf->mpi.world_size = 1; @@ -170,13 +173,13 @@ void post_process_configuration(struct cats_configuration *conf) char *filename = malloc_or_die(count); snprintf(filename, count, "performance/%s_%03d.csv", conf->run_name, conf->simulation.replicate); - conf->performance_file = fopen(filename, "w"); - if (!conf->performance_file) { + conf->output.performance_file = fopen(filename, "w"); + if (!conf->output.performance_file) { log_message(LOG_ERROR, "failed to open %s: %s", filename, strerror(errno)); exit_cats(EXIT_FAILURE); } - fprintf(conf->performance_file, "%s\n", "year,stat,cpu_time,wall_time"); + fprintf(conf->output.performance_file, "%s\n", "year,stat,cpu_time,wall_time"); } if (conf->param_max_threads <= 0) { @@ -221,13 +224,13 @@ void cleanup_configuration(struct cats_configuration **conf_orig) struct cats_configuration *conf = *conf_orig; // THIS HAS TO BE THE FIRST ENTRY cleanup_module_registry(&conf->modules); - if (conf->summary_file) { - fclose(conf->summary_file); - free(conf->summary_file_name); + if (conf->output.summary_file) { + fclose(conf->output.summary_file); + free(conf->output.summary_file_name); } - if (conf->statsfile_global) fclose(conf->statsfile_global); - free(conf->file_content); + if (conf->output.statsfile_global) fclose(conf->output.statsfile_global); + free(conf->output.file_content); /* keep sorted!*/ free(conf->cycle.actions); @@ -251,7 +254,7 @@ void cleanup_configuration(struct cats_configuration **conf_orig) free(conf->dispersal); - free(conf->output_directory); + free(conf->output.output_directory); for (int i = 0; i < conf->param_count; i++) { free(conf->param[i].preset_name); @@ -277,8 +280,8 @@ void cleanup_configuration(struct cats_configuration **conf_orig) //free(conf->predictors); cleanup_overlays(&conf->overlays); cleanup_environment_registry(&conf->environment_registry); - if (conf->performance_file) fclose(conf->performance_file); - conf->performance_file = NULL; + if (conf->output.performance_file) fclose(conf->output.performance_file); + conf->output.performance_file = NULL; free_ini(conf->ini); #ifdef USEMPI @@ -289,7 +292,8 @@ void cleanup_configuration(struct cats_configuration **conf_orig) free(conf->command_line_options.output_directory); free(conf->global_stats.populated_by_classes); - + free_string_array(&conf->output.needed_output_directories); + free_string_array(&conf->output.needed_module_output_directories); free(conf->param); conf->param = NULL; free(conf->run_name); diff --git a/src/cats/configuration/configuration.h b/src/cats/configuration/configuration.h index 1613e915be901baa179a281c2c8c9105a6dbcf7e..ca57b76b3f31e187ff92afa84b2f60f19713f332 100644 --- a/src/cats/configuration/configuration.h +++ b/src/cats/configuration/configuration.h @@ -122,13 +122,27 @@ struct cats_environment_collection { }; +struct cats_output { + struct string_array *needed_output_directories; + struct string_array *needed_module_output_directories; + bool have_glm; + bool write_all; + char *output_directory; + char *summary_file_name; + FILE *summary_file; + char *log_file_name; + FILE *lambda_stat_file; + bool param_compression; + FILE *statsfile_global; + FILE *performance_file; + char *file_content; + +}; + /// @brief Contains the configuration and state of the simulation struct cats_configuration { - char *output_directory; - char *summary_file_name; - FILE *summary_file; - char *log_file_name; + bool quiet; struct cats_global *global; struct program_options command_line_options; @@ -151,7 +165,6 @@ struct cats_configuration { int link_count; - bool write_all; bool all_species_same; @@ -179,7 +192,7 @@ struct cats_configuration { struct cats_overlays overlays; - bool param_compression; + int32_t grid_count; @@ -197,7 +210,6 @@ struct cats_configuration { char *run_name; // actions - FILE *lambda_stat_file; //enum simulation_mode mode; @@ -207,8 +219,7 @@ struct cats_configuration { int64_t rng_seed; - FILE *statsfile_global; - FILE *performance_file; + bool timing_info; struct cats_cycle cycle; @@ -218,8 +229,11 @@ struct cats_configuration { cats_dt_rates direct_scale_factor; cats_dt_rates lambda_at_OT; // FIXME, per parameter set - char *file_content; + enum cats_debug_flags debug; + + + struct cats_output output; }; void cleanup_configuration(struct cats_configuration **conf); diff --git a/src/cats/configuration/load_configuration.c b/src/cats/configuration/load_configuration.c index d7d98ec9e945e09f5d08fd1e5af495cb40cb6d55..fcbf15a4da1daa868f54baea71a479318d591e2a 100644 --- a/src/cats/configuration/load_configuration.c +++ b/src/cats/configuration/load_configuration.c @@ -67,14 +67,14 @@ load_configuration_from_file(const char *filename, const struct program_options // create empty configuration struct cats_configuration *conf = new_configuration(); conf->quiet = command_line_options->quiet; - conf->log_file_name = command_line_options->log_file; - conf->summary_file = NULL; - conf->summary_file_name = command_line_options->summary_file; - if (conf->summary_file_name) { - conf->summary_file = fopen(conf->summary_file_name, "w"); - ENSURE_FILE_OPENED(conf->summary_file, conf->summary_file_name) - fprintf(conf->summary_file, "type,path,year\n"); - if (conf->log_file_name) fprintf(conf->summary_file, "log,%s,\n",conf->log_file_name); + conf->output.log_file_name = command_line_options->log_file; + conf->output.summary_file = NULL; + conf->output.summary_file_name = command_line_options->summary_file; + if (conf->output.summary_file_name) { + conf->output.summary_file = fopen(conf->output.summary_file_name, "w"); + ENSURE_FILE_OPENED(conf->output.summary_file, conf->output.summary_file_name) + fprintf(conf->output.summary_file, "type,path,year\n"); + if (conf->output.log_file_name) fprintf(conf->output.summary_file, "log,%s,\n",conf->output.log_file_name); } #ifdef USEMPI mpi_setup(conf); @@ -120,7 +120,7 @@ load_configuration_from_file(const char *filename, const struct program_options conf->ini = ini; // we keep a copy of the configuration file contents in memory if (conf->command_line_options.need_conf) { - conf->file_content = slurp_file(filename); + conf->output.file_content = slurp_file(filename); } // load data from loaded ini file into the configuration diff --git a/src/cats/configuration/load_configuration_general.c b/src/cats/configuration/load_configuration_general.c index 2c83421d0bd167f779421fec9e5b815e56fcd147..5b044dc92bb1eed89b518427e11d08244f3d0360 100644 --- a/src/cats/configuration/load_configuration_general.c +++ b/src/cats/configuration/load_configuration_general.c @@ -63,14 +63,14 @@ void load_general_info(struct cats_configuration *conf, struct cats_ini *ini) char *od; bool have_od = load_conf_value(false, ini, "general", "output directory", &od); if (have_od) { - free(conf->output_directory); - conf->output_directory = od; + free(conf->output.output_directory); + conf->output.output_directory = od; } load_conf_value(false, ini, "general", "debug", &conf->debug_enabled); - load_conf_value(false, ini, "general", "compression", &conf->param_compression); + load_conf_value(false, ini, "general", "compression", &conf->output.param_compression); - load_conf_value(false, ini, "general", "write all", &conf->write_all); + load_conf_value(false, ini, "general", "write all", &conf->output.write_all); load_conf_value(false, ini, "general", "file format", &conf->geometry.file_format); load_conf_value(false, ini, "general", "ignore raster projection", &conf->geometry.ignore_raster_projection); load_conf_value(false, ini, "general", "threads", &conf->param_max_threads); diff --git a/src/cats/configuration/load_configuration_glm.c b/src/cats/configuration/load_configuration_glm.c index e3b80973512cb3f9d6a6f03c5fe493bca8b88442..366749270f35673dabefdf79b0faee9a217bf2ac 100644 --- a/src/cats/configuration/load_configuration_glm.c +++ b/src/cats/configuration/load_configuration_glm.c @@ -167,5 +167,7 @@ void add_glm_from_conf(struct cats_configuration *conf, struct cats_ini *ini, ch predictors->string[i]); add_to_environment(set, env); } + + conf->output.have_glm = true; } diff --git a/src/cats/grids/cats_grid.c b/src/cats/grids/cats_grid.c index 912b4cf9bf19edae2bface737dde4c1c269fe2d7..c99fcd3c066fcd609c96702f443c2ca93a5e4505 100644 --- a/src/cats/grids/cats_grid.c +++ b/src/cats/grids/cats_grid.c @@ -353,7 +353,7 @@ void initialize_grid_stats(struct cats_grid *grid, struct cats_configuration *co remove(filename); grid->stats.file = fopen(filename, "a+"); ENSURE_FILE_OPENED(grid->stats.file, filename) - if (conf->summary_file) fprintf(conf->summary_file, "grid-stats,%s,\n",filename); + if (conf->output.summary_file) fprintf(conf->output.summary_file, "grid-stats,%s,\n",filename); free(filename); write_grid_stats(conf, grid, true); fflush(grid->stats.file); diff --git a/src/cats/grids/gdal_helper.c b/src/cats/grids/gdal_helper.c index ab8ef1fe46d07abfcaef2904a5bc60c7b917ac50..619dbe1c704f5b6318e638a0e44893ca38a2a351 100644 --- a/src/cats/grids/gdal_helper.c +++ b/src/cats/grids/gdal_helper.c @@ -234,7 +234,7 @@ create_gdal_dataset(const struct simulation_geometry *geometry, const char *file } GDALSetMetadataItem(dataset, "TIFFTAG_SOFTWARE", cats_version(), NULL); - GDALSetMetadataItem(dataset, "TIFFTAG_IMAGEDESCRIPTION", conf->file_content, NULL); + GDALSetMetadataItem(dataset, "TIFFTAG_IMAGEDESCRIPTION", conf->output.file_content, NULL); CSLDestroy(options); return dataset; diff --git a/src/cats/grids/gdal_save.c b/src/cats/grids/gdal_save.c index e86cd34f99aa7503e129fd62da29ef80d5bfe657..739a13d937cbb146e73cc4b1d1b543e311400bab 100644 --- a/src/cats/grids/gdal_save.c +++ b/src/cats/grids/gdal_save.c @@ -70,7 +70,7 @@ void *save_population_to_gdal(struct cats_grid *grid, struct cats_configuration (cats_dt_population) get_vital_rate_maximum(&grid->param.carrying_capacity)); fflush(stderr); } - if (conf->summary_file) fprintf(conf->summary_file, "population,%s,%d\n",filename, conf->time.year_current); + if (conf->output.summary_file) fprintf(conf->output.summary_file, "population,%s,%d\n",filename, conf->time.year_current); free(filename); return 0; @@ -276,7 +276,7 @@ save_grid_to_gdal(struct grid_wrapper *gridwrapper, GDALDataType out_datatype, c set_gdal_dataset_geo_info(dataset, &conf->geometry, &gridwrapper->offset); set_gdal_band_nodata(band, nodata_value); set_gdal_band_metadata(band, GCI_GrayIndex, description); - set_gdal_dataset_metadata(dataset, "configuration", conf->file_content); + set_gdal_dataset_metadata(dataset, "configuration", conf->output.file_content); band = GDALGetRasterBand(dataset, 1); diff --git a/src/cats/modules/load_module.c b/src/cats/modules/load_module.c index 67c5862b3770d7ac7c04c6e6c63b2ec556fa547d..e7a245f9526c0d795dd5766cae7f053ecc88c881 100644 --- a/src/cats/modules/load_module.c +++ b/src/cats/modules/load_module.c @@ -107,7 +107,7 @@ int32_t register_module(struct cats_configuration *conf, const char *module_name int32_t module_id = conf->modules.count; CATS_MODULE_ID_INTERNAL = module_id; CATS_MODULE_DATA_INTERNAL = module_data; - logging_initialize(conf->command_line_options.default_log_level, &conf->global->time_info, conf->log_file_name, conf->quiet); + logging_initialize(conf->command_line_options.default_log_level, &conf->global->time_info, conf->output.log_file_name, conf->quiet); logging_set_module_name(module_name); conf->modules.module[module_id].flags = module_flags; @@ -169,4 +169,9 @@ void register_module_vital_rate(struct cats_configuration *conf, struct cats_vit strncpy(vr->name, name, MAX_VITAL_NAME_LEN + 1); m->vital_rate_count++; +} + +void add_module_output_directory(struct cats_configuration *conf, const char *name) +{ + string_array_add(conf->output.needed_module_output_directories, name); } \ No newline at end of file diff --git a/src/cats/modules/load_module.h b/src/cats/modules/load_module.h index 38dd81e811b7c6f8ff546c4e89c1e70beda751d6..bd87c6049a1eda9d523de4d79598388e476f55c2 100644 --- a/src/cats/modules/load_module.h +++ b/src/cats/modules/load_module.h @@ -50,4 +50,6 @@ void register_load_species_param_config_func(struct cats_configuration *conf, ca void print_modules(struct cats_configuration *conf); +void add_module_output_directory(struct cats_configuration *conf, const char *name); + #endif //CATS_LOAD_MODULE_H diff --git a/src/cats/paths/directory_helper.c b/src/cats/paths/directory_helper.c index 327518fa867c1ed86dc7f87a4125df41e125321f..11494f0d642625f0ccdaef0bb6580953fd6f5b95 100644 --- a/src/cats/paths/directory_helper.c +++ b/src/cats/paths/directory_helper.c @@ -59,8 +59,14 @@ struct string_array *get_needed_directories(const struct cats_configuration *con struct string_array *array = new_string_array(); string_array_add(array, "adults"); string_array_add(array, "stats"); - string_array_add(array, "environments"); - if (conf->write_all) { + + + if (conf->output.write_all && conf->output.have_glm) { + string_array_add(array, "environments"); + } + + + if (conf->output.write_all) { string_array_add(array, "seeds"); string_array_add(array, "juveniles"); } @@ -87,29 +93,36 @@ void ensure_needed_directories_exist(const struct cats_configuration *conf, cons log_message(LOG_INFO, "%s: Checking output directories", __func__); - - - - struct string_array *output = new_string_array_init(conf->output_directory); + struct string_array *output = new_string_array_init(conf->output.output_directory); check_and_create_directory_if_needed(output); free_string_array(&output); for (int32_t i = 0; i < output_dirs->count; i++) { struct string_array *path = get_output_directory(conf, output_dirs->string[i]); check_and_create_directory_if_needed(path); free_string_array(&path); + + } + + free_string_array(&output); } +void setup_module_directories(struct cats_configuration *conf) +{ + struct string_array *dirs_to_check = conf->output.needed_module_output_directories; + ensure_needed_directories_exist(conf, dirs_to_check); +} -void setup_directories(struct cats_configuration *conf) -{ if (conf->command_line_options.output_directory) { - log_message(LOG_IMPORTANT, "overriding output directory from '%s' to '%s'", conf->output_directory, +void setup_directories(struct cats_configuration *conf) +{ + if (conf->command_line_options.output_directory) { + log_message(LOG_IMPORTANT, "overriding output directory from '%s' to '%s'", conf->output.output_directory, conf->command_line_options.output_directory); - free(conf->output_directory); - conf->output_directory = strdup(conf->command_line_options.output_directory); + free(conf->output.output_directory); + conf->output.output_directory = strdup(conf->command_line_options.output_directory); } else { - log_message(LOG_IMPORTANT, "output directory is '%s'", conf->output_directory); + log_message(LOG_IMPORTANT, "output directory is '%s'", conf->output.output_directory); } struct string_array *dirs_to_check = get_needed_directories(conf); diff --git a/src/cats/paths/directory_helper.h b/src/cats/paths/directory_helper.h index 1593ce568803787e080b9b04cf0e917ad6f5493a..6632bc0ea8f99db0c0523be2b475587c6c57d0bf 100644 --- a/src/cats/paths/directory_helper.h +++ b/src/cats/paths/directory_helper.h @@ -35,5 +35,6 @@ struct string_array *get_needed_directories(const struct cats_configuration *con bool check_and_create_directory_if_needed(const struct string_array *path); +void setup_module_directories(struct cats_configuration *conf); #endif //CATS_DIRECTORY_HELPER_H diff --git a/src/cats/paths/output_paths.c b/src/cats/paths/output_paths.c index 0725cfece66698296ec98c52e31d6efd412d3a51..0bf139b941e1faa696768168a8dffd70a84c8490 100644 --- a/src/cats/paths/output_paths.c +++ b/src/cats/paths/output_paths.c @@ -36,8 +36,8 @@ const char *get_base_output_directory(const struct cats_configuration *conf) { - if (conf->output_directory && strlen(conf->output_directory)) { - return conf->output_directory; + if (conf->output.output_directory && strlen(conf->output.output_directory)) { + return conf->output.output_directory; } return DEFAULT_OUTPUT_DIRECTORY; diff --git a/src/cats/performance/performance_stats.c b/src/cats/performance/performance_stats.c index 98155d10bb7e07194f3273a5bb771d7a800d25c7..9d9355a6b712466e5e4b1fb4c64d3aab0994e577 100644 --- a/src/cats/performance/performance_stats.c +++ b/src/cats/performance/performance_stats.c @@ -27,6 +27,6 @@ void add_performance_info(const struct cats_configuration *conf, int year, const char *name, double time_cpu, double time_wall) { - if (!conf->performance_file) return; - fprintf(conf->performance_file, "%d,%s,%f,%f\n", year, name, time_cpu, time_wall); + if (!conf->output.performance_file) return; + fprintf(conf->output.performance_file, "%d,%s,%f,%f\n", year, name, time_cpu, time_wall); } \ No newline at end of file diff --git a/src/cats/stats/global_stats.c b/src/cats/stats/global_stats.c index 5e26d55d38610dfe782765e20f6b9f4eb377d9da..5e8b086b4d4edcd17d7bc1a0cff9f29fd770fa16 100644 --- a/src/cats/stats/global_stats.c +++ b/src/cats/stats/global_stats.c @@ -47,14 +47,14 @@ void initialize_global_stats(struct cats_configuration *conf) char *filename = get_global_stat_filename(conf); remove(filename); - conf->statsfile_global = fopen(filename, "a+"); - ENSURE_FILE_OPENED(conf->statsfile_global, filename) - if (conf->summary_file) fprintf(conf->summary_file, "global-stats,%s,\n",filename); + conf->output.statsfile_global = fopen(filename, "a+"); + ENSURE_FILE_OPENED(conf->output.statsfile_global, filename) + if (conf->output.summary_file) fprintf(conf->output.summary_file, "global-stats,%s,\n",filename); write_global_stats(conf, NULL, true); - fflush(conf->statsfile_global); + fflush(conf->output.statsfile_global); free(filename); } @@ -109,8 +109,8 @@ void write_global_stats(struct cats_configuration *conf, struct cats_grid *grid, } char *string = string_array_paste(x, ","); - fprintf(conf->statsfile_global, "%s", string); - fflush(conf->statsfile_global); + fprintf(conf->output.statsfile_global, "%s", string); + fflush(conf->output.statsfile_global); } diff --git a/src/cats/stats/write_stats.c b/src/cats/stats/write_stats.c index b567bec652a7b6b3c399f26f1bffc026e11f7fa3..eb80e40d7368f28f39532422f8d5a19fb3b9dac6 100644 --- a/src/cats/stats/write_stats.c +++ b/src/cats/stats/write_stats.c @@ -157,7 +157,7 @@ void gui_output_grid_stats(const struct string_array *header, const struct strin void write_grid_stats(struct cats_configuration *conf, struct cats_grid *grid, bool header) { - if (conf->performance_file && grid->id == 0) fflush(conf->performance_file); + if (conf->output.performance_file && grid->id == 0) fflush(conf->output.performance_file); if (grid->stats.file == NULL) { log_message(LOG_ERROR,