diff --git a/src/modules/butterflies/CMakeLists.txt b/src/modules/butterflies/CMakeLists.txt index c20a250845e6cfd490a47a0312602fc2f7ded1c1..fd53b9a94562a0844d24faa61342b9b8a72b70f8 100644 --- a/src/modules/butterflies/CMakeLists.txt +++ b/src/modules/butterflies/CMakeLists.txt @@ -10,7 +10,7 @@ add_library(cats-butterflies SHARED "" butterflies_overlays.c butterflies_overlays.h butterflies_paths.c butterflies_paths.h butterflies_actions_setup.c - butterflies_actions_setup.h butterflies_initial_population.c butterflies_initial_population.h butterflies_scale.c butterflies_scale.h) + butterflies_actions_setup.h butterflies_initial_population.c butterflies_initial_population.h butterflies_scale.c butterflies_scale.h inline_butterflies.h) target_include_directories(cats-butterflies PUBLIC ".") diff --git a/src/modules/butterflies/butterflies_dispersal.c b/src/modules/butterflies/butterflies_dispersal.c index b995e3dab695c13bf7998b6dba32c35602ee734f..6c7807149c158be70dfeb07dfe869ed096999845 100644 --- a/src/modules/butterflies/butterflies_dispersal.c +++ b/src/modules/butterflies/butterflies_dispersal.c @@ -10,6 +10,7 @@ #include "butterflies_dispersal.h" #include "configuration/configuration.h" #include "modules/module_header.h" +#include "inline_butterflies.h" const int N_DIRECTIONS = 9; /* @@ -19,7 +20,7 @@ const int N_DIRECTIONS = 9; * 6 7 8 */ -const cats_dt_coord DIRECTION_OFFSETS[9][2] = { +const cats_dt_coord DIRECTION_OFFSETS[9][2] = { // initialisation, non-spatial {+0, +0}, {+0, +1}, {-1, +1}, @@ -38,7 +39,7 @@ static void inline single_random_walk(struct cats_thread_info *ts, struct cats_g { const int module_id = CATS_MODULE_ID; - const struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; + struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; const struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; const bool debug_rw = module_conf->debug_rw; @@ -74,7 +75,8 @@ static void inline single_random_walk(struct cats_thread_info *ts, struct cats_g // is the cell a valid dispersal target location? - if (!(data->info_layer[row][col] & BF_CELL_VALID_DISPERSAL_TARGET)) { + int32_t cell_info = butterflies_get_info_layer(data, row, col); + if (!(cell_info & BF_CELL_VALID_DISPERSAL_TARGET)) { if (debug_rw) { fprintf(module_conf->debug_rw_file, "%d,%d,%d,%d,%d,%d,%d\n", rw_num, row, col, step + 1, @@ -93,7 +95,8 @@ 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; + butterflies_add_eggs(data, row, col, (float) eggs_to_deposit); + ts->rw_debug_deposits++; if (debug_rw) { fprintf(module_conf->debug_rw_file, "%d,%d,%d,%d,%d,%d,%d\n", rw_num, row, col, step + 1, @@ -176,7 +179,8 @@ butterflies_cell_dispersal(struct cats_grid *grid, struct cats_thread_info *ts, const cats_dt_rates source_cell_eggs = stationary_females * eggs_per_female + wandering_females * (eggs_per_female - eggs_to_disperse_per_female); - data->eggs[row][col] += (float) ceill(source_cell_eggs); + butterflies_add_eggs(data, row, col, (float) ceill(source_cell_eggs)); + if (eggs_to_disperse_per_female == 0) { diff --git a/src/modules/butterflies/butterflies_generations.c b/src/modules/butterflies/butterflies_generations.c index 3e0ab6617f8f0d0d4efe25115d927ac16138080c..89cedd8e6ccbb38cfb6d42f6b7d4b91d2901d163 100644 --- a/src/modules/butterflies/butterflies_generations.c +++ b/src/modules/butterflies/butterflies_generations.c @@ -5,6 +5,8 @@ #include "actions/cats_actions.h" #include "butterflies_generations.h" #include "inline.h" +#include "inline_butterflies.h" + // only run at the start of the year void bf_area_generation_update(struct cats_grid *grid, struct cats_thread_info *ts) @@ -32,37 +34,37 @@ void bf_area_generation_update(struct cats_grid *grid, struct cats_thread_info * for (cats_dt_coord row = start_row; row < end_row; row++) { for (cats_dt_coord col = start_col; col < end_col; col++) { + float eggs = butterflies_get_eggs(data, row, col); if (get_suitability(grid, row, col) < ot) { - if (data->eggs[row][col] > 0) cells_with_eggs_removed += 1; - data->eggs[row][col] = 0.0f; - data->generations[row][col] = 0.0f; + if (eggs > 0) cells_with_eggs_removed += 1; + butterflies_set_eggs(data, row, col, 0.0f); + butterflies_set_generations(data, row, col, 0.0f); set_population_ignore_cc(grid, row, col, 0); continue; } if (cell_excluded_by_overlay(conf, row, col)) { - if (data->eggs[row][col] > 0) cells_with_eggs_removed += 1; - data->eggs[row][col] = 0.0f; - data->generations[row][col] = 0.0f; + if (eggs > 0) cells_with_eggs_removed += 1; + butterflies_set_eggs(data, row, col, 0.0f); + butterflies_set_generations(data, row, col, 0.0f); set_population_ignore_cc(grid, row, col, 0); continue; } - if ( ! (data->info_layer[row][col] & BF_CELL_VALID_DISPERSAL_TARGET)){ - if (data->eggs[row][col] > 0) cells_with_eggs_removed += 1; - data->eggs[row][col] = 0.0f; - data->generations[row][col] = 0.0f; + int32_t cell_info = butterflies_get_info_layer(data, row, col); + if ( ! (cell_info & BF_CELL_VALID_DISPERSAL_TARGET)){ + if (eggs > 0) cells_with_eggs_removed += 1; + butterflies_set_eggs(data, row, col, 0.0f); + butterflies_set_generations(data, row, col, 0.0f); set_population_ignore_cc(grid, row, col, 0); continue; } cats_dt_rates gen = calculate_rate(rate, 0, conf->param, grid, row, col, NULL); - - data->generations[row][col] = (float) gen; - if (data->eggs[row][col] > 0) cells_with_eggs += 1; - + butterflies_set_generations(data, row, col, (float) gen); + if (eggs > 0) cells_with_eggs += 1; } } diff --git a/src/modules/butterflies/butterflies_initial_population.c b/src/modules/butterflies/butterflies_initial_population.c index f4fc811d292b12b08cf0ad73a594ee11e36c3319..37825c033558962610dd612ad24f34416a5be349 100644 --- a/src/modules/butterflies/butterflies_initial_population.c +++ b/src/modules/butterflies/butterflies_initial_population.c @@ -14,6 +14,7 @@ #include "modules/module_header.h" #include "actions/cats_actions.h" #include "butterflies_initial_population.h" +#include "inline_butterflies.h" void bf_initial_population_adjustment(struct cats_configuration *conf, struct cats_grid *grid) @@ -48,7 +49,7 @@ void bf_initial_population_adjustment(struct cats_configuration *conf, struct ca start += 1; cats_dt_rates multiplier = 1.0; if (conf->overlays.overlay[OL_HABITAT_TYPE_CC].enabled) { - multiplier *= conf->overlays.habitat_cc->data[row][col]; + multiplier *= get_overlay_habitat_cc_value(conf, row, col);]; } cats_dt_rates suit = get_suitability(grid, row, col); cats_dt_rates cc_raw = cc_rate->func->func(cc_rate, &grid->param, suit, 0, NAN); @@ -95,12 +96,14 @@ void bf_initial_population_adjustment(struct cats_configuration *conf, struct ca for (cats_dt_coord row = 0; row < rows; row++) { for (cats_dt_coord col = 0; col < cols; col++) { + #ifdef BF_DEBUG - if (get_adult_population(grid, row, col) || data->eggs[row][col]) { + float eggs = butterflies_get_eggs(data, row, col); + if (get_adult_population(grid, row, col) || eggs) { printf("" "BFDBG::%s::initial adults -> eggs::%d,%d,%d,%f\n", __func__, row, col, get_adult_population(grid, row, col), - data->eggs[row][col]); + eggs); } #endif set_population_ignore_cc(grid, row, col, 0); diff --git a/src/modules/butterflies/butterflies_inline.h b/src/modules/butterflies/butterflies_inline.h index 2551ab7c3d6894228886493398ed61fdeb0c9482..31d2b6ee8ea847f34597bc1a5a31332cd5dc3bd9 100644 --- a/src/modules/butterflies/butterflies_inline.h +++ b/src/modules/butterflies/butterflies_inline.h @@ -6,13 +6,15 @@ #include "butterflies_main.h" #include "modules/module_header.h" +#include "inline_butterflies.h" 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 == 0.0 || data->generation_current > (int32_t) ceilf(data->generations[row][col])) return true; + float generations = butterflies_get_generations(data, row, col); + if (data->generation_current == 0.0 || data->generation_current > (int32_t) ceilf(generations)) return true; return false; } diff --git a/src/modules/butterflies/butterflies_overlays.c b/src/modules/butterflies/butterflies_overlays.c index 704b4fb5a10c1c0b60c34bd24a5e5335ad2f190b..c040b0586caa965164e6b0b41323276c7b2d7f25 100644 --- a/src/modules/butterflies/butterflies_overlays.c +++ b/src/modules/butterflies/butterflies_overlays.c @@ -7,6 +7,38 @@ #include "butterflies_main.h" #include "inline_overlays.h" #include "inline_population.h" +#include "inline_butterflies.h" + + +bool butterflies_habitat_ok(const struct cats_configuration *conf, cats_dt_coord row, cats_dt_coord col) +{ + // we have no habitat layer -> all cells have suitable habitat + if (conf->overlays.overlay[OL_HABITAT_TYPE_CC].enabled == false) { + return true; + } + // habitat layer exists and the carrying capacity is > 0 -> this cell's habitat is suitable + if (get_overlay_habitat_cc_value(conf, row, col) > 0) { + return true; + } + + return false; +} + + +bool butterflies_resources_ok(const struct cats_configuration *conf, cats_dt_coord row, cats_dt_coord col) +{ + // we have no resource layer -> all cells have the resource available + if (conf->overlays.overlay[OL_RESOURCE].enabled == false) { + return true; + } + + // resource layer exists and the resource is > 0 -> this cell's resource is available + if (get_overlay_resource_value(conf, row, col) > 0) { + return true; + } + + return false; +} enum action_status bf_grid_overlay_update(const struct cats_configuration *conf, struct cats_grid *grid) @@ -30,49 +62,43 @@ enum action_status bf_grid_overlay_update(const struct cats_configuration *conf, for (cats_dt_coord row = 0; row < rows; row++) { for (cats_dt_coord col = 0; col < cols; col++) { + int32_t cell_info = BF_CELL_CLEAR; - data->info_layer[row][col] = BF_CELL_CLEAR; - + float eggs = butterflies_get_eggs(data, row, col); if (cell_excluded_by_overlay(conf, row, col)) { - data->info_layer[row][col] |= BF_CELL_EXCLUDED; - if (data->eggs[row][col]) cells_eggs_removed += 1; + cell_info |= BF_CELL_EXCLUDED; + butterflies_set_info_layer(data, row, col, cell_info); + if (eggs) cells_eggs_removed += 1; if (get_adult_population(grid, row, col)) cells_adults_removed += 1; - data->eggs[row][col] = 0; + butterflies_set_eggs(data, row, col, 0.0f); set_population_ignore_cc(grid, row, col, 0); cells_excluded += 1; continue; } - - 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; - cells_habitat_ok += 1; - } else if (!conf->overlays.overlay[OL_HABITAT_TYPE_CC].enabled) { - data->info_layer[row][col] |= BF_CELL_HABITAT_OK; + if (butterflies_habitat_ok(conf, row, col)) { + cell_info |= BF_CELL_HABITAT_OK; cells_habitat_ok += 1; } - if (conf->overlays.overlay[OL_RESOURCE].enabled && - conf->overlays.resources->data[row][col] > 0) { - data->info_layer[row][col] |= BF_CELL_RESOURCE_AVAILABLE; - cells_resource_ok += 1; - } else if (!conf->overlays.overlay[OL_RESOURCE].enabled) { - data->info_layer[row][col] |= BF_CELL_RESOURCE_AVAILABLE; + if (butterflies_resources_ok(conf, row, col)) { + cell_info |= BF_CELL_RESOURCE_AVAILABLE; cells_resource_ok += 1; } - if ((data->info_layer[row][col] & BF_CELL_HABITAT_OK) && - (data->info_layer[row][col] & BF_CELL_RESOURCE_AVAILABLE)) { - data->info_layer[row][col] |= BF_CELL_VALID_DISPERSAL_TARGET; + + if ((cell_info & BF_CELL_HABITAT_OK) && (cell_info & BF_CELL_RESOURCE_AVAILABLE)) { + cell_info |= BF_CELL_VALID_DISPERSAL_TARGET; cells_habitat_and_resource_ok += 1; } else { - if (data->eggs[row][col]) cells_eggs_removed += 1; + if (eggs) cells_eggs_removed += 1; if (get_adult_population(grid, row, col)) cells_adults_removed += 1; - data->eggs[row][col] = 0; + butterflies_set_eggs(data, row, col, 0.0f); set_population_ignore_cc(grid, row, col, 0); } + + butterflies_set_info_layer(data, row, col, cell_info); } } @@ -80,7 +106,7 @@ enum action_status bf_grid_overlay_update(const struct cats_configuration *conf, double total_eggs = 0; for (cats_dt_coord row = 0; row < rows; row++) { for (cats_dt_coord col = 0; col < cols; col++) { - float eggs = data->eggs[row][col]; + float eggs = butterflies_get_eggs(data, row, col); if (eggs > 0) { cells_with_eggs += 1; total_eggs += eggs; diff --git a/src/modules/butterflies/butterflies_populations.c b/src/modules/butterflies/butterflies_populations.c index 07c3c6a1b099f7a7cba247ea7dad1c168e9790f8..dbbe83b1befbd2f8676f62c88d320198f8eff493 100644 --- a/src/modules/butterflies/butterflies_populations.c +++ b/src/modules/butterflies/butterflies_populations.c @@ -14,6 +14,8 @@ #include "butterflies_inline.h" #include "inline.h" #include "populations/population.h" +#include "inline_butterflies.h" + int64_t count_populated_cells(const struct cats_grid *grid) { @@ -43,8 +45,9 @@ int64_t butterflies_prune_invalid_cells(struct cats_grid *grid) for (cats_dt_coord row = 0; row < rows; row++) { for (cats_dt_coord col = 0; col < cols; col++) { + int32_t cell_info = butterflies_get_info_layer(data, row, col); + if (!(cell_info & BF_CELL_VALID_DISPERSAL_TARGET)) { - if (!(data->info_layer[row][col] & BF_CELL_VALID_DISPERSAL_TARGET)) { if(get_adult_population(grid, row, col)) { invalid_habitat += 1; } @@ -71,7 +74,7 @@ float get_fractional_generation(struct cats_grid *grid, cats_dt_coord row, cats_ float this_generation_fraction = 1.0f; - float local_generation = data->generations[row][col]; + float local_generation = butterflies_get_generations(data,row,col); int32_t global_max_generation = module_conf->generations_max; int32_t local_max_generation = (int32_t) ceilf(local_generation); int32_t global_current_generation = data->generation_current; @@ -106,10 +109,10 @@ void bf_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cat const int module_id = CATS_MODULE_ID; struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; - - 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]); + const float all_eggs = butterflies_get_eggs(data, row, col); + if (all_eggs == 0) return; + if (all_eggs < 0) { + log_message(LOG_ERROR, "Number of eggs < 0: row %d col %d: %f", row, col, all_eggs); exit(EXIT_FAILURE); } @@ -135,21 +138,20 @@ void bf_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cat //cats_dt_population max_cc = (cats_dt_population) grid->param.carrying_capacity.max_rate; - const float eggs = this_generation_fraction * data->eggs[row][col]; + const float eggs = this_generation_fraction * all_eggs; #ifdef BF_DEBUG printf("BFDBG::%s::row %d, col %d: local gen %f gen fraction %f, eggs %f, this gen eggs %f\n", - __func__, row, col, local_generation, this_generation_fraction, data->eggs[row][col], eggs); + __func__, row, col, local_generation, this_generation_fraction, all_eggs, eggs); #endif if (eggs == 0) return; - 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], + if (eggs > all_eggs) { + log_message(LOG_ERROR, "Removing more eggs than present: %d %d: %f/%f", row, col, all_eggs, eggs); exit_cats(EXIT_FAILURE); } + butterflies_remove_eggs(data, row, col, eggs); - data->eggs[row][col] -= eggs; - assert(data->eggs[row][col] >= 0); // not capped, we can have more adults than CC @@ -165,7 +167,7 @@ void bf_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cat //printf("row %d col %d: suitability: %f, eggs: %f, reproduction rate %Lf\n", row, col, suit, eggs, reproduction_rate); if (reproduction_rate == 0) { - data->eggs[row][col] = 0; + butterflies_set_eggs(data, row, col, 0.0f); set_population_ignore_cc(grid, row, col, 0); return; } diff --git a/src/modules/butterflies/inline_butterflies.h b/src/modules/butterflies/inline_butterflies.h new file mode 100644 index 0000000000000000000000000000000000000000..c56f01b55d15f8f577dc468be28ee58fe317feda --- /dev/null +++ b/src/modules/butterflies/inline_butterflies.h @@ -0,0 +1,52 @@ +#ifndef CATS_INLINE_BUTTERFLIES_H +#define CATS_INLINE_BUTTERFLIES_H + +#include "butterflies_main.h" + +static inline float butterflies_get_eggs(const struct grid_data_butterflies *data, cats_dt_coord row, cats_dt_coord col) +{ assert(data->eggs[row][col] >= 0); // setter [butterflies_get_eggs] + return data->eggs[row][col]; // setter [butterflies_get_eggs] +} + +static inline void butterflies_set_eggs(struct grid_data_butterflies *data, cats_dt_coord row, cats_dt_coord col, float eggs) +{ + assert(eggs >= 0); + data->eggs[row][col] = eggs; // setter [butterflies_set_eggs] +} + +static inline void butterflies_add_eggs(struct grid_data_butterflies *data, cats_dt_coord row, cats_dt_coord col, float by) +{ + assert(by >= 0); + data->eggs[row][col] += by; // setter [butterflies_add_eggs] +} + +static inline void butterflies_remove_eggs(struct grid_data_butterflies *data, cats_dt_coord row, cats_dt_coord col, float by) +{ + assert(by >= 0); + data->eggs[row][col] -= by; // setter [butterflies_remove_eggs] + assert(data->eggs[row][col] >= 0); // setter [butterflies_remove_eggs] +} + +static inline void butterflies_set_generations(struct grid_data_butterflies *data, cats_dt_coord row, cats_dt_coord col, float generations) +{ + assert(generations >= 0); // setter [butterflies_set_generations] + data->generations[row][col] = generations; // setter [butterflies_set_generations] +} + +static inline float butterflies_get_generations(const struct grid_data_butterflies *data, cats_dt_coord row, cats_dt_coord col) +{ + return data->generations[row][col]; // getter [butterflies_get_generations] +} + +static inline void butterflies_set_info_layer(struct grid_data_butterflies *data, cats_dt_coord row, cats_dt_coord col, int32_t value) +{ + data->info_layer[row][col] = value; // setter [butterflies_set_info_layer] +} + +static inline int32_t butterflies_get_info_layer(const struct grid_data_butterflies *data, cats_dt_coord row, cats_dt_coord col) +{ + return data->info_layer[row][col]; // getter [butterflies_get_info_layer] +} + + +#endif //CATS_INLINE_BUTTERFLIES_H