From 2bad1c92f97484a1bd32b8d760b78ea55650cd54 Mon Sep 17 00:00:00 2001
From: Andreas Gattringer <gattringera@a772-cvl-ws23.biodiv.univie.ac.at>
Date: Wed, 8 Feb 2023 12:40:39 +0100
Subject: [PATCH] fixes for loadable modules

---
 src/cats/actions/setup_actions.c              | 41 +++++++++++++++++--
 src/cats/actions/setup_actions.h              | 12 +++++-
 src/cats/cats.c                               |  8 ++++
 .../load_configuration_species_params.c       |  5 ++-
 src/cats/grids/cats_grid.c                    | 22 +++++++---
 src/cats/modules/load_module.c                |  2 +-
 src/cats/stats/write_stats.c                  |  1 +
 src/cats/vital_rates/default_vital_rates.c    | 11 +++--
 src/cats/vital_rates/setup_rates.c            |  2 +-
 src/cats/vital_rates/setup_rates.h            |  4 --
 src/cats/vital_rates/vital_rates.h            |  1 +
 11 files changed, 88 insertions(+), 21 deletions(-)

diff --git a/src/cats/actions/setup_actions.c b/src/cats/actions/setup_actions.c
index 478dc9c..5902def 100644
--- a/src/cats/actions/setup_actions.c
+++ b/src/cats/actions/setup_actions.c
@@ -52,7 +52,7 @@ const char *ACTION_DEFAULT = "_default";
 void add_default_actions(struct cats_configuration *conf)
 {
         assert(conf != NULL);
-        register_default_functions(conf);
+        //register_default_action_functions(conf);
         log_message(LOG_INFO, "setting up default actions");
 
         append_action(conf, action_grid_stats_reset, ALL_STAGES, "statistics reset", ACTION_ALWAYS);
@@ -158,6 +158,41 @@ append_action(struct cats_configuration *conf, action_function action, enum cats
         return conf->cycle.num_actions;
 }
 
+void list_actions_full(struct cats_configuration *conf)
+{
+        log_message(LOG_INFO, "Action functions: %d", conf->action_functions.count);
+        for (int32_t i = 0; i < conf->action_functions.count; i++) {
+                log_message(LOG_INFO, "%d: %s %p ", i, conf->action_functions.names[i],
+                            conf->action_functions.functions[i]);
+        }
+}
+
+
+action_function get_action_by_name(struct cats_configuration *conf, const char *name)
+{
+        for (int32_t i = 0; i < conf->action_functions.count; i++) {
+                if (!strcmp(conf->action_functions.names[i], name)) return conf->action_functions.functions[i];
+        }
+        return NULL;
+}
+
+int32_t
+append_action_by_name(struct cats_configuration *conf, const char *action_name, enum cats_simulation_stages when,
+                      const char *name, const char *module_name)
+{
+        int32_t n = conf->cycle.num_actions;
+        conf->cycle.actions = realloc_or_die(conf->cycle.actions, (n + 1) * sizeof(struct cats_action));
+        conf->cycle.num_actions++;
+        action_function action = get_action_by_name(conf, action_name);
+        if (action == NULL) {
+                log_message(LOG_ERROR, "%s: could not find action '%s'", __func__, action_name);
+                exit_cats(EXIT_FAILURE);
+        }
+        add_action_at(conf, n, action, when, name, module_name);
+
+        return conf->cycle.num_actions;
+}
+
 
 void shift_action_functions_down_by_one(struct cats_configuration *conf, int32_t from)
 {
@@ -258,7 +293,7 @@ bool action_is_registered(const struct cats_configuration *conf, const action_fu
         const struct action_function_registry *registry = &conf->action_functions;
 
         for (int32_t i = 0; i < registry->count; i++) {
-                if (registry->functions[i] == function) return true;
+                if (*(registry->functions[i]) == function) return true;
         }
 
         return false;
@@ -266,7 +301,7 @@ bool action_is_registered(const struct cats_configuration *conf, const action_fu
 }
 
 
-void register_default_functions(struct cats_configuration *conf)
+void register_default_action_functions(struct cats_configuration *conf)
 {
 
         register_action_function(conf, action_grid_stats_reset, "action_reset_grid_stats", "resetting stats");
diff --git a/src/cats/actions/setup_actions.h b/src/cats/actions/setup_actions.h
index 6712074..242c474 100644
--- a/src/cats/actions/setup_actions.h
+++ b/src/cats/actions/setup_actions.h
@@ -41,7 +41,7 @@ int32_t append_action(struct cats_configuration *conf, action_function action, e
 action_function get_action_function(const struct cats_configuration *conf, const char *name);
 
 
-void register_default_functions(struct cats_configuration *conf);
+void register_default_action_functions(struct cats_configuration *conf);
 
 int32_t
 add_action_after_function(struct cats_configuration *conf, action_function function, enum cats_simulation_stages when,
@@ -54,4 +54,14 @@ void replace_function(struct cats_configuration *conf, action_function function,
 
 void cleanup_action_functions(struct action_function_registry *registry);
 
+void list_actions(const struct cats_configuration *conf);
+
+void list_actions_full(struct cats_configuration *conf);
+
+void register_action_function(struct cats_configuration *conf, action_function function, const char *name,
+                              const char *message);
+
+int32_t append_action_by_name(struct cats_configuration *conf, const char *action_name, enum cats_simulation_stages when,
+                      const char *name, const char *module_name);
+
 #endif //CATS_SETUP_ACTIONS_H
diff --git a/src/cats/cats.c b/src/cats/cats.c
index be52637..9cbc75a 100644
--- a/src/cats/cats.c
+++ b/src/cats/cats.c
@@ -163,6 +163,13 @@ void load_modules(struct cats_configuration *conf)
 
                         }
 
+
+                                printf("%s: %d\n", __func__, j);
+                                if (p->module_data[j].load_species_param_function) {
+                                        p->module_data[j].load_species_param_function(conf, conf->ini, p->species_config_section, p);
+                                }
+
+
                 }
 
         }
@@ -177,6 +184,7 @@ struct cats_configuration *load_main_configuration(const struct program_options
         setup_directories(conf);
         post_process_configuration(conf);
         //print_config_summary(conf);
+        register_default_action_functions(conf);
 
 
         load_modules(conf);
diff --git a/src/cats/configuration/load_configuration_species_params.c b/src/cats/configuration/load_configuration_species_params.c
index 4ec6390..6480603 100644
--- a/src/cats/configuration/load_configuration_species_params.c
+++ b/src/cats/configuration/load_configuration_species_params.c
@@ -101,7 +101,9 @@ void load_conf_vital_rate(struct cats_vital_rate *vr, struct cats_configuration
         char *vr_name = vr->name;
         char *vital_rate_maximum = compound_string(vr_name, "maximum", " ");
 
-        bool req = vr->preset.have_maximum;
+        bool req = !vr->preset.have_maximum;
+        printf("%s: %s required %d\n", __func__, vr->name, req);
+        if (vr == &p->carrying_capacity) req = true;
         bool have_max = load_conf_value(req, ini, species_section, vital_rate_maximum, &vr->max_rate);
         if (vr->is_integer_quantity) {
                 vr->max_rate = roundl(vr->max_rate);
@@ -278,6 +280,7 @@ void load_config_species_parameter(struct cats_configuration *conf, struct cats_
 
 
         for (int32_t i = 0; i < conf->modules.count; i++) {
+                printf("%s: %d\n", __func__, i);
                 if (p->module_data[i].load_species_param_function) {
                         p->module_data[i].load_species_param_function(conf, ini, species_section, p);
                 }
diff --git a/src/cats/grids/cats_grid.c b/src/cats/grids/cats_grid.c
index 413161a..292eb16 100644
--- a/src/cats/grids/cats_grid.c
+++ b/src/cats/grids/cats_grid.c
@@ -251,17 +251,27 @@ void cleanup_grid_seeds_and_juveniles(struct cats_grid *grid)
 
         free_grid(&grid->seeds_produced, grid->dimension.rows);
         free_grid(&grid->dispersed_seeds, grid->dimension.rows);
+        if (grid->seed_bank) {
+                for (cats_dt_coord row = 0; row < grid->dimension.rows; row++) {
+                        for (cats_dt_coord col = 0; col < grid->dimension.cols; col++) {
+                                destroy_seed_structure(grid, row, col);
+                        }
 
-        for (cats_dt_coord row = 0; row < grid->dimension.rows; row++) {
-                for (cats_dt_coord col = 0; col < grid->dimension.cols; col++) {
-                        destroy_seed_structure(grid, row, col);
-                        destroy_juveniles(grid, row, col);
+                        free(grid->juveniles[row]);
                 }
+        }
+
+        if (grid->seed_bank) {
+                for (cats_dt_coord row = 0; row < grid->dimension.rows; row++) {
+                        for (cats_dt_coord col = 0; col < grid->dimension.cols; col++) {
+                                destroy_juveniles(grid, row, col);
+                        }
 
-                free(grid->seed_bank[row]);
-                free(grid->juveniles[row]);
+                        free(grid->juveniles[row]);
+                }
         }
 
+
         free(grid->seed_bank);
         free(grid->juveniles);
         free(grid->seeds_produced);
diff --git a/src/cats/modules/load_module.c b/src/cats/modules/load_module.c
index 65bc4cb..ad1f8c2 100644
--- a/src/cats/modules/load_module.c
+++ b/src/cats/modules/load_module.c
@@ -164,7 +164,7 @@ void register_module_vital_rate(struct cats_configuration *conf, struct cats_vit
         m->vital_rate_required = realloc_or_die(m->vital_rate_required, sizeof(bool) * (vr_count + 1));
         m->vr[vr_count] = vr;
         m->vital_rate_name[vr_count] = strdup(name);
-
+        vr->is_carrying_capacity = false;
 
         strncpy(vr->name, name, MAX_VITAL_NAME_LEN + 1);
 
diff --git a/src/cats/stats/write_stats.c b/src/cats/stats/write_stats.c
index 11844db..b4e440d 100644
--- a/src/cats/stats/write_stats.c
+++ b/src/cats/stats/write_stats.c
@@ -189,6 +189,7 @@ void write_grid_stats(struct cats_configuration *conf, struct cats_grid *grid, b
 
         for (int32_t module_id = 0; module_id < conf->modules.count; module_id++) {
                 struct string_array *module_stats = add_module_stats(conf, grid, header, module_id);
+                if (module_stats == NULL) continue;
                 write_to_file(file, module_stats, ",");
                 if (conf->modules.module[module_id].stats_header == NULL) {
                         conf->modules.module[module_id].stats_header = copy_string_array(module_stats);
diff --git a/src/cats/vital_rates/default_vital_rates.c b/src/cats/vital_rates/default_vital_rates.c
index 83b6de1..270c657 100644
--- a/src/cats/vital_rates/default_vital_rates.c
+++ b/src/cats/vital_rates/default_vital_rates.c
@@ -285,12 +285,15 @@ void postprocess_vital_rates(struct cats_configuration *conf)
                 post_process_vital_rate(conf, &param->carrying_capacity, set, param);
 
 
-                for (enum cats_vital_rate_id vr_idx = VR_MIN + 1; vr_idx < VR_MAX; vr_idx++) {
-                        struct cats_vital_rate *vr = &param->vital_rates[vr_idx];
-                        vr->default_rate_id = vr_idx;
-                        post_process_vital_rate(conf, vr, set, param);
+                if (param->demographic_module == NULL) {
+                        for (enum cats_vital_rate_id vr_idx = VR_MIN + 1; vr_idx < VR_MAX; vr_idx++) {
+                                struct cats_vital_rate *vr = &param->vital_rates[vr_idx];
+                                vr->default_rate_id = vr_idx;
+                                post_process_vital_rate(conf, vr, set, param);
+                        }
                 }
 
+
                 for (int32_t i = 0; i < conf->modules.count; i++) {
                         for (int32_t j = 0; j < param->module_data[i].vital_rate_count; j++) {
                                 post_process_vital_rate(conf, param->module_data[i].vr[j], set, param);
diff --git a/src/cats/vital_rates/setup_rates.c b/src/cats/vital_rates/setup_rates.c
index 9bdace8..2f167f5 100644
--- a/src/cats/vital_rates/setup_rates.c
+++ b/src/cats/vital_rates/setup_rates.c
@@ -113,7 +113,7 @@ void set_vital_density(struct cats_vital_rate *vital, enum cats_density_dependen
 {
         assert(vital != NULL);
         if (vital->is_carrying_capacity && density != NO_DENSITY_DEP) {
-                log_message(LOG_ERROR, "%s: carrying capacity may never depend on population density", __func__);
+                log_message(LOG_ERROR, "%s (%s): carrying capacity may never depend on population density", __func__, vital->name);
                 exit_cats(EXIT_FAILURE);
         }
         vital->density = density;
diff --git a/src/cats/vital_rates/setup_rates.h b/src/cats/vital_rates/setup_rates.h
index f480919..f700b88 100644
--- a/src/cats/vital_rates/setup_rates.h
+++ b/src/cats/vital_rates/setup_rates.h
@@ -33,10 +33,6 @@ void set_vital_rate_suitability_cutoff_hint(struct cats_vital_rate *vital,
 
 void set_vital_density_ts(struct cats_vital_rate *vital, cats_dt_rates ts);
 
-void set_vital_rate(struct cats_vital_rate *vital, const char *name, cats_dt_rates max_rate, cats_dt_rates cutoff,
-                    struct cats_environment *set, enum cats_density_dependence density,
-                    const struct cats_species_param *param);
-
 void set_vital_rate_name(struct cats_vital_rate *vital, const char *name);
 
 int32_t setup_default_links(struct cats_vital_rate_hybrid_function *vital_dependency_registry);
diff --git a/src/cats/vital_rates/vital_rates.h b/src/cats/vital_rates/vital_rates.h
index 21d9cc0..aa96909 100644
--- a/src/cats/vital_rates/vital_rates.h
+++ b/src/cats/vital_rates/vital_rates.h
@@ -26,6 +26,7 @@
 #define CATS_VITAL_RATES_H
 
 #include "data/cats_datatypes.h"
+#include "defaults.h"
 
 struct cats_species_param;
 struct cats_grid;
-- 
GitLab