diff --git a/CMakeLists.txt b/CMakeLists.txt index 05993bf744095920ea251a6b776c119aaf8a45da..cf625b9a48322ab57e452a9be1518ca5047b3579 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,6 @@ if ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUA -Wall -Werror -O3 - -g -D_GNU_SOURCE -DHAVE_INLINE -DGSL_C99_INLINE diff --git a/src/cats/CMakeLists.txt b/src/cats/CMakeLists.txt index 00239ae79b9860e9a72cbc61f3233041b377a531..fb05cbcc22490e4cb15fc96ea5f9e61d72a8cd6c 100644 --- a/src/cats/CMakeLists.txt +++ b/src/cats/CMakeLists.txt @@ -39,7 +39,7 @@ include_directories(${GDAL_INCLUDE_DIR}) include_directories(${GSL_INCLUDE_DIR}) include_directories(${MPI_C_INCLUDE_PATH}) -add_library(libcats STATIC "" stats/statistics.c stats/statistics.h data/cats_global.c ../cats_windows.h test/test_ini.c test/test_ini.h debug/debug_vital_rates.c debug/debug_vital_rates.h overlays/overlay_resources.c overlays/overlay_resources.h paths/path_patterns.c paths/path_patterns.h) +add_library(libcats STATIC "" stats/statistics.c stats/statistics.h data/cats_global.c ../cats_windows.h test/test_ini.c test/test_ini.h debug/debug_vital_rates.c debug/debug_vital_rates.h overlays/overlay_resources.c overlays/overlay_resources.h paths/path_patterns.c paths/path_patterns.h grids/dimensions.c grids/dimensions.h grids/direct_access.c grids/direct_access.h) target_include_directories(libcats PUBLIC ".") target_sources(libcats PRIVATE diff --git a/src/cats/actions/process_inter_period_survival.c b/src/cats/actions/process_inter_period_survival.c index 479385a710b9537fb919d1156d0de5ce54e15fdb..24c48b3000a25ca838e877d9d10e590efec142e9 100644 --- a/src/cats/actions/process_inter_period_survival.c +++ b/src/cats/actions/process_inter_period_survival.c @@ -57,22 +57,18 @@ void write_stats(struct cats_grid *grid, const struct cats_configuration *conf, j_sum_weighted, get_seed_sum(g, 0, 0)); - fprintf(f, ",%f", g->dispersed_seeds[0][0]); + fprintf(f, ",%f", get_dispersed_seeds(grid, 0, 0)); for (int32_t i = 0; i < seed_persistence; i++) { - if (g->seed_bank[0][0]) { - fprintf(f, ",%f", g->seed_bank[0][0][i]); + if (seed_bank_exists(g, 0, 0)) { + fprintf(f, ",%f", get_seed_bank_seeds(g, 0, 0, i)); } else { fprintf(f, ",%f", 0.0); } } - for (int32_t i = 0; i < max_age_of_maturity + 1; i++) { - if (g->juveniles[0][0]) { - fprintf(f, ",%d", g->juveniles[0][0][i]); - } else { - fprintf(f, ",%d", 0); - } + for (int32_t i = 0; i < max_age_of_maturity + 1; i++) { + fprintf(f, ",%d", get_juveniles(g, 0, 0, i)); } fprintf(f, "\n"); diff --git a/src/cats/actions/process_seed_dispersal.c b/src/cats/actions/process_seed_dispersal.c index 8157c95b09fcf74f17d9d72cbca5e0bdac6cf45c..ab47e317a7d4c765bc19bceb3f73e30616402330 100644 --- a/src/cats/actions/process_seed_dispersal.c +++ b/src/cats/actions/process_seed_dispersal.c @@ -43,6 +43,7 @@ #include "inline_overlays.h" #include "actions/cats_actions.h" #include "temporal/years.h" +#include "inline.h" void area_post_process_seeds(struct cats_grid *grid, struct cats_thread_info *ts); @@ -106,7 +107,7 @@ enum action_status process_disperse_seeds(struct cats_grid *grid, struct cats_co if (conf->command_line_options.lambda_test) { disperse_seeds(grid, 0, 0, grid->single_thread); - grid->seeds_produced[0][0] = 0.0f; + set_produced_seeds(grid, 0, 0, 0.0f); cell_post_process_seeds(grid, conf, 0, 0, grid->single_thread); return ACTION_RUN; } @@ -172,7 +173,7 @@ void area_post_process_seeds(struct cats_grid *grid, struct cats_thread_info *ts mark_cell_done(&debug, row, col); #endif if (cell_excluded_by_overlay(conf, row, col)) { - grid->dispersed_seeds[row][col] = 0; + set_dispersed_seeds(grid, row, col, 0.0f); } else { cell_post_process_seeds(grid, conf, row, col, ts); } @@ -194,8 +195,8 @@ void dispersal_wrapper(struct cats_grid *grid, struct cats_thread_info *ts) mark_cell_done(&debug, row, col); #endif if (cell_excluded_by_overlay(conf, row, col)) { continue; } - if (grid->seeds_produced[row][col] > 0.0) disperse_seeds(grid, row, col, ts); - grid->seeds_produced[row][col] = 0.0f; + if (get_produced_seeds(grid, row, col) > 0.0) disperse_seeds(grid, row, col, ts); + set_produced_seeds(grid, row, col, 0.0f); } } } diff --git a/src/cats/actions/setup.c b/src/cats/actions/setup.c index d88079d3b9f4f5fe416fee6c3f9d6d6b7c425dc1..7252e60aae619729cbad693cd91ee1ddccd27b0d 100644 --- a/src/cats/actions/setup.c +++ b/src/cats/actions/setup.c @@ -37,6 +37,7 @@ #include "temporal/simulation_time.h" #include "populations/population.h" #include "dispersal/dispersal.h" +#include "inline.h" void setup_lambda_test_simulation(struct cats_configuration *conf, struct cats_grid *grid) // FIXME MAYBE MOVE @@ -55,7 +56,7 @@ void setup_lambda_test_simulation(struct cats_configuration *conf, struct cats_g cats_dt_coord row = 0; cats_dt_coord col = 0; - grid->suitability->environments[0]->current.values[row][col] = (cats_dt_environment) grid->param.OT; // FIXME -> set suitability + set_suitability(grid, row, col, (cats_dt_environment) grid->param.OT); cats_dt_population target_pop = get_adult_carrying_capacity(grid, row, col) / 5; set_population_ignore_cc(grid, row, col, target_pop); @@ -94,7 +95,8 @@ void setup_lambda_gradient_simulation(struct cats_configuration *conf, struct ca cats_dt_environment diff = 1.0f / ((cats_dt_environment) conf->geometry.dimension.cols - 1.0f); for (cats_dt_coord row = 0; row < rows; row++) { for (cats_dt_coord col = 0; col < cols; col++) { - grid->suitability->environments[0]->current.values[row][col] = (cats_dt_environment) col * diff; + cats_dt_environment value = (cats_dt_environment) col * diff; + set_suitability(grid, row, col, value); } } diff --git a/src/cats/configuration/check_configuration.c b/src/cats/configuration/check_configuration.c index 4eaae98ecaf30719d2db216b7da409c5473269d9..fb5445585a447ca2e7eeda0e451f22e146c89898 100644 --- a/src/cats/configuration/check_configuration.c +++ b/src/cats/configuration/check_configuration.c @@ -32,6 +32,7 @@ #include "inline_vital_rates.h" #include "dispersal/dispersal.h" #include "data/simulation_geometry.h" +#include "inline_vital_ages.h" int check_string(char *value, char *name) diff --git a/src/cats/configuration/configuration.c b/src/cats/configuration/configuration.c index 6d6fb2af6824235e861c56bdd6f93df2d5b257e6..c6cc5a61b9f0241d6c9b4076cddfd66e7c530262 100644 --- a/src/cats/configuration/configuration.c +++ b/src/cats/configuration/configuration.c @@ -48,6 +48,7 @@ #include "inline_vital_rates.h" #include "dispersal/dispersal.h" #include "stats/grid_stats.h" +#include "inline_vital_ages.h" #ifdef CATS_ON_WINDOWS #include <windows.h> diff --git a/src/cats/configuration/preset.c b/src/cats/configuration/preset.c index 562e3cfca9ca1f55ecf4348c38599efc244fb9aa..fef6c8a57e64756a6b57a4240261063187d0e64f 100644 --- a/src/cats/configuration/preset.c +++ b/src/cats/configuration/preset.c @@ -21,11 +21,14 @@ * */ +#include <string.h> #include "cats_global.h" #include "preset.h" #include "vital_ages/default_vital_ages.h" #include "vital_rates/default_vital_rates.h" #include "inline_vital_rates.h" +#include "inline_vital_ages.h" +#include "misc/cats_maths_inline.h" enum cats_species_preset get_species_preset_from_from_string(const char *string) diff --git a/src/cats/configuration/print_configuration.c b/src/cats/configuration/print_configuration.c index 8265fe845b4b8d30efb164dc770ade3b11a814a0..13bb981936a3e8004d5aa5dce601aa421f5c51c4 100644 --- a/src/cats/configuration/print_configuration.c +++ b/src/cats/configuration/print_configuration.c @@ -33,6 +33,7 @@ #include "inline_vital_rates.h" #include "dispersal/dispersal.h" #include "modules/load_module.h" +#include "inline_vital_ages.h" const char *get_dispersal_name(enum dispersal_type type); diff --git a/src/cats/debug/debug_vital_rates.c b/src/cats/debug/debug_vital_rates.c index ec6f3625f7bbd5623949155b7a2ecf6e19a1f456..4e3de11fbc82b0bbb8a7da3cd59e36f6acc7b22a 100644 --- a/src/cats/debug/debug_vital_rates.c +++ b/src/cats/debug/debug_vital_rates.c @@ -90,7 +90,7 @@ struct cats_grid *minimal_grid(struct cats_configuration *conf, struct cats_envi } -void set_suitability(struct cats_environment *env, cats_dt_environment suit) +void debug_set_suitability(struct cats_environment *env, cats_dt_environment suit) { env->environments[0]->current.values[0][0] = suit; } @@ -138,7 +138,7 @@ static inline cats_dt_rates attempt_rate_calculation(cats_dt_environment suit, c } - set_suitability(grid->suitability, suit); + debug_set_suitability(grid->suitability, suit); *K_suit = get_adult_carrying_capacity(grid, 0, 0); if (N > *K_suit) return NAN; @@ -209,7 +209,7 @@ void debug_vital_rate(struct cats_vital_rate *vr, struct cats_vital_rate *cc, st void debug_vital_rates(struct cats_configuration *conf, const struct program_options *command_line_options) { struct cats_environment *env = minimal_suitability_environment(); - set_suitability(env, 0.5f); + debug_set_suitability(env, 0.5f); struct cats_grid *grid = minimal_grid(conf, env); struct cats_species_param *param = &grid->param; set_param_values(param, 0.5, 0.25, 0.5); diff --git a/src/cats/dispersal/dispersal.c b/src/cats/dispersal/dispersal.c index 938c362b52f6e663e0f524c66a1be237dc1a64e2..4f13f4a51a23bb1a804bd4204457a598e14eeb53 100644 --- a/src/cats/dispersal/dispersal.c +++ b/src/cats/dispersal/dispersal.c @@ -51,6 +51,7 @@ #include "memory/cats_memory.h" #include "inline_overlays.h" +#include "inline.h" // ANSATZPUNKTE // 3 verschiedene dispersals: @@ -153,7 +154,7 @@ void disperse_seeds(const struct cats_grid *restrict grid, cats_dt_coord s_row, assert(s_col < grid->dimension.cols); - float seeds = grid->seeds_produced[s_row][s_col]; + float seeds = get_produced_seeds(grid, s_row, s_col); assert(seeds >= 0.0); if (seeds < 1.0) return; diff --git a/src/cats/dispersal/local_dispersal.c b/src/cats/dispersal/local_dispersal.c index c91fd5411d000bcf8d9040f389cd568eb85cb550..14c41918b72f56ddfa462330e76ddc542badd3a0 100644 --- a/src/cats/dispersal/local_dispersal.c +++ b/src/cats/dispersal/local_dispersal.c @@ -29,6 +29,7 @@ #include "configuration/configuration.h" #include "data/cats_grid.h" #include "local_dispersal.h" +#include "inline.h" void cell_local_dispersal(struct cats_configuration *conf, struct cats_grid *grid, cats_dt_coord row, @@ -37,11 +38,12 @@ void cell_local_dispersal(struct cats_configuration *conf, struct cats_grid *gri const struct cats_dispersal *const dispersal = grid->dispersal; if (dispersal->local_dispersal <= 0.0) return; - float seeds = grid->seeds_produced[row][col]; + float seeds = get_produced_seeds(grid, row, col); cats_dt_seeds self = (float) (seeds * dispersal->local_dispersal); self = min_float(seeds, self); - grid->dispersed_seeds[row][col] += self; - grid->seeds_produced[row][col] -= self; + increase_dispersed_seeds(grid, row, col, self); + decrease_produced_seeds(grid, row, col, self); + } \ No newline at end of file diff --git a/src/cats/environment/environment.c b/src/cats/environment/environment.c index 0f85e76c9623f18e51cbf92d2eea08cf7fbbb382..6b44fecde2b8128428bd8c73b29d3b3020e7947c 100644 --- a/src/cats/environment/environment.c +++ b/src/cats/environment/environment.c @@ -38,6 +38,7 @@ #include "environment.h" #include "grids/gdal_load.h" #include "environment/environment_rasters.h" +#include "grids/dimensions.h" #ifdef USEMPI #include "mpi/mpi_save.h" @@ -69,10 +70,11 @@ void interpolate_environment(const struct cats_configuration *conf, const cats_dt_coord rows = environment->current.dimension.rows; const cats_dt_coord cols = environment->current.dimension.cols; - if (environment->start.dimension.rows != environment->end.dimension.rows - || environment->start.dimension.cols != environment->end.dimension.cols - || environment->start.dimension.rows != environment->current.dimension.rows - || environment->start.dimension.cols != environment->current.dimension.cols) { + bool matching_dimensions = cats_dimensions_match(&environment->start.dimension, &environment->end.dimension) + && + cats_dimensions_match(&environment->start.dimension, &environment->current.dimension); + + if (!matching_dimensions) { log_message(LOG_ERROR, "%s: dimension mismatch", __func__); log_message(LOG_ERROR, "environment (start): %d x %d", environment->start.dimension.rows, environment->start.dimension.cols); @@ -149,8 +151,9 @@ load_environment_raster(struct cats_configuration *conf, struct cats_environment } unload_environment_raster(raster); - raster->dimension.rows = conf->geometry.dimension.rows; - raster->dimension.cols = conf->geometry.dimension.cols; + + copy_cats_dimensions(&conf->geometry.dimension, &raster->dimension); + raster->interpolation_type = type; raster->environment_type = environment_type; if (raster->values == NULL) { diff --git a/src/cats/environment/environment_rasters.c b/src/cats/environment/environment_rasters.c index e7a3a12f79f9c8ae006bda529ad47e709005c439..2c2f9025798c1bdd8ac77b452bfe29a128ce36d6 100644 --- a/src/cats/environment/environment_rasters.c +++ b/src/cats/environment/environment_rasters.c @@ -27,6 +27,7 @@ #include "logging.h" #include "environment_rasters.h" #include "environment.h" +#include "grids/dimensions.h" void print_raster_quick_info(struct cats_environment_raster *gr) @@ -53,9 +54,8 @@ void create_raster_if_needed(struct cats_configuration *conf, struct cats_enviro log_message(LOG_INFO, "\tinitializing empty grid for <%s>", get_raster_type_name_specific(raster)); log_message(LOG_DEBUG, "%s: ALLOCATING NEW GRID NOW", __func__); raster->values = new_raw_2d_array_from_dimension(conf->geometry.dimension, sizeof(cats_dt_environment)); - raster->dimension.rows = conf->geometry.dimension.rows; - raster->dimension.cols = conf->geometry.dimension.cols; + copy_cats_dimensions(&conf->geometry.dimension, &raster->dimension); } diff --git a/src/cats/grids/cats_grid.c b/src/cats/grids/cats_grid.c index 8814d975d2f21948b7fa680b0318318436a7baee..b3edba612207830d1238ac09480daa84701def54 100644 --- a/src/cats/grids/cats_grid.c +++ b/src/cats/grids/cats_grid.c @@ -255,7 +255,7 @@ void cleanup_grid_seeds_and_juveniles(struct cats_grid *grid) for (cats_dt_coord col = 0; col < grid->dimension.cols; col++) { destroy_seed_structure(grid, row, col); } - free(grid->seed_bank[row]); + free(grid->seed_bank[row]); // clean-up [cleanup_grid_seeds_and_juveniles] } } @@ -266,7 +266,7 @@ void cleanup_grid_seeds_and_juveniles(struct cats_grid *grid) destroy_juveniles(grid, row, col); } - free(grid->juveniles[row]); + free(grid->juveniles[row]); // clean-up [cleanup_grid_seeds_and_juveniles] } } diff --git a/src/cats/grids/dimensions.c b/src/cats/grids/dimensions.c new file mode 100644 index 0000000000000000000000000000000000000000..78f9dc6b1510f29877f762b6ef52b1fea2a1be89 --- /dev/null +++ b/src/cats/grids/dimensions.c @@ -0,0 +1,17 @@ +#include "dimensions.h" + + +void copy_cats_dimensions(const struct cats_dimension *source, struct cats_dimension *destination) +{ + assert(source != NULL); + assert(destination != NULL); + destination->rows = source->rows; + destination->cols = source->cols; +} + + +bool cats_dimensions_match(const struct cats_dimension *dim1, const struct cats_dimension *dim2) +{ + if (dim1->rows == dim2->rows && dim1->cols == dim2->cols) return true; + return false; +} \ No newline at end of file diff --git a/src/cats/grids/dimensions.h b/src/cats/grids/dimensions.h new file mode 100644 index 0000000000000000000000000000000000000000..9b62aaf503b5a7ea5445cb12b185ab6a4414198e --- /dev/null +++ b/src/cats/grids/dimensions.h @@ -0,0 +1,23 @@ +#ifndef CATS_DIMENSIONS_H +#define CATS_DIMENSIONS_H + +#include "memory/arrays.h" +#include "assert.h" + + +static inline bool valid_coordinates(const struct cats_dimension *dim, cats_dt_coord row, cats_dt_coord col) +{ + assert(dim != NULL); + if (row < 0 || col < 0) return false; + if (row >= dim->rows || col >= dim->cols) return false; + return true; +} + + +void copy_cats_dimensions(const struct cats_dimension *source, struct cats_dimension *destination); + +bool cats_dimensions_match(const struct cats_dimension *dim1, const struct cats_dimension *dim2); + +bool valid_coordinates(const struct cats_dimension *dim, cats_dt_coord row, cats_dt_coord col); + +#endif //CATS_DIMENSIONS_H diff --git a/src/cats/grids/direct_access.c b/src/cats/grids/direct_access.c new file mode 100644 index 0000000000000000000000000000000000000000..cdb851962d4a98c16196a7e62f7767d1d8673b63 --- /dev/null +++ b/src/cats/grids/direct_access.c @@ -0,0 +1,28 @@ +#include <assert.h> +#include "direct_access.h" +#include "dimensions.h" + + +double load_input_2d_array_double(const struct cats_2d_array_double *raster, cats_dt_coord row, cats_dt_coord col) +{ + valid_coordinates(&raster->dimension, row, col); + return raster->data[row][col]; // getter [load_input2d_array_double] +} + +char load_input_2d_array_char(const struct cats_2d_array_char *raster, cats_dt_coord row, cats_dt_coord col) +{ + valid_coordinates(&raster->dimension, row, col); + return raster->data[row][col]; // getter [load_input_2d_array_char] +} + +cats_dt_environment load_input_environment_raster(struct cats_environment_raster *raster, cats_dt_coord row, cats_dt_coord col) +{ + valid_coordinates(&raster->dimension, row, col); + return raster->values[row][col]; // getter [load_input_environment_raster] +} + +void set_input_environment_raster(struct cats_environment_raster *raster, cats_dt_coord row, cats_dt_coord col, cats_dt_environment value) +{ + valid_coordinates(&raster->dimension, row, col); + raster->values[row][col] = value; // getter [set_input_environment_raster] +} \ No newline at end of file diff --git a/src/cats/grids/direct_access.h b/src/cats/grids/direct_access.h new file mode 100644 index 0000000000000000000000000000000000000000..147dab25442a3ee11f9b7eebae28dd2cbee7f3b4 --- /dev/null +++ b/src/cats/grids/direct_access.h @@ -0,0 +1,10 @@ +#ifndef CATS_DIRECT_ACCESS_H +#define CATS_DIRECT_ACCESS_H +#include "memory/arrays.h" +#include "environment/environment.h" + +double load_input_2d_array_double(const struct cats_2d_array_double *raster, cats_dt_coord row, cats_dt_coord col); +cats_dt_environment load_input_environment_raster(struct cats_environment_raster *raster, cats_dt_coord row, cats_dt_coord col); +void set_input_environment_raster(struct cats_environment_raster *raster, cats_dt_coord row, cats_dt_coord col, cats_dt_environment value); +char load_input_2d_array_char(const struct cats_2d_array_char *raster, cats_dt_coord row, cats_dt_coord col); +#endif //CATS_DIRECT_ACCESS_H diff --git a/src/cats/grids/gdal_save.c b/src/cats/grids/gdal_save.c index b6d25342bc7332ef4447fbbb0aa26d920a439d3b..6a2e0a244b11a08f903391cce702a10606134692 100644 --- a/src/cats/grids/gdal_save.c +++ b/src/cats/grids/gdal_save.c @@ -132,7 +132,7 @@ void *save_dispersed_seeds_to_gdal(struct cats_grid *grid, struct cats_configura const int32_t cols = grid->dimension.cols; for (cats_dt_coord row = 0; row < rows; row++) { for (cats_dt_coord col = 0; col < cols; col++) { - seeds[row][col] = grid->dispersed_seeds[row][col]; + seeds[row][col] = get_dispersed_seeds(grid, row, col); } } @@ -173,13 +173,13 @@ void *save_seeds_to_gdal(struct cats_grid *grid, struct cats_configuration *conf for (cats_dt_coord col = 0; col < cols; col++) { if (i > 0) { int year = i - 1; - if (grid->seed_bank[row][col]) { - seeds[row][col] = (int32_t) grid->seed_bank[row][col][year]; + if (seed_bank_exists(grid, row, col)) { + seeds[row][col] = (int32_t) get_seed_bank_seeds(grid, row, col, year); } else { seeds[row][col] = 0; } } else { - seeds[row][col] = (int32_t) grid->dispersed_seeds[row][col]; + seeds[row][col] = (int32_t) get_dispersed_seeds(grid, row, col); } } } @@ -221,11 +221,7 @@ void *save_juveniles_to_gdal(struct cats_grid *grid, struct cats_configuration * sizeof(int32_t));//new_int32t_grid(grid->rows, grid->cols); for (cats_dt_coord row = 0; row < rows; row++) { for (cats_dt_coord col = 0; col < cols; col++) { - if (grid->juveniles[row][col]) { - juvs[row][col] = grid->juveniles[row][col][i]; - } else { - juvs[row][col] = 0; - } + juvs[row][col] = get_juveniles(grid, row, col, i); } } struct cats_dimension dim = {.rows = rows, .cols = cols}; diff --git a/src/cats/grids/grid_converters.c b/src/cats/grids/grid_converters.c index b09dd2c32afda8bdbccf6599b83942e91f9db761..f76b82a9e0fc5f9b02fbfefe73d03246b10acdc9 100644 --- a/src/cats/grids/grid_converters.c +++ b/src/cats/grids/grid_converters.c @@ -33,6 +33,7 @@ #include "populations/population.h" #include "inline_population.h" #include "dispersal/dispersal.h" +#include "misc/cats_maths_inline.h" cats_dt_environment **convert_double_to_environment(const struct cats_2d_array_double *in_grid) @@ -43,7 +44,7 @@ cats_dt_environment **convert_double_to_environment(const struct cats_2d_array_d const cats_dt_coord cols = in_grid->dimension.cols; for (int32_t r = 0; r < rows; r++) { for (int32_t c = 0; c < cols; c++) { - array[r][c] = (float) in_grid->data[r][c]; + array[r][c] = (float) in_grid->data[r][c]; // converter [convert_double_to_environment] } } diff --git a/src/cats/grids/grid_setup.c b/src/cats/grids/grid_setup.c index e8b72b419bb9aae992449aa5422d05afa4e13941..3f879c20afa42ce1dc704d4a1c2a1870667337f9 100644 --- a/src/cats/grids/grid_setup.c +++ b/src/cats/grids/grid_setup.c @@ -53,10 +53,10 @@ void setup_grid_seed_structures(const struct cats_configuration *conf, struct ca grid->seed_bank = calloc_or_die(rows, sizeof(cats_dt_seeds **)); for (cats_dt_coord row = 0; row < rows; row++) { - grid->seed_bank[row] = calloc_or_die(cols, sizeof(cats_dt_seeds *)); + grid->seed_bank[row] = calloc_or_die(cols, sizeof(cats_dt_seeds *)); // initialisation [setup_grid_seed_structure] for (cats_dt_coord col = 0; col < cols; col++) { - grid->seed_bank[row][col] = NULL; + grid->seed_bank[row][col] = NULL; // initialisation [setup_grid_seed_structure] } } } @@ -98,10 +98,10 @@ void setup_grid_juvenile_structures_opt(struct cats_configuration *conf, struct grid->juveniles = calloc_or_die(grid->dimension.rows, sizeof(cats_dt_population **)); for (cats_dt_coord row = 0; row < grid->dimension.rows; row++) { - grid->juveniles[row] = calloc_or_die(grid->dimension.cols, sizeof(cats_dt_population *)); + grid->juveniles[row] = calloc_or_die(grid->dimension.cols, sizeof(cats_dt_population *)); // initialisation [setup_grid_juvenile_structures_opt] for (cats_dt_coord col = 0; col < grid->dimension.cols; col++) { - grid->juveniles[row][col] = NULL; + grid->juveniles[row][col] = NULL; // initialisation [setup_grid_juvenile_structures_opt] } } } diff --git a/src/cats/inline.h b/src/cats/inline.h index da78d7702595de8e57ce90e6454941d9b4b5c172..cb0f3b5c0a46255c77760fd78e1753426867c5ce 100644 --- a/src/cats/inline.h +++ b/src/cats/inline.h @@ -42,6 +42,25 @@ #include "inline_carrying_capacity.h" #include "inline_population.h" #include "inline_vital_ages.h" +#include "grids/dimensions.h" + +static inline bool valid_dispersed_seeds_grid(const struct cats_grid *grid, cats_dt_coord row) +{ + if (grid == NULL) return false; + if (grid->dispersed_seeds == NULL) return false; + if (grid->dispersed_seeds[row] == NULL) return false; // validator [valid_dispersed_seeds_grid] + return true; +} + + +static inline bool valid_produced_seed_grid(const struct cats_grid *grid, cats_dt_coord row) +{ + if (grid == NULL) return false; + if (grid->seeds_produced == NULL) return false; + if (grid->seeds_produced[row] == NULL) return false; // validator [valid_produced_seed_grid] + return true; +} + static inline cats_dt_environment @@ -49,11 +68,124 @@ get_suitability_from_env(const struct cats_environment *set, cats_dt_coord row, { assert(set->type == ENVIRONMENT_TYPE_SUITABILITY); assert(set->count == 1); - assert(row >= 0); - assert(col >= 0); - assert(row < set->environments[0]->current.dimension.rows); - assert(col < set->environments[0]->current.dimension.cols); - return set->environments[0]->current.values[row][col]; + assert(valid_coordinates(&set->environments[0]->current.dimension, row, col)); + return load_input_environment_raster(&set->environments[0]->current, row, col); +} + +static inline cats_dt_seeds +get_dispersed_seeds(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) +{ + assert(valid_coordinates(&grid->dimension, row, col)); + assert(valid_dispersed_seeds_grid(grid, row)); + return grid->dispersed_seeds[row][col]; // getter [get_dispersed_seeds] +} + +static inline void +set_dispersed_seeds(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, cats_dt_seeds seeds) +{ + assert(valid_coordinates(&grid->dimension, row, col)); + assert(valid_dispersed_seeds_grid(grid, row)); + assert(seeds >= 0); + grid->dispersed_seeds[row][col] = seeds; // setter [set_dispersed_seeds] +} + +static inline void +increase_dispersed_seeds(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, cats_dt_seeds by) +{ + assert(valid_coordinates(&grid->dimension, row, col)); + assert(valid_dispersed_seeds_grid(grid, row)); + assert(by >= 0); + grid->dispersed_seeds[row][col] += by; // setter [increase_dispersed_seeds] +} + +static inline void +decrease_dispersed_seeds(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, cats_dt_seeds by) +{ + assert(valid_coordinates(&grid->dimension, row, col)); + assert(valid_dispersed_seeds_grid(grid, row)); + assert(by >= 0); + grid->dispersed_seeds[row][col] -= by; // setter [decrease_dispersed_seeds] + assert(grid->dispersed_seeds[row][col] >= 0); // setter [decrease_dispersed_seeds] +} + + + +static inline cats_dt_seeds +get_produced_seeds(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) +{ + assert(valid_coordinates(&grid->dimension, row, col)); + assert(valid_produced_seed_grid(grid, row)); + return grid->seeds_produced[row][col]; // getter [get_produced_seeds] +} + +static inline bool valid_seed_bank_grid(const struct cats_grid *grid, cats_dt_coord row) +{ + if (grid == NULL || grid->seed_bank == NULL || grid->seed_bank[row] == NULL) return false; // validator [valid_seed_bank_grid] + return true; +} + +static inline bool seed_bank_exists(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) +{ + assert(valid_coordinates(&grid->dimension, row, col)); + assert(valid_seed_bank_grid(grid, row)); + return grid->seed_bank[row][col] != NULL; // validator [seed_bank_exists] +} + +static inline cats_dt_seeds get_seed_bank_seeds(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, int32_t year) +{ + assert(seed_bank_exists(grid, row, col)); + assert(year < get_vital_age(grid, VA_SEED_PERSISTENCE)); + assert(year >= 0); + return grid->seed_bank[row][col][year]; // getter [get_seed_bank_seeds] +} + +static inline void set_seed_bank_seeds(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, int32_t year, cats_dt_seeds seeds) +{ + assert(seed_bank_exists(grid, row, col)); + assert(year < get_vital_age(grid, VA_SEED_PERSISTENCE)); + assert(seeds >= 0.0f); + grid->seed_bank[row][col][year] = seeds; // setter [set_seed_bank_seeds] +} + + + +static inline void +set_produced_seeds(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, cats_dt_seeds seeds) +{ + assert(valid_coordinates(&grid->dimension, row, col)); + assert(valid_produced_seed_grid(grid, row)); + assert(seeds >= 0); + grid->seeds_produced[row][col] = seeds; // setter [set_produced_seeds] +} + +static inline void +increase_produced_seeds(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, cats_dt_seeds by) +{ + assert(valid_coordinates(&grid->dimension, row, col)); + assert(valid_produced_seed_grid(grid, row)); + assert(by > 0); + grid->seeds_produced[row][col] += by; // setter [increase_produced_seeds] +} + + +static inline void +decrease_produced_seeds(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, cats_dt_seeds by) +{ + assert(valid_coordinates(&grid->dimension, row, col)); + assert(valid_produced_seed_grid(grid, row)); + assert(by > 0); + grid->seeds_produced[row][col] -= by; // setter [decrease_produced_seeds] + assert(grid->seeds_produced[row][col] >= 0); // setter [decrease_produced_seeds] +} + + + +static inline void +set_suitability(struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, cats_dt_environment value) +{ + assert(value >= 0.0f); + assert(value <= 1.0f); + set_input_environment_raster(&grid->suitability->environments[0]->current, row, col, value); } @@ -171,13 +303,13 @@ static inline cats_dt_environment get_suitability(const struct cats_grid *grid, static inline double get_seed_sum(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) { assert(grid != NULL && grid->juveniles != NULL); - assert(row >= 0 && row < grid->dimension.rows); - assert(col >= 0 && col < grid->dimension.cols); + assert(valid_coordinates(&grid->dimension, row, col)); const int32_t max_sp = get_vital_age(grid, VA_SEED_PERSISTENCE); //grid->param.seed_persistence; - double sum = grid->dispersed_seeds[row][col]; - if (grid->seed_bank[row][col] == NULL) return sum; + double sum = get_dispersed_seeds(grid, row, col); + + if (!seed_bank_exists(grid, row, col)) return sum; for (int32_t i = 0; i < max_sp; i++) { - sum += grid->seed_bank[row][col][i]; + sum += get_seed_bank_seeds(grid, row, col, i); } return sum; } @@ -187,20 +319,16 @@ static inline cats_dt_population_sum get_juvenile_sum(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) { assert(grid != NULL && grid->juveniles != NULL); - assert(row >= 0 && row < grid->dimension.rows); - assert(col >= 0 && col < grid->dimension.cols); - assert(grid->juveniles[row] != NULL); + if (!juveniles_exist(grid, row, col)) return 0; - const cats_dt_population *juveniles = grid->juveniles[row][col]; - if (juveniles == NULL) return 0; + const cats_dt_population *juveniles = grid->juveniles[row][col]; // getter [get_juvenile_sum] cats_dt_population_sum juvenile_sum = 0; - const int32_t max_stage = - get_vital_age(grid, VA_AGE_OF_MATURITY_MAX) + 1; //grid->param.max_age_of_maturity + 1; + const int32_t max_stage = get_vital_age(grid, VA_AGE_OF_MATURITY_MAX) + 1; + for (int32_t i = 0; i < max_stage; i++) { - juvenile_sum += juveniles[i]; + juvenile_sum += juveniles[i]; // getter [get_juvenile_sum] } - return juvenile_sum; } diff --git a/src/cats/inline_carrying_capacity.h b/src/cats/inline_carrying_capacity.h index 9b4c42ceeed868d41220383216ec2fd98e1c70e0..c598758133c5d65cdfd8c5229bbe885ef724e512 100644 --- a/src/cats/inline_carrying_capacity.h +++ b/src/cats/inline_carrying_capacity.h @@ -36,6 +36,7 @@ #include "configuration/configuration.h" #include "plants/juveniles.h" #include "inline_vital_ages.h" +#include "inline_carrying_capacity.h" static inline cats_dt_rates juvenile_cc_multiplier(const struct cats_species_param *param, int32_t stage) diff --git a/src/cats/inline_overlays.h b/src/cats/inline_overlays.h index 519689e39cf39c53b519c1de0e5529f6948fc49e..5248ecb2a67bcae8df8a5badcd96b782e0b70df7 100644 --- a/src/cats/inline_overlays.h +++ b/src/cats/inline_overlays.h @@ -28,6 +28,7 @@ #include "assert.h" #include "overlays/overlays.h" #include "configuration/configuration.h" +#include "grids/direct_access.h" static inline bool @@ -35,21 +36,20 @@ cell_excluded_by_habitat(const struct cats_configuration *config, cats_dt_coord { if (!config->overlays.have_overlays) return false; if (!config->overlays.overlay[OL_HABITAT_TYPE_CC].enabled) return false; - - return (config->overlays.habitat_cc->data[row][col] == 0.0); + return (load_input_2d_array_double(config->overlays.habitat_cc, row, col) == 0.0); } - static inline bool cell_excluded_by_overlay(const struct cats_configuration *config, cats_dt_coord row, cats_dt_coord col) { assert(config != NULL); - if (config->overlays.have_overlays == false || config->overlays.overlay[OL_EXCLUSION].enabled == false) return false; + if (config->overlays.have_overlays == false || config->overlays.overlay[OL_EXCLUSION].enabled == false) + return false; assert(config->overlays.exclusion->data != NULL); - const char value = config->overlays.exclusion->data[row][col]; + const char value = load_input_2d_array_char(config->overlays.exclusion, row, col); switch (value) { // NOLINT(hicpp-multiway-paths-covered) case OL_EXCLUSION_NOT_EXCLUDED: @@ -63,5 +63,17 @@ cell_excluded_by_overlay(const struct cats_configuration *config, cats_dt_coord exit_cats(EXIT_FAILURE); } +static inline double get_overlay_habitat_cc_value(const struct cats_configuration *conf, cats_dt_coord row, cats_dt_coord col) +{ + assert(conf->overlays.overlay[OL_HABITAT_TYPE_CC].enabled); + return conf->overlays.habitat_cc->data[row][col]; // getter [get_overlay_habitat_cc_value] +} + +static inline double get_overlay_resource_value(const struct cats_configuration *conf, cats_dt_coord row, cats_dt_coord col) +{ + assert(conf->overlays.overlay[OL_RESOURCE].enabled); + return conf->overlays.resources->data[row][col]; // getter [get_overlay_resource_value] +} + #endif //CATS_INLINE_OVERLAYS_H diff --git a/src/cats/inline_population.h b/src/cats/inline_population.h index 933b3d0146be4077f0729cef783dc7e0df7a604b..f537dad855770c1e3312e9b06cdfee01d33cae7d 100644 --- a/src/cats/inline_population.h +++ b/src/cats/inline_population.h @@ -34,17 +34,56 @@ #include "inline_overlays.h" #include "populations/carrying_capacity.h" #include "populations/plant_juveniles.h" +#include "grids/dimensions.h" +#include "inline_vital_ages.h" + + +static inline bool valid_population_grid(const struct cats_grid *grid, cats_dt_coord row) +{ + if (grid && grid->population && grid->population[row]) return true; // validator [valid_population_grid] + return false; +} + +static inline bool valid_juvenile_grid(const struct cats_grid *grid, cats_dt_coord row) +{ + if (grid == NULL) return false; + if (grid->juveniles == NULL) return false; + if (grid->juveniles[row] == NULL) return false; // validator [valid_juvenile_grid] + return true; +} + + +static inline bool juveniles_exist(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) +{ + assert(valid_coordinates(&grid->dimension, row, col)); + assert(valid_juvenile_grid(grid, row)); + return grid->juveniles[row][col] != NULL; // validator [juveniles_exist] +} + +static inline cats_dt_population get_juveniles(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, int year) +{ + if (juveniles_exist(grid, row, col) == false) return 0; + assert(year < get_vital_age(grid, VA_AGE_OF_MATURITY_MAX) + 1); + // FIXME check year + return grid->juveniles[row][col][year]; // getter [get_juveniles] +} + +static inline void set_juveniles(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, int year, cats_dt_population juv) +{ + assert(juveniles_exist(grid, row, col)); + assert(year < get_vital_age(grid, VA_AGE_OF_MATURITY_MAX) + 1); + assert(juv >= 0); + grid->juveniles[row][col][year] = juv; // setter [set_juveniles] +} static inline cats_dt_population get_adult_population(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) { - assert(grid != NULL && grid->population != NULL); - assert(row >= 0 && row < grid->dimension.rows); - assert(col >= 0 && col < grid->dimension.cols); - assert(grid->population[row] != NULL); - assert(grid->population[row][col] >= 0); - return grid->population[row][col]; // getter + assert(valid_population_grid(grid, row)); + assert(valid_coordinates(&grid->dimension, row, col)); + assert(grid->population[row][col] >= 0); // getter [get_adult_population] + return grid->population[row][col]; // getter [get_adult_population] } @@ -81,20 +120,12 @@ static inline cats_dt_population reduce_population_by(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, cats_dt_population to_reduce) { assert(to_reduce >= 0); - assert(grid != NULL); - assert(grid->population != NULL); - assert(row < grid->dimension.rows); - assert(col < grid->dimension.cols); - assert(row >= 0); - assert(col >= 0); - assert(grid->population[row] != NULL); - - //cats_dt_population cc = get_carrying_capacity(grid, row, col); + assert(valid_population_grid(grid, row)); + assert(valid_coordinates(&grid->dimension, row, col)); + cats_dt_population pop = get_adult_population(grid, row, col); if (to_reduce > pop) { to_reduce = pop; } - - - grid->population[row][col] = pop - to_reduce;// setter; + grid->population[row][col] = pop - to_reduce; // setter [reduce_population_by] return to_reduce; } @@ -104,9 +135,8 @@ static inline void set_population_ignore_cc(const struct cats_grid *grid, const cats_dt_coord row, const cats_dt_coord col, const cats_dt_population pop) { - assert(grid != NULL && grid->population != NULL); - assert(row >= 0 && row < grid->dimension.rows && col >= 0 && col < grid->dimension.cols); - assert(grid->population[row] != NULL); + assert(valid_population_grid(grid, row)); + assert(valid_coordinates(&grid->dimension, row, col)); if (pop > CATS_MAX_POPULATION || pop < 0.0) { log_message(LOG_ERROR, "%s: population %d out of allowed population range [0, %d].", @@ -114,7 +144,7 @@ set_population_ignore_cc(const struct cats_grid *grid, const cats_dt_coord row, exit(EXIT_FAILURE); } - if (pop >= 0) grid->population[row][col] = pop; // setter ignore cc; + if (pop >= 0) grid->population[row][col] = pop; // setter [set_population_ignore_cc] } @@ -169,19 +199,14 @@ static inline cats_dt_population get_population_ts(const struct cats_grid *grid, const cats_dt_coord row, const cats_dt_coord col, const int threshold, int64_t *unfiltered) { - assert(grid != NULL); - assert(grid->population != NULL); - assert(row < grid->dimension.rows); - assert(col < grid->dimension.cols); - assert(row >= 0); - assert(col >= 0); - assert(grid->population[row] != NULL); + assert(valid_population_grid(grid, row)); + assert(valid_coordinates(&grid->dimension, row, col)); - cats_dt_population tmp = grid->population[row][col]; // getter + cats_dt_population tmp = grid->population[row][col]; // getter [get_population_ts] if (unfiltered) *unfiltered = tmp; - if (grid->population[row][col] >= threshold) { + if (grid->population[row][col] >= threshold) { // getter [get_population_ts] return tmp; } else { return 0; diff --git a/src/cats/inline_vital_rates.h b/src/cats/inline_vital_rates.h index 65b7194198802dea774ea8fa429ac19e70888a20..38de70314b495f0347900c03817c55cf843e6f78 100644 --- a/src/cats/inline_vital_rates.h +++ b/src/cats/inline_vital_rates.h @@ -29,6 +29,7 @@ #include "data/cats_grid.h" #include "vital_rates/glm_functions.h" #include "vital_rates/direct_functions.h" +#include "inline.h" static inline cats_dt_rates get_vital_rate_maximum(const struct cats_vital_rate *vr) diff --git a/src/cats/misc/debug.c b/src/cats/misc/debug.c index 7141dd8bb5dce5a2f3dce4f2fd4a0490a789d67f..487140b58696b6feb281fcfc7984a82e1deeef61 100644 --- a/src/cats/misc/debug.c +++ b/src/cats/misc/debug.c @@ -28,6 +28,12 @@ #include <memory/cats_memory.h> +static inline cats_dt_population debug_get_juveniles(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, int year) +{ + if (grid->juveniles[row][col] == NULL) return 0; // debug [debug_get_juveniles] + return grid->juveniles[row][col][year]; // debug [debug_get_juveniles] +} + void debug_juveniles(const struct cats_grid *grid, const struct cats_configuration *conf, cats_dt_coord row, cats_dt_coord col, const char *action) @@ -38,11 +44,7 @@ debug_juveniles(const struct cats_grid *grid, const struct cats_configuration *c const int32_t max_age_of_maturity = get_vital_age(grid, VA_AGE_OF_MATURITY_MAX); for (int32_t i = 0; i < max_age_of_maturity + 1; i++) { - if (grid->juveniles[row][col]) { - fprintf(cats_debug.misc_debug_file, ",%d", grid->juveniles[row][col][i]); - } else { - fprintf(cats_debug.misc_debug_file, ",%d", 0); - } + fprintf(cats_debug.misc_debug_file, ",%d", debug_get_juveniles(grid, row, col, i)); } fprintf(cats_debug.misc_debug_file, "\n"); @@ -55,11 +57,11 @@ void debug_seeds(struct cats_grid *grid, const struct cats_configuration *conf, { if (row == cats_debug.misc_debug_coords.row && col == cats_debug.misc_debug_coords.col) { fprintf(cats_debug.misc_debug_file, "%d,%d,%s,seeds,%f", grid->id, conf->time.year_current, action, - grid->dispersed_seeds[row][col]); + get_dispersed_seeds(grid, row, col)); const int32_t seed_persistence = get_vital_age(grid, VA_SEED_PERSISTENCE); for (int32_t i = 0; i < seed_persistence; i++) { - if (grid->seed_bank[row][col]) { - fprintf(cats_debug.misc_debug_file, ",%f", grid->seed_bank[row][col][i]); + if (seed_bank_exists(grid, row, col)) { + fprintf(cats_debug.misc_debug_file, ",%f", get_seed_bank_seeds(grid, row, col, i)); } else { fprintf(cats_debug.misc_debug_file, ",%d", 0); } diff --git a/src/cats/mpi/mpi_save.c b/src/cats/mpi/mpi_save.c index 3af93daf2c104e5026338d21f5bfb548d758b1c2..c667d1e47b8900063762cf57f571997cbc9f466e 100644 --- a/src/cats/mpi/mpi_save.c +++ b/src/cats/mpi/mpi_save.c @@ -35,6 +35,7 @@ #include "memory/cats_memory.h" #include "mpi/mpi_grid_helpers.h" #include "paths/output_paths.h" +#include "inline.h" /* @@ -80,7 +81,7 @@ void *save_seeds0_to_gdal_mpi(struct cats_grid *grid, struct cats_configuration for (int r = 0; r < grid->dimension.rows; r++) { for (int c = 0; c < grid->dimension.cols; c++) { - seeds0[r * grid->dimension.cols + c] = grid->dispersed_seeds[r][c]; + seeds0[r * grid->dimension.cols + c] = get_dispersed_seeds(grid, r, c); } } diff --git a/src/cats/mpi/mpi_seeds.c b/src/cats/mpi/mpi_seeds.c index 9b3f1531155c10a551b73c13c1a92aec08a8f6ae..89bb25d4ec3abb6cc3cdc1fd4f1f5d5a4253ee6c 100644 --- a/src/cats/mpi/mpi_seeds.c +++ b/src/cats/mpi/mpi_seeds.c @@ -29,6 +29,7 @@ #include "mpi_grid_helpers.h" #include "memory/raw_arrays.h" #include "mpi_seeds.h" +#include "inline.h" void send_and_receive_dispersed_seeds_mpi(struct cats_grid *grid, struct cats_configuration *conf) @@ -143,7 +144,7 @@ void add_seeds0_from_below(const struct cats_configuration *conf, struct cats_gr for (int r = 0; r < radius; r++) { for (int c = 0; c < cols; c++) { - grid->dispersed_seeds[start_row + r][c] += from_below[r * cols + c]; + increase_dispersed_seeds(grid, start_row + r, c, (cats_dt_seeds) from_below[r * cols + c]); } } } @@ -159,7 +160,7 @@ void add_seeds0_from_above(const struct cats_configuration *conf, struct cats_gr for (int r = 0; r < radius; r++) { for (int c = 0; c < cols; c++) { - grid->dispersed_seeds[r][c] += from_above[r * cols + c]; + increase_dispersed_seeds(grid, r, c, (cats_dt_seeds) from_above[r * cols + c]); } } } \ No newline at end of file diff --git a/src/cats/overlays/overlay_exclusion.c b/src/cats/overlays/overlay_exclusion.c index f68b8691b9e9215d4b0b9552f13962cffe458b2b..d54fafce3f3869a7f082efaf4822ecda36616377 100644 --- a/src/cats/overlays/overlay_exclusion.c +++ b/src/cats/overlays/overlay_exclusion.c @@ -110,17 +110,19 @@ struct cats_2d_array_char *translate_exclusion(const struct cats_2d_array_double for (cats_dt_coord row = 0; row < rows; row++) { for (cats_dt_coord col = 0; col < cols; col++) { - const int32_t val = (int32_t) round(data->data[row][col]); + const int32_t in_val = (int32_t) round(data->data[row][col]); // converter [translate_exclusion] + char out_val; - if (val == 0) { - result->data[row][col] = OL_EXCLUSION_NOT_EXCLUDED; + if (in_val == 0) { + out_val = OL_EXCLUSION_NOT_EXCLUDED; } else if (isnan(data->data[row][col])) { - result->data[row][col] = OL_EXCLUSION_NAN; + out_val = OL_EXCLUSION_NAN; count += 1; } else { - result->data[row][col] = OL_EXCLUSION_EXCLUDED; + out_val = OL_EXCLUSION_EXCLUDED; count += 1; } + result->data[row][col] = out_val; // converter [translate_exclusion] } } diff --git a/src/cats/overlays/overlay_habitat_type_cc.c b/src/cats/overlays/overlay_habitat_type_cc.c index e98c258f98d2059292ecac0f7667e78c9d4697c2..d922c15bffc385f0262dcf03c88b1819023e1f76 100644 --- a/src/cats/overlays/overlay_habitat_type_cc.c +++ b/src/cats/overlays/overlay_habitat_type_cc.c @@ -30,6 +30,7 @@ #include "cats_csv/cats_csv.h" #include "logging.h" #include "memory/cats_memory.h" +#include "grids/direct_access.h" void cleanup_habitat_layer_cc_aux(void **data) @@ -128,14 +129,31 @@ struct cats_2d_array_double *translate_habitat(const struct cats_2d_array_double double value = data->data[row][col]; if (isnan(value)) { - result->data[row][col] = 0.0; + result->data[row][col] = 0.0; // converter [translate_habitat] } else { int32_t val = (int32_t) round(value); double multi = get_habitat_cc_multiplier(habitat_info, val); - result->data[row][col] = multi; + result->data[row][col] = multi; // converter [translate_habitat] } } } return result; } + + +double get_overlay_cc_multiplier(const struct cats_configuration *conf, cats_dt_coord row, cats_dt_coord col) +{ + + if (!conf->overlays.overlay[OL_HABITAT_TYPE_CC].enabled) { + return 1.0; + } + + double multiplier = load_input_2d_array_double(conf->overlays.habitat_cc, row, col); + + if (multiplier <= 0.0) { + return 0.0; + } + + return multiplier; +} \ No newline at end of file diff --git a/src/cats/overlays/overlay_habitat_type_cc.h b/src/cats/overlays/overlay_habitat_type_cc.h index c355afb307db70983df92cf9dcddae94467986d7..89b2997ed9e4fff2e56c14fa9ab1472814ac8220 100644 --- a/src/cats/overlays/overlay_habitat_type_cc.h +++ b/src/cats/overlays/overlay_habitat_type_cc.h @@ -26,6 +26,7 @@ #include <stdint.h> #include "../../memory/arrays.h" +#include "configuration/configuration.h" #define MAX_HABITAT_TYPE_CODES 1024 @@ -43,4 +44,6 @@ struct cats_2d_array_double *translate_habitat(const struct cats_2d_array_double struct habitat_layer_cc_aux *load_habitat_layer_cc_aux(const char *csv_file, double default_value); +double get_overlay_cc_multiplier(const struct cats_configuration *conf, cats_dt_coord row, cats_dt_coord col); + #endif //CATS_OVERLAY_HABITAT_TYPE_CC_H diff --git a/src/cats/overlays/overlay_resources.c b/src/cats/overlays/overlay_resources.c index 64a171f856e369a527a9a5d3a804722574f8f4d9..63798ac18e2d2c03a0d4886178f06c05d7026f45 100644 --- a/src/cats/overlays/overlay_resources.c +++ b/src/cats/overlays/overlay_resources.c @@ -1,4 +1,3 @@ -#include <assert.h> #include <math.h> #include "overlay_resources.h" #include "memory/arrays.h" @@ -14,15 +13,15 @@ struct cats_2d_array_double *translate_resources(const struct cats_2d_array_doub for (cats_dt_coord row = 0; row < rows; row++) { for (cats_dt_coord col = 0; col < cols; col++) { - double value = data->data[row][col]; + double in_value = data->data[row][col]; // converter [translate_resources] + double out_value; - if (isnan(value)) { - result->data[row][col] = 0.0; + if (isnan(in_value)) { + out_value = 0.0; } else { - - if (value <0 ) value = 0; - result->data[row][col] = value; - } + if (in_value < 0 ) in_value = 0; + out_value = in_value; + } result->data[row][col] = out_value; // converter [translate_resources] } } diff --git a/src/cats/plants/inter_period.c b/src/cats/plants/inter_period.c index 2c6ae48e2ed7137932db41b984ac1e986272d448..c8d4eeb68857495ce3e1593b777dd559e075f797 100644 --- a/src/cats/plants/inter_period.c +++ b/src/cats/plants/inter_period.c @@ -35,53 +35,63 @@ void inter_period_survival_seeds(struct cats_grid *grid, struct cats_configurati cats_dt_coord col, struct cats_thread_info *ts) { // if we have no seeds, we are done - if (grid->dispersed_seeds[row][col] == 0.0 && grid->seed_bank[row][col] == NULL) return; + cats_dt_seeds disp_seeds = get_dispersed_seeds(grid, row, col); + if (disp_seeds == 0.0 && seed_bank_exists(grid, row, col) == false) return; cats_dt_rates seed_survival_rate; + bool have_seed_bank = seed_bank_exists(grid, row, col); const struct cats_vital_rate *rate_link_surv = get_default_vital_rate(grid, VR_SEED_SURVIVAL); seed_survival_rate = calculate_rate(rate_link_surv, NAN, &grid->param, grid, row, col, NULL); - if (grid->dispersed_seeds[row][col] > 0) { - cats_dt_seeds dying_0 = poisson_seeds_capped(ts->rng, grid->dispersed_seeds[row][col] * + if (disp_seeds > 0) { + cats_dt_seeds dying_0 = poisson_seeds_capped(ts->rng, disp_seeds * (1.0 - seed_survival_rate), - grid->dispersed_seeds[row][col]); + disp_seeds); - grid->dispersed_seeds[row][col] = grid->dispersed_seeds[row][col] - dying_0; + disp_seeds = disp_seeds - dying_0; + set_dispersed_seeds(grid, row, col, disp_seeds); - if (grid->dispersed_seeds[row][col] > 0.0 && grid->seed_bank[row][col] == NULL) { + + if (disp_seeds > 0.0 && have_seed_bank == false) { create_seed_structure(grid, row, col); } } - if (grid->dispersed_seeds[row][col] == 0.0 && grid->seed_bank[row][col] == NULL) return; + + if (disp_seeds == 0.0 && have_seed_bank == false) return; + + if (have_seed_bank == false) create_seed_structure(grid, row, col); const int32_t seed_persistence = get_vital_age(grid, VA_SEED_PERSISTENCE); - for (int32_t stage = 0; stage < seed_persistence - 0; stage++) { // -1 + for (int32_t stage = 0; stage < seed_persistence; stage++) { + cats_dt_seeds seeds_i = get_seed_bank_seeds(grid, row, col, stage); cats_dt_seeds dying = poisson_seeds_capped(ts->rng, - grid->seed_bank[row][col][stage] * + seeds_i * (1.0 - seed_survival_rate), - grid->seed_bank[row][col][stage]); - grid->seed_bank[row][col][stage] = grid->seed_bank[row][col][stage] - dying; + seeds_i); + set_seed_bank_seeds(grid, row, col, stage, seeds_i - dying); } - for (int32_t k = seed_persistence - 1; k >= 1; k--) { // -2 - grid->seed_bank[row][col][k] = grid->seed_bank[row][col][k - 1]; + for (int32_t k = seed_persistence - 1; k >= 1; k--) { + cats_dt_seeds s = get_seed_bank_seeds(grid, row, col, k - 1); + set_seed_bank_seeds(grid, row, col, k, s); } - grid->seed_bank[row][col][0] = grid->dispersed_seeds[row][col]; - assert(grid->seed_bank[row][col][0] >= 0.0); - grid->dispersed_seeds[row][col] = 0.0f; + set_seed_bank_seeds(grid, row, col, 0, get_dispersed_seeds(grid, row, col)); + assert(get_seed_bank_seeds(grid, row, col, 0) >= 0); + set_dispersed_seeds(grid, row, col, 0.0f); } void inter_period_survival_juveniles(struct cats_grid *grid, struct cats_configuration *conf, cats_dt_coord row, cats_dt_coord col, struct cats_thread_info *ts) { - if (grid->juveniles[row][col] == NULL) return; + if (juveniles_exist(grid, row, col) == false) return; + const int32_t mat_max = get_vital_age(grid, VA_AGE_OF_MATURITY_MAX); const int32_t mat_min = get_vital_age(grid, VA_AGE_OF_MATURITY_MIN); @@ -94,30 +104,34 @@ void inter_period_survival_juveniles(struct cats_grid *grid, struct cats_configu germination_to_adult_survival, &grid->param); for (int32_t i = 0; i <= mat_max; i++) { + cats_dt_rates modified_juvenile_transition_rate = age_modified_juvenile_survival_rate( juvenile_transition_rate, i, mat_min, mat_max); + cats_dt_rates juvenile_mortality = (1.0 - modified_juvenile_transition_rate); assert(juvenile_mortality >= 0 && juvenile_mortality <= 1.0); - assert(grid->juveniles[row][col][i] >= 0); + cats_dt_population juveniles_i = get_juveniles(grid, row, col, i); + assert(juveniles_i >= 0); + cats_dt_population dying = poisson_population_capped(ts->rng, - (cats_dt_rates) grid->juveniles[row][col][i] * + (cats_dt_rates) juveniles_i * juvenile_mortality, - grid->juveniles[row][col][i]); + juveniles_i); + set_juveniles(grid, row, col, i, juveniles_i - dying); - grid->juveniles[row][col][i] = grid->juveniles[row][col][i] - dying; - assert(grid->juveniles[row][col][i] >= 0); + assert(get_juveniles(grid, row, col, i) >= 0); } // advance juvenile stage (after transition rates have been applied) for (int32_t stage = mat_max; stage > 0; stage--) { - grid->juveniles[row][col][stage] = grid->juveniles[row][col][stage - 1]; + cats_dt_population juveniles_younger = get_juveniles(grid, row, col, stage - 1); + set_juveniles(grid, row, col, stage, juveniles_younger); } // youngest stage now empty - grid->juveniles[row][col][0] = 0; - + set_juveniles(grid, row, col, 0, 0); } diff --git a/src/cats/plants/juveniles.c b/src/cats/plants/juveniles.c index 010876337f050000f6bd887f89553e0c4cf72d7c..a83e1e6e88cf8b2e243cd0e5fe6014f8ef6bd162 100644 --- a/src/cats/plants/juveniles.c +++ b/src/cats/plants/juveniles.c @@ -54,21 +54,23 @@ juvenile_adult_transition(struct cats_grid *g, cats_dt_coord row, cats_dt_coord // once the cell is full, we stop and juveniles have to wait at least until // the next year to have a chance to mature + // FIXME check max age! for (int32_t age = mat_max; age >= mat_min; age--) { - cats_dt_population juveniles = g->juveniles[row][col][age]; + cats_dt_population juveniles = get_juveniles(g, row, col, age); if (juveniles == 0) continue; // the cell_maturation rate depends on the age -- the older the juvenile, the higher the probability to mature cats_dt_rates maturation_rate = age_specific_maturation_rate(age, juvenile_survival_rate, mat_min, mat_max); + cats_dt_population newly_matured = poisson_population_capped(ts->rng, (cats_dt_rates) juveniles * maturation_rate, juveniles); newly_matured = min_population_t(newly_matured, space_left); + set_juveniles(g, row, col, age, juveniles - newly_matured); - g->juveniles[row][col][age] = juveniles - newly_matured; - assert(g->juveniles[row][col][age] >= 0); + assert(get_juveniles(g, row, col, age) >= 0); newly_matured_sum += newly_matured; space_left -= newly_matured; @@ -100,8 +102,7 @@ cell_maturation(struct cats_grid *grid, struct cats_thread_info *ts, cats_dt_coo #else if (__builtin_expect(cell_excluded_by_overlay(conf, row, col), false)) { return 0; } #endif - - if (grid->juveniles[row][col] == NULL) return 0; + if (juveniles_exist(grid, row, col) == false) return 0; const int32_t mat_max = get_vital_age(grid, VA_AGE_OF_MATURITY_MAX); const int32_t mat_min = get_vital_age(grid, VA_AGE_OF_MATURITY_MIN); diff --git a/src/cats/plants/long_range_dispersal.c b/src/cats/plants/long_range_dispersal.c index 61684296e691e5cb1bc273a2d496162d201c26de..eb6d86d0e93fc0db87c9400dcd74a3f5ba911b0d 100644 --- a/src/cats/plants/long_range_dispersal.c +++ b/src/cats/plants/long_range_dispersal.c @@ -87,7 +87,7 @@ void disperse_long_range(struct cats_grid *grid) } // disperse seeds and reduce number of local seeds - grid->dispersed_seeds[trow][tcol] += (cats_dt_seeds) package; + increase_dispersed_seeds(grid, trow, tcol, (cats_dt_seeds) package); grid->seeds_produced[row][col] -= (cats_dt_seeds) package; // stop if no more seeds are left to distribute diff --git a/src/cats/plants/plant_rates.c b/src/cats/plants/plant_rates.c index 4c4275395650d1410f9fdba9c37eed3708af74d5..16c881ea4f5d59aa207db297e161bf0669f0b600 100644 --- a/src/cats/plants/plant_rates.c +++ b/src/cats/plants/plant_rates.c @@ -29,6 +29,7 @@ #include "data/cats_grid.h" #include "inline_population.h" #include "populations/population.h" +#include "misc/cats_maths_inline.h" cats_dt_rates get_pollination_probability(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col, diff --git a/src/cats/plants/plant_structures.c b/src/cats/plants/plant_structures.c index d75d8f482c6ce09d617fcd346c464115bb2f1865..3218cdfcc5cdfe722403939b43b30984601f4316 100644 --- a/src/cats/plants/plant_structures.c +++ b/src/cats/plants/plant_structures.c @@ -29,6 +29,7 @@ #include "seeds.h" #include "inline_population.h" #include "populations/population.h" +#include "inline_vital_ages.h" #include <memory/cats_memory.h> @@ -39,50 +40,42 @@ void destroy_plant_cell(struct cats_grid *grid, const cats_dt_coord row, const c assert(col >= 0 && col < grid->dimension.cols); destroy_juveniles(grid, row, col); destroy_seed_structure(grid, row, col); - grid->dispersed_seeds[row][col] = 0.0f; - grid->seeds_produced[row][col] = 0.0f; + set_dispersed_seeds(grid, row, col, 0.0f); + set_produced_seeds(grid, row, col, 0.0f); set_population_ignore_cc(grid, row, col, 0); } void create_seed_structure(const struct cats_grid *grid, const cats_dt_coord row, const cats_dt_coord col) { - assert(grid != NULL); - if (grid->seed_bank[row][col] != NULL) return; + + assert(valid_seed_bank_grid(grid, row)); + if (seed_bank_exists(grid, row, col) == true) return; const int32_t seed_persistence = get_vital_age(grid, VA_SEED_PERSISTENCE); - const int32_t size = seed_persistence - 0; // - 1); + const int32_t size = seed_persistence; if (size <= 0) return; // no seed persistence - assert(grid->seed_bank != NULL); - assert(row >= 0 && row < grid->dimension.rows); - assert(col >= 0 && col < grid->dimension.cols); - assert(grid->seed_bank[row][col] == NULL); - - grid->seed_bank[row][col] = calloc_or_die(size, sizeof(cats_dt_seeds)); - - + grid->seed_bank[row][col] = calloc_or_die(size, sizeof(cats_dt_seeds)); // initialisation [create_seed_structure] } void destroy_seed_structure(const struct cats_grid *grid, const cats_dt_coord row, const cats_dt_coord col) { assert(grid != NULL); - assert(grid->seed_bank != NULL); - assert(row >= 0 && row < grid->dimension.rows); - assert(col >= 0 && col < grid->dimension.cols); + const int32_t seed_persistence = get_vital_age(grid, VA_SEED_PERSISTENCE); - const int size = (seed_persistence - 0); // -1 + const int size = (seed_persistence - 0); // do we actually have seeds in the ground? - if (size <= 0 || grid->seed_bank[row][col] == NULL) return; + if (size <= 0 || seed_bank_exists(grid, row, col) == false) return; - for (uint32_t i = 0; i < size; i++) { - grid->seed_bank[row][col][i] = 0.0f; + for (int32_t i = 0; i < size; i++) { + set_seed_bank_seeds(grid, row, col, i, 0.0f); // clean-up [destroy_seed_structure] } - free(grid->seed_bank[row][col]); - grid->seed_bank[row][col] = NULL; + free(grid->seed_bank[row][col]); // clean-up [destroy_seed_structure] + grid->seed_bank[row][col] = NULL; // clean-up [destroy_seed_structure] } @@ -92,19 +85,18 @@ inline void create_juvenile_structure_if_needed(struct cats_grid *grid, const cats_dt_coord row, const cats_dt_coord col) { - if (grid->juveniles[row][col]) return; + if (juveniles_exist(grid, row, col)) return; const int32_t max_age_of_maturity = get_vital_age(grid, VA_AGE_OF_MATURITY_MAX); - - grid->juveniles[row][col] = create_juvenile_structure(max_age_of_maturity); + grid->juveniles[row][col] = create_juvenile_structure(max_age_of_maturity); // initialisation [create_juvenile_structure_if_needed] } void destroy_juveniles(const struct cats_grid *grid, const cats_dt_coord row, const cats_dt_coord col) { - assert(grid != NULL); - assert(row >= 0 && row < grid->dimension.rows); - assert(col >= 0 && col < grid->dimension.cols); + assert(grid != NULL); // clean-up [destroy_juveniles] + assert(row >= 0 && row < grid->dimension.rows); // clean-up [destroy_juveniles] + assert(col >= 0 && col < grid->dimension.cols); // clean-up [destroy_juveniles] assert(grid->juveniles != NULL); @@ -113,10 +105,10 @@ void destroy_juveniles(const struct cats_grid *grid, const cats_dt_coord row, co const int32_t stages = max_age_of_maturity + 1; assert(stages >= 0); - if (grid->juveniles[row] && grid->juveniles[row][col]) { - memset(grid->juveniles[row][col], 0, stages * sizeof(cats_dt_population)); - free(grid->juveniles[row][col]); - grid->juveniles[row][col] = NULL; + if (grid->juveniles[row] && grid->juveniles[row][col]) { // clean-up [destroy_juveniles] + memset(grid->juveniles[row][col], 0, stages * sizeof(cats_dt_population)); // clean-up [destroy_juveniles] + free(grid->juveniles[row][col]); // clean-up [destroy_juveniles] + grid->juveniles[row][col] = NULL; // clean-up [destroy_juveniles] } } diff --git a/src/cats/plants/seeds.c b/src/cats/plants/seeds.c index 797e98fc5733883ff0b8a98f14a3b288d012d36f..0cd63b9ecbb845deea358249cdf1d8487261294d 100644 --- a/src/cats/plants/seeds.c +++ b/src/cats/plants/seeds.c @@ -33,6 +33,8 @@ #include "inline_overlays.h" #include "inline_population.h" #include "populations/population.h" +#include "misc/cats_maths_inline.h" +#include "inline_vital_ages.h" #ifdef USEMPI #include "mpi/mpi_cats.h" @@ -85,9 +87,8 @@ void cell_seed_production(struct cats_grid *grid, cats_dt_coord row, cats_dt_coo assert(grid->seeds_produced != NULL); // ensure that no seeds are left-over in the cell - assert(grid->seeds_produced[row][col] == 0.0); - - grid->seeds_produced[row][col] = 0.0f; + assert(get_produced_seeds(grid, row, col) == 0.0f); + set_produced_seeds(grid, row, col, 0.0f); // no population -> no seeds cats_dt_rates N = get_adult_population(grid, row, col); @@ -122,10 +123,11 @@ void cell_seed_production(struct cats_grid *grid, cats_dt_coord row, cats_dt_coo const cats_dt_rates total_seeds = N * flowering_frequency * seed_yield * pollination_rate; assert(total_seeds >= 0.0); + cats_dt_seeds seeds = poisson_seeds(ts->rng, total_seeds); // we don't cap + set_produced_seeds(grid, row, col, seeds); - grid->seeds_produced[row][col] = poisson_seeds(ts->rng, total_seeds); // we don't cap - if (grid->seeds_produced[row][col] > 0) ts->stats[grid->id].stats[CS_SEEDS_PRODUCED] += 1; + if (seeds > 0) ts->stats[grid->id].stats[CS_SEEDS_PRODUCED] += 1; cats_dt_rates hapaxanth = grid->param.hapaxanthy; @@ -165,17 +167,19 @@ germinate_seeds_in_ground(struct cats_thread_info *ts, struct cats_grid *grid, c for (int32_t k = 0; k < max_k; k++) { - cats_dt_population germinated = poisson(ts->rng, grid->seed_bank[row][col][k] * germination_rate); + cats_dt_seeds seeds_k = get_seed_bank_seeds(grid, row, col, k); + cats_dt_population germinated = poisson(ts->rng, seeds_k * germination_rate); if (germinated <= 0) continue; add_germinated(ts, grid, row, col, germinated, K_class); - grid->seed_bank[row][col][k] = max_float(grid->seed_bank[row][col][k] - (float) germinated, 0.0f); - + seeds_k = max_float(seeds_k - (float) germinated, 0.0f); + set_seed_bank_seeds(grid, row, col, k, seeds_k); } } - +/* +// no longer used static inline void germinate_seeds0(struct cats_grid *grid, const cats_dt_coord row, const cats_dt_coord col, struct cats_thread_info *ts, const cats_dt_rates germination_rate) @@ -195,16 +199,16 @@ germinate_seeds0(struct cats_grid *grid, const cats_dt_coord row, const cats_dt_ grid->dispersed_seeds[row][col] = max_float(grid->dispersed_seeds[row][col] - (float) germinated, 0.0f); // fixme max_seeds } - +*/ inline static bool have_seeds_in_cell(const struct cats_grid *grid, const struct cats_configuration *conf, cats_dt_coord row, cats_dt_coord col, const struct cats_thread_info *ts) { - assert(grid->dispersed_seeds != NULL); - assert(grid->dispersed_seeds[row][col] >= 0); - return (grid->seed_bank[row][col] != NULL || grid->dispersed_seeds[row][col] > 0.5); + cats_dt_seeds d_seeds = get_dispersed_seeds(grid, row, col); + assert(d_seeds >= 0); + return (seed_bank_exists(grid, row, col) || d_seeds > 0.5); } @@ -240,21 +244,22 @@ cell_post_process_seeds(struct cats_grid *grid, struct cats_configuration *conf, struct cats_thread_info *ts) { assert(grid != NULL); - assert(grid->dispersed_seeds != NULL); - assert(grid->dispersed_seeds[row][col] >= 0); + assert(valid_dispersed_seeds_grid(grid, row)); + + cats_dt_seeds disp_seeds = get_dispersed_seeds(grid, row, col); + assert(disp_seeds >= 0); + if (disp_seeds == 0.0f) return; if (cell_excluded_by_overlay(conf, row, col)) { - grid->dispersed_seeds[row][col] = 0; + set_dispersed_seeds(grid, row, col, 0.0f); return; } - if (grid->dispersed_seeds[row][col] == 0.0) return; - const int32_t id = grid->id; ts->stats[id].stats[CS_SEEDS_BEFORE_POISSON] += 1; cats_dt_seeds seeds_after_poisson = poisson_seeds(ts->rng, - grid->dispersed_seeds[row][col]); /* IMPORTANT stochasticity required */ - grid->dispersed_seeds[row][col] = seeds_after_poisson; + disp_seeds); /* IMPORTANT stochasticity required */ + set_dispersed_seeds(grid, row, col, seeds_after_poisson); if (seeds_after_poisson > 0) ts->stats[id].stats[CS_SEEDS_AFTER_POISSON] += 1; } diff --git a/src/cats/populations/carrying_capacity.c b/src/cats/populations/carrying_capacity.c index a285ee516d61783de0b9c63054980ef7692b0f29..6d9ef8c8d30d7f7e4c5c38a82ea272a65ddf5dc4 100644 --- a/src/cats/populations/carrying_capacity.c +++ b/src/cats/populations/carrying_capacity.c @@ -28,6 +28,7 @@ #include "plants/juveniles.h" #include "inline_overlays.h" #include "inline_population.h" +#include "overlays/overlay_habitat_type_cc.h" void @@ -50,22 +51,18 @@ get_carrying_capacity_all_classes(struct cats_grid **grids, cats_dt_coord row, c cats_dt_population get_carrying_capacity(const struct cats_grid *grid, cats_dt_coord row, cats_dt_coord col) { - assert(grid->conf != NULL); + assert(grid != NULL && grid->conf != NULL); const struct cats_configuration *conf = grid->conf; // if we have an exclusion mask AND it is set the CC is 0 if (cell_excluded_by_overlay(conf, row, col)) { return 0; } - double multiplier = 1.0; + double multiplier = get_overlay_cc_multiplier(conf, row, col); + if (multiplier <= 0.0) { return 0; } - if (conf->overlays.overlay[OL_HABITAT_TYPE_CC].enabled) { - multiplier *= conf->overlays.habitat_cc->data[row][col]; - if (multiplier <= 0.0) { return 0; } - } cats_dt_rates cc; - const struct cats_vital_rate *link = &grid->param.carrying_capacity; cc = calculate_rate(link, NAN, &grid->param, grid, row, col, NULL); @@ -91,7 +88,7 @@ cell_apply_carrying_capacity(struct cats_grid *grid, struct cats_thread_info *ts if (grid->param.default_demographics) { cats_dt_population N = get_adult_population(grid, row, col); - if (N == 0 && grid->juveniles[row][col] == NULL) return; + if (N == 0 && juveniles_exist(grid, row, col) == false) return; if (N > 0) ts->stats[grid_id].stats[CS_POPULATED_BEFORE_CC] += 1; cats_dt_population K_A = get_adult_carrying_capacity_from_cc(grid, K_tot); diff --git a/src/cats/populations/plant_juveniles.c b/src/cats/populations/plant_juveniles.c index fd9e70975c8f4174b70fd27627fd40bc6c803922..1f41a8532394afe0aa5b3b2d9793a5c2f73ac687 100644 --- a/src/cats/populations/plant_juveniles.c +++ b/src/cats/populations/plant_juveniles.c @@ -29,6 +29,8 @@ #include "data/cats_grid.h" #include "inline_vital_rates.h" #include "memory/cats_memory.h" +#include "inline_vital_ages.h" +#include "inline_carrying_capacity.h" void setup_plant_juvenile_weights(struct cats_species_param *param) @@ -85,12 +87,12 @@ scale_down_juveniles2(struct cats_grid *grid, cats_dt_coord row, cats_dt_coord c assert(grid != NULL && grid->juveniles != NULL); assert(row >= 0 && row < grid->dimension.rows); assert(col >= 0 && col < grid->dimension.cols); - assert(grid->juveniles[row] != NULL); + assert(juveniles_exist(grid, row, col)); assert(juvenile_cc > 0); - if (grid->juveniles[row][col] == NULL || weighted_juvenile_sum == 0) return; + if (juveniles_exist(grid, row, col) == false || weighted_juvenile_sum == 0) return; if (weighted_juvenile_sum < juvenile_cc) return; - const int32_t mat_max = get_vital_age(grid, VA_AGE_OF_MATURITY_MAX); // grid->param.max_age_of_maturity; + const int32_t mat_max = get_vital_age(grid, VA_AGE_OF_MATURITY_MAX); cats_dt_rates factor = 1.0; for (int32_t i = 0; i < mat_max + 1; i++) { @@ -119,8 +121,8 @@ scale_down_juveniles2(struct cats_grid *grid, cats_dt_coord row, cats_dt_coord c log_message(LOG_ERROR, "%s: weighted juvenile sum > juvenile CC", __func__); log_message(LOG_RAW, "sum: %"PRId64", cc %"PRId64"\n", weighted_juvenile_sum, juvenile_cc); log_message(LOG_RAW, "factor %f\n", (double) factor); - for (int32_t i = 0; i < mat_max + 1 - 1; i++) { - log_message(LOG_RAW, "juvenile stage %d: %d - multiplier %f\n", i, + for (int32_t i = 0; i < mat_max + 1; i++) { + log_message(LOG_RAW, "juvenile stage %d: %d - multiplier %f\n", i, grid->juveniles[row][col][i], (double) juvenile_cc_multiplier(&grid->param, i)); } @@ -135,7 +137,7 @@ void cell_apply_juvenile_cc(struct cats_grid *g, cats_dt_coord row, cats_dt_coord col, cats_dt_population K_tot, cats_dt_population N) { if (g->juveniles == NULL) return; - if (g->juveniles[row][col] == NULL) return; + if (juveniles_exist(g, row, col) == false) return; cats_dt_population K_J = K_tot - N; diff --git a/src/cats/populations/population.c b/src/cats/populations/population.c index e5143ea6200926e355d00f7725c0ad969b6d75b9..c6509c1443e9b9ae74f228e48b4f8ae68d8843db 100644 --- a/src/cats/populations/population.c +++ b/src/cats/populations/population.c @@ -56,14 +56,15 @@ void adjust_juvenile_populations(struct cats_configuration *conf, struct cats_gr //cats_dt_rates w = juvenile_cc_multiplier(&grid->param, i); cats_dt_rates w = grid->param.juvenile_cc_weights[i]; cats_dt_rates juv_pop = (cats_dt_rates) N * multi / w; + if (juv_pop > CATS_MAX_POPULATION) { juv_pop = CATS_MAX_POPULATION / 2.0; } - grid->juveniles[r][c][i] = round_population_safe(juv_pop); + + set_juveniles(grid, r, c, i, round_population_safe(juv_pop)); } } } - } @@ -153,7 +154,8 @@ void prune_initial_population_under_threshold(struct cats_configuration *conf, s } } - log_message(LOG_INFO, "Species '%s': pruned %"PRId64" of %"PRId64" initial populations (suitability < threshold), %"PRId64" remaining", + log_message(LOG_INFO, + "Species '%s': pruned %"PRId64" of %"PRId64" initial populations (suitability < threshold), %"PRId64" remaining", grid->param.species_name, destroyed, populated, populated - destroyed); } diff --git a/src/cats/vital_rates/direct_functions.c b/src/cats/vital_rates/direct_functions.c index a42104895c550d4012c0474668673a3686756d6f..1599ad06032ffd8999fc3961cf20062d57de502e 100644 --- a/src/cats/vital_rates/direct_functions.c +++ b/src/cats/vital_rates/direct_functions.c @@ -45,7 +45,8 @@ cats_dt_rates get_direct_rate(const struct cats_vital_rate *rate_info, log_message(LOG_ERROR, "%s: wrong environment set type for set '%s'", __func__, set->name); exit(EXIT_FAILURE); } - cats_dt_rates rate = set->environments[0]->current.values[row][col] * rate_info->environment_multiplier; + cats_dt_environment value = load_input_environment_raster(&set->environments[0]->current, row, col); + cats_dt_rates rate = value * rate_info->environment_multiplier; if (isnan(rate)) return 0.0f; cats_dt_rates dens_multiplier = density_multiplier(density_type, N, K, rate_info->density_ts); diff --git a/src/cats/vital_rates/glm_functions.c b/src/cats/vital_rates/glm_functions.c index 60a9c3eb41b65f7260eb928c1ed5748c584337a7..0be349a10ada9234c3265b03c01e19d4af8bd782 100644 --- a/src/cats/vital_rates/glm_functions.c +++ b/src/cats/vital_rates/glm_functions.c @@ -45,13 +45,13 @@ cats_dt_rates get_glm(const struct cats_vital_rate *rate_info, if (set->glm.type == GLM_QUADRATIC) { for (int32_t i = 0; i < set->count; i++) { - const cats_dt_rates predictor = set->environments[i]->current.values[row][col]; + const cats_dt_rates predictor = load_input_environment_raster(&set->environments[i]->current, row, col); result += predictor * set->glm.linear[i] + predictor * predictor * set->glm.quadratic[i]; } } else if (set->glm.type == GLM_LINEAR) { for (int32_t i = 0; i < set->count; i++) { - const cats_dt_rates predictor = set->environments[i]->current.values[row][col]; + const cats_dt_rates predictor = load_input_environment_raster(&set->environments[i]->current, row, col); result += predictor * set->glm.linear[i]; } } else { diff --git a/src/cats_csv/cats_csv.c b/src/cats_csv/cats_csv.c index 676cf3275f533ff6b74c9773cd751f49d1613eef..57b45d97b5cda9d96e3d36fca009a240739dfb12 100644 --- a/src/cats_csv/cats_csv.c +++ b/src/cats_csv/cats_csv.c @@ -89,8 +89,8 @@ void csv_free(struct cats_csv **csv) if (this->data[row] == NULL) continue; for (int32_t col = 0; col < this->column_count; col++) { - free(this->data[row][col]); - this->data[row][col] = NULL; + free(this->data[row][col]); // clean-up, non-spatial [csv_free] + this->data[row][col] = NULL; // clean-up, non-spatial [csv_free] } free(this->data[row]); @@ -142,7 +142,7 @@ char *csv_get_value_field_name(struct cats_csv *csv, int32_t row, const char *fi exit(EXIT_FAILURE); } - return csv->data[row][field_idx]; + return csv->data[row][field_idx]; // getter, non-spatial [csv_get_value_field_name] } @@ -164,7 +164,7 @@ char *csv_get_value_field_idx(struct cats_csv *csv, int32_t row, int32_t field_i exit(EXIT_FAILURE); } - return csv->data[row][field_idx]; + return csv->data[row][field_idx]; // getter, non-spatial [csv_get_value_field_idx] } @@ -242,8 +242,7 @@ void csv_add_row(struct cats_csv *csv, char *line) csv->data[row] = malloc_or_die_trace(fields * sizeof(char *), __func__); for (int32_t i = 0; i < csv->column_count; i++) { - csv->data[row][i] = strdup(data->string[i]); - + csv->data[row][i] = strdup(data->string[i]); // initialisation, non-spatial [csv_add_row] } free_string_array(&data); 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 7448a98e88ae635efa25c5f45229521b8a3bc69b..fd67848d076b8c0f7e8b9bcdcd9371a0b69604e8 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; const int64_t stat_id_deposits = module_conf->stat_ids[BF_RANDOM_WALK_DEPOSIT_COUNT]; @@ -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,8 +95,9 @@ 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); increase_custom_stat(ts->stats, stat_id_deposits, 1); + if (debug_rw) { 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, eggs_to_deposit, eggs_left); @@ -175,7 +178,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 f0fd931e1d6cd4581717cb8d16f4fe061e0e90ad..116c98f346888edeee7bf9787c2801524909afaf 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,36 +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) < suit_ts) { - 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 cf0d8fc6f2cb2f74e58a4e5898da3eb9f922303a..9e8bc727191cd541e83307666282f894576711c4 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); @@ -92,12 +93,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 f0e0690b6ba94ee09c85b27f24d36a23ebd88853..a2654ed81834797d52489fc246cc25b2a609063c 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; @@ -107,10 +110,11 @@ 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); } @@ -136,21 +140,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 @@ -167,7 +170,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