diff --git a/src/modules/butterflies/CMakeLists.txt b/src/modules/butterflies/CMakeLists.txt index e99e173564e7ec84e560963f8ed394201ff04832..5eb11b6d5a4452081c285adf236b7c305d7e2a6d 100644 --- a/src/modules/butterflies/CMakeLists.txt +++ b/src/modules/butterflies/CMakeLists.txt @@ -1,4 +1,16 @@ -add_library(cats-butterflies SHARED "" butterflies_actions.c butterflies_actions.h butterflies_vital_rates.c butterflies_vital_rates.h module.h butterflies_dispersal.c butterflies_dispersal.h butterflies_populations.c butterflies_populations.h butterflies_inline.h butterflies_generations.c butterflies_generations.h butterflies_stats.c butterflies_overlays.c butterflies_overlays.h) +add_library(cats-butterflies SHARED "" + butterflies_actions.c butterflies_actions.h + butterflies_vital_rates.c butterflies_vital_rates.h + module.h + butterflies_dispersal.c butterflies_dispersal.h + butterflies_populations.c butterflies_populations.h + butterflies_inline.h + butterflies_generations.c butterflies_generations.h + butterflies_stats.c + butterflies_overlays.c butterflies_overlays.h + butterflies_filenames.c butterflies_filenames.h + butterflies_action_helpers.c + butterflies_action_helpers.h) target_include_directories(cats-butterflies PUBLIC ".") @@ -8,10 +20,8 @@ target_sources(cats-butterflies PUBLIC - ) - set_property(TARGET cats-butterflies PROPERTY POSITION_INDEPENDENT_CODE ON) target_link_libraries(cats-butterflies cats_logging libcats) diff --git a/src/modules/butterflies/butterflies_action_helpers.c b/src/modules/butterflies/butterflies_action_helpers.c new file mode 100644 index 0000000000000000000000000000000000000000..22db214e7612f21d498e094706af134f4e1deaae --- /dev/null +++ b/src/modules/butterflies/butterflies_action_helpers.c @@ -0,0 +1,75 @@ + +#include "butterflies_action_helpers.h" +#include "configuration/configuration.h" +#include "actions/setup_actions.h" +#include "module.h" +#include "modules/module_header.h" +#include "butterflies_actions.h" +#include "butterflies_main.h" + +void bf_add_generation_action(struct cats_configuration *conf, action_function function, const char *name, + int generation) +{ + char *result = NULL; + int rc = asprintf(&result, "%s (generation %d)", name, generation); + asprintf_check(rc); + append_action(conf, function, ALL_STAGES, result, module_name); + free(result); +} + +void bf_register_actions(struct cats_configuration *conf) +{ + + register_action_function(conf, bf_action_stats_reset, "butterfly_action_reset_stats", + "resetting butterfly statistics"); + register_action_function(conf, bf_action_generation_update, "butterfly_action_update_generations", + "update generations"); + + register_action_function(conf, bf_action_generation_finish, "bf_action_generation_finish", + "update generation"); + register_action_function(conf, bf_action_generation_start, "bf_action_generation_start", + "start generation"); + + + register_action_function(conf, bf_action_maturation, "butterfly_action_egg_to_adult", + "transition eggs to adults"); + + register_action_function(conf, bf_action_overlay_update, "butterfly_action_overlay_update", + "updating overlays"); + + register_action_function(conf, bf_action_dispersal, "butterfly_action_dispersal", "egg dispersal"); + register_action_function(conf, bf_action_save_grid, "bf_action_save_grid", "output"); + register_action_function(conf, bf_action_stats_gather, "bf_action_stats_gather", "gather stats"); + register_action_function(conf, bf_action_stats_reset, "bf_action_stats_reset", "reset stats"); + register_action_function(conf, bf_action_stats_write, "bf_action_stats_write", "write stats"); +} + + +void bf_add_actions(struct cats_configuration *conf) +{ + struct conf_data_butterflies *data = CATS_MODULE_DATA; + + printf("MAXIMUM GENERATIONS %d\n", data->generations_max); + bf_register_actions(conf); + + list_actions_full(conf); + + append_action(conf, bf_action_stats_reset, ALL_STAGES, "resetting butterfly statistics", module_name); + append_action_by_name(conf, "action_load_environments", ALL_STAGES, "environment update", module_name); + append_action_by_name(conf, "action_overlay_update", ALL_STAGES, "overlay update", module_name); + append_action(conf, bf_action_overlay_update, ALL_STAGES, "updating resource layer", module_name); + append_action(conf, bf_action_generation_update, ALL_STAGES, "update generations", module_name); + + for (int32_t generation = data->generations_max; generation > 0; generation--) { + + bf_add_generation_action(conf, bf_action_stats_reset, "reset stats", generation); + bf_add_generation_action(conf, bf_action_generation_start, "start generation", generation); + bf_add_generation_action(conf, bf_action_maturation, "transition eggs to adults", + generation); + bf_add_generation_action(conf, bf_action_stats_gather, "gather stats", generation); + bf_add_generation_action(conf, bf_action_dispersal, "dispersal", generation); + bf_add_generation_action(conf, bf_action_save_grid, "output", generation); + bf_add_generation_action(conf, bf_action_generation_finish, "finish generation", generation); + bf_add_generation_action(conf, bf_action_stats_write, "write stats", generation); + } +} \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_action_helpers.h b/src/modules/butterflies/butterflies_action_helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..bd75bfabe5480e05580a0b123f0da838260afae1 --- /dev/null +++ b/src/modules/butterflies/butterflies_action_helpers.h @@ -0,0 +1,9 @@ +#ifndef CATS_BUTTERFLIES_ACTION_HELPERS_H +#define CATS_BUTTERFLIES_ACTION_HELPERS_H + +#include "configuration/configuration.h" + +void bf_register_actions(struct cats_configuration *conf); +void bf_add_actions(struct cats_configuration *conf); + +#endif //CATS_BUTTERFLIES_ACTION_HELPERS_H diff --git a/src/modules/butterflies/butterflies_actions.c b/src/modules/butterflies/butterflies_actions.c index 0fe97aa6b989a6689f20f2386a55d624e1e04ae6..9ae122262f298e669f601a976340181f6df72dcd 100644 --- a/src/modules/butterflies/butterflies_actions.c +++ b/src/modules/butterflies/butterflies_actions.c @@ -1,9 +1,6 @@ - #include "actions/cats_actions.h" -#include "actions/setup_actions.h" #include "modules/module_header.h" #include "butterflies_actions.h" -#include "module.h" #include "butterflies_main.h" #include "inline_overlays.h" #include "butterflies_populations.h" @@ -11,29 +8,17 @@ #include "butterflies_inline.h" #include "grids/grid_wrapper.h" #include "grids/gdal_save.h" -#include "paths/output_paths.h" #include "paths/paths.h" #include "populations/population.h" -#include "inline_population.h" #include "butterflies_generations.h" #include "butterflies_dispersal.h" #include "butterflies_overlays.h" +#include "butterflies_filenames.h" -inline void increase_custom_stat(struct statistics stats, int64_t stat_id, int64_t by) -{ - -} - - -inline void ensure_valid_stat_id(struct statistics stats, int64_t stat_id) +enum action_status bf_action_stats_reset(struct cats_grid *grid, struct cats_configuration *conf) { - -} - -enum action_status action_butterfly_stats_reset(struct cats_grid *grid, struct cats_configuration *conf) -{ - return ACTION_RUN; + return action_grid_stats_reset(grid, conf); } @@ -46,25 +31,22 @@ void grid_butterflies_maturation(struct cats_grid *grid, struct cats_thread_info const cats_dt_coord start_col = ts->area.start_col; const cats_dt_coord end_col = ts->area.end_col; - ts->temp = 0; for (cats_dt_coord row = start_row; row < end_row; row++) { for (cats_dt_coord col = start_col; col < end_col; col++) { if (cell_excluded_by_overlay(conf, row, col) - || cell_excluded_by_generation(grid, row, col)) { + || bf_cell_excluded_by_generation(grid, row, col)) { continue; } - butterflies_cell_maturation(grid, ts, row, col, false); - - + bf_cell_maturation(grid, ts, row, col, false); } } } -void grid_butterflies_dispersal(struct cats_grid *grid, struct cats_thread_info *ts) +void butterflies_area_dispersal(struct cats_grid *grid, struct cats_thread_info *ts) { struct cats_configuration *conf = ts->conf; const cats_dt_coord start_row = ts->area.start_row; @@ -73,18 +55,16 @@ void grid_butterflies_dispersal(struct cats_grid *grid, struct cats_thread_info const cats_dt_coord start_col = ts->area.start_col; const cats_dt_coord end_col = ts->area.end_col; - // struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; - //const int module_id = CATS_MODULE_ID; - //struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; - ts->temp = 0; ts->temp1 = 0; ts->temp2 = 0; + + for (cats_dt_coord row = start_row; row < end_row; row++) { for (cats_dt_coord col = start_col; col < end_col; col++) { if (cell_excluded_by_overlay(conf, row, col) - || cell_excluded_by_generation(grid, row, col)) { + || bf_cell_excluded_by_generation(grid, row, col)) { continue; } @@ -95,62 +75,18 @@ void grid_butterflies_dispersal(struct cats_grid *grid, struct cats_thread_info } -void grid_butterflies_kill_adults(struct cats_grid *grid, struct cats_thread_info *ts) -{ - const cats_dt_coord start_row = ts->area.start_row; - const cats_dt_coord end_row = ts->area.end_row; - - const cats_dt_coord start_col = ts->area.start_col; - const cats_dt_coord end_col = ts->area.end_col; - - for (cats_dt_coord row = start_row; row < end_row; row++) { - for (cats_dt_coord col = start_col; col < end_col; col++) { - set_population_ignore_cc(grid, row, col, 0); - } - } -} - - -enum action_status action_butterflies_maturation(struct cats_grid *grid, struct cats_configuration *conf) +enum action_status bf_action_maturation(struct cats_grid *grid, struct cats_configuration *conf) { threaded_action(&grid_butterflies_maturation, grid, conf, TS_DEFAULT); return ACTION_RUN; } -char *get_butterfly_population_filename(struct cats_configuration *conf, struct cats_grid *grid) -{ - - assert(grid != NULL); - assert(conf != NULL); - assert(conf->grid_count == 1); - - int module_id = CATS_MODULE_ID; - struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; - - - struct string_array *path = get_output_directory(conf, "butterfly-adults"); // FIXME MAKE DIRECTORY - - char *extension = get_extension(conf, "adults"); - struct string_array *name = standard_output_file_name(conf, NULL, NULL, NULL); - string_array_add_int(name, data->generation_current, "g%03d"); - - char *filename = assemble_filename(path, name, "_", extension); - - free_string_array(&path); - free_string_array(&name); - free(extension); - - return filename; - - -} - -enum action_status action_butterflies_save_grid(struct cats_grid *grid, struct cats_configuration *conf) +enum action_status bf_action_save_grid(struct cats_grid *grid, struct cats_configuration *conf) { int32_t id = grid->id; - char *filename = get_butterfly_population_filename(conf, grid); + char *filename = bf_population_filename(conf, grid); struct grid_wrapper data = gridwrapper(grid->population, grid->dimension); save_grid_to_gdal(&data, GDT_Int32, conf, filename, conf->param[id].species_name); free(filename); @@ -158,57 +94,37 @@ enum action_status action_butterflies_save_grid(struct cats_grid *grid, struct c } -enum action_status action_butterflies_kill_adults(struct cats_grid *grid, struct cats_configuration *conf) +enum action_status bf_action_dispersal(struct cats_grid *grid, struct cats_configuration *conf) { - threaded_action(&grid_butterflies_kill_adults, grid, conf, TS_DEFAULT); - - return ACTION_RUN; -} - + threaded_action(&butterflies_area_dispersal, grid, conf, TS_DISPERSAL); + struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; -enum action_status action_butterflies_dispersal(struct cats_grid *grid, struct cats_configuration *conf) -{ - threaded_action(&grid_butterflies_dispersal, grid, conf, TS_DISPERSAL); + for (enum butterfly_stats which = BF_POPULATED_AT_DISPERSAL; which < BF_STAT_MAX; which++) { + int64_t stat_id = module_conf->stat_ids[which]; + printf("%s: %ld\n", bf_get_stats_field_name(which), grid->stats.stats[stat_id]); + } + exit_cats(EXIT_SUCCESS); return ACTION_RUN; } -enum action_status action_butterflies_output(struct cats_grid *grid, struct cats_configuration *conf) +enum action_status bf_action_stats_gather(struct cats_grid *grid, struct cats_configuration *conf) { + threaded_action(&bf_area_stats_gather, grid, conf, TS_DEFAULT); return ACTION_RUN; } -enum action_status action_butterfly_stats_gather(struct cats_grid *grid, struct cats_configuration *conf) +enum action_status bf_action_stats_write(__attribute__((unused)) struct cats_grid *grid, __attribute__((unused)) struct cats_configuration *conf) { - struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; - int64_t excluded_id = module_conf->stat_ids[BF_STAT_EXCLUDED]; - - const cats_dt_coord rows = grid->dimension.rows; - const cats_dt_coord cols = grid->dimension.cols; - for (cats_dt_coord row = 0; row < rows; row++) { - for (cats_dt_coord col = 0; col < cols; col++) { - if (cell_excluded_by_overlay(conf, row, col)) { - increase_custom_stat(grid->stats, excluded_id, 1); - continue; - } - + bf_stats_write(conf, grid); - - } - } return ACTION_RUN; } - -enum action_status action_butterfly_stats_write(struct cats_grid *grid, struct cats_configuration *conf) -{ - return ACTION_RUN; -} - - -enum action_status action_butterfly_update_generations(struct cats_grid *grid, struct cats_configuration *conf) +// only run at the start of the year +enum action_status bf_action_generation_update(struct cats_grid *grid, struct cats_configuration *conf) { int module_id = CATS_MODULE_ID; struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; @@ -224,117 +140,38 @@ enum action_status action_butterfly_update_generations(struct cats_grid *grid, s grid->param.initial_population.adjusted = true; } - threaded_action(&area_update_generations, grid, conf, TS_DEFAULT); + threaded_action(&bf_area_generation_update, grid, conf, TS_DEFAULT); return ACTION_RUN; } -void reset_info_layer(const struct cats_grid *grid, struct grid_data_butterflies *data) +enum action_status bf_action_overlay_update(struct cats_grid *grid, struct cats_configuration *conf) { - const cats_dt_coord rows = grid->dimension.rows; - const cats_dt_coord cols = grid->dimension.cols; - - for (cats_dt_coord row = 0; row < rows; row++) { - for (cats_dt_coord col = 0; col < cols; col++) { - data->info_layer[row][col] = 0; - } - } + return bf_grid_overlay_update(conf, grid); } -enum action_status action_butterflies_update_overlays(struct cats_grid *grid, struct cats_configuration *conf) -{ - return butterflies_update_overlays(conf, grid); -} - - -enum action_status action_finish_generation(struct cats_grid *grid, struct cats_configuration *conf) +enum action_status bf_action_generation_finish(struct cats_grid *grid, struct cats_configuration *conf) { const int module_id = CATS_MODULE_ID; struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; + threaded_action(&bf_area_kill_adults, grid, conf, TS_DEFAULT); + + data->generation_current--; - log_message(LOG_IMPORTANT, "Setting generation to %d\n", data->generation_current); assert(data->generation_current >= 0); // struct conf_data_butterflies *data = CATS_MODULE_DATA; return ACTION_RUN; } -enum action_status action_start_generation(struct cats_grid *grid, struct cats_configuration *conf) +enum action_status bf_action_generation_start(struct cats_grid *grid, __attribute__((unused)) struct cats_configuration *conf) { int module_id = CATS_MODULE_ID; struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; - log_message(LOG_IMPORTANT, "Starting generation to %d\n", data->generation_current); assert(data->generation_current >= 0); - // struct conf_data_butterflies *data = CATS_MODULE_DATA; return ACTION_RUN; } - - -void add_butterfly_generation_action(struct cats_configuration *conf, action_function function, const char *name, - int generation) -{ - char *result = NULL; - int rc = asprintf(&result, "%s (generation %d)", name, generation); - asprintf_check(rc); - append_action(conf, function, ALL_STAGES, result, module_name); - free(result); -} - - -void add_actions(struct cats_configuration *conf) -{ - struct conf_data_butterflies *data = CATS_MODULE_DATA; - - printf("MAXIMUM GENERATIONS %d\n", data->generations_max); - - register_action_function(conf, action_butterfly_stats_reset, "butterfly_action_reset_stats", - "resetting butterfly statistics"); - register_action_function(conf, action_butterfly_update_generations, "butterfly_action_update_generations", - "update generations"); - - register_action_function(conf, action_finish_generation, "action_finish_generation", - "update generation"); - register_action_function(conf, action_start_generation, "action_start_generation", - "start generation"); - - - register_action_function(conf, action_butterflies_maturation, "butterfly_action_egg_to_adult", - "transition eggs to adults"); - - register_action_function(conf, action_butterflies_update_overlays, "butterfly_action_overlay_update", - "updating overlays"); - - register_action_function(conf, action_butterflies_dispersal, "butterfly_action_dispersal", "egg dispersal"); - register_action_function(conf, action_butterflies_kill_adults, "butterfly_kill_adults", "kill adults"); - register_action_function(conf, action_butterflies_save_grid, "action_butterflies_save_grid", "output"); - register_action_function(conf, action_butterfly_stats_gather, "action_butterfly_stats_gather", "gather stats"); - register_action_function(conf, action_butterfly_stats_reset, "action_butterfly_stats_reset", "reset stats"); - register_action_function(conf, action_butterfly_stats_write, "action_butterfly_stats_write", "write stats"); - list_actions_full(conf); - - - append_action(conf, action_butterfly_stats_reset, ALL_STAGES, "resetting butterfly statistics", module_name); - append_action_by_name(conf, "action_load_environments", ALL_STAGES, "environment update", module_name); - append_action_by_name(conf, "action_overlay_update", ALL_STAGES, "overlay update", module_name); - append_action(conf, action_butterflies_update_overlays, ALL_STAGES, "updating resource layer", module_name); - append_action(conf, action_butterfly_update_generations, ALL_STAGES, "update generations", module_name); - - for (int32_t generation = data->generations_max; generation > 0; generation--) { - - add_butterfly_generation_action(conf, action_butterfly_stats_reset, "reset stats", generation); - add_butterfly_generation_action(conf, action_start_generation, "start generation", generation); - add_butterfly_generation_action(conf, action_butterflies_maturation, "transition eggs to adults", - generation); - add_butterfly_generation_action(conf, action_butterfly_stats_gather, "gather stats", generation); - add_butterfly_generation_action(conf, action_butterflies_dispersal, "dispersal", generation); - add_butterfly_generation_action(conf, action_butterflies_save_grid, "output", generation); - add_butterfly_generation_action(conf, action_butterflies_kill_adults, "kill adults", generation); - add_butterfly_generation_action(conf, action_finish_generation, "finish generation", generation); - add_butterfly_generation_action(conf, action_butterfly_stats_write, "write stats", generation); - } - -} \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_actions.h b/src/modules/butterflies/butterflies_actions.h index 5b785bc5e96d9d249d5d71f7d645b138186e1cbb..69a0c17268dd9a89412e1c155f663d8311b21955 100644 --- a/src/modules/butterflies/butterflies_actions.h +++ b/src/modules/butterflies/butterflies_actions.h @@ -1,6 +1,26 @@ - #ifndef CATS_BUTTERFLIES_ACTIONS_H #define CATS_BUTTERFLIES_ACTIONS_H + #include "configuration/configuration.h" -void add_actions(struct cats_configuration *conf); + +enum action_status bf_action_maturation(struct cats_grid *grid, struct cats_configuration *conf); + +enum action_status bf_action_save_grid(struct cats_grid *grid, struct cats_configuration *conf); + +enum action_status bf_action_dispersal(struct cats_grid *grid, struct cats_configuration *conf); + +enum action_status bf_action_stats_gather(struct cats_grid *grid, struct cats_configuration *conf); + +enum action_status bf_action_stats_reset(__attribute__((unused)) struct cats_grid *grid, __attribute__((unused)) struct cats_configuration *conf); + +enum action_status bf_action_stats_write(__attribute__((unused)) struct cats_grid *grid, __attribute__((unused)) struct cats_configuration *conf); + +enum action_status bf_action_overlay_update(struct cats_grid *grid, struct cats_configuration *conf); + +enum action_status bf_action_generation_finish(struct cats_grid *grid, struct cats_configuration *conf); + +enum action_status bf_action_generation_start(struct cats_grid *grid, __attribute__((unused)) struct cats_configuration *conf); + +enum action_status bf_action_generation_update(struct cats_grid *grid, struct cats_configuration *conf); + #endif //CATS_BUTTERFLIES_ACTIONS_H diff --git a/src/modules/butterflies/butterflies_dispersal.c b/src/modules/butterflies/butterflies_dispersal.c index dcff01f41c4082ad09c1fe75523b1a04a190ca75..d136ecdb932327e9e5bc129d992167bfd47f65b9 100644 --- a/src/modules/butterflies/butterflies_dispersal.c +++ b/src/modules/butterflies/butterflies_dispersal.c @@ -1,6 +1,3 @@ -// -// Created by gattringera on 21/11/22. -// #include "inline_population.h" #include "butterflies_inline.h" #include "misc/cats_random.h" @@ -23,26 +20,21 @@ const int N_DIRECTIONS = 9; */ const cats_dt_coord DIRECTION_OFFSETS[9][2] = { - {+0, +0}, {+0, +1}, {-1, +1}, - {-1, +0}, {-1, -1}, {+0, -1}, - {+1, -1}, {+1, +0}, {+1, +1} + {+0, +0}, + {+0, +1}, + {-1, +1}, + {-1, +0}, + {-1, -1}, + {+0, -1}, + {+1, -1}, + {+1, +0}, + {+1, +1} }; - - -void add_dispersed_eggs(struct cats_configuration *conf, struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, float eggs) -{ - //struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; - const int module_id = CATS_MODULE_ID; - struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; - assert(eggs >= 0); - data->eggs[row][col] += eggs; -} - - - -static void inline single_random_walk(struct cats_thread_info *ts, struct cats_grid *grid, cats_dt_coord source_row, cats_dt_coord source_col, int32_t eggs, cats_dt_rates egg_fraction_step, int32_t rw_num) +static void inline single_random_walk(struct cats_thread_info *ts, struct cats_grid *grid, cats_dt_coord source_row, + cats_dt_coord source_col, int32_t eggs, cats_dt_rates egg_fraction_step, + __attribute__((unused)) int32_t rw_num) { const int module_id = CATS_MODULE_ID; @@ -62,9 +54,10 @@ static void inline single_random_walk(struct cats_thread_info *ts, struct cats_g while (steps < max_steps) { const unsigned long int direction = gsl_rng_uniform_int(ts->rng, N_DIRECTIONS); - const cats_dt_coord *offsets = DIRECTION_OFFSETS[direction]; + + const cats_dt_coord *offsets = DIRECTION_OFFSETS[direction]; const cats_dt_coord row_offset = offsets[0]; const cats_dt_coord col_offset = offsets[1]; @@ -74,14 +67,12 @@ static void inline single_random_walk(struct cats_thread_info *ts, struct cats_g row += row_offset; col += col_offset; - if (row >= rows || row < 0 || col >= cols || col < 0) { + if (row >= rows || row < 0 || col >= cols || col < 0) { return; // we escaped the simulation extent and got lost } - - // is the cell a valid dispersal target location? - if (! (data->info_layer[row][col] & BF_CELL_VALID_DISPERSAL_TARGET)) { + if (!(data->info_layer[row][col] & BF_CELL_VALID_DISPERSAL_TARGET)) { continue; } @@ -94,10 +85,7 @@ static void inline single_random_walk(struct cats_thread_info *ts, struct cats_g eggs_left -= eggs_to_deposit; data->eggs[row][col] += (float) eggs_to_deposit; - - - - + ts->temp2++; if (eggs_left == 0) break; steps++; @@ -107,31 +95,36 @@ static void inline single_random_walk(struct cats_thread_info *ts, struct cats_g } -void butterflies_cell_dispersal(struct cats_grid *grid, struct cats_thread_info *ts, cats_dt_coord row, cats_dt_coord col, bool check_exclusion) +void +butterflies_cell_dispersal(struct cats_grid *grid, struct cats_thread_info *ts, cats_dt_coord row, cats_dt_coord col, + bool check_exclusion) { const struct cats_configuration *conf = ts->conf; if (check_exclusion - && (cell_excluded_by_overlay(conf, row, col) ||cell_excluded_by_generation(grid, row, col))) return; + && (cell_excluded_by_overlay(conf, row, col) || bf_cell_excluded_by_generation(grid, row, col))) + return; // total adults: the number of adults that became adult in this cell, possibly exceeding the carrying capacity (thanks to poisson processes) - cats_dt_population total_adults = get_adult_population(grid, row, col); - cats_dt_population cc = get_carrying_capacity(grid, row, col); + const cats_dt_population total_adults = get_adult_population(grid, row, col); + if (total_adults == 0) return; + ts->temp++; // total females: how many of the total adults are female, as drawn from a binomial distribution with p = 0.5 // can be safely cast, because gsl_ran_binomial will return a number <= total_adults - cats_dt_population total_females = (cats_dt_population) gsl_ran_binomial(ts->rng, 0.5, total_adults); - assert(total_females > 0 && total_females <= total_adults); + const cats_dt_population total_females = (cats_dt_population) gsl_ran_binomial(ts->rng, 0.5, total_adults); + assert(total_females >= 0 && total_females <= total_adults); // total males: the rest - cats_dt_population total_males = total_adults - total_females; + const cats_dt_population total_males = total_adults - total_females; // we need at least one female and one male if (total_females == 0 || total_males == 0) return; // here we calculate the number of eggs per female, so we can return early if the cell is unsuitable struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; - cats_dt_rates eggs_per_f = calculate_rate(&module_conf->eggs_per_female, total_adults, &grid->param, grid, row, col, NULL); + cats_dt_rates eggs_per_f = calculate_rate(&module_conf->eggs_per_female, total_adults, &grid->param, grid, row, + col, NULL); int32_t eggs_per_female = (int32_t) ceill(eggs_per_f); assert(eggs_per_female >= 0); @@ -139,7 +132,8 @@ void butterflies_cell_dispersal(struct cats_grid *grid, struct cats_thread_info // supernumerous_adults: the number of adults exceeding the carrying capacity - cats_dt_population supernumerous_adults = total_adults - cc; + const cats_dt_population cc = get_carrying_capacity(grid, row, col); + const cats_dt_population supernumerous_adults = total_adults - cc; // supernumerous_females: the (randomly assigned, drawn from a hypergeometric distribution) number of females // in the number of supernumerous adults @@ -150,55 +144,57 @@ void butterflies_cell_dispersal(struct cats_grid *grid, struct cats_thread_info // Too many adults in the cell. These must leave the cell, either to be added to the number of // * dispersing females // * discarded (males) - supernumerous_females = (cats_dt_population) gsl_ran_hypergeometric(ts->rng, total_females, total_males, supernumerous_adults); + supernumerous_females = (cats_dt_population) gsl_ran_hypergeometric(ts->rng, total_females, total_males, + supernumerous_adults); + } - // remaining_females: the number of females within the carrying capacity - cats_dt_population remaining_females = total_females - supernumerous_females; - // at this point the number of 'remaining' adults in the cell is equal or less than the carrying capacity + // females_within_cc: the number of females within the carrying capacity + cats_dt_population females_within_cc = total_females - supernumerous_females; + + // at this point the number of 'remaining' adults in the cell is equal or less than the carrying capacity // how many females will leave the cell (not counting the number of supernumerous ones)? // wandering_females: the number of females that will leave the cell and do a random walk - // we draw from a Poisson distribution with a species-specific parameter, the probability to leave times the - // number of females - cats_dt_rates probability_to_leave = 1.0 - module_conf->probability_to_stay; - cats_dt_population wandering_females = poisson(ts->rng, remaining_females * probability_to_leave); - - // but cap the number of females actually available - if (wandering_females > remaining_females) { - wandering_females = remaining_females; + cats_dt_population wandering_females = + (cats_dt_population) (females_within_cc * (1.0 - module_conf->probability_to_stay)); + + // stationary_females: the number of females that will not leave the cell, and leave all their eggs here + cats_dt_population stationary_females = females_within_cc - wandering_females; + + if (wandering_females < 0) { + wandering_females = 0; } // we need to add the previously subtracted supernumerous females wandering_females += supernumerous_females; - // stationary_females: the number of females that will not leave the cell, and leave all their eggs here - cats_dt_population stationary_females = total_females - wandering_females; - - const int module_id = CATS_MODULE_ID; struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; - // how many eggs are deposited in the local cell? - // all the eggs of all the stationary females - cats_dt_rates local_eggs = (stationary_females * eggs_per_female); - // plus the local fraction of the eggs for the wandering females - cats_dt_rates wandering_local_eggs = (module_conf->egg_fraction_source * eggs_per_female); - local_eggs += (wandering_females * wandering_local_eggs); - data->eggs[row][col] += (float) ceill(local_eggs); + int32_t eggs_to_disperse_per_female = (int32_t) ceill( + eggs_per_female * (1.0 - module_conf->egg_fraction_source)); + + // all the eggs of all the stationary females + the eggs the wandering females leave in the source cell + const cats_dt_rates source_cell_eggs = stationary_females * eggs_per_female + + wandering_females * (eggs_per_female - eggs_to_disperse_per_female); - int32_t wandering_eggs = (int32_t) ceill(eggs_per_female - wandering_local_eggs); + // add source cell eggs to the source cell + data->eggs[row][col] += (float) ceill(source_cell_eggs); - if (wandering_eggs == 0) { + if (eggs_to_disperse_per_female == 0) { log_message(LOG_ERROR, "%s: random walk with no eggs to distribute in cell %d %d", __func__, row, col); return; } - // fixme maybe define threshold over which the random walks are bundled + // FIXME: define threshold over which the random walks are bundled const cats_dt_rates egg_fraction_step = module_conf->egg_fraction_step; + //printf("thread %d: row %d col %d: doing %d rws\n", ts->id, row, col, wandering_females); + for (int32_t rw_number = 0; rw_number < wandering_females; rw_number++) { - single_random_walk(ts, grid, row, col, wandering_eggs, egg_fraction_step, rw_number); + single_random_walk(ts, grid, row, col, eggs_to_disperse_per_female, egg_fraction_step, rw_number); + ts->temp1++; } } \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_filenames.c b/src/modules/butterflies/butterflies_filenames.c new file mode 100644 index 0000000000000000000000000000000000000000..56f0323f93ba4757e30f507285235b588f124fa6 --- /dev/null +++ b/src/modules/butterflies/butterflies_filenames.c @@ -0,0 +1,52 @@ +#include "butterflies_generations.h" +#include "paths/paths.h" +#include "paths/output_paths.h" +#include "butterflies_populations.h" +#include "inline_overlays.h" +#include "butterflies_main.h" +#include "butterflies_actions.h" +#include "modules/module_header.h" +#include "actions/cats_actions.h" +#include "butterflies_filenames.h" +#include "module.h" + + +char *bf_population_filename(struct cats_configuration *conf, struct cats_grid *grid) +{ + assert(grid != NULL); + assert(conf != NULL); + assert(conf->grid_count == 1); + + int module_id = CATS_MODULE_ID; + struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; + + + struct string_array *path = get_output_directory(conf, "butterfly-adults"); // FIXME MAKE DIRECTORY + + char *extension = get_extension(conf, "adults"); + struct string_array *name = standard_output_file_name(conf, NULL, NULL, NULL); + string_array_add_int(name, data->generation_current, "g%03d"); + + char *filename = assemble_filename(path, name, "_", extension); + + free_string_array(&path); + free_string_array(&name); + free(extension); + + return filename; +} + +char *bf_stats_filename(struct cats_configuration *conf, struct cats_grid *grid) +{ + struct string_array *path = get_output_directory(conf, "stats"); + + struct string_array *name = new_string_array(); + string_array_add(name, module_name); + string_array_add(name, conf->run_name); + string_array_add_int(name, conf->simulation.replicate, "r%03d"); + char *filename = assemble_filename(path, name, "_", "csv"); + free_string_array(&path); + free_string_array(&name); + + return filename; +} \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_filenames.h b/src/modules/butterflies/butterflies_filenames.h new file mode 100644 index 0000000000000000000000000000000000000000..92a3cd36a34b2082ab82d6b4f2e756903dc5f5b5 --- /dev/null +++ b/src/modules/butterflies/butterflies_filenames.h @@ -0,0 +1,8 @@ +#ifndef CATS_BUTTERFLIES_FILENAMES_H +#define CATS_BUTTERFLIES_FILENAMES_H + +#include "configuration/configuration.h" + +char *bf_population_filename(struct cats_configuration *conf, struct cats_grid *grid); +char *bf_stats_filename(struct cats_configuration *conf, struct cats_grid *grid); +#endif //CATS_BUTTERFLIES_FILENAMES_H diff --git a/src/modules/butterflies/butterflies_generations.c b/src/modules/butterflies/butterflies_generations.c index c349f7959f31b4d2789576fb004e302600443303..f466eb2266da7aef766c7869b975051d7dd8d19f 100644 --- a/src/modules/butterflies/butterflies_generations.c +++ b/src/modules/butterflies/butterflies_generations.c @@ -1,4 +1,3 @@ - #include "butterflies_populations.h" #include "inline_overlays.h" #include "butterflies_main.h" @@ -7,7 +6,8 @@ #include "butterflies_generations.h" #include "inline.h" -void area_update_generations(struct cats_grid *grid, struct cats_thread_info *ts) +// only run at the start of the year +void bf_area_generation_update(struct cats_grid *grid, struct cats_thread_info *ts) { struct cats_configuration *conf = ts->conf; struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; @@ -21,14 +21,15 @@ void area_update_generations(struct cats_grid *grid, struct cats_thread_info *ts const cats_dt_coord start_col = ts->area.start_col; const cats_dt_coord end_col = ts->area.end_col; + for (cats_dt_coord row = start_row; row < end_row; row++) { for (cats_dt_coord col = start_col; col < end_col; col++) { - if (cell_excluded_by_overlay(conf, row, col)) { + if (cell_excluded_by_overlay(conf, row, col) + || (data->info_layer[row][col] & BF_CELL_VALID_DISPERSAL_TARGET) == false) { data->eggs[row][col] = 0.0f; - set_population_ignore_cc(grid, row, col, 0); - data->generations[row][col] = 0.0f; + set_population_ignore_cc(grid, row, col, 0); continue; } diff --git a/src/modules/butterflies/butterflies_generations.h b/src/modules/butterflies/butterflies_generations.h index 343d78e641969c4bcba3226ab7026778ac313dba..5df061be22cd4cf788a65ed00eab4d09ba65f98a 100644 --- a/src/modules/butterflies/butterflies_generations.h +++ b/src/modules/butterflies/butterflies_generations.h @@ -1,6 +1,9 @@ #ifndef CATS_BUTTERFLIES_GENERATIONS_H #define CATS_BUTTERFLIES_GENERATIONS_H + #include "data/cats_grid.h" #include "threading/threading.h" -void area_update_generations(struct cats_grid *grid, struct cats_thread_info *ts); -#endif //CATS_BUTTERFLIES_GENERATIONS_H + +void bf_area_generation_update(struct cats_grid *grid, struct cats_thread_info *ts); + +#endif //CATS_BUTTERFLIES_GENERATIONS_H \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_inline.h b/src/modules/butterflies/butterflies_inline.h index 2574b22ae0502da3806fbcdded6a45e2b66b1efd..2551ab7c3d6894228886493398ed61fdeb0c9482 100644 --- a/src/modules/butterflies/butterflies_inline.h +++ b/src/modules/butterflies/butterflies_inline.h @@ -8,12 +8,11 @@ #include "modules/module_header.h" - -static inline bool cell_excluded_by_generation (const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) +static inline bool bf_cell_excluded_by_generation(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) { const int module_id = CATS_MODULE_ID; const struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; - if (data->generation_current > (int32_t) ceilf(data->generations[row][col])) return true; + if (data->generation_current == 0.0 || data->generation_current > (int32_t) ceilf(data->generations[row][col])) return true; return false; } diff --git a/src/modules/butterflies/butterflies_main.c b/src/modules/butterflies/butterflies_main.c index 91809b744520bc856362600bed79de8597fec94f..108f378e35185a53360a3d9249069c15cf5d21fc 100644 --- a/src/modules/butterflies/butterflies_main.c +++ b/src/modules/butterflies/butterflies_main.c @@ -7,12 +7,13 @@ #include "butterflies_actions.h" #include "butterflies_vital_rates.h" #include "cats_ini/cats_ini.h" +#include "butterflies_action_helpers.h" struct cats_global global; struct cats_debug_options cats_debug; -void *butterfly_grid_init(struct cats_configuration *conf, struct cats_grid *grid, void *ignored) +void *butterfly_grid_init(__attribute__((unused)) struct cats_configuration *conf, struct cats_grid *grid, __attribute__((unused)) void *ignored) { log_message(LOG_INFO, "%s: %s: grid init", module_name, __func__); printf("%d %d\n", grid->dimension.cols, grid->dimension.rows); @@ -36,7 +37,7 @@ void *butterfly_grid_init(struct cats_configuration *conf, struct cats_grid *gri } -void *butterfly_grid_cleanup(struct cats_configuration *conf, struct cats_grid *grid, void *data) +void *butterfly_grid_cleanup(__attribute__((unused)) struct cats_configuration *conf, struct cats_grid *grid, void *data) { log_message(LOG_INFO, "%s: grid cleanup", module_name); assert(grid != NULL); @@ -58,13 +59,12 @@ void load_butterflies_species_params(struct cats_configuration *conf, struct cat { struct conf_data_butterflies *data = CATS_MODULE_DATA; - load_conf_vital_rate(&data->eggs_per_female, conf, ini, section_name, param); load_conf_vital_rate(&data->butterfly_generations, conf, ini, section_name, param); - load_conf_vital_rate(&data->butterfly_egg_to_adult_survival, conf, ini, section_name, param); - cats_dt_rates female_percentage; + load_conf_vital_rate(&data->butterfly_egg_to_adult_survival, conf, ini, section_name, param); + load_conf_value(true, ini, section_name, "butterflies random walk steps maximum", &data->animal_dispersal_max_radius); if (data->animal_dispersal_max_radius <= 0) { @@ -72,16 +72,23 @@ void load_butterflies_species_params(struct cats_configuration *conf, struct cat exit_cats(EXIT_FAILURE); } - load_conf_value(true, ini, section_name, "butterflies female fraction", &female_percentage); + load_conf_value(true, ini, section_name, "butterflies probability to stay", &data->probability_to_stay); + + if (data->probability_to_stay < 0.0 || data->probability_to_stay > 1.0) { + log_message(LOG_ERROR, "butterflies probability to stay has to be in range [0, 1]"); + exit_cats(EXIT_FAILURE); + } + data->generations_max = (int32_t) ceill(data->butterfly_generations.max_rate); + data->generations_min = (int32_t) ceill(data->butterfly_generations.min_rate); param->plant_dispersal_max_radius = data->animal_dispersal_max_radius; + if (! data->actions_added) { - add_actions(conf); + bf_register_actions(conf); + bf_add_actions(conf); data->actions_added = true; } - - } @@ -92,12 +99,11 @@ void cats_module_init(struct cats_configuration *conf) int32_t id = register_module(conf, module_name, data, flags); register_cats_grid_init_function(conf, butterfly_grid_init, butterfly_grid_cleanup); register_load_species_param_config_func(conf, load_butterflies_species_params); - add_vital_rates(conf, data); + bf_add_vital_rates(conf, data); log_message(LOG_INFO, "Hello from %s (id: %d)\n", module_name, id); for (enum butterfly_stats which = BF_STAT_MIN; which < BF_STAT_MAX; which++) { - data->stat_ids[which] = add_custom_stat(&conf->stats_registry, get_butterfly_stats_name(which)); + data->stat_ids[which] = add_custom_stat(&conf->stats_registry, bf_get_stats_field_name(which)); } } - diff --git a/src/modules/butterflies/butterflies_main.h b/src/modules/butterflies/butterflies_main.h index 3e9496eab5164ea55fe4b23542239a5c372b220f..0170209bfdded5f4759fed9f085740281cb8e22c 100644 --- a/src/modules/butterflies/butterflies_main.h +++ b/src/modules/butterflies/butterflies_main.h @@ -33,23 +33,27 @@ enum butterfly_cell_info { struct conf_data_butterflies { // fixme -> move to grid data; - int32_t generations_max; + int32_t current_generation; + int32_t generations_max; + int32_t generations_min; int32_t animal_dispersal_max_radius; ///< maximal flight/dispersal distance cats_dt_rates egg_to_adult_survival_rate_maximum; cats_dt_rates egg_per_female_maximum; cats_dt_rates probability_to_stay; cats_dt_rates egg_fraction_source; cats_dt_rates egg_fraction_step; - - - - bool actions_added; cats_dt_rates stationary_females; struct cats_vital_rate eggs_per_female; struct cats_vital_rate butterfly_egg_to_adult_survival; struct cats_vital_rate butterfly_generations; + + + bool actions_added; + int64_t stat_ids[BF_STAT_MAX]; + FILE *stats_file; + }; diff --git a/src/modules/butterflies/butterflies_overlays.c b/src/modules/butterflies/butterflies_overlays.c index 050de1a59a8c2dd4c1af66d1a476ab0dd6faedee..dfc589bc364298ac44bdc44b5b9d1fe41bd0fba0 100644 --- a/src/modules/butterflies/butterflies_overlays.c +++ b/src/modules/butterflies/butterflies_overlays.c @@ -1,16 +1,15 @@ - - - +#include "paths/paths.h" +#include "butterflies_populations.h" #include "modules/module_header.h" #include "actions/cats_actions.h" + +#include "butterflies_overlays.h" #include "butterflies_main.h" #include "inline_overlays.h" -enum action_status butterflies_update_overlays(struct cats_configuration *conf, struct cats_grid *grid) +enum action_status bf_grid_overlay_update(const struct cats_configuration *conf, struct cats_grid *grid) { - - if (conf->overlays.have_overlays == false) { return ACTION_NOT_RUN; } @@ -18,6 +17,7 @@ enum action_status butterflies_update_overlays(struct cats_configuration *conf, int module_id = CATS_MODULE_ID; struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; + const cats_dt_coord rows = grid->dimension.rows; const cats_dt_coord cols = grid->dimension.cols; @@ -28,8 +28,11 @@ enum action_status butterflies_update_overlays(struct cats_configuration *conf, if (cell_excluded_by_overlay(conf, row, col)) { data->info_layer[row][col] |= BF_CELL_EXCLUDED; + continue; } + data->info_layer[row][col] = BF_CELL_VALID_DISPERSAL_TARGET; + if (conf->overlays.overlay[OL_HABITAT_TYPE_CC].enabled && conf->overlays.habitat_cc->data[row][col] > 0) { data->info_layer[row][col] |= BF_CELL_HABITAT_OK; @@ -49,4 +52,4 @@ enum action_status butterflies_update_overlays(struct cats_configuration *conf, } return ACTION_RUN; -} \ No newline at end of file +} diff --git a/src/modules/butterflies/butterflies_overlays.h b/src/modules/butterflies/butterflies_overlays.h index f1e3f26e2d07b517ddbfd68ab96f5411577a6354..4d9b11970130425f3d71cbcc161e4c70646e1c72 100644 --- a/src/modules/butterflies/butterflies_overlays.h +++ b/src/modules/butterflies/butterflies_overlays.h @@ -1,10 +1,7 @@ -// -// Created by andreas on 20/03/23. -// - #ifndef CATS_BUTTERFLIES_OVERLAYS_H #define CATS_BUTTERFLIES_OVERLAYS_H #include "configuration/configuration.h" -enum action_status butterflies_update_overlays(struct cats_configuration *conf, struct cats_grid *grid); +enum action_status bf_grid_overlay_update(const struct cats_configuration *conf, struct cats_grid *grid); + #endif //CATS_BUTTERFLIES_OVERLAYS_H diff --git a/src/modules/butterflies/butterflies_populations.c b/src/modules/butterflies/butterflies_populations.c index cf8999044cbc98ad0e2c7f2c26b5c322bbda654b..f960967e86edf224f6fcf74a2e90426985a3aa6a 100644 --- a/src/modules/butterflies/butterflies_populations.c +++ b/src/modules/butterflies/butterflies_populations.c @@ -1,49 +1,73 @@ #include <assert.h> #include <math.h> -#include "butterflies_populations.h" + +#include "paths/paths.h" +#include "paths/output_paths.h" +#include "actions/cats_actions.h" +#include "misc/cats_random.h" #include "data/cats_grid.h" -#include "overlays/overlay_exclusion.h" -#include "inline_overlays.h" #include "threading/threading-helpers.h" #include "modules/module_header.h" + +#include "butterflies_populations.h" #include "butterflies_main.h" -#include "inline_population.h" -#include "misc/cats_random.h" -#include "populations/population.h" #include "butterflies_inline.h" +#include "inline_population.h" - -void butterflies_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cats_dt_coord row, cats_dt_coord col, bool check_exclusion) +void bf_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cats_dt_coord row, cats_dt_coord col, + bool check_exclusion) { + const struct cats_configuration *conf = ts->conf; - if (check_exclusion - && (cell_excluded_by_overlay(conf, row, col) ||cell_excluded_by_generation(grid, row, col))) return; + assert (conf->grid_count == 1); + + if (check_exclusion) { + if (bf_cell_excluded_by_generation(grid, row, col)) return; + } + + - struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; const int module_id = CATS_MODULE_ID; struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; - int32_t local_max_generation = (int32_t) ceilf(data->generations[row][col]); + + if (data->eggs[row][col] == 0) return; if (data->eggs[row][col] < 0) { log_message(LOG_ERROR, "Number of eggs < 0: row %d col %d: %f", row, col, data->eggs[row][col]); exit(EXIT_FAILURE); } - float proportion = 1.0f; - if (data->generation_current == local_max_generation && (float) local_max_generation > proportion) { - proportion = (float) local_max_generation- data->generations[row][col]; + // the number of generations per cell is usually not an integer value + // the non-integer part of the number of generations is used in the generation which is + // one greater than the integer part of the number of generations + // i.e. if the number of generations is 2.4, 40% of all eggs in the cell + // will be considered as if they belonged to generation 3 + // the minimum number of generations is 1 if the cell is climatically viable (and the host species is present) + // if the number of generations is 0, the cell will be ignored + // + // note that the generations are processed backwards + // i.e. if the maximum number of generations is 5, individual cells will have 1 ... 5 generations + // first the all cells which have 5 (> 4) generations are modelled + // then all the cells with have at least 4 (> 3) generations are modelled + // ... + // at last all cells with have at least 1 generations are modelled + + float this_generation_fraction = 1.0f; + int32_t local_max_generation = (int32_t) ceilf(data->generations[row][col]); + if (data->generation_current == local_max_generation) { + this_generation_fraction = (float) local_max_generation - data->generations[row][col]; + assert(this_generation_fraction >= 0); + assert(this_generation_fraction <= 1.0); } - assert(proportion >= 0); - assert(proportion <= 1.0); - if (data->eggs[row][col] == 0) return; // FIXME MOVE UP - assert (conf->grid_count == 1); - float eggs = proportion * data->eggs[row][col]; + + float eggs = this_generation_fraction * data->eggs[row][col]; if (eggs > data->eggs[row][col]) { - log_message(LOG_ERROR, "Removing more eggs than present: %d %d: %f/%f", row, col, data->eggs[row][col], eggs); + log_message(LOG_ERROR, "Removing more eggs than present: %d %d: %f/%f", row, col, data->eggs[row][col], + eggs); exit(EXIT_FAILURE); } @@ -51,15 +75,27 @@ void butterflies_cell_maturation(struct cats_grid *grid, struct cats_thread_info assert(data->eggs[row][col] >= 0); + struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; + cats_dt_rates maturation_rate = calculate_rate(&module_conf->butterfly_egg_to_adult_survival, NAN, &grid->param, + grid, row, col, NULL); - cats_dt_rates maturation_rate = calculate_rate(&module_conf->butterfly_egg_to_adult_survival, NAN, &grid->param, grid, row, col, NULL); - cats_dt_population K = get_carrying_capacity(grid, row, col); - cats_dt_population adults = poisson_population_capped(ts->rng, eggs * proportion * maturation_rate, K); - /* - if (adults >0 ) { - printf("adults %d %d: %d\n", row, col, adults); - }*/ - set_population(grid, row, col, adults); + // not capped, we can have more adults than CC + cats_dt_population adults = poisson(ts->rng, eggs * maturation_rate); + assert(adults >= 0); + set_population_ignore_cc(grid, row, col, adults); } +void bf_area_kill_adults(struct cats_grid *grid, struct cats_thread_info *ts) +{ + const cats_dt_coord start_row = ts->area.start_row; + const cats_dt_coord end_row = ts->area.end_row; + const cats_dt_coord start_col = ts->area.start_col; + const cats_dt_coord end_col = ts->area.end_col; + + for (cats_dt_coord row = start_row; row < end_row; row++) { + for (cats_dt_coord col = start_col; col < end_col; col++) { + set_population_ignore_cc(grid, row, col, 0); + } + } +} \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_populations.h b/src/modules/butterflies/butterflies_populations.h index 5babb7ec7ca98f7ef8d82479158e816c9d62cc61..20c6488a39ad28bf14b9280ae1283d6871591e1b 100644 --- a/src/modules/butterflies/butterflies_populations.h +++ b/src/modules/butterflies/butterflies_populations.h @@ -5,5 +5,6 @@ #ifndef CATS_BUTTERFLIES_POPULATIONS_H #define CATS_BUTTERFLIES_POPULATIONS_H #include "data/cats_grid.h" -void butterflies_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cats_dt_coord row, cats_dt_coord col, bool check_exclusion); +void bf_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cats_dt_coord row, cats_dt_coord col, bool check_exclusion); +void bf_area_kill_adults(struct cats_grid *grid, struct cats_thread_info *ts); #endif //CATS_BUTTERFLIES_POPULATIONS_H diff --git a/src/modules/butterflies/butterflies_stats.c b/src/modules/butterflies/butterflies_stats.c index 9a08c6752600b9cf95c0f123653be56cc000ee3f..6fe9fd29bfcc0359d6cbbc8b67530fef20b99ce2 100644 --- a/src/modules/butterflies/butterflies_stats.c +++ b/src/modules/butterflies/butterflies_stats.c @@ -1,12 +1,18 @@ -// -// Created by gattringera on 16/03/23. -// #include "butterflies_stats.h" #include "logging.h" #include "cats_global.h" +#include "data/cats_grid.h" +#include "modules/module_header.h" +#include "butterflies_main.h" +#include "inline_overlays.h" +#include "inline_population.h" +#include "inline.h" +#include "butterflies_filenames.h" +#include "temporal/phase_names.h" +#include "temporal/years.h" -const char *get_butterfly_stats_name(enum butterfly_stats which) +const char *bf_get_stats_field_name(enum butterfly_stats which) { switch (which) { case BF_STAT_POPULATED_FIT: @@ -19,6 +25,19 @@ const char *get_butterfly_stats_name(enum butterfly_stats which) return "unpopulated_unfit"; case BF_STAT_EXCLUDED: return "excluded"; + case BF_STAT_GENERATION_ACTIVE: + return "generation_active"; + case BF_POPULATED_AT_DISPERSAL: + return "populated_at_dispersal"; + + case BF_RANDOM_WALK_COUNT: + return "random_walk_count"; + + case BF_RANDOM_WALK_STEP_COUNT: + return "random_walk_step_count"; + case BF_OUTPUT_STAT_MAX: + return "<guard value>"; + case BF_STAT_MAX: break; } @@ -26,3 +45,139 @@ const char *get_butterfly_stats_name(enum butterfly_stats which) log_message(LOG_ERROR, "unknown butterfly stats name with id %d", which); exit_cats(EXIT_FAILURE); } + +struct string_array *bf_assemble_stats(struct cats_configuration *conf, struct cats_grid *grid, bool header) +{ + struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; + assert(module_conf->stats_file != NULL); + const int32_t grid_id = grid->id; + int module_id = CATS_MODULE_ID; + struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; + + + struct string_array *x = new_string_array(); + + if (header) { + + string_array_add(x, "phase"); + string_array_add(x, "year"); + string_array_add(x, "run"); + string_array_add(x, "replicate"); + string_array_add(x, "species"); + string_array_add(x, "id"); + string_array_add(x, "generation"); + + for (enum butterfly_stats which = BF_STAT_MIN; which < BF_OUTPUT_STAT_MAX; which++) { + const char *name = bf_get_stats_field_name(which); + string_array_add(x, name); + } + } else { + string_array_add(x, get_phase_shortname(conf->time.phase)); + string_array_add_int64(x, get_phase_year_abs(conf), NULL); + string_array_add(x, conf->run_name); + string_array_add_int64(x, conf->simulation.replicate, NULL); + string_array_add(x, conf->param[grid_id].species_name); + string_array_add_int64(x, grid_id, NULL); + string_array_add_int(x, data->generation_current, NULL); + + for (enum butterfly_stats which = BF_STAT_MIN; which < BF_OUTPUT_STAT_MAX; which++) { + int64_t stat_id = module_conf->stat_ids[which]; + string_array_add_int64(x, grid->stats.custom_stats[stat_id], NULL); + } + + } + + + return x; + +} + + + +void bf_stats_write(struct cats_configuration *conf, struct cats_grid *grid) +{ + struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; + struct string_array *data = NULL; + + if (module_conf->stats_file == NULL) { + char *fn = bf_stats_filename(conf, grid); + module_conf->stats_file = fopen(fn, "w"); + ENSURE_FILE_OPENED(module_conf->stats_file, fn); + free(fn); + data = bf_assemble_stats(conf, grid, true); + + } else { + + data = bf_assemble_stats(conf, grid, false); + } + char *string = string_array_paste(data, ","); + fprintf(module_conf->stats_file, "%s\n", string); + free(string); + + free_string_array(&data); + + exit_cats(EXIT_FAILURE); + + + + +} + +void bf_area_stats_gather(struct cats_grid *grid, struct cats_thread_info *ts) +{ + struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; + struct cats_configuration *conf = ts->conf; + const int64_t id_excluded = module_conf->stat_ids[BF_STAT_EXCLUDED]; + + const int64_t id_pop_fit = module_conf->stat_ids[BF_STAT_POPULATED_FIT]; + const int64_t id_pop_unfit = module_conf->stat_ids[BF_STAT_POPULATED_UNFIT]; + + const int64_t id_unpop_fit = module_conf->stat_ids[BF_STAT_UNPOPULATED_FIT]; + const int64_t id_unpop_unfit = module_conf->stat_ids[BF_STAT_UNPOPULATED_UNFIT]; + const int32_t grid_id = grid->id; + + //const cats_dt_rates zt = grid->param.ZT; + const cats_dt_rates ot = grid->param.OT; + struct statistics *stats = &ts->stats[grid_id]; + + const cats_dt_coord start_row = ts->area.start_row; + const cats_dt_coord end_row = ts->area.end_row; + const cats_dt_coord start_col = ts->area.start_col; + const cats_dt_coord end_col = ts->area.end_col; + + for (cats_dt_coord row = start_row; row < end_row; row++) { + for (cats_dt_coord col = start_col; col < end_col; col++) { + cats_dt_population pop = get_adult_population(grid, row, col); + + if (cell_excluded_by_overlay(conf, row, col)) { + stats->custom_stats[id_excluded] += 1; + if (pop > 0) { + log_message(LOG_ERROR, "%s: population > 0 (%d) in excluded cell %d %d", + __func__, pop, row, col); + exit_cats(EXIT_FAILURE); + } + continue; + } + + cats_dt_environment suit = get_suitability(grid, row, col); + + if (pop > 0) { + if (suit >= ot) { + stats->custom_stats[id_pop_fit] += 1; + + } else { + stats->custom_stats[id_pop_unfit] += 1; + } + } else { + if (suit >= ot) { + stats->custom_stats[id_unpop_fit] += 1; + + } else { + stats->custom_stats[id_unpop_unfit] += 1; + } + + } + } + } + +} \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_stats.h b/src/modules/butterflies/butterflies_stats.h index a3bb6a1fda2499a893044a65ebf8f4848ddeb503..2a198419603c92e8b090e793a83cba3b1e4e0366 100644 --- a/src/modules/butterflies/butterflies_stats.h +++ b/src/modules/butterflies/butterflies_stats.h @@ -1,10 +1,11 @@ -// -// Created by gattringera on 16/03/23. -// #ifndef CATS_BUTTERFLIES_STATS_H #define CATS_BUTTERFLIES_STATS_H +#include <assert.h> +#include "stats/statistics.h" +#include "threading/threading.h" + enum butterfly_stats { BF_STAT_MIN = 0, BF_STAT_POPULATED_FIT = 0, @@ -12,10 +13,25 @@ enum butterfly_stats { BF_STAT_UNPOPULATED_FIT, BF_STAT_UNPOPULATED_UNFIT, BF_STAT_EXCLUDED, + BF_STAT_GENERATION_ACTIVE, + BF_OUTPUT_STAT_MAX, + BF_POPULATED_AT_DISPERSAL, + BF_RANDOM_WALK_COUNT, + BF_RANDOM_WALK_STEP_COUNT, BF_STAT_MAX }; -const char *get_butterfly_stats_name(enum butterfly_stats which); +const char *bf_get_stats_field_name(enum butterfly_stats which); +void bf_area_stats_gather(struct cats_grid *grid, struct cats_thread_info *ts); +void bf_stats_write(struct cats_configuration *conf, struct cats_grid *grid); + +static inline void increase_custom_stat(struct statistics *stats, int64_t stat_id, int64_t by) +{ + assert(stats != NULL); + assert(stat_id >= 0 && stat_id < stats->custom_stat_count); + stats->custom_stats[stat_id] += by; + +} diff --git a/src/modules/butterflies/butterflies_vital_rates.c b/src/modules/butterflies/butterflies_vital_rates.c index 5af6b76793ad3fd39b9e5289d24cb91ab9cbbedc..3f0e67855a1f147e366ada43fe052b730399862c 100644 --- a/src/modules/butterflies/butterflies_vital_rates.c +++ b/src/modules/butterflies/butterflies_vital_rates.c @@ -1,28 +1,26 @@ - - #include "butterflies_vital_rates.h" -void add_vital_rates(struct cats_configuration *conf, struct conf_data_butterflies *data) +void bf_add_vital_rates(struct cats_configuration *conf, struct conf_data_butterflies *data) { // generations register_module_vital_rate(conf, &data->butterfly_generations,"butterflies generations"); set_vital_rate_name(&data->butterfly_generations, "butterflies generations"); - set_vital_rate_suitability_cutoff_hint(&data->butterfly_generations, HYBRID_SUIT_TS_ZT); set_vital_rate_link_hybrid_function(&data->butterfly_generations, conf, LINK_SUITABILITY_SIGMOID); set_vital_density(&data->butterfly_generations, NO_DENSITY_DEP); - // eggs + // adult to eggs register_module_vital_rate(conf, &data->eggs_per_female, "butterflies eggs per female"); set_vital_rate_name(&data->eggs_per_female, "butterflies eggs per female"); set_vital_rate_suitability_cutoff_hint(&data->eggs_per_female, HYBRID_SUIT_TS_ZT); set_vital_rate_link_hybrid_function(&data->eggs_per_female, conf, LINK_SUITABILITY_SIGMOID); + // egg to adult survival register_module_vital_rate(conf, &data->butterfly_egg_to_adult_survival,"butterflies egg to adult survival rate"); set_vital_rate_name(&data->butterfly_egg_to_adult_survival, "butterflies eggs to adult survival rate"); set_vital_rate_suitability_cutoff_hint(&data->butterfly_egg_to_adult_survival, HYBRID_SUIT_TS_ZT); set_vital_rate_link_hybrid_function(&data->butterfly_egg_to_adult_survival, conf, LINK_SUITABILITY_SIGMOID); - set_vital_density(&data->butterfly_egg_to_adult_survival, DENSITY_DEP_NEGATIVE); + set_vital_density(&data->butterfly_egg_to_adult_survival, NO_DENSITY_DEP); } diff --git a/src/modules/butterflies/butterflies_vital_rates.h b/src/modules/butterflies/butterflies_vital_rates.h index 968f550198ecd29d6cce1bb1f24776d1b8b467b7..1a1d097bc9b7e5b57376102937c6a8cc34f3d99c 100644 --- a/src/modules/butterflies/butterflies_vital_rates.h +++ b/src/modules/butterflies/butterflies_vital_rates.h @@ -6,5 +6,5 @@ #include "vital_rates/setup_rates.h" #include "modules/module_header.h" -void add_vital_rates(struct cats_configuration *conf, struct conf_data_butterflies *data) ; +void bf_add_vital_rates(struct cats_configuration *conf, struct conf_data_butterflies *data) ; #endif //CATS_BUTTERFLIES_VITAL_RATES_H diff --git a/src/modules/butterflies/module.h b/src/modules/butterflies/module.h index 02ce2be565ffc98fe6d576ff673ef7857bd8217b..6da8133282863e8ada0fc405c2893b82d98540de 100644 --- a/src/modules/butterflies/module.h +++ b/src/modules/butterflies/module.h @@ -1,6 +1,6 @@ - - #ifndef CATS_MODULE_H #define CATS_MODULE_H + static const char *module_name = "cats-butterflies"; + #endif //CATS_MODULE_H