From ce26bdaf8dc3658bde3aed663a9d46011dde4666 Mon Sep 17 00:00:00 2001
From: Andreas Gattringer <andreas.gattringer@univie.ac.at>
Date: Thu, 27 Jul 2023 11:34:15 +0200
Subject: [PATCH] cats: no longer directly access seed data structures, use new
 getter/setter functions instead

---
 .../actions/process_inter_period_survival.c   |   6 +-
 src/cats/actions/process_seed_dispersal.c     |   9 +-
 src/cats/dispersal/dispersal.c                |   3 +-
 src/cats/dispersal/local_dispersal.c          |   8 +-
 src/cats/grids/cats_grid.c                    |   2 +-
 src/cats/grids/gdal_save.c                    |   6 +-
 src/cats/grids/grid_setup.c                   |   2 +-
 src/cats/inline.h                             | 109 ++++++++++++++++--
 src/cats/misc/debug.c                         |   6 +-
 src/cats/mpi/mpi_save.c                       |   3 +-
 src/cats/mpi/mpi_seeds.c                      |   5 +-
 src/cats/plants/inter_period.c                |  41 ++++---
 src/cats/plants/long_range_dispersal.c        |   2 +-
 src/cats/plants/plant_structures.c            |  36 +++---
 src/cats/plants/seeds.c                       |  43 +++----
 15 files changed, 192 insertions(+), 89 deletions(-)

diff --git a/src/cats/actions/process_inter_period_survival.c b/src/cats/actions/process_inter_period_survival.c
index 479385a..0f6d050 100644
--- a/src/cats/actions/process_inter_period_survival.c
+++ b/src/cats/actions/process_inter_period_survival.c
@@ -57,10 +57,10 @@ 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);
 
diff --git a/src/cats/actions/process_seed_dispersal.c b/src/cats/actions/process_seed_dispersal.c
index 8157c95..ab47e31 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/dispersal/dispersal.c b/src/cats/dispersal/dispersal.c
index 938c362..4f13f4a 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 c91fd54..14c4191 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/grids/cats_grid.c b/src/cats/grids/cats_grid.c
index 8814d97..3ddb38e 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]
                 }
         }
 
diff --git a/src/cats/grids/gdal_save.c b/src/cats/grids/gdal_save.c
index ba02526..89d05a6 100644
--- a/src/cats/grids/gdal_save.c
+++ b/src/cats/grids/gdal_save.c
@@ -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);
                                 }
                         }
                 }
diff --git a/src/cats/grids/grid_setup.c b/src/cats/grids/grid_setup.c
index 5c31dcd..899ce48 100644
--- a/src/cats/grids/grid_setup.c
+++ b/src/cats/grids/grid_setup.c
@@ -53,7 +53,7 @@ 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;  // initialisation [setup_grid_seed_structure]
diff --git a/src/cats/inline.h b/src/cats/inline.h
index 5c17dc4..fe3ae80 100644
--- a/src/cats/inline.h
+++ b/src/cats/inline.h
@@ -44,14 +44,15 @@
 #include "inline_vital_ages.h"
 #include "grids/dimensions.h"
 
-static inline bool valid_dispersed_seed_grid(const struct cats_grid *grid, cats_dt_coord row)
+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_population_grid]
+        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;
@@ -75,18 +76,109 @@ 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_seed_grid(grid, row));
-        return grid->dispersed_seeds[row][col];  // get [get_dispersed_seeds]
+        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];  // get [get_produced_seeds]
+        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)
@@ -213,10 +305,11 @@ static inline double get_seed_sum(const struct cats_grid *grid, cats_dt_coord ro
         assert(grid != NULL && grid->juveniles != NULL);
         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;
 }
diff --git a/src/cats/misc/debug.c b/src/cats/misc/debug.c
index 4900cc3..9683654 100644
--- a/src/cats/misc/debug.c
+++ b/src/cats/misc/debug.c
@@ -57,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]);  // debug [debug_seeds]
+                        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]) {  // debug [debug_seeds]
-                                fprintf(cats_debug.misc_debug_file, ",%f", grid->seed_bank[row][col][i]); // debug [debug_seeds]
+                        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 3af93da..c667d1e 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 9b3f153..89bb25d 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/plants/inter_period.c b/src/cats/plants/inter_period.c
index 2c6ae48..267c288 100644
--- a/src/cats/plants/inter_period.c
+++ b/src/cats/plants/inter_period.c
@@ -35,46 +35,55 @@ 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);
 }
 
 
diff --git a/src/cats/plants/long_range_dispersal.c b/src/cats/plants/long_range_dispersal.c
index 6168429..eb6d86d 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_structures.c b/src/cats/plants/plant_structures.c
index 8d1378c..cd36a39 100644
--- a/src/cats/plants/plant_structures.c
+++ b/src/cats/plants/plant_structures.c
@@ -40,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]
 }
 
 
diff --git a/src/cats/plants/seeds.c b/src/cats/plants/seeds.c
index c4cb44d..0cd63b9 100644
--- a/src/cats/plants/seeds.c
+++ b/src/cats/plants/seeds.c
@@ -87,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);
@@ -124,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;
 
@@ -167,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)
@@ -197,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);
 }
 
 
@@ -242,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;
 }
-- 
GitLab