From f4cae40f8cf2a21a3d356b33ac95d9bdcb6a6f00 Mon Sep 17 00:00:00 2001 From: Andreas Gattringer <andreas.gattringer@univie.ac.at> Date: Thu, 9 Feb 2023 07:56:16 +0100 Subject: [PATCH] butterflies: start of random walk implementation --- src/modules/butterflies/CMakeLists.txt | 2 +- src/modules/butterflies/butterflies_inline.h | 20 +++- .../butterflies/butterflies_populations.c | 12 +- src/modules/butterflies/butterfly_actions.c | 67 +++++++++-- src/modules/butterflies/random_walk.c | 107 +++++++++++++++++- src/modules/butterflies/random_walk.h | 3 + 6 files changed, 184 insertions(+), 27 deletions(-) diff --git a/src/modules/butterflies/CMakeLists.txt b/src/modules/butterflies/CMakeLists.txt index a9f3c1f..7d73382 100644 --- a/src/modules/butterflies/CMakeLists.txt +++ b/src/modules/butterflies/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(cats-butterflies SHARED "" butterfly_actions.c butterfly_actions.h butterfly_vital_rates.c butterfly_vital_rates.h module.h butterflies_dispersal.c butterflies_dispersal.h butterflies_populations.c butterflies_populations.h) +add_library(cats-butterflies SHARED "" butterfly_actions.c butterfly_actions.h butterfly_vital_rates.c butterfly_vital_rates.h module.h butterflies_dispersal.c butterflies_dispersal.h butterflies_populations.c butterflies_populations.h butterflies_inline.h) target_include_directories(cats-butterflies PUBLIC ".") diff --git a/src/modules/butterflies/butterflies_inline.h b/src/modules/butterflies/butterflies_inline.h index e137724..40f9ac7 100644 --- a/src/modules/butterflies/butterflies_inline.h +++ b/src/modules/butterflies/butterflies_inline.h @@ -1,8 +1,20 @@ -// -// Created by andreas on 08/02/23. -// - #ifndef CATS_BUTTERFLIES_INLINE_H #define CATS_BUTTERFLIES_INLINE_H +#include <math.h> +#include <stdbool.h> + +#include "butterflies_main.h" +#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) +{ + const int module_id = CATS_MODULE_ID; + 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; + return false; +} + #endif //CATS_BUTTERFLIES_INLINE_H diff --git a/src/modules/butterflies/butterflies_populations.c b/src/modules/butterflies/butterflies_populations.c index 3ac7549..1797420 100644 --- a/src/modules/butterflies/butterflies_populations.c +++ b/src/modules/butterflies/butterflies_populations.c @@ -1,7 +1,3 @@ -// -// Created by gattringera on 21/11/22. -// - #include <assert.h> #include <math.h> #include "butterflies_populations.h" @@ -11,15 +7,17 @@ #include "threading/threading-helpers.h" #include "modules/module_header.h" #include "butterflies_main.h" -#include "inline_carrying_capacity.h" #include "inline_population.h" -#include "inline.h" #include "misc/cats_random.h" #include "populations/population.h" +#include "butterflies_inline.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) { const struct cats_configuration *conf = ts->conf; - if (check_exclusion && cell_excluded_by_overlay(conf, row, col)) return; + 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; diff --git a/src/modules/butterflies/butterfly_actions.c b/src/modules/butterflies/butterfly_actions.c index e74afb5..d9bacb5 100644 --- a/src/modules/butterflies/butterfly_actions.c +++ b/src/modules/butterflies/butterfly_actions.c @@ -8,12 +8,16 @@ #include "inline_overlays.h" #include "butterflies_populations.h" #include "inline_population.h" +#include "random_walk.h" +#include "butterflies_inline.h" + enum action_status action_butterfly_stats_reset(struct cats_grid *grid, struct cats_configuration *conf) { return ACTION_RUN; } + void grid_butterflies_maturation(struct cats_grid *grid, struct cats_thread_info *ts) { struct cats_configuration *conf = ts->conf; @@ -23,17 +27,48 @@ 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; + + 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) + || cell_excluded_by_generation(grid, row, col)) { continue; } + butterflies_cell_maturation(grid, ts, row, col, false); } } } +void grid_butterflies_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; + 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; + + 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; + + + 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])) { + continue; + } + + butterflies_random_walk() + } + } +} void grid_butterflies_kill_adults(struct cats_grid *grid, struct cats_thread_info *ts) @@ -73,16 +108,19 @@ enum action_status action_butterflies_dispersal(struct cats_grid *grid, struct c return ACTION_RUN; } + enum action_status action_butterflies_output(struct cats_grid *grid, struct cats_configuration *conf) { return ACTION_RUN; } + enum action_status action_butterfly_stats_gather(struct cats_grid *grid, struct cats_configuration *conf) { return ACTION_RUN; } + enum action_status action_butterfly_stats_write(struct cats_grid *grid, struct cats_configuration *conf) { return ACTION_RUN; @@ -118,21 +156,24 @@ 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; - data-> 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) { 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) + +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); @@ -142,14 +183,15 @@ 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_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_butterflies_maturation, "butterfly_action_egg_to_adult", "transition eggs to adults"); @@ -159,14 +201,15 @@ void add_actions(struct cats_configuration *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_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_butterflies_maturation, "transition eggs to adults", generation); - add_butterfly_generation_action(conf, action_butterflies_dispersal, "dispersal", generation); - add_butterfly_generation_action(conf, action_butterflies_kill_adults, "kill adults", generation); + 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_butterflies_maturation, "transition eggs to adults", + generation); + add_butterfly_generation_action(conf, action_butterflies_dispersal, "dispersal", generation); + add_butterfly_generation_action(conf, action_butterflies_kill_adults, "kill adults", generation); } } \ No newline at end of file diff --git a/src/modules/butterflies/random_walk.c b/src/modules/butterflies/random_walk.c index 22b263f..b8bb21a 100644 --- a/src/modules/butterflies/random_walk.c +++ b/src/modules/butterflies/random_walk.c @@ -1,17 +1,118 @@ // // Created by gattringera on 22/06/22. // - +#include <math.h> #include "random_walk.h" +#include "inline_overlays.h" +#include "modules/module_header.h" +#include "populations/carrying_capacity.h" +#include "misc/cats_random.h" +#include "populations/population.h" +#include "butterflies_main.h" +#include "butterflies_inline.h" +#include "inline_population.h" + +const int N_DIRECTIONS = 9; +/* + * directions + * 4 3 2 + * 5 0 1 + * 6 7 8 + */ + +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} +}; + +static inline bool suitable_for_egg_laying(const struct cats_configuration *conf, struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) +{ + + if (cell_excluded_by_overlay(conf, row, col)) return false; + + if (conf->overlays.overlay[OL_RESOURCE].enabled) { + double resources = conf->overlays.resources->data[row][col]; + if (resources <= 0) return false; + + } + + if (conf->overlays.overlay[OL_HABITAT_TYPE_CC].enabled) { + double multiplier = conf->overlays.habitat_cc->data[row][col]; + if (multiplier < 1.0) { return false; } + } -void random_step(struct cats_grid *grid, cats_dt_coord start_row, cats_dt_coord col) + + 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) { + 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; + + double max_distance = 0; + cats_dt_coord max_steps = 10; + 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; + while (! done) { + 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) { + 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; + distance += this_distance; + } else { + accepted = false; + done = true; + } + + 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++; + } + + if (steps >= max_steps) done = true; + steps += 1; + } } -void random_walk(struct cats_configuration *conf, struct cats_grid *grid) +void butterflies_random_walk(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; + + 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; + for (int32_t p = 0; p < dispersing_population; p++) { + single_random_walk(ts, grid, row, col, eggs); + } } diff --git a/src/modules/butterflies/random_walk.h b/src/modules/butterflies/random_walk.h index ab3a7d5..f2cdafb 100644 --- a/src/modules/butterflies/random_walk.h +++ b/src/modules/butterflies/random_walk.h @@ -1,4 +1,7 @@ #ifndef CATS_RANDOM_WALK_H #define CATS_RANDOM_WALK_H #include "cats/configuration/configuration.h" +#include "threading/threading.h" + +void butterflies_random_walk(struct cats_grid *grid, struct cats_thread_info *ts, cats_dt_coord row, cats_dt_coord col, bool check_exclusion); #endif //CATS_RANDOM_WALK_H -- GitLab