void calculate_water_balance(control *c, fluxes *f, met *m, params *p, state *s, int daylen, double trans_leaf, double omega_leaf, double rnet_leaf) { /* Calculate the water balance (including all water fluxes). Parameters: ---------- control : structure control structure fluxes : structure fluxes structure met : structure meteorological drivers structure params : structure parameters structure day : int project day. (Dummy argument, only passed for daily model) daylen : double length of day in hours. (Dummy argument, only passed for daily model) trans_leaf : double leaf transpiration (Dummy argument, only passed for sub-daily model) omega_leaf : double decoupling coefficient (Dummy argument, only passed for sub-daily model) rnet_leaf : double total canopy rnet (Dummy argument, only passed for sub-daily model) */ double soil_evap, et, interception, runoff, conv, transpiration, net_rad, SEC_2_DAY, DAY_2_SEC, transpiration_am, transpiration_pm, gs_am, gs_pm, LE_am, LE_pm, ga_am, ga_pm, net_rad_am, net_rad_pm, trans_am, omega_am, gs_mol_m2_hfday_am, ga_mol_m2_hfday_am, gpp_am, gpp_pm, trans_pm, omega_pm, gs_mol_m2_hfday_pm, ga_mol_m2_hfday_pm, throughfall, canopy_evap; SEC_2_DAY = 60.0 * 60.0 * daylen; DAY_2_SEC = 1.0 / SEC_2_DAY; if (c->sub_daily) { /* calculate potential canopy evap rate, this may be reduced later depending on canopy water storage */ canopy_evap = calc_canopy_evaporation(m, p, s, rnet_leaf); /* mol m-2 s-1 to mm/day */ conv = MOLE_WATER_2_G_WATER * G_TO_KG * SEC_2_HLFHR; canopy_evap *= conv; calc_interception(c, m, p, f, s, &throughfall, &interception, &canopy_evap); } else { /* don't need to work out the canopy evap */ calc_interception(c, m, p, f, s, &throughfall, &interception, &canopy_evap); } net_rad = calc_net_radiation(p, m->sw_rad, m->tair); soil_evap = calc_soil_evaporation(m, p, s, net_rad); if (c->sub_daily) { soil_evap *= MOLE_WATER_2_G_WATER * G_TO_KG * SEC_2_HLFHR; } else { net_rad_am = calc_net_radiation(p, m->sw_rad_am, m->tair_am); net_rad_pm = calc_net_radiation(p, m->sw_rad_pm, m->tair_pm); soil_evap *= MOLE_WATER_2_G_WATER * G_TO_KG * (60.0 * 60.0 * daylen); } if (c->sub_daily) { /* mol m-2 s-1 to mm/30 min */ transpiration = trans_leaf * MOLE_WATER_2_G_WATER * G_TO_KG * \ SEC_2_HLFHR; } else { /* gC m-2 day-1 -> umol m-2 s-1 */ conv = GRAMS_C_TO_MOL_C * MOL_TO_UMOL * DAY_2_SEC; gpp_am = f->gpp_am * conv; gpp_pm = f->gpp_pm * conv; penman_canopy_wrapper(p, s, m->press, m->vpd_am, m->tair_am, m->wind_am, net_rad_am, m->Ca, gpp_am, &ga_am, &gs_am, &transpiration_am, &LE_am, &omega_am); penman_canopy_wrapper(p, s, m->press, m->vpd_pm, m->tair_pm, m->wind_pm, net_rad_pm, m->Ca, gpp_pm, &ga_pm, &gs_pm, &transpiration_pm, &LE_pm, &omega_pm); /* mol m-2 s-1 to mm/day */ conv = MOLE_WATER_2_G_WATER * G_TO_KG * SEC_2_DAY; transpiration = (transpiration_am + transpiration_pm) * conv; f->omega = (omega_am + omega_pm) / 2.0; /* output in mol H20 m-2 s-1 */ f->gs_mol_m2_sec = gs_am + gs_pm; f->ga_mol_m2_sec = ga_am + ga_pm; } /* ** NB. et, transpiration & soil evap may all be adjusted in ** update_water_storage if we don't have sufficient water */ et = transpiration + soil_evap + canopy_evap; update_water_storage(c, f, p, s, throughfall, interception, canopy_evap, &transpiration, &soil_evap, &et, &runoff); if (c->sub_daily) { sum_hourly_water_fluxes(f, soil_evap, transpiration, et, interception, throughfall, canopy_evap, runoff, omega_leaf); } else { update_daily_water_struct(f, soil_evap, transpiration, et, interception, throughfall, canopy_evap, runoff); } return; }
void calculate_water_balance_sub_daily(control *c, fluxes *f, met *m, nrutil *nr, params *p, state *s, int daylen, double trans, double omega_leaf, double rnet_leaf) { /* Calculate the water balance (including all water fluxes). - we are using all the hydraulics instead Parameters: ---------- control : structure control structure fluxes : structure fluxes structure met : structure meteorological drivers structure params : structure parameters structure day : int project day. (Dummy argument, only passed for daily model) daylen : double length of day in hours. (Dummy argument, only passed for daily model) trans : double transpiration (Dummy argument, only passed for sub-daily model) omega_leaf : double decoupling coefficient (Dummy argument, only passed for sub-daily model) rnet_leaf : double total canopy rnet (Dummy argument, only passed for sub-daily model) */ int i; double soil_evap, et, interception, runoff, conv, transpiration, net_rad; double SEC_2_DAY, DAY_2_SEC, transpiration_am, transpiration_pm, gs_am; double canopy_evap, surface_water; // Water drained through the bottom soil layer double water_lost = 0.0; if (c->water_balance == HYDRAULICS) { zero_water_movement(f, p); // calculate potential canopy evap rate, this may be reduced later // depending on canopy water storage canopy_evap = calc_canopy_evaporation(m, p, s, rnet_leaf); /* mol m-2 s-1 to mm d-1 */ conv = MOLE_WATER_2_G_WATER * G_TO_KG * SEC_2_HLFHR; canopy_evap *= conv; /* We could now replace this interception bit with the Rutter scheme? */ calc_interception(c, m, p, f, s, &surface_water, &interception, &canopy_evap); net_rad = calc_net_radiation(p, m->sw_rad, m->tair); soil_evap = calc_soil_evaporation(m, p, s, net_rad); soil_evap *= MOLE_WATER_2_G_WATER * G_TO_KG * SEC_2_HLFHR; /* mol m-2 s-1 to mm/30 min */ transpiration = trans * MOLE_WATER_2_G_WATER * G_TO_KG * \ SEC_2_HLFHR; et = transpiration + soil_evap + canopy_evap; // // The loop needs to be outside the func as we need to be able to // calculate the soil conductance per layer and call this via // the integration func when we update the soil water balance // for (i = 0; i < p->n_layers; i++) { f->soil_conduct[i] = calc_soil_conductivity(s->water_frac[i], p->cond1[i], p->cond2[i], p->cond3[i]); } calc_soil_water_potential(f, p, s); calc_soil_root_resistance(f, p, s); // If we have leaves we are transpiring if (s->lai > 0.0) { calc_water_uptake_per_layer(f, p, s); } // Calculates the thickness of the top dry layer and determines water // lost in upper layers due to evaporation calc_wetting_layers(f, p, s, soil_evap, surface_water); extract_water_from_layers(f, s, soil_evap, transpiration); // // determines water movement between soil layers due drainage // down the profile // for (i = 0; i < p->n_layers; i++) { calc_soil_balance(f, nr, p, s, i, &water_lost); } // // how much surface water infiltrantes the first soil layer in the // current time step? Water which does not infiltrate in a single step // is considered runoff // runoff = calc_infiltration(f, p, s, surface_water); runoff += water_lost * M_TO_MM; // Don't see point of calculating these again // Find SWP & soil resistance without updating waterfrac yet calc_soil_water_potential(f, p, s); calc_soil_root_resistance(f, p, s); update_soil_water_storage(f, p, s, &soil_evap, &transpiration); et = transpiration + soil_evap + canopy_evap; } else { // Simple soil water bucket appoximation // calculate potential canopy evap rate, this may be reduced later // depending on canopy water storage canopy_evap = calc_canopy_evaporation(m, p, s, rnet_leaf); /* mol m-2 s-1 to mm/day */ conv = MOLE_WATER_2_G_WATER * G_TO_KG * SEC_2_HLFHR; canopy_evap *= conv; calc_interception(c, m, p, f, s, &surface_water, &interception, &canopy_evap); net_rad = calc_net_radiation(p, m->sw_rad, m->tair); soil_evap = calc_soil_evaporation(m, p, s, net_rad); soil_evap *= MOLE_WATER_2_G_WATER * G_TO_KG * SEC_2_HLFHR; /* mol m-2 s-1 to mm/30 min */ transpiration = trans * MOLE_WATER_2_G_WATER * G_TO_KG * \ SEC_2_HLFHR; /* ** NB. et, transpiration & soil evap may all be adjusted in ** update_water_storage if we don't have sufficient water */ et = transpiration + soil_evap + canopy_evap; update_water_storage(c, f, p, s, surface_water, interception, canopy_evap, &transpiration, &soil_evap, &et, &runoff); } sum_hourly_water_fluxes(f, soil_evap, transpiration, et, interception, surface_water, canopy_evap, runoff, omega_leaf, m->rain); }