Skip to content

Commit

Permalink
Make code run with "vegetation establishment" activated
Browse files Browse the repository at this point in the history
- addressing #336

- note: "vegetation establishment" functionality must be activated and output turned on (see #336 for more details)

- "ERROR: Input/estab.in : Layers requested (estab_lyrs) > (# transpiration layers=0)." was produced because code previously tested `estab_lyrs` before `SW_Site.n_transp_lyrs[]` was initialized

-> this commit
* creates new `SW_VES_init_run()` to initialize vegetation establishment parameters of each species by `_spp_init()` and checked by `_sanity_check()` -- which now are called after `SW_SIT_init_run()` that initializes soil parameters (to fix above error message); previously, they were erroneously called by `SW_VegEstab_construct()`, i.e., before soil parameters were initialized
* struct `SW_VEGESTAB_INFO` gains new element `vegType` to encode to which vegetation type a species belongs; this is required to correctly check validity of `estab_lyrs` (previous code was from a time before `SOILWAT2` handled multiple vegetation types simultaneously)
* accordingly, species input files with establishment parameters gain one new input line to provide associated vegetation type, and `_read_spp()` is updated to read in value of `vegType`
* `_sanity_check()` now checks that `vegType` is implemented; now correctly checks `estab_lyrs` against `SW_Site.n_transp_lyrs[]` of the associated vegetation type; and error messages now include species name
* `SW_VegEstab_construct()` now allocates memory for `SW_VegEstab.p_oagg[eSW_Year]->days` (which is de-allocated by `SW_VES_deconstruct()` which previously errored because it was previously erroneously never allocated)
  • Loading branch information
dschlaep committed Jan 9, 2023
1 parent 436bfeb commit 087242a
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 53 deletions.
2 changes: 1 addition & 1 deletion SW_Control.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void SW_CTL_init_run(void) {
SW_PET_init_run();
SW_SKY_init_run();
SW_SIT_init_run();
// SW_VES_init_run() not needed
SW_VES_init_run(); // must run after `SW_SIT_init_run()`
SW_VPD_init_run();
SW_FLW_init_run();
SW_ST_init_run();
Expand Down
154 changes: 115 additions & 39 deletions SW_VegEstab.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "SW_Model.h" // externs SW_Model
#include "SW_SoilWater.h" // externs SW_Soilwat
#include "SW_Weather.h" // externs SW_Weather
#include "SW_VegProd.h" // externs `key2veg[]`
#include "SW_VegEstab.h"


Expand Down Expand Up @@ -130,7 +131,7 @@ void SW_VES_deconstruct(void)
// De-allocate days and parameters
if (SW_VegEstab.count > 0)
{
if (!isnull(SW_VegEstab.p_oagg[pd]->days)) {
if (pd > eSW_Day && !isnull(SW_VegEstab.p_oagg[pd]->days)) {
Mem_Free(SW_VegEstab.p_oagg[eSW_Year]->days);
}

Expand Down Expand Up @@ -190,27 +191,44 @@ void SW_VES_read(void) {
CloseFile(&f);

SW_VegEstab_construct();

if (EchoInits)
_echo_VegEstab();
}

/**
@brief Construct SW_VegEstab variable
@brief Construct SW_VegEstab output variables
*/
void SW_VegEstab_construct(void)
{
if (SW_VegEstab.count > 0) {
SW_VegEstab.p_oagg[eSW_Year]->days = (TimeInt *) Mem_Calloc(
SW_VegEstab.count, sizeof(TimeInt), "SW_VegEstab_construct()");

SW_VegEstab.p_accu[eSW_Year]->days = (TimeInt *) Mem_Calloc(
SW_VegEstab.count, sizeof(TimeInt), "SW_VegEstab_construct()");
}
}


/**
@brief Initialization and checks of species establishment parameters
This works correctly only after
* species establishment parameters are read from file by `SW_VES_read()`
* soil layers are initialized by `SW_SIT_init_run()`
*/
void SW_VES_init_run(void) {
IntU i;

for (i = 0; i < SW_VegEstab.count; i++)
for (i = 0; i < SW_VegEstab.count; i++) {
_spp_init(i);
}

if (SW_VegEstab.count > 0) {
SW_VegEstab.p_accu[eSW_Year]->days = (TimeInt *) Mem_Calloc(
SW_VegEstab.count, sizeof(TimeInt), "SW_VegEstab_construct()");
if (EchoInits) {
_echo_VegEstab();
}
}



/**
@brief Check that each count coincides with a day of the year.
*/
Expand Down Expand Up @@ -327,7 +345,7 @@ static void _zero_state(unsigned int sppnum) {
static void _read_spp(const char *infile) {
/* =================================================== */
SW_VEGESTAB_INFO *v;
const int nitems = 15;
const int nitems = 16;
FILE *f;
int lineno = 0;
char name[80]; /* only allow 4 char sppnames */
Expand All @@ -347,45 +365,48 @@ static void _read_spp(const char *infile) {
strcpy(name, inbuf);
break;
case 1:
v->estab_lyrs = atoi(inbuf);
v->vegType = atoi(inbuf);
break;
case 2:
v->bars[SW_GERM_BARS] = fabs(atof(inbuf));
v->estab_lyrs = atoi(inbuf);
break;
case 3:
v->bars[SW_ESTAB_BARS] = fabs(atof(inbuf));
v->bars[SW_GERM_BARS] = fabs(atof(inbuf));
break;
case 4:
v->min_pregerm_days = atoi(inbuf);
v->bars[SW_ESTAB_BARS] = fabs(atof(inbuf));
break;
case 5:
v->max_pregerm_days = atoi(inbuf);
v->min_pregerm_days = atoi(inbuf);
break;
case 6:
v->min_wetdays_for_germ = atoi(inbuf);
v->max_pregerm_days = atoi(inbuf);
break;
case 7:
v->max_drydays_postgerm = atoi(inbuf);
v->min_wetdays_for_germ = atoi(inbuf);
break;
case 8:
v->min_wetdays_for_estab = atoi(inbuf);
v->max_drydays_postgerm = atoi(inbuf);
break;
case 9:
v->min_days_germ2estab = atoi(inbuf);
v->min_wetdays_for_estab = atoi(inbuf);
break;
case 10:
v->max_days_germ2estab = atoi(inbuf);
v->min_days_germ2estab = atoi(inbuf);
break;
case 11:
v->min_temp_germ = atof(inbuf);
v->max_days_germ2estab = atoi(inbuf);
break;
case 12:
v->max_temp_germ = atof(inbuf);
v->min_temp_germ = atof(inbuf);
break;
case 13:
v->min_temp_estab = atof(inbuf);
v->max_temp_germ = atof(inbuf);
break;
case 14:
v->min_temp_estab = atof(inbuf);
break;
case 15:
v->max_temp_estab = atof(inbuf);
break;
}
Expand Down Expand Up @@ -443,33 +464,78 @@ static void _sanity_check(unsigned int sppnum) {
/* =================================================== */
SW_LAYER_INFO **lyr = SW_Site.lyr;
SW_VEGESTAB_INFO *v = SW_VegEstab.parms[sppnum];
LyrIndex min_transp_lyrs;
int k;

min_transp_lyrs = SW_Site.n_transp_lyrs[SW_TREES];
ForEachVegType(k) {
min_transp_lyrs = min(min_transp_lyrs, SW_Site.n_transp_lyrs[k]);

if (v->vegType > NVEGTYPES) {
LogError(
logfp,
LOGFATAL,
"%s (%s) : Specified vegetation type (%s [%d]) is not implemented.",
MyFileName,
v->sppname,
key2veg[v->vegType],
v->vegType
);
}

if (v->estab_lyrs > min_transp_lyrs) {
LogError(logfp, LOGFATAL, "%s : Layers requested (estab_lyrs) > (# transpiration layers=%d).", MyFileName, min_transp_lyrs);
if (v->estab_lyrs > SW_Site.n_transp_lyrs[v->vegType]) {
LogError(
logfp,
LOGFATAL,
"%s (%s) : Layers requested (estab_lyrs = %d) > "
"(# transpiration layers = %d).",
MyFileName,
v->sppname,
v->estab_lyrs,
SW_Site.n_transp_lyrs[v->vegType]
);
}

if (v->min_pregerm_days > v->max_pregerm_days) {
LogError(logfp, LOGFATAL, "%s : First day of germination > last day of germination.", MyFileName);
LogError(
logfp,
LOGFATAL,
"%s (%s) : First day of germination > last day of germination.",
MyFileName,
v->sppname
);
}

if (v->min_wetdays_for_estab > v->max_days_germ2estab) {
LogError(logfp, LOGFATAL, "%s : Minimum wetdays after germination (%d) > maximum days allowed for establishment (%d).", MyFileName, v->min_wetdays_for_estab,
v->max_days_germ2estab);
LogError(
logfp,
LOGFATAL,
"%s (%s) : Minimum wetdays after germination (%d) > "
"maximum days allowed for establishment (%d).",
MyFileName,
v->sppname,
v->min_wetdays_for_estab,
v->max_days_germ2estab
);
}

if (v->min_swc_germ < lyr[0]->swcBulk_wiltpt) {
LogError(logfp, LOGFATAL, "%s : Minimum swc for germination (%.4f) < wiltpoint (%.4f)", MyFileName, v->min_swc_germ, lyr[0]->swcBulk_wiltpt);
LogError(
logfp,
LOGFATAL,
"%s (%s) : Minimum swc for germination (%.4f) < wiltpoint (%.4f)",
MyFileName,
v->sppname,
v->min_swc_germ,
lyr[0]->swcBulk_wiltpt
);
}

if (v->min_swc_estab < lyr[0]->swcBulk_wiltpt) {
LogError(logfp, LOGFATAL, "%s : Minimum swc for establishment (%.4f) < wiltpoint (%.4f)", MyFileName, v->min_swc_estab, lyr[0]->swcBulk_wiltpt);
LogError(
logfp,
LOGFATAL,
"%s (%s) : Minimum swc for establishment (%.4f) < wiltpoint (%.4f)",
MyFileName,
v->sppname,
v->min_swc_estab,
lyr[0]->swcBulk_wiltpt
);
}

}
Expand Down Expand Up @@ -512,7 +578,8 @@ void _echo_VegEstab(void) {

strcpy(outstr, errstr);
for (i = 0; i < SW_VegEstab.count; i++) {
sprintf(errstr, "Species: %s\n----------------\n"
sprintf(
errstr, "Species: %s (vegetation type %s [%d])\n----------------\n"
"Germination parameters:\n"
"\tMinimum SWP (bars) : -%.4f\n"
"\tMinimum SWC (cm/cm) : %.4f\n"
Expand All @@ -522,9 +589,18 @@ void _echo_VegEstab(void) {
"\tFirst possible day : %d\n"
"\tLast possible day : %d\n"
"\tMinimum consecutive wet days (after first possible day): %d\n",
v[i]->sppname, v[i]->bars[SW_GERM_BARS], v[i]->min_swc_germ / lyr[0]->width,
v[i]->min_swc_germ, v[i]->min_temp_germ, v[i]->max_temp_germ,
v[i]->min_pregerm_days, v[i]->max_pregerm_days, v[i]->min_wetdays_for_germ);
v[i]->sppname,
key2veg[v[i]->vegType],
v[i]->vegType,
v[i]->bars[SW_GERM_BARS],
v[i]->min_swc_germ / lyr[0]->width,
v[i]->min_swc_germ,
v[i]->min_temp_germ,
v[i]->max_temp_germ,
v[i]->min_pregerm_days,
v[i]->max_pregerm_days,
v[i]->min_wetdays_for_germ
);

sprintf(errstr, "Establishment parameters:\n"
"\tNumber of layers affecting successful establishment: %d\n"
Expand Down
5 changes: 3 additions & 2 deletions SW_VegEstab.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ typedef struct {
/* THESE VARIABLES DO NOT CHANGE DURING THE NORMAL MODEL RUN */
char sppFileName[MAX_FILENAMESIZE]; /* Store the file Name and Path, Mostly for Rsoilwat */
char sppname[MAX_SPECIESNAMELEN + 1]; /* one set of parms per species */
unsigned int vegType; /**< Vegetation type of species (see "Indices to vegetation types") */
TimeInt min_pregerm_days, /* first possible day of germination */
max_pregerm_days, /* last possible day of germination */
min_wetdays_for_germ, /* number of consecutive days top layer must be */
Expand Down Expand Up @@ -75,7 +76,7 @@ typedef struct {

typedef struct {
TimeInt *days; /* only output the day of estab for each species in the input */
/* this array is allocated via SW_VES_Init() */
/* this array is allocated via `SW_VegEstab_construct()` */
/* each day in the array corresponds to the ordered species list */
} SW_VEGESTAB_OUTPUTS;

Expand All @@ -102,7 +103,7 @@ extern SW_VEGESTAB SW_VegEstab;
void SW_VES_read(void);
void SW_VES_construct(void);
void SW_VES_deconstruct(void);
void SW_VES_init(void);
void SW_VES_init_run(void);
void SW_VegEstab_construct(void);
void SW_VES_checkestab(void);
void SW_VES_new_year(void);
Expand Down
19 changes: 10 additions & 9 deletions testing/Input/bouteloua.estab
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
bogr # 4-char name of species
bogr # 4-char name of species
3 # Vegetation type of species (0, trees; 1, shrubs; 2, forbs; 3 grasses)
# soil layer parameters
2 # number of layers affecting establishment
10. # SWP (bars) requirement for germination (top layer)
15. # SWP (bars) requirement for establishment (average of top layers)
# timing parameters in days
60 # first possible day of germination
180 # last possible day of germination
180 # last possible day of germination
2 # min number of consecutive "wet" days for germination to occur
40 # max number of consecutive "dry" days after germination allowing estab
40 # max number of consecutive "dry" days after germination allowing estab
5 # min number of consecutive "wet" days after germination before establishment
15 # min number of days between germination and establishment
75 # max number of days between germination and establishment
15 # min number of days between germination and establishment
75 # max number of days between germination and establishment
# temperature parameters in C
5. # min temp threshold for germination
20. # max temp threshold for germination
0. # min temp threshold for establishment
20. # max temp threshold for establishment
5. # min temp threshold for germination
20. # max temp threshold for germination
0. # min temp threshold for establishment
20. # max temp threshold for establishment
5 changes: 3 additions & 2 deletions testing/Input/bromus.estab
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
brte # 4-char name of species
3 # Vegetation type of species (0, trees; 1, shrubs; 2, forbs; 3 grasses)
# soil layer parameters
3 # number of layers affecting establishment - 45 cm Harris and Hulbert
10. # SWP (bars) requirement for germination (top layer) - Harris
Expand All @@ -7,12 +8,12 @@ brte # 4-char name of species
200 # first possible day of germination - Hulbert and Harris
365 # last possible day of germination - Hulbert
6 # min number of consecutive "wet" days for germination to occur - Hurlbert and Harris
45 # max number of consecutive "dry" days after germination allowing estab - Harris (longtime)
45 # max number of consecutive "dry" days after germination allowing estab - Harris (longtime)
6 # min number of consecutive "wet" days after germination before establishment - Harris
15 # min number of days between germination and establishment - Hulbert
90 # max number of days between germination and establishment - Harris and Hulbert
# temperature parameters in C
10. # min temp threshold for germination - Hulbert and Harris
30. # max temp threshold for germination - Hulbert and Harris
3. # min temp threshold for establishment - Harris
30. # max temp threshold for establishment - Harris and Hulbert
30. # max temp threshold for establishment - Harris and Hulbert

0 comments on commit 087242a

Please sign in to comment.