diff --git a/src/modules/butterflies/CMakeLists.txt b/src/modules/butterflies/CMakeLists.txt index 5eb11b6d5a4452081c285adf236b7c305d7e2a6d..c20a250845e6cfd490a47a0312602fc2f7ded1c1 100644 --- a/src/modules/butterflies/CMakeLists.txt +++ b/src/modules/butterflies/CMakeLists.txt @@ -1,16 +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 - butterflies_filenames.c butterflies_filenames.h - butterflies_action_helpers.c - butterflies_action_helpers.h) + 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_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) target_include_directories(cats-butterflies PUBLIC ".") diff --git a/src/modules/butterflies/butterflies_actions.c b/src/modules/butterflies/butterflies_actions.c index 40e05cd02cd67414a88a82efe53ba2073264faa1..027e1de46b0191a9639ad8827a3dec4566c01d6a 100644 --- a/src/modules/butterflies/butterflies_actions.c +++ b/src/modules/butterflies/butterflies_actions.c @@ -13,44 +13,55 @@ #include "butterflies_generations.h" #include "butterflies_dispersal.h" #include "butterflies_overlays.h" -#include "butterflies_filenames.h" +#include "butterflies_paths.h" #include "inline.h" #include "lambda/leslie_matrix.h" #include "temporal/years.h" +#include "butterflies_initial_population.h" enum action_status bf_action_stats_reset(struct cats_grid *grid, struct cats_configuration *conf) { - // FIXME MOVE - if (conf->time.year_current == conf->time.year_start) { + struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; + int module_id = CATS_MODULE_ID; + + struct grid_data_butterflies *module_data = grid->grid_modules[module_id].module_data; + if (conf->time.year_current == conf->time.year_start && + module_conf->generations_max == module_data->generation_current) { log_message(LOG_INFO, "SUMMARY: Scale factor: %Lf", grid->param.scale_factor); struct lambda_parameters l_param = {0}; l_param.calculate_scale = true; l_param.suitability = grid->param.OT; l_param.N = 0; l_param.K = (cats_dt_population) - (get_vital_rate_maximum(&conf->param[grid->id].carrying_capacity) * conf->param->max_adult_cc_fraction); + (get_vital_rate_maximum(&conf->param[grid->id].carrying_capacity) * + conf->param->max_adult_cc_fraction); l_param.grid = 0; l_param.row = 0; l_param.col = 0; l_param.param = &conf->param[grid->id]; l_param.species_id = grid->id; bool print_rate = false; - struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; cats_dt_rates female_fraction = module_conf->female_fraction; cats_dt_rates stationary = module_conf->probability_to_stay; cats_dt_rates mobile = 1.0 - stationary; cats_dt_rates egg_fraction_source = module_conf->egg_fraction_source; - cats_dt_rates eggs_per_female = calculate_rate_for_matrix(&module_conf->eggs_per_female, &l_param, print_rate); - cats_dt_rates reproduction_rate = calculate_rate_for_matrix(&module_conf->reproduction_rate, &l_param, print_rate); - cats_dt_rates K = calculate_rate_for_matrix(&conf->param[grid->id].carrying_capacity, &l_param, print_rate) * conf->param->max_adult_cc_fraction; - cats_dt_rates local_eggs = (stationary + mobile * egg_fraction_source ) * eggs_per_female; + cats_dt_rates eggs_per_female = calculate_rate_for_matrix(&module_conf->eggs_per_female, &l_param, + print_rate); + cats_dt_rates reproduction_rate = calculate_rate_for_matrix(&module_conf->reproduction_rate, &l_param, + print_rate); + cats_dt_rates K = + calculate_rate_for_matrix(&conf->param[grid->id].carrying_capacity, &l_param, print_rate) * + conf->param->max_adult_cc_fraction; + cats_dt_rates local_eggs = (stationary + mobile * egg_fraction_source) * eggs_per_female; // female -> female // to achieve the target reproduction rate, the number of eggs per female laid in the cell // that survive and become adult has to be the reproduction rate divided by the female fraction divided by the number of eggs - cats_dt_rates eggs_to_adults_rate = bf_egg_to_adult_survival_rate(reproduction_rate, local_eggs, female_fraction); - cats_dt_rates result = local_eggs * eggs_to_adults_rate * female_fraction; - cats_dt_rates generations = calculate_rate_for_matrix(&module_conf->butterfly_generations, &l_param, print_rate); + cats_dt_rates eggs_to_adults_rate = + bf_egg_to_adult_survival_rate(reproduction_rate, local_eggs) / module_conf->female_fraction; + cats_dt_rates result = local_eggs * eggs_to_adults_rate * female_fraction; + cats_dt_rates generations = calculate_rate_for_matrix(&module_conf->butterfly_generations, &l_param, + print_rate); log_message(LOG_INFO, "SUMMARY: reproduction rate at OT: %Lf", reproduction_rate); @@ -58,7 +69,8 @@ enum action_status bf_action_stats_reset(struct cats_grid *grid, struct cats_con log_message(LOG_INFO, "SUMMARY: local eggs at OT: %Lf", local_eggs); log_message(LOG_INFO, "SUMMARY: stationary females at OT: %Lf", stationary); log_message(LOG_INFO, "SUMMARY: eggs to adult rate at OT: %Lf", eggs_to_adults_rate); - log_message(LOG_INFO, "SUMMARY: egg fraction source (non-stationary females) at OT: %Lf", egg_fraction_source); + log_message(LOG_INFO, "SUMMARY: egg fraction source (non-stationary females) at OT: %Lf", + egg_fraction_source); log_message(LOG_INFO, "SUMMARY: carrying capacity at OT: %Lf", K); log_message(LOG_INFO, "SUMMARY: generations at OT: %Lf", generations); log_message(LOG_INFO, "SUMMARY: effective female to female rate at OT: %Lf\n", result); @@ -66,10 +78,12 @@ enum action_status bf_action_stats_reset(struct cats_grid *grid, struct cats_con l_param.suitability = 1.0; eggs_per_female = calculate_rate_for_matrix(&module_conf->eggs_per_female, &l_param, print_rate); reproduction_rate = calculate_rate_for_matrix(&module_conf->reproduction_rate, &l_param, print_rate); - K = calculate_rate_for_matrix(&conf->param[grid->id].carrying_capacity, &l_param, print_rate) * conf->param->max_adult_cc_fraction; - local_eggs = (stationary + mobile * egg_fraction_source ) * eggs_per_female; - eggs_to_adults_rate = bf_egg_to_adult_survival_rate(reproduction_rate, local_eggs, female_fraction); - result = local_eggs * eggs_to_adults_rate * female_fraction; + K = calculate_rate_for_matrix(&conf->param[grid->id].carrying_capacity, &l_param, print_rate) * + conf->param->max_adult_cc_fraction; + local_eggs = (stationary + mobile * egg_fraction_source) * eggs_per_female; + eggs_to_adults_rate = + bf_egg_to_adult_survival_rate(reproduction_rate, local_eggs) / module_conf->female_fraction; + result = local_eggs * eggs_to_adults_rate; generations = calculate_rate_for_matrix(&module_conf->butterfly_generations, &l_param, print_rate); log_message(LOG_INFO, "SUMMARY: reproduction rate at suitability 1: %Lf", reproduction_rate); @@ -77,12 +91,12 @@ enum action_status bf_action_stats_reset(struct cats_grid *grid, struct cats_con log_message(LOG_INFO, "SUMMARY: local eggs at suitability 1: %Lf", local_eggs); log_message(LOG_INFO, "SUMMARY: stationary females at suitability 1: %Lf", stationary); log_message(LOG_INFO, "SUMMARY: eggs to adult rate at suitability 1: %Lf", eggs_to_adults_rate); - log_message(LOG_INFO, "SUMMARY: egg fraction source (non-stationary females) at suitability 1: %Lf", egg_fraction_source); + log_message(LOG_INFO, "SUMMARY: egg fraction source (non-stationary females) at suitability 1: %Lf", + egg_fraction_source); log_message(LOG_INFO, "SUMMARY: carrying capacity at suitability 1: %Lf", K); log_message(LOG_INFO, "SUMMARY: generations at suitability 1: %Lf", generations); log_message(LOG_INFO, "SUMMARY: effective female to female rate at suitability 1: %Lf\n", result); - } return action_grid_stats_reset(grid, conf); @@ -99,11 +113,24 @@ void grid_butterflies_maturation(struct cats_grid *grid, struct cats_thread_info const cats_dt_coord end_col = ts->area.end_col; ts->rw_debug_cells_with_adults = 0; + for (cats_dt_coord row = start_row; row < end_row; row++) { for (cats_dt_coord col = start_col; col < end_col; col++) { - +#ifdef BF_DEBUG + if (get_adult_population(grid, row, col)) { + printf("BFDBG::%s::adults at maturation::%d,%d,%d\n", + __func__, row, col, get_adult_population(grid, row, col)); + } +#endif if (cell_excluded_by_overlay(conf, row, col) || bf_cell_excluded_by_generation(grid, row, col)) { +#ifdef BF_DEBUG + if (get_adult_population(grid, row, col)) { + printf("BFDBG::%s::adults at maturation::%d,%d,%d - excluded by generation\n", + __func__, row, col, get_adult_population(grid, row, col)); + } +#endif + continue; } bf_cell_maturation(grid, ts, row, col, false); @@ -113,6 +140,30 @@ void grid_butterflies_maturation(struct cats_grid *grid, struct cats_thread_info } +void bf_initial_population_to_eggs(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; + + + 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)) { + continue; + } + set_population(grid, row, col, get_adult_population(grid, row, col)); + butterflies_cell_dispersal(grid, ts, row, col, false, true); + } + } + +} + + void butterflies_area_dispersal(struct cats_grid *grid, struct cats_thread_info *ts) { struct cats_configuration *conf = ts->conf; @@ -135,15 +186,14 @@ void butterflies_area_dispersal(struct cats_grid *grid, struct cats_thread_info continue; } - butterflies_cell_dispersal(grid, ts, row, col, false); + butterflies_cell_dispersal(grid, ts, row, col, false, false); } } - if (ts->rw_debug_cells_with_adults) { - printf("thread %d: %ld cells with adults, %ld random walks, %ld deposits\n", - ts->id, ts->rw_debug_cells_with_adults, ts->rw_debug_random_walks, ts->rw_debug_deposits); + if (ts->rw_debug_cells_with_adults) { + log_message(LOG_INFO, "thread %d: %ld cells with adults, %ld random walks, %ld deposits\n", + ts->id, ts->rw_debug_cells_with_adults, ts->rw_debug_random_walks, ts->rw_debug_deposits); } - } @@ -166,6 +216,7 @@ enum action_status bf_action_save_grid(struct cats_grid *grid, struct cats_confi return ACTION_RUN; } + enum action_status bf_action_save_overlay(struct cats_grid *grid, struct cats_configuration *conf) { if (!is_output_year(&conf->time)) return ACTION_NOT_RUN; @@ -183,7 +234,6 @@ enum action_status bf_action_save_overlay(struct cats_grid *grid, struct cats_co } - enum action_status bf_action_save_eggs_grid(struct cats_grid *grid, struct cats_configuration *conf) { if (!is_output_year(&conf->time)) return ACTION_NOT_RUN; @@ -198,7 +248,6 @@ enum action_status bf_action_save_eggs_grid(struct cats_grid *grid, struct cats_ } - enum action_status bf_action_dispersal(struct cats_grid *grid, struct cats_configuration *conf) { threaded_action(&butterflies_area_dispersal, grid, conf, TS_DISPERSAL); @@ -206,7 +255,7 @@ enum action_status bf_action_dispersal(struct cats_grid *grid, struct cats_confi 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]); + log_message(LOG_INFO, "STAT %s: %ld", bf_get_stats_field_name(which), grid->stats.stats[stat_id]); } @@ -229,106 +278,6 @@ enum action_status bf_action_stats_write(__attribute__((unused)) struct cats_gri return ACTION_RUN; } -int64_t count_populated_cells(const struct cats_grid *grid) -{ - int64_t cells = 0; - cats_dt_coord rows = grid->dimension.rows; - 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 (get_adult_population(grid, row, col)) { - cells += 1; - } - - } - } - return cells; -} - -int64_t butterflies_prune_invalid_cells(struct cats_grid *grid) -{ - int64_t invalid_habitat = 0; - int module_id = CATS_MODULE_ID; - struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; - cats_dt_coord rows = grid->dimension.rows; - 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 (!(data->info_layer[row][col] & BF_CELL_VALID_DISPERSAL_TARGET)) { - set_population_ignore_cc(grid, row, col, 0); - invalid_habitat += 1; - } - } - } - return invalid_habitat; -} - -void initial_population_adjustment(struct cats_configuration *conf, struct cats_grid *grid) -{ - int64_t init_populated_cells = count_populated_cells(grid); - int64_t invalid_resources = butterflies_prune_invalid_cells(grid); - log_message(LOG_IMPORTANT, "Loaded initial populations: %ld cells occupied before adjustment", init_populated_cells); - if (grid->param.initial_population.set_to_cc == true) { - -//#define DEBUG_INITIAL_POPULATIONS 1 -#ifdef DEBUG_INITIAL_POPULATIONS - const int32_t max_i = 10; - struct cats_vital_rate *cc_rate = &grid->param.carrying_capacity; - cats_dt_rates OT = grid->param.OT; - for (int32_t i = 0; i < max_i; i++) { - - cats_dt_rates suit = OT + i * (1.0 - OT)/max_i; - cats_dt_rates cc = cc_rate->func->func(cc_rate, &grid->param, suit, 0, NAN); - log_message(LOG_INFO, "Carrying capacity for suitability %Lf: %Lf", suit, cc); - - } - const cats_dt_coord rows = grid->dimension.rows; - const cats_dt_coord cols = grid->dimension.cols; - int64_t start = 0; - int64_t multi_excluded = 0; - - for (cats_dt_coord row = 0; row < rows; row++) { - for (cats_dt_coord col = 0; col < cols; col++) { - - if (get_adult_population(grid, row, col) == 0) continue; - 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]; - } - 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); - if (multiplier == 0) { - multi_excluded += 1; - } - cats_dt_population cc = get_carrying_capacity(grid, row, col); - - printf("DEBUG::row %d col %d, suit %Lf, cc multi %Lf, cc raw %Lf, cc %d\n", row, col, suit, multiplier, cc_raw, cc); - } - } - - - -#endif - - increase_initial_population_to_cc(grid, conf); - int64_t populated_cells_after_cc = count_populated_cells(grid); - log_message(LOG_IMPORTANT, "\t%ld cells occupied after setting population sizes to carrying capacity", populated_cells_after_cc); - } - - - - if (grid->param.initial_population.suitability_threshold > 0.0) { - prune_initial_population_under_threshold(conf, grid); - } - - int64_t after_populated_cells = count_populated_cells(grid); - - log_message(LOG_IMPORTANT, "Pruned initial populations from %ld cells to %ld, (%ld wrong habitat)", - init_populated_cells, after_populated_cells, invalid_resources); - grid->param.initial_population.adjusted = true; -} // only run at the start of the year enum action_status bf_action_generation_update(struct cats_grid *grid, struct cats_configuration *conf) @@ -345,7 +294,7 @@ enum action_status bf_action_generation_update(struct cats_grid *grid, struct ca log_message(LOG_IMPORTANT, "resetting generation to %d", module_conf->generations_max); if (grid->param.initial_population.adjusted == false) { - initial_population_adjustment(conf, grid); + bf_initial_population_adjustment(conf, grid); grid->param.initial_population.adjusted = true; } @@ -353,7 +302,8 @@ enum action_status bf_action_generation_update(struct cats_grid *grid, struct ca int64_t cells_with_eggs = grid->stats.custom_stats[egg_cells_id]; int64_t cells_with_eggs_removed = grid->stats.custom_stats[egg_cells_removed_id]; - log_message(LOG_INFO, "%ld cells with eggs left, %ld cells with eggs removed", cells_with_eggs, cells_with_eggs_removed); + log_message(LOG_INFO, "%ld cells with eggs left, %ld cells with eggs removed", cells_with_eggs, + cells_with_eggs_removed); grid->stats.custom_stats[egg_cells_id] = 0; grid->stats.custom_stats[egg_cells_removed_id] = 0; return ACTION_RUN; @@ -381,13 +331,27 @@ enum action_status bf_action_generation_finish(struct cats_grid *grid, struct ca return ACTION_RUN; } + enum action_status bf_action_generation_start(struct cats_grid *grid, __attribute__((unused)) struct cats_configuration *conf) { +#ifdef BF_DEBUG + cats_dt_population rows = grid->dimension.rows; + cats_dt_population cols = grid->dimension.cols; + for (cats_dt_coord row = 0; row < rows; row++) { + for (cats_dt_coord col = 0; col < cols; col++) { + if (get_adult_population(grid, row, col)) { + printf("BFDBG::%s::adults at start of generation::%d,%d,%d\n", + __func__, row, col, get_adult_population(grid, row, col)); + + } + } + } +#endif 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); + log_message(LOG_INFO, "Starting generation %d", data->generation_current); assert(data->generation_current >= 0); return ACTION_RUN; } diff --git a/src/modules/butterflies/butterflies_action_helpers.c b/src/modules/butterflies/butterflies_actions_setup.c similarity index 95% rename from src/modules/butterflies/butterflies_action_helpers.c rename to src/modules/butterflies/butterflies_actions_setup.c index e551e1a9e99f601f3a8b7605b5ae4c8a0086f159..9258f0ffaa45de1ff829a6faeab1329470d4db84 100644 --- a/src/modules/butterflies/butterflies_action_helpers.c +++ b/src/modules/butterflies/butterflies_actions_setup.c @@ -1,5 +1,5 @@ -#include "butterflies_action_helpers.h" +#include "butterflies_actions_setup.h" #include "configuration/configuration.h" #include "actions/setup_actions.h" #include "module.h" @@ -51,10 +51,8 @@ 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); + log_message(LOG_INFO, "Adding actions of %d generations", data->generations_max); - 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); @@ -70,7 +68,7 @@ void bf_add_actions(struct cats_configuration *conf) 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_save_grid, "output", generation); + bf_add_generation_action(conf, bf_action_save_grid, "output 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_eggs_grid, "output eggs", generation); diff --git a/src/modules/butterflies/butterflies_action_helpers.h b/src/modules/butterflies/butterflies_actions_setup.h similarity index 55% rename from src/modules/butterflies/butterflies_action_helpers.h rename to src/modules/butterflies/butterflies_actions_setup.h index bd75bfabe5480e05580a0b123f0da838260afae1..224068527270fadfbef4b2e9a312283468c5a7ab 100644 --- a/src/modules/butterflies/butterflies_action_helpers.h +++ b/src/modules/butterflies/butterflies_actions_setup.h @@ -1,9 +1,9 @@ -#ifndef CATS_BUTTERFLIES_ACTION_HELPERS_H -#define CATS_BUTTERFLIES_ACTION_HELPERS_H +#ifndef CATS_BUTTERFLIES_ACTIONS_SETUP_H +#define CATS_BUTTERFLIES_ACTIONS_SETUP_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 +#endif //CATS_BUTTERFLIES_ACTIONS_SETUP_H diff --git a/src/modules/butterflies/butterflies_dispersal.c b/src/modules/butterflies/butterflies_dispersal.c index 1582d7fb4aa4968969c92010dd195ddbe6dcbdb6..7422d08ff3c1e0a2c518eedbd374ccc21d5cd12a 100644 --- a/src/modules/butterflies/butterflies_dispersal.c +++ b/src/modules/butterflies/butterflies_dispersal.c @@ -53,7 +53,7 @@ static void inline single_random_walk(struct cats_thread_info *ts, struct cats_g const cats_dt_coord cols = grid->dimension.cols; - for (cats_dt_coord step = 0; step < max_steps; step++){ + for (cats_dt_coord step = 0; step < max_steps; step++) { const unsigned long int direction = gsl_rng_uniform_int(ts->rng, N_DIRECTIONS); @@ -74,7 +74,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)) { if (debug_rw) { - fprintf(module_conf->debug_rw_file, "%d,%d,%d,%d,%d,%d,%d\n", rw_num, row, col, step + 1, + fprintf(module_conf->debug_rw_file, "%d,%d,%d,%d,%d,%d,%d\n", rw_num, row, col, + step + 1, module_conf->animal_dispersal_max_radius - step - 1, 0, eggs_left); } @@ -106,9 +107,13 @@ 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) + bool check_exclusion, bool local_only) { const struct cats_configuration *conf = ts->conf; if (check_exclusion @@ -118,12 +123,15 @@ butterflies_cell_dispersal(struct cats_grid *grid, struct cats_thread_info *ts, // total adults: the number of adults that became adult in this cell, possibly exceeding the carrying capacity (thanks to poisson processes) const cats_dt_population total_adults = get_adult_population(grid, row, col); + if (total_adults == 0) return; ts->rw_debug_cells_with_adults++; struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; // 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 - const cats_dt_population total_females = (cats_dt_population) gsl_ran_binomial(ts->rng, (double) module_conf->female_fraction, total_adults); + const cats_dt_population total_females = (cats_dt_population) gsl_ran_binomial(ts->rng, + (double) module_conf->female_fraction, + total_adults); assert(total_females >= 0 && total_females <= total_adults); // total males: the rest @@ -142,44 +150,18 @@ butterflies_cell_dispersal(struct cats_grid *grid, struct cats_thread_info *ts, if (eggs_per_female == 0) return; - // supernumerous_adults: the number of adults exceeding the carrying capacity - 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 - cats_dt_population supernumerous_females = 0; - - - if (supernumerous_adults > 0) { - // 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); - - } - - - // 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)? + // how many females will leave the cell // wandering_females: the number of females that will leave the cell and do a random walk - cats_dt_population wandering_females = - (cats_dt_population) (females_within_cc * (1.0 - module_conf->probability_to_stay)); + cats_dt_rates probability_to_leave = (1.0 - module_conf->probability_to_stay); + cats_dt_population wandering_females = poisson_population_capped(ts->rng, + total_females * probability_to_leave, + total_females); // 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; - } + cats_dt_population stationary_females = total_females - wandering_females; + assert(stationary_females >= 0); + assert(wandering_females >= 0); - // we need to add the previously subtracted supernumerous females - wandering_females += supernumerous_females; const int module_id = CATS_MODULE_ID; struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; @@ -192,30 +174,33 @@ 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); - // add source cell eggs to the source cell - data->eggs[row][col] += (float) ceill(source_cell_eggs); + 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: 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); + + + + if (local_only) { + return; + } if (debug_rw) { - fprintf(module_conf->debug_rw_file, "# total source cell eggs = %d\n", (int)ceill(source_cell_eggs)); + fprintf(module_conf->debug_rw_file, "# total source cell eggs = %d\n", (int) ceill(source_cell_eggs)); fprintf(module_conf->debug_rw_file, "# stationary females = %d\n", stationary_females); fprintf(module_conf->debug_rw_file, "# wandering females = %d\n", wandering_females); fprintf(module_conf->debug_rw_file, "# total females = %d\n", wandering_females + stationary_females); - fprintf(module_conf->debug_rw_file, "# wandering females source cell eggs = %d\n", (int) (wandering_females * (eggs_per_female - eggs_to_disperse_per_female))); - fprintf(module_conf->debug_rw_file, "# stationary females source cell eggs = %d\n", (int) (stationary_females * eggs_per_female)); - + fprintf(module_conf->debug_rw_file, "# wandering females source cell eggs = %d\n", + (int) (wandering_females * (eggs_per_female - eggs_to_disperse_per_female))); + fprintf(module_conf->debug_rw_file, "# stationary females source cell eggs = %d\n", + (int) (stationary_females * eggs_per_female)); fprintf(module_conf->debug_rw_file, "id,row,col,step,steps left,eggs deposited,eggs left\n"); - } for (int32_t rw_number = 0; rw_number < wandering_females; rw_number++) { diff --git a/src/modules/butterflies/butterflies_dispersal.h b/src/modules/butterflies/butterflies_dispersal.h index 6385792ccd2b7055dbc0ad4fa0dac2bf2d07898c..d0fe418daccdaa8a03b71d48406dec781206f9ad 100644 --- a/src/modules/butterflies/butterflies_dispersal.h +++ b/src/modules/butterflies/butterflies_dispersal.h @@ -1,12 +1,14 @@ -// -// Created by gattringera on 21/11/22. -// - #ifndef CATS_BUTTERFLIES_DISPERSAL_H #define CATS_BUTTERFLIES_DISPERSAL_H #include "threading/threading.h" #include "cats/configuration/configuration.h" -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, + bool local_only); + +void bf_initial_population_to_eggs(struct cats_grid *grid, struct cats_thread_info *ts); #endif //CATS_BUTTERFLIES_DISPERSAL_H diff --git a/src/modules/butterflies/butterflies_generations.c b/src/modules/butterflies/butterflies_generations.c index b046bceae97003bf978fbbb420c023e1917ac1e4..70f21d1b01fc1164d2657db156d93046666c69f3 100644 --- a/src/modules/butterflies/butterflies_generations.c +++ b/src/modules/butterflies/butterflies_generations.c @@ -32,7 +32,6 @@ 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++) { - if (get_suitability(grid, row, col) < ot) { if (data->eggs[row][col] > 0) cells_with_eggs_removed += 1; @@ -69,4 +68,5 @@ void bf_area_generation_update(struct cats_grid *grid, struct cats_thread_info * stats->custom_stats[egg_cells_id] += cells_with_eggs; stats->custom_stats[egg_cells_removed_id] += cells_with_eggs_removed; + } \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_initial_population.c b/src/modules/butterflies/butterflies_initial_population.c new file mode 100644 index 0000000000000000000000000000000000000000..f4fc811d292b12b08cf0ad73a594ee11e36c3319 --- /dev/null +++ b/src/modules/butterflies/butterflies_initial_population.c @@ -0,0 +1,112 @@ + +#include "lambda/leslie_matrix.h" +#include "inline.h" + +#include "butterflies_dispersal.h" +#include "butterflies_generations.h" +#include "populations/population.h" +#include "paths/paths.h" + +#include "butterflies_populations.h" + +#include "butterflies_main.h" +#include "butterflies_actions.h" +#include "modules/module_header.h" +#include "actions/cats_actions.h" +#include "butterflies_initial_population.h" + + +void bf_initial_population_adjustment(struct cats_configuration *conf, struct cats_grid *grid) +{ + int64_t init_populated_cells = count_populated_cells(grid); + int64_t invalid_resources = butterflies_prune_invalid_cells(grid); + log_message(LOG_IMPORTANT, "Loaded initial populations: %ld cells occupied before adjustment", + init_populated_cells); + if (grid->param.initial_population.set_to_cc == true) { + +//#define DEBUG_INITIAL_POPULATIONS 1 +#ifdef DEBUG_INITIAL_POPULATIONS + const int32_t max_i = 10; + struct cats_vital_rate *cc_rate = &grid->param.carrying_capacity; + cats_dt_rates OT = grid->param.OT; + for (int32_t i = 0; i < max_i; i++) { + + cats_dt_rates suit = OT + i * (1.0 - OT)/max_i; + cats_dt_rates cc = cc_rate->func->func(cc_rate, &grid->param, suit, 0, NAN); + log_message(LOG_INFO, "Carrying capacity for suitability %Lf: %Lf", suit, cc); + + } + const cats_dt_coord rows = grid->dimension.rows; + const cats_dt_coord cols = grid->dimension.cols; + int64_t start = 0; + int64_t multi_excluded = 0; + + for (cats_dt_coord row = 0; row < rows; row++) { + for (cats_dt_coord col = 0; col < cols; col++) { + + if (get_adult_population(grid, row, col) == 0) continue; + 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]; + } + 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); + if (multiplier == 0) { + multi_excluded += 1; + } + cats_dt_population cc = get_carrying_capacity(grid, row, col); + + printf("DEBUG::row %d col %d, suit %Lf, cc multi %Lf, cc raw %Lf, cc %d\n", row, col, suit, multiplier, cc_raw, cc); + } + } + + + +#endif + + increase_initial_population_to_cc(grid, conf); + int64_t populated_cells_after_cc = count_populated_cells(grid); + log_message(LOG_IMPORTANT, "\t%ld cells occupied after setting population sizes to carrying capacity", + populated_cells_after_cc); + } + + + if (grid->param.initial_population.suitability_threshold > 0.0) { + prune_initial_population_under_threshold(conf, grid); + } + + int64_t after_populated_cells = count_populated_cells(grid); + + log_message(LOG_IMPORTANT, "Pruned initial populations from %ld cells to %ld, (%ld wrong habitat)", + init_populated_cells, after_populated_cells, invalid_resources); + + + cats_dt_population rows = grid->dimension.rows; + cats_dt_population cols = grid->dimension.cols; + + threaded_action(&bf_initial_population_to_eggs, grid, conf, TS_DISPERSAL); + +#ifdef BF_DEBUG + int module_id = CATS_MODULE_ID; + struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; +#endif + + + 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]) { + printf("" + "BFDBG::%s::initial adults -> eggs::%d,%d,%d,%f\n", + __func__, row, col, get_adult_population(grid, row, col), + data->eggs[row][col]); + } +#endif + set_population_ignore_cc(grid, row, col, 0); + } + } + + + grid->param.initial_population.adjusted = true; +} \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_initial_population.h b/src/modules/butterflies/butterflies_initial_population.h new file mode 100644 index 0000000000000000000000000000000000000000..718f3cf48fa1380bc16b757767ea4107ceb4b04f --- /dev/null +++ b/src/modules/butterflies/butterflies_initial_population.h @@ -0,0 +1,5 @@ +#ifndef CATS_BUTTERFLIES_INITIAL_POPULATION_H +#define CATS_BUTTERFLIES_INITIAL_POPULATION_H +#include "data/cats_grid.h" +void bf_initial_population_adjustment(struct cats_configuration *conf, struct cats_grid *grid); +#endif //CATS_BUTTERFLIES_INITIAL_POPULATION_H diff --git a/src/modules/butterflies/butterflies_main.c b/src/modules/butterflies/butterflies_main.c index bd0d13a8c7068a36610f77a16a360d15a60bb362..bd1ee7b29daa0262dc949bb5361af95ea7417ae0 100644 --- a/src/modules/butterflies/butterflies_main.c +++ b/src/modules/butterflies/butterflies_main.c @@ -7,50 +7,38 @@ #include "butterflies_actions.h" #include "butterflies_vital_rates.h" #include "cats_ini/cats_ini.h" -#include "butterflies_action_helpers.h" +#include "butterflies_actions_setup.h" #include "paths/output_paths.h" #include "paths/directory_helper.h" #include "butterflies_populations.h" -#include "butterflies_filenames.h" +#include "butterflies_paths.h" struct cats_global global; struct cats_debug_options cats_debug; #include "lambda/leslie_matrix.h" +#include "actions/setup_actions.h" +#include "butterflies_scale.h" -double *butterflies_matrix(struct cats_configuration *conf, struct lambda_parameters *l_param, - bool silent, int32_t *N_out){ - bool print_rate = !silent; - +cats_dt_rates bf_expected_local_eggs_per_female(struct cats_configuration *conf, struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) +{ struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; - cats_dt_rates eggs_per_female = calculate_rate_for_matrix(&module_conf->eggs_per_female, l_param, print_rate); - cats_dt_rates reproduction_rate = calculate_rate_for_matrix(&module_conf->reproduction_rate, l_param, print_rate); - cats_dt_rates female_fraction = module_conf->female_fraction; cats_dt_rates stationary = module_conf->probability_to_stay; cats_dt_rates mobile = 1.0 - stationary; cats_dt_rates egg_fraction_source = module_conf->egg_fraction_source; - + cats_dt_rates eggs_per_female = calculate_rate(&module_conf->eggs_per_female, NAN, &grid->param, grid, row, col, NULL); cats_dt_rates local_eggs = (stationary + mobile * egg_fraction_source ) * eggs_per_female; - // female -> female - // to achieve the target reproduction rate, the number of eggs per female laid in the cell - // that survive and become adult has to be the reproduction rate divided by the female fraction divided by the number of eggs - cats_dt_rates eggs_to_adults_rate = bf_egg_to_adult_survival_rate(reproduction_rate, local_eggs, female_fraction); - cats_dt_rates result = local_eggs * eggs_to_adults_rate * female_fraction; - - double *matrix = calloc_or_die(1, sizeof(double)); - - *matrix = (double) result; - *N_out = 1; - return matrix; - + return local_eggs; } + 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); + log_message(LOG_INFO, "%s: %s: grid init of grid %d with %d rows and %d cols", + module_name, __func__, grid->id, grid->dimension.cols, grid->dimension.rows); + struct grid_data_butterflies *data = malloc_or_die(sizeof(struct grid_data_butterflies)); log_message(LOG_INFO, "allocating data for generations"); @@ -171,24 +159,30 @@ void load_butterflies_species_params(struct cats_configuration *conf, struct cat if (!data->actions_added) { bf_register_actions(conf); + list_actions_full(conf); + log_message(LOG_EMPTY, " "); bf_add_actions(conf); + log_message(LOG_EMPTY, " "); + data->actions_added = true; + + } } -void cats_module_init(struct cats_configuration *conf) +int cats_module_init(struct cats_configuration *conf) { struct conf_data_butterflies *data = calloc_or_die(1, sizeof(struct conf_data_butterflies)); enum cats_module_flags flags = MODULE_ALTERNATE_DEMOGRAPHIC | MODULE_OVERRIDE_ACTIONS; 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); - register_create_leslie_matrix_func(conf, butterflies_matrix); + register_create_leslie_matrix_func(conf, bf_leslie_matrix); bf_add_vital_rates(conf, data); - log_message(LOG_INFO, "Hello from %s (id: %d)\n", module_name, id); + log_message(LOG_INFO, "Hello from '%s' (id: %d)", module_name, id); for (enum butterfly_stats which = BF_STAT_MIN; which < BF_STAT_MAX; which++) { @@ -196,4 +190,5 @@ void cats_module_init(struct cats_configuration *conf) } bf_add_directories(conf); + return id; } diff --git a/src/modules/butterflies/butterflies_overlays.c b/src/modules/butterflies/butterflies_overlays.c index 2dd223fcdadb8090bdd455ecf94a7f55db50ef0a..704b4fb5a10c1c0b60c34bd24a5e5335ad2f190b 100644 --- a/src/modules/butterflies/butterflies_overlays.c +++ b/src/modules/butterflies/butterflies_overlays.c @@ -96,6 +96,8 @@ enum action_status bf_grid_overlay_update(const struct cats_configuration *conf, cells_with_eggs, total_eggs, total_eggs / (float) cells_with_eggs); log_message(LOG_INFO, "Overlay update: %ld cells with eggs removed", cells_eggs_removed); log_message(LOG_INFO, "Overlay update: %ld cells with adults removed", cells_adults_removed); + + return ACTION_RUN; } diff --git a/src/modules/butterflies/butterflies_filenames.c b/src/modules/butterflies/butterflies_paths.c similarity index 99% rename from src/modules/butterflies/butterflies_filenames.c rename to src/modules/butterflies/butterflies_paths.c index 1b37a6469b0464bb118bf2f720dbc6c80c03847e..29ca2fef3a387c16d5dab0fa6921aa7609f0dfc4 100644 --- a/src/modules/butterflies/butterflies_filenames.c +++ b/src/modules/butterflies/butterflies_paths.c @@ -7,7 +7,7 @@ #include "butterflies_actions.h" #include "modules/module_header.h" #include "actions/cats_actions.h" -#include "butterflies_filenames.h" +#include "butterflies_paths.h" #include "module.h" void bf_add_directories(struct cats_configuration *conf) diff --git a/src/modules/butterflies/butterflies_filenames.h b/src/modules/butterflies/butterflies_paths.h similarity index 80% rename from src/modules/butterflies/butterflies_filenames.h rename to src/modules/butterflies/butterflies_paths.h index 05ae28669045342007e32e01ef73bda75ef99d45..a109363339cf3b5e428182be01ffd534304da700 100644 --- a/src/modules/butterflies/butterflies_filenames.h +++ b/src/modules/butterflies/butterflies_paths.h @@ -1,5 +1,5 @@ -#ifndef CATS_BUTTERFLIES_FILENAMES_H -#define CATS_BUTTERFLIES_FILENAMES_H +#ifndef CATS_BUTTERFLIES_PATHS_H +#define CATS_BUTTERFLIES_PATHS_H #include "configuration/configuration.h" char *bf_population_eggs_filename(struct cats_configuration *conf, struct cats_grid *grid); @@ -7,4 +7,4 @@ char *bf_population_filename(struct cats_configuration *conf, struct cats_grid * char *bf_stats_filename(struct cats_configuration *conf, struct cats_grid *grid); char *bf_population_overlay_filename(struct cats_configuration *conf, struct cats_grid *grid); void bf_add_directories(struct cats_configuration *conf); -#endif //CATS_BUTTERFLIES_FILENAMES_H +#endif //CATS_BUTTERFLIES_PATHS_H diff --git a/src/modules/butterflies/butterflies_populations.c b/src/modules/butterflies/butterflies_populations.c index 8480c84653972b4807570692df82aac798b66675..1ce531422f0946aa649381543248976f8856bf92 100644 --- a/src/modules/butterflies/butterflies_populations.c +++ b/src/modules/butterflies/butterflies_populations.c @@ -12,39 +12,80 @@ #include "butterflies_populations.h" #include "butterflies_main.h" #include "butterflies_inline.h" -#include "inline_population.h" #include "inline.h" #include "populations/population.h" +int64_t count_populated_cells(const struct cats_grid *grid) +{ + int64_t cells = 0; + cats_dt_coord rows = grid->dimension.rows; + 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 (get_adult_population(grid, row, col)) { + cells += 1; + } + + } + } + return cells; +} + + +int64_t butterflies_prune_invalid_cells(struct cats_grid *grid) +{ + int64_t invalid_habitat = 0; + int module_id = CATS_MODULE_ID; + struct grid_data_butterflies *data = grid->grid_modules[module_id].module_data; + cats_dt_coord rows = grid->dimension.rows; + 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 (!(data->info_layer[row][col] & BF_CELL_VALID_DISPERSAL_TARGET)) { + if(get_adult_population(grid, row, col)) { + invalid_habitat += 1; + } + set_population_ignore_cc(grid, row, col, 0); + + } + } + } + return invalid_habitat; +} -cats_dt_rates bf_egg_to_adult_survival_rate(cats_dt_rates reproduction_rate, cats_dt_rates eggs, cats_dt_rates female_fraction) + +cats_dt_rates +bf_egg_to_adult_survival_rate(cats_dt_rates reproduction_rate, cats_dt_rates eggs) { - return (reproduction_rate / female_fraction) / eggs; + return reproduction_rate / eggs; } + 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; assert (conf->grid_count == 1); - if (check_exclusion) { if (bf_cell_excluded_by_generation(grid, row, col)) return; } - 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]); exit(EXIT_FAILURE); } + + + + // 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 @@ -66,7 +107,7 @@ void bf_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cat float current_generation_float = (float) data->generation_current; if (current_generation_float == local_generation - || data->generation_current == module_conf->generations_min) { + || data->generation_current == module_conf->generations_min) { this_generation_fraction = 1.0f; } else if (data->generation_current == local_max_generation) { this_generation_fraction = (float) local_max_generation - local_generation; @@ -77,6 +118,11 @@ 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; float eggs = this_generation_fraction * data->eggs[row][col]; +#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); +#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], @@ -85,10 +131,8 @@ void bf_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cat } data->eggs[row][col] -= eggs; - - assert(data->eggs[row][col] >= 0); - if (eggs == 0) return; + // not capped, we can have more adults than CC @@ -96,7 +140,8 @@ void bf_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cat cats_dt_rates reproduction_rate = calculate_rate(&module_conf->reproduction_rate, NAN, &grid->param, grid, row, col, NULL); if (suit < grid->param.OT && reproduction_rate > 0) { - log_message(LOG_ERROR, "Suitability %f under OT %Lf, but adults per female = %Lf", suit, grid->param.OT, reproduction_rate); + log_message(LOG_ERROR, "Suitability %f under OT %Lf, but adults per female = %Lf", suit, grid->param.OT, + reproduction_rate); exit_cats(EXIT_FAILURE); } @@ -108,15 +153,19 @@ void bf_cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cat return; } - - - - cats_dt_rates survival = bf_egg_to_adult_survival_rate(reproduction_rate, eggs, module_conf->female_fraction); + cats_dt_rates expected_eggs = bf_expected_local_eggs_per_female(ts->conf, grid, row, col); + cats_dt_rates survival = bf_egg_to_adult_survival_rate(reproduction_rate, expected_eggs)/module_conf->female_fraction; cats_dt_population adults = poisson(ts->rng, eggs * survival); assert(adults >= 0); - - set_population(grid, row, col, adults); +#ifdef BF_DEBUG + adults = get_adult_population(grid, row, col); + printf("BFDBG::%s::row %d, col %d: year %d, suitability %f, OT %Lf\n", __func__, row, col, conf->time.year_current, suit, grid->param.OT); + printf("BFDBG::%s::row %d, col %d: year %d, eggs %f, survival rate %Lf, reproduction rate %Lf, adults %d\n", + __func__, row, col, conf->time.year_current, eggs, survival, reproduction_rate, adults); + printf("XXXX,%d,%f,%d\n", conf->time.year_current, current_generation_float,adults); +#endif + } diff --git a/src/modules/butterflies/butterflies_populations.h b/src/modules/butterflies/butterflies_populations.h index f8f164b81c7f01c7b20d3bb37c15b81e9a976beb..894fce21b4a0c8315181dc58ce50c016bf901cdb 100644 --- a/src/modules/butterflies/butterflies_populations.h +++ b/src/modules/butterflies/butterflies_populations.h @@ -5,8 +5,10 @@ #ifndef CATS_BUTTERFLIES_POPULATIONS_H #define CATS_BUTTERFLIES_POPULATIONS_H #include "data/cats_grid.h" +int64_t count_populated_cells(const struct cats_grid *grid); 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); -cats_dt_rates bf_egg_to_adult_survival_rate(cats_dt_rates reproduction_rate, cats_dt_rates eggs, cats_dt_rates female_ratio); - +cats_dt_rates bf_egg_to_adult_survival_rate(cats_dt_rates reproduction_rate, cats_dt_rates eggs); +cats_dt_rates bf_expected_local_eggs_per_female(struct cats_configuration *conf, struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col); +int64_t butterflies_prune_invalid_cells(struct cats_grid *grid); #endif //CATS_BUTTERFLIES_POPULATIONS_H diff --git a/src/modules/butterflies/butterflies_scale.c b/src/modules/butterflies/butterflies_scale.c new file mode 100644 index 0000000000000000000000000000000000000000..53627e85d7c4126c8695708abea9bf05f83a4793 --- /dev/null +++ b/src/modules/butterflies/butterflies_scale.c @@ -0,0 +1,37 @@ +// +// Created by andreas on 03/07/23. +// +#include "modules/module_header.h" +#include "butterflies_main.h" +#include "butterflies_scale.h" +#include "butterflies_populations.h" + + +double *bf_leslie_matrix(struct cats_configuration *conf, struct lambda_parameters *l_param, + bool silent, int32_t *N_out){ + bool print_rate = !silent; + + struct conf_data_butterflies *module_conf = CATS_MODULE_DATA; + cats_dt_rates eggs_per_female = calculate_rate_for_matrix(&module_conf->eggs_per_female, l_param, print_rate); + cats_dt_rates reproduction_rate = calculate_rate_for_matrix(&module_conf->reproduction_rate, l_param, print_rate); + cats_dt_rates stationary = module_conf->probability_to_stay; + cats_dt_rates mobile = 1.0 - stationary; + cats_dt_rates egg_fraction_source = module_conf->egg_fraction_source; + + cats_dt_rates local_eggs = (stationary + mobile * egg_fraction_source ) * eggs_per_female; + + // female -> female + // to achieve the target reproduction rate, the number of eggs per female laid in the cell + // that survive and become adult has to be the reproduction rate divided by the female fraction divided by the number of eggs + + cats_dt_rates eggs_to_adults_rate = bf_egg_to_adult_survival_rate(reproduction_rate, local_eggs) ; + cats_dt_rates result = local_eggs * eggs_to_adults_rate; + + printf("scale %Lf: eggs %Lf, eggs to adults %Lf\n", conf->param->scale_factor, eggs_per_female, eggs_to_adults_rate); + double *matrix = calloc_or_die(1, sizeof(double)); + + *matrix = (double) result; + *N_out = 1; + return matrix; + +} \ No newline at end of file diff --git a/src/modules/butterflies/butterflies_scale.h b/src/modules/butterflies/butterflies_scale.h new file mode 100644 index 0000000000000000000000000000000000000000..3dbcd1d911a04e928e5159901818982804dfc5da --- /dev/null +++ b/src/modules/butterflies/butterflies_scale.h @@ -0,0 +1,16 @@ +// +// Created by andreas on 03/07/23. +// + +#ifndef CATS_BUTTERFLIES_SCALE_H +#define CATS_BUTTERFLIES_SCALE_H + +#include <stdbool.h> +#include <stdint.h> +#include "configuration/configuration.h" +#include "lambda/leslie_matrix.h" + +double *bf_leslie_matrix(struct cats_configuration *conf, struct lambda_parameters *l_param, + bool silent, int32_t *N_out); + +#endif //CATS_BUTTERFLIES_SCALE_H diff --git a/src/modules/butterflies/butterflies_stats.c b/src/modules/butterflies/butterflies_stats.c index ce77d1b323e528ab4be50762f728ead21d26d4b1..20925e9467b81c86abd65d121e3b86430ea1150f 100644 --- a/src/modules/butterflies/butterflies_stats.c +++ b/src/modules/butterflies/butterflies_stats.c @@ -8,7 +8,7 @@ #include "inline_overlays.h" #include "inline_population.h" #include "inline.h" -#include "butterflies_filenames.h" +#include "butterflies_paths.h" #include "temporal/phase_names.h" #include "temporal/years.h" diff --git a/src/modules/cats_test_module/register_module.c b/src/modules/cats_test_module/register_module.c index 7e12973861abfb7036f210e2db19e50bbd2aab72..c97616d35e85e56ecbdeb33dfc15df8e1af0b889 100644 --- a/src/modules/cats_test_module/register_module.c +++ b/src/modules/cats_test_module/register_module.c @@ -59,7 +59,7 @@ void cats_module_init(struct cats_configuration *conf) enum cats_module_flags flags = MODULE_NO_FLAGS; int32_t id = register_module(conf, module_name, data, flags); register_cats_grid_init_function(conf, grid_init, grid_cleanup); - log_message(LOG_INFO, "Hello from %s (id: %d)\n", module_name, id); + log_message(LOG_INFO, "Hello from '%s' (id: %d)", module_name, id); greeting2(); }