diff --git a/src/modules/butterflies/butterflies_dispersal.c b/src/modules/butterflies/butterflies_dispersal.c index a30bbf1f40d012e77d6eb13c38436b0f7e3d9112..8cc7b964cb8eb3a833c6654e5f18d90ed2ffac00 100644 --- a/src/modules/butterflies/butterflies_dispersal.c +++ b/src/modules/butterflies/butterflies_dispersal.c @@ -12,5 +12,6 @@ void add_dispersed_eggs(struct cats_configuration *conf, struct cats_grid *grid, //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; } \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_main.c b/src/modules/butterflies/butterflies_main.c index 5c9bfcff076a584355da10c51ee8e0354f368ad7..62f7e3ac7ac3ec8e06ccea17221806e6779be534 100644 --- a/src/modules/butterflies/butterflies_main.c +++ b/src/modules/butterflies/butterflies_main.c @@ -51,16 +51,25 @@ void load_butterflies_species_params(struct cats_configuration *conf, struct cat load_conf_vital_rate(&data->butterfly_egg_to_adult_survival, conf, ini, section_name, param); //bool _get_int32_config_value(const struct cats_ini *ini, const char *section, const char *key, bool required, int32_t *value); - int32_t rw_max; + cats_dt_rates female_percentage; - load_conf_value(true, ini, section_name, "butterflies random walk steps maximum", &rw_max); + load_conf_value(true, ini, section_name, "butterflies random walk steps maximum", &data->animal_dispersal_max_radius); + + if (data->animal_dispersal_max_radius <= 0) { + log_message(LOG_ERROR, "butterflies random walk steps maximum must be > 0, is %d", data->animal_dispersal_max_radius); + exit_cats(EXIT_FAILURE); + } + load_conf_value(true, ini, section_name, "butterflies female fraction", &female_percentage); data->generations_max = (int32_t) ceill(data->butterfly_generations.max_rate); + param->plant_dispersal_max_radius = data->animal_dispersal_max_radius; if (! data->actions_added) { add_actions(conf); data->actions_added = true; } + + } diff --git a/src/modules/butterflies/butterflies_main.h b/src/modules/butterflies/butterflies_main.h index 2a93c9cb762b625d042e5b5affadca7c3745a176..3971330881e8c25ce9d8bbd2ec94963a43fa73e9 100644 --- a/src/modules/butterflies/butterflies_main.h +++ b/src/modules/butterflies/butterflies_main.h @@ -13,8 +13,12 @@ struct grid_data_butterflies { }; +#define BF_DEBUG_ROW 4319 +#define BF_DEBUG_COL 10502 + struct conf_data_butterflies { + // fixme -> move to grid data; int32_t generations_max; int32_t current_generation; int32_t animal_dispersal_max_radius; ///< maximal flight/dispersal distance diff --git a/src/modules/butterflies/butterflies_populations.c b/src/modules/butterflies/butterflies_populations.c index 17974206200cd0b790c4c97cfa315071baf7757d..c42baf4377db4a6a2982bec537ff612c8627f841 100644 --- a/src/modules/butterflies/butterflies_populations.c +++ b/src/modules/butterflies/butterflies_populations.c @@ -23,22 +23,42 @@ void butterflies_cell_maturation(struct cats_grid *grid, struct cats_thread_info 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->generation_current > local_max_generation ) return; - 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 = data->generations[row][col] - (float) local_max_generation; - } + proportion = (float) local_max_generation- data->generations[row][col]; + } + 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]; + + 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); + exit(EXIT_FAILURE); + } + data->eggs[row][col] -= eggs; + + assert(data->eggs[row][col] >= 0); + + 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); - set_population_ignore_cc(grid, row, col, adults); + /* + if (adults >0 ) { + printf("adults %d %d: %d\n", row, col, adults); + }*/ + set_population(grid, row, col, adults); } diff --git a/src/modules/butterflies/butterfly_actions.c b/src/modules/butterflies/butterfly_actions.c index d9bacb588bed6d46afe2aad73d32c9a10315b1d0..9baac04471f151a9debd5b17bb68887cf44df744 100644 --- a/src/modules/butterflies/butterfly_actions.c +++ b/src/modules/butterflies/butterfly_actions.c @@ -7,9 +7,14 @@ #include "butterflies_main.h" #include "inline_overlays.h" #include "butterflies_populations.h" -#include "inline_population.h" #include "random_walk.h" #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" enum action_status action_butterfly_stats_reset(struct cats_grid *grid, struct cats_configuration *conf) @@ -28,7 +33,7 @@ void grid_butterflies_maturation(struct cats_grid *grid, struct cats_thread_info 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++) { @@ -36,10 +41,11 @@ void grid_butterflies_maturation(struct cats_grid *grid, struct cats_thread_info || cell_excluded_by_generation(grid, row, col)) { continue; } - butterflies_cell_maturation(grid, ts, row, col, false); + } } + } @@ -52,22 +58,25 @@ 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; - + // 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) - || data->generation_current > (int32_t) ceilf(data->generations[row][col])) { + || cell_excluded_by_generation(grid, row, col)) { continue; } - butterflies_random_walk() + butterflies_random_walk(grid, ts, row, col, false); } } + // if (ts->temp) printf("thread %d: %ld random walks (%ld cells) avg %f\n", ts->id, ts->temp, ts->temp1, (float) ts->temp / (float) ts->temp1); } @@ -94,6 +103,46 @@ enum action_status action_butterflies_maturation(struct cats_grid *grid, struct 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) +{ + int32_t id = grid->id; + char *filename = get_butterfly_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); + return ACTION_RUN; +} + enum action_status action_butterflies_kill_adults(struct cats_grid *grid, struct cats_configuration *conf) { @@ -105,6 +154,8 @@ enum action_status action_butterflies_kill_adults(struct cats_grid *grid, struct enum action_status action_butterflies_dispersal(struct cats_grid *grid, struct cats_configuration *conf) { + threaded_action(&grid_butterflies_dispersal, grid, conf, TS_DISPERSAL); + return ACTION_RUN; } @@ -151,6 +202,7 @@ void grid_update_generations(struct cats_grid *grid, struct cats_thread_info *ts } cats_dt_rates gen = calculate_rate(rate, 0, conf->param, grid, row, col, NULL); data->generations[row][col] = (float) gen; + //printf("GENERATIONS::thread %03d:: %d %d %f\n", ts->id ,row, col, (float) gen); } } @@ -159,15 +211,47 @@ void grid_update_generations(struct cats_grid *grid, struct cats_thread_info *ts enum action_status action_butterfly_update_generations(struct cats_grid *grid, struct cats_configuration *conf) { - struct conf_data_butterflies *data = CATS_MODULE_DATA; + int module_id = CATS_MODULE_ID; + struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; + struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; + + data->generation_current = module_conf->generations_max; + log_message(LOG_IMPORTANT, "resetting generation to %d", module_conf->generations_max); + if (grid->param.initial_population.adjusted == false) { + if (grid->param.initial_population.set_to_cc == true) increase_initial_population_to_cc(grid, conf); + if (grid->param.initial_population.suitability_threshold > 0.0) { + prune_initial_population_under_threshold(conf, grid); + } + grid->param.initial_population.adjusted = true; + } + threaded_action(&grid_update_generations, grid, conf, TS_DEFAULT); return ACTION_RUN; } -enum action_status action_update_generation(struct cats_grid *grid, struct cats_configuration *conf) +enum action_status action_finish_generation(struct cats_grid *grid, struct cats_configuration *conf) { - struct conf_data_butterflies *data = CATS_MODULE_DATA; + int module_id = CATS_MODULE_ID; + + struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; + + 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) +{ + 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; } @@ -186,17 +270,27 @@ void add_butterfly_generation_action(struct cats_configuration *conf, action_fun 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_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"); + list_actions_full(conf); @@ -204,12 +298,16 @@ void add_actions(struct cats_configuration *conf) 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_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_update_generation, "update generation", 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_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); } } \ No newline at end of file diff --git a/src/modules/butterflies/random_walk.c b/src/modules/butterflies/random_walk.c index b8bb21a155ae52d6994226e43369fa9b39610408..e4e4c976473a4af8e1fdd7f60e7e1230f6559cd7 100644 --- a/src/modules/butterflies/random_walk.c +++ b/src/modules/butterflies/random_walk.c @@ -39,44 +39,52 @@ static inline bool suitable_for_egg_laying(const struct cats_configuration *conf if (conf->overlays.overlay[OL_HABITAT_TYPE_CC].enabled) { double multiplier = conf->overlays.habitat_cc->data[row][col]; - if (multiplier < 1.0) { return false; } + if (multiplier < 0.0) { return false; } } return true; } -void 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) +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, int32_t rw_num) { const struct cats_configuration *conf = ts->conf; const int module_id = CATS_MODULE_ID; struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; + struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; - double max_distance = 0; - cats_dt_coord max_steps = 10; - double distance = 0; + int32_t eggs_left = eggs; + cats_dt_coord max_steps = module_conf->animal_dispersal_max_radius; + //double max_distance = 0; + //double distance = 0; cats_dt_coord steps = 0; bool done = false; cats_dt_coord row = source_row; cats_dt_coord col = source_col; int32_t deposition_count = 0; + /* + if (row == BF_DEBUG_ROW && col == BF_DEBUG_COL ) { + printf("rw,run,row,col,step,deposit,eggs_left,thread_id\n"); + printf("rw,%d,%d,%d,%d,%d,%d,%d\n", rw_num, row, col, 0, 0, eggs_left,ts->id); + } + */ while (! done) { - bool accepted = false; + //bool accepted = false; unsigned long int direction = gsl_rng_uniform_int(ts->rng, N_DIRECTIONS); cats_dt_coord *offsets = DIRECTION_OFFSETS[direction]; cats_dt_coord row_offset = offsets[0]; cats_dt_coord col_offset = offsets[1]; assert(row_offset >= -1 && row_offset <= 1); assert(col_offset >= -1 && col_offset <= 1); - row += row_offset; col += col_offset; if (row >= grid->dimension.rows || row < 0 || col >= grid->dimension.cols || col < 0) { + //printf("out of bounds %d %d - %d %d\n", row, col, grid->dimension.rows, grid->dimension.cols); return; // we escaped the simulation extent and got lost } steps++; - +/* double this_distance = sqrt((row_offset * row_offset) + (col_offset * col_offset)); if (distance + this_distance <= max_distance) { accepted = true; @@ -85,17 +93,34 @@ void single_random_walk(struct cats_thread_info *ts, struct cats_grid *grid, cat accepted = false; done = true; } + if (!accepted) return; +*/ + int32_t eggs_to_deposit = 0; if (suitable_for_egg_laying(conf, grid, row, col)) { - int32_t eggs_to_deposit= (int32_t) ceilf((float) eggs/(float) deposition_count); - data->eggs[row][col] += (float) eggs_to_deposit; deposition_count++; + eggs_to_deposit = (int32_t) ceilf((float) eggs_left/(2.0f)); + assert(eggs_to_deposit >= 0); + + if (eggs_to_deposit > eggs_left) { + eggs_to_deposit = eggs_left; + } + eggs_left -= eggs_to_deposit; + data->eggs[row][col] += (float) eggs_to_deposit; + + } + /* + if (source_row == BF_DEBUG_ROW && source_col == BF_DEBUG_COL ) { + printf("rw,%d,%d,%d,%d,%d,%d,%d\n", rw_num, row, col, steps, eggs_to_deposit,eggs_left,ts->id); + } + */ - if (steps >= max_steps) done = true; - steps += 1; + if (steps >= max_steps || eggs_left == 0) done = true; } - + //printf("rw,%d,%d,%d,%d,%d,%d,%d\n", rw_num, row, col, steps, 0,eggs_left,ts->id); + fflush(stdout); + assert(eggs_left >= 0); } @@ -105,14 +130,27 @@ void butterflies_random_walk(struct cats_grid *grid, struct cats_thread_info *ts if (check_exclusion && (cell_excluded_by_overlay(conf, row, col) ||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; + // 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 population = get_adult_population(grid, row, col); int32_t dispersing_population = population; - int32_t eggs = 0; + struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; + cats_dt_population N = get_adult_population(grid, row, col); + cats_dt_rates eggs = calculate_rate(&module_conf->eggs_per_female, N, &grid->param, grid, row, col, NULL); + int32_t e = (int32_t) ceill(eggs); + assert(e >= 0); + if (e == 0) return; + if (dispersing_population > 0) ts->temp1++; + if (dispersing_population == 0) return; + for (int32_t p = 0; p < dispersing_population; p++) { - single_random_walk(ts, grid, row, col, eggs); + + single_random_walk(ts, grid, row, col, e, p); + ts->temp++; + + } + //exit_cats(EXIT_SUCCESS); }