From ec6eba36c88a0aa095dc5da43be6d6581894c5d1 Mon Sep 17 00:00:00 2001 From: dschlaep Date: Mon, 22 Jan 2018 17:02:28 -0500 Subject: [PATCH 1/8] Convert vegetation variables into arrays - start addressing #135 - all complete except those defined in SW_VegProd.h --- SW_Defines.h | 17 ++- SW_Flow.c | 80 ++++++------ SW_Output.c | 336 ++++++++++++++++++++++++------------------------- SW_Site.c | 116 ++++++++--------- SW_Site.h | 13 +- SW_SoilWater.h | 54 ++++---- SW_VegEstab.c | 4 +- 7 files changed, 314 insertions(+), 306 deletions(-) diff --git a/SW_Defines.h b/SW_Defines.h index 779777765..3273d07d7 100644 --- a/SW_Defines.h +++ b/SW_Defines.h @@ -33,7 +33,6 @@ #define MAX_LAYERS 25 #define MAX_TRANSP_REGIONS 4 #define MAX_ST_RGR 100 -#define NVEGTYPES 4 #define MAX_NYEAR 2500 /**< An integer representing the max calendar year that is supported. The number just needs to be reasonable, it is an artifical limit. */ @@ -64,16 +63,24 @@ #define SW_MIN 0 #define SW_MAX 1 +/* indices to vegetation types */ +#define NVEGTYPES 4 +#define SW_TREES 0 +#define SW_SHRUB 1 +#define SW_FORBS 2 +#define SW_GRASS 3 + + /*------------ DON'T CHANGE ANYTHING BELOW THIS LINE ------------*/ /* Macros to simplify and add consistency to common tasks */ /* Note the loop var must be declared as LyrIndex */ #define ForEachSoilLayer(i) for((i)=0; (i) < SW_Site.n_layers; (i)++) #define ForEachEvapLayer(i) for((i)=0; (i) < SW_Site.n_evap_lyrs; (i)++) -#define ForEachTreeTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs_tree; (i)++) -#define ForEachShrubTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs_shrub; (i)++) -#define ForEachGrassTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs_grass; (i)++) -#define ForEachForbTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs_forb; (i)++) +#define ForEachTreeTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs[SW_TREES]; (i)++) +#define ForEachShrubTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs[SW_SHRUB]; (i)++) +#define ForEachGrassTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs[SW_GRASS]; (i)++) +#define ForEachForbTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs[SW_FORBS]; (i)++) #define ForEachTranspRegion(r) for((r)=0; (r) < SW_Site.n_transp_rgn; (r)++) /* define m as Months */ #define ForEachMonth(m) for((m)=Jan; (m) <= Dec; (m)++) diff --git a/SW_Flow.c b/SW_Flow.c index fa5d7525e..520c79c16 100644 --- a/SW_Flow.c +++ b/SW_Flow.c @@ -330,10 +330,10 @@ void SW_Water_Flow(void) { } /* Sum cumulative intercepted components */ - SW_Soilwat.tree_int = tree_h2o; - SW_Soilwat.shrub_int = shrub_h2o; - SW_Soilwat.forb_int = forb_h2o; - SW_Soilwat.grass_int = grass_h2o; + SW_Soilwat.int_veg[SW_TREES] = tree_h2o; + SW_Soilwat.int_veg[SW_SHRUB] = shrub_h2o; + SW_Soilwat.int_veg[SW_FORBS] = forb_h2o; + SW_Soilwat.int_veg[SW_GRASS] = grass_h2o; SW_Soilwat.litter_int = litter_h2o; tree_h2o_qum[Today] = tree_h2o_qum[Yesterday] + tree_h2o; @@ -435,7 +435,7 @@ void SW_Water_Flow(void) { soil_evap_rate_tree = 0.; } - transp_weighted_avg(&swpot_avg_tree, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs_tree, lyrTrRegions_Tree, lyrTranspCo_Tree, lyrSWCBulk); + transp_weighted_avg(&swpot_avg_tree, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_TREES], lyrTrRegions_Tree, lyrTranspCo_Tree, lyrSWCBulk); pot_transp(&transp_rate_tree, swpot_avg_tree, SW_VegProd.tree.biolive_daily[doy], SW_VegProd.tree.biodead_daily[doy], transp_tree, SW_Soilwat.pet, SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, SW_VegProd.tree.shade_scale, SW_VegProd.tree.shade_deadmax, @@ -459,7 +459,7 @@ void SW_Water_Flow(void) { soil_evap_rate_shrub = 0.; } - transp_weighted_avg(&swpot_avg_shrub, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs_shrub, lyrTrRegions_Shrub, lyrTranspCo_Shrub, lyrSWCBulk); + transp_weighted_avg(&swpot_avg_shrub, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_SHRUB], lyrTrRegions_Shrub, lyrTranspCo_Shrub, lyrSWCBulk); pot_transp(&transp_rate_shrub, swpot_avg_shrub, SW_VegProd.shrub.biolive_daily[doy], SW_VegProd.shrub.biodead_daily[doy], transp_shrub, SW_Soilwat.pet, SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, SW_VegProd.shrub.shade_scale, SW_VegProd.shrub.shade_deadmax, @@ -484,7 +484,7 @@ void SW_Water_Flow(void) { soil_evap_rate_forb = 0.; } - transp_weighted_avg(&swpot_avg_forb, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs_forb, lyrTrRegions_Forb, lyrTranspCo_Forb, lyrSWCBulk); + transp_weighted_avg(&swpot_avg_forb, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_FORBS], lyrTrRegions_Forb, lyrTranspCo_Forb, lyrSWCBulk); pot_transp(&transp_rate_forb, swpot_avg_forb, SW_VegProd.forb.biolive_daily[doy], SW_VegProd.forb.biodead_daily[doy], transp_forb, SW_Soilwat.pet, SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, SW_VegProd.forb.shade_scale, SW_VegProd.forb.shade_deadmax, @@ -509,7 +509,7 @@ void SW_Water_Flow(void) { soil_evap_rate_grass = 0.; } - transp_weighted_avg(&swpot_avg_grass, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs_grass, lyrTrRegions_Grass, lyrTranspCo_Grass, lyrSWCBulk); + transp_weighted_avg(&swpot_avg_grass, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_GRASS], lyrTrRegions_Grass, lyrTranspCo_Grass, lyrSWCBulk); pot_transp(&transp_rate_grass, swpot_avg_grass, SW_VegProd.grass.biolive_daily[doy], SW_VegProd.grass.biodead_daily[doy], transp_grass, SW_Soilwat.pet, SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, SW_VegProd.grass.shade_scale, SW_VegProd.grass.shade_deadmax, @@ -567,10 +567,10 @@ void SW_Water_Flow(void) { evap_fromSurface(&litter_h2o_qum[Today], &surface_evap_litter_rate, &SW_Soilwat.aet); evap_fromSurface(&standingWater[Today], &surface_evap_standingWater_rate, &SW_Soilwat.aet); - SW_Soilwat.tree_evap = surface_evap_tree_rate; - SW_Soilwat.shrub_evap = surface_evap_shrub_rate; - SW_Soilwat.forb_evap = surface_evap_forb_rate; - SW_Soilwat.grass_evap = surface_evap_grass_rate; + SW_Soilwat.evap_veg[SW_TREES] = surface_evap_tree_rate; + SW_Soilwat.evap_veg[SW_SHRUB] = surface_evap_shrub_rate; + SW_Soilwat.evap_veg[SW_FORBS] = surface_evap_forb_rate; + SW_Soilwat.evap_veg[SW_GRASS] = surface_evap_grass_rate; SW_Soilwat.litter_evap = surface_evap_litter_rate; SW_Soilwat.surfaceWater_evap = surface_evap_standingWater_rate; @@ -591,13 +591,13 @@ void SW_Water_Flow(void) { remove_from_soil(lyrSWCBulk, lyrEvap_Tree, &SW_Soilwat.aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_tree, lyrSWCBulk_HalfWiltpts); /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Tree, &SW_Soilwat.aet, SW_Site.n_transp_lyrs_tree, lyrTranspCo_Tree, transp_rate_tree, lyrSWCBulk_atSWPcrit_Tree); + remove_from_soil(lyrSWCBulk, lyrTransp_Tree, &SW_Soilwat.aet, SW_Site.n_transp_lyrs[SW_TREES], lyrTranspCo_Tree, transp_rate_tree, lyrSWCBulk_atSWPcrit_Tree); } else { /* Set daily array to zero, no evaporation or transpiration */ LyrIndex i; for (i = 0; i < SW_Site.n_evap_lyrs;) lyrEvap_Tree[i++] = 0.; - for (i = 0; i < SW_Site.n_transp_lyrs_tree;) + for (i = 0; i < SW_Site.n_transp_lyrs[SW_TREES];) lyrTransp_Tree[i++] = 0.; } @@ -607,13 +607,13 @@ void SW_Water_Flow(void) { remove_from_soil(lyrSWCBulk, lyrEvap_Shrub, &SW_Soilwat.aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_shrub, lyrSWCBulk_HalfWiltpts); /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Shrub, &SW_Soilwat.aet, SW_Site.n_transp_lyrs_shrub, lyrTranspCo_Shrub, transp_rate_shrub, lyrSWCBulk_atSWPcrit_Shrub); + remove_from_soil(lyrSWCBulk, lyrTransp_Shrub, &SW_Soilwat.aet, SW_Site.n_transp_lyrs[SW_SHRUB], lyrTranspCo_Shrub, transp_rate_shrub, lyrSWCBulk_atSWPcrit_Shrub); } else { /* Set daily array to zero, no evaporation or transpiration */ LyrIndex i; for (i = 0; i < SW_Site.n_evap_lyrs;) lyrEvap_Shrub[i++] = 0.; - for (i = 0; i < SW_Site.n_transp_lyrs_shrub;) + for (i = 0; i < SW_Site.n_transp_lyrs[SW_SHRUB];) lyrTransp_Shrub[i++] = 0.; } @@ -623,13 +623,13 @@ void SW_Water_Flow(void) { remove_from_soil(lyrSWCBulk, lyrEvap_Forb, &SW_Soilwat.aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_forb, lyrSWCBulk_HalfWiltpts); /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Forb, &SW_Soilwat.aet, SW_Site.n_transp_lyrs_forb, lyrTranspCo_Forb, transp_rate_forb, lyrSWCBulk_atSWPcrit_Forb); + remove_from_soil(lyrSWCBulk, lyrTransp_Forb, &SW_Soilwat.aet, SW_Site.n_transp_lyrs[SW_FORBS], lyrTranspCo_Forb, transp_rate_forb, lyrSWCBulk_atSWPcrit_Forb); } else { /* Set daily array to zero, no evaporation or transpiration */ LyrIndex i; for (i = 0; i < SW_Site.n_evap_lyrs;) lyrEvap_Forb[i++] = 0.; - for (i = 0; i < SW_Site.n_transp_lyrs_forb;) + for (i = 0; i < SW_Site.n_transp_lyrs[SW_FORBS];) lyrTransp_Forb[i++] = 0.; } @@ -639,13 +639,13 @@ void SW_Water_Flow(void) { remove_from_soil(lyrSWCBulk, lyrEvap_Grass, &SW_Soilwat.aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_grass, lyrSWCBulk_HalfWiltpts); /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Grass, &SW_Soilwat.aet, SW_Site.n_transp_lyrs_grass, lyrTranspCo_Grass, transp_rate_grass, lyrSWCBulk_atSWPcrit_Grass); + remove_from_soil(lyrSWCBulk, lyrTransp_Grass, &SW_Soilwat.aet, SW_Site.n_transp_lyrs[SW_GRASS], lyrTranspCo_Grass, transp_rate_grass, lyrSWCBulk_atSWPcrit_Grass); } else { /* Set daily array to zero, no evaporation or transpiration */ LyrIndex i; for (i = 0; i < SW_Site.n_evap_lyrs;) lyrEvap_Grass[i++] = 0.; - for (i = 0; i < SW_Site.n_transp_lyrs_grass;) + for (i = 0; i < SW_Site.n_transp_lyrs[SW_GRASS];) lyrTransp_Grass[i++] = 0.; } @@ -729,18 +729,18 @@ static void records2arrays(void) { if (SW_Model.doy == SW_Model.firstdoy) { ForEachSoilLayer(i) { - lyrTrRegions_Tree[i] = SW_Site.lyr[i]->my_transp_rgn_tree; - lyrTrRegions_Forb[i] = SW_Site.lyr[i]->my_transp_rgn_forb; - lyrTrRegions_Shrub[i] = SW_Site.lyr[i]->my_transp_rgn_shrub; - lyrTrRegions_Grass[i] = SW_Site.lyr[i]->my_transp_rgn_grass; + lyrTrRegions_Tree[i] = SW_Site.lyr[i]->my_transp_rgn[SW_TREES]; + lyrTrRegions_Forb[i] = SW_Site.lyr[i]->my_transp_rgn[SW_FORBS]; + lyrTrRegions_Shrub[i] = SW_Site.lyr[i]->my_transp_rgn[SW_SHRUB]; + lyrTrRegions_Grass[i] = SW_Site.lyr[i]->my_transp_rgn[SW_GRASS]; lyrSWCBulk_FieldCaps[i] = SW_Site.lyr[i]->swcBulk_fieldcap; lyrWidths[i] = SW_Site.lyr[i]->width; lyrSWCBulk_Wiltpts[i] = SW_Site.lyr[i]->swcBulk_wiltpt; lyrSWCBulk_HalfWiltpts[i] = SW_Site.lyr[i]->swcBulk_wiltpt / 2.; - lyrSWCBulk_atSWPcrit_Tree[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit_tree; - lyrSWCBulk_atSWPcrit_Forb[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit_forb; - lyrSWCBulk_atSWPcrit_Shrub[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit_shrub; - lyrSWCBulk_atSWPcrit_Grass[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit_grass; + lyrSWCBulk_atSWPcrit_Tree[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit[SW_TREES]; + lyrSWCBulk_atSWPcrit_Forb[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit[SW_FORBS]; + lyrSWCBulk_atSWPcrit_Shrub[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit[SW_SHRUB]; + lyrSWCBulk_atSWPcrit_Grass[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit[SW_GRASS]; lyrSWCBulk_Mins[i] = SW_Site.lyr[i]->swcBulk_min; lyrpsisMatric[i] = SW_Site.lyr[i]->psisMatric; lyrthetasMatric[i] = SW_Site.lyr[i]->thetasMatric; @@ -759,22 +759,22 @@ static void records2arrays(void) { ForEachTreeTranspLayer(i) { - lyrTranspCo_Tree[i] = SW_Site.lyr[i]->transp_coeff_tree; + lyrTranspCo_Tree[i] = SW_Site.lyr[i]->transp_coeff[SW_TREES]; } ForEachShrubTranspLayer(i) { - lyrTranspCo_Shrub[i] = SW_Site.lyr[i]->transp_coeff_shrub; + lyrTranspCo_Shrub[i] = SW_Site.lyr[i]->transp_coeff[SW_SHRUB]; } ForEachForbTranspLayer(i) { - lyrTranspCo_Forb[i] = SW_Site.lyr[i]->transp_coeff_forb; + lyrTranspCo_Forb[i] = SW_Site.lyr[i]->transp_coeff[SW_FORBS]; } ForEachGrassTranspLayer(i) { - lyrTranspCo_Grass[i] = SW_Site.lyr[i]->transp_coeff_grass; + lyrTranspCo_Grass[i] = SW_Site.lyr[i]->transp_coeff[SW_GRASS]; } ForEachEvapLayer(i) @@ -794,10 +794,10 @@ static void arrays2records(void) { { SW_Soilwat.swcBulk[Today][i] = lyrSWCBulk[i]; SW_Soilwat.drain[i] = lyrDrain[i]; - SW_Soilwat.hydred_tree[i] = lyrHydRed_Tree[i]; - SW_Soilwat.hydred_shrub[i] = lyrHydRed_Shrub[i]; - SW_Soilwat.hydred_forb[i] = lyrHydRed_Forb[i]; - SW_Soilwat.hydred_grass[i] = lyrHydRed_Grass[i]; + SW_Soilwat.hydred[SW_TREES][i] = lyrHydRed_Tree[i]; + SW_Soilwat.hydred[SW_SHRUB][i] = lyrHydRed_Shrub[i]; + SW_Soilwat.hydred[SW_FORBS][i] = lyrHydRed_Forb[i]; + SW_Soilwat.hydred[SW_GRASS][i] = lyrHydRed_Grass[i]; SW_Soilwat.sTemp[i] = lyrsTemp[i]; } SW_Soilwat.surfaceTemp = surfaceTemp[Today]; @@ -808,22 +808,22 @@ static void arrays2records(void) { ForEachTreeTranspLayer(i) { - SW_Soilwat.transpiration_tree[i] = lyrTransp_Tree[i]; + SW_Soilwat.transpiration[SW_TREES][i] = lyrTransp_Tree[i]; } ForEachShrubTranspLayer(i) { - SW_Soilwat.transpiration_shrub[i] = lyrTransp_Shrub[i]; + SW_Soilwat.transpiration[SW_SHRUB][i] = lyrTransp_Shrub[i]; } ForEachForbTranspLayer(i) { - SW_Soilwat.transpiration_forb[i] = lyrTransp_Forb[i]; + SW_Soilwat.transpiration[SW_FORBS][i] = lyrTransp_Forb[i]; } ForEachGrassTranspLayer(i) { - SW_Soilwat.transpiration_grass[i] = lyrTransp_Grass[i]; + SW_Soilwat.transpiration[SW_GRASS][i] = lyrTransp_Grass[i]; } ForEachEvapLayer(i) diff --git a/SW_Output.c b/SW_Output.c index 98c6d4a2c..34d6e29a4 100644 --- a/SW_Output.c +++ b/SW_Output.c @@ -2844,16 +2844,16 @@ static void get_transp(OutPeriod pd) switch (pd) { case eSW_Day: - val[i] = v->dysum.transp_tree[i]; + val[i] = v->dysum.transp[SW_TREES][i]; break; case eSW_Week: - val[i] = v->wkavg.transp_tree[i]; + val[i] = v->wkavg.transp[SW_TREES][i]; break; case eSW_Month: - val[i] = v->moavg.transp_tree[i]; + val[i] = v->moavg.transp[SW_TREES][i]; break; case eSW_Year: - val[i] = v->yravg.transp_tree[i]; + val[i] = v->yravg.transp[SW_TREES][i]; break; } } @@ -2862,19 +2862,19 @@ static void get_transp(OutPeriod pd) { case eSW_Day: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Day][SW_Output[eSW_Transp].dy_row + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 1)] = v->dysum.transp_tree[i]; + p_rOUT[eSW_Transp][eSW_Day][SW_Output[eSW_Transp].dy_row + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 1)] = v->dysum.transp[SW_TREES][i]; break; case eSW_Week: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Week][SW_Output[eSW_Transp].wk_row + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 1)] = v->wkavg.transp_tree[i]; + p_rOUT[eSW_Transp][eSW_Week][SW_Output[eSW_Transp].wk_row + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 1)] = v->wkavg.transp[SW_TREES][i]; break; case eSW_Month: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Month][SW_Output[eSW_Transp].mo_row + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 1)] = v->moavg.transp_tree[i]; + p_rOUT[eSW_Transp][eSW_Month][SW_Output[eSW_Transp].mo_row + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 1)] = v->moavg.transp[SW_TREES][i]; break; case eSW_Year: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Year][SW_Output[eSW_Transp].yr_row + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 1)] = v->yravg.transp_tree[i]; + p_rOUT[eSW_Transp][eSW_Year][SW_Output[eSW_Transp].yr_row + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 1)] = v->yravg.transp[SW_TREES][i]; break; } #endif @@ -2918,16 +2918,16 @@ static void get_transp(OutPeriod pd) switch (pd) { case eSW_Day: - val[i] = v->dysum.transp_shrub[i]; + val[i] = v->dysum.transp[SW_SHRUB][i]; break; case eSW_Week: - val[i] = v->wkavg.transp_shrub[i]; + val[i] = v->wkavg.transp[SW_SHRUB][i]; break; case eSW_Month: - val[i] = v->moavg.transp_shrub[i]; + val[i] = v->moavg.transp[SW_SHRUB][i]; break; case eSW_Year: - val[i] = v->yravg.transp_shrub[i]; + val[i] = v->yravg.transp[SW_SHRUB][i]; break; } } @@ -2936,19 +2936,19 @@ static void get_transp(OutPeriod pd) { case eSW_Day: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Day][SW_Output[eSW_Transp].dy_row + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 2)] = v->dysum.transp_shrub[i]; + p_rOUT[eSW_Transp][eSW_Day][SW_Output[eSW_Transp].dy_row + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 2)] = v->dysum.transp[SW_SHRUB][i]; break; case eSW_Week: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Week][SW_Output[eSW_Transp].wk_row + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 2)] = v->wkavg.transp_shrub[i]; + p_rOUT[eSW_Transp][eSW_Week][SW_Output[eSW_Transp].wk_row + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 2)] = v->wkavg.transp[SW_SHRUB][i]; break; case eSW_Month: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Month][SW_Output[eSW_Transp].mo_row + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 2)] = v->moavg.transp_shrub[i]; + p_rOUT[eSW_Transp][eSW_Month][SW_Output[eSW_Transp].mo_row + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 2)] = v->moavg.transp[SW_SHRUB][i]; break; case eSW_Year: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Year][SW_Output[eSW_Transp].yr_row + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 2)] = v->yravg.transp_shrub[i]; + p_rOUT[eSW_Transp][eSW_Year][SW_Output[eSW_Transp].yr_row + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 2)] = v->yravg.transp[SW_SHRUB][i]; break; } #endif @@ -2992,16 +2992,16 @@ static void get_transp(OutPeriod pd) switch (pd) { case eSW_Day: - val[i] = v->dysum.transp_forb[i]; + val[i] = v->dysum.transp[SW_FORBS][i]; break; case eSW_Week: - val[i] = v->wkavg.transp_forb[i]; + val[i] = v->wkavg.transp[SW_FORBS][i]; break; case eSW_Month: - val[i] = v->moavg.transp_forb[i]; + val[i] = v->moavg.transp[SW_FORBS][i]; break; case eSW_Year: - val[i] = v->yravg.transp_forb[i]; + val[i] = v->yravg.transp[SW_FORBS][i]; break; } } @@ -3010,19 +3010,19 @@ static void get_transp(OutPeriod pd) { case eSW_Day: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Day][SW_Output[eSW_Transp].dy_row + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 3)] = v->dysum.transp_forb[i]; + p_rOUT[eSW_Transp][eSW_Day][SW_Output[eSW_Transp].dy_row + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 3)] = v->dysum.transp[SW_FORBS][i]; break; case eSW_Week: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Week][SW_Output[eSW_Transp].wk_row + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 3)] = v->wkavg.transp_forb[i]; + p_rOUT[eSW_Transp][eSW_Week][SW_Output[eSW_Transp].wk_row + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 3)] = v->wkavg.transp[SW_FORBS][i]; break; case eSW_Month: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Month][SW_Output[eSW_Transp].mo_row + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 3)] = v->moavg.transp_forb[i]; + p_rOUT[eSW_Transp][eSW_Month][SW_Output[eSW_Transp].mo_row + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 3)] = v->moavg.transp[SW_FORBS][i]; break; case eSW_Year: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Year][SW_Output[eSW_Transp].yr_row + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 3)] = v->yravg.transp_forb[i]; + p_rOUT[eSW_Transp][eSW_Year][SW_Output[eSW_Transp].yr_row + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 3)] = v->yravg.transp[SW_FORBS][i]; break; } #endif @@ -3067,16 +3067,16 @@ static void get_transp(OutPeriod pd) switch (pd) { case eSW_Day: - val[i] = v->dysum.transp_grass[i]; + val[i] = v->dysum.transp[SW_GRASS][i]; break; case eSW_Week: - val[i] = v->wkavg.transp_grass[i]; + val[i] = v->wkavg.transp[SW_GRASS][i]; break; case eSW_Month: - val[i] = v->moavg.transp_grass[i]; + val[i] = v->moavg.transp[SW_GRASS][i]; break; case eSW_Year: - val[i] = v->yravg.transp_grass[i]; + val[i] = v->yravg.transp[SW_GRASS][i]; break; } } @@ -3085,22 +3085,22 @@ static void get_transp(OutPeriod pd) { case eSW_Day: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Day][SW_Output[eSW_Transp].dy_row + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 4)] = v->dysum.transp_grass[i]; + p_rOUT[eSW_Transp][eSW_Day][SW_Output[eSW_Transp].dy_row + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 4)] = v->dysum.transp[SW_GRASS][i]; SW_Output[eSW_Transp].dy_row++; break; case eSW_Week: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Week][SW_Output[eSW_Transp].wk_row + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 4)] = v->wkavg.transp_grass[i]; + p_rOUT[eSW_Transp][eSW_Week][SW_Output[eSW_Transp].wk_row + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 4)] = v->wkavg.transp[SW_GRASS][i]; SW_Output[eSW_Transp].wk_row++; break; case eSW_Month: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Month][SW_Output[eSW_Transp].mo_row + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 4)] = v->moavg.transp_grass[i]; + p_rOUT[eSW_Transp][eSW_Month][SW_Output[eSW_Transp].mo_row + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 4)] = v->moavg.transp[SW_GRASS][i]; SW_Output[eSW_Transp].mo_row++; break; case eSW_Year: ForEachSoilLayer(i) - p_rOUT[eSW_Transp][eSW_Year][SW_Output[eSW_Transp].yr_row + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 4)] = v->yravg.transp_grass[i]; + p_rOUT[eSW_Transp][eSW_Year][SW_Output[eSW_Transp].yr_row + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 4)] = v->yravg.transp[SW_GRASS][i]; SW_Output[eSW_Transp].yr_row++; break; } @@ -3220,37 +3220,37 @@ static void get_evapSurface(OutPeriod pd) { case eSW_Day: val_tot = v->dysum.total_evap; - val_tree = v->dysum.tree_evap; - val_forb = v->dysum.forb_evap; - val_shrub = v->dysum.shrub_evap; - val_grass = v->dysum.grass_evap; + val_tree = v->dysum.evap_veg[SW_TREES]; + val_forb = v->dysum.evap_veg[SW_FORBS]; + val_shrub = v->dysum.evap_veg[SW_SHRUB]; + val_grass = v->dysum.evap_veg[SW_GRASS]; val_litter = v->dysum.litter_evap; val_water = v->dysum.surfaceWater_evap; break; case eSW_Week: val_tot = v->wkavg.total_evap; - val_tree = v->wkavg.tree_evap; - val_forb = v->wkavg.forb_evap; - val_shrub = v->wkavg.shrub_evap; - val_grass = v->wkavg.grass_evap; + val_tree = v->wkavg.evap_veg[SW_TREES]; + val_forb = v->wkavg.evap_veg[SW_FORBS]; + val_shrub = v->wkavg.evap_veg[SW_SHRUB]; + val_grass = v->wkavg.evap_veg[SW_GRASS]; val_litter = v->wkavg.litter_evap; val_water = v->wkavg.surfaceWater_evap; break; case eSW_Month: val_tot = v->moavg.total_evap; - val_tree = v->moavg.tree_evap; - val_forb = v->moavg.forb_evap; - val_shrub = v->moavg.shrub_evap; - val_grass = v->moavg.grass_evap; + val_tree = v->moavg.evap_veg[SW_TREES]; + val_forb = v->moavg.evap_veg[SW_FORBS]; + val_shrub = v->moavg.evap_veg[SW_SHRUB]; + val_grass = v->moavg.evap_veg[SW_GRASS]; val_litter = v->moavg.litter_evap; val_water = v->moavg.surfaceWater_evap; break; case eSW_Year: val_tot = v->yravg.total_evap; - val_tree = v->yravg.tree_evap; - val_forb = v->yravg.forb_evap; - val_shrub = v->yravg.shrub_evap; - val_grass = v->yravg.grass_evap; + val_tree = v->yravg.evap_veg[SW_TREES]; + val_forb = v->yravg.evap_veg[SW_FORBS]; + val_shrub = v->yravg.evap_veg[SW_SHRUB]; + val_grass = v->yravg.evap_veg[SW_GRASS]; val_litter = v->yravg.litter_evap; val_water = v->yravg.surfaceWater_evap; break; @@ -3269,10 +3269,10 @@ static void get_evapSurface(OutPeriod pd) p[delta + dy_nrow * 0] = SW_Model.simyear; p[delta + dy_nrow * 1] = SW_Model.doy; p[delta + dy_nrow * 2] = v->dysum.total_evap; - p[delta + dy_nrow * 3] = v->dysum.tree_evap; - p[delta + dy_nrow * 4] = v->dysum.shrub_evap; - p[delta + dy_nrow * 5] = v->dysum.forb_evap; - p[delta + dy_nrow * 6] = v->dysum.grass_evap; + p[delta + dy_nrow * 3] = v->dysum.evap_veg[SW_TREES]; + p[delta + dy_nrow * 4] = v->dysum.evap_veg[SW_SHRUB]; + p[delta + dy_nrow * 5] = v->dysum.evap_veg[SW_FORBS]; + p[delta + dy_nrow * 6] = v->dysum.evap_veg[SW_GRASS]; p[delta + dy_nrow * 7] = v->dysum.litter_evap; p[delta + dy_nrow * 8] = v->dysum.surfaceWater_evap; SW_Output[eSW_EvapSurface].dy_row++; @@ -3283,10 +3283,10 @@ static void get_evapSurface(OutPeriod pd) p[delta + wk_nrow * 0] = SW_Model.simyear; p[delta + wk_nrow * 1] = (SW_Model.week + 1) - tOffset; p[delta + wk_nrow * 2] = v->wkavg.total_evap; - p[delta + wk_nrow * 3] = v->wkavg.tree_evap; - p[delta + wk_nrow * 4] = v->wkavg.shrub_evap; - p[delta + wk_nrow * 5] = v->wkavg.forb_evap; - p[delta + wk_nrow * 6] = v->wkavg.grass_evap; + p[delta + wk_nrow * 3] = v->wkavg.evap_veg[SW_TREES]; + p[delta + wk_nrow * 4] = v->wkavg.evap_veg[SW_SHRUB]; + p[delta + wk_nrow * 5] = v->wkavg.evap_veg[SW_FORBS]; + p[delta + wk_nrow * 6] = v->wkavg.evap_veg[SW_GRASS]; p[delta + wk_nrow * 7] = v->wkavg.litter_evap; p[delta + wk_nrow * 8] = v->wkavg.surfaceWater_evap; SW_Output[eSW_EvapSurface].wk_row++; @@ -3297,10 +3297,10 @@ static void get_evapSurface(OutPeriod pd) p[delta + mo_nrow * 0] = SW_Model.simyear; p[delta + mo_nrow * 1] = (SW_Model.month + 1) - tOffset; p[delta + mo_nrow * 2] = v->moavg.total_evap; - p[delta + mo_nrow * 3] = v->moavg.tree_evap; - p[delta + mo_nrow * 4] = v->moavg.shrub_evap; - p[delta + mo_nrow * 5] = v->moavg.forb_evap; - p[delta + mo_nrow * 6] = v->moavg.grass_evap; + p[delta + mo_nrow * 3] = v->moavg.evap_veg[SW_TREES]; + p[delta + mo_nrow * 4] = v->moavg.evap_veg[SW_SHRUB]; + p[delta + mo_nrow * 5] = v->moavg.evap_veg[SW_FORBS]; + p[delta + mo_nrow * 6] = v->moavg.evap_veg[SW_GRASS]; p[delta + mo_nrow * 7] = v->moavg.litter_evap; p[delta + mo_nrow * 8] = v->moavg.surfaceWater_evap; SW_Output[eSW_EvapSurface].mo_row++; @@ -3310,10 +3310,10 @@ static void get_evapSurface(OutPeriod pd) p = p_rOUT[eSW_EvapSurface][eSW_Year]; // set shorthand copy of 'p_rOUT' pointer p[delta + yr_nrow * 0] = SW_Model.simyear; p[delta + yr_nrow * 1] = v->yravg.total_evap; - p[delta + yr_nrow * 2] = v->yravg.tree_evap; - p[delta + yr_nrow * 3] = v->yravg.shrub_evap; - p[delta + yr_nrow * 4] = v->yravg.forb_evap; - p[delta + yr_nrow * 5] = v->yravg.grass_evap; + p[delta + yr_nrow * 2] = v->yravg.evap_veg[SW_TREES]; + p[delta + yr_nrow * 3] = v->yravg.evap_veg[SW_SHRUB]; + p[delta + yr_nrow * 4] = v->yravg.evap_veg[SW_FORBS]; + p[delta + yr_nrow * 5] = v->yravg.evap_veg[SW_GRASS]; p[delta + yr_nrow * 6] = v->yravg.litter_evap; p[delta + yr_nrow * 7] = v->yravg.surfaceWater_evap; SW_Output[eSW_EvapSurface].yr_row++; @@ -3337,34 +3337,34 @@ static void get_interception(OutPeriod pd) { case eSW_Day: val_tot = v->dysum.total_int; - val_tree = v->dysum.tree_int; - val_forb = v->dysum.forb_int; - val_shrub = v->dysum.shrub_int; - val_grass = v->dysum.grass_int; + val_tree = v->dysum.int_veg[SW_TREES]; + val_forb = v->dysum.int_veg[SW_FORBS]; + val_shrub = v->dysum.int_veg[SW_SHRUB]; + val_grass = v->dysum.int_veg[SW_GRASS]; val_litter = v->dysum.litter_int; break; case eSW_Week: val_tot = v->wkavg.total_int; - val_tree = v->wkavg.tree_int; - val_forb = v->wkavg.forb_int; - val_shrub = v->wkavg.shrub_int; - val_grass = v->wkavg.grass_int; + val_tree = v->wkavg.int_veg[SW_TREES]; + val_forb = v->wkavg.int_veg[SW_FORBS]; + val_shrub = v->wkavg.int_veg[SW_SHRUB]; + val_grass = v->wkavg.int_veg[SW_GRASS]; val_litter = v->wkavg.litter_int; break; case eSW_Month: val_tot = v->moavg.total_int; - val_tree = v->moavg.tree_int; - val_forb = v->moavg.forb_int; - val_shrub = v->moavg.shrub_int; - val_grass = v->moavg.grass_int; + val_tree = v->moavg.int_veg[SW_TREES]; + val_forb = v->moavg.int_veg[SW_FORBS]; + val_shrub = v->moavg.int_veg[SW_SHRUB]; + val_grass = v->moavg.int_veg[SW_GRASS]; val_litter = v->moavg.litter_int; break; case eSW_Year: val_tot = v->yravg.total_int; - val_tree = v->yravg.tree_int; - val_forb = v->yravg.forb_int; - val_shrub = v->yravg.shrub_int; - val_grass = v->yravg.grass_int; + val_tree = v->yravg.int_veg[SW_TREES]; + val_forb = v->yravg.int_veg[SW_FORBS]; + val_shrub = v->yravg.int_veg[SW_SHRUB]; + val_grass = v->yravg.int_veg[SW_GRASS]; val_litter = v->yravg.litter_int; break; } @@ -3382,10 +3382,10 @@ static void get_interception(OutPeriod pd) p[delta + dy_nrow * 0] = SW_Model.simyear; p[delta + dy_nrow * 1] = SW_Model.doy; p[delta + dy_nrow * 2] = v->dysum.total_int; - p[delta + dy_nrow * 3] = v->dysum.tree_int; - p[delta + dy_nrow * 4] = v->dysum.shrub_int; - p[delta + dy_nrow * 5] = v->dysum.forb_int; - p[delta + dy_nrow * 6] = v->dysum.grass_int; + p[delta + dy_nrow * 3] = v->dysum.int_veg[SW_TREES]; + p[delta + dy_nrow * 4] = v->dysum.int_veg[SW_SHRUB]; + p[delta + dy_nrow * 5] = v->dysum.int_veg[SW_FORBS]; + p[delta + dy_nrow * 6] = v->dysum.int_veg[SW_GRASS]; p[delta + dy_nrow * 7] = v->dysum.litter_int; SW_Output[eSW_Interception].dy_row++; break; @@ -3395,10 +3395,10 @@ static void get_interception(OutPeriod pd) p[delta + wk_nrow * 0] = SW_Model.simyear; p[delta + wk_nrow * 1] = (SW_Model.week + 1) - tOffset; p[delta + wk_nrow * 2] = v->wkavg.total_int; - p[delta + wk_nrow * 3] = v->wkavg.tree_int; - p[delta + wk_nrow * 4] = v->wkavg.shrub_int; - p[delta + wk_nrow * 5] = v->wkavg.forb_int; - p[delta + wk_nrow * 6] = v->wkavg.grass_int; + p[delta + wk_nrow * 3] = v->wkavg.int_veg[SW_TREES]; + p[delta + wk_nrow * 4] = v->wkavg.int_veg[SW_SHRUB]; + p[delta + wk_nrow * 5] = v->wkavg.int_veg[SW_FORBS]; + p[delta + wk_nrow * 6] = v->wkavg.int_veg[SW_GRASS]; p[delta + wk_nrow * 7] = v->wkavg.litter_int; SW_Output[eSW_Interception].wk_row++; break; @@ -3408,10 +3408,10 @@ static void get_interception(OutPeriod pd) p[delta + mo_nrow * 0] = SW_Model.simyear; p[delta + mo_nrow * 1] = (SW_Model.month + 1) - tOffset; p[delta + mo_nrow * 2] = v->moavg.total_int; - p[delta + mo_nrow * 3] = v->moavg.tree_int; - p[delta + mo_nrow * 4] = v->moavg.shrub_int; - p[delta + mo_nrow * 5] = v->moavg.forb_int; - p[delta + mo_nrow * 6] = v->moavg.grass_int; + p[delta + mo_nrow * 3] = v->moavg.int_veg[SW_TREES]; + p[delta + mo_nrow * 4] = v->moavg.int_veg[SW_SHRUB]; + p[delta + mo_nrow * 5] = v->moavg.int_veg[SW_FORBS]; + p[delta + mo_nrow * 6] = v->moavg.int_veg[SW_GRASS]; p[delta + mo_nrow * 7] = v->moavg.litter_int; SW_Output[eSW_Interception].mo_row++; break; @@ -3420,10 +3420,10 @@ static void get_interception(OutPeriod pd) p = p_rOUT[eSW_Interception][eSW_Year]; // set shorthand copy of 'p_rOUT' pointer p[delta + yr_nrow * 0] = SW_Model.simyear; p[delta + yr_nrow * 1] = v->yravg.total_int; - p[delta + yr_nrow * 2] = v->yravg.tree_int; - p[delta + yr_nrow * 3] = v->yravg.shrub_int; - p[delta + yr_nrow * 4] = v->yravg.forb_int; - p[delta + yr_nrow * 5] = v->yravg.grass_int; + p[delta + yr_nrow * 2] = v->yravg.int_veg[SW_TREES]; + p[delta + yr_nrow * 3] = v->yravg.int_veg[SW_SHRUB]; + p[delta + yr_nrow * 4] = v->yravg.int_veg[SW_FORBS]; + p[delta + yr_nrow * 5] = v->yravg.int_veg[SW_GRASS]; p[delta + yr_nrow * 6] = v->yravg.litter_int; SW_Output[eSW_Interception].yr_row++; break; @@ -3619,16 +3619,16 @@ static void get_hydred(OutPeriod pd) switch (pd) { case eSW_Day: - val = v->dysum.hydred_tree[i]; + val = v->dysum.hydred[SW_TREES][i]; break; case eSW_Week: - val = v->wkavg.hydred_tree[i]; + val = v->wkavg.hydred[SW_TREES][i]; break; case eSW_Month: - val = v->moavg.hydred_tree[i]; + val = v->moavg.hydred[SW_TREES][i]; break; case eSW_Year: - val = v->yravg.hydred_tree[i]; + val = v->yravg.hydred[SW_TREES][i]; break; } @@ -3640,16 +3640,16 @@ static void get_hydred(OutPeriod pd) switch (pd) { case eSW_Day: - val = v->dysum.hydred_shrub[i]; + val = v->dysum.hydred[SW_SHRUB][i]; break; case eSW_Week: - val = v->wkavg.hydred_shrub[i]; + val = v->wkavg.hydred[SW_SHRUB][i]; break; case eSW_Month: - val = v->moavg.hydred_shrub[i]; + val = v->moavg.hydred[SW_SHRUB][i]; break; case eSW_Year: - val = v->yravg.hydred_shrub[i]; + val = v->yravg.hydred[SW_SHRUB][i]; break; } @@ -3661,16 +3661,16 @@ static void get_hydred(OutPeriod pd) switch (pd) { case eSW_Day: - val = v->dysum.hydred_forb[i]; + val = v->dysum.hydred[SW_FORBS][i]; break; case eSW_Week: - val = v->wkavg.hydred_forb[i]; + val = v->wkavg.hydred[SW_FORBS][i]; break; case eSW_Month: - val = v->moavg.hydred_forb[i]; + val = v->moavg.hydred[SW_FORBS][i]; break; case eSW_Year: - val = v->yravg.hydred_forb[i]; + val = v->yravg.hydred[SW_FORBS][i]; break; } @@ -3683,16 +3683,16 @@ static void get_hydred(OutPeriod pd) switch (pd) { case eSW_Day: - val = v->dysum.hydred_grass[i]; + val = v->dysum.hydred[SW_GRASS][i]; break; case eSW_Week: - val = v->wkavg.hydred_grass[i]; + val = v->wkavg.hydred[SW_GRASS][i]; break; case eSW_Month: - val = v->moavg.hydred_grass[i]; + val = v->moavg.hydred[SW_GRASS][i]; break; case eSW_Year: - val = v->yravg.hydred_grass[i]; + val = v->yravg.hydred[SW_GRASS][i]; break; } @@ -3756,19 +3756,19 @@ static void get_hydred(OutPeriod pd) { case eSW_Day: ForEachSoilLayer(i) - p[delta + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 1)] = v->dysum.hydred_tree[i]; + p[delta + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 1)] = v->dysum.hydred[SW_TREES][i]; break; case eSW_Week: ForEachSoilLayer(i) - p[delta + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 1)] = v->wkavg.hydred_tree[i]; + p[delta + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 1)] = v->wkavg.hydred[SW_TREES][i]; break; case eSW_Month: ForEachSoilLayer(i) - p[delta + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 1)] = v->moavg.hydred_tree[i]; + p[delta + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 1)] = v->moavg.hydred[SW_TREES][i]; break; case eSW_Year: ForEachSoilLayer(i) - p[delta + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 1)] = v->yravg.hydred_tree[i]; + p[delta + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 1)] = v->yravg.hydred[SW_TREES][i]; break; } @@ -3777,19 +3777,19 @@ static void get_hydred(OutPeriod pd) { case eSW_Day: ForEachSoilLayer(i) - p[delta + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 2)] = v->dysum.hydred_shrub[i]; + p[delta + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 2)] = v->dysum.hydred[SW_SHRUB][i]; break; case eSW_Week: ForEachSoilLayer(i) - p[delta + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 2)] = v->wkavg.hydred_shrub[i]; + p[delta + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 2)] = v->wkavg.hydred[SW_SHRUB][i]; break; case eSW_Month: ForEachSoilLayer(i) - p[delta + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 2)] = v->moavg.hydred_shrub[i]; + p[delta + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 2)] = v->moavg.hydred[SW_SHRUB][i]; break; case eSW_Year: ForEachSoilLayer(i) - p[delta + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 2)] = v->yravg.hydred_shrub[i]; + p[delta + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 2)] = v->yravg.hydred[SW_SHRUB][i]; break; } @@ -3798,19 +3798,19 @@ static void get_hydred(OutPeriod pd) { case eSW_Day: ForEachSoilLayer(i) - p[delta + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 3)] = v->dysum.hydred_forb[i]; + p[delta + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 3)] = v->dysum.hydred[SW_FORBS][i]; break; case eSW_Week: ForEachSoilLayer(i) - p[delta + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 3)] = v->wkavg.hydred_forb[i]; + p[delta + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 3)] = v->wkavg.hydred[SW_FORBS][i]; break; case eSW_Month: ForEachSoilLayer(i) - p[delta + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 3)] = v->moavg.hydred_forb[i]; + p[delta + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 3)] = v->moavg.hydred[SW_FORBS][i]; break; case eSW_Year: ForEachSoilLayer(i) - p[delta + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 3)] = v->yravg.hydred_forb[i]; + p[delta + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 3)] = v->yravg.hydred[SW_FORBS][i]; break; } @@ -3819,22 +3819,22 @@ static void get_hydred(OutPeriod pd) { case eSW_Day: ForEachSoilLayer(i) - p[delta + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 4)] = v->dysum.hydred_grass[i]; + p[delta + dy_nrow * (i + 2) + (dy_nrow * SW_Site.n_layers * 4)] = v->dysum.hydred[SW_GRASS][i]; SW_Output[eSW_HydRed].dy_row++; break; case eSW_Week: ForEachSoilLayer(i) - p[delta + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 4)] = v->wkavg.hydred_grass[i]; + p[delta + wk_nrow * (i + 2) + (wk_nrow * SW_Site.n_layers * 4)] = v->wkavg.hydred[SW_GRASS][i]; SW_Output[eSW_HydRed].wk_row++; break; case eSW_Month: ForEachSoilLayer(i) - p[delta + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 4)] = v->moavg.hydred_grass[i]; + p[delta + mo_nrow * (i + 2) + (mo_nrow * SW_Site.n_layers * 4)] = v->moavg.hydred[SW_GRASS][i]; SW_Output[eSW_HydRed].mo_row++; break; case eSW_Year: ForEachSoilLayer(i) - p[delta + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 4)] = v->yravg.hydred_grass[i]; + p[delta + yr_nrow * (i + 1) + (yr_nrow * SW_Site.n_layers * 4)] = v->yravg.hydred[SW_GRASS][i]; SW_Output[eSW_HydRed].yr_row++; break; } @@ -4357,13 +4357,13 @@ static void sumof_swc(SW_SOILWAT *v, SW_SOILWAT_OUTPUTS *s, OutKey k) case eSW_Transp: ForEachSoilLayer(i) { - s->transp_total[i] += v->transpiration_tree[i] - + v->transpiration_forb[i] + v->transpiration_shrub[i] - + v->transpiration_grass[i]; - s->transp_tree[i] += v->transpiration_tree[i]; - s->transp_shrub[i] += v->transpiration_shrub[i]; - s->transp_forb[i] += v->transpiration_forb[i]; - s->transp_grass[i] += v->transpiration_grass[i]; + s->transp_total[i] += v->transpiration[SW_TREES][i] + + v->transpiration[SW_SHRUB][i] + v->transpiration[SW_FORBS][i] + + v->transpiration[SW_GRASS][i]; + s->transp[SW_TREES][i] += v->transpiration[SW_TREES][i]; + s->transp[SW_SHRUB][i] += v->transpiration[SW_SHRUB][i]; + s->transp[SW_FORBS][i] += v->transpiration[SW_FORBS][i]; + s->transp[SW_GRASS][i] += v->transpiration[SW_GRASS][i]; } break; @@ -4373,23 +4373,23 @@ static void sumof_swc(SW_SOILWAT *v, SW_SOILWAT_OUTPUTS *s, OutKey k) break; case eSW_EvapSurface: - s->total_evap += v->tree_evap + v->forb_evap + v->shrub_evap - + v->grass_evap + v->litter_evap + v->surfaceWater_evap; - s->tree_evap += v->tree_evap; - s->shrub_evap += v->shrub_evap; - s->forb_evap += v->forb_evap; - s->grass_evap += v->grass_evap; + s->total_evap += v->evap_veg[SW_TREES] + v->evap_veg[SW_FORBS] + v->evap_veg[SW_SHRUB] + + v->evap_veg[SW_GRASS] + v->litter_evap + v->surfaceWater_evap; + s->evap_veg[SW_TREES] += v->evap_veg[SW_TREES]; + s->evap_veg[SW_SHRUB] += v->evap_veg[SW_SHRUB]; + s->evap_veg[SW_FORBS] += v->evap_veg[SW_FORBS]; + s->evap_veg[SW_GRASS] += v->evap_veg[SW_GRASS]; s->litter_evap += v->litter_evap; s->surfaceWater_evap += v->surfaceWater_evap; break; case eSW_Interception: - s->total_int += v->tree_int + v->forb_int + v->shrub_int + v->grass_int + s->total_int += v->int_veg[SW_TREES] + v->int_veg[SW_FORBS] + v->int_veg[SW_SHRUB] + v->int_veg[SW_GRASS] + v->litter_int; - s->tree_int += v->tree_int; - s->shrub_int += v->shrub_int; - s->forb_int += v->forb_int; - s->grass_int += v->grass_int; + s->int_veg[SW_TREES] += v->int_veg[SW_TREES]; + s->int_veg[SW_SHRUB] += v->int_veg[SW_SHRUB]; + s->int_veg[SW_FORBS] += v->int_veg[SW_FORBS]; + s->int_veg[SW_GRASS] += v->int_veg[SW_GRASS]; s->litter_int += v->litter_int; break; @@ -4401,12 +4401,12 @@ static void sumof_swc(SW_SOILWAT *v, SW_SOILWAT_OUTPUTS *s, OutKey k) case eSW_HydRed: ForEachSoilLayer(i) { - s->hydred_total[i] += v->hydred_tree[i] + v->hydred_forb[i] - + v->hydred_shrub[i] + v->hydred_grass[i]; - s->hydred_tree[i] += v->hydred_tree[i]; - s->hydred_shrub[i] += v->hydred_shrub[i]; - s->hydred_forb[i] += v->hydred_forb[i]; - s->hydred_grass[i] += v->hydred_grass[i]; + s->hydred_total[i] += v->hydred[SW_TREES][i] + v->hydred[SW_FORBS][i] + + v->hydred[SW_SHRUB][i] + v->hydred[SW_GRASS][i]; + s->hydred[SW_TREES][i] += v->hydred[SW_TREES][i]; + s->hydred[SW_SHRUB][i] += v->hydred[SW_SHRUB][i]; + s->hydred[SW_FORBS][i] += v->hydred[SW_FORBS][i]; + s->hydred[SW_GRASS][i] += v->hydred[SW_GRASS][i]; } break; @@ -4628,10 +4628,10 @@ static void average_for(ObjType otyp, OutPeriod pd) ForEachSoilLayer(i) { savg->transp_total[i] = ssumof->transp_total[i] / div; - savg->transp_tree[i] = ssumof->transp_tree[i] / div; - savg->transp_shrub[i] = ssumof->transp_shrub[i] / div; - savg->transp_forb[i] = ssumof->transp_forb[i] / div; - savg->transp_grass[i] = ssumof->transp_grass[i] / div; + savg->transp[SW_TREES][i] = ssumof->transp[SW_TREES][i] / div; + savg->transp[SW_SHRUB][i] = ssumof->transp[SW_SHRUB][i] / div; + savg->transp[SW_FORBS][i] = ssumof->transp[SW_FORBS][i] / div; + savg->transp[SW_GRASS][i] = ssumof->transp[SW_GRASS][i] / div; } break; @@ -4642,20 +4642,20 @@ static void average_for(ObjType otyp, OutPeriod pd) case eSW_EvapSurface: savg->total_evap = ssumof->total_evap / div; - savg->tree_evap = ssumof->tree_evap / div; - savg->shrub_evap = ssumof->shrub_evap / div; - savg->forb_evap = ssumof->forb_evap / div; - savg->grass_evap = ssumof->grass_evap / div; + savg->evap_veg[SW_TREES] = ssumof->evap_veg[SW_TREES] / div; + savg->evap_veg[SW_SHRUB] = ssumof->evap_veg[SW_SHRUB] / div; + savg->evap_veg[SW_FORBS] = ssumof->evap_veg[SW_FORBS] / div; + savg->evap_veg[SW_GRASS] = ssumof->evap_veg[SW_GRASS] / div; savg->litter_evap = ssumof->litter_evap / div; savg->surfaceWater_evap = ssumof->surfaceWater_evap / div; break; case eSW_Interception: savg->total_int = ssumof->total_int / div; - savg->tree_int = ssumof->tree_int / div; - savg->shrub_int = ssumof->shrub_int / div; - savg->forb_int = ssumof->forb_int / div; - savg->grass_int = ssumof->grass_int / div; + savg->int_veg[SW_TREES] = ssumof->int_veg[SW_TREES] / div; + savg->int_veg[SW_SHRUB] = ssumof->int_veg[SW_SHRUB] / div; + savg->int_veg[SW_FORBS] = ssumof->int_veg[SW_FORBS] / div; + savg->int_veg[SW_GRASS] = ssumof->int_veg[SW_GRASS] / div; savg->litter_int = ssumof->litter_int / div; break; @@ -4672,10 +4672,10 @@ static void average_for(ObjType otyp, OutPeriod pd) ForEachSoilLayer(i) { savg->hydred_total[i] = ssumof->hydred_total[i] / div; - savg->hydred_tree[i] = ssumof->hydred_tree[i] / div; - savg->hydred_shrub[i] = ssumof->hydred_shrub[i] / div; - savg->hydred_forb[i] = ssumof->hydred_forb[i] / div; - savg->hydred_grass[i] = ssumof->hydred_grass[i] / div; + savg->hydred[SW_TREES][i] = ssumof->hydred[SW_TREES][i] / div; + savg->hydred[SW_SHRUB][i] = ssumof->hydred[SW_SHRUB][i] / div; + savg->hydred[SW_FORBS][i] = ssumof->hydred[SW_FORBS][i] / div; + savg->hydred[SW_GRASS][i] = ssumof->hydred[SW_GRASS][i] / div; } break; diff --git a/SW_Site.c b/SW_Site.c index cc96ebc49..519a1b21c 100644 --- a/SW_Site.c +++ b/SW_Site.c @@ -492,17 +492,17 @@ static void _read_layers(void) { v->lyr[lyrno]->soilMatric_density = matricd; v->lyr[lyrno]->fractionVolBulk_gravel = f_gravel; v->lyr[lyrno]->evap_coeff = evco; - v->lyr[lyrno]->transp_coeff_forb = trco_forb; - v->lyr[lyrno]->transp_coeff_tree = trco_tree; - v->lyr[lyrno]->transp_coeff_shrub = trco_shrub; - v->lyr[lyrno]->transp_coeff_grass = trco_grass; + v->lyr[lyrno]->transp_coeff[SW_FORBS] = trco_forb; + v->lyr[lyrno]->transp_coeff[SW_TREES] = trco_tree; + v->lyr[lyrno]->transp_coeff[SW_SHRUB] = trco_shrub; + v->lyr[lyrno]->transp_coeff[SW_GRASS] = trco_grass; v->lyr[lyrno]->fractionWeightMatric_sand = psand; v->lyr[lyrno]->fractionWeightMatric_clay = pclay; v->lyr[lyrno]->impermeability = imperm; - v->lyr[lyrno]->my_transp_rgn_tree = 0; - v->lyr[lyrno]->my_transp_rgn_forb = 0; - v->lyr[lyrno]->my_transp_rgn_shrub = 0; - v->lyr[lyrno]->my_transp_rgn_grass = 0; + v->lyr[lyrno]->my_transp_rgn[SW_TREES] = 0; + v->lyr[lyrno]->my_transp_rgn[SW_FORBS] = 0; + v->lyr[lyrno]->my_transp_rgn[SW_SHRUB] = 0; + v->lyr[lyrno]->my_transp_rgn[SW_GRASS] = 0; v->lyr[lyrno]->sTemp = soiltemp; if (evap_ok) { @@ -512,26 +512,26 @@ static void _read_layers(void) { evap_ok = swFALSE; } if (transp_ok_forb) { - if (GT(v->lyr[lyrno]->transp_coeff_forb, 0.0)) { - v->n_transp_lyrs_forb++; + if (GT(v->lyr[lyrno]->transp_coeff[SW_FORBS], 0.0)) { + v->n_transp_lyrs[SW_FORBS]++; } else transp_ok_forb = swFALSE; } if (transp_ok_tree) { - if (GT(v->lyr[lyrno]->transp_coeff_tree, 0.0)) { - v->n_transp_lyrs_tree++; + if (GT(v->lyr[lyrno]->transp_coeff[SW_TREES], 0.0)) { + v->n_transp_lyrs[SW_TREES]++; } else transp_ok_tree = swFALSE; } if (transp_ok_shrub) { - if (GT(v->lyr[lyrno]->transp_coeff_shrub, 0.0)) { - v->n_transp_lyrs_shrub++; + if (GT(v->lyr[lyrno]->transp_coeff[SW_SHRUB], 0.0)) { + v->n_transp_lyrs[SW_SHRUB]++; } else transp_ok_shrub = swFALSE; } if (transp_ok_grass) { - if (GT(v->lyr[lyrno]->transp_coeff_grass, 0.0)) { - v->n_transp_lyrs_grass++; + if (GT(v->lyr[lyrno]->transp_coeff[SW_GRASS], 0.0)) { + v->n_transp_lyrs[SW_GRASS]++; } else transp_ok_grass = swFALSE; } @@ -594,16 +594,16 @@ void init_site_info(void) { lyr = sp->lyr[s]; /* sum ev and tr coefficients for later */ evsum += lyr->evap_coeff; - trsum_forb += lyr->transp_coeff_forb; - trsum_tree += lyr->transp_coeff_tree; - trsum_shrub += lyr->transp_coeff_shrub; - trsum_grass += lyr->transp_coeff_grass; + trsum_forb += lyr->transp_coeff[SW_FORBS]; + trsum_tree += lyr->transp_coeff[SW_TREES]; + trsum_shrub += lyr->transp_coeff[SW_SHRUB]; + trsum_grass += lyr->transp_coeff[SW_GRASS]; /* calculate soil water content at SWPcrit for each vegetation type */ - lyr->swcBulk_atSWPcrit_forb = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.forb.SWPcrit, s) * lyr->width; - lyr->swcBulk_atSWPcrit_tree = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.tree.SWPcrit, s) * lyr->width; - lyr->swcBulk_atSWPcrit_shrub = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.shrub.SWPcrit, s) * lyr->width; - lyr->swcBulk_atSWPcrit_grass = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.grass.SWPcrit, s) * lyr->width; + lyr->swcBulk_atSWPcrit[SW_FORBS] = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.forb.SWPcrit, s) * lyr->width; + lyr->swcBulk_atSWPcrit[SW_TREES] = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.tree.SWPcrit, s) * lyr->width; + lyr->swcBulk_atSWPcrit[SW_SHRUB] = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.shrub.SWPcrit, s) * lyr->width; + lyr->swcBulk_atSWPcrit[SW_GRASS] = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.grass.SWPcrit, s) * lyr->width; /* Find which transpiration region the current soil layer * is in and check validity of result. Region bounds are @@ -614,7 +614,7 @@ void init_site_info(void) { ForEachTranspRegion(r) { if (s < _TranspRgnBounds[r]) { - if (ZRO(lyr->transp_coeff_forb)) + if (ZRO(lyr->transp_coeff[SW_FORBS])) break; /* end of transpiring layers */ curregion = r + 1; break; @@ -623,8 +623,8 @@ void init_site_info(void) { if (curregion || _TranspRgnBounds[curregion] == 0) { LogError(logfp, LOGNOTE, " Layer %d : curregion %d _TranspRgnBounds %d", s + 1, curregion, _TranspRgnBounds[curregion]); - lyr->my_transp_rgn_forb = curregion; - sp->n_transp_lyrs_forb = max(sp->n_transp_lyrs_forb, s); + lyr->my_transp_rgn[SW_FORBS] = curregion; + sp->n_transp_lyrs[SW_FORBS] = max(sp->n_transp_lyrs[SW_FORBS], s); } else if (s == 0) { LogError(logfp, LOGFATAL, "%s : Top soil layer must be included\n" @@ -641,7 +641,7 @@ void init_site_info(void) { ForEachTranspRegion(r) { if (s < _TranspRgnBounds[r]) { - if (ZRO(lyr->transp_coeff_tree)) + if (ZRO(lyr->transp_coeff[SW_TREES])) break; /* end of transpiring layers */ curregion = r + 1; break; @@ -649,8 +649,8 @@ void init_site_info(void) { } if (curregion || _TranspRgnBounds[curregion] == 0) { - lyr->my_transp_rgn_tree = curregion; - sp->n_transp_lyrs_tree = max(sp->n_transp_lyrs_tree, s); + lyr->my_transp_rgn[SW_TREES] = curregion; + sp->n_transp_lyrs[SW_TREES] = max(sp->n_transp_lyrs[SW_TREES], s); } else if (s == 0) { LogError(logfp, LOGFATAL, "%s : Top soil layer must be included\n" @@ -667,7 +667,7 @@ void init_site_info(void) { ForEachTranspRegion(r) { if (s < _TranspRgnBounds[r]) { - if (ZRO(lyr->transp_coeff_shrub)) + if (ZRO(lyr->transp_coeff[SW_SHRUB])) break; /* end of transpiring layers */ curregion = r + 1; break; @@ -675,8 +675,8 @@ void init_site_info(void) { } if (curregion || _TranspRgnBounds[curregion] == 0) { - lyr->my_transp_rgn_shrub = curregion; - sp->n_transp_lyrs_shrub = max(sp->n_transp_lyrs_shrub, s); + lyr->my_transp_rgn[SW_SHRUB] = curregion; + sp->n_transp_lyrs[SW_SHRUB] = max(sp->n_transp_lyrs[SW_SHRUB], s); } else if (s == 0) { LogError(logfp, LOGFATAL, "%s : Top soil layer must be included\n" @@ -692,7 +692,7 @@ void init_site_info(void) { ForEachTranspRegion(r) { if (s < _TranspRgnBounds[r]) { - if (ZRO(lyr->transp_coeff_grass)) + if (ZRO(lyr->transp_coeff[SW_GRASS])) break; /* end of transpiring layers */ curregion = r + 1; break; @@ -700,8 +700,8 @@ void init_site_info(void) { } if (curregion || _TranspRgnBounds[curregion] == 0) { - lyr->my_transp_rgn_grass = curregion; - sp->n_transp_lyrs_grass = max(sp->n_transp_lyrs_grass, s); + lyr->my_transp_rgn[SW_GRASS] = curregion; + sp->n_transp_lyrs[SW_GRASS] = max(sp->n_transp_lyrs[SW_GRASS], s); } else if (s == 0) { LogError(logfp, LOGFATAL, "%s : Top soil layer must be included\n" @@ -770,8 +770,8 @@ void init_site_info(void) { "tr_co_forb sum (%5.4f) != 1.0.\nNew Coefficients are:", MyFileName, trsum_forb); ForEachForbTranspLayer(s) { - SW_Site.lyr[s]->transp_coeff_forb /= trsum_forb; - LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff_forb); + SW_Site.lyr[s]->transp_coeff[SW_FORBS] /= trsum_forb; + LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff[SW_FORBS]); } } if (!EQ(trsum_tree, 1.0)) { @@ -779,8 +779,8 @@ void init_site_info(void) { "tr_co_tree sum (%5.4f) != 1.0.\nNew coefficients are:", MyFileName, trsum_tree); ForEachTreeTranspLayer(s) { - SW_Site.lyr[s]->transp_coeff_tree /= trsum_tree; - LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff_tree); + SW_Site.lyr[s]->transp_coeff[SW_TREES] /= trsum_tree; + LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff[SW_TREES]); } } if (!EQ(trsum_shrub, 1.0)) { @@ -788,8 +788,8 @@ void init_site_info(void) { "tr_co_shrub sum (%5.4f) != 1.0.\nNew coefficients are:", MyFileName, trsum_shrub); ForEachShrubTranspLayer(s) { - SW_Site.lyr[s]->transp_coeff_shrub /= trsum_shrub; - LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff_shrub); + SW_Site.lyr[s]->transp_coeff[SW_SHRUB] /= trsum_shrub; + LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff[SW_SHRUB]); } } if (!EQ(trsum_grass, 1.0)) { @@ -797,8 +797,8 @@ void init_site_info(void) { "tr_co_grass sum (%5.4f) != 1.0.\nNew coefficients are:", MyFileName, trsum_grass); ForEachGrassTranspLayer(s) { - SW_Site.lyr[s]->transp_coeff_grass /= trsum_grass; - LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff_grass); + SW_Site.lyr[s]->transp_coeff[SW_GRASS] /= trsum_grass; + LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff[SW_GRASS]); } } @@ -894,10 +894,10 @@ void _echo_inputs(void) { LogError(logfp, LOGNOTE, " Soils File: %s\n", SW_F_name(eLayers)); LogError(logfp, LOGNOTE, " Number of soil layers: %d\n", s->n_layers); LogError(logfp, LOGNOTE, " Number of evaporation layers: %d\n", s->n_evap_lyrs); - LogError(logfp, LOGNOTE, " Number of forb transpiration layers: %d\n", s->n_transp_lyrs_forb); - LogError(logfp, LOGNOTE, " Number of tree transpiration layers: %d\n", s->n_transp_lyrs_tree); - LogError(logfp, LOGNOTE, " Number of shrub transpiration layers: %d\n", s->n_transp_lyrs_shrub); - LogError(logfp, LOGNOTE, " Number of grass transpiration layers: %d\n", s->n_transp_lyrs_grass); + LogError(logfp, LOGNOTE, " Number of forb transpiration layers: %d\n", s->n_transp_lyrs[SW_FORBS]); + LogError(logfp, LOGNOTE, " Number of tree transpiration layers: %d\n", s->n_transp_lyrs[SW_TREES]); + LogError(logfp, LOGNOTE, " Number of shrub transpiration layers: %d\n", s->n_transp_lyrs[SW_SHRUB]); + LogError(logfp, LOGNOTE, " Number of grass transpiration layers: %d\n", s->n_transp_lyrs[SW_GRASS]); LogError(logfp, LOGNOTE, " Number of transpiration regions: %d\n", s->n_transp_rgn); LogError(logfp, LOGNOTE, "\nLayer Specific Values:\n----------------------\n"); @@ -914,10 +914,10 @@ void _echo_inputs(void) { " %3d %5.1f %9.5f %6.2f %8.5f %8.5f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %9.2f %9.2f %9.2f %9.2f %9.2f %10d %10d %15d %15d %15.4f %9.4f %9.4f %9.4f %9.4f\n", i + 1, s->lyr[i]->width, s->lyr[i]->soilBulk_density, s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_fieldcap / s->lyr[i]->width, s->lyr[i]->swcBulk_wiltpt / s->lyr[i]->width, s->lyr[i]->fractionWeightMatric_sand, s->lyr[i]->fractionWeightMatric_clay, - s->lyr[i]->swcBulk_atSWPcrit_forb / s->lyr[i]->width, s->lyr[i]->swcBulk_atSWPcrit_tree / s->lyr[i]->width, - s->lyr[i]->swcBulk_atSWPcrit_shrub / s->lyr[i]->width, s->lyr[i]->swcBulk_atSWPcrit_grass / s->lyr[i]->width, s->lyr[i]->evap_coeff, - s->lyr[i]->transp_coeff_forb, s->lyr[i]->transp_coeff_tree, s->lyr[i]->transp_coeff_shrub, s->lyr[i]->transp_coeff_grass, s->lyr[i]->my_transp_rgn_forb, - s->lyr[i]->my_transp_rgn_tree, s->lyr[i]->my_transp_rgn_shrub, s->lyr[i]->my_transp_rgn_grass, s->lyr[i]->swcBulk_wet / s->lyr[i]->width, + s->lyr[i]->swcBulk_atSWPcrit[SW_FORBS] / s->lyr[i]->width, s->lyr[i]->swcBulk_atSWPcrit[SW_TREES] / s->lyr[i]->width, + s->lyr[i]->swcBulk_atSWPcrit[SW_SHRUB] / s->lyr[i]->width, s->lyr[i]->swcBulk_atSWPcrit[SW_GRASS] / s->lyr[i]->width, s->lyr[i]->evap_coeff, + s->lyr[i]->transp_coeff[SW_FORBS], s->lyr[i]->transp_coeff[SW_TREES], s->lyr[i]->transp_coeff[SW_SHRUB], s->lyr[i]->transp_coeff[SW_GRASS], s->lyr[i]->my_transp_rgn[SW_FORBS], + s->lyr[i]->my_transp_rgn[SW_TREES], s->lyr[i]->my_transp_rgn[SW_SHRUB], s->lyr[i]->my_transp_rgn[SW_GRASS], s->lyr[i]->swcBulk_wet / s->lyr[i]->width, s->lyr[i]->swcBulk_min / s->lyr[i]->width, s->lyr[i]->swcBulk_init / s->lyr[i]->width, s->lyr[i]->swcBulk_saturated / s->lyr[i]->width, s->lyr[i]->impermeability); @@ -934,8 +934,8 @@ void _echo_inputs(void) { { LogError(logfp, LOGNOTE, " %3d %5.1f %9.5f %6.2f %8.5f %8.5f %6.2f %6.2f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %8.4f %7.4f %5.4f\n", i + 1, s->lyr[i]->width, s->lyr[i]->soilBulk_density, s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_fieldcap, s->lyr[i]->swcBulk_wiltpt, s->lyr[i]->fractionWeightMatric_sand, - s->lyr[i]->fractionWeightMatric_clay, s->lyr[i]->swcBulk_atSWPcrit_forb, s->lyr[i]->swcBulk_atSWPcrit_tree, s->lyr[i]->swcBulk_atSWPcrit_shrub, - s->lyr[i]->swcBulk_atSWPcrit_grass, s->lyr[i]->swcBulk_wet, s->lyr[i]->swcBulk_min, s->lyr[i]->swcBulk_init, s->lyr[i]->swcBulk_saturated, s->lyr[i]->sTemp); + s->lyr[i]->fractionWeightMatric_clay, s->lyr[i]->swcBulk_atSWPcrit[SW_FORBS], s->lyr[i]->swcBulk_atSWPcrit[SW_TREES], s->lyr[i]->swcBulk_atSWPcrit[SW_SHRUB], + s->lyr[i]->swcBulk_atSWPcrit[SW_GRASS], s->lyr[i]->swcBulk_wet, s->lyr[i]->swcBulk_min, s->lyr[i]->swcBulk_init, s->lyr[i]->swcBulk_saturated, s->lyr[i]->sTemp); } LogError(logfp, LOGNOTE, "\n Water Potential values:\n"); @@ -950,10 +950,10 @@ void _echo_inputs(void) { LogError(logfp, LOGNOTE, " %3d %15.4f %15.4f %15.4f %15.4f %15.4f %15.4f %15.4f %15.4f %15.4f\n", i + 1, SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_fieldcap, i), SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_wiltpt, i), - SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_atSWPcrit_forb, i), - SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_atSWPcrit_tree, i), - SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_atSWPcrit_shrub, i), - SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_atSWPcrit_grass, i), + SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_atSWPcrit[SW_FORBS], i), + SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_atSWPcrit[SW_TREES], i), + SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_atSWPcrit[SW_SHRUB], i), + SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_atSWPcrit[SW_GRASS], i), SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_wet, i), SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_min, i), SW_SWCbulk2SWPmatric(s->lyr[i]->fractionVolBulk_gravel, s->lyr[i]->swcBulk_init, i)); diff --git a/SW_Site.h b/SW_Site.h index f05c326a5..a8f2529b3 100644 --- a/SW_Site.h +++ b/SW_Site.h @@ -39,7 +39,7 @@ fractionVolBulk_gravel is the gravel content as a fraction of the bulk soil renamed many of the of the variables in SW_LAYER_INFO to better reflect BULK and MATRIC values due to the renaming, also had to update the use of these variables in the other files. - 07/09/2013 (clk) added the variables transp_coeff_forb, swcBulk_atSWPcrit_forb, and my_transp_rgn_forb to SW_LAYER_INFO + 07/09/2013 (clk) added the variables transp_coeff[SW_FORBS], swcBulk_atSWPcrit[SW_FORBS], and my_transp_rgn[SW_FORBS] to SW_LAYER_INFO 07/09/2013 (clk) added the variable n_transp_lyrs_forb to SW_SITE */ /********************************************************/ @@ -57,7 +57,7 @@ typedef struct { RealD width, /* width of the soil layer (cm) */ soilBulk_density, /* bulk soil density, i.e., including gravel component, (g/cm3) */ evap_coeff, /* prop. of total soil evap from this layer */ - transp_coeff_forb, transp_coeff_tree, transp_coeff_shrub, transp_coeff_grass, /* prop. of total transp from this layer */ + transp_coeff[NVEGTYPES], /* prop. of total transp from this layer */ soilMatric_density, /* matric soil density, i.e., gravel component excluded, (g/cm3) */ fractionVolBulk_gravel, /* gravel content (> 2 mm) as volume-fraction of bulk soil (g/cm3) */ fractionWeightMatric_sand, /* sand content (< 2 mm & > . mm) as weight-fraction of matric soil (g/g) */ @@ -69,7 +69,7 @@ typedef struct { swcBulk_min, /* swc cannot go below this (cm) *width */ swcBulk_saturated, /* saturated soil water content (cm) * width */ impermeability, /* fraction of how impermeable a layer is (0=permeable, 1=impermeable) */ - swcBulk_atSWPcrit_forb, swcBulk_atSWPcrit_tree, swcBulk_atSWPcrit_shrub, swcBulk_atSWPcrit_grass, /* swc at the critical soil water potential */ + swcBulk_atSWPcrit[NVEGTYPES], /* swc at the critical soil water potential */ thetasMatric, /* This group is parameters for */ psisMatric, /* Cosby et al. (1982) SWC <-> SWP */ @@ -78,10 +78,10 @@ typedef struct { sTemp; /* initial soil temperature for each soil layer */ - LyrIndex my_transp_rgn_forb, my_transp_rgn_tree, my_transp_rgn_shrub, my_transp_rgn_grass; /* which transp zones from Site am I in? */ - + LyrIndex my_transp_rgn[NVEGTYPES]; /* which transp zones from Site am I in? */ } SW_LAYER_INFO; + typedef struct { Bool reset_yr, /* 1: reset values at start of each year */ @@ -91,8 +91,9 @@ typedef struct { LyrIndex n_layers, /* total number of soil layers */ n_transp_rgn, /* soil layers are grouped into n transp. regions */ n_evap_lyrs, /* number of layers in which evap is possible */ - n_transp_lyrs_forb, n_transp_lyrs_tree, n_transp_lyrs_shrub, n_transp_lyrs_grass, /* layer index of deepest transp. region */ + n_transp_lyrs[NVEGTYPES], /* layer index of deepest transp. region */ deep_lyr; /* index of deep drainage layer if deepdrain, 0 otherwise */ + RealD slow_drain_coeff, /* low soil water drainage coefficient */ pet_scale, /* changes relative effect of PET calculation */ latitude, /* latitude of the site (radians) */ diff --git a/SW_SoilWater.h b/SW_SoilWater.h index 12ad52783..11a846db5 100644 --- a/SW_SoilWater.h +++ b/SW_SoilWater.h @@ -23,8 +23,8 @@ 02/19/2011 (drs) moved soil_inf from SW_SOILWAT and SW_SOILWAT_OUTPUTS to SW_WEATHER and SW_WEATHER_OUTPUTS 07/22/2011 (drs) added for saturated conditions: surfaceWater and surfaceWater_evap to SW_SOILWAT_OUTPUTS and SW_SOILWAT 08/22/2011 (drs) added function RealD SW_SnowDepth( RealD SWE, RealD snowdensity) - 09/08/2011 (drs) replaced in both struct SW_SOILWAT_OUTPUTS and SW_SOILWAT RealD crop_int, forest_int with RealD tree_int, shrub_int, grass_int - 09/09/2011 (drs) replaced in both struct SW_SOILWAT_OUTPUTS and SW_SOILWAT RealD veg_evap with RealD tree_evap, shrub_evap, grass_evap + 09/08/2011 (drs) replaced in both struct SW_SOILWAT_OUTPUTS and SW_SOILWAT RealD crop_int, forest_int with RealD int_veg[SW_TREES], int_veg[SW_SHRUB], int_veg[SW_GRASS] + 09/09/2011 (drs) replaced in both struct SW_SOILWAT_OUTPUTS and SW_SOILWAT RealD veg_evap with RealD evap_veg[SW_TREES], evap_veg[SW_SHRUB], evap_veg[SW_GRASS] 09/09/2011 (drs) replaced in both struct SW_SOILWAT_OUTPUTS and SW_SOILWAT RealD transpiration and hydred with RealD transpiration_xx, hydred_xx for each vegetation type (tree, shrub, grass) 09/12/2011 (drs) added RealD snowdepth [TWO_DAYS] to struct SW_SOILWAT_OUTPUTS and SW_SOILWAT 02/03/2012 (drs) added function 'RealD SW_SWC_SWCres(RealD sand, RealD clay, RealD porosity)': which calculates 'Brooks-Corey' residual volumetric soil water based on Rawls & Brakensiek (1985) @@ -32,8 +32,8 @@ 04/16/2013 (clk) Added the variables vwcMatric, and swaMatric to SW_SOILWAT_OUTPUTS Also, renamed a few of the other variables to better reflect MATRIC vs BULK values and SWC vs VWC. modified the use of these variables throughout the rest of the code. - 07/09/2013 (clk) Added the variables transp_forb, forb_evap, hydred_forb, and forb_int to SW_SOILWAT_OUTPUTS - Added the variables transpiration_forb, hydred_forb, forb_evap, and forb_int to SW_SOILWAT + 07/09/2013 (clk) Added the variables transp_forb, evap_veg[SW_FORBS], hydred[SW_FORBS], and int_veg[SW_FORBS] to SW_SOILWAT_OUTPUTS + Added the variables transpiration_forb, hydred[SW_FORBS], evap_veg[SW_FORBS], and int_veg[SW_FORBS] to SW_SOILWAT */ /********************************************************/ /********************************************************/ @@ -66,17 +66,15 @@ typedef struct { vwcMatric[MAX_LAYERS], swcBulk[MAX_LAYERS], /* soil water content cm/layer */ swpMatric[MAX_LAYERS], /* soil water potential */ swaBulk[MAX_LAYERS], /* available soil water cm/layer, swc-(wilting point) */ - swaMatric[MAX_LAYERS], transp_total[MAX_LAYERS], transp_tree[MAX_LAYERS], transp_forb[MAX_LAYERS], transp_shrub[MAX_LAYERS], transp_grass[MAX_LAYERS], evap[MAX_LAYERS], - lyrdrain[MAX_LAYERS], hydred_total[MAX_LAYERS], hydred_tree[MAX_LAYERS], /* hydraulic redistribution cm/layer */ - hydred_forb[MAX_LAYERS], hydred_shrub[MAX_LAYERS], hydred_grass[MAX_LAYERS], surfaceWater, total_evap, surfaceWater_evap, tree_evap, forb_evap, shrub_evap, - grass_evap, - litter_evap, - total_int, - tree_int, - forb_int, - shrub_int, - grass_int, - litter_int, + swaMatric[MAX_LAYERS], + transp_total[MAX_LAYERS], transp[NVEGTYPES][MAX_LAYERS], + evap[MAX_LAYERS], + lyrdrain[MAX_LAYERS], + hydred_total[MAX_LAYERS], hydred[NVEGTYPES][MAX_LAYERS], /* hydraulic redistribution cm/layer */ + surfaceWater, surfaceWater_evap, + total_evap, evap_veg[NVEGTYPES], + litter_evap, + total_int, int_veg[NVEGTYPES], litter_int, snowpack, snowdepth, et, @@ -93,19 +91,19 @@ typedef struct { /* current daily soil water related values */ Bool is_wet[MAX_LAYERS]; /* swc sufficient to count as wet today */ - RealD swcBulk[TWO_DAYS][MAX_LAYERS], snowpack[TWO_DAYS], /* swe of snowpack, if accumulation flag set */ - snowdepth, transpiration_tree[MAX_LAYERS], transpiration_forb[MAX_LAYERS], transpiration_shrub[MAX_LAYERS], transpiration_grass[MAX_LAYERS], evaporation[MAX_LAYERS], - drain[MAX_LAYERS], /* amt of swc able to drain from curr layer to next */ - hydred_tree[MAX_LAYERS], /* hydraulic redistribution cm/layer */ - hydred_forb[MAX_LAYERS], hydred_shrub[MAX_LAYERS], hydred_grass[MAX_LAYERS], surfaceWater, surfaceWater_evap, pet, aet, litter_evap, tree_evap, forb_evap, - shrub_evap, grass_evap, - litter_int, - tree_int, - forb_int, - shrub_int, - grass_int, - sTemp[MAX_LAYERS], - surfaceTemp; // soil surface temperature + RealD swcBulk[TWO_DAYS][MAX_LAYERS], + snowpack[TWO_DAYS], /* swe of snowpack, if accumulation flag set */ + snowdepth, + transpiration[NVEGTYPES][MAX_LAYERS], + evaporation[MAX_LAYERS], + drain[MAX_LAYERS], /* amt of swc able to drain from curr layer to next */ + hydred[NVEGTYPES][MAX_LAYERS], /* hydraulic redistribution cm/layer */ + surfaceWater, surfaceWater_evap, + pet, aet, + litter_evap, evap_veg[NVEGTYPES], + litter_int, int_veg[NVEGTYPES], + sTemp[MAX_LAYERS], + surfaceTemp; // soil surface temperature Bool partsError; // soil temperature error indicator diff --git a/SW_VegEstab.c b/SW_VegEstab.c index 24debe760..32096ab39 100644 --- a/SW_VegEstab.c +++ b/SW_VegEstab.c @@ -377,7 +377,9 @@ static void _sanity_check(unsigned int sppnum) { SW_VEGESTAB_INFO *v = SW_VegEstab.parms[sppnum]; LyrIndex min_transp_lyrs; - min_transp_lyrs = min(SW_Site.n_transp_lyrs_tree, min(SW_Site.n_transp_lyrs_forb, min(SW_Site.n_transp_lyrs_shrub, SW_Site.n_transp_lyrs_grass))); + min_transp_lyrs = min(SW_Site.n_transp_lyrs[SW_TREES], + min(SW_Site.n_transp_lyrs[SW_SHRUB], min(SW_Site.n_transp_lyrs[SW_FORBS], + SW_Site.n_transp_lyrs[SW_GRASS]))); if (v->estab_lyrs > min_transp_lyrs) { LogError(logfp, LOGFATAL, "%s : Layers requested (estab_lyrs) > (# transpiration layers=%d).", MyFileName, min_transp_lyrs); From 2c87e85aceaf9326f5e6fc3a766c765e48595873 Mon Sep 17 00:00:00 2001 From: dschlaep Date: Mon, 22 Jan 2018 18:37:47 -0500 Subject: [PATCH 2/8] Convert vegetation variables into arrays (part 2) - address #135 - convert vegetation variables defined in SW_VegProd.h --- SW_Carbon.c | 26 +- SW_Defines.h | 1 + SW_Flow.c | 282 +++++++++--------- SW_Output.c | 106 ++++--- SW_Output_mock.c | 2 +- SW_Site.c | 10 +- SW_VegProd.c | 619 +++++++++++++++++----------------------- SW_VegProd.h | 4 +- test/test_SW_Carbon.cc | 14 +- test/test_SW_VegProd.cc | 27 +- 10 files changed, 493 insertions(+), 598 deletions(-) diff --git a/SW_Carbon.c b/SW_Carbon.c index 8951fbb23..e5e7160c9 100644 --- a/SW_Carbon.c +++ b/SW_Carbon.c @@ -209,6 +209,7 @@ void SW_CBN_read(void) * be simulated. */ void calculate_CO2_multipliers(void) { + int k; TimeInt year, simendyr = SW_Model.endyr + SW_Model.addtl_yr; double ppm; @@ -235,28 +236,25 @@ void calculate_CO2_multipliers(void) { } // Calculate multipliers per PFT - if (c->use_bio_mult) - { - v->grass.co2_multipliers[BIO_INDEX][year] = v->grass.co2_bio_coeff1 * pow(ppm, v->grass.co2_bio_coeff2); - v->shrub.co2_multipliers[BIO_INDEX][year] = v->shrub.co2_bio_coeff1 * pow(ppm, v->shrub.co2_bio_coeff2); - v->tree.co2_multipliers[BIO_INDEX][year] = v->tree.co2_bio_coeff1 * pow(ppm, v->tree.co2_bio_coeff2); - v->forb.co2_multipliers[BIO_INDEX][year] = v->forb.co2_bio_coeff1 * pow(ppm, v->forb.co2_bio_coeff2); + if (c->use_bio_mult) { + ForEachVegType(k) { + v->veg[k].co2_multipliers[BIO_INDEX][year] = v->veg[k].co2_bio_coeff1 * pow(ppm, v->veg[k].co2_bio_coeff2); + } } #ifdef SWDEBUG if (debug) { swprintf("Shrub: use%d: bio_mult[%d] = %1.3f / coeff1 = %1.3f / coeff2 = %1.3f / ppm = %3.2f\n", - c->use_bio_mult, year, v->shrub.co2_multipliers[BIO_INDEX][year], - v->shrub.co2_bio_coeff1, v->shrub.co2_bio_coeff2, ppm); + c->use_bio_mult, year, v->veg[SW_SHRUB].co2_multipliers[BIO_INDEX][year], + v->veg[SW_SHRUB].co2_bio_coeff1, v->veg[SW_SHRUB].co2_bio_coeff2, ppm); } #endif - if (c->use_wue_mult) - { - v->grass.co2_multipliers[WUE_INDEX][year] = v->grass.co2_wue_coeff1 * pow(ppm, v->grass.co2_wue_coeff2); - v->shrub.co2_multipliers[WUE_INDEX][year] = v->shrub.co2_wue_coeff1 * pow(ppm, v->shrub.co2_wue_coeff2); - v->tree.co2_multipliers[WUE_INDEX][year] = v->tree.co2_wue_coeff1 * pow(ppm, v->tree.co2_wue_coeff2); - v->forb.co2_multipliers[WUE_INDEX][year] = v->forb.co2_wue_coeff1 * pow(ppm, v->forb.co2_wue_coeff2); + if (c->use_wue_mult) { + ForEachVegType(k) { + v->veg[k].co2_multipliers[WUE_INDEX][year] = v->veg[k].co2_wue_coeff1 * + pow(ppm, v->veg[k].co2_wue_coeff2); + } } } } diff --git a/SW_Defines.h b/SW_Defines.h index 3273d07d7..68c64ea23 100644 --- a/SW_Defines.h +++ b/SW_Defines.h @@ -82,6 +82,7 @@ #define ForEachGrassTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs[SW_GRASS]; (i)++) #define ForEachForbTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs[SW_FORBS]; (i)++) #define ForEachTranspRegion(r) for((r)=0; (r) < SW_Site.n_transp_rgn; (r)++) +#define ForEachVegType(k) for ((k) = 0; (k) < NVEGTYPES; (k)++) /* define m as Months */ #define ForEachMonth(m) for((m)=Jan; (m) <= Dec; (m)++) diff --git a/SW_Flow.c b/SW_Flow.c index 520c79c16..275d8f87a 100644 --- a/SW_Flow.c +++ b/SW_Flow.c @@ -87,7 +87,7 @@ Added soil_evap_rate_bs to rate_help, and then adjusted soil_evap_rate_bs by rate_help if needed, Added call to remove bare-soil evap from swv, And added lyrEvap_BareGround into the calculation for SW_Soilwat.evaporation. - Also, added SW_W_VegProd.bare_cov.albedo*SW_VegProd.fractionBareGround to the paramater in petfunc() that was originally SW_VegProd.grass.cov.albedo*SW_VegProd.fractionGrass + SW_VegProd.shrub.cov.albedo*SW_VegProd.shrub.cov.fCover + SW_VegProd.tree.cov.albedo*SW_VegProd.tree.cov.fCover + Also, added SW_W_VegProd.bare_cov.albedo*SW_VegProd.fractionBareGround to the paramater in petfunc() that was originally SW_VegProd.veg[SW_GRASS].cov.albedo*SW_VegProd.fractionGrass + SW_VegProd.shrub.cov.albedo*SW_VegProd.shrub.cov.fCover + SW_VegProd.tree.cov.albedo*SW_VegProd.tree.cov.fCover 04/16/2013 (clk) Renamed a lot of the variables to better reflect BULK versus MATRIC values updated the use of these variables in all the files 06/24/2013 (rjm) added 'soil_temp_error', 'soil_temp_init' and 'fusion_pool_init' as global variable @@ -190,6 +190,7 @@ void SW_FLW_construct(void) { SW_Soilwat.partsError = swFALSE; soil_temp_init = 0; fusion_pool_init = 0; + //These only have to be cleared if a loop is wrong in the code. for (i = 0; i < MAX_LAYERS; i++) { lyrTrRegions_Forb[i] = lyrTrRegions_Tree[i] = lyrTrRegions_Shrub[i] = lyrTrRegions_Grass[i] = 0; @@ -202,8 +203,10 @@ void SW_FLW_construct(void) { lyrHydRed_Tree[i] = lyrHydRed_Shrub[i] = lyrHydRed_Grass[i] = lyrImpermeability[i] = lyrSWCBulk_Saturated[i] = 0; lyroldsTemp[i] = lyrsTemp[i] = lyrbDensity[i] = 0; } + for(i=0; i<= MAX_TRANSP_REGIONS; i++) lyrSumTrCo[i] = 0; + //When running as a library make sure these are set to zero. drainout = 0; surfaceTemp[0] = surfaceTemp[1] = 0.0; @@ -217,6 +220,9 @@ void SW_FLW_construct(void) { /* --------------------------------------------------- */ void SW_Water_Flow(void) { + SW_VEGPROD *v = &SW_VegProd; + SW_SOILWAT *sw = &SW_Soilwat; + RealD swpot_avg_forb, swpot_avg_tree, swpot_avg_shrub, swpot_avg_grass, soil_evap_forb, soil_evap_tree, soil_evap_shrub, soil_evap_grass, soil_evap_rate_forb = 1., soil_evap_rate_tree = 1., soil_evap_rate_shrub = 1., soil_evap_rate_grass = 1., soil_evap_rate_bs = 1., transp_forb, transp_tree, transp_shrub, transp_grass, transp_rate_forb = 1., transp_rate_tree = 1., transp_rate_shrub = 1., transp_rate_grass = 1., snow_evap_rate, surface_evap_forb_rate, surface_evap_tree_rate, @@ -233,7 +239,7 @@ void SW_Water_Flow(void) { records2arrays(); /* snowdepth scaling */ - SW_Soilwat.snowdepth = SW_SnowDepth(SW_Soilwat.snowpack[Today], SW_Sky.snow_density_daily[doy]); + sw->snowdepth = SW_SnowDepth(sw->snowpack[Today], SW_Sky.snow_density_daily[doy]); /* if snow depth is deeper than vegetation height then - rain and snowmelt infiltrates directly to soil (no vegetation or litter interception of today) only @@ -241,86 +247,86 @@ void SW_Water_Flow(void) { - infiltrate water high - infiltrate water low */ - if (GT(SW_VegProd.grass.veg_height_daily[doy], 0.)) { - snowdepth_scale_grass = 1. - SW_Soilwat.snowdepth / SW_VegProd.grass.veg_height_daily[doy]; + if (GT(v->veg[SW_GRASS].veg_height_daily[doy], 0.)) { + snowdepth_scale_grass = 1. - sw->snowdepth / v->veg[SW_GRASS].veg_height_daily[doy]; } else { snowdepth_scale_grass = 1.; } - if (GT(SW_VegProd.forb.veg_height_daily[doy], 0.)) { - snowdepth_scale_forb = 1. - SW_Soilwat.snowdepth / SW_VegProd.forb.veg_height_daily[doy]; + if (GT(v->veg[SW_FORBS].veg_height_daily[doy], 0.)) { + snowdepth_scale_forb = 1. - sw->snowdepth / v->veg[SW_FORBS].veg_height_daily[doy]; } else { snowdepth_scale_forb = 1.; } - if (GT(SW_VegProd.shrub.veg_height_daily[doy], 0.)) { - snowdepth_scale_shrub = 1. - SW_Soilwat.snowdepth / SW_VegProd.shrub.veg_height_daily[doy]; + if (GT(v->veg[SW_SHRUB].veg_height_daily[doy], 0.)) { + snowdepth_scale_shrub = 1. - sw->snowdepth / v->veg[SW_SHRUB].veg_height_daily[doy]; } else { snowdepth_scale_shrub = 1.; } - if (GT(SW_VegProd.tree.veg_height_daily[doy], 0.)) { - snowdepth_scale_tree = 1. - SW_Soilwat.snowdepth / SW_VegProd.tree.veg_height_daily[doy]; + if (GT(v->veg[SW_TREES].veg_height_daily[doy], 0.)) { + snowdepth_scale_tree = 1. - sw->snowdepth / v->veg[SW_TREES].veg_height_daily[doy]; } else { snowdepth_scale_tree = 1.; } /* Interception */ ppt_toUse = SW_Weather.now.rain[Today]; /* ppt is partioned into ppt = snow + rain */ - if (GT(SW_VegProd.tree.cov.fCover, 0.) && GT(snowdepth_scale_tree, 0.)) { /* trees present AND trees not fully covered in snow */ - tree_intercepted_water(&h2o_for_soil, &tree_h2o, ppt_toUse, SW_VegProd.tree.lai_live_daily[doy], snowdepth_scale_tree * SW_VegProd.tree.cov.fCover, - SW_VegProd.tree.veg_intPPT_a, SW_VegProd.tree.veg_intPPT_b, SW_VegProd.tree.veg_intPPT_c, SW_VegProd.tree.veg_intPPT_d); + if (GT(v->veg[SW_TREES].cov.fCover, 0.) && GT(snowdepth_scale_tree, 0.)) { /* trees present AND trees not fully covered in snow */ + tree_intercepted_water(&h2o_for_soil, &tree_h2o, ppt_toUse, v->veg[SW_TREES].lai_live_daily[doy], snowdepth_scale_tree * v->veg[SW_TREES].cov.fCover, + v->veg[SW_TREES].veg_intPPT_a, v->veg[SW_TREES].veg_intPPT_b, v->veg[SW_TREES].veg_intPPT_c, v->veg[SW_TREES].veg_intPPT_d); ppt_toUse = h2o_for_soil; /* amount of rain that is not intercepted by the forest canopy */ } else { /* snow depth is more than vegetation height */ h2o_for_soil = ppt_toUse; tree_h2o = 0.; } /* end forest interception */ - if (GT(SW_VegProd.shrub.cov.fCover, 0.) && GT(snowdepth_scale_shrub, 0.)) { - shrub_intercepted_water(&h2o_for_soil, &shrub_h2o, ppt_toUse, SW_VegProd.shrub.vegcov_daily[doy], snowdepth_scale_shrub * SW_VegProd.shrub.cov.fCover, - SW_VegProd.shrub.veg_intPPT_a, SW_VegProd.shrub.veg_intPPT_b, SW_VegProd.shrub.veg_intPPT_c, SW_VegProd.shrub.veg_intPPT_d); + if (GT(v->veg[SW_SHRUB].cov.fCover, 0.) && GT(snowdepth_scale_shrub, 0.)) { + shrub_intercepted_water(&h2o_for_soil, &shrub_h2o, ppt_toUse, v->veg[SW_SHRUB].vegcov_daily[doy], snowdepth_scale_shrub * v->veg[SW_SHRUB].cov.fCover, + v->veg[SW_SHRUB].veg_intPPT_a, v->veg[SW_SHRUB].veg_intPPT_b, v->veg[SW_SHRUB].veg_intPPT_c, v->veg[SW_SHRUB].veg_intPPT_d); ppt_toUse = h2o_for_soil; /* amount of rain that is not intercepted by the shrub canopy */ } else { shrub_h2o = 0.; } /* end shrub interception */ - if (GT(SW_VegProd.forb.cov.fCover, 0.) && GT(snowdepth_scale_forb, 0.)) { /* forbs present AND not fully covered in snow */ - forb_intercepted_water(&h2o_for_soil, &forb_h2o, ppt_toUse, SW_VegProd.forb.vegcov_daily[doy], snowdepth_scale_forb * SW_VegProd.forb.cov.fCover, - SW_VegProd.forb.veg_intPPT_a, SW_VegProd.forb.veg_intPPT_b, SW_VegProd.forb.veg_intPPT_c, SW_VegProd.forb.veg_intPPT_d); + if (GT(v->veg[SW_FORBS].cov.fCover, 0.) && GT(snowdepth_scale_forb, 0.)) { /* forbs present AND not fully covered in snow */ + forb_intercepted_water(&h2o_for_soil, &forb_h2o, ppt_toUse, v->veg[SW_FORBS].vegcov_daily[doy], snowdepth_scale_forb * v->veg[SW_FORBS].cov.fCover, + v->veg[SW_FORBS].veg_intPPT_a, v->veg[SW_FORBS].veg_intPPT_b, v->veg[SW_FORBS].veg_intPPT_c, v->veg[SW_FORBS].veg_intPPT_d); ppt_toUse = h2o_for_soil; /* amount of rain that is not intercepted by the forbs */ } else { /* snow depth is more than vegetation height */ forb_h2o = 0.; } /* end forb interception */ - if (GT(SW_VegProd.grass.cov.fCover, 0.) && GT(snowdepth_scale_grass, 0.)) { - grass_intercepted_water(&h2o_for_soil, &grass_h2o, ppt_toUse, SW_VegProd.grass.vegcov_daily[doy], snowdepth_scale_grass * SW_VegProd.grass.cov.fCover, - SW_VegProd.grass.veg_intPPT_a, SW_VegProd.grass.veg_intPPT_b, SW_VegProd.grass.veg_intPPT_c, SW_VegProd.grass.veg_intPPT_d); + if (GT(v->veg[SW_GRASS].cov.fCover, 0.) && GT(snowdepth_scale_grass, 0.)) { + grass_intercepted_water(&h2o_for_soil, &grass_h2o, ppt_toUse, v->veg[SW_GRASS].vegcov_daily[doy], snowdepth_scale_grass * v->veg[SW_GRASS].cov.fCover, + v->veg[SW_GRASS].veg_intPPT_a, v->veg[SW_GRASS].veg_intPPT_b, v->veg[SW_GRASS].veg_intPPT_c, v->veg[SW_GRASS].veg_intPPT_d); } else { grass_h2o = 0.; } /* end grass interception */ - if (EQ(SW_Soilwat.snowpack[Today], 0.)) { /* litter interception only when no snow */ + if (EQ(sw->snowpack[Today], 0.)) { /* litter interception only when no snow */ litter_h2o_help = 0.; - if (GT(SW_VegProd.tree.cov.fCover, 0.)) { - litter_intercepted_water(&h2o_for_soil, &litter_h2o, SW_VegProd.tree.litter_daily[doy], SW_VegProd.tree.cov.fCover, SW_VegProd.tree.litt_intPPT_a, - SW_VegProd.tree.litt_intPPT_b, SW_VegProd.tree.litt_intPPT_c, SW_VegProd.tree.litt_intPPT_d); + if (GT(v->veg[SW_TREES].cov.fCover, 0.)) { + litter_intercepted_water(&h2o_for_soil, &litter_h2o, v->veg[SW_TREES].litter_daily[doy], v->veg[SW_TREES].cov.fCover, v->veg[SW_TREES].litt_intPPT_a, + v->veg[SW_TREES].litt_intPPT_b, v->veg[SW_TREES].litt_intPPT_c, v->veg[SW_TREES].litt_intPPT_d); litter_h2o_help += litter_h2o; } - if (GT(SW_VegProd.shrub.cov.fCover, 0.)) { - litter_intercepted_water(&h2o_for_soil, &litter_h2o, SW_VegProd.shrub.litter_daily[doy], SW_VegProd.shrub.cov.fCover, SW_VegProd.shrub.litt_intPPT_a, - SW_VegProd.shrub.litt_intPPT_b, SW_VegProd.shrub.litt_intPPT_c, SW_VegProd.shrub.litt_intPPT_d); + if (GT(v->veg[SW_SHRUB].cov.fCover, 0.)) { + litter_intercepted_water(&h2o_for_soil, &litter_h2o, v->veg[SW_SHRUB].litter_daily[doy], v->veg[SW_SHRUB].cov.fCover, v->veg[SW_SHRUB].litt_intPPT_a, + v->veg[SW_SHRUB].litt_intPPT_b, v->veg[SW_SHRUB].litt_intPPT_c, v->veg[SW_SHRUB].litt_intPPT_d); litter_h2o_help += litter_h2o; } - if (GT(SW_VegProd.forb.cov.fCover, 0.)) { - litter_intercepted_water(&h2o_for_soil, &litter_h2o, SW_VegProd.forb.litter_daily[doy], SW_VegProd.forb.cov.fCover, SW_VegProd.forb.litt_intPPT_a, - SW_VegProd.forb.litt_intPPT_b, SW_VegProd.forb.litt_intPPT_c, SW_VegProd.forb.litt_intPPT_d); + if (GT(v->veg[SW_FORBS].cov.fCover, 0.)) { + litter_intercepted_water(&h2o_for_soil, &litter_h2o, v->veg[SW_FORBS].litter_daily[doy], v->veg[SW_FORBS].cov.fCover, v->veg[SW_FORBS].litt_intPPT_a, + v->veg[SW_FORBS].litt_intPPT_b, v->veg[SW_FORBS].litt_intPPT_c, v->veg[SW_FORBS].litt_intPPT_d); litter_h2o_help += litter_h2o; } - if (GT(SW_VegProd.grass.cov.fCover, 0.)) { - litter_intercepted_water(&h2o_for_soil, &litter_h2o, SW_VegProd.grass.litter_daily[doy], SW_VegProd.grass.cov.fCover, SW_VegProd.grass.litt_intPPT_a, - SW_VegProd.grass.litt_intPPT_b, SW_VegProd.grass.litt_intPPT_c, SW_VegProd.grass.litt_intPPT_d); + if (GT(v->veg[SW_GRASS].cov.fCover, 0.)) { + litter_intercepted_water(&h2o_for_soil, &litter_h2o, v->veg[SW_GRASS].litter_daily[doy], v->veg[SW_GRASS].cov.fCover, v->veg[SW_GRASS].litt_intPPT_a, + v->veg[SW_GRASS].litt_intPPT_b, v->veg[SW_GRASS].litt_intPPT_c, v->veg[SW_GRASS].litt_intPPT_d); litter_h2o_help += litter_h2o; } @@ -330,11 +336,11 @@ void SW_Water_Flow(void) { } /* Sum cumulative intercepted components */ - SW_Soilwat.int_veg[SW_TREES] = tree_h2o; - SW_Soilwat.int_veg[SW_SHRUB] = shrub_h2o; - SW_Soilwat.int_veg[SW_FORBS] = forb_h2o; - SW_Soilwat.int_veg[SW_GRASS] = grass_h2o; - SW_Soilwat.litter_int = litter_h2o; + sw->int_veg[SW_TREES] = tree_h2o; + sw->int_veg[SW_SHRUB] = shrub_h2o; + sw->int_veg[SW_FORBS] = forb_h2o; + sw->int_veg[SW_GRASS] = grass_h2o; + sw->litter_int = litter_h2o; tree_h2o_qum[Today] = tree_h2o_qum[Yesterday] + tree_h2o; shrub_h2o_qum[Today] = shrub_h2o_qum[Yesterday] + shrub_h2o; @@ -407,65 +413,65 @@ void SW_Water_Flow(void) { /* PET */ - SW_Soilwat.pet = SW_Site.pet_scale + sw->pet = SW_Site.pet_scale * petfunc(doy, SW_Weather.now.temp_avg[Today], SW_Site.latitude, SW_Site.altitude, SW_Site.slope, SW_Site.aspect, - SW_VegProd.grass.cov.albedo * SW_VegProd.grass.cov.fCover + SW_VegProd.shrub.cov.albedo * SW_VegProd.shrub.cov.fCover + SW_VegProd.forb.cov.albedo * SW_VegProd.forb.cov.fCover - + SW_VegProd.tree.cov.albedo * SW_VegProd.tree.cov.fCover + SW_VegProd.bare_cov.albedo * SW_VegProd.bare_cov.fCover, SW_Sky.r_humidity_daily[doy], + v->veg[SW_GRASS].cov.albedo * v->veg[SW_GRASS].cov.fCover + v->veg[SW_SHRUB].cov.albedo * v->veg[SW_SHRUB].cov.fCover + v->veg[SW_FORBS].cov.albedo * v->veg[SW_FORBS].cov.fCover + + v->veg[SW_TREES].cov.albedo * v->veg[SW_TREES].cov.fCover + v->bare_cov.albedo * v->bare_cov.fCover, SW_Sky.r_humidity_daily[doy], SW_Sky.windspeed_daily[doy], SW_Sky.cloudcov_daily[doy], SW_Sky.transmission_daily[doy]); /* Bare-soil evaporation rates */ - if (GT(SW_VegProd.bare_cov.fCover, 0.) && EQ(SW_Soilwat.snowpack[Today], 0.)) /* bare ground present AND no snow on ground */ + if (GT(v->bare_cov.fCover, 0.) && EQ(sw->snowpack[Today], 0.)) /* bare ground present AND no snow on ground */ { - pot_soil_evap_bs(&soil_evap_rate_bs, SW_Site.n_evap_lyrs, lyrEvapCo, SW_Soilwat.pet, SW_Site.evap.xinflec, SW_Site.evap.slope, SW_Site.evap.yinflec, + pot_soil_evap_bs(&soil_evap_rate_bs, SW_Site.n_evap_lyrs, lyrEvapCo, sw->pet, SW_Site.evap.xinflec, SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk); - soil_evap_rate_bs *= SW_VegProd.bare_cov.fCover; + soil_evap_rate_bs *= v->bare_cov.fCover; } else { soil_evap_rate_bs = 0; } /* Tree transpiration & bare-soil evaporation rates */ - if (GT(SW_VegProd.tree.cov.fCover, 0.) && GT(snowdepth_scale_tree, 0.)) { /* trees present AND trees not fully covered in snow */ - tree_EsT_partitioning(&soil_evap_tree, &transp_tree, SW_VegProd.tree.lai_live_daily[doy], SW_VegProd.tree.EsTpartitioning_param); + if (GT(v->veg[SW_TREES].cov.fCover, 0.) && GT(snowdepth_scale_tree, 0.)) { /* trees present AND trees not fully covered in snow */ + tree_EsT_partitioning(&soil_evap_tree, &transp_tree, v->veg[SW_TREES].lai_live_daily[doy], v->veg[SW_TREES].EsTpartitioning_param); - if (EQ(SW_Soilwat.snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ - pot_soil_evap(&soil_evap_rate_tree, SW_Site.n_evap_lyrs, lyrEvapCo, SW_VegProd.tree.total_agb_daily[doy], soil_evap_tree, SW_Soilwat.pet, SW_Site.evap.xinflec, - SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, SW_VegProd.tree.Es_param_limit); - soil_evap_rate_tree *= SW_VegProd.tree.cov.fCover; + if (EQ(sw->snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ + pot_soil_evap(&soil_evap_rate_tree, SW_Site.n_evap_lyrs, lyrEvapCo, v->veg[SW_TREES].total_agb_daily[doy], soil_evap_tree, sw->pet, SW_Site.evap.xinflec, + SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, v->veg[SW_TREES].Es_param_limit); + soil_evap_rate_tree *= v->veg[SW_TREES].cov.fCover; } else { soil_evap_rate_tree = 0.; } transp_weighted_avg(&swpot_avg_tree, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_TREES], lyrTrRegions_Tree, lyrTranspCo_Tree, lyrSWCBulk); - pot_transp(&transp_rate_tree, swpot_avg_tree, SW_VegProd.tree.biolive_daily[doy], SW_VegProd.tree.biodead_daily[doy], transp_tree, SW_Soilwat.pet, - SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, SW_VegProd.tree.shade_scale, SW_VegProd.tree.shade_deadmax, - SW_VegProd.tree.tr_shade_effects.xinflec, SW_VegProd.tree.tr_shade_effects.slope, SW_VegProd.tree.tr_shade_effects.yinflec, - SW_VegProd.tree.tr_shade_effects.range, SW_VegProd.tree.co2_multipliers[WUE_INDEX][SW_Model.simyear]); - transp_rate_tree *= snowdepth_scale_tree * SW_VegProd.tree.cov.fCover; + pot_transp(&transp_rate_tree, swpot_avg_tree, v->veg[SW_TREES].biolive_daily[doy], v->veg[SW_TREES].biodead_daily[doy], transp_tree, sw->pet, + SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, v->veg[SW_TREES].shade_scale, v->veg[SW_TREES].shade_deadmax, + v->veg[SW_TREES].tr_shade_effects.xinflec, v->veg[SW_TREES].tr_shade_effects.slope, v->veg[SW_TREES].tr_shade_effects.yinflec, + v->veg[SW_TREES].tr_shade_effects.range, v->veg[SW_TREES].co2_multipliers[WUE_INDEX][SW_Model.simyear]); + transp_rate_tree *= snowdepth_scale_tree * v->veg[SW_TREES].cov.fCover; } else { soil_evap_rate_tree = 0.; transp_rate_tree = 0.; } /* Shrub transpiration & bare-soil evaporation rates */ - if (GT(SW_VegProd.shrub.cov.fCover, 0.) && GT(snowdepth_scale_shrub, 0.)) { /* shrubs present AND shrubs not fully covered in snow */ - shrub_EsT_partitioning(&soil_evap_shrub, &transp_shrub, SW_VegProd.shrub.lai_live_daily[doy], SW_VegProd.shrub.EsTpartitioning_param); + if (GT(v->veg[SW_SHRUB].cov.fCover, 0.) && GT(snowdepth_scale_shrub, 0.)) { /* shrubs present AND shrubs not fully covered in snow */ + shrub_EsT_partitioning(&soil_evap_shrub, &transp_shrub, v->veg[SW_SHRUB].lai_live_daily[doy], v->veg[SW_SHRUB].EsTpartitioning_param); - if (EQ(SW_Soilwat.snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ - pot_soil_evap(&soil_evap_rate_shrub, SW_Site.n_evap_lyrs, lyrEvapCo, SW_VegProd.shrub.total_agb_daily[doy], soil_evap_shrub, SW_Soilwat.pet, SW_Site.evap.xinflec, - SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, SW_VegProd.shrub.Es_param_limit); - soil_evap_rate_shrub *= SW_VegProd.shrub.cov.fCover; + if (EQ(sw->snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ + pot_soil_evap(&soil_evap_rate_shrub, SW_Site.n_evap_lyrs, lyrEvapCo, v->veg[SW_SHRUB].total_agb_daily[doy], soil_evap_shrub, sw->pet, SW_Site.evap.xinflec, + SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, v->veg[SW_SHRUB].Es_param_limit); + soil_evap_rate_shrub *= v->veg[SW_SHRUB].cov.fCover; } else { soil_evap_rate_shrub = 0.; } transp_weighted_avg(&swpot_avg_shrub, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_SHRUB], lyrTrRegions_Shrub, lyrTranspCo_Shrub, lyrSWCBulk); - pot_transp(&transp_rate_shrub, swpot_avg_shrub, SW_VegProd.shrub.biolive_daily[doy], SW_VegProd.shrub.biodead_daily[doy], transp_shrub, SW_Soilwat.pet, - SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, SW_VegProd.shrub.shade_scale, SW_VegProd.shrub.shade_deadmax, - SW_VegProd.shrub.tr_shade_effects.xinflec, SW_VegProd.shrub.tr_shade_effects.slope, SW_VegProd.shrub.tr_shade_effects.yinflec, - SW_VegProd.shrub.tr_shade_effects.range, SW_VegProd.shrub.co2_multipliers[WUE_INDEX][SW_Model.simyear]); - transp_rate_shrub *= snowdepth_scale_shrub * SW_VegProd.shrub.cov.fCover; + pot_transp(&transp_rate_shrub, swpot_avg_shrub, v->veg[SW_SHRUB].biolive_daily[doy], v->veg[SW_SHRUB].biodead_daily[doy], transp_shrub, sw->pet, + SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, v->veg[SW_SHRUB].shade_scale, v->veg[SW_SHRUB].shade_deadmax, + v->veg[SW_SHRUB].tr_shade_effects.xinflec, v->veg[SW_SHRUB].tr_shade_effects.slope, v->veg[SW_SHRUB].tr_shade_effects.yinflec, + v->veg[SW_SHRUB].tr_shade_effects.range, v->veg[SW_SHRUB].co2_multipliers[WUE_INDEX][SW_Model.simyear]); + transp_rate_shrub *= snowdepth_scale_shrub * v->veg[SW_SHRUB].cov.fCover; } else { soil_evap_rate_shrub = 0.; @@ -473,24 +479,24 @@ void SW_Water_Flow(void) { } /* Forb transpiration & bare-soil evaporation rates */ - if (GT(SW_VegProd.forb.cov.fCover, 0.) && GT(snowdepth_scale_forb, 0.)) { /* forbs present AND forbs not fully covered in snow */ - forb_EsT_partitioning(&soil_evap_forb, &transp_forb, SW_VegProd.forb.lai_live_daily[doy], SW_VegProd.forb.EsTpartitioning_param); + if (GT(v->veg[SW_FORBS].cov.fCover, 0.) && GT(snowdepth_scale_forb, 0.)) { /* forbs present AND forbs not fully covered in snow */ + forb_EsT_partitioning(&soil_evap_forb, &transp_forb, v->veg[SW_FORBS].lai_live_daily[doy], v->veg[SW_FORBS].EsTpartitioning_param); - if (EQ(SW_Soilwat.snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ - pot_soil_evap(&soil_evap_rate_forb, SW_Site.n_evap_lyrs, lyrEvapCo, SW_VegProd.forb.total_agb_daily[doy], soil_evap_forb, SW_Soilwat.pet, SW_Site.evap.xinflec, - SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, SW_VegProd.forb.Es_param_limit); - soil_evap_rate_forb *= SW_VegProd.forb.cov.fCover; + if (EQ(sw->snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ + pot_soil_evap(&soil_evap_rate_forb, SW_Site.n_evap_lyrs, lyrEvapCo, v->veg[SW_FORBS].total_agb_daily[doy], soil_evap_forb, sw->pet, SW_Site.evap.xinflec, + SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, v->veg[SW_FORBS].Es_param_limit); + soil_evap_rate_forb *= v->veg[SW_FORBS].cov.fCover; } else { soil_evap_rate_forb = 0.; } transp_weighted_avg(&swpot_avg_forb, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_FORBS], lyrTrRegions_Forb, lyrTranspCo_Forb, lyrSWCBulk); - pot_transp(&transp_rate_forb, swpot_avg_forb, SW_VegProd.forb.biolive_daily[doy], SW_VegProd.forb.biodead_daily[doy], transp_forb, SW_Soilwat.pet, - SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, SW_VegProd.forb.shade_scale, SW_VegProd.forb.shade_deadmax, - SW_VegProd.forb.tr_shade_effects.xinflec, SW_VegProd.forb.tr_shade_effects.slope, SW_VegProd.forb.tr_shade_effects.yinflec, - SW_VegProd.forb.tr_shade_effects.range, SW_VegProd.forb.co2_multipliers[WUE_INDEX][SW_Model.simyear]); - transp_rate_forb *= snowdepth_scale_forb * SW_VegProd.forb.cov.fCover; + pot_transp(&transp_rate_forb, swpot_avg_forb, v->veg[SW_FORBS].biolive_daily[doy], v->veg[SW_FORBS].biodead_daily[doy], transp_forb, sw->pet, + SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, v->veg[SW_FORBS].shade_scale, v->veg[SW_FORBS].shade_deadmax, + v->veg[SW_FORBS].tr_shade_effects.xinflec, v->veg[SW_FORBS].tr_shade_effects.slope, v->veg[SW_FORBS].tr_shade_effects.yinflec, + v->veg[SW_FORBS].tr_shade_effects.range, v->veg[SW_FORBS].co2_multipliers[WUE_INDEX][SW_Model.simyear]); + transp_rate_forb *= snowdepth_scale_forb * v->veg[SW_FORBS].cov.fCover; } else { soil_evap_rate_forb = 0.; @@ -498,24 +504,24 @@ void SW_Water_Flow(void) { } /* Grass transpiration & bare-soil evaporation rates */ - if (GT(SW_VegProd.grass.cov.fCover, 0.) && GT(snowdepth_scale_grass, 0.)) { /* grasses present AND grasses not fully covered in snow */ - grass_EsT_partitioning(&soil_evap_grass, &transp_grass, SW_VegProd.grass.lai_live_daily[doy], SW_VegProd.grass.EsTpartitioning_param); + if (GT(v->veg[SW_GRASS].cov.fCover, 0.) && GT(snowdepth_scale_grass, 0.)) { /* grasses present AND grasses not fully covered in snow */ + grass_EsT_partitioning(&soil_evap_grass, &transp_grass, v->veg[SW_GRASS].lai_live_daily[doy], v->veg[SW_GRASS].EsTpartitioning_param); - if (EQ(SW_Soilwat.snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ - pot_soil_evap(&soil_evap_rate_grass, SW_Site.n_evap_lyrs, lyrEvapCo, SW_VegProd.grass.total_agb_daily[doy], soil_evap_grass, SW_Soilwat.pet, SW_Site.evap.xinflec, - SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, SW_VegProd.grass.Es_param_limit); - soil_evap_rate_grass *= SW_VegProd.grass.cov.fCover; + if (EQ(sw->snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ + pot_soil_evap(&soil_evap_rate_grass, SW_Site.n_evap_lyrs, lyrEvapCo, v->veg[SW_GRASS].total_agb_daily[doy], soil_evap_grass, sw->pet, SW_Site.evap.xinflec, + SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, v->veg[SW_GRASS].Es_param_limit); + soil_evap_rate_grass *= v->veg[SW_GRASS].cov.fCover; } else { soil_evap_rate_grass = 0.; } transp_weighted_avg(&swpot_avg_grass, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_GRASS], lyrTrRegions_Grass, lyrTranspCo_Grass, lyrSWCBulk); - pot_transp(&transp_rate_grass, swpot_avg_grass, SW_VegProd.grass.biolive_daily[doy], SW_VegProd.grass.biodead_daily[doy], transp_grass, SW_Soilwat.pet, - SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, SW_VegProd.grass.shade_scale, SW_VegProd.grass.shade_deadmax, - SW_VegProd.grass.tr_shade_effects.xinflec, SW_VegProd.grass.tr_shade_effects.slope, SW_VegProd.grass.tr_shade_effects.yinflec, - SW_VegProd.grass.tr_shade_effects.range, SW_VegProd.grass.co2_multipliers[WUE_INDEX][SW_Model.simyear]); - transp_rate_grass *= snowdepth_scale_grass * SW_VegProd.grass.cov.fCover; + pot_transp(&transp_rate_grass, swpot_avg_grass, v->veg[SW_GRASS].biolive_daily[doy], v->veg[SW_GRASS].biodead_daily[doy], transp_grass, sw->pet, + SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, v->veg[SW_GRASS].shade_scale, v->veg[SW_GRASS].shade_deadmax, + v->veg[SW_GRASS].tr_shade_effects.xinflec, v->veg[SW_GRASS].tr_shade_effects.slope, v->veg[SW_GRASS].tr_shade_effects.yinflec, + v->veg[SW_GRASS].tr_shade_effects.range, v->veg[SW_GRASS].co2_multipliers[WUE_INDEX][SW_Model.simyear]); + transp_rate_grass *= snowdepth_scale_grass * v->veg[SW_GRASS].cov.fCover; } else { soil_evap_rate_grass = 0.; transp_rate_grass = 0.; @@ -535,8 +541,8 @@ void SW_Water_Flow(void) { + surface_evap_standingWater_rate + soil_evap_rate_tree + transp_rate_tree + soil_evap_rate_forb + transp_rate_forb + soil_evap_rate_shrub + transp_rate_shrub + soil_evap_rate_grass + transp_rate_grass + soil_evap_rate_bs; - if (GT(rate_help, SW_Soilwat.pet)) { - rate_help = SW_Soilwat.pet / rate_help; + if (GT(rate_help, sw->pet)) { + rate_help = sw->pet / rate_help; surface_evap_tree_rate *= rate_help; surface_evap_forb_rate *= rate_help; @@ -556,28 +562,28 @@ void SW_Water_Flow(void) { } /* Start adding components to AET */ - SW_Soilwat.aet = 0.; /* init aet for the day */ - SW_Soilwat.aet += snow_evap_rate; + sw->aet = 0.; /* init aet for the day */ + sw->aet += snow_evap_rate; /* Evaporation of intercepted and surface water */ - evap_fromSurface(&tree_h2o_qum[Today], &surface_evap_tree_rate, &SW_Soilwat.aet); - evap_fromSurface(&shrub_h2o_qum[Today], &surface_evap_shrub_rate, &SW_Soilwat.aet); - evap_fromSurface(&forb_h2o_qum[Today], &surface_evap_forb_rate, &SW_Soilwat.aet); - evap_fromSurface(&grass_h2o_qum[Today], &surface_evap_grass_rate, &SW_Soilwat.aet); - evap_fromSurface(&litter_h2o_qum[Today], &surface_evap_litter_rate, &SW_Soilwat.aet); - evap_fromSurface(&standingWater[Today], &surface_evap_standingWater_rate, &SW_Soilwat.aet); - - SW_Soilwat.evap_veg[SW_TREES] = surface_evap_tree_rate; - SW_Soilwat.evap_veg[SW_SHRUB] = surface_evap_shrub_rate; - SW_Soilwat.evap_veg[SW_FORBS] = surface_evap_forb_rate; - SW_Soilwat.evap_veg[SW_GRASS] = surface_evap_grass_rate; - SW_Soilwat.litter_evap = surface_evap_litter_rate; - SW_Soilwat.surfaceWater_evap = surface_evap_standingWater_rate; + evap_fromSurface(&tree_h2o_qum[Today], &surface_evap_tree_rate, &sw->aet); + evap_fromSurface(&shrub_h2o_qum[Today], &surface_evap_shrub_rate, &sw->aet); + evap_fromSurface(&forb_h2o_qum[Today], &surface_evap_forb_rate, &sw->aet); + evap_fromSurface(&grass_h2o_qum[Today], &surface_evap_grass_rate, &sw->aet); + evap_fromSurface(&litter_h2o_qum[Today], &surface_evap_litter_rate, &sw->aet); + evap_fromSurface(&standingWater[Today], &surface_evap_standingWater_rate, &sw->aet); + + sw->evap_veg[SW_TREES] = surface_evap_tree_rate; + sw->evap_veg[SW_SHRUB] = surface_evap_shrub_rate; + sw->evap_veg[SW_FORBS] = surface_evap_forb_rate; + sw->evap_veg[SW_GRASS] = surface_evap_grass_rate; + sw->litter_evap = surface_evap_litter_rate; + sw->surfaceWater_evap = surface_evap_standingWater_rate; /* bare-soil evaporation */ - if (GT(SW_VegProd.bare_cov.fCover, 0.) && EQ(SW_Soilwat.snowpack[Today], 0.)) { + if (GT(v->bare_cov.fCover, 0.) && EQ(sw->snowpack[Today], 0.)) { /* remove bare-soil evap from swv */ - remove_from_soil(lyrSWCBulk, lyrEvap_BareGround, &SW_Soilwat.aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_bs, lyrSWCBulk_HalfWiltpts); + remove_from_soil(lyrSWCBulk, lyrEvap_BareGround, &sw->aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_bs, lyrSWCBulk_HalfWiltpts); } else { /* Set daily array to zero, no evaporation */ LyrIndex i; @@ -586,12 +592,12 @@ void SW_Water_Flow(void) { } /* Tree transpiration and bare-soil evaporation */ - if (GT(SW_VegProd.tree.cov.fCover, 0.) && GT(snowdepth_scale_tree, 0.)) { + if (GT(v->veg[SW_TREES].cov.fCover, 0.) && GT(snowdepth_scale_tree, 0.)) { /* remove bare-soil evap from swc */ - remove_from_soil(lyrSWCBulk, lyrEvap_Tree, &SW_Soilwat.aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_tree, lyrSWCBulk_HalfWiltpts); + remove_from_soil(lyrSWCBulk, lyrEvap_Tree, &sw->aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_tree, lyrSWCBulk_HalfWiltpts); /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Tree, &SW_Soilwat.aet, SW_Site.n_transp_lyrs[SW_TREES], lyrTranspCo_Tree, transp_rate_tree, lyrSWCBulk_atSWPcrit_Tree); + remove_from_soil(lyrSWCBulk, lyrTransp_Tree, &sw->aet, SW_Site.n_transp_lyrs[SW_TREES], lyrTranspCo_Tree, transp_rate_tree, lyrSWCBulk_atSWPcrit_Tree); } else { /* Set daily array to zero, no evaporation or transpiration */ LyrIndex i; @@ -602,12 +608,12 @@ void SW_Water_Flow(void) { } /* Shrub transpiration and bare-soil evaporation */ - if (GT(SW_VegProd.shrub.cov.fCover, 0.) && GT(snowdepth_scale_shrub, 0.)) { + if (GT(v->veg[SW_SHRUB].cov.fCover, 0.) && GT(snowdepth_scale_shrub, 0.)) { /* remove bare-soil evap from swc */ - remove_from_soil(lyrSWCBulk, lyrEvap_Shrub, &SW_Soilwat.aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_shrub, lyrSWCBulk_HalfWiltpts); + remove_from_soil(lyrSWCBulk, lyrEvap_Shrub, &sw->aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_shrub, lyrSWCBulk_HalfWiltpts); /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Shrub, &SW_Soilwat.aet, SW_Site.n_transp_lyrs[SW_SHRUB], lyrTranspCo_Shrub, transp_rate_shrub, lyrSWCBulk_atSWPcrit_Shrub); + remove_from_soil(lyrSWCBulk, lyrTransp_Shrub, &sw->aet, SW_Site.n_transp_lyrs[SW_SHRUB], lyrTranspCo_Shrub, transp_rate_shrub, lyrSWCBulk_atSWPcrit_Shrub); } else { /* Set daily array to zero, no evaporation or transpiration */ LyrIndex i; @@ -618,12 +624,12 @@ void SW_Water_Flow(void) { } /* Forb transpiration and bare-soil evaporation */ - if (GT(SW_VegProd.forb.cov.fCover, 0.) && GT(snowdepth_scale_forb, 0.)) { + if (GT(v->veg[SW_FORBS].cov.fCover, 0.) && GT(snowdepth_scale_forb, 0.)) { /* remove bare-soil evap from swc */ - remove_from_soil(lyrSWCBulk, lyrEvap_Forb, &SW_Soilwat.aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_forb, lyrSWCBulk_HalfWiltpts); + remove_from_soil(lyrSWCBulk, lyrEvap_Forb, &sw->aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_forb, lyrSWCBulk_HalfWiltpts); /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Forb, &SW_Soilwat.aet, SW_Site.n_transp_lyrs[SW_FORBS], lyrTranspCo_Forb, transp_rate_forb, lyrSWCBulk_atSWPcrit_Forb); + remove_from_soil(lyrSWCBulk, lyrTransp_Forb, &sw->aet, SW_Site.n_transp_lyrs[SW_FORBS], lyrTranspCo_Forb, transp_rate_forb, lyrSWCBulk_atSWPcrit_Forb); } else { /* Set daily array to zero, no evaporation or transpiration */ LyrIndex i; @@ -634,12 +640,12 @@ void SW_Water_Flow(void) { } /* Grass transpiration & bare-soil evaporation */ - if (GT(SW_VegProd.grass.cov.fCover, 0.) && GT(snowdepth_scale_grass, 0.)) { + if (GT(v->veg[SW_GRASS].cov.fCover, 0.) && GT(snowdepth_scale_grass, 0.)) { /* remove bare-soil evap from swc */ - remove_from_soil(lyrSWCBulk, lyrEvap_Grass, &SW_Soilwat.aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_grass, lyrSWCBulk_HalfWiltpts); + remove_from_soil(lyrSWCBulk, lyrEvap_Grass, &sw->aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_grass, lyrSWCBulk_HalfWiltpts); /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Grass, &SW_Soilwat.aet, SW_Site.n_transp_lyrs[SW_GRASS], lyrTranspCo_Grass, transp_rate_grass, lyrSWCBulk_atSWPcrit_Grass); + remove_from_soil(lyrSWCBulk, lyrTransp_Grass, &sw->aet, SW_Site.n_transp_lyrs[SW_GRASS], lyrTranspCo_Grass, transp_rate_grass, lyrSWCBulk_atSWPcrit_Grass); } else { /* Set daily array to zero, no evaporation or transpiration */ LyrIndex i; @@ -650,21 +656,21 @@ void SW_Water_Flow(void) { } /* Hydraulic redistribution */ - if (SW_VegProd.grass.flagHydraulicRedistribution && GT(SW_VegProd.grass.cov.fCover, 0.) && GT(SW_VegProd.grass.biolive_daily[doy], 0.)) { - hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Grass, lyrHydRed_Grass, SW_Site.n_layers, SW_VegProd.grass.maxCondroot, - SW_VegProd.grass.swpMatric50, SW_VegProd.grass.shapeCond, SW_VegProd.grass.cov.fCover); + if (v->veg[SW_GRASS].flagHydraulicRedistribution && GT(v->veg[SW_GRASS].cov.fCover, 0.) && GT(v->veg[SW_GRASS].biolive_daily[doy], 0.)) { + hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Grass, lyrHydRed_Grass, SW_Site.n_layers, v->veg[SW_GRASS].maxCondroot, + v->veg[SW_GRASS].swpMatric50, v->veg[SW_GRASS].shapeCond, v->veg[SW_GRASS].cov.fCover); } - if (SW_VegProd.forb.flagHydraulicRedistribution && GT(SW_VegProd.forb.cov.fCover, 0.) && GT(SW_VegProd.forb.biolive_daily[doy], 0.)) { - hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Forb, lyrHydRed_Forb, SW_Site.n_layers, SW_VegProd.forb.maxCondroot, SW_VegProd.forb.swpMatric50, - SW_VegProd.forb.shapeCond, SW_VegProd.forb.cov.fCover); + if (v->veg[SW_FORBS].flagHydraulicRedistribution && GT(v->veg[SW_FORBS].cov.fCover, 0.) && GT(v->veg[SW_FORBS].biolive_daily[doy], 0.)) { + hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Forb, lyrHydRed_Forb, SW_Site.n_layers, v->veg[SW_FORBS].maxCondroot, v->veg[SW_FORBS].swpMatric50, + v->veg[SW_FORBS].shapeCond, v->veg[SW_FORBS].cov.fCover); } - if (SW_VegProd.shrub.flagHydraulicRedistribution && GT(SW_VegProd.shrub.cov.fCover, 0.) && GT(SW_VegProd.shrub.biolive_daily[doy], 0.)) { - hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Shrub, lyrHydRed_Shrub, SW_Site.n_layers, SW_VegProd.shrub.maxCondroot, - SW_VegProd.shrub.swpMatric50, SW_VegProd.shrub.shapeCond, SW_VegProd.shrub.cov.fCover); + if (v->veg[SW_SHRUB].flagHydraulicRedistribution && GT(v->veg[SW_SHRUB].cov.fCover, 0.) && GT(v->veg[SW_SHRUB].biolive_daily[doy], 0.)) { + hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Shrub, lyrHydRed_Shrub, SW_Site.n_layers, v->veg[SW_SHRUB].maxCondroot, + v->veg[SW_SHRUB].swpMatric50, v->veg[SW_SHRUB].shapeCond, v->veg[SW_SHRUB].cov.fCover); } - if (SW_VegProd.tree.flagHydraulicRedistribution && GT(SW_VegProd.tree.cov.fCover, 0.) && GT(SW_VegProd.tree.biolive_daily[doy], 0.)) { - hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Tree, lyrHydRed_Tree, SW_Site.n_layers, SW_VegProd.tree.maxCondroot, SW_VegProd.tree.swpMatric50, - SW_VegProd.tree.shapeCond, SW_VegProd.tree.cov.fCover); + if (v->veg[SW_TREES].flagHydraulicRedistribution && GT(v->veg[SW_TREES].cov.fCover, 0.) && GT(v->veg[SW_TREES].biolive_daily[doy], 0.)) { + hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Tree, lyrHydRed_Tree, SW_Site.n_layers, v->veg[SW_TREES].maxCondroot, v->veg[SW_TREES].swpMatric50, + v->veg[SW_TREES].shapeCond, v->veg[SW_TREES].cov.fCover); } /* Calculate percolation for unsaturated soil water conditions. */ @@ -673,20 +679,20 @@ void SW_Water_Flow(void) { infiltrate_water_low(lyrSWCBulk, lyrDrain, &drainout, SW_Site.n_layers, SW_Site.slow_drain_coeff, SLOW_DRAIN_DEPTH, lyrSWCBulk_FieldCaps, lyrWidths, lyrSWCBulk_Mins, lyrSWCBulk_Saturated, lyrImpermeability, &standingWater[Today]); - SW_Soilwat.surfaceWater = standingWater[Today]; + sw->surfaceWater = standingWater[Today]; /* Soil Temperature starts here */ double biomass; // computing the live biomass real quickly to condense the call to soil_temperature -biomass = SW_VegProd.grass.biomass_daily[doy] * SW_VegProd.grass.cov.fCover + SW_VegProd.shrub.biolive_daily[doy] * SW_VegProd.shrub.cov.fCover - + SW_VegProd.forb.biomass_daily[doy] * SW_VegProd.forb.cov.fCover + SW_VegProd.tree.biolive_daily[doy] * SW_VegProd.tree.cov.fCover; // changed to exclude tree biomass, bMatric/c it was breaking the soil_temperature function +biomass = v->veg[SW_GRASS].biomass_daily[doy] * v->veg[SW_GRASS].cov.fCover + v->veg[SW_SHRUB].biolive_daily[doy] * v->veg[SW_SHRUB].cov.fCover + + v->veg[SW_FORBS].biomass_daily[doy] * v->veg[SW_FORBS].cov.fCover + v->veg[SW_TREES].biolive_daily[doy] * v->veg[SW_TREES].cov.fCover; // changed to exclude tree biomass, bMatric/c it was breaking the soil_temperature function // soil_temperature function computes the soil temp for each layer and stores it in lyrsTemp // doesn't affect SWC at all, but needs it for the calculation, so therefore the temperature is the last calculation done if (SW_Site.use_soil_temp) - soil_temperature(SW_Weather.now.temp_avg[Today], SW_Soilwat.pet, SW_Soilwat.aet, biomass, lyrSWCBulk, lyrSWCBulk_Saturated, lyrbDensity, lyrWidths, lyroldsTemp, lyrsTemp,surfaceTemp, SW_Site.n_layers, + soil_temperature(SW_Weather.now.temp_avg[Today], sw->pet, sw->aet, biomass, lyrSWCBulk, lyrSWCBulk_Saturated, lyrbDensity, lyrWidths, lyroldsTemp, lyrsTemp,surfaceTemp, SW_Site.n_layers, lyrSWCBulk_FieldCaps, lyrSWCBulk_Wiltpts, SW_Site.bmLimiter, SW_Site.t1Param1, SW_Site.t1Param2, SW_Site.t1Param3, SW_Site.csParam1, SW_Site.csParam2, - SW_Site.shParam, SW_Soilwat.snowdepth, SW_Site.meanAirTemp, SW_Site.stDeltaX, SW_Site.stMaxDepth, SW_Site.stNRGR, SW_Soilwat.snowpack[Today]); + SW_Site.shParam, sw->snowdepth, SW_Site.meanAirTemp, SW_Site.stDeltaX, SW_Site.stMaxDepth, SW_Site.stNRGR, sw->snowpack[Today]); /* Soil Temperature ends here */ diff --git a/SW_Output.c b/SW_Output.c index 34d6e29a4..4f3888e34 100644 --- a/SW_Output.c +++ b/SW_Output.c @@ -1355,14 +1355,14 @@ static void get_co2effects(OutPeriod pd) { // Grab the multipliers that were just used // No averaging or summing required - RealD bio_mult_grass = v->grass.co2_multipliers[BIO_INDEX][SW_Model.simyear]; - RealD bio_mult_shrub = v->shrub.co2_multipliers[BIO_INDEX][SW_Model.simyear]; - RealD bio_mult_tree = v->tree.co2_multipliers[BIO_INDEX][SW_Model.simyear]; - RealD bio_mult_forb = v->forb.co2_multipliers[BIO_INDEX][SW_Model.simyear]; - RealD wue_mult_grass = v->grass.co2_multipliers[WUE_INDEX][SW_Model.simyear]; - RealD wue_mult_shrub = v->shrub.co2_multipliers[WUE_INDEX][SW_Model.simyear]; - RealD wue_mult_tree = v->tree.co2_multipliers[WUE_INDEX][SW_Model.simyear]; - RealD wue_mult_forb = v->forb.co2_multipliers[WUE_INDEX][SW_Model.simyear]; + RealD bio_mult_grass = v->veg[SW_GRASS].co2_multipliers[BIO_INDEX][SW_Model.simyear]; + RealD bio_mult_shrub = v->veg[SW_SHRUB].co2_multipliers[BIO_INDEX][SW_Model.simyear]; + RealD bio_mult_tree = v->veg[SW_TREES].co2_multipliers[BIO_INDEX][SW_Model.simyear]; + RealD bio_mult_forb = v->veg[SW_FORBS].co2_multipliers[BIO_INDEX][SW_Model.simyear]; + RealD wue_mult_grass = v->veg[SW_GRASS].co2_multipliers[WUE_INDEX][SW_Model.simyear]; + RealD wue_mult_shrub = v->veg[SW_SHRUB].co2_multipliers[WUE_INDEX][SW_Model.simyear]; + RealD wue_mult_tree = v->veg[SW_TREES].co2_multipliers[WUE_INDEX][SW_Model.simyear]; + RealD wue_mult_forb = v->veg[SW_FORBS].co2_multipliers[WUE_INDEX][SW_Model.simyear]; #ifndef RSOILWAT char str[OUTSTRLEN]; @@ -1371,14 +1371,14 @@ static void get_co2effects(OutPeriod pd) { switch(pd) { case eSW_Day: - biomass_grass = v->dysum.grass.biomass; - biomass_shrub = v->dysum.shrub.biomass; - biomass_tree = v->dysum.tree.biomass; - biomass_forb = v->dysum.forb.biomass; - biolive_grass = v->dysum.grass.biolive; - biolive_shrub = v->dysum.shrub.biolive; - biolive_tree = v->dysum.tree.biolive; - biolive_forb = v->dysum.forb.biolive; + biomass_grass = v->dysum.veg[SW_GRASS].biomass; + biomass_shrub = v->dysum.veg[SW_SHRUB].biomass; + biomass_tree = v->dysum.veg[SW_TREES].biomass; + biomass_forb = v->dysum.veg[SW_FORBS].biomass; + biolive_grass = v->dysum.veg[SW_GRASS].biolive; + biolive_shrub = v->dysum.veg[SW_SHRUB].biolive; + biolive_tree = v->dysum.veg[SW_TREES].biolive; + biolive_forb = v->dysum.veg[SW_FORBS].biolive; biomass_total = biomass_grass + biomass_shrub + biomass_tree + biomass_forb; biolive_total = biolive_grass + biolive_shrub + biolive_tree + biolive_forb; @@ -1410,14 +1410,14 @@ static void get_co2effects(OutPeriod pd) { break; case eSW_Week: - biomass_grass = v->wkavg.grass.biomass; - biomass_shrub = v->wkavg.shrub.biomass; - biomass_tree = v->wkavg.tree.biomass; - biomass_forb = v->wkavg.forb.biomass; - biolive_grass = v->wkavg.grass.biolive; - biolive_shrub = v->wkavg.shrub.biolive; - biolive_tree = v->wkavg.tree.biolive; - biolive_forb = v->wkavg.forb.biolive; + biomass_grass = v->wkavg.veg[SW_GRASS].biomass; + biomass_shrub = v->wkavg.veg[SW_SHRUB].biomass; + biomass_tree = v->wkavg.veg[SW_TREES].biomass; + biomass_forb = v->wkavg.veg[SW_FORBS].biomass; + biolive_grass = v->wkavg.veg[SW_GRASS].biolive; + biolive_shrub = v->wkavg.veg[SW_SHRUB].biolive; + biolive_tree = v->wkavg.veg[SW_TREES].biolive; + biolive_forb = v->wkavg.veg[SW_FORBS].biolive; biomass_total = biomass_grass + biomass_shrub + biomass_tree + biomass_forb; biolive_total = biolive_grass + biolive_shrub + biolive_tree + biolive_forb; @@ -1449,14 +1449,14 @@ static void get_co2effects(OutPeriod pd) { break; case eSW_Month: - biomass_grass = v->moavg.grass.biomass; - biomass_shrub = v->moavg.shrub.biomass; - biomass_tree = v->moavg.tree.biomass; - biomass_forb = v->moavg.forb.biomass; - biolive_grass = v->moavg.grass.biolive; - biolive_shrub = v->moavg.shrub.biolive; - biolive_tree = v->moavg.tree.biolive; - biolive_forb = v->moavg.forb.biolive; + biomass_grass = v->moavg.veg[SW_GRASS].biomass; + biomass_shrub = v->moavg.veg[SW_SHRUB].biomass; + biomass_tree = v->moavg.veg[SW_TREES].biomass; + biomass_forb = v->moavg.veg[SW_FORBS].biomass; + biolive_grass = v->moavg.veg[SW_GRASS].biolive; + biolive_shrub = v->moavg.veg[SW_SHRUB].biolive; + biolive_tree = v->moavg.veg[SW_TREES].biolive; + biolive_forb = v->moavg.veg[SW_FORBS].biolive; biomass_total = biomass_grass + biomass_shrub + biomass_tree + biomass_forb; biolive_total = biolive_grass + biolive_shrub + biolive_tree + biolive_forb; @@ -1488,14 +1488,14 @@ static void get_co2effects(OutPeriod pd) { break; case eSW_Year: - biomass_grass = v->yravg.grass.biomass; - biomass_shrub = v->yravg.shrub.biomass; - biomass_tree = v->yravg.tree.biomass; - biomass_forb = v->yravg.forb.biomass; - biolive_grass = v->yravg.grass.biolive; - biolive_shrub = v->yravg.shrub.biolive; - biolive_tree = v->yravg.tree.biolive; - biolive_forb = v->yravg.forb.biolive; + biomass_grass = v->yravg.veg[SW_GRASS].biomass; + biomass_shrub = v->yravg.veg[SW_SHRUB].biomass; + biomass_tree = v->yravg.veg[SW_TREES].biomass; + biomass_forb = v->yravg.veg[SW_FORBS].biomass; + biolive_grass = v->yravg.veg[SW_GRASS].biolive; + biolive_shrub = v->yravg.veg[SW_SHRUB].biolive; + biolive_tree = v->yravg.veg[SW_TREES].biolive; + biolive_forb = v->yravg.veg[SW_FORBS].biolive; biomass_total = biomass_grass + biomass_shrub + biomass_tree + biomass_forb; biolive_total = biolive_grass + biolive_shrub + biolive_tree + biolive_forb; @@ -4239,17 +4239,15 @@ static void get_soiltemp(OutPeriod pd) static void sumof_vpd(SW_VEGPROD *v, SW_VEGPROD_OUTPUTS *s, OutKey k) { + int ik; + switch (k) { case eSW_CO2Effects: - s->grass.biomass += v->grass.biomass_daily[SW_Model.doy]; - s->shrub.biomass += v->shrub.biomass_daily[SW_Model.doy]; - s->tree.biomass += v->tree.biomass_daily[SW_Model.doy]; - s->forb.biomass += v->forb.biomass_daily[SW_Model.doy]; - s->grass.biolive += v->grass.biolive_daily[SW_Model.doy]; - s->shrub.biolive += v->shrub.biolive_daily[SW_Model.doy]; - s->tree.biolive += v->tree.biolive_daily[SW_Model.doy]; - s->forb.biolive += v->forb.biolive_daily[SW_Model.doy]; + ForEachVegType(ik) { + s->veg[ik].biomass += v->veg[ik].biomass_daily[SW_Model.doy]; + s->veg[ik].biolive += v->veg[ik].biolive_daily[SW_Model.doy]; + } break; default: @@ -4697,14 +4695,10 @@ static void average_for(ObjType otyp, OutPeriod pd) break; case eSW_CO2Effects: - vpavg->grass.biomass = vpsumof->grass.biomass / div; - vpavg->shrub.biomass = vpsumof->shrub.biomass / div; - vpavg->tree.biomass = vpsumof->tree.biomass / div; - vpavg->forb.biomass = vpsumof->forb.biomass / div; - vpavg->grass.biolive = vpsumof->grass.biolive / div; - vpavg->shrub.biolive = vpsumof->shrub.biolive / div; - vpavg->tree.biolive = vpsumof->tree.biolive / div; - vpavg->forb.biolive = vpsumof->forb.biolive / div; + ForEachVegType(i) { + vpavg->veg[i].biomass = vpsumof->veg[i].biomass / div; + vpavg->veg[i].biolive = vpsumof->veg[i].biolive / div; + } break; default: diff --git a/SW_Output_mock.c b/SW_Output_mock.c index 6d862a033..86b215bfe 100644 --- a/SW_Output_mock.c +++ b/SW_Output_mock.c @@ -161,7 +161,7 @@ static void sumof_vpd(SW_VEGPROD *v, SW_VEGPROD_OUTPUTS *s, OutKey k) if ((int)x == 1) {} if (EQ(0., v->bare_cov.fCover)) {} - if (EQ(0., s->grass.biomass)) {} + if (EQ(0., s->veg[SW_GRASS].biomass)) {} } static void sumof_ves(SW_VEGESTAB *v, SW_VEGESTAB_OUTPUTS *s, OutKey k) diff --git a/SW_Site.c b/SW_Site.c index 519a1b21c..19be07f2e 100644 --- a/SW_Site.c +++ b/SW_Site.c @@ -578,7 +578,7 @@ void init_site_info(void) { SW_SITE *sp = &SW_Site; SW_LAYER_INFO *lyr; LyrIndex s, r, curregion; - int wiltminflag = 0, initminflag = 0; + int k, wiltminflag = 0, initminflag = 0; RealD evsum = 0., trsum_forb = 0., trsum_tree = 0., trsum_shrub = 0., trsum_grass = 0., swcmin_help1, swcmin_help2; /* sp->deepdrain indicates an extra (dummy) layer for deep drainage @@ -600,10 +600,10 @@ void init_site_info(void) { trsum_grass += lyr->transp_coeff[SW_GRASS]; /* calculate soil water content at SWPcrit for each vegetation type */ - lyr->swcBulk_atSWPcrit[SW_FORBS] = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.forb.SWPcrit, s) * lyr->width; - lyr->swcBulk_atSWPcrit[SW_TREES] = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.tree.SWPcrit, s) * lyr->width; - lyr->swcBulk_atSWPcrit[SW_SHRUB] = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.shrub.SWPcrit, s) * lyr->width; - lyr->swcBulk_atSWPcrit[SW_GRASS] = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.grass.SWPcrit, s) * lyr->width; + ForEachVegType(k) { + lyr->swcBulk_atSWPcrit[k] = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, + SW_VegProd.veg[k].SWPcrit, s) * lyr->width; + } /* Find which transpiration region the current soil layer * is in and check validity of result. Region bounds are diff --git a/SW_VegProd.c b/SW_VegProd.c index 19869c882..bcc288f16 100644 --- a/SW_VegProd.c +++ b/SW_VegProd.c @@ -25,7 +25,7 @@ increased length of char outstr[1000] to outstr[1500] because of increased echo 09/13/2011 (drs) added input in SW_VPD_read() of RealD canopy_height_constant and updated SW_VPD_init() (as option: if > 0 then constant canopy height (cm) and overriding cnpy-tangens=f(biomass)) 09/15/2011 (drs) added input in SW_VPD_read() of RealD albedo 09/26/2011 (drs) added calls to Times.c:interpolate_monthlyValues() in SW_VPD_init() for each monthly input variable; replaced monthly loop with a daily loop for additional daily variables; adjusted _echo_inits() -10/17/2011 (drs) in SW_VPD_init(): v->tree.total_agb_daily[doy] = v->tree.litter_daily[doy] + v->tree.biolive_daily[doy] instead of = v->tree.litter_daily[doy] + v->tree.biomass_daily[doy] to adjust for better scaling of potential bare-soil evaporation +10/17/2011 (drs) in SW_VPD_init(): v->veg[SW_TREES].total_agb_daily[doy] = v->veg[SW_TREES].litter_daily[doy] + v->veg[SW_TREES].biolive_daily[doy] instead of = v->veg[SW_TREES].litter_daily[doy] + v->veg[SW_TREES].biomass_daily[doy] to adjust for better scaling of potential bare-soil evaporation 02/04/2012 (drs) added input in SW_VPD_read() of RealD SWPcrit 01/29/2013 (clk) changed the read in to account for the extra fractional component in total vegetation, bare ground added the variable RealF help_bareGround as a place holder for the sscanf call. @@ -86,9 +86,10 @@ void SW_VPD_read(void) { SW_VEGPROD *v = &SW_VegProd; FILE *f; TimeInt mon = Jan; - int x, lineno = 0; + int x, k, lineno = 0; const int line_help = 33; - RealF help_grass, help_shrub, help_tree, help_forb, help_bareGround, litt, biom, pctl, laic, co2_coeff_grass, co2_coeff_shrub, co2_coeff_tree, co2_coeff_forb; + RealF help_grass, help_shrub, help_tree, help_forb, help_bareGround, + litt, biom, pctl, laic, co2_coeff_grass, co2_coeff_shrub, co2_coeff_tree, co2_coeff_forb; RealD fraction_sum = 0.; MyFileName = SW_F_name(eVegProd); @@ -100,429 +101,429 @@ void SW_VPD_read(void) { /* fractions of vegetation types */ case 1: x = sscanf(inbuf, "%f %f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb, &help_bareGround); - if (x < 5) { + if (x < NVEGTYPES + 1) { sprintf(errstr, "ERROR: invalid record in vegetation type components in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.cov.fCover = help_grass; - v->shrub.cov.fCover = help_shrub; - v->tree.cov.fCover = help_tree; - v->forb.cov.fCover = help_forb; + v->veg[SW_GRASS].cov.fCover = help_grass; + v->veg[SW_SHRUB].cov.fCover = help_shrub; + v->veg[SW_TREES].cov.fCover = help_tree; + v->veg[SW_FORBS].cov.fCover = help_forb; v->bare_cov.fCover = help_bareGround; break; /* albedo */ case 2: x = sscanf(inbuf, "%f %f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb, &help_bareGround); - if (x < 5) { + if (x < NVEGTYPES + 1) { sprintf(errstr, "ERROR: invalid record in albedo values in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.cov.albedo = help_grass; - v->shrub.cov.albedo = help_shrub; - v->tree.cov.albedo = help_tree; - v->forb.cov.albedo = help_forb; + v->veg[SW_GRASS].cov.albedo = help_grass; + v->veg[SW_SHRUB].cov.albedo = help_shrub; + v->veg[SW_TREES].cov.albedo = help_tree; + v->veg[SW_FORBS].cov.albedo = help_forb; v->bare_cov.albedo = help_bareGround; break; /* LAI converter for % cover */ case 3: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in percent cover converting in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.conv_stcr = help_grass; - v->shrub.conv_stcr = help_shrub; - v->tree.conv_stcr = help_tree; - v->forb.conv_stcr = help_forb; + v->veg[SW_GRASS].conv_stcr = help_grass; + v->veg[SW_SHRUB].conv_stcr = help_shrub; + v->veg[SW_TREES].conv_stcr = help_tree; + v->veg[SW_FORBS].conv_stcr = help_forb; break; /* canopy height */ case 4: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in canopy xinflec in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.cnpy.xinflec = help_grass; - v->shrub.cnpy.xinflec = help_shrub; - v->tree.cnpy.xinflec = help_tree; - v->forb.cnpy.xinflec = help_forb; + v->veg[SW_GRASS].cnpy.xinflec = help_grass; + v->veg[SW_SHRUB].cnpy.xinflec = help_shrub; + v->veg[SW_TREES].cnpy.xinflec = help_tree; + v->veg[SW_FORBS].cnpy.xinflec = help_forb; break; case 5: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in canopy yinflec in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.cnpy.yinflec = help_grass; - v->shrub.cnpy.yinflec = help_shrub; - v->tree.cnpy.yinflec = help_tree; - v->forb.cnpy.yinflec = help_forb; + v->veg[SW_GRASS].cnpy.yinflec = help_grass; + v->veg[SW_SHRUB].cnpy.yinflec = help_shrub; + v->veg[SW_TREES].cnpy.yinflec = help_tree; + v->veg[SW_FORBS].cnpy.yinflec = help_forb; break; case 6: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in canopy range in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.cnpy.range = help_grass; - v->shrub.cnpy.range = help_shrub; - v->tree.cnpy.range = help_tree; - v->forb.cnpy.range = help_forb; + v->veg[SW_GRASS].cnpy.range = help_grass; + v->veg[SW_SHRUB].cnpy.range = help_shrub; + v->veg[SW_TREES].cnpy.range = help_tree; + v->veg[SW_FORBS].cnpy.range = help_forb; break; case 7: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in canopy slope in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.cnpy.slope = help_grass; - v->shrub.cnpy.slope = help_shrub; - v->tree.cnpy.slope = help_tree; - v->forb.cnpy.slope = help_forb; + v->veg[SW_GRASS].cnpy.slope = help_grass; + v->veg[SW_SHRUB].cnpy.slope = help_shrub; + v->veg[SW_TREES].cnpy.slope = help_tree; + v->veg[SW_FORBS].cnpy.slope = help_forb; break; case 8: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in canopy height constant option in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.canopy_height_constant = help_grass; - v->shrub.canopy_height_constant = help_shrub; - v->tree.canopy_height_constant = help_tree; - v->forb.canopy_height_constant = help_forb; + v->veg[SW_GRASS].canopy_height_constant = help_grass; + v->veg[SW_SHRUB].canopy_height_constant = help_shrub; + v->veg[SW_TREES].canopy_height_constant = help_tree; + v->veg[SW_FORBS].canopy_height_constant = help_forb; break; /* vegetation interception parameters */ case 9: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in interception parameter a in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.veg_intPPT_a = help_grass; - v->shrub.veg_intPPT_a = help_shrub; - v->tree.veg_intPPT_a = help_tree; - v->forb.veg_intPPT_a = help_forb; + v->veg[SW_GRASS].veg_intPPT_a = help_grass; + v->veg[SW_SHRUB].veg_intPPT_a = help_shrub; + v->veg[SW_TREES].veg_intPPT_a = help_tree; + v->veg[SW_FORBS].veg_intPPT_a = help_forb; break; case 10: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in interception parameter b in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.veg_intPPT_b = help_grass; - v->shrub.veg_intPPT_b = help_shrub; - v->tree.veg_intPPT_b = help_tree; - v->forb.veg_intPPT_b = help_forb; + v->veg[SW_GRASS].veg_intPPT_b = help_grass; + v->veg[SW_SHRUB].veg_intPPT_b = help_shrub; + v->veg[SW_TREES].veg_intPPT_b = help_tree; + v->veg[SW_FORBS].veg_intPPT_b = help_forb; break; case 11: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in interception parameter c in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.veg_intPPT_c = help_grass; - v->shrub.veg_intPPT_c = help_shrub; - v->tree.veg_intPPT_c = help_tree; - v->forb.veg_intPPT_c = help_forb; + v->veg[SW_GRASS].veg_intPPT_c = help_grass; + v->veg[SW_SHRUB].veg_intPPT_c = help_shrub; + v->veg[SW_TREES].veg_intPPT_c = help_tree; + v->veg[SW_FORBS].veg_intPPT_c = help_forb; break; case 12: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in interception parameter d in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.veg_intPPT_d = help_grass; - v->shrub.veg_intPPT_d = help_shrub; - v->tree.veg_intPPT_d = help_tree; - v->forb.veg_intPPT_d = help_forb; + v->veg[SW_GRASS].veg_intPPT_d = help_grass; + v->veg[SW_SHRUB].veg_intPPT_d = help_shrub; + v->veg[SW_TREES].veg_intPPT_d = help_tree; + v->veg[SW_FORBS].veg_intPPT_d = help_forb; break; /* litter interception parameters */ case 13: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in litter interception parameter a in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.litt_intPPT_a = help_grass; - v->shrub.litt_intPPT_a = help_shrub; - v->tree.litt_intPPT_a = help_tree; - v->forb.litt_intPPT_a = help_forb; + v->veg[SW_GRASS].litt_intPPT_a = help_grass; + v->veg[SW_SHRUB].litt_intPPT_a = help_shrub; + v->veg[SW_TREES].litt_intPPT_a = help_tree; + v->veg[SW_FORBS].litt_intPPT_a = help_forb; break; case 14: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in litter interception parameter b in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.litt_intPPT_b = help_grass; - v->shrub.litt_intPPT_b = help_shrub; - v->tree.litt_intPPT_b = help_tree; - v->forb.litt_intPPT_b = help_forb; + v->veg[SW_GRASS].litt_intPPT_b = help_grass; + v->veg[SW_SHRUB].litt_intPPT_b = help_shrub; + v->veg[SW_TREES].litt_intPPT_b = help_tree; + v->veg[SW_FORBS].litt_intPPT_b = help_forb; break; case 15: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in litter interception parameter c in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.litt_intPPT_c = help_grass; - v->shrub.litt_intPPT_c = help_shrub; - v->tree.litt_intPPT_c = help_tree; - v->forb.litt_intPPT_c = help_forb; + v->veg[SW_GRASS].litt_intPPT_c = help_grass; + v->veg[SW_SHRUB].litt_intPPT_c = help_shrub; + v->veg[SW_TREES].litt_intPPT_c = help_tree; + v->veg[SW_FORBS].litt_intPPT_c = help_forb; break; case 16: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in litter interception parameter d in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.litt_intPPT_d = help_grass; - v->shrub.litt_intPPT_d = help_shrub; - v->tree.litt_intPPT_d = help_tree; - v->forb.litt_intPPT_d = help_forb; + v->veg[SW_GRASS].litt_intPPT_d = help_grass; + v->veg[SW_SHRUB].litt_intPPT_d = help_shrub; + v->veg[SW_TREES].litt_intPPT_d = help_tree; + v->veg[SW_FORBS].litt_intPPT_d = help_forb; break; /* parameter for partitioning of bare-soil evaporation and transpiration */ case 17: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in parameter for partitioning of bare-soil evaporation and transpiration in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.EsTpartitioning_param = help_grass; - v->shrub.EsTpartitioning_param = help_shrub; - v->tree.EsTpartitioning_param = help_tree; - v->forb.EsTpartitioning_param = help_forb; + v->veg[SW_GRASS].EsTpartitioning_param = help_grass; + v->veg[SW_SHRUB].EsTpartitioning_param = help_shrub; + v->veg[SW_TREES].EsTpartitioning_param = help_tree; + v->veg[SW_FORBS].EsTpartitioning_param = help_forb; break; /* Parameter for scaling and limiting bare soil evaporation rate */ case 18: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in parameter for Parameter for scaling and limiting bare soil evaporation rate in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.Es_param_limit = help_grass; - v->shrub.Es_param_limit = help_shrub; - v->tree.Es_param_limit = help_tree; - v->forb.Es_param_limit = help_forb; + v->veg[SW_GRASS].Es_param_limit = help_grass; + v->veg[SW_SHRUB].Es_param_limit = help_shrub; + v->veg[SW_TREES].Es_param_limit = help_tree; + v->veg[SW_FORBS].Es_param_limit = help_forb; break; /* shade effects */ case 19: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade scale in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.shade_scale = help_grass; - v->shrub.shade_scale = help_shrub; - v->tree.shade_scale = help_tree; - v->forb.shade_scale = help_forb; + v->veg[SW_GRASS].shade_scale = help_grass; + v->veg[SW_SHRUB].shade_scale = help_shrub; + v->veg[SW_TREES].shade_scale = help_tree; + v->veg[SW_FORBS].shade_scale = help_forb; break; case 20: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade max dead biomass in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.shade_deadmax = help_grass; - v->shrub.shade_deadmax = help_shrub; - v->tree.shade_deadmax = help_tree; - v->forb.shade_deadmax = help_forb; + v->veg[SW_GRASS].shade_deadmax = help_grass; + v->veg[SW_SHRUB].shade_deadmax = help_shrub; + v->veg[SW_TREES].shade_deadmax = help_tree; + v->veg[SW_FORBS].shade_deadmax = help_forb; break; case 21: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade xinflec in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.tr_shade_effects.xinflec = help_grass; - v->shrub.tr_shade_effects.xinflec = help_shrub; - v->tree.tr_shade_effects.xinflec = help_tree; - v->forb.tr_shade_effects.xinflec = help_forb; + v->veg[SW_GRASS].tr_shade_effects.xinflec = help_grass; + v->veg[SW_SHRUB].tr_shade_effects.xinflec = help_shrub; + v->veg[SW_TREES].tr_shade_effects.xinflec = help_tree; + v->veg[SW_FORBS].tr_shade_effects.xinflec = help_forb; break; case 22: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade yinflec in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.tr_shade_effects.yinflec = help_grass; - v->shrub.tr_shade_effects.yinflec = help_shrub; - v->tree.tr_shade_effects.yinflec = help_tree; - v->forb.tr_shade_effects.yinflec = help_forb; + v->veg[SW_GRASS].tr_shade_effects.yinflec = help_grass; + v->veg[SW_SHRUB].tr_shade_effects.yinflec = help_shrub; + v->veg[SW_TREES].tr_shade_effects.yinflec = help_tree; + v->veg[SW_FORBS].tr_shade_effects.yinflec = help_forb; break; case 23: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade range in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.tr_shade_effects.range = help_grass; - v->shrub.tr_shade_effects.range = help_shrub; - v->tree.tr_shade_effects.range = help_tree; - v->forb.tr_shade_effects.range = help_forb; + v->veg[SW_GRASS].tr_shade_effects.range = help_grass; + v->veg[SW_SHRUB].tr_shade_effects.range = help_shrub; + v->veg[SW_TREES].tr_shade_effects.range = help_tree; + v->veg[SW_FORBS].tr_shade_effects.range = help_forb; break; case 24: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade slope in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.tr_shade_effects.slope = help_grass; - v->shrub.tr_shade_effects.slope = help_shrub; - v->tree.tr_shade_effects.slope = help_tree; - v->forb.tr_shade_effects.slope = help_forb; + v->veg[SW_GRASS].tr_shade_effects.slope = help_grass; + v->veg[SW_SHRUB].tr_shade_effects.slope = help_shrub; + v->veg[SW_TREES].tr_shade_effects.slope = help_tree; + v->veg[SW_FORBS].tr_shade_effects.slope = help_forb; break; /* Hydraulic redistribution */ case 25: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in hydraulic redistribution: flag in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.flagHydraulicRedistribution = (Bool) help_grass; - v->shrub.flagHydraulicRedistribution = (Bool) help_shrub; - v->tree.flagHydraulicRedistribution = (Bool) help_tree; - v->forb.flagHydraulicRedistribution = (Bool) help_forb; + v->veg[SW_GRASS].flagHydraulicRedistribution = (Bool) help_grass; + v->veg[SW_SHRUB].flagHydraulicRedistribution = (Bool) help_shrub; + v->veg[SW_TREES].flagHydraulicRedistribution = (Bool) help_tree; + v->veg[SW_FORBS].flagHydraulicRedistribution = (Bool) help_forb; break; case 26: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in hydraulic redistribution: maxCondroot in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.maxCondroot = help_grass; - v->shrub.maxCondroot = help_shrub; - v->tree.maxCondroot = help_tree; - v->forb.maxCondroot = help_forb; + v->veg[SW_GRASS].maxCondroot = help_grass; + v->veg[SW_SHRUB].maxCondroot = help_shrub; + v->veg[SW_TREES].maxCondroot = help_tree; + v->veg[SW_FORBS].maxCondroot = help_forb; break; case 27: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in hydraulic redistribution: swpMatric50 in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.swpMatric50 = help_grass; - v->shrub.swpMatric50 = help_shrub; - v->tree.swpMatric50 = help_tree; - v->forb.swpMatric50 = help_forb; + v->veg[SW_GRASS].swpMatric50 = help_grass; + v->veg[SW_SHRUB].swpMatric50 = help_shrub; + v->veg[SW_TREES].swpMatric50 = help_tree; + v->veg[SW_FORBS].swpMatric50 = help_forb; break; case 28: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in hydraulic redistribution: shapeCond in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.shapeCond = help_grass; - v->shrub.shapeCond = help_shrub; - v->tree.shapeCond = help_tree; - v->forb.shapeCond = help_forb; + v->veg[SW_GRASS].shapeCond = help_grass; + v->veg[SW_SHRUB].shapeCond = help_shrub; + v->veg[SW_TREES].shapeCond = help_tree; + v->veg[SW_FORBS].shapeCond = help_forb; break; /* Critical soil water potential */ case 29: x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in critical soil water potentials: flag in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.SWPcrit = -10. * help_grass; - v->shrub.SWPcrit = -10. * help_shrub; - v->tree.SWPcrit = -10. * help_tree; - v->forb.SWPcrit = -10. * help_forb; + v->veg[SW_GRASS].SWPcrit = -10. * help_grass; + v->veg[SW_SHRUB].SWPcrit = -10. * help_shrub; + v->veg[SW_TREES].SWPcrit = -10. * help_tree; + v->veg[SW_FORBS].SWPcrit = -10. * help_forb; break; /* CO2 Biomass Power Equation */ // Coefficient 1 case 30: x = sscanf(inbuf, "%f %f %f %f", &co2_coeff_grass, &co2_coeff_shrub, &co2_coeff_tree, &co2_coeff_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: Not enough arguments for CO2 Biomass Coefficient 1 in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.co2_bio_coeff1 = co2_coeff_grass; - v->shrub.co2_bio_coeff1 = co2_coeff_shrub; - v->tree.co2_bio_coeff1 = co2_coeff_tree; - v->forb.co2_bio_coeff1 = co2_coeff_forb; + v->veg[SW_GRASS].co2_bio_coeff1 = co2_coeff_grass; + v->veg[SW_SHRUB].co2_bio_coeff1 = co2_coeff_shrub; + v->veg[SW_TREES].co2_bio_coeff1 = co2_coeff_tree; + v->veg[SW_FORBS].co2_bio_coeff1 = co2_coeff_forb; break; // Coefficient 2 case 31: x = sscanf(inbuf, "%f %f %f %f", &co2_coeff_grass, &co2_coeff_shrub, &co2_coeff_tree, &co2_coeff_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: Not enough arguments for CO2 Biomass Coefficient 2 in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.co2_bio_coeff2 = co2_coeff_grass; - v->shrub.co2_bio_coeff2 = co2_coeff_shrub; - v->tree.co2_bio_coeff2 = co2_coeff_tree; - v->forb.co2_bio_coeff2 = co2_coeff_forb; + v->veg[SW_GRASS].co2_bio_coeff2 = co2_coeff_grass; + v->veg[SW_SHRUB].co2_bio_coeff2 = co2_coeff_shrub; + v->veg[SW_TREES].co2_bio_coeff2 = co2_coeff_tree; + v->veg[SW_FORBS].co2_bio_coeff2 = co2_coeff_forb; break; /* CO2 WUE Power Equation */ // Coefficient 1 case 32: x = sscanf(inbuf, "%f %f %f %f", &co2_coeff_grass, &co2_coeff_shrub, &co2_coeff_tree, &co2_coeff_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: Not enough arguments for CO2 WUE Coefficient 1 in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.co2_wue_coeff1 = co2_coeff_grass; - v->shrub.co2_wue_coeff1 = co2_coeff_shrub; - v->tree.co2_wue_coeff1 = co2_coeff_tree; - v->forb.co2_wue_coeff1 = co2_coeff_forb; + v->veg[SW_GRASS].co2_wue_coeff1 = co2_coeff_grass; + v->veg[SW_SHRUB].co2_wue_coeff1 = co2_coeff_shrub; + v->veg[SW_TREES].co2_wue_coeff1 = co2_coeff_tree; + v->veg[SW_FORBS].co2_wue_coeff1 = co2_coeff_forb; break; // Coefficient 2 case 33: x = sscanf(inbuf, "%f %f %f %f", &co2_coeff_grass, &co2_coeff_shrub, &co2_coeff_tree, &co2_coeff_forb); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: Not enough arguments for CO2 WUE Coefficient 2 in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->grass.co2_wue_coeff2 = co2_coeff_grass; - v->shrub.co2_wue_coeff2 = co2_coeff_shrub; - v->tree.co2_wue_coeff2 = co2_coeff_tree; - v->forb.co2_wue_coeff2 = co2_coeff_forb; + v->veg[SW_GRASS].co2_wue_coeff2 = co2_coeff_grass; + v->veg[SW_SHRUB].co2_wue_coeff2 = co2_coeff_shrub; + v->veg[SW_TREES].co2_wue_coeff2 = co2_coeff_tree; + v->veg[SW_FORBS].co2_wue_coeff2 = co2_coeff_forb; break; default: @@ -534,34 +535,34 @@ void SW_VPD_read(void) { mon = Jan; x = sscanf(inbuf, "%f %f %f %f", &litt, &biom, &pctl, &laic); - if (x < 4) { + if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record %d in %s\n", mon + 1, MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } if (lineno > line_help + 12 * 3 && lineno <= line_help + 12 * 4) { - v->forb.litter[mon] = litt; - v->forb.biomass[mon] = biom; - v->forb.pct_live[mon] = pctl; - v->forb.lai_conv[mon] = laic; + v->veg[SW_FORBS].litter[mon] = litt; + v->veg[SW_FORBS].biomass[mon] = biom; + v->veg[SW_FORBS].pct_live[mon] = pctl; + v->veg[SW_FORBS].lai_conv[mon] = laic; } else if (lineno > line_help + 12 * 2 && lineno <= line_help + 12 * 3) { - v->tree.litter[mon] = litt; - v->tree.biomass[mon] = biom; - v->tree.pct_live[mon] = pctl; - v->tree.lai_conv[mon] = laic; + v->veg[SW_TREES].litter[mon] = litt; + v->veg[SW_TREES].biomass[mon] = biom; + v->veg[SW_TREES].pct_live[mon] = pctl; + v->veg[SW_TREES].lai_conv[mon] = laic; } else if (lineno > line_help + 12 && lineno <= line_help + 12 * 2) { - v->shrub.litter[mon] = litt; - v->shrub.biomass[mon] = biom; - v->shrub.pct_live[mon] = pctl; - v->shrub.lai_conv[mon] = laic; + v->veg[SW_SHRUB].litter[mon] = litt; + v->veg[SW_SHRUB].biomass[mon] = biom; + v->veg[SW_SHRUB].pct_live[mon] = pctl; + v->veg[SW_SHRUB].lai_conv[mon] = laic; } else if (lineno > line_help && lineno <= line_help + 12) { - v->grass.litter[mon] = litt; - v->grass.biomass[mon] = biom; - v->grass.pct_live[mon] = pctl; - v->grass.lai_conv[mon] = laic; + v->veg[SW_GRASS].litter[mon] = litt; + v->veg[SW_GRASS].biomass[mon] = biom; + v->veg[SW_GRASS].pct_live[mon] = pctl; + v->veg[SW_GRASS].lai_conv[mon] = laic; } mon++; @@ -574,20 +575,22 @@ void SW_VPD_read(void) { LogError(logfp, LOGWARN, errstr); } - fraction_sum = v->grass.cov.fCover + v->shrub.cov.fCover + v->tree.cov.fCover + v->forb.cov.fCover + v->bare_cov.fCover; + fraction_sum = v->bare_cov.fCover; + ForEachVegType(k) { + fraction_sum += v->veg[k].cov.fCover; + } + if (!EQ(fraction_sum, 1.0)) { LogError(logfp, LOGWARN, "%s : Fractions of vegetation components were normalized, " "sum of fractions (%5.4f) != 1.0.\nNew coefficients are:", MyFileName, fraction_sum); - v->grass.cov.fCover /= fraction_sum; - v->shrub.cov.fCover /= fraction_sum; - v->tree.cov.fCover /= fraction_sum; + v->bare_cov.fCover /= fraction_sum; - v->forb.cov.fCover /= fraction_sum; - LogError(logfp, LOGWARN, " Grassland fraction : %5.4f", v->grass.cov.fCover); - LogError(logfp, LOGWARN, " Shrubland fraction : %5.4f", v->shrub.cov.fCover); - LogError(logfp, LOGWARN, " Forest/tree fraction : %5.4f", v->tree.cov.fCover); - LogError(logfp, LOGWARN, " FORB fraction : %5.4f", v->forb.cov.fCover); LogError(logfp, LOGWARN, " Bare Ground fraction : %5.4f", v->bare_cov.fCover); + + ForEachVegType(k) { + v->veg[k].cov.fCover /= fraction_sum; + LogError(logfp, LOGWARN, " %d fraction : %5.4f", k, v->veg[k].cov.fCover); + } } CloseFile(&f); @@ -609,18 +612,15 @@ void SW_VPD_construct(void) { SW_VEGPROD *v = &SW_VegProd; - int year; + int year, k; for (year = 0; year < MAX_NYEAR; year++) { - v->grass.co2_multipliers[BIO_INDEX][year] = 1.; - v->grass.co2_multipliers[WUE_INDEX][year] = 1.; - v->shrub.co2_multipliers[BIO_INDEX][year] = 1.; - v->shrub.co2_multipliers[WUE_INDEX][year] = 1.; - v->tree.co2_multipliers[BIO_INDEX][year] = 1.; - v->tree.co2_multipliers[WUE_INDEX][year] = 1.; - v->forb.co2_multipliers[BIO_INDEX][year] = 1.; - v->forb.co2_multipliers[WUE_INDEX][year] = 1.; + ForEachVegType(k) + { + v->veg[k].co2_multipliers[BIO_INDEX][year] = 1.; + v->veg[k].co2_multipliers[WUE_INDEX][year] = 1.; + } } } @@ -668,162 +668,71 @@ void SW_VPD_init(void) { SW_VEGPROD *v = &SW_VegProd; /* convenience */ TimeInt doy; /* base1 */ + int k; // Grab the real year so we can access CO2 data - - if (GT(v->grass.cov.fCover, 0.)) { - // CO2 - apply_biomassCO2effect(v->grass.CO2_biomass, v->grass.biomass, v->grass.co2_multipliers[BIO_INDEX][SW_Model.simyear]); - - // Interpolation - interpolate_monthlyValues(v->grass.litter, v->grass.litter_daily); - interpolate_monthlyValues(v->grass.CO2_biomass, v->grass.biomass_daily); - interpolate_monthlyValues(v->grass.pct_live, v->grass.pct_live_daily); - interpolate_monthlyValues(v->grass.lai_conv, v->grass.lai_conv_daily); - } - - if (GT(v->shrub.cov.fCover, 0.)) { - // CO2 - apply_biomassCO2effect(v->shrub.CO2_biomass, v->shrub.biomass, v->shrub.co2_multipliers[BIO_INDEX][SW_Model.simyear]); - - // Interpolation - interpolate_monthlyValues(v->shrub.litter, v->shrub.litter_daily); - interpolate_monthlyValues(v->shrub.CO2_biomass, v->shrub.biomass_daily); - interpolate_monthlyValues(v->shrub.pct_live, v->shrub.pct_live_daily); - interpolate_monthlyValues(v->shrub.lai_conv, v->shrub.lai_conv_daily); - } - - if (GT(v->tree.cov.fCover, 0.)) { - // CO2 - apply_biomassCO2effect(v->tree.CO2_pct_live, v->tree.pct_live, v->tree.co2_multipliers[BIO_INDEX][SW_Model.simyear]); - - // Interpolation - interpolate_monthlyValues(v->tree.litter, v->tree.litter_daily); - interpolate_monthlyValues(v->tree.biomass, v->tree.biomass_daily); - interpolate_monthlyValues(v->tree.CO2_pct_live, v->tree.pct_live_daily); - interpolate_monthlyValues(v->tree.lai_conv, v->tree.lai_conv_daily); - } - - if (GT(v->forb.cov.fCover, 0.)) { - // CO2 - apply_biomassCO2effect(v->forb.CO2_biomass, v->forb.biomass, v->forb.co2_multipliers[BIO_INDEX][SW_Model.simyear]); - - // Interpolation - interpolate_monthlyValues(v->forb.litter, v->forb.litter_daily); - interpolate_monthlyValues(v->forb.CO2_biomass, v->forb.biomass_daily); - interpolate_monthlyValues(v->forb.pct_live, v->forb.pct_live_daily); - interpolate_monthlyValues(v->forb.lai_conv, v->forb.lai_conv_daily); - } - - for (doy = 1; doy <= MAX_DAYS; doy++) { - if (GT(v->grass.cov.fCover, 0.)) { - lai_standing = v->grass.biomass_daily[doy] / v->grass.lai_conv_daily[doy]; - v->grass.pct_cover_daily[doy] = lai_standing / v->grass.conv_stcr; - if (GT(v->grass.canopy_height_constant, 0.)) { - v->grass.veg_height_daily[doy] = v->grass.canopy_height_constant; - } - else { - v->grass.veg_height_daily[doy] = tanfunc(v->grass.biomass_daily[doy], - v->grass.cnpy.xinflec, - v->grass.cnpy.yinflec, - v->grass.cnpy.range, - v->grass.cnpy.slope); /* used for vegcov and for snowdepth_scale */ + ForEachVegType(k) + { + if (GT(v->veg[k].cov.fCover, 0.)) + { + // CO2 + if (k == SW_TREES) + { + apply_biomassCO2effect(v->veg[k].CO2_pct_live, v->veg[k].pct_live, + v->veg[k].co2_multipliers[BIO_INDEX][SW_Model.simyear]); + } else { + apply_biomassCO2effect(v->veg[k].CO2_biomass, v->veg[k].biomass, + v->veg[k].co2_multipliers[BIO_INDEX][SW_Model.simyear]); } - v->grass.lai_live_daily[doy] = lai_standing * v->grass.pct_live_daily[doy]; - v->grass.vegcov_daily[doy] = v->grass.pct_cover_daily[doy] * v->grass.veg_height_daily[doy]; /* used for vegetation interception */ - v->grass.biolive_daily[doy] = v->grass.biomass_daily[doy] * v->grass.pct_live_daily[doy]; - v->grass.biodead_daily[doy] = v->grass.biomass_daily[doy] - v->grass.biolive_daily[doy]; /* used for transpiration */ - v->grass.total_agb_daily[doy] = v->grass.litter_daily[doy] + v->grass.biomass_daily[doy]; /* used for bare-soil evaporation */ - } - else { - v->grass.lai_live_daily[doy] = 0.; - v->grass.vegcov_daily[doy] = 0.; - v->grass.biolive_daily[doy] = 0.; - v->grass.biodead_daily[doy] = 0.; - v->grass.total_agb_daily[doy] = 0.; - } - - if (GT(v->shrub.cov.fCover, 0.)) { - lai_standing = v->shrub.biomass_daily[doy] / v->shrub.lai_conv_daily[doy]; - v->shrub.pct_cover_daily[doy] = lai_standing / v->shrub.conv_stcr; - if (GT(v->shrub.canopy_height_constant, 0.)) { - v->shrub.veg_height_daily[doy] = v->shrub.canopy_height_constant; - } - else { - v->shrub.veg_height_daily[doy] = tanfunc(v->shrub.biomass_daily[doy], - v->shrub.cnpy.xinflec, - v->shrub.cnpy.yinflec, - v->shrub.cnpy.range, - v->shrub.cnpy.slope); /* used for vegcov and for snowdepth_scale */ - } - v->shrub.lai_live_daily[doy] = lai_standing * v->shrub.pct_live_daily[doy]; - v->shrub.vegcov_daily[doy] = v->shrub.pct_cover_daily[doy] * v->shrub.veg_height_daily[doy]; /* used for vegetation interception */ - v->shrub.biolive_daily[doy] = v->shrub.biomass_daily[doy] * v->shrub.pct_live_daily[doy]; - v->shrub.biodead_daily[doy] = v->shrub.biomass_daily[doy] - v->shrub.biolive_daily[doy]; /* used for transpiration */ - v->shrub.total_agb_daily[doy] = v->shrub.litter_daily[doy] + v->shrub.biomass_daily[doy]; /* used for bare-soil evaporation */ - } - else { - v->shrub.lai_live_daily[doy] = 0.; - v->shrub.vegcov_daily[doy] = 0.; - v->shrub.biolive_daily[doy] = 0.; - v->shrub.biodead_daily[doy] = 0.; - v->shrub.total_agb_daily[doy] = 0.; - } - if (GT(v->tree.cov.fCover, 0.)) { - lai_standing = v->tree.biomass_daily[doy] / v->tree.lai_conv_daily[doy]; - v->tree.pct_cover_daily[doy] = lai_standing / v->tree.conv_stcr; - if (GT(v->tree.canopy_height_constant, 0.)) { - v->tree.veg_height_daily[doy] = v->tree.canopy_height_constant; - } - else { - v->tree.veg_height_daily[doy] = tanfunc(v->tree.biomass_daily[doy], - v->tree.cnpy.xinflec, - v->tree.cnpy.yinflec, - v->tree.cnpy.range, - v->tree.cnpy.slope); /* used for vegcov and for snowdepth_scale */ - } - v->tree.lai_live_daily[doy] = lai_standing * v->tree.pct_live_daily[doy]; /* used for vegetation interception */ - v->tree.vegcov_daily[doy] = v->tree.pct_cover_daily[doy] * v->tree.veg_height_daily[doy]; - v->tree.biolive_daily[doy] = v->tree.biomass_daily[doy] * v->tree.pct_live_daily[doy]; - v->tree.biodead_daily[doy] = v->tree.biomass_daily[doy] - v->tree.biolive_daily[doy]; /* used for transpiration */ - v->tree.total_agb_daily[doy] = v->tree.litter_daily[doy] + v->tree.biolive_daily[doy]; /* used for bare-soil evaporation */ - } - else { - v->tree.lai_live_daily[doy] = 0.; - v->tree.vegcov_daily[doy] = 0.; - v->tree.biolive_daily[doy] = 0.; - v->tree.biodead_daily[doy] = 0.; - v->tree.total_agb_daily[doy] = 0.; + // Interpolation + interpolate_monthlyValues(v->veg[k].litter, v->veg[k].litter_daily); + interpolate_monthlyValues(v->veg[k].CO2_biomass, v->veg[k].biomass_daily); + interpolate_monthlyValues(v->veg[k].pct_live, v->veg[k].pct_live_daily); + interpolate_monthlyValues(v->veg[k].lai_conv, v->veg[k].lai_conv_daily); } + } - if (GT(v->forb.cov.fCover, 0.)) { - lai_standing = v->forb.biomass_daily[doy] / v->forb.lai_conv_daily[doy]; - v->forb.pct_cover_daily[doy] = lai_standing / v->forb.conv_stcr; - if (GT(v->forb.canopy_height_constant, 0.)) { - v->forb.veg_height_daily[doy] = v->forb.canopy_height_constant; + for (doy = 1; doy <= MAX_DAYS; doy++) + { + ForEachVegType(k) + if (GT(v->veg[k].cov.fCover, 0.)) + { + lai_standing = v->veg[k].biomass_daily[doy] / v->veg[k].lai_conv_daily[doy]; + v->veg[k].pct_cover_daily[doy] = lai_standing / v->veg[k].conv_stcr; + + if (GT(v->veg[k].canopy_height_constant, 0.)) + { + v->veg[k].veg_height_daily[doy] = v->veg[k].canopy_height_constant; + + } else { + v->veg[k].veg_height_daily[doy] = tanfunc(v->veg[k].biomass_daily[doy], + v->veg[k].cnpy.xinflec, + v->veg[k].cnpy.yinflec, + v->veg[k].cnpy.range, + v->veg[k].cnpy.slope); /* used for vegcov and for snowdepth_scale */ + } + + v->veg[k].lai_live_daily[doy] = lai_standing * v->veg[k].pct_live_daily[doy]; + v->veg[k].vegcov_daily[doy] = v->veg[k].pct_cover_daily[doy] * v->veg[k].veg_height_daily[doy]; /* used for vegetation interception */ + v->veg[k].biolive_daily[doy] = v->veg[k].biomass_daily[doy] * v->veg[k].pct_live_daily[doy]; + v->veg[k].biodead_daily[doy] = v->veg[k].biomass_daily[doy] - v->veg[k].biolive_daily[doy]; /* used for transpiration */ + + if (k == SW_TREES) + { + v->veg[k].total_agb_daily[doy] = v->veg[k].litter_daily[doy] + v->veg[k].biolive_daily[doy]; + } else { + v->veg[k].total_agb_daily[doy] = v->veg[k].litter_daily[doy] + v->veg[k].biomass_daily[doy]; /* used for bare-soil evaporation */ + } + + } else { + v->veg[k].lai_live_daily[doy] = 0.; + v->veg[k].vegcov_daily[doy] = 0.; + v->veg[k].biolive_daily[doy] = 0.; + v->veg[k].biodead_daily[doy] = 0.; + v->veg[k].total_agb_daily[doy] = 0.; } - else { - v->forb.veg_height_daily[doy] = tanfunc(v->forb.biomass_daily[doy], - v->forb.cnpy.xinflec, - v->forb.cnpy.yinflec, - v->forb.cnpy.range, - v->forb.cnpy.slope); /* used for vegcov and for snowdepth_scale */ - } - v->forb.lai_live_daily[doy] = lai_standing * v->forb.pct_live_daily[doy]; /* used for vegetation interception */ - v->forb.vegcov_daily[doy] = v->forb.pct_cover_daily[doy] * v->forb.veg_height_daily[doy]; - v->forb.biolive_daily[doy] = v->forb.biomass_daily[doy] * v->forb.pct_live_daily[doy]; - v->forb.biodead_daily[doy] = v->forb.biomass_daily[doy] - v->forb.biolive_daily[doy]; /* used for transpiration */ - v->forb.total_agb_daily[doy] = v->forb.litter_daily[doy] + v->forb.biolive_daily[doy]; /* used for bare-soil evaporation */ - } - else { - v->forb.lai_live_daily[doy] = 0.; - v->forb.vegcov_daily[doy] = 0.; - v->forb.biolive_daily[doy] = 0.; - v->forb.biodead_daily[doy] = 0.; - v->forb.total_agb_daily[doy] = 0.; } - } } void _echo_VegProd(void) { @@ -839,25 +748,25 @@ void _echo_VegProd(void) { sprintf(errstr, "Grassland component\t= %1.2f\n" "\tAlbedo\t= %1.2f\n" - "\tHydraulic redistribution flag\t= %d\n", v->grass.cov.fCover, v->grass.cov.albedo, v->grass.flagHydraulicRedistribution); + "\tHydraulic redistribution flag\t= %d\n", v->veg[SW_GRASS].cov.fCover, v->veg[SW_GRASS].cov.albedo, v->veg[SW_GRASS].flagHydraulicRedistribution); strcpy(outstr, errstr); LogError(logfp, LOGNOTE, outstr); sprintf(errstr, "Shrubland component\t= %1.2f\n" "\tAlbedo\t= %1.2f\n" - "\tHydraulic redistribution flag\t= %d\n", v->shrub.cov.fCover, v->shrub.cov.albedo, v->shrub.flagHydraulicRedistribution); + "\tHydraulic redistribution flag\t= %d\n", v->veg[SW_SHRUB].cov.fCover, v->veg[SW_SHRUB].cov.albedo, v->veg[SW_SHRUB].flagHydraulicRedistribution); strcpy(outstr, errstr); LogError(logfp, LOGNOTE, outstr); sprintf(errstr, "Forest-Tree component\t= %1.2f\n" "\tAlbedo\t= %1.2f\n" - "\tHydraulic redistribution flag\t= %d\n", v->tree.cov.fCover, v->tree.cov.albedo, v->tree.flagHydraulicRedistribution); + "\tHydraulic redistribution flag\t= %d\n", v->veg[SW_TREES].cov.fCover, v->veg[SW_TREES].cov.albedo, v->veg[SW_TREES].flagHydraulicRedistribution); strcpy(outstr, errstr); LogError(logfp, LOGNOTE, outstr); sprintf(errstr, "FORB component\t= %1.2f\n" "\tAlbedo\t= %1.2f\n" - "\tHydraulic redistribution flag\t= %d\n", v->forb.cov.fCover, v->forb.cov.albedo, v->forb.flagHydraulicRedistribution); + "\tHydraulic redistribution flag\t= %d\n", v->veg[SW_FORBS].cov.fCover, v->veg[SW_FORBS].cov.albedo, v->veg[SW_FORBS].flagHydraulicRedistribution); strcpy(outstr, errstr); LogError(logfp, LOGNOTE, outstr); diff --git a/SW_VegProd.h b/SW_VegProd.h index 176076cf7..d03ff6de3 100644 --- a/SW_VegProd.h +++ b/SW_VegProd.h @@ -102,12 +102,12 @@ typedef struct { typedef struct { - VegTypeOut grass, shrub, tree, forb; + VegTypeOut veg[NVEGTYPES]; // used to be: grass, shrub, tree, forb; } SW_VEGPROD_OUTPUTS; typedef struct { - VegType grass, shrub, tree, forb; + VegType veg[NVEGTYPES]; // used to be: grass, shrub, tree, forb; CoverType bare_cov; /* bare ground cover of plot */ SW_VEGPROD_OUTPUTS dysum, /* helpful placeholder */ diff --git a/test/test_SW_Carbon.cc b/test/test_SW_Carbon.cc index a562172d0..bfa19ec5e 100644 --- a/test/test_SW_Carbon.cc +++ b/test/test_SW_Carbon.cc @@ -103,6 +103,7 @@ namespace { // Test the calculation of CO2-effect multipliers TEST(CarbonTest, CO2multipliers) { TimeInt year; + int k; SW_CBN_construct(); strcpy(c->scenario, "RCP85"); @@ -114,15 +115,10 @@ namespace { calculate_CO2_multipliers(); for (year = SW_Model.startyr + SW_Model.addtl_yr; year <= simendyr; year++) { - EXPECT_GT(v->forb.co2_multipliers[BIO_INDEX][year], 0.); - EXPECT_GT(v->grass.co2_multipliers[BIO_INDEX][year], 0.); - EXPECT_GT(v->shrub.co2_multipliers[BIO_INDEX][year], 0.); - EXPECT_GT(v->tree.co2_multipliers[BIO_INDEX][year], 0.); - - EXPECT_GT(v->forb.co2_multipliers[WUE_INDEX][year], 0.); - EXPECT_GT(v->grass.co2_multipliers[WUE_INDEX][year], 0.); - EXPECT_GT(v->shrub.co2_multipliers[WUE_INDEX][year], 0.); - EXPECT_GT(v->tree.co2_multipliers[WUE_INDEX][year], 0.); + ForEachVegType(k) { + EXPECT_GT(v->veg[k].co2_multipliers[BIO_INDEX][year], 0.); + EXPECT_GT(v->veg[k].co2_multipliers[WUE_INDEX][year], 0.); + } } // Reset to previous global states diff --git a/test/test_SW_VegProd.cc b/test/test_SW_VegProd.cc index 116d4551b..35db8064a 100644 --- a/test/test_SW_VegProd.cc +++ b/test/test_SW_VegProd.cc @@ -42,28 +42,19 @@ extern SW_VEGPROD SW_VegProd; namespace { SW_VEGPROD *v = &SW_VegProd; + int k; // Test the SW_VEGPROD constructor 'SW_VPD_construct' TEST(VegTest, Constructor) { SW_VPD_construct(); - EXPECT_DOUBLE_EQ(1., v->grass.co2_multipliers[BIO_INDEX][0]); - EXPECT_DOUBLE_EQ(1., v->shrub.co2_multipliers[BIO_INDEX][0]); - EXPECT_DOUBLE_EQ(1., v->tree.co2_multipliers[BIO_INDEX][0]); - EXPECT_DOUBLE_EQ(1., v->forb.co2_multipliers[BIO_INDEX][0]); - EXPECT_DOUBLE_EQ(1., v->grass.co2_multipliers[BIO_INDEX][MAX_NYEAR - 1]); - EXPECT_DOUBLE_EQ(1., v->shrub.co2_multipliers[BIO_INDEX][MAX_NYEAR - 1]); - EXPECT_DOUBLE_EQ(1., v->tree.co2_multipliers[BIO_INDEX][MAX_NYEAR - 1]); - EXPECT_DOUBLE_EQ(1., v->forb.co2_multipliers[BIO_INDEX][MAX_NYEAR - 1]); - - EXPECT_DOUBLE_EQ(1., v->grass.co2_multipliers[WUE_INDEX][0]); - EXPECT_DOUBLE_EQ(1., v->shrub.co2_multipliers[WUE_INDEX][0]); - EXPECT_DOUBLE_EQ(1., v->tree.co2_multipliers[WUE_INDEX][0]); - EXPECT_DOUBLE_EQ(1., v->forb.co2_multipliers[WUE_INDEX][0]); - EXPECT_DOUBLE_EQ(1., v->grass.co2_multipliers[WUE_INDEX][MAX_NYEAR - 1]); - EXPECT_DOUBLE_EQ(1., v->shrub.co2_multipliers[WUE_INDEX][MAX_NYEAR - 1]); - EXPECT_DOUBLE_EQ(1., v->tree.co2_multipliers[WUE_INDEX][MAX_NYEAR - 1]); - EXPECT_DOUBLE_EQ(1., v->forb.co2_multipliers[WUE_INDEX][MAX_NYEAR - 1]); + ForEachVegType(k) { + EXPECT_DOUBLE_EQ(1., v->veg[k].co2_multipliers[BIO_INDEX][0]); + EXPECT_DOUBLE_EQ(1., v->veg[k].co2_multipliers[BIO_INDEX][MAX_NYEAR - 1]); + + EXPECT_DOUBLE_EQ(1., v->veg[k].co2_multipliers[WUE_INDEX][0]); + EXPECT_DOUBLE_EQ(1., v->veg[k].co2_multipliers[WUE_INDEX][MAX_NYEAR - 1]); + } // Reset to previous global state Reset_SOILWAT2_after_UnitTest(); @@ -81,7 +72,7 @@ namespace { } // One example - x = v->grass.co2_multipliers[BIO_INDEX][SW_Model.startyr + SW_Model.addtl_yr]; + x = v->veg[SW_GRASS].co2_multipliers[BIO_INDEX][SW_Model.startyr + SW_Model.addtl_yr]; apply_biomassCO2effect(biom2, biom1, x); for (i = 0; i < 12; i++) { From 654b43affea4bdc83d26a91a94f242c1bb9acbe0 Mon Sep 17 00:00:00 2001 From: dschlaep Date: Mon, 22 Jan 2018 18:43:22 -0500 Subject: [PATCH 3/8] Introduced variable 'key2veg' - 'key2veg' contains string representations of vegetation types --> use for console message output --- SW_VegProd.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/SW_VegProd.c b/SW_VegProd.c index bcc288f16..fedecbacc 100644 --- a/SW_VegProd.c +++ b/SW_VegProd.c @@ -70,6 +70,9 @@ static char *MyFileName; static RealD lai_standing; /*standing crop lai (g/m**2) */ +// key2veg must be in the same order as the indices to vegetation types defined in SW_Defines.h +char const *key2veg[] = {"Trees", "Shrubs", "Forbs", "Grasses"}; + /* =================================================== */ /* =================================================== */ /* Private Function Definitions */ @@ -589,7 +592,7 @@ void SW_VPD_read(void) { ForEachVegType(k) { v->veg[k].cov.fCover /= fraction_sum; - LogError(logfp, LOGWARN, " %d fraction : %5.4f", k, v->veg[k].cov.fCover); + LogError(logfp, LOGWARN, " %d fraction : %5.4f", key2veg[k], v->veg[k].cov.fCover); } } @@ -740,35 +743,25 @@ void _echo_VegProd(void) { SW_VEGPROD *v = &SW_VegProd; /* convenience */ char outstr[1500]; + int k; sprintf(errstr, "\n==============================================\n" "Vegetation Production Parameters\n\n"); strcpy(outstr, errstr); LogError(logfp, LOGNOTE, outstr); - sprintf(errstr, "Grassland component\t= %1.2f\n" - "\tAlbedo\t= %1.2f\n" - "\tHydraulic redistribution flag\t= %d\n", v->veg[SW_GRASS].cov.fCover, v->veg[SW_GRASS].cov.albedo, v->veg[SW_GRASS].flagHydraulicRedistribution); - strcpy(outstr, errstr); - LogError(logfp, LOGNOTE, outstr); - - sprintf(errstr, "Shrubland component\t= %1.2f\n" - "\tAlbedo\t= %1.2f\n" - "\tHydraulic redistribution flag\t= %d\n", v->veg[SW_SHRUB].cov.fCover, v->veg[SW_SHRUB].cov.albedo, v->veg[SW_SHRUB].flagHydraulicRedistribution); - strcpy(outstr, errstr); - LogError(logfp, LOGNOTE, outstr); - - sprintf(errstr, "Forest-Tree component\t= %1.2f\n" - "\tAlbedo\t= %1.2f\n" - "\tHydraulic redistribution flag\t= %d\n", v->veg[SW_TREES].cov.fCover, v->veg[SW_TREES].cov.albedo, v->veg[SW_TREES].flagHydraulicRedistribution); - strcpy(outstr, errstr); - LogError(logfp, LOGNOTE, outstr); + ForEachVegType(k) { + sprintf(errstr, + "%s component\t= %1.2f\n" + "\tAlbedo\t= %1.2f\n" + "\tHydraulic redistribution flag\t= %d\n", + key2veg[k], v->veg[SW_GRASS].cov.fCover, + v->veg[SW_GRASS].cov.albedo, + v->veg[SW_GRASS].flagHydraulicRedistribution); + strcpy(outstr, errstr); + LogError(logfp, LOGNOTE, outstr); + } - sprintf(errstr, "FORB component\t= %1.2f\n" - "\tAlbedo\t= %1.2f\n" - "\tHydraulic redistribution flag\t= %d\n", v->veg[SW_FORBS].cov.fCover, v->veg[SW_FORBS].cov.albedo, v->veg[SW_FORBS].flagHydraulicRedistribution); - strcpy(outstr, errstr); - LogError(logfp, LOGNOTE, outstr); sprintf(errstr, "Bare Ground component\t= %1.2f\n" "\tAlbedo\t= %1.2f\n", v->bare_cov.fCover, v->bare_cov.albedo); From 031a67720f23e6b1aa371a02531c9f17c9e78bac Mon Sep 17 00:00:00 2001 From: dschlaep Date: Tue, 23 Jan 2018 08:27:00 -0500 Subject: [PATCH 4/8] Converted veg variables local to SW_VegProd to array - addressing #135 --- SW_VegProd.c | 339 +++++++++++++++++++++++++-------------------------- 1 file changed, 169 insertions(+), 170 deletions(-) diff --git a/SW_VegProd.c b/SW_VegProd.c index fedecbacc..58cbda1e8 100644 --- a/SW_VegProd.c +++ b/SW_VegProd.c @@ -91,8 +91,7 @@ void SW_VPD_read(void) { TimeInt mon = Jan; int x, k, lineno = 0; const int line_help = 33; - RealF help_grass, help_shrub, help_tree, help_forb, help_bareGround, - litt, biom, pctl, laic, co2_coeff_grass, co2_coeff_shrub, co2_coeff_tree, co2_coeff_forb; + RealF help_veg[NVEGTYPES], help_bareGround, litt, biom, pctl, laic; RealD fraction_sum = 0.; MyFileName = SW_F_name(eVegProd); @@ -103,430 +102,430 @@ void SW_VPD_read(void) { switch (lineno) { /* fractions of vegetation types */ case 1: - x = sscanf(inbuf, "%f %f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb, &help_bareGround); + x = sscanf(inbuf, "%f %f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS], &help_bareGround); if (x < NVEGTYPES + 1) { sprintf(errstr, "ERROR: invalid record in vegetation type components in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].cov.fCover = help_grass; - v->veg[SW_SHRUB].cov.fCover = help_shrub; - v->veg[SW_TREES].cov.fCover = help_tree; - v->veg[SW_FORBS].cov.fCover = help_forb; + ForEachVegType(k) { + v->veg[k].cov.fCover = help_veg[k]; + } v->bare_cov.fCover = help_bareGround; break; /* albedo */ case 2: - x = sscanf(inbuf, "%f %f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb, &help_bareGround); + x = sscanf(inbuf, "%f %f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS], &help_bareGround); if (x < NVEGTYPES + 1) { sprintf(errstr, "ERROR: invalid record in albedo values in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].cov.albedo = help_grass; - v->veg[SW_SHRUB].cov.albedo = help_shrub; - v->veg[SW_TREES].cov.albedo = help_tree; - v->veg[SW_FORBS].cov.albedo = help_forb; + ForEachVegType(k) { + v->veg[k].cov.albedo = help_veg[k]; + } v->bare_cov.albedo = help_bareGround; break; /* LAI converter for % cover */ case 3: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in percent cover converting in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].conv_stcr = help_grass; - v->veg[SW_SHRUB].conv_stcr = help_shrub; - v->veg[SW_TREES].conv_stcr = help_tree; - v->veg[SW_FORBS].conv_stcr = help_forb; + ForEachVegType(k) { + v->veg[k].conv_stcr = help_veg[k]; + } break; /* canopy height */ case 4: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in canopy xinflec in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].cnpy.xinflec = help_grass; - v->veg[SW_SHRUB].cnpy.xinflec = help_shrub; - v->veg[SW_TREES].cnpy.xinflec = help_tree; - v->veg[SW_FORBS].cnpy.xinflec = help_forb; + ForEachVegType(k) { + v->veg[k].cnpy.xinflec = help_veg[k]; + } break; case 5: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in canopy yinflec in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].cnpy.yinflec = help_grass; - v->veg[SW_SHRUB].cnpy.yinflec = help_shrub; - v->veg[SW_TREES].cnpy.yinflec = help_tree; - v->veg[SW_FORBS].cnpy.yinflec = help_forb; + ForEachVegType(k) { + v->veg[k].cnpy.yinflec = help_veg[k]; + } break; case 6: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in canopy range in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].cnpy.range = help_grass; - v->veg[SW_SHRUB].cnpy.range = help_shrub; - v->veg[SW_TREES].cnpy.range = help_tree; - v->veg[SW_FORBS].cnpy.range = help_forb; + ForEachVegType(k) { + v->veg[k].cnpy.range = help_veg[k]; + } break; case 7: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in canopy slope in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].cnpy.slope = help_grass; - v->veg[SW_SHRUB].cnpy.slope = help_shrub; - v->veg[SW_TREES].cnpy.slope = help_tree; - v->veg[SW_FORBS].cnpy.slope = help_forb; + ForEachVegType(k) { + v->veg[k].cnpy.slope = help_veg[k]; + } break; case 8: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in canopy height constant option in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].canopy_height_constant = help_grass; - v->veg[SW_SHRUB].canopy_height_constant = help_shrub; - v->veg[SW_TREES].canopy_height_constant = help_tree; - v->veg[SW_FORBS].canopy_height_constant = help_forb; + ForEachVegType(k) { + v->veg[k].canopy_height_constant = help_veg[k]; + } break; /* vegetation interception parameters */ case 9: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in interception parameter a in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].veg_intPPT_a = help_grass; - v->veg[SW_SHRUB].veg_intPPT_a = help_shrub; - v->veg[SW_TREES].veg_intPPT_a = help_tree; - v->veg[SW_FORBS].veg_intPPT_a = help_forb; + ForEachVegType(k) { + v->veg[k].veg_intPPT_a = help_veg[k]; + } break; case 10: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in interception parameter b in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].veg_intPPT_b = help_grass; - v->veg[SW_SHRUB].veg_intPPT_b = help_shrub; - v->veg[SW_TREES].veg_intPPT_b = help_tree; - v->veg[SW_FORBS].veg_intPPT_b = help_forb; + ForEachVegType(k) { + v->veg[k].veg_intPPT_b = help_veg[k]; + } break; case 11: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in interception parameter c in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].veg_intPPT_c = help_grass; - v->veg[SW_SHRUB].veg_intPPT_c = help_shrub; - v->veg[SW_TREES].veg_intPPT_c = help_tree; - v->veg[SW_FORBS].veg_intPPT_c = help_forb; + ForEachVegType(k) { + v->veg[k].veg_intPPT_c = help_veg[k]; + } break; case 12: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in interception parameter d in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].veg_intPPT_d = help_grass; - v->veg[SW_SHRUB].veg_intPPT_d = help_shrub; - v->veg[SW_TREES].veg_intPPT_d = help_tree; - v->veg[SW_FORBS].veg_intPPT_d = help_forb; + ForEachVegType(k) { + v->veg[k].veg_intPPT_d = help_veg[k]; + } break; /* litter interception parameters */ case 13: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in litter interception parameter a in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].litt_intPPT_a = help_grass; - v->veg[SW_SHRUB].litt_intPPT_a = help_shrub; - v->veg[SW_TREES].litt_intPPT_a = help_tree; - v->veg[SW_FORBS].litt_intPPT_a = help_forb; + ForEachVegType(k) { + v->veg[k].litt_intPPT_a = help_veg[k]; + } break; case 14: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in litter interception parameter b in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].litt_intPPT_b = help_grass; - v->veg[SW_SHRUB].litt_intPPT_b = help_shrub; - v->veg[SW_TREES].litt_intPPT_b = help_tree; - v->veg[SW_FORBS].litt_intPPT_b = help_forb; + ForEachVegType(k) { + v->veg[k].litt_intPPT_b = help_veg[k]; + } break; case 15: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in litter interception parameter c in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].litt_intPPT_c = help_grass; - v->veg[SW_SHRUB].litt_intPPT_c = help_shrub; - v->veg[SW_TREES].litt_intPPT_c = help_tree; - v->veg[SW_FORBS].litt_intPPT_c = help_forb; + ForEachVegType(k) { + v->veg[k].litt_intPPT_c = help_veg[k]; + } break; case 16: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in litter interception parameter d in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].litt_intPPT_d = help_grass; - v->veg[SW_SHRUB].litt_intPPT_d = help_shrub; - v->veg[SW_TREES].litt_intPPT_d = help_tree; - v->veg[SW_FORBS].litt_intPPT_d = help_forb; + ForEachVegType(k) { + v->veg[k].litt_intPPT_d = help_veg[k]; + } break; /* parameter for partitioning of bare-soil evaporation and transpiration */ case 17: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in parameter for partitioning of bare-soil evaporation and transpiration in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].EsTpartitioning_param = help_grass; - v->veg[SW_SHRUB].EsTpartitioning_param = help_shrub; - v->veg[SW_TREES].EsTpartitioning_param = help_tree; - v->veg[SW_FORBS].EsTpartitioning_param = help_forb; + ForEachVegType(k) { + v->veg[k].EsTpartitioning_param = help_veg[k]; + } break; /* Parameter for scaling and limiting bare soil evaporation rate */ case 18: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in parameter for Parameter for scaling and limiting bare soil evaporation rate in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].Es_param_limit = help_grass; - v->veg[SW_SHRUB].Es_param_limit = help_shrub; - v->veg[SW_TREES].Es_param_limit = help_tree; - v->veg[SW_FORBS].Es_param_limit = help_forb; + ForEachVegType(k) { + v->veg[k].Es_param_limit = help_veg[k]; + } break; /* shade effects */ case 19: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade scale in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].shade_scale = help_grass; - v->veg[SW_SHRUB].shade_scale = help_shrub; - v->veg[SW_TREES].shade_scale = help_tree; - v->veg[SW_FORBS].shade_scale = help_forb; + ForEachVegType(k) { + v->veg[k].shade_scale = help_veg[k]; + } break; case 20: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade max dead biomass in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].shade_deadmax = help_grass; - v->veg[SW_SHRUB].shade_deadmax = help_shrub; - v->veg[SW_TREES].shade_deadmax = help_tree; - v->veg[SW_FORBS].shade_deadmax = help_forb; + ForEachVegType(k) { + v->veg[k].shade_deadmax = help_veg[k]; + } break; case 21: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade xinflec in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].tr_shade_effects.xinflec = help_grass; - v->veg[SW_SHRUB].tr_shade_effects.xinflec = help_shrub; - v->veg[SW_TREES].tr_shade_effects.xinflec = help_tree; - v->veg[SW_FORBS].tr_shade_effects.xinflec = help_forb; + ForEachVegType(k) { + v->veg[k].tr_shade_effects.xinflec = help_veg[k]; + } break; case 22: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade yinflec in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].tr_shade_effects.yinflec = help_grass; - v->veg[SW_SHRUB].tr_shade_effects.yinflec = help_shrub; - v->veg[SW_TREES].tr_shade_effects.yinflec = help_tree; - v->veg[SW_FORBS].tr_shade_effects.yinflec = help_forb; + ForEachVegType(k) { + v->veg[k].tr_shade_effects.yinflec = help_veg[k]; + } break; case 23: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade range in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].tr_shade_effects.range = help_grass; - v->veg[SW_SHRUB].tr_shade_effects.range = help_shrub; - v->veg[SW_TREES].tr_shade_effects.range = help_tree; - v->veg[SW_FORBS].tr_shade_effects.range = help_forb; + ForEachVegType(k) { + v->veg[k].tr_shade_effects.range = help_veg[k]; + } break; case 24: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in shade slope in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].tr_shade_effects.slope = help_grass; - v->veg[SW_SHRUB].tr_shade_effects.slope = help_shrub; - v->veg[SW_TREES].tr_shade_effects.slope = help_tree; - v->veg[SW_FORBS].tr_shade_effects.slope = help_forb; + ForEachVegType(k) { + v->veg[k].tr_shade_effects.slope = help_veg[k]; + } break; /* Hydraulic redistribution */ case 25: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in hydraulic redistribution: flag in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].flagHydraulicRedistribution = (Bool) help_grass; - v->veg[SW_SHRUB].flagHydraulicRedistribution = (Bool) help_shrub; - v->veg[SW_TREES].flagHydraulicRedistribution = (Bool) help_tree; - v->veg[SW_FORBS].flagHydraulicRedistribution = (Bool) help_forb; + ForEachVegType(k) { + v->veg[k].flagHydraulicRedistribution = help_veg[k]; + } break; case 26: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in hydraulic redistribution: maxCondroot in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].maxCondroot = help_grass; - v->veg[SW_SHRUB].maxCondroot = help_shrub; - v->veg[SW_TREES].maxCondroot = help_tree; - v->veg[SW_FORBS].maxCondroot = help_forb; + ForEachVegType(k) { + v->veg[k].maxCondroot = help_veg[k]; + } break; case 27: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in hydraulic redistribution: swpMatric50 in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].swpMatric50 = help_grass; - v->veg[SW_SHRUB].swpMatric50 = help_shrub; - v->veg[SW_TREES].swpMatric50 = help_tree; - v->veg[SW_FORBS].swpMatric50 = help_forb; + ForEachVegType(k) { + v->veg[k].swpMatric50 = help_veg[k]; + } break; case 28: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in hydraulic redistribution: shapeCond in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].shapeCond = help_grass; - v->veg[SW_SHRUB].shapeCond = help_shrub; - v->veg[SW_TREES].shapeCond = help_tree; - v->veg[SW_FORBS].shapeCond = help_forb; + ForEachVegType(k) { + v->veg[k].shapeCond = help_veg[k]; + } break; /* Critical soil water potential */ case 29: - x = sscanf(inbuf, "%f %f %f %f", &help_grass, &help_shrub, &help_tree, &help_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: invalid record in critical soil water potentials: flag in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].SWPcrit = -10. * help_grass; - v->veg[SW_SHRUB].SWPcrit = -10. * help_shrub; - v->veg[SW_TREES].SWPcrit = -10. * help_tree; - v->veg[SW_FORBS].SWPcrit = -10. * help_forb; + ForEachVegType(k) { + v->veg[k].SWPcrit = -10. * help_veg[k]; + } break; /* CO2 Biomass Power Equation */ // Coefficient 1 case 30: - x = sscanf(inbuf, "%f %f %f %f", &co2_coeff_grass, &co2_coeff_shrub, &co2_coeff_tree, &co2_coeff_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: Not enough arguments for CO2 Biomass Coefficient 1 in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].co2_bio_coeff1 = co2_coeff_grass; - v->veg[SW_SHRUB].co2_bio_coeff1 = co2_coeff_shrub; - v->veg[SW_TREES].co2_bio_coeff1 = co2_coeff_tree; - v->veg[SW_FORBS].co2_bio_coeff1 = co2_coeff_forb; + ForEachVegType(k) { + v->veg[k].co2_bio_coeff1 = help_veg[k]; + } break; // Coefficient 2 case 31: - x = sscanf(inbuf, "%f %f %f %f", &co2_coeff_grass, &co2_coeff_shrub, &co2_coeff_tree, &co2_coeff_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: Not enough arguments for CO2 Biomass Coefficient 2 in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].co2_bio_coeff2 = co2_coeff_grass; - v->veg[SW_SHRUB].co2_bio_coeff2 = co2_coeff_shrub; - v->veg[SW_TREES].co2_bio_coeff2 = co2_coeff_tree; - v->veg[SW_FORBS].co2_bio_coeff2 = co2_coeff_forb; + ForEachVegType(k) { + v->veg[k].co2_bio_coeff2 = help_veg[k]; + } break; /* CO2 WUE Power Equation */ // Coefficient 1 case 32: - x = sscanf(inbuf, "%f %f %f %f", &co2_coeff_grass, &co2_coeff_shrub, &co2_coeff_tree, &co2_coeff_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: Not enough arguments for CO2 WUE Coefficient 1 in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].co2_wue_coeff1 = co2_coeff_grass; - v->veg[SW_SHRUB].co2_wue_coeff1 = co2_coeff_shrub; - v->veg[SW_TREES].co2_wue_coeff1 = co2_coeff_tree; - v->veg[SW_FORBS].co2_wue_coeff1 = co2_coeff_forb; + ForEachVegType(k) { + v->veg[k].co2_wue_coeff1 = help_veg[k]; + } break; // Coefficient 2 case 33: - x = sscanf(inbuf, "%f %f %f %f", &co2_coeff_grass, &co2_coeff_shrub, &co2_coeff_tree, &co2_coeff_forb); + x = sscanf(inbuf, "%f %f %f %f", &help_veg[SW_GRASS], &help_veg[SW_SHRUB], + &help_veg[SW_TREES], &help_veg[SW_FORBS]); if (x < NVEGTYPES) { sprintf(errstr, "ERROR: Not enough arguments for CO2 WUE Coefficient 2 in %s\n", MyFileName); CloseFile(&f); LogError(logfp, LOGFATAL, errstr); } - v->veg[SW_GRASS].co2_wue_coeff2 = co2_coeff_grass; - v->veg[SW_SHRUB].co2_wue_coeff2 = co2_coeff_shrub; - v->veg[SW_TREES].co2_wue_coeff2 = co2_coeff_tree; - v->veg[SW_FORBS].co2_wue_coeff2 = co2_coeff_forb; + ForEachVegType(k) { + v->veg[k].co2_wue_coeff2 = help_veg[k]; + } break; default: @@ -755,9 +754,9 @@ void _echo_VegProd(void) { "%s component\t= %1.2f\n" "\tAlbedo\t= %1.2f\n" "\tHydraulic redistribution flag\t= %d\n", - key2veg[k], v->veg[SW_GRASS].cov.fCover, - v->veg[SW_GRASS].cov.albedo, - v->veg[SW_GRASS].flagHydraulicRedistribution); + key2veg[k], v->veg[k].cov.fCover, + v->veg[k].cov.albedo, + v->veg[k].flagHydraulicRedistribution); strcpy(outstr, errstr); LogError(logfp, LOGNOTE, outstr); } From 834b0acd250821ba940fe392ee3014761f604283 Mon Sep 17 00:00:00 2001 From: dschlaep Date: Tue, 23 Jan 2018 09:37:07 -0500 Subject: [PATCH 5/8] Fix how biomass-effects of [CO2] are applied to trees - fix commit 2c87e85aceaf9326f5e6fc3a766c765e48595873 --- SW_VegProd.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/SW_VegProd.c b/SW_VegProd.c index 58cbda1e8..a08cb013d 100644 --- a/SW_VegProd.c +++ b/SW_VegProd.c @@ -677,20 +677,26 @@ void SW_VPD_init(void) { { if (GT(v->veg[k].cov.fCover, 0.)) { - // CO2 if (k == SW_TREES) { + // CO2 effects on biomass restricted to percent live biomass apply_biomassCO2effect(v->veg[k].CO2_pct_live, v->veg[k].pct_live, v->veg[k].co2_multipliers[BIO_INDEX][SW_Model.simyear]); + + interpolate_monthlyValues(v->veg[k].CO2_pct_live, v->veg[k].pct_live_daily); + interpolate_monthlyValues(v->veg[k].biomass, v->veg[k].biomass_daily); + } else { + // CO2 effects on biomass applied to total biomass apply_biomassCO2effect(v->veg[k].CO2_biomass, v->veg[k].biomass, v->veg[k].co2_multipliers[BIO_INDEX][SW_Model.simyear]); + + interpolate_monthlyValues(v->veg[k].CO2_biomass, v->veg[k].biomass_daily); + interpolate_monthlyValues(v->veg[k].pct_live, v->veg[k].pct_live_daily); } - // Interpolation + // Interpolation of remaining variables from monthly to daily values interpolate_monthlyValues(v->veg[k].litter, v->veg[k].litter_daily); - interpolate_monthlyValues(v->veg[k].CO2_biomass, v->veg[k].biomass_daily); - interpolate_monthlyValues(v->veg[k].pct_live, v->veg[k].pct_live_daily); interpolate_monthlyValues(v->veg[k].lai_conv, v->veg[k].lai_conv_daily); } } From 8dc7164e451679a4e22b6fe02aaebf91f05cb745 Mon Sep 17 00:00:00 2001 From: dschlaep Date: Tue, 23 Jan 2018 12:42:28 -0500 Subject: [PATCH 6/8] Convert vegetation variables into arrays (part 3) - address #135 - convert local vegetation variables defined in SW_Flow.c and SW_Site.c - use pre-defined loop 'ForEachVegType' whenever possible - define loop 'ForEachVegTypeBottomUp' for use by, e.g., hydraulic redistribution - SW_Flow_lib: collapsed all (identical) functions * 'XXX_intercepted_water' into 'veg_intercepted_water' * 'XXX_EsT_partitioning' into 'EsT_partitioning' --- SW_Defines.h | 1 + SW_Flow.c | 622 ++++++++++++++++++++------------------------------ SW_Flow_lib.c | 193 +++------------- SW_Flow_lib.h | 15 +- SW_Site.c | 255 ++++++--------------- SW_VegEstab.c | 8 +- 6 files changed, 358 insertions(+), 736 deletions(-) diff --git a/SW_Defines.h b/SW_Defines.h index 68c64ea23..0e6a93586 100644 --- a/SW_Defines.h +++ b/SW_Defines.h @@ -83,6 +83,7 @@ #define ForEachForbTranspLayer(i) for((i)=0; (i) < SW_Site.n_transp_lyrs[SW_FORBS]; (i)++) #define ForEachTranspRegion(r) for((r)=0; (r) < SW_Site.n_transp_rgn; (r)++) #define ForEachVegType(k) for ((k) = 0; (k) < NVEGTYPES; (k)++) +#define ForEachVegTypeBottomUp(k) for ((k) = NVEGTYPES - 1; (k) >= 0; (k)--) /* define m as Months */ #define ForEachMonth(m) for((m)=Jan; (m) <= Dec; (m)++) diff --git a/SW_Flow.c b/SW_Flow.c index 275d8f87a..1cf882ebc 100644 --- a/SW_Flow.c +++ b/SW_Flow.c @@ -141,15 +141,25 @@ extern unsigned int fusion_pool_init; * array indexing in those routines will be from * zero rather than 1. see records2arrays(). */ -IntU lyrTrRegions_Forb[MAX_LAYERS], lyrTrRegions_Tree[MAX_LAYERS], lyrTrRegions_Shrub[MAX_LAYERS], lyrTrRegions_Grass[MAX_LAYERS]; -RealD lyrSWCBulk[MAX_LAYERS], lyrDrain[MAX_LAYERS], lyrTransp_Forb[MAX_LAYERS], lyrTransp_Tree[MAX_LAYERS], lyrTransp_Shrub[MAX_LAYERS], lyrTransp_Grass[MAX_LAYERS], - lyrTranspCo_Forb[MAX_LAYERS], lyrTranspCo_Tree[MAX_LAYERS], lyrTranspCo_Shrub[MAX_LAYERS], lyrTranspCo_Grass[MAX_LAYERS], lyrEvap_BareGround[MAX_LAYERS], - lyrEvap_Forb[MAX_LAYERS], lyrEvap_Tree[MAX_LAYERS], lyrEvap_Shrub[MAX_LAYERS], lyrEvap_Grass[MAX_LAYERS], lyrEvapCo[MAX_LAYERS], lyrSWCBulk_FieldCaps[MAX_LAYERS], - lyrWidths[MAX_LAYERS], lyrSWCBulk_Wiltpts[MAX_LAYERS], lyrSWCBulk_HalfWiltpts[MAX_LAYERS], lyrSWCBulk_Mins[MAX_LAYERS], lyrSWCBulk_atSWPcrit_Forb[MAX_LAYERS], - lyrSWCBulk_atSWPcrit_Tree[MAX_LAYERS], lyrSWCBulk_atSWPcrit_Shrub[MAX_LAYERS], lyrSWCBulk_atSWPcrit_Grass[MAX_LAYERS], lyrpsisMatric[MAX_LAYERS], - lyrthetasMatric[MAX_LAYERS], lyrBetasMatric[MAX_LAYERS], lyrBetaInvMatric[MAX_LAYERS], lyrSumTrCo[MAX_TRANSP_REGIONS + 1], lyrHydRed_Forb[MAX_LAYERS], - lyrHydRed_Tree[MAX_LAYERS], lyrHydRed_Shrub[MAX_LAYERS], lyrHydRed_Grass[MAX_LAYERS], lyrImpermeability[MAX_LAYERS], lyrSWCBulk_Saturated[MAX_LAYERS], - lyroldsTemp[MAX_LAYERS], lyrsTemp[MAX_LAYERS], lyrbDensity[MAX_LAYERS]; +IntU lyrTrRegions[NVEGTYPES][MAX_LAYERS]; + +RealD lyrSWCBulk[MAX_LAYERS], lyrDrain[MAX_LAYERS], + + lyrTransp[NVEGTYPES][MAX_LAYERS], lyrTranspCo[NVEGTYPES][MAX_LAYERS], + lyrEvap[NVEGTYPES][MAX_LAYERS], lyrEvap_BareGround[MAX_LAYERS], + lyrSWCBulk_atSWPcrit[NVEGTYPES][MAX_LAYERS], lyrHydRed[NVEGTYPES][MAX_LAYERS], + lyrHydRed[NVEGTYPES][MAX_LAYERS], + + lyrbDensity[MAX_LAYERS], lyrWidths[MAX_LAYERS], + lyrEvapCo[MAX_LAYERS], lyrSumTrCo[MAX_TRANSP_REGIONS + 1], + lyrImpermeability[MAX_LAYERS], + lyrSWCBulk_FieldCaps[MAX_LAYERS], lyrSWCBulk_Saturated[MAX_LAYERS], + lyrSWCBulk_Wiltpts[MAX_LAYERS], lyrSWCBulk_HalfWiltpts[MAX_LAYERS], + lyrSWCBulk_Mins[MAX_LAYERS], + lyrpsisMatric[MAX_LAYERS], lyrthetasMatric[MAX_LAYERS], + lyrBetasMatric[MAX_LAYERS], lyrBetaInvMatric[MAX_LAYERS], + + lyroldsTemp[MAX_LAYERS], lyrsTemp[MAX_LAYERS]; RealD drainout; /* h2o drained out of deepest layer */ @@ -158,7 +168,9 @@ RealD UpNeigh_lyrSWCBulk[MAX_LAYERS], UpNeigh_lyrDrain[MAX_LAYERS], UpNeigh_drai UpNeigh_standingWater; -static RealD surfaceTemp[TWO_DAYS], forb_h2o_qum[TWO_DAYS], tree_h2o_qum[TWO_DAYS], shrub_h2o_qum[TWO_DAYS], grass_h2o_qum[TWO_DAYS], litter_h2o_qum[TWO_DAYS], standingWater[TWO_DAYS]; /* water on soil surface if layer below is saturated */ +static RealD surfaceTemp[TWO_DAYS], + veg_h2o_qum[NVEGTYPES][TWO_DAYS], litter_h2o_qum[TWO_DAYS], + standingWater[TWO_DAYS]; /* water on soil surface if layer below is saturated */ /* *************************************************** */ @@ -186,21 +198,29 @@ void SW_Water_Flow(void); void SW_FLW_construct(void) { /* 06/26/2013 (rjm) added function SW_FLW_construct() to init global variables between consecutive calls to SoilWat as dynamic library */ - int i=0; + int i, k; SW_Soilwat.partsError = swFALSE; soil_temp_init = 0; fusion_pool_init = 0; //These only have to be cleared if a loop is wrong in the code. for (i = 0; i < MAX_LAYERS; i++) { - lyrTrRegions_Forb[i] = lyrTrRegions_Tree[i] = lyrTrRegions_Shrub[i] = lyrTrRegions_Grass[i] = 0; - lyrSWCBulk[i] = lyrDrain[i] = lyrTransp_Forb[i] = lyrTransp_Tree[i] = lyrTransp_Shrub[i] = lyrTransp_Grass[i] = 0; - lyrTranspCo_Forb[i] = lyrTranspCo_Tree[i] = lyrTranspCo_Shrub[i] = lyrTranspCo_Grass[i] = lyrEvap_BareGround[i] = 0; - lyrEvap_Forb[i] = lyrEvap_Tree[i] = lyrEvap_Shrub[i] = lyrEvap_Grass[i] = lyrEvapCo[i] = lyrSWCBulk_FieldCaps[i] = 0; - lyrWidths[i] = lyrSWCBulk_Wiltpts[i] = lyrSWCBulk_HalfWiltpts[i] = lyrSWCBulk_Mins[i] = lyrSWCBulk_atSWPcrit_Forb[i] = 0; - lyrSWCBulk_atSWPcrit_Tree[i] = lyrSWCBulk_atSWPcrit_Shrub[i] = lyrSWCBulk_atSWPcrit_Grass[i] = lyrpsisMatric[i] = 0; - lyrthetasMatric[i] = lyrBetasMatric[i] = lyrBetaInvMatric[i] = lyrHydRed_Forb[i] = 0; - lyrHydRed_Tree[i] = lyrHydRed_Shrub[i] = lyrHydRed_Grass[i] = lyrImpermeability[i] = lyrSWCBulk_Saturated[i] = 0; + ForEachVegType(k) { + lyrTrRegions[k][i] = 0; + lyrTransp[k][i] = 0.; + lyrTranspCo[k][i] = 0.; + lyrEvap[k][i] = 0.; + lyrSWCBulk_atSWPcrit[k][i] = 0.; + lyrHydRed[k][i] = 0; + } + + lyrSWCBulk[i] = lyrDrain[i] = 0.; + lyrEvap_BareGround[i] = 0; + lyrEvapCo[i] = lyrSWCBulk_FieldCaps[i] = 0; + lyrWidths[i] = lyrSWCBulk_Wiltpts[i] = lyrSWCBulk_HalfWiltpts[i] = 0; + lyrSWCBulk_Mins[i] = lyrpsisMatric[i] = 0; + lyrthetasMatric[i] = lyrBetasMatric[i] = lyrBetaInvMatric[i] = 0; + lyrImpermeability[i] = lyrSWCBulk_Saturated[i] = 0; lyroldsTemp[i] = lyrsTemp[i] = lyrbDensity[i] = 0; } @@ -209,9 +229,13 @@ void SW_FLW_construct(void) { //When running as a library make sure these are set to zero. drainout = 0; - surfaceTemp[0] = surfaceTemp[1] = 0.0; - forb_h2o_qum[0]=tree_h2o_qum[0]=shrub_h2o_qum[0]=grass_h2o_qum[0]=litter_h2o_qum[0]=standingWater[0]=0; - forb_h2o_qum[1]=tree_h2o_qum[1]=shrub_h2o_qum[1]=grass_h2o_qum[1]=litter_h2o_qum[1]=standingWater[1]=0; + surfaceTemp[0] = surfaceTemp[1] = 0.; + standingWater[0] = standingWater[1] = 0.; + litter_h2o_qum[0] = litter_h2o_qum[1] = 0.; + + ForEachVegType(k) { + veg_h2o_qum[k][0] = veg_h2o_qum[k][0] = 0.; + } } /* *************************************************** */ @@ -223,14 +247,18 @@ void SW_Water_Flow(void) { SW_VEGPROD *v = &SW_VegProd; SW_SOILWAT *sw = &SW_Soilwat; - RealD swpot_avg_forb, swpot_avg_tree, swpot_avg_shrub, swpot_avg_grass, soil_evap_forb, soil_evap_tree, soil_evap_shrub, soil_evap_grass, soil_evap_rate_forb = 1., - soil_evap_rate_tree = 1., soil_evap_rate_shrub = 1., soil_evap_rate_grass = 1., soil_evap_rate_bs = 1., transp_forb, transp_tree, transp_shrub, transp_grass, - transp_rate_forb = 1., transp_rate_tree = 1., transp_rate_shrub = 1., transp_rate_grass = 1., snow_evap_rate, surface_evap_forb_rate, surface_evap_tree_rate, - surface_evap_shrub_rate, surface_evap_grass_rate, surface_evap_litter_rate, surface_evap_standingWater_rate, grass_h2o, shrub_h2o, tree_h2o, forb_h2o, litter_h2o, - litter_h2o_help, h2o_for_soil = 0., ppt_toUse, snowmelt, snowdepth_scale_grass = 1., snowdepth_scale_shrub = 1., snowdepth_scale_tree = 1., - snowdepth_scale_forb = 1., rate_help; - - int doy; + RealD swpot_avg[NVEGTYPES], + transp_veg[NVEGTYPES], transp_rate[NVEGTYPES] = {1.}, + soil_evap[NVEGTYPES], soil_evap_rate[NVEGTYPES] = {1.}, soil_evap_rate_bs = 1., + surface_evap_veg_rate[NVEGTYPES] = {1.}, + surface_evap_litter_rate = 1., surface_evap_standingWater_rate = 1., + snow_evap_rate = 1., + veg_h2o[NVEGTYPES], litter_h2o, + litter_h2o_help, h2o_for_soil = 0., ppt_toUse, snowmelt, + snowdepth_scale_veg[NVEGTYPES] = {1.}, + rate_help, x; + + int doy, k; LyrIndex i; doy = SW_Model.doy; /* base1 */ @@ -247,87 +275,56 @@ void SW_Water_Flow(void) { - infiltrate water high - infiltrate water low */ - if (GT(v->veg[SW_GRASS].veg_height_daily[doy], 0.)) { - snowdepth_scale_grass = 1. - sw->snowdepth / v->veg[SW_GRASS].veg_height_daily[doy]; - } else { - snowdepth_scale_grass = 1.; - } - if (GT(v->veg[SW_FORBS].veg_height_daily[doy], 0.)) { - snowdepth_scale_forb = 1. - sw->snowdepth / v->veg[SW_FORBS].veg_height_daily[doy]; - } else { - snowdepth_scale_forb = 1.; - } - if (GT(v->veg[SW_SHRUB].veg_height_daily[doy], 0.)) { - snowdepth_scale_shrub = 1. - sw->snowdepth / v->veg[SW_SHRUB].veg_height_daily[doy]; - } else { - snowdepth_scale_shrub = 1.; - } - if (GT(v->veg[SW_TREES].veg_height_daily[doy], 0.)) { - snowdepth_scale_tree = 1. - sw->snowdepth / v->veg[SW_TREES].veg_height_daily[doy]; - } else { - snowdepth_scale_tree = 1.; + ForEachVegType(k) + { + if (GT(v->veg[k].veg_height_daily[doy], 0.)) { + snowdepth_scale_veg[k] = 1. - sw->snowdepth / v->veg[k].veg_height_daily[doy]; + } else { + snowdepth_scale_veg[k] = 1.; + } } /* Interception */ ppt_toUse = SW_Weather.now.rain[Today]; /* ppt is partioned into ppt = snow + rain */ - if (GT(v->veg[SW_TREES].cov.fCover, 0.) && GT(snowdepth_scale_tree, 0.)) { /* trees present AND trees not fully covered in snow */ - tree_intercepted_water(&h2o_for_soil, &tree_h2o, ppt_toUse, v->veg[SW_TREES].lai_live_daily[doy], snowdepth_scale_tree * v->veg[SW_TREES].cov.fCover, - v->veg[SW_TREES].veg_intPPT_a, v->veg[SW_TREES].veg_intPPT_b, v->veg[SW_TREES].veg_intPPT_c, v->veg[SW_TREES].veg_intPPT_d); - ppt_toUse = h2o_for_soil; /* amount of rain that is not intercepted by the forest canopy */ - } else { /* snow depth is more than vegetation height */ - h2o_for_soil = ppt_toUse; - tree_h2o = 0.; - } /* end forest interception */ - - if (GT(v->veg[SW_SHRUB].cov.fCover, 0.) && GT(snowdepth_scale_shrub, 0.)) { - shrub_intercepted_water(&h2o_for_soil, &shrub_h2o, ppt_toUse, v->veg[SW_SHRUB].vegcov_daily[doy], snowdepth_scale_shrub * v->veg[SW_SHRUB].cov.fCover, - v->veg[SW_SHRUB].veg_intPPT_a, v->veg[SW_SHRUB].veg_intPPT_b, v->veg[SW_SHRUB].veg_intPPT_c, v->veg[SW_SHRUB].veg_intPPT_d); - ppt_toUse = h2o_for_soil; /* amount of rain that is not intercepted by the shrub canopy */ - } else { - shrub_h2o = 0.; - } /* end shrub interception */ - if (GT(v->veg[SW_FORBS].cov.fCover, 0.) && GT(snowdepth_scale_forb, 0.)) { /* forbs present AND not fully covered in snow */ - forb_intercepted_water(&h2o_for_soil, &forb_h2o, ppt_toUse, v->veg[SW_FORBS].vegcov_daily[doy], snowdepth_scale_forb * v->veg[SW_FORBS].cov.fCover, - v->veg[SW_FORBS].veg_intPPT_a, v->veg[SW_FORBS].veg_intPPT_b, v->veg[SW_FORBS].veg_intPPT_c, v->veg[SW_FORBS].veg_intPPT_d); - ppt_toUse = h2o_for_soil; /* amount of rain that is not intercepted by the forbs */ - } else { /* snow depth is more than vegetation height */ - forb_h2o = 0.; + ForEachVegType(k) + { + if (GT(v->veg[k].cov.fCover, 0.) && GT(snowdepth_scale_veg[k], 0.)) + { + /* veg type k present AND veg not fully covered in snow */ + if (k == SW_TREES) { + x = v->veg[k].lai_live_daily[doy]; + } else { + x = v->veg[k].vegcov_daily[doy]; + } - } /* end forb interception */ + veg_intercepted_water(&h2o_for_soil, &veg_h2o[k], ppt_toUse, x, + snowdepth_scale_veg[k] * v->veg[k].cov.fCover, + v->veg[k].veg_intPPT_a, v->veg[k].veg_intPPT_b, + v->veg[k].veg_intPPT_c, v->veg[k].veg_intPPT_d); - if (GT(v->veg[SW_GRASS].cov.fCover, 0.) && GT(snowdepth_scale_grass, 0.)) { - grass_intercepted_water(&h2o_for_soil, &grass_h2o, ppt_toUse, v->veg[SW_GRASS].vegcov_daily[doy], snowdepth_scale_grass * v->veg[SW_GRASS].cov.fCover, - v->veg[SW_GRASS].veg_intPPT_a, v->veg[SW_GRASS].veg_intPPT_b, v->veg[SW_GRASS].veg_intPPT_c, v->veg[SW_GRASS].veg_intPPT_d); - } else { - grass_h2o = 0.; - } /* end grass interception */ + /* amount of rain that is not intercepted by the canopy */ + ppt_toUse = h2o_for_soil; + + } else { + /* snow depth is more than vegetation height */ + h2o_for_soil = ppt_toUse; + veg_h2o[k] = 0.; + } /* end interception */ + } if (EQ(sw->snowpack[Today], 0.)) { /* litter interception only when no snow */ litter_h2o_help = 0.; - if (GT(v->veg[SW_TREES].cov.fCover, 0.)) { - litter_intercepted_water(&h2o_for_soil, &litter_h2o, v->veg[SW_TREES].litter_daily[doy], v->veg[SW_TREES].cov.fCover, v->veg[SW_TREES].litt_intPPT_a, - v->veg[SW_TREES].litt_intPPT_b, v->veg[SW_TREES].litt_intPPT_c, v->veg[SW_TREES].litt_intPPT_d); - litter_h2o_help += litter_h2o; - } - - if (GT(v->veg[SW_SHRUB].cov.fCover, 0.)) { - litter_intercepted_water(&h2o_for_soil, &litter_h2o, v->veg[SW_SHRUB].litter_daily[doy], v->veg[SW_SHRUB].cov.fCover, v->veg[SW_SHRUB].litt_intPPT_a, - v->veg[SW_SHRUB].litt_intPPT_b, v->veg[SW_SHRUB].litt_intPPT_c, v->veg[SW_SHRUB].litt_intPPT_d); - litter_h2o_help += litter_h2o; - } - - if (GT(v->veg[SW_FORBS].cov.fCover, 0.)) { - litter_intercepted_water(&h2o_for_soil, &litter_h2o, v->veg[SW_FORBS].litter_daily[doy], v->veg[SW_FORBS].cov.fCover, v->veg[SW_FORBS].litt_intPPT_a, - v->veg[SW_FORBS].litt_intPPT_b, v->veg[SW_FORBS].litt_intPPT_c, v->veg[SW_FORBS].litt_intPPT_d); - litter_h2o_help += litter_h2o; - } + ForEachVegType(k) + { + if (GT(v->veg[k].cov.fCover, 0.)) { + litter_intercepted_water(&h2o_for_soil, &litter_h2o, v->veg[k].litter_daily[doy], + v->veg[k].cov.fCover, v->veg[k].litt_intPPT_a, v->veg[k].litt_intPPT_b, + v->veg[k].litt_intPPT_c, v->veg[k].litt_intPPT_d); - if (GT(v->veg[SW_GRASS].cov.fCover, 0.)) { - litter_intercepted_water(&h2o_for_soil, &litter_h2o, v->veg[SW_GRASS].litter_daily[doy], v->veg[SW_GRASS].cov.fCover, v->veg[SW_GRASS].litt_intPPT_a, - v->veg[SW_GRASS].litt_intPPT_b, v->veg[SW_GRASS].litt_intPPT_c, v->veg[SW_GRASS].litt_intPPT_d); - litter_h2o_help += litter_h2o; + litter_h2o_help += litter_h2o; + } } litter_h2o = litter_h2o_help; @@ -336,16 +333,13 @@ void SW_Water_Flow(void) { } /* Sum cumulative intercepted components */ - sw->int_veg[SW_TREES] = tree_h2o; - sw->int_veg[SW_SHRUB] = shrub_h2o; - sw->int_veg[SW_FORBS] = forb_h2o; - sw->int_veg[SW_GRASS] = grass_h2o; - sw->litter_int = litter_h2o; + ForEachVegType(k) + { + sw->int_veg[k] = veg_h2o[k]; + veg_h2o_qum[k][Today] = veg_h2o_qum[k][Yesterday] + veg_h2o[k]; + } - tree_h2o_qum[Today] = tree_h2o_qum[Yesterday] + tree_h2o; - shrub_h2o_qum[Today] = shrub_h2o_qum[Yesterday] + shrub_h2o; - forb_h2o_qum[Today] = forb_h2o_qum[Yesterday] + forb_h2o; - grass_h2o_qum[Today] = grass_h2o_qum[Yesterday] + grass_h2o; + sw->litter_int = litter_h2o; litter_h2o_qum[Today] = litter_h2o_qum[Yesterday] + litter_h2o; /* End Interception */ @@ -413,151 +407,100 @@ void SW_Water_Flow(void) { /* PET */ - sw->pet = SW_Site.pet_scale - * petfunc(doy, SW_Weather.now.temp_avg[Today], SW_Site.latitude, SW_Site.altitude, SW_Site.slope, SW_Site.aspect, - v->veg[SW_GRASS].cov.albedo * v->veg[SW_GRASS].cov.fCover + v->veg[SW_SHRUB].cov.albedo * v->veg[SW_SHRUB].cov.fCover + v->veg[SW_FORBS].cov.albedo * v->veg[SW_FORBS].cov.fCover - + v->veg[SW_TREES].cov.albedo * v->veg[SW_TREES].cov.fCover + v->bare_cov.albedo * v->bare_cov.fCover, SW_Sky.r_humidity_daily[doy], - SW_Sky.windspeed_daily[doy], SW_Sky.cloudcov_daily[doy], SW_Sky.transmission_daily[doy]); + x = v->bare_cov.albedo * v->bare_cov.fCover; + ForEachVegType(k) + { + x += v->veg[k].cov.albedo * v->veg[k].cov.fCover; + } + + sw->pet = SW_Site.pet_scale; + sw->pet *= petfunc(doy, SW_Weather.now.temp_avg[Today], SW_Site.latitude, + SW_Site.altitude, SW_Site.slope, SW_Site.aspect, x, SW_Sky.r_humidity_daily[doy], + SW_Sky.windspeed_daily[doy], SW_Sky.cloudcov_daily[doy], SW_Sky.transmission_daily[doy]); + /* Bare-soil evaporation rates */ if (GT(v->bare_cov.fCover, 0.) && EQ(sw->snowpack[Today], 0.)) /* bare ground present AND no snow on ground */ { - pot_soil_evap_bs(&soil_evap_rate_bs, SW_Site.n_evap_lyrs, lyrEvapCo, sw->pet, SW_Site.evap.xinflec, SW_Site.evap.slope, SW_Site.evap.yinflec, - SW_Site.evap.range, lyrWidths, lyrSWCBulk); + pot_soil_evap_bs(&soil_evap_rate_bs, SW_Site.n_evap_lyrs, lyrEvapCo, sw->pet, + SW_Site.evap.xinflec, SW_Site.evap.slope, SW_Site.evap.yinflec, + SW_Site.evap.range, lyrWidths, lyrSWCBulk); soil_evap_rate_bs *= v->bare_cov.fCover; + } else { soil_evap_rate_bs = 0; } - /* Tree transpiration & bare-soil evaporation rates */ - if (GT(v->veg[SW_TREES].cov.fCover, 0.) && GT(snowdepth_scale_tree, 0.)) { /* trees present AND trees not fully covered in snow */ - tree_EsT_partitioning(&soil_evap_tree, &transp_tree, v->veg[SW_TREES].lai_live_daily[doy], v->veg[SW_TREES].EsTpartitioning_param); - - if (EQ(sw->snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ - pot_soil_evap(&soil_evap_rate_tree, SW_Site.n_evap_lyrs, lyrEvapCo, v->veg[SW_TREES].total_agb_daily[doy], soil_evap_tree, sw->pet, SW_Site.evap.xinflec, - SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, v->veg[SW_TREES].Es_param_limit); - soil_evap_rate_tree *= v->veg[SW_TREES].cov.fCover; - } else { - soil_evap_rate_tree = 0.; - } - - transp_weighted_avg(&swpot_avg_tree, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_TREES], lyrTrRegions_Tree, lyrTranspCo_Tree, lyrSWCBulk); - - pot_transp(&transp_rate_tree, swpot_avg_tree, v->veg[SW_TREES].biolive_daily[doy], v->veg[SW_TREES].biodead_daily[doy], transp_tree, sw->pet, - SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, v->veg[SW_TREES].shade_scale, v->veg[SW_TREES].shade_deadmax, - v->veg[SW_TREES].tr_shade_effects.xinflec, v->veg[SW_TREES].tr_shade_effects.slope, v->veg[SW_TREES].tr_shade_effects.yinflec, - v->veg[SW_TREES].tr_shade_effects.range, v->veg[SW_TREES].co2_multipliers[WUE_INDEX][SW_Model.simyear]); - transp_rate_tree *= snowdepth_scale_tree * v->veg[SW_TREES].cov.fCover; - } else { - soil_evap_rate_tree = 0.; - transp_rate_tree = 0.; - } + /* Potential transpiration & bare-soil evaporation rates */ + ForEachVegType(k) + { + if (GT(v->veg[k].cov.fCover, 0.) && GT(snowdepth_scale_veg[k], 0.)) { + /* vegetation type k present AND not fully covered in snow */ + EsT_partitioning(&soil_evap[k], &transp_veg[k], v->veg[k].lai_live_daily[doy], + v->veg[k].EsTpartitioning_param); - /* Shrub transpiration & bare-soil evaporation rates */ - if (GT(v->veg[SW_SHRUB].cov.fCover, 0.) && GT(snowdepth_scale_shrub, 0.)) { /* shrubs present AND shrubs not fully covered in snow */ - shrub_EsT_partitioning(&soil_evap_shrub, &transp_shrub, v->veg[SW_SHRUB].lai_live_daily[doy], v->veg[SW_SHRUB].EsTpartitioning_param); + if (EQ(sw->snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ + pot_soil_evap(&soil_evap_rate[k], SW_Site.n_evap_lyrs, lyrEvapCo, + v->veg[k].total_agb_daily[doy], soil_evap[k], sw->pet, + SW_Site.evap.xinflec, SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, + lyrWidths, lyrSWCBulk, v->veg[k].Es_param_limit); - if (EQ(sw->snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ - pot_soil_evap(&soil_evap_rate_shrub, SW_Site.n_evap_lyrs, lyrEvapCo, v->veg[SW_SHRUB].total_agb_daily[doy], soil_evap_shrub, sw->pet, SW_Site.evap.xinflec, - SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, v->veg[SW_SHRUB].Es_param_limit); - soil_evap_rate_shrub *= v->veg[SW_SHRUB].cov.fCover; - } else { - soil_evap_rate_shrub = 0.; - } + soil_evap_rate[k] *= v->veg[k].cov.fCover; - transp_weighted_avg(&swpot_avg_shrub, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_SHRUB], lyrTrRegions_Shrub, lyrTranspCo_Shrub, lyrSWCBulk); + } else { + soil_evap_rate[k] = 0.; + } - pot_transp(&transp_rate_shrub, swpot_avg_shrub, v->veg[SW_SHRUB].biolive_daily[doy], v->veg[SW_SHRUB].biodead_daily[doy], transp_shrub, sw->pet, - SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, v->veg[SW_SHRUB].shade_scale, v->veg[SW_SHRUB].shade_deadmax, - v->veg[SW_SHRUB].tr_shade_effects.xinflec, v->veg[SW_SHRUB].tr_shade_effects.slope, v->veg[SW_SHRUB].tr_shade_effects.yinflec, - v->veg[SW_SHRUB].tr_shade_effects.range, v->veg[SW_SHRUB].co2_multipliers[WUE_INDEX][SW_Model.simyear]); - transp_rate_shrub *= snowdepth_scale_shrub * v->veg[SW_SHRUB].cov.fCover; + transp_weighted_avg(&swpot_avg[k], SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[k], + lyrTrRegions[k], lyrTranspCo[k], lyrSWCBulk); - } else { - soil_evap_rate_shrub = 0.; - transp_rate_shrub = 0.; - } + pot_transp(&transp_rate[k], swpot_avg[k], + v->veg[k].biolive_daily[doy], v->veg[k].biodead_daily[doy], + transp_veg[k], sw->pet, + SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, + v->veg[k].shade_scale, v->veg[k].shade_deadmax, + v->veg[k].tr_shade_effects.xinflec, v->veg[k].tr_shade_effects.slope, + v->veg[k].tr_shade_effects.yinflec, v->veg[k].tr_shade_effects.range, + v->veg[k].co2_multipliers[WUE_INDEX][SW_Model.simyear]); - /* Forb transpiration & bare-soil evaporation rates */ - if (GT(v->veg[SW_FORBS].cov.fCover, 0.) && GT(snowdepth_scale_forb, 0.)) { /* forbs present AND forbs not fully covered in snow */ - forb_EsT_partitioning(&soil_evap_forb, &transp_forb, v->veg[SW_FORBS].lai_live_daily[doy], v->veg[SW_FORBS].EsTpartitioning_param); + transp_rate[k] *= snowdepth_scale_veg[k] * v->veg[k].cov.fCover; - if (EQ(sw->snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ - pot_soil_evap(&soil_evap_rate_forb, SW_Site.n_evap_lyrs, lyrEvapCo, v->veg[SW_FORBS].total_agb_daily[doy], soil_evap_forb, sw->pet, SW_Site.evap.xinflec, - SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, v->veg[SW_FORBS].Es_param_limit); - soil_evap_rate_forb *= v->veg[SW_FORBS].cov.fCover; } else { - soil_evap_rate_forb = 0.; + soil_evap_rate[k] = 0.; + transp_rate[k] = 0.; } - - transp_weighted_avg(&swpot_avg_forb, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_FORBS], lyrTrRegions_Forb, lyrTranspCo_Forb, lyrSWCBulk); - - pot_transp(&transp_rate_forb, swpot_avg_forb, v->veg[SW_FORBS].biolive_daily[doy], v->veg[SW_FORBS].biodead_daily[doy], transp_forb, sw->pet, - SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, v->veg[SW_FORBS].shade_scale, v->veg[SW_FORBS].shade_deadmax, - v->veg[SW_FORBS].tr_shade_effects.xinflec, v->veg[SW_FORBS].tr_shade_effects.slope, v->veg[SW_FORBS].tr_shade_effects.yinflec, - v->veg[SW_FORBS].tr_shade_effects.range, v->veg[SW_FORBS].co2_multipliers[WUE_INDEX][SW_Model.simyear]); - transp_rate_forb *= snowdepth_scale_forb * v->veg[SW_FORBS].cov.fCover; - - } else { - soil_evap_rate_forb = 0.; - transp_rate_forb = 0.; } - /* Grass transpiration & bare-soil evaporation rates */ - if (GT(v->veg[SW_GRASS].cov.fCover, 0.) && GT(snowdepth_scale_grass, 0.)) { /* grasses present AND grasses not fully covered in snow */ - grass_EsT_partitioning(&soil_evap_grass, &transp_grass, v->veg[SW_GRASS].lai_live_daily[doy], v->veg[SW_GRASS].EsTpartitioning_param); - - if (EQ(sw->snowpack[Today], 0.)) { /* bare-soil evaporation only when no snow */ - pot_soil_evap(&soil_evap_rate_grass, SW_Site.n_evap_lyrs, lyrEvapCo, v->veg[SW_GRASS].total_agb_daily[doy], soil_evap_grass, sw->pet, SW_Site.evap.xinflec, - SW_Site.evap.slope, SW_Site.evap.yinflec, SW_Site.evap.range, lyrWidths, lyrSWCBulk, v->veg[SW_GRASS].Es_param_limit); - soil_evap_rate_grass *= v->veg[SW_GRASS].cov.fCover; - } else { - soil_evap_rate_grass = 0.; - } - - transp_weighted_avg(&swpot_avg_grass, SW_Site.n_transp_rgn, SW_Site.n_transp_lyrs[SW_GRASS], lyrTrRegions_Grass, lyrTranspCo_Grass, lyrSWCBulk); - pot_transp(&transp_rate_grass, swpot_avg_grass, v->veg[SW_GRASS].biolive_daily[doy], v->veg[SW_GRASS].biodead_daily[doy], transp_grass, sw->pet, - SW_Site.transp.xinflec, SW_Site.transp.slope, SW_Site.transp.yinflec, SW_Site.transp.range, v->veg[SW_GRASS].shade_scale, v->veg[SW_GRASS].shade_deadmax, - v->veg[SW_GRASS].tr_shade_effects.xinflec, v->veg[SW_GRASS].tr_shade_effects.slope, v->veg[SW_GRASS].tr_shade_effects.yinflec, - v->veg[SW_GRASS].tr_shade_effects.range, v->veg[SW_GRASS].co2_multipliers[WUE_INDEX][SW_Model.simyear]); - transp_rate_grass *= snowdepth_scale_grass * v->veg[SW_GRASS].cov.fCover; - } else { - soil_evap_rate_grass = 0.; - transp_rate_grass = 0.; + /* Potential evaporation rates of intercepted and surface water */ + ForEachVegType(k) { + surface_evap_veg_rate[k] = veg_h2o_qum[k][Today]; } - /* Potential evaporation rates of intercepted and surface water */ - surface_evap_tree_rate = tree_h2o_qum[Today]; - surface_evap_shrub_rate = shrub_h2o_qum[Today]; - surface_evap_forb_rate = forb_h2o_qum[Today]; - surface_evap_grass_rate = grass_h2o_qum[Today]; surface_evap_litter_rate = litter_h2o_qum[Today]; surface_evap_standingWater_rate = standingWater[Today]; snow_evap_rate = SW_Weather.now.snowloss[Today]; /* but this is fixed and can also include snow redistribution etc., so don't scale to PET */ /* Scale all (potential) evaporation and transpiration flux rates to PET */ - rate_help = surface_evap_tree_rate + surface_evap_forb_rate + surface_evap_shrub_rate + surface_evap_grass_rate + surface_evap_litter_rate - + surface_evap_standingWater_rate + soil_evap_rate_tree + transp_rate_tree + soil_evap_rate_forb + transp_rate_forb + soil_evap_rate_shrub + transp_rate_shrub - + soil_evap_rate_grass + transp_rate_grass + soil_evap_rate_bs; + rate_help = surface_evap_litter_rate + surface_evap_standingWater_rate + + soil_evap_rate_bs; + ForEachVegType(k) { + rate_help += surface_evap_veg_rate[k] + soil_evap_rate[k] + transp_rate[k]; + } + if (GT(rate_help, sw->pet)) { rate_help = sw->pet / rate_help; - surface_evap_tree_rate *= rate_help; - surface_evap_forb_rate *= rate_help; - surface_evap_shrub_rate *= rate_help; - surface_evap_grass_rate *= rate_help; + ForEachVegType(k) + { + surface_evap_veg_rate[k] *= rate_help; + soil_evap_rate[k] *= rate_help; + transp_rate[k] *= rate_help; + } + surface_evap_litter_rate *= rate_help; surface_evap_standingWater_rate *= rate_help; - soil_evap_rate_tree *= rate_help; - transp_rate_tree *= rate_help; - soil_evap_rate_forb *= rate_help; - transp_rate_forb *= rate_help; - soil_evap_rate_shrub *= rate_help; - transp_rate_shrub *= rate_help; - soil_evap_rate_grass *= rate_help; - transp_rate_grass *= rate_help; soil_evap_rate_bs *= rate_help; } @@ -566,134 +509,98 @@ void SW_Water_Flow(void) { sw->aet += snow_evap_rate; /* Evaporation of intercepted and surface water */ - evap_fromSurface(&tree_h2o_qum[Today], &surface_evap_tree_rate, &sw->aet); - evap_fromSurface(&shrub_h2o_qum[Today], &surface_evap_shrub_rate, &sw->aet); - evap_fromSurface(&forb_h2o_qum[Today], &surface_evap_forb_rate, &sw->aet); - evap_fromSurface(&grass_h2o_qum[Today], &surface_evap_grass_rate, &sw->aet); + ForEachVegType(k) + { + evap_fromSurface(&veg_h2o_qum[k][Today], &surface_evap_veg_rate[k], &sw->aet); + sw->evap_veg[k] = surface_evap_veg_rate[k]; + } + evap_fromSurface(&litter_h2o_qum[Today], &surface_evap_litter_rate, &sw->aet); evap_fromSurface(&standingWater[Today], &surface_evap_standingWater_rate, &sw->aet); - sw->evap_veg[SW_TREES] = surface_evap_tree_rate; - sw->evap_veg[SW_SHRUB] = surface_evap_shrub_rate; - sw->evap_veg[SW_FORBS] = surface_evap_forb_rate; - sw->evap_veg[SW_GRASS] = surface_evap_grass_rate; sw->litter_evap = surface_evap_litter_rate; sw->surfaceWater_evap = surface_evap_standingWater_rate; /* bare-soil evaporation */ if (GT(v->bare_cov.fCover, 0.) && EQ(sw->snowpack[Today], 0.)) { /* remove bare-soil evap from swv */ - remove_from_soil(lyrSWCBulk, lyrEvap_BareGround, &sw->aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_bs, lyrSWCBulk_HalfWiltpts); + remove_from_soil(lyrSWCBulk, lyrEvap_BareGround, &sw->aet, SW_Site.n_evap_lyrs, + lyrEvapCo, soil_evap_rate_bs, lyrSWCBulk_HalfWiltpts); + } else { /* Set daily array to zero, no evaporation */ - LyrIndex i; - for (i = 0; i < SW_Site.n_evap_lyrs;) - lyrEvap_BareGround[i++] = 0.; + ForEachEvapLayer(i) { + lyrEvap_BareGround[i] = 0.; + } } - /* Tree transpiration and bare-soil evaporation */ - if (GT(v->veg[SW_TREES].cov.fCover, 0.) && GT(snowdepth_scale_tree, 0.)) { - /* remove bare-soil evap from swc */ - remove_from_soil(lyrSWCBulk, lyrEvap_Tree, &sw->aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_tree, lyrSWCBulk_HalfWiltpts); - - /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Tree, &sw->aet, SW_Site.n_transp_lyrs[SW_TREES], lyrTranspCo_Tree, transp_rate_tree, lyrSWCBulk_atSWPcrit_Tree); - } else { - /* Set daily array to zero, no evaporation or transpiration */ - LyrIndex i; - for (i = 0; i < SW_Site.n_evap_lyrs;) - lyrEvap_Tree[i++] = 0.; - for (i = 0; i < SW_Site.n_transp_lyrs[SW_TREES];) - lyrTransp_Tree[i++] = 0.; - } + /* Vegetation transpiration and bare-soil evaporation */ + ForEachVegType(k) + { + if (GT(v->veg[k].cov.fCover, 0.) && GT(snowdepth_scale_veg[k], 0.)) { + /* remove bare-soil evap from swc */ + remove_from_soil(lyrSWCBulk, lyrEvap[k], &sw->aet, SW_Site.n_evap_lyrs, + lyrEvapCo, soil_evap_rate[k], lyrSWCBulk_HalfWiltpts); - /* Shrub transpiration and bare-soil evaporation */ - if (GT(v->veg[SW_SHRUB].cov.fCover, 0.) && GT(snowdepth_scale_shrub, 0.)) { - /* remove bare-soil evap from swc */ - remove_from_soil(lyrSWCBulk, lyrEvap_Shrub, &sw->aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_shrub, lyrSWCBulk_HalfWiltpts); + /* remove transp from swc */ + remove_from_soil(lyrSWCBulk, lyrTransp[k], &sw->aet, SW_Site.n_transp_lyrs[k], + lyrTranspCo[k], transp_rate[k], lyrSWCBulk_atSWPcrit[k]); - /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Shrub, &sw->aet, SW_Site.n_transp_lyrs[SW_SHRUB], lyrTranspCo_Shrub, transp_rate_shrub, lyrSWCBulk_atSWPcrit_Shrub); - } else { - /* Set daily array to zero, no evaporation or transpiration */ - LyrIndex i; - for (i = 0; i < SW_Site.n_evap_lyrs;) - lyrEvap_Shrub[i++] = 0.; - for (i = 0; i < SW_Site.n_transp_lyrs[SW_SHRUB];) - lyrTransp_Shrub[i++] = 0.; + } else { + /* Set daily array to zero, no evaporation or transpiration */ + ForEachSoilLayer(i) { + lyrTransp[k][i] = lyrEvap[k][i] = 0.; + } + } } - /* Forb transpiration and bare-soil evaporation */ - if (GT(v->veg[SW_FORBS].cov.fCover, 0.) && GT(snowdepth_scale_forb, 0.)) { - /* remove bare-soil evap from swc */ - remove_from_soil(lyrSWCBulk, lyrEvap_Forb, &sw->aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_forb, lyrSWCBulk_HalfWiltpts); - - /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Forb, &sw->aet, SW_Site.n_transp_lyrs[SW_FORBS], lyrTranspCo_Forb, transp_rate_forb, lyrSWCBulk_atSWPcrit_Forb); - } else { - /* Set daily array to zero, no evaporation or transpiration */ - LyrIndex i; - for (i = 0; i < SW_Site.n_evap_lyrs;) - lyrEvap_Forb[i++] = 0.; - for (i = 0; i < SW_Site.n_transp_lyrs[SW_FORBS];) - lyrTransp_Forb[i++] = 0.; - } - /* Grass transpiration & bare-soil evaporation */ - if (GT(v->veg[SW_GRASS].cov.fCover, 0.) && GT(snowdepth_scale_grass, 0.)) { - /* remove bare-soil evap from swc */ - remove_from_soil(lyrSWCBulk, lyrEvap_Grass, &sw->aet, SW_Site.n_evap_lyrs, lyrEvapCo, soil_evap_rate_grass, lyrSWCBulk_HalfWiltpts); + /* Hydraulic redistribution */ + ForEachVegTypeBottomUp(k) { + if (v->veg[k].flagHydraulicRedistribution && GT(v->veg[k].cov.fCover, 0.) && + GT(v->veg[k].biolive_daily[doy], 0.)) { - /* remove transp from swc */ - remove_from_soil(lyrSWCBulk, lyrTransp_Grass, &sw->aet, SW_Site.n_transp_lyrs[SW_GRASS], lyrTranspCo_Grass, transp_rate_grass, lyrSWCBulk_atSWPcrit_Grass); - } else { - /* Set daily array to zero, no evaporation or transpiration */ - LyrIndex i; - for (i = 0; i < SW_Site.n_evap_lyrs;) - lyrEvap_Grass[i++] = 0.; - for (i = 0; i < SW_Site.n_transp_lyrs[SW_GRASS];) - lyrTransp_Grass[i++] = 0.; + hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo[k], + lyrHydRed[k], SW_Site.n_layers, v->veg[k].maxCondroot, v->veg[k].swpMatric50, + v->veg[k].shapeCond, v->veg[k].cov.fCover); + } } - /* Hydraulic redistribution */ - if (v->veg[SW_GRASS].flagHydraulicRedistribution && GT(v->veg[SW_GRASS].cov.fCover, 0.) && GT(v->veg[SW_GRASS].biolive_daily[doy], 0.)) { - hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Grass, lyrHydRed_Grass, SW_Site.n_layers, v->veg[SW_GRASS].maxCondroot, - v->veg[SW_GRASS].swpMatric50, v->veg[SW_GRASS].shapeCond, v->veg[SW_GRASS].cov.fCover); - } - if (v->veg[SW_FORBS].flagHydraulicRedistribution && GT(v->veg[SW_FORBS].cov.fCover, 0.) && GT(v->veg[SW_FORBS].biolive_daily[doy], 0.)) { - hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Forb, lyrHydRed_Forb, SW_Site.n_layers, v->veg[SW_FORBS].maxCondroot, v->veg[SW_FORBS].swpMatric50, - v->veg[SW_FORBS].shapeCond, v->veg[SW_FORBS].cov.fCover); - } - if (v->veg[SW_SHRUB].flagHydraulicRedistribution && GT(v->veg[SW_SHRUB].cov.fCover, 0.) && GT(v->veg[SW_SHRUB].biolive_daily[doy], 0.)) { - hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Shrub, lyrHydRed_Shrub, SW_Site.n_layers, v->veg[SW_SHRUB].maxCondroot, - v->veg[SW_SHRUB].swpMatric50, v->veg[SW_SHRUB].shapeCond, v->veg[SW_SHRUB].cov.fCover); - } - if (v->veg[SW_TREES].flagHydraulicRedistribution && GT(v->veg[SW_TREES].cov.fCover, 0.) && GT(v->veg[SW_TREES].biolive_daily[doy], 0.)) { - hydraulic_redistribution(lyrSWCBulk, lyrSWCBulk_Wiltpts, lyrTranspCo_Tree, lyrHydRed_Tree, SW_Site.n_layers, v->veg[SW_TREES].maxCondroot, v->veg[SW_TREES].swpMatric50, - v->veg[SW_TREES].shapeCond, v->veg[SW_TREES].cov.fCover); - } /* Calculate percolation for unsaturated soil water conditions. */ /* 01/06/2011 (drs) call to infiltrate_water_low() has to be the last swc affecting calculation */ - infiltrate_water_low(lyrSWCBulk, lyrDrain, &drainout, SW_Site.n_layers, SW_Site.slow_drain_coeff, SLOW_DRAIN_DEPTH, lyrSWCBulk_FieldCaps, lyrWidths, lyrSWCBulk_Mins, - lyrSWCBulk_Saturated, lyrImpermeability, &standingWater[Today]); + infiltrate_water_low(lyrSWCBulk, lyrDrain, &drainout, SW_Site.n_layers, + SW_Site.slow_drain_coeff, SLOW_DRAIN_DEPTH, lyrSWCBulk_FieldCaps, lyrWidths, + lyrSWCBulk_Mins, lyrSWCBulk_Saturated, lyrImpermeability, &standingWater[Today]); sw->surfaceWater = standingWater[Today]; - /* Soil Temperature starts here */ - double biomass; // computing the live biomass real quickly to condense the call to soil_temperature -biomass = v->veg[SW_GRASS].biomass_daily[doy] * v->veg[SW_GRASS].cov.fCover + v->veg[SW_SHRUB].biolive_daily[doy] * v->veg[SW_SHRUB].cov.fCover - + v->veg[SW_FORBS].biomass_daily[doy] * v->veg[SW_FORBS].cov.fCover + v->veg[SW_TREES].biolive_daily[doy] * v->veg[SW_TREES].cov.fCover; // changed to exclude tree biomass, bMatric/c it was breaking the soil_temperature function + /* Soil Temperature starts here */ - // soil_temperature function computes the soil temp for each layer and stores it in lyrsTemp - // doesn't affect SWC at all, but needs it for the calculation, so therefore the temperature is the last calculation done - if (SW_Site.use_soil_temp) - soil_temperature(SW_Weather.now.temp_avg[Today], sw->pet, sw->aet, biomass, lyrSWCBulk, lyrSWCBulk_Saturated, lyrbDensity, lyrWidths, lyroldsTemp, lyrsTemp,surfaceTemp, SW_Site.n_layers, - lyrSWCBulk_FieldCaps, lyrSWCBulk_Wiltpts, SW_Site.bmLimiter, SW_Site.t1Param1, SW_Site.t1Param2, SW_Site.t1Param3, SW_Site.csParam1, SW_Site.csParam2, - SW_Site.shParam, sw->snowdepth, SW_Site.meanAirTemp, SW_Site.stDeltaX, SW_Site.stMaxDepth, SW_Site.stNRGR, sw->snowpack[Today]); + // computing the live biomass real quickly to condense the call to soil_temperature + x = 0.; + ForEachVegType(k) + { + if (k == SW_TREES || k == SW_SHRUB) { + // changed to exclude tree biomass, bMatric/c it was breaking the soil_temperature function + x += v->veg[k].biolive_daily[doy] * v->veg[k].cov.fCover; + } else { + x += v->veg[k].biomass_daily[doy] * v->veg[k].cov.fCover; + } + } + // soil_temperature function computes the soil temp for each layer and stores it in lyrsTemp + // doesn't affect SWC at all (yet), but needs it for the calculation, so therefore the temperature is the last calculation done + if (SW_Site.use_soil_temp) { + soil_temperature(SW_Weather.now.temp_avg[Today], sw->pet, sw->aet, x, lyrSWCBulk, + lyrSWCBulk_Saturated, lyrbDensity, lyrWidths, lyroldsTemp, lyrsTemp,surfaceTemp, + SW_Site.n_layers, lyrSWCBulk_FieldCaps, lyrSWCBulk_Wiltpts, SW_Site.bmLimiter, + SW_Site.t1Param1, SW_Site.t1Param2, SW_Site.t1Param3, SW_Site.csParam1, + SW_Site.csParam2, SW_Site.shParam, sw->snowdepth, SW_Site.meanAirTemp, + SW_Site.stDeltaX, SW_Site.stMaxDepth, SW_Site.stNRGR, sw->snowpack[Today]); + } /* Soil Temperature ends here */ @@ -702,10 +609,9 @@ biomass = v->veg[SW_GRASS].biomass_daily[doy] * v->veg[SW_GRASS].cov.fCover + v- standingWater[Yesterday] = standingWater[Today]; litter_h2o_qum[Yesterday] = litter_h2o_qum[Today]; - tree_h2o_qum[Yesterday] = tree_h2o_qum[Today]; - shrub_h2o_qum[Yesterday] = shrub_h2o_qum[Today]; - forb_h2o_qum[Yesterday] = forb_h2o_qum[Today]; - grass_h2o_qum[Yesterday] = grass_h2o_qum[Today]; + ForEachVegType(k) { + veg_h2o_qum[k][Yesterday] = veg_h2o_qum[k][Today]; + } } /* END OF WATERFLOW */ @@ -725,6 +631,7 @@ static void records2arrays(void) { * see also Site.c. */ LyrIndex i; + int k; ForEachSoilLayer(i) { @@ -735,18 +642,10 @@ static void records2arrays(void) { if (SW_Model.doy == SW_Model.firstdoy) { ForEachSoilLayer(i) { - lyrTrRegions_Tree[i] = SW_Site.lyr[i]->my_transp_rgn[SW_TREES]; - lyrTrRegions_Forb[i] = SW_Site.lyr[i]->my_transp_rgn[SW_FORBS]; - lyrTrRegions_Shrub[i] = SW_Site.lyr[i]->my_transp_rgn[SW_SHRUB]; - lyrTrRegions_Grass[i] = SW_Site.lyr[i]->my_transp_rgn[SW_GRASS]; lyrSWCBulk_FieldCaps[i] = SW_Site.lyr[i]->swcBulk_fieldcap; lyrWidths[i] = SW_Site.lyr[i]->width; lyrSWCBulk_Wiltpts[i] = SW_Site.lyr[i]->swcBulk_wiltpt; lyrSWCBulk_HalfWiltpts[i] = SW_Site.lyr[i]->swcBulk_wiltpt / 2.; - lyrSWCBulk_atSWPcrit_Tree[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit[SW_TREES]; - lyrSWCBulk_atSWPcrit_Forb[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit[SW_FORBS]; - lyrSWCBulk_atSWPcrit_Shrub[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit[SW_SHRUB]; - lyrSWCBulk_atSWPcrit_Grass[i] = SW_Site.lyr[i]->swcBulk_atSWPcrit[SW_GRASS]; lyrSWCBulk_Mins[i] = SW_Site.lyr[i]->swcBulk_min; lyrpsisMatric[i] = SW_Site.lyr[i]->psisMatric; lyrthetasMatric[i] = SW_Site.lyr[i]->thetasMatric; @@ -756,31 +655,13 @@ static void records2arrays(void) { lyrSWCBulk_Saturated[i] = SW_Site.lyr[i]->swcBulk_saturated; lyrbDensity[i] = SW_Site.lyr[i]->soilBulk_density; - /*Init hydraulic redistribution to zero */ - lyrHydRed_Tree[i] = 0.; - lyrHydRed_Shrub[i] = 0.; - lyrHydRed_Forb[i] = 0.; - lyrHydRed_Grass[i] = 0.; - } - - ForEachTreeTranspLayer(i) - { - lyrTranspCo_Tree[i] = SW_Site.lyr[i]->transp_coeff[SW_TREES]; - } - - ForEachShrubTranspLayer(i) - { - lyrTranspCo_Shrub[i] = SW_Site.lyr[i]->transp_coeff[SW_SHRUB]; - } - - ForEachForbTranspLayer(i) - { - lyrTranspCo_Forb[i] = SW_Site.lyr[i]->transp_coeff[SW_FORBS]; - } - - ForEachGrassTranspLayer(i) - { - lyrTranspCo_Grass[i] = SW_Site.lyr[i]->transp_coeff[SW_GRASS]; + ForEachVegType(k) + { + lyrTrRegions[k][i] = SW_Site.lyr[i]->my_transp_rgn[k]; + lyrSWCBulk_atSWPcrit[k][i] = SW_Site.lyr[i]->swcBulk_atSWPcrit[k]; + lyrHydRed[k][i] = 0.; // Init hydraulic redistribution to zero + lyrTranspCo[k][i] = SW_Site.lyr[i]->transp_coeff[k]; + } } ForEachEvapLayer(i) @@ -795,16 +676,18 @@ static void arrays2records(void) { * the appropriate records. */ LyrIndex i; + int k; ForEachSoilLayer(i) { SW_Soilwat.swcBulk[Today][i] = lyrSWCBulk[i]; SW_Soilwat.drain[i] = lyrDrain[i]; - SW_Soilwat.hydred[SW_TREES][i] = lyrHydRed_Tree[i]; - SW_Soilwat.hydred[SW_SHRUB][i] = lyrHydRed_Shrub[i]; - SW_Soilwat.hydred[SW_FORBS][i] = lyrHydRed_Forb[i]; - SW_Soilwat.hydred[SW_GRASS][i] = lyrHydRed_Grass[i]; SW_Soilwat.sTemp[i] = lyrsTemp[i]; + ForEachVegType(k) + { + SW_Soilwat.hydred[k][i] = lyrHydRed[k][i]; + SW_Soilwat.transpiration[k][i] = lyrTransp[k][i]; + } } SW_Soilwat.surfaceTemp = surfaceTemp[Today]; SW_Weather.surfaceTemp = surfaceTemp[Today]; @@ -812,29 +695,14 @@ static void arrays2records(void) { if (SW_Site.deepdrain) SW_Soilwat.swcBulk[Today][SW_Site.deep_lyr] = drainout; - ForEachTreeTranspLayer(i) - { - SW_Soilwat.transpiration[SW_TREES][i] = lyrTransp_Tree[i]; - } - - ForEachShrubTranspLayer(i) - { - SW_Soilwat.transpiration[SW_SHRUB][i] = lyrTransp_Shrub[i]; - } - - ForEachForbTranspLayer(i) - { - SW_Soilwat.transpiration[SW_FORBS][i] = lyrTransp_Forb[i]; - } - - ForEachGrassTranspLayer(i) - { - SW_Soilwat.transpiration[SW_GRASS][i] = lyrTransp_Grass[i]; - } ForEachEvapLayer(i) { - SW_Soilwat.evaporation[i] = lyrEvap_BareGround[i] + lyrEvap_Tree[i] + lyrEvap_Forb[i] + lyrEvap_Shrub[i] + lyrEvap_Grass[i]; + SW_Soilwat.evaporation[i] = lyrEvap_BareGround[i]; + ForEachVegType(k) + { + SW_Soilwat.evaporation[i] += lyrEvap[k][i]; + } } } diff --git a/SW_Flow_lib.c b/SW_Flow_lib.c index a66c7285c..cb1485529 100644 --- a/SW_Flow_lib.c +++ b/SW_Flow_lib.c @@ -120,24 +120,24 @@ static ST_RGR_VALUES stValues; // keeps track of the soil_temperature values /* --------------------------------------------------- */ /** - \fn void grass_intercepted_water(double *pptleft, double *wintgrass, double ppt, double vegcov, double scale, double a, double b, double c, double d) { - \brief Calculate the water intercepted by grasses. + \fn void veg_intercepted_water(double *pptleft, double *wintgrass, double ppt, double x, double scale, double a, double b, double c, double d) { + \brief Calculate the water intercepted by vegetation. Equations based on Corbet and Crouse (1968). \cite Corbett1968 - \param pptleft. - \param wintgrass. - \param ppt. daily precipitation - \param vegcov. vegetation cover of grass for the day (based on monthly biomass - values, see the routine "initprod"). - \param scale. Scale paramater. Used to represent snow depth. - \param a. a parameter for intercept of grass interception equation. - \param b. b parameter for intercept of grass interception equation. - \param c. c parameter for slope of grass interception equation. - \param d. d parameter for slope of grass interception equation. - - \return pptleft. Amount of precipitation left after interception. - \return wintgrass. Amount of precipitation interception by grass. + \param pptleft + \param wintgrass + \param ppt daily precipitation + \param x vegetation cover or LAI for the day (based on monthly biomass + values, see the routine "initprod"). + \param scale Scale paramater. Used to represent snow depth. + \param a a parameter for intercept of grass interception equation. + \param b b parameter for intercept of grass interception equation. + \param c c parameter for slope of grass interception equation. + \param d d parameter for slope of grass interception equation. + + \return pptleft Amount of precipitation left after interception. + \return wintgrass Amount of precipitation interception by grass. */ @@ -158,112 +158,25 @@ static ST_RGR_VALUES stValues; // keeps track of the soil_temperature values 21-Oct-03 (cwb) added MAX_WINTLIT line **********************************************************************/ -void grass_intercepted_water(double *pptleft, double *wintgrass, double ppt, double vegcov, double scale, double a, double b, double c, double d) { - double intcpt, slope; - - if (GT(vegcov, 0.) && GT(ppt, 0.)) { - intcpt = b * vegcov + a; - slope = d * vegcov + c; - - *wintgrass = (intcpt + slope * ppt) * scale; - - *wintgrass = fmin(*wintgrass, ppt); - *wintgrass = fmin(*wintgrass, MAX_WINTSTCR); - *pptleft = fmax( ppt - *wintgrass, 0.0); - } else { /* no precip., so obviously nothing is intercepted by standing crop. */ - *pptleft = ppt; - *wintgrass = 0.0; - } -} - -void shrub_intercepted_water(double *pptleft, double *wintshrub, double ppt, double vegcov, double scale, double a, double b, double c, double d) { - /********************************************************************** - PURPOSE: Calculate the water intercepted by shrubs - **********************************************************************/ - double intcpt, slope; - - if (GT(vegcov, 0.) && GT(ppt, 0.)) { - intcpt = b * vegcov + a; - slope = d * vegcov + c; - - *wintshrub = (intcpt + slope * ppt) * scale; - - *wintshrub = fmin(*wintshrub, ppt); - *wintshrub = fmin(*wintshrub, MAX_WINTSTCR); - *pptleft = fmax( ppt - *wintshrub, 0.0); - } else { /* no precip., so obviously nothing is intercepted by standing crop. */ - *pptleft = ppt; - *wintshrub = 0.0; - } -} - -void tree_intercepted_water(double *pptleft, double *wintfor, double ppt, double LAI, double scale, double a, double b, double c, double d) { - /********************************************************************** - PURPOSE: Calculate water intercepted by forests - - HISTORY: - 11/16/2010 (drs) - - INPUTS: - ppt - precip. for the day in cm - LAI - forest LAI in cm/cm - scale - scale interception with fraction of tree vegetation component or with snowdepth-scaler - - OUTPUT: - pptleft - precip. left after interception by forest in cm. - wintfor - amount of water intercepted by forest in cm. - **********************************************************************/ +void veg_intercepted_water(double *pptleft, double *wintveg, double ppt, double x, + double scale, double a, double b, double c, double d) +{ double intcpt, slope; - if (GT(LAI, 0.) && GT(ppt, 0.)) { - intcpt = b * LAI + a; - slope = d * LAI + c; - - *wintfor = (intcpt + slope * ppt) * scale; - - *wintfor = fmin(*wintfor, ppt); - *wintfor = fmin(*wintfor, MAX_WINTFOR); - *pptleft = fmax( ppt - *wintfor, 0.0); - } else { /* no precip., so obviously nothing is intercepted by forest. */ - *pptleft = ppt; - *wintfor = 0.0; - } -} - -void forb_intercepted_water(double *pptleft, double *wintforb, double ppt, double vegcov, double scale, double a, double b, double c, double d) { - /********************************************************************** - PURPOSE: Calculate water intercepted by forbs - - - HISTORY: - 07/09/2013 (clk) - - INPUTS: - - ppt - precip. for the day in cm - vegcov - vegetation cover for the day (based on monthly biomass - values, see the routine "initprod") - scale - scale interception with fraction of forb vegetation component or with snowdepth-scaler - - OUTPUT: - - pptleft - precip. left after interception by forb in cm. - wintforb - amount of water intercepted by forb in cm. - **********************************************************************/ - double intcpt, slope; + if (GT(x, 0.) && GT(ppt, 0.)) { + intcpt = b * x + a; + slope = d * x + c; - if (GT(vegcov, 0.) && GT(ppt, 0.)) { - intcpt = b * vegcov + a; - slope = d * vegcov + c; + *wintveg = (intcpt + slope * ppt) * scale; - *wintforb = (intcpt + slope * ppt) * scale; + *wintveg = fmin(*wintveg, ppt); + *wintveg = fmin(*wintveg, MAX_WINTSTCR(x)); + *pptleft = fmax(ppt - *wintveg, 0.0); - *wintforb = fmin(*wintforb, ppt); - *wintforb = fmin(*wintforb, MAX_WINTSTCR); - *pptleft = fmax( ppt - *wintforb, 0.0); - } else { /* no precip., so obviously nothing is intercepted by forest. */ + } else { + /* no precip. or no biomass, so obviously nothing is intercepted by standing crop. */ *pptleft = ppt; - *wintforb = 0.0; + *wintveg = 0.0; } } @@ -636,7 +549,7 @@ void transp_weighted_avg(double *swp_avg, unsigned int n_tr_rgns, unsigned int n * @param blivelai the live biomass leaf area index * @param lai_param */ -void grass_EsT_partitioning(double *fbse, double *fbst, double blivelai, double lai_param) { +void EsT_partitioning(double *fbse, double *fbst, double blivelai, double lai_param) { /********************************************************************** PURPOSE: Calculate fraction of water loss from bare soil evaporation and transpiration @@ -645,6 +558,10 @@ void grass_EsT_partitioning(double *fbse, double *fbst, double blivelai, double 4/30/92 (SLC) 24-Oct-03 (cwb) changed exp(-blivelai*bsepar1) + bsepar2; to exp(-blivelai); + 08/22/2011 (drs) For trees: according to a regression based on a review by + Daikoku, K., S. Hattori, A. Deguchi, Y. Aoki, M. Miyashita, K. Matsumoto, J. Akiyama, + S. Iida, T. Toba, Y. Fujita, and T. Ohta. 2008. Influence of evaporation from the + forest floor on evapotranspiration from the dry canopy. Hydrological Processes 22:4083-4096. INPUTS: blivelai - live biomass leaf area index @@ -666,50 +583,6 @@ void grass_EsT_partitioning(double *fbse, double *fbst, double blivelai, double *fbst = 1. - (*fbse); } -void shrub_EsT_partitioning(double *fbse, double *fbst, double blivelai, double lai_param) { - /********************************************************************** - PURPOSE: Calculate fraction of water loss from bare soil - evaporation and transpiration - **********************************************************************/ - - double bsemax = 0.995; - - *fbse = exp(-lai_param * blivelai); - - *fbse = fmin(*fbse, bsemax); - *fbst = 1. - (*fbse); -} - -void tree_EsT_partitioning(double *fbse, double *fbst, double blivelai, double lai_param) { - /********************************************************************** - PURPOSE: Calculate fraction of water loss from bare soil - evaporation and transpiration - - 08/22/2011 (drs) According to a regression based on a review by Daikoku, K., S. Hattori, A. Deguchi, Y. Aoki, M. Miyashita, K. Matsumoto, J. Akiyama, S. Iida, T. Toba, Y. Fujita, and T. Ohta. 2008. Influence of evaporation from the forest floor on evapotranspiration from the dry canopy. Hydrological Processes 22:4083-4096. - **********************************************************************/ - - double bsemax = 0.995; - - *fbse = exp(-lai_param * blivelai); - - *fbse = fmin(*fbse, bsemax); - *fbst = 1. - (*fbse); -} - -void forb_EsT_partitioning(double *fbse, double *fbst, double blivelai, double lai_param) { - /********************************************************************** - PURPOSE: Calculate fraction of water loss from bare soil - evaporation and transpiration - - **********************************************************************/ - - double bsemax = 0.995; - - *fbse = exp(-lai_param * blivelai); - - *fbse = fmin(*fbse, bsemax); - *fbst = 1. - (*fbse); -} void pot_soil_evap(double *bserate, unsigned int nelyrs, double ecoeff[], double totagb, double fbse, double petday, double shift, double shape, double inflec, double range, double width[], double swc[], double Es_param_limit) { diff --git a/SW_Flow_lib.h b/SW_Flow_lib.h index f18621c5a..50760ddc0 100644 --- a/SW_Flow_lib.h +++ b/SW_Flow_lib.h @@ -40,7 +40,7 @@ /* Standing crop can only intercept so much precip * This is the limiter used inside stdcrop_intercepted() */ -#define MAX_WINTSTCR (vegcov * .1) +#define MAX_WINTSTCR(x) ((x) * .1) #define MAX_WINTFOR (ppt) /* Litter can only intercept so much precip. @@ -80,13 +80,9 @@ typedef struct { /* =================================================== */ /* Function Definitions */ /* --------------------------------------------------- */ -void grass_intercepted_water(double *pptleft, double *wintgrass, double ppt, double vegcov, double scale, double a, double b, double c, double d); -void shrub_intercepted_water(double *pptleft, double *wintshrub, double ppt, double vegcov, double scale, double a, double b, double c, double d); - -void tree_intercepted_water(double *pptleft, double *wintfor, double ppt, double LAI, double scale, double a, double b, double c, double d); - -void forb_intercepted_water(double *pptleft, double *wintforb, double ppt, double vegcov, double scale, double a, double b, double c, double d); +void veg_intercepted_water(double *pptleft, double *wintveg, double ppt, double x, + double scale, double a, double b, double c, double d); void litter_intercepted_water(double *pptleft, double *wintlit, double blitter, double scale, double a, double b, double c, double d); @@ -100,10 +96,7 @@ double svapor(double temp); void transp_weighted_avg(double *swp_avg, unsigned int n_tr_rgns, unsigned int n_layers, unsigned int tr_regions[], double tr_coeff[], double swc[]); -void grass_EsT_partitioning(double *fbse, double *fbst, double blivelai, double lai_param); -void shrub_EsT_partitioning(double *fbse, double *fbst, double blivelai, double lai_param); -void tree_EsT_partitioning(double *fbse, double *fbst, double blivelai, double lai_param); -void forb_EsT_partitioning(double *fbse, double *fbst, double blivelai, double lai_param); +void EsT_partitioning(double *fbse, double *fbst, double blivelai, double lai_param); void pot_soil_evap(double *bserate, unsigned int nelyrs, double ecoeff[], double totagb, double fbse, double petday, double shift, double shape, double inflec, double range, double width[], double swc[], double Es_param_limit); diff --git a/SW_Site.c b/SW_Site.c index 19be07f2e..4b4277390 100644 --- a/SW_Site.c +++ b/SW_Site.c @@ -80,6 +80,7 @@ extern SW_CARBON SW_Carbon; SW_SITE SW_Site; /* declared here, externed elsewhere */ extern Bool EchoInits; +extern char const *key2veg[]; #ifdef RSOILWAT extern Bool collectInData; @@ -432,14 +433,13 @@ static void _read_layers(void) { SW_SITE *v = &SW_Site; FILE *f; Bool evap_ok = swTRUE, /* mitigate gaps in layers' evap coeffs */ - transp_ok_forb = swTRUE, transp_ok_tree = swTRUE, /* same for transpiration coefficients */ - transp_ok_shrub = swTRUE, /* same for transpiration coefficients */ - transp_ok_grass = swTRUE, /* same for transpiration coefficients */ - fail = swFALSE; - LyrIndex lyrno; - int x; + transp_ok_veg[NVEGTYPES] = {swTRUE}, /* same for transpiration coefficients */ + fail = swFALSE; + LyrIndex lyrno; + int x, k; const char *errtype = "\0"; - RealF dmin = 0.0, dmax, evco, trco_forb, trco_tree, trco_shrub, trco_grass, psand, pclay, matricd, imperm, soiltemp, fval = 0, f_gravel; + RealF dmin = 0.0, dmax, evco, trco_veg[NVEGTYPES], psand, pclay, matricd, imperm, + soiltemp, fval = 0, f_gravel; /* note that Files.read() must be called prior to this. */ MyFileName = SW_F_name(eLayers); @@ -449,8 +449,9 @@ static void _read_layers(void) { while (GetALine(f, inbuf)) { lyrno = _newlayer(); - x = sscanf(inbuf, "%f %f %f %f %f %f %f %f %f %f %f %f", &dmax, &matricd, &f_gravel, &evco, &trco_grass, &trco_shrub, &trco_tree, &trco_forb, &psand, &pclay, &imperm, - &soiltemp); + x = sscanf(inbuf, "%f %f %f %f %f %f %f %f %f %f %f %f", &dmax, &matricd, &f_gravel, + &evco, &trco_veg[SW_GRASS], &trco_veg[SW_SHRUB], &trco_veg[SW_TREES], + &trco_veg[SW_FORBS], &psand, &pclay, &imperm, &soiltemp); if (x < 10) { CloseFile(&f); LogError(logfp, LOGFATAL, "%s : Incomplete record %d.\n", MyFileName, lyrno + 1); @@ -492,17 +493,14 @@ static void _read_layers(void) { v->lyr[lyrno]->soilMatric_density = matricd; v->lyr[lyrno]->fractionVolBulk_gravel = f_gravel; v->lyr[lyrno]->evap_coeff = evco; - v->lyr[lyrno]->transp_coeff[SW_FORBS] = trco_forb; - v->lyr[lyrno]->transp_coeff[SW_TREES] = trco_tree; - v->lyr[lyrno]->transp_coeff[SW_SHRUB] = trco_shrub; - v->lyr[lyrno]->transp_coeff[SW_GRASS] = trco_grass; + ForEachVegType(k) + { + v->lyr[lyrno]->transp_coeff[k] = trco_veg[k]; + v->lyr[lyrno]->my_transp_rgn[k] = 0; + } v->lyr[lyrno]->fractionWeightMatric_sand = psand; v->lyr[lyrno]->fractionWeightMatric_clay = pclay; v->lyr[lyrno]->impermeability = imperm; - v->lyr[lyrno]->my_transp_rgn[SW_TREES] = 0; - v->lyr[lyrno]->my_transp_rgn[SW_FORBS] = 0; - v->lyr[lyrno]->my_transp_rgn[SW_SHRUB] = 0; - v->lyr[lyrno]->my_transp_rgn[SW_GRASS] = 0; v->lyr[lyrno]->sTemp = soiltemp; if (evap_ok) { @@ -511,29 +509,15 @@ static void _read_layers(void) { } else evap_ok = swFALSE; } - if (transp_ok_forb) { - if (GT(v->lyr[lyrno]->transp_coeff[SW_FORBS], 0.0)) { - v->n_transp_lyrs[SW_FORBS]++; - } else - transp_ok_forb = swFALSE; - } - if (transp_ok_tree) { - if (GT(v->lyr[lyrno]->transp_coeff[SW_TREES], 0.0)) { - v->n_transp_lyrs[SW_TREES]++; - } else - transp_ok_tree = swFALSE; - } - if (transp_ok_shrub) { - if (GT(v->lyr[lyrno]->transp_coeff[SW_SHRUB], 0.0)) { - v->n_transp_lyrs[SW_SHRUB]++; - } else - transp_ok_shrub = swFALSE; - } - if (transp_ok_grass) { - if (GT(v->lyr[lyrno]->transp_coeff[SW_GRASS], 0.0)) { - v->n_transp_lyrs[SW_GRASS]++; - } else - transp_ok_grass = swFALSE; + + ForEachVegType(k) + { + if (transp_ok_veg[k]) { + if (GT(v->lyr[lyrno]->transp_coeff[k], 0.0)) { + v->n_transp_lyrs[k]++; + } else + transp_ok_veg[k] = swFALSE; + } } water_eqn(f_gravel, psand, pclay, lyrno); @@ -579,7 +563,7 @@ void init_site_info(void) { SW_LAYER_INFO *lyr; LyrIndex s, r, curregion; int k, wiltminflag = 0, initminflag = 0; - RealD evsum = 0., trsum_forb = 0., trsum_tree = 0., trsum_shrub = 0., trsum_grass = 0., swcmin_help1, swcmin_help2; + RealD evsum = 0., trsum_veg[NVEGTYPES] = {0.}, swcmin_help1, swcmin_help2; /* sp->deepdrain indicates an extra (dummy) layer for deep drainage * has been added, so n_layers really should be n_layers -1 @@ -594,125 +578,44 @@ void init_site_info(void) { lyr = sp->lyr[s]; /* sum ev and tr coefficients for later */ evsum += lyr->evap_coeff; - trsum_forb += lyr->transp_coeff[SW_FORBS]; - trsum_tree += lyr->transp_coeff[SW_TREES]; - trsum_shrub += lyr->transp_coeff[SW_SHRUB]; - trsum_grass += lyr->transp_coeff[SW_GRASS]; + ForEachVegType(k) + { + trsum_veg[k] += lyr->transp_coeff[k]; - /* calculate soil water content at SWPcrit for each vegetation type */ - ForEachVegType(k) { + /* calculate soil water content at SWPcrit for each vegetation type */ lyr->swcBulk_atSWPcrit[k] = SW_SWPmatric2VWCBulk(lyr->fractionVolBulk_gravel, SW_VegProd.veg[k].SWPcrit, s) * lyr->width; - } - /* Find which transpiration region the current soil layer - * is in and check validity of result. Region bounds are - * base1 but s is base0. - */ - /* for forbs */ - curregion = 0; - ForEachTranspRegion(r) - { - if (s < _TranspRgnBounds[r]) { - if (ZRO(lyr->transp_coeff[SW_FORBS])) - break; /* end of transpiring layers */ - curregion = r + 1; - break; + /* Find which transpiration region the current soil layer + * is in and check validity of result. Region bounds are + * base1 but s is base0.*/ + curregion = 0; + ForEachTranspRegion(r) + { + if (s < _TranspRgnBounds[r]) { + if (ZRO(lyr->transp_coeff[k])) + break; /* end of transpiring layers */ + curregion = r + 1; + break; + } } - } - - if (curregion || _TranspRgnBounds[curregion] == 0) { - LogError(logfp, LOGNOTE, " Layer %d : curregion %d _TranspRgnBounds %d", s + 1, curregion, _TranspRgnBounds[curregion]); - lyr->my_transp_rgn[SW_FORBS] = curregion; - sp->n_transp_lyrs[SW_FORBS] = max(sp->n_transp_lyrs[SW_FORBS], s); - - } else if (s == 0) { - LogError(logfp, LOGFATAL, "%s : Top soil layer must be included\n" - " in your forb tranpiration regions.\n", SW_F_name(eSite)); - } else if (r < sp->n_transp_rgn) { - LogError(logfp, LOGFATAL, "%s : Transpiration region %d \n" - " is deeper than the deepest layer with a\n" - " forb transpiration coefficient > 0 (%d) in '%s'.\n" - " Please fix the discrepancy and try again.\n", SW_F_name(eSite), r + 1, s, SW_F_name(eLayers)); - } - /* for trees */ - curregion = 0; - ForEachTranspRegion(r) - { - if (s < _TranspRgnBounds[r]) { - if (ZRO(lyr->transp_coeff[SW_TREES])) - break; /* end of transpiring layers */ - curregion = r + 1; - break; + if (curregion || _TranspRgnBounds[curregion] == 0) { + lyr->my_transp_rgn[k] = curregion; + sp->n_transp_lyrs[k] = max(sp->n_transp_lyrs[k], s); + + } else if (s == 0) { + LogError(logfp, LOGFATAL, "%s : Top soil layer must be included\n" + " in %s tranpiration regions.\n", SW_F_name(eSite), key2veg[k]); + } else if (r < sp->n_transp_rgn) { + LogError(logfp, LOGFATAL, "%s : Transpiration region %d \n" + " is deeper than the deepest layer with a\n" + " %s transpiration coefficient > 0 (%d) in '%s'.\n" + " Please fix the discrepancy and try again.\n", + SW_F_name(eSite), r + 1, key2veg[k], s, SW_F_name(eLayers)); } } - if (curregion || _TranspRgnBounds[curregion] == 0) { - lyr->my_transp_rgn[SW_TREES] = curregion; - sp->n_transp_lyrs[SW_TREES] = max(sp->n_transp_lyrs[SW_TREES], s); - - } else if (s == 0) { - LogError(logfp, LOGFATAL, "%s : Top soil layer must be included\n" - " in your tree tranpiration regions.\n", SW_F_name(eSite)); - } else if (r < sp->n_transp_rgn) { - LogError(logfp, LOGFATAL, "%s : Transpiration region %d \n" - " is deeper than the deepest layer with a\n" - " tree transpiration coefficient > 0 (%d) in '%s'.\n" - " Please fix the discrepancy and try again.\n", SW_F_name(eSite), r + 1, s, SW_F_name(eLayers)); - } - - /* for shrubs */ - curregion = 0; - ForEachTranspRegion(r) - { - if (s < _TranspRgnBounds[r]) { - if (ZRO(lyr->transp_coeff[SW_SHRUB])) - break; /* end of transpiring layers */ - curregion = r + 1; - break; - } - } - - if (curregion || _TranspRgnBounds[curregion] == 0) { - lyr->my_transp_rgn[SW_SHRUB] = curregion; - sp->n_transp_lyrs[SW_SHRUB] = max(sp->n_transp_lyrs[SW_SHRUB], s); - - } else if (s == 0) { - LogError(logfp, LOGFATAL, "%s : Top soil layer must be included\n" - " in your shrub tranpiration regions.\n", SW_F_name(eSite)); - } else if (r < sp->n_transp_rgn) { - LogError(logfp, LOGFATAL, "%s : Transpiration region %d \n" - " is deeper than the deepest layer with a\n" - " shrub transpiration coefficient > 0 (%d) in '%s'.\n" - " Please fix the discrepancy and try again.\n", SW_F_name(eSite), r + 1, s, SW_F_name(eLayers)); - } - /* for grasses */ - curregion = 0; - ForEachTranspRegion(r) - { - if (s < _TranspRgnBounds[r]) { - if (ZRO(lyr->transp_coeff[SW_GRASS])) - break; /* end of transpiring layers */ - curregion = r + 1; - break; - } - } - - if (curregion || _TranspRgnBounds[curregion] == 0) { - lyr->my_transp_rgn[SW_GRASS] = curregion; - sp->n_transp_lyrs[SW_GRASS] = max(sp->n_transp_lyrs[SW_GRASS], s); - - } else if (s == 0) { - LogError(logfp, LOGFATAL, "%s : Top soil layer must be included\n" - " in your grass tranpiration regions.\n", SW_F_name(eSite)); - } else if (r < sp->n_transp_rgn) { - LogError(logfp, LOGFATAL, "%s : Transpiration region %d \n" - " is deeper than the deepest layer with a\n" - " grass transpiration coefficient > 0 (%d) in '%s'.\n" - " Please fix the discrepancy and try again.\n", SW_F_name(eSite), r + 1, s, SW_F_name(eLayers)); - } - /* Compute swc wet and dry limits and init value */ if (LT(_SWCMinVal, 0.0)) { /* estimate swcBulk_min for each layer based on residual SWC from an equation in Rawls WJ, Brakensiek DL (1985) Prediction of soil water properties for hydrological modeling. In Watershed management in the Eighties (eds Jones EB, Ward TJ), pp. 293-299. American Society of Civil Engineers, New York. or based on SWC at -3 MPa if smaller (= suction at residual SWC from Fredlund DG, Xing AQ (1994) EQUATIONS FOR THE SOIL-WATER CHARACTERISTIC CURVE. Canadian Geotechnical Journal, 31, 521-532.) */ @@ -765,40 +668,22 @@ void init_site_info(void) { LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->evap_coeff); } } - if (!EQ(trsum_forb, 1.0)) { - LogError(logfp, LOGWARN, "%s : Transp coefficients for forbs were normalized, " - "tr_co_forb sum (%5.4f) != 1.0.\nNew Coefficients are:", MyFileName, trsum_forb); - ForEachForbTranspLayer(s) - { - SW_Site.lyr[s]->transp_coeff[SW_FORBS] /= trsum_forb; - LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff[SW_FORBS]); - } - } - if (!EQ(trsum_tree, 1.0)) { - LogError(logfp, LOGWARN, "%s : Transp coefficients for trees were normalized, " - "tr_co_tree sum (%5.4f) != 1.0.\nNew coefficients are:", MyFileName, trsum_tree); - ForEachTreeTranspLayer(s) - { - SW_Site.lyr[s]->transp_coeff[SW_TREES] /= trsum_tree; - LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff[SW_TREES]); - } - } - if (!EQ(trsum_shrub, 1.0)) { - LogError(logfp, LOGWARN, "%s : Transp coefficients for shrubs were normalized, " - "tr_co_shrub sum (%5.4f) != 1.0.\nNew coefficients are:", MyFileName, trsum_shrub); - ForEachShrubTranspLayer(s) - { - SW_Site.lyr[s]->transp_coeff[SW_SHRUB] /= trsum_shrub; - LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff[SW_SHRUB]); - } - } - if (!EQ(trsum_grass, 1.0)) { - LogError(logfp, LOGWARN, "%s : Transp coefficients for grasses were normalized, " - "tr_co_grass sum (%5.4f) != 1.0.\nNew coefficients are:", MyFileName, trsum_grass); - ForEachGrassTranspLayer(s) - { - SW_Site.lyr[s]->transp_coeff[SW_GRASS] /= trsum_grass; - LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff[SW_GRASS]); + + ForEachVegType(k) + { + if (!EQ(trsum_veg[k], 1.0)) { + LogError(logfp, LOGWARN, "%s : Transp coefficients for %s were normalized, " + "tr_co_forb sum (%5.4f) != 1.0.\nNew Coefficients are:", + MyFileName, key2veg[k], trsum_veg[k]); + + ForEachSoilLayer(s) + { + if (GT(SW_Site.lyr[s]->transp_coeff[k], 0.)) + { + SW_Site.lyr[s]->transp_coeff[k] /= trsum_veg[k]; + LogError(logfp, LOGNOTE, " Layer %d : %5.4f", s + 1, SW_Site.lyr[s]->transp_coeff[k]); + } + } } } diff --git a/SW_VegEstab.c b/SW_VegEstab.c index 32096ab39..0629a90c0 100644 --- a/SW_VegEstab.c +++ b/SW_VegEstab.c @@ -376,10 +376,12 @@ 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 = min(SW_Site.n_transp_lyrs[SW_TREES], - min(SW_Site.n_transp_lyrs[SW_SHRUB], min(SW_Site.n_transp_lyrs[SW_FORBS], - SW_Site.n_transp_lyrs[SW_GRASS]))); + 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->estab_lyrs > min_transp_lyrs) { LogError(logfp, LOGFATAL, "%s : Layers requested (estab_lyrs) > (# transpiration layers=%d).", MyFileName, min_transp_lyrs); From ec6c4d53f5e5c0ede6b75b82c56682f813f7a546 Mon Sep 17 00:00:00 2001 From: dschlaep Date: Tue, 23 Jan 2018 15:15:08 -0500 Subject: [PATCH 7/8] Correctly initialize new array variables - this commit exactly reproduces output as current master (plus new fix for forbs #47) --- SW_Flow.c | 10 +++++----- SW_Site.c | 7 ++++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/SW_Flow.c b/SW_Flow.c index 1cf882ebc..ccf4a041a 100644 --- a/SW_Flow.c +++ b/SW_Flow.c @@ -132,6 +132,7 @@ extern SW_SKY SW_Sky; extern unsigned int soil_temp_init; // simply keeps track of whether or not the values for the soil_temperature function have been initialized. 0 for no, 1 for yes. extern unsigned int fusion_pool_init; +extern char const *key2veg[]; /* *************************************************** */ /* Module-Level Variables */ @@ -148,7 +149,6 @@ RealD lyrSWCBulk[MAX_LAYERS], lyrDrain[MAX_LAYERS], lyrTransp[NVEGTYPES][MAX_LAYERS], lyrTranspCo[NVEGTYPES][MAX_LAYERS], lyrEvap[NVEGTYPES][MAX_LAYERS], lyrEvap_BareGround[MAX_LAYERS], lyrSWCBulk_atSWPcrit[NVEGTYPES][MAX_LAYERS], lyrHydRed[NVEGTYPES][MAX_LAYERS], - lyrHydRed[NVEGTYPES][MAX_LAYERS], lyrbDensity[MAX_LAYERS], lyrWidths[MAX_LAYERS], lyrEvapCo[MAX_LAYERS], lyrSumTrCo[MAX_TRANSP_REGIONS + 1], @@ -248,14 +248,14 @@ void SW_Water_Flow(void) { SW_SOILWAT *sw = &SW_Soilwat; RealD swpot_avg[NVEGTYPES], - transp_veg[NVEGTYPES], transp_rate[NVEGTYPES] = {1.}, - soil_evap[NVEGTYPES], soil_evap_rate[NVEGTYPES] = {1.}, soil_evap_rate_bs = 1., - surface_evap_veg_rate[NVEGTYPES] = {1.}, + transp_veg[NVEGTYPES], transp_rate[NVEGTYPES], + soil_evap[NVEGTYPES], soil_evap_rate[NVEGTYPES], soil_evap_rate_bs = 1., + surface_evap_veg_rate[NVEGTYPES], surface_evap_litter_rate = 1., surface_evap_standingWater_rate = 1., snow_evap_rate = 1., veg_h2o[NVEGTYPES], litter_h2o, litter_h2o_help, h2o_for_soil = 0., ppt_toUse, snowmelt, - snowdepth_scale_veg[NVEGTYPES] = {1.}, + snowdepth_scale_veg[NVEGTYPES], rate_help, x; int doy, k; diff --git a/SW_Site.c b/SW_Site.c index 4b4277390..a3406dd59 100644 --- a/SW_Site.c +++ b/SW_Site.c @@ -433,7 +433,7 @@ static void _read_layers(void) { SW_SITE *v = &SW_Site; FILE *f; Bool evap_ok = swTRUE, /* mitigate gaps in layers' evap coeffs */ - transp_ok_veg[NVEGTYPES] = {swTRUE}, /* same for transpiration coefficients */ + transp_ok_veg[NVEGTYPES], /* same for transpiration coefficients */ fail = swFALSE; LyrIndex lyrno; int x, k; @@ -441,6 +441,11 @@ static void _read_layers(void) { RealF dmin = 0.0, dmax, evco, trco_veg[NVEGTYPES], psand, pclay, matricd, imperm, soiltemp, fval = 0, f_gravel; + // Initialize + ForEachVegType(k) { + transp_ok_veg[k] = swTRUE; + } + /* note that Files.read() must be called prior to this. */ MyFileName = SW_F_name(eLayers); From c0448dca4fa43cfea2f0e682fc8d61050cea0bdb Mon Sep 17 00:00:00 2001 From: dschlaep Date: Tue, 23 Jan 2018 15:21:19 -0500 Subject: [PATCH 8/8] A few cleanup fixes from previous commit --- SW_Flow.c | 2 +- SW_VegProd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SW_Flow.c b/SW_Flow.c index ccf4a041a..93a80a5ac 100644 --- a/SW_Flow.c +++ b/SW_Flow.c @@ -234,7 +234,7 @@ void SW_FLW_construct(void) { litter_h2o_qum[0] = litter_h2o_qum[1] = 0.; ForEachVegType(k) { - veg_h2o_qum[k][0] = veg_h2o_qum[k][0] = 0.; + veg_h2o_qum[k][0] = veg_h2o_qum[k][1] = 0.; } } diff --git a/SW_VegProd.c b/SW_VegProd.c index a08cb013d..87c501849 100644 --- a/SW_VegProd.c +++ b/SW_VegProd.c @@ -418,7 +418,7 @@ void SW_VPD_read(void) { LogError(logfp, LOGFATAL, errstr); } ForEachVegType(k) { - v->veg[k].flagHydraulicRedistribution = help_veg[k]; + v->veg[k].flagHydraulicRedistribution = (Bool) EQ(help_veg[k], 1.); } break; case 26: