void surface_daily_F( struct world_object *world, struct basin_object *basin, struct hillslope_object *hillslope, struct zone_object *zone, struct patch_object *patch, struct command_line_object *command_line, struct tec_entry *event, struct date current_date) { /*--------------------------------------------------------------*/ /* Local function declaration */ /*--------------------------------------------------------------*/ double compute_diffuse_radiative_fluxes( int, double *, double, double, double, double, double, double); double compute_direct_radiative_fluxes( int, double *, double, double, double, double, double, double); double compute_direct_radiative_PAR_fluxes( int, double *, double, double, double, double, double, double, double, double); double compute_nonvascular_stratum_conductance( int , double , double , double , double , double ); double compute_litter_rain_stored( int, struct patch_object *); double penman_monteith( int, double, double, double, double, double, double, int); double compute_subsurface_temperature_profile( struct surface_energy_object *, struct surface_energy_default *, double, double, double *); /*--------------------------------------------------------------*/ /* Local variable definition. */ /*--------------------------------------------------------------*/ double detention_store_evaporation; double detention_store_potential_evaporation; double detention_store_potential_dry_evaporation_rate; double detention_store_potential_rainy_evaporation_rate; double albedo; double dry_evaporation; double Kstar_direct; double Kstar_diffuse; double APAR_diffuse; double APAR_direct; double potential_evaporation_rate; double potential_rainy_evaporation_rate; double rainy_evaporation; double rnet_evap, rnet_evap_pond, rnet_evap_litter, rnet_evap_soil; double rnet; double PE_rate, PE_rainy_rate; double soil_potential_evaporation; double soil_potential_dry_evaporation_rate; double soil_potential_rainy_evaporation_rate; double exfiltration; double K_used; double K_initial; double hv; /* latent heat of vaporization for water (KJ/kg) */ double water_density; /* density of water in kg/m^3 */ double fraction_direct_K; double fraction_diffuse_K; double fraction_Lstar_soil; double fraction_surface_heat_flux; struct litter_object *litter; /*--------------------------------------------------------------*/ /* Initialize litter variables. */ /*--------------------------------------------------------------*/ Kstar_diffuse = 0.0; APAR_diffuse = 0.0; Kstar_direct = 0.0; APAR_direct = 0.0; exfiltration = 0; rainy_evaporation = 0; dry_evaporation = 0; rnet = 0.0; litter = &(patch[0].litter); hv = 2.495 * 1e3; /* latent heat of vaporization for water (KJ/kg) */ water_density = 1000; /* density of water in kg/m^3 */ /*--------------------------------------------------------------*/ /* DETENTION STORE EVAPORATION: */ /* Check to see if detention store is greater than current */ /* litter holding capacity. If so, run water surface evap */ /* first. */ /* but only do this if there is actually a detention_store capacity to hold water */ /*--------------------------------------------------------------*/ if ( (patch[0].detention_store > (max(litter[0].rain_capacity - litter[0].rain_stored, 0.0))) && (patch[0].soil_defaults[0][0].detention_store_size > 0.0)) { /*** Calculate available energy at surface. Assumes Kdowns are partially ***/ /*** reflected by water surface based on water albedo. ***/ if (zone[0].metv.dayl > ZERO) { rnet_evap_pond = 1000 * ( (1-WATER_ALBEDO) * (patch[0].Kdown_direct + patch[0].Kdown_diffuse) - patch[0].Lstar_soil + patch[0].surface_heat_flux) / zone[0].metv.dayl; if (rnet_evap_pond <= ZERO) { rnet_evap_pond = 0.0; } } else rnet_evap_pond = 0.0; /*** Use Penman with rsurface=0 for open water evaporation. ***/ patch[0].ga = max((patch[0].ga * patch[0].stability_correction),0.0001); detention_store_potential_dry_evaporation_rate = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, zone[0].metv.vpd, rnet_evap_pond, 0.0, 1/(patch[0].ga), 2) ; detention_store_potential_rainy_evaporation_rate = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, 10, rnet_evap_pond, 0.0, 1/(patch[0].ga), 2) ; detention_store_potential_evaporation = detention_store_potential_dry_evaporation_rate * (zone[0].metv.dayl - zone[0].daytime_rain_duration ) + detention_store_potential_rainy_evaporation_rate * zone[0].daytime_rain_duration; // Avoid over-estimating ET from surfaces with no detention store size // (e.g. impervious surface) by gating ET by detention_store_size detention_store_evaporation = min(detention_store_potential_evaporation, min(patch[0].detention_store, patch[0].soil_defaults[0][0].detention_store_size) ); } else detention_store_evaporation = 0.0; patch[0].detention_store -= detention_store_evaporation; /*** If snowpack is over detention store, then add evaporated water to snowpack. ***/ if (patch[0].snowpack.water_equivalent_depth > ZERO) { patch[0].snowpack.water_equivalent_depth += detention_store_evaporation; detention_store_evaporation = 0.0; } patch[0].evaporation_surf += detention_store_evaporation; /*** Update patch radiation to remove any radiation used to evaporate pond. ***/ /*** Assume same proportions as original 4 energy sources. ***/ K_used = detention_store_evaporation * hv * water_density; K_initial = (1-WATER_ALBEDO) * (patch[0].Kdown_direct + patch[0].Kdown_diffuse) - patch[0].Lstar_soil + patch[0].surface_heat_flux; if ( K_used > 0 ){ if ( K_initial > 0 ){ fraction_direct_K = (1-WATER_ALBEDO) * patch[0].Kdown_direct / K_initial; fraction_diffuse_K = (1-WATER_ALBEDO) * patch[0].Kdown_diffuse / K_initial; fraction_Lstar_soil = patch[0].Lstar_soil / K_initial; fraction_surface_heat_flux = patch[0].surface_heat_flux / K_initial; } else { fraction_direct_K = 0.0; fraction_diffuse_K = 0.0; fraction_Lstar_soil = 0.0; fraction_surface_heat_flux = 0.0; } patch[0].Kdown_direct = ((1-WATER_ALBEDO) * patch[0].Kdown_direct) - (fraction_direct_K * K_used); patch[0].Kdown_diffuse = ((1-WATER_ALBEDO) * patch[0].Kdown_diffuse) - (fraction_diffuse_K * K_used); patch[0].Lstar_soil = patch[0].Lstar_soil - (fraction_Lstar_soil * K_used); patch[0].surface_heat_flux = patch[0].surface_heat_flux - (fraction_surface_heat_flux * K_used); } /*--------------------------------------------------------------*/ /* LITTER STORE EVAPORATION: */ /* Now move to litter and then bare soil evaporation if the */ /* remaining surface water can be held by the litter. */ /*--------------------------------------------------------------*/ if ( patch[0].detention_store <= (litter[0].rain_capacity - litter[0].rain_stored) ) { /*--------------------------------------------------------------*/ /* calculate surface albedo as a function of amount of */ /* litter vs soil */ /*--------------------------------------------------------------*/ if (litter->proj_pai >= 1.0) albedo = LITTER_ALBEDO; else { albedo = LITTER_ALBEDO * litter->proj_pai + patch[0].soil_defaults[0][0].albedo * (1-litter->proj_pai); } /*--------------------------------------------------------------*/ /* Intercept diffuse radiation. */ /* We assume that the zone slope == patch slope. */ /* We also assume that radiation reflected into the upper */ /* hemisphere is lost. */ /* We do not make adjustements for chaanging gap fraction over */ /* the diurnal cycle - using a suitable mean gap fraction */ /* instead. */ /* We do take into account the patch level horizon which will */ /* allow simulation of clear-cuts/clearings with low sza's */ /* Note that for zone level temperature and radiation */ /* computation we took into account only zone level horizon*/ /* since we figured that climate above the zone was well */ /* mixed. */ /*--------------------------------------------------------------*/ Kstar_diffuse = compute_diffuse_radiative_fluxes( command_line[0].verbose_flag, &(patch[0].Kdown_diffuse), patch[0].Kdown_direct, -10000.0, 0.0, 1.0, basin[0].theta_noon, albedo); APAR_diffuse = compute_diffuse_radiative_fluxes( command_line[0].verbose_flag, &(patch[0].PAR_diffuse), patch[0].PAR_direct, -10000.0, 0.0, 1.0, basin[0].theta_noon, albedo); /*--------------------------------------------------------------*/ /* Intercept direct radiation. */ /* hard to measure for each strata. We could use top */ /* of canopy albedo but this integrates the effect of the */ /* entire canopy. Furthermore, it requires in general */ /* knowledge of the canopy BRDF - which we want to avoid. */ /* Instead we assume a certain reflectance and */ /* transmittance for each strata's canopy elements. */ /* We assume that the zone slope == patch slope. */ /* We also assume that radiation reflected into the upper */ /* hemisphere is lost. */ /* We do not make adjustements for chaanging gap fraction over */ /* the diurnal cycle - using a suitable mean gap fraction */ /* instead. */ /* We do take into account the patch level horizon which will */ /* allow simulation of clear-cuts/clearings with low sza's */ /* Note that for zone level temperature and radiation */ /* computation we took into account only zone level horizon*/ /* since we figured that climate above the zone was well */ /* mixed. */ /*--------------------------------------------------------------*/ Kstar_direct = compute_direct_radiative_fluxes( command_line[0].verbose_flag, &(patch[0].Kdown_direct), -10000, 0.0, 1.0, basin[0].theta_noon, albedo, albedo); APAR_direct = compute_direct_radiative_fluxes( command_line[0].verbose_flag, &(patch[0].PAR_direct), -10000, 0.0, 1.0, basin[0].theta_noon, albedo, albedo); /*--------------------------------------------------------------*/ /* Determine non-vascular condductance to evaporation. */ /* This conductance represnets the inverse of an additional */ /* resistance to vapour flux from the stratum rian storage */ /* surface over and above aerodynamic resistances that also */ /* affect turbulent heat transfer. */ /* */ /* A linear relationship is currently assumed with the amount */ /* of relative rain stored - or with the patch unsat zone storage */ /* relative to water equiv depth top water table if roots are present */ /* . Parameters for the relationship */ /* are supplied via the stratum default file. */ /*--------------------------------------------------------------*/ litter[0].gsurf = compute_nonvascular_stratum_conductance( command_line[0].verbose_flag, litter[0].rain_stored + patch[0].detention_store, litter[0].rain_capacity, litter[0].gl_c, litter[0].gsurf_slope, litter[0].gsurf_intercept); if (patch[0].rootzone.depth > ZERO) { patch[0].gsurf = compute_nonvascular_stratum_conductance( command_line[0].verbose_flag, patch[0].rz_storage + patch[0].detention_store, patch[0].sat_deficit, patch[0].soil_defaults[0][0].gl_c, patch[0].soil_defaults[0][0].gsurf_slope, patch[0].soil_defaults[0][0].gsurf_intercept); } else { patch[0].gsurf = compute_nonvascular_stratum_conductance( command_line[0].verbose_flag, patch[0].unsat_storage + patch[0].detention_store, patch[0].sat_deficit, patch[0].soil_defaults[0][0].gl_c, patch[0].soil_defaults[0][0].gsurf_slope, patch[0].soil_defaults[0][0].gsurf_intercept); } /*--------------------------------------------------------------*/ /* COmpute evaporation and exfiltration RATES (m/s) */ /* for daylight period . */ /* The rainy rate assumes a vpd of 10Pa. */ /* Note if surface heat flux makes evap negative we */ /* have condensation. */ /*--------------------------------------------------------------*/ if(zone[0].metv.dayl > ZERO) { rnet_evap = 1000 * (Kstar_direct + Kstar_diffuse - patch[0].Lstar_soil + patch[0].surface_heat_flux) / zone[0].metv.dayl; if (rnet_evap <= ZERO) { rnet_evap_pond = 0.0; } } else rnet_evap = 0.0; rnet_evap_litter = min(litter->proj_pai,1)*rnet_evap; rnet_evap_soil = max(0.0, rnet_evap-rnet_evap_litter); if (rnet_evap < 0.0) rnet_evap = 0.0; /*--------------------------------------------------------------*/ /* Make sure ga and gsurf are non-zero. */ /*--------------------------------------------------------------*/ patch[0].ga = max((patch[0].ga * patch[0].stability_correction),0.0001); /*--------------------------------------------------------------*/ /* Estimate potential evap rates. */ /*--------------------------------------------------------------*/ potential_evaporation_rate = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, zone[0].metv.vpd, rnet_evap_litter, 1/patch[0].litter.gsurf, 1/(patch[0].ga), 2) ; potential_rainy_evaporation_rate = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, 10, rnet_evap_litter, 1/patch[0].litter.gsurf, 1/(patch[0].ga), 2) ; PE_rate = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, zone[0].metv.vpd, rnet_evap_litter, 0.0, 1/(patch[0].ga), 2) ; PE_rainy_rate = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, 10, rnet_evap_litter, 0.0, 1/(patch[0].ga), 2) ; PE_rainy_rate = max(0, PE_rainy_rate); PE_rate = max(0, PE_rate); potential_evaporation_rate = max(0,potential_evaporation_rate); potential_rainy_evaporation_rate = max(0,potential_rainy_evaporation_rate); /*--------------------------------------------------------------*/ /* Do not allow negative potential evap if it raining */ /* since condensation/dew dep is the same as rain */ /*--------------------------------------------------------------*/ if ( zone[0].rain > 0 ){ potential_evaporation_rate = max(0,potential_evaporation_rate); potential_rainy_evaporation_rate = max(0,potential_rainy_evaporation_rate); } /*--------------------------------------------------------------*/ /* Compute potential evaporation of litter. */ /* Weighted by rain and non rain periods of the daytime */ /* m/day = m/s * (sec/day) */ /* */ /* Note that Kstar is converted from Kj/m2*day to W/m2 */ /*--------------------------------------------------------------*/ patch[0].potential_evaporation = potential_evaporation_rate * (zone[0].metv.dayl - zone[0].daytime_rain_duration ) + potential_rainy_evaporation_rate * zone[0].daytime_rain_duration; patch[0].PE = PE_rate * (zone[0].metv.dayl - zone[0].daytime_rain_duration ) + PE_rainy_rate * zone[0].daytime_rain_duration; /*--------------------------------------------------------------*/ /* Update rain storage ( this also updates the patch level */ /* detention store and potential_evaporation */ /*--------------------------------------------------------------*/ litter[0].rain_stored = compute_litter_rain_stored( command_line[0].verbose_flag, patch); /*--------------------------------------------------------------*/ /* if litter is empty then we have bare soil */ /* */ /* We assume that the exfiltration rate is limited to */ /* the minimum of the potential evap rate for the */ /* soil and the max exfiltration rate. */ /* The potential evap rate is estimated using P-M with */ /* the same aero cond as the litter but with a */ /* surface cond estimated based on vapour conductance in */ /* soil column. */ /* */ /* The surface heat flux of the soil column is estimated */ /* aasuming no litter covering the surface (0 m height). */ /*--------------------------------------------------------------*/ soil_potential_rainy_evaporation_rate = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, 10.0, rnet_evap_soil, 1.0/patch[0].gsurf, 1.0/patch[0].ga, 2); soil_potential_dry_evaporation_rate = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, zone[0].metv.vpd, rnet_evap_soil, 1.0/patch[0].gsurf, 1.0/patch[0].ga, 2); soil_potential_evaporation = soil_potential_dry_evaporation_rate * (zone[0].metv.dayl - zone[0].daytime_rain_duration ) + soil_potential_rainy_evaporation_rate * zone[0].daytime_rain_duration; /*--------------------------------------------------------------*/ /* BARE SOIL EVAPORATION: */ /* base soil evapotration/ exfiltration will only occur */ /* on exposed soil layers */ /*--------------------------------------------------------------*/ exfiltration = min(soil_potential_evaporation, patch[0].potential_exfiltration); if ( patch[0].sat_deficit_z > 0 ){ patch[0].exfiltration_unsat_zone = exfiltration; patch[0].exfiltration_sat_zone = 0; } else{ patch[0].exfiltration_unsat_zone = 0; patch[0].exfiltration_sat_zone = exfiltration; } } /*--------------------------------------------------------------*/ /* if we want to solve surface temperature profile, determine */ /* moistures and depths to send to solver */ /* then call solver compute_subsurface_temperature_profile */ /* will also determine % of soil water that is frozen */ /* note that depth for layer 3 is always the soil depth so */ /* this is set only once in construct_patch */ /*--------------------------------------------------------------*/ if (command_line[0].surface_energy_flag == 1) { patch[0].surface_energy_profile[0].depth = patch[0].litter.depth; patch[0].surface_energy_profile[0].moisture = patch[0].litter.rain_stored; if (patch[0].sat_deficit > patch[0].rootzone.potential_sat) { patch[0].surface_energy_profile[1].depth = patch[0].surface_energy_profile[0].depth + patch[0].rootzone.depth; patch[0].surface_energy_profile[1].moisture = patch[0].rz_storage; patch[0].surface_energy_profile[2].depth = patch[0].surface_energy_profile[0].depth + patch[0].sat_deficit_z; patch[0].surface_energy_profile[2].moisture = patch[0].unsat_storage; patch[0].surface_energy_profile[3].moisture = patch[0].soil_defaults[0][0].soil_water_cap - patch[0].sat_deficit; } else { patch[0].surface_energy_profile[1].depth = patch[0].surface_energy_profile[0].depth + patch[0].sat_deficit_z; patch[0].surface_energy_profile[1].moisture = patch[0].rz_storage; patch[0].surface_energy_profile[2].depth = patch[0].surface_energy_profile[0].depth + patch[0].rootzone.depth; patch[0].surface_energy_profile[2].moisture = patch[0].rootzone.potential_sat - patch[0].sat_deficit; patch[0].surface_energy_profile[3].moisture = patch[0].soil_defaults[0][0].soil_water_cap - patch[0].rootzone.potential_sat; } compute_subsurface_temperature_profile( patch[0].surface_energy_profile, patch[0].surface_energy_defaults[0], zone[0].metv.tavg, rnet, &(patch[0].percent_soil_water_unfrozen)); /*--------------------------------------------------------------*/ /* map iterative temperatures back to soil and litter, for now */ /* we don't differentiate between unsat, rootzone and sat for temperature */ /*--------------------------------------------------------------*/ patch[0].litter.T = patch[0].surface_energy_profile[0].T; if (patch[0].sat_deficit > patch[0].rootzone.potential_sat) patch[0].rootzone.T = patch[0].surface_energy_profile[1].T; else patch[0].rootzone.T = (patch[0].surface_energy_profile[1].T * (patch[0].sat_deficit) + patch[0].surface_energy_profile[2].T * (patch[0].rootzone.potential_sat - patch[0].sat_deficit)) / (patch[0].rootzone.potential_sat); patch[0].Tsoil = (patch[0].surface_energy_profile[1].T * (patch[0].surface_energy_profile[1].depth - patch[0].surface_energy_profile[0].depth) + patch[0].surface_energy_profile[2].T * (patch[0].surface_energy_profile[2].depth - patch[0].surface_energy_profile[1].depth) + patch[0].surface_energy_profile[3].T * (patch[0].surface_energy_profile[3].depth - patch[0].surface_energy_profile[2].depth)) / patch[0].surface_energy_profile[3].depth; } return; }/*end surface_daily_F.c*/
void penman_canopy_wrapper(params *p, state *s, double press, double vpd, double tair, double wind, double rnet, double ca, double gpp, double *ga, double *gsv, double *transpiration, double *LE, double *omega) { /* Calculates transpiration at the canopy scale (or big leaf) using the Penman-Monteith Parameters: ---------- parms : structure parameters state : structure state variables press : float atmospheric pressure (Pa) vpd : float vapour pressure deficit of air (Pa) tair : float air temperature (deg C) wind : float wind speed (m s-1) rnet : float net radiation (J m-2 s-1) ca : float ambient CO2 concentration (umol mol-1) gpp : float gross primary productivity (umol m-2 s-1) ga : float canopy scale boundary layer conductance (mol m-2 s-1; returned) gsv : float stomatal conductance to H20 (mol m-2 s-1; returned) transpiration : float transpiration (mol H2O m-2 s-1; returned) LE : float latent heat flux (W m-2; returned) */ double gb, gv, gsc, epsilon, arg1, arg2, slope, gamma, lambda; /* stomtal conductance to CO2 */ gsc = calc_stomatal_conductance(p, s, vpd, ca, gpp); /* stomtal conductance to H2O */ *gsv = GSVGSC * gsc; *ga = canopy_boundary_layer_conduct(p, s->canht, wind, press, tair); /* Total leaf conductance to water vapour */ gv = 1.0 / (1.0 / *gsv + 1.0 / *ga); lambda = calc_latent_heat_of_vapourisation(tair); gamma = calc_pyschrometric_constant(press, lambda); slope = calc_slope_of_sat_vapour_pressure_curve(tair); penman_monteith(press, vpd, rnet, slope, lambda, gamma, ga, &gv, transpiration, LE); /* Calculate decoupling coefficient (McNaughton and Jarvis 1986) */ epsilon = slope / gamma; *omega = (1.0 + epsilon) / (1.0 + epsilon + *ga / *gsv); return; }
void penman_leaf_wrapper(met *m, params *p, state *s, double tleaf, double rnet, double gsc, double *transpiration, double *LE, double *gbc, double *gh, double *gv, double *omega) { /* Calculates transpiration by leaves using the Penman-Monteith Parameters: ---------- press : float atmospheric pressure (Pa) rnet : float net radiation (J m-2 s-1) vpd : float vapour pressure deficit of air (Pa) tair : float air temperature (deg C) transpiration : float transpiration (mol H2O m-2 s-1) (returned) LE : float latent heat flux, W m-2 (returned) */ double slope, epsilon, lambda, arg1, arg2, gradn, gbhu, gbhf, gbh, gbv, gsv, gamma, Tdiff, sensible_heat, ema, Tk; /* Radiation conductance (mol m-2 s-1) */ gradn = calc_radiation_conductance(m->tair); /* Boundary layer conductance for heat - single sided, forced convection (mol m-2 s-1) */ gbhu = calc_bdn_layer_forced_conduct(m->tair, m->press, m->wind, p->leaf_width); /* Boundary layer conductance for heat - single sided, free convection */ gbhf = calc_bdn_layer_free_conduct(m->tair, tleaf, m->press, p->leaf_width); /* Total boundary layer conductance for heat */ gbh = gbhu + gbhf; /* Total conductance for heat - two-sided */ *gh = 2.0 * (gbh + gradn); gbv = GBVGBH * gbh; gsv = GSVGSC * gsc; /* Total leaf conductance to water vapour */ *gv = (gbv * gsv) / (gbv + gsv); *gbc = gbh / GBHGBC; lambda = calc_latent_heat_of_vapourisation(m->tair); gamma = calc_pyschrometric_constant(m->press, lambda); slope = calc_slope_of_sat_vapour_pressure_curve(m->tair); penman_monteith(m->press, m->vpd, rnet, slope, lambda, gamma, gh, gv, transpiration, LE); /* Calculate decoupling coefficient (McNaughton and Jarvis 1986) */ epsilon = slope / gamma; *omega = (1.0 + epsilon) / (1.0 + epsilon + gbv / gsv); return; }
void canopy_stratum_daily_F( struct world_object *world, struct basin_object *basin, struct hillslope_object *hillslope, struct zone_object *zone, struct patch_object *patch, struct layer_object *layer, struct canopy_strata_object *stratum, struct command_line_object *command_line, struct tec_entry *event, struct date current_date) { /*--------------------------------------------------------------*/ /* Local function declaration */ /*--------------------------------------------------------------*/ long julday(struct date calendar_date); double compute_diffuse_radiative_fluxes( int, double *, double, double, double, double, double, double); double compute_diffuse_radiative_PAR_fluxes( int , double *, double , double , double , double , double , double ); double compute_direct_radiative_fluxes( int , double *, double , double , double , double , double , double ); int compute_maint_resp( double, double, struct cstate_struct *, struct nstate_struct *, struct epconst_struct *, struct metvar_struct *, struct cdayflux_struct *); double compute_snow_stored( int , double , double , double *, double *, struct canopy_strata_object *); double compute_rain_stored( int , double *, struct canopy_strata_object *); double compute_ra_overstory( int , double , double *, double , double , double , double *); double compute_ra_understory( int , double , double *, double , double , double *); double compute_ra_surface( int , double , double *, double , double , double *); double compute_vascular_stratum_conductance( int , int , double , double , double , double , double , double , double , double , double , double , double , double , double , double , double , double , double , double , double , double , double , double, int, struct canopy_strata_object *, struct patch_object *); double compute_nonvascular_stratum_conductance( int , double , double , double , double , double ); double compute_surface_heat_flux( int , double , double , double , double , double , double , double , double , double ); double penman_monteith( int , double , double , double , double , double , double , int ); int compute_farq_psn( struct psnin_struct * , struct psnout_struct * , int); double compute_potential_N_uptake_Dickenson( struct epconst_struct, struct epvar_struct *, struct cstate_struct *cs, struct nstate_struct *ns, struct cdayflux_struct *); double compute_potential_N_uptake_Waring( struct epconst_struct, struct epvar_struct *, struct cstate_struct *cs, struct nstate_struct *ns, struct cdayflux_struct *); double compute_potential_N_uptake( struct epconst_struct, struct epvar_struct *, struct cstate_struct *cs, struct nstate_struct *ns, struct cdayflux_struct *); void update_mortality( struct epconst_struct, struct cstate_struct *, struct cdayflux_struct *, struct cdayflux_patch_struct *, struct nstate_struct *, struct ndayflux_struct *, struct ndayflux_patch_struct *, struct litter_c_object *, struct litter_n_object *, int, struct mortality_struct); /*--------------------------------------------------------------*/ /* Local variable definition. */ /*--------------------------------------------------------------*/ double tmid; double assim_sunlit; double assim_shade; double dC13_sunlit, dC13_shade; double APAR_direct_sunlit; double dry_evaporation; double ga; double Kdown_direct; double Kdown_diffuse; double PAR_diffuse; double PAR_direct; double total_incoming_PAR; double perc_sunlit; double potential_evaporation_rate; double potential_rainy_evaporation_rate; double rainy_evaporation; double rain_throughfall; double rnet_evap; double rnet_trans, rnet_trans_sunlit, rnet_trans_shade; double snow_throughfall; double transpiration; double transpiration_rate; double transpiration_rate_sunlit; double transpiration_rate_shade; double potential_transpiration; double potential_transpiration_rate; double potential_transpiration_rate_sunlit; double potential_transpiration_rate_shade; double wind; double leafcloss_perc; double m_APAR_sunlit; double m_tavg_sunlit; double m_LWP_sunlit; double m_CO2_sunlit; double m_tmin_sunlit; double m_vpd_sunlit; double m_APAR_shade; double m_tavg_shade; double m_LWP_shade; double m_CO2_shade; double m_tmin_shade; double m_vpd_shade; struct psnin_struct psnin; struct psnout_struct psnout; struct mortality_struct mort; if ( command_line[0].verbose_flag > 1 ) printf("\n%8d -444.1 ",julday(current_date)-2449000); if ( command_line[0].verbose_flag > 1 ) printf("%8.2f %8.2f %8.2f %8.2f ", patch[0].Kdown_direct, patch[0].Kdown_diffuse, patch[0].PAR_direct/1000, patch[0].PAR_diffuse/1000); /*--------------------------------------------------------------*/ /* Initialize stratum variables. */ /*--------------------------------------------------------------*/ stratum[0].Kstar_diffuse = 0.0; stratum[0].APAR_diffuse = 0.0; stratum[0].Kstar_direct = 0.0; stratum[0].APAR_direct = 0.0; stratum[0].potential_evaporation = 0.0; m_APAR_sunlit=0.0; m_tavg_sunlit=0.0; m_LWP_sunlit=0.0; m_CO2_sunlit=0.0; m_tmin_sunlit=0.0; m_vpd_sunlit=0.0; m_APAR_shade=0.0; m_tavg_shade=0.0; m_LWP_shade=0.0; m_CO2_shade=0.0; m_tmin_shade=0.0; m_vpd_shade=0.0; stratum[0].mult_conductance.vpd = 0.0; stratum[0].mult_conductance.tmin = 0.0; stratum[0].mult_conductance.tavg = 0.0; stratum[0].mult_conductance.CO2 = 0.0; stratum[0].mult_conductance.LWP = 0.0; stratum[0].mult_conductance.APAR = 0.0; /*--------------------------------------------------------------*/ /* Initialize temporary variables for transmitted fluxes. */ /*--------------------------------------------------------------*/ Kdown_diffuse = patch[0].Kdown_diffuse ; PAR_diffuse = patch[0].PAR_diffuse; Kdown_direct = patch[0].Kdown_direct; PAR_direct = patch[0].PAR_direct; rain_throughfall = patch[0].rain_throughfall; snow_throughfall = patch[0].snow_throughfall; ga = patch[0].ga; wind = patch[0].wind; transpiration = 0.0; potential_transpiration = 0.0; rainy_evaporation = 0; dry_evaporation = 0; total_incoming_PAR = PAR_diffuse + PAR_direct; /*--------------------------------------------------------------*/ /* perform plant grazing losses */ /* (if grow flag is on) */ /*--------------------------------------------------------------*/ if ((stratum[0].cs.leafc > ZERO) && (patch[0].grazing_Closs > ZERO) && command_line[0].grow_flag == 1 ) { leafcloss_perc = patch[0].grazing_Closs * (stratum[0].ns.leafn/stratum[0].cs.leafc) / patch[0].grazing_mean_nc / stratum[0].cs.leafc; mort.mort_leafc = leafcloss_perc; mort.mort_cpool = 0.0; mort.mort_deadleafc = 0.0; mort.mort_livestemc = 0.0; mort.mort_deadstemc = 0.0; mort.mort_livecrootc = 0.0; mort.mort_deadcrootc = 0.0; mort.mort_frootc = 0.0; update_mortality(stratum[0].defaults[0][0].epc, &(stratum[0].cs), &(stratum[0].cdf), &(patch[0].cdf), &(stratum[0].ns), &(stratum[0].ndf), &(patch[0].ndf), &(patch[0].litter_cs), &(patch[0].litter_ns), 2, mort); printf("\n completed %lf from %lf", leafcloss_perc, stratum[0].cs.leafc); } /* NEW CHECK TO SEE IF STRATUM IS VEGETATED, OTHERWISE SKIP */ /* TO END TO UPDATE RADIATION BY COVER FRACTION */ if (stratum[0].defaults[0][0].epc.veg_type != NON_VEG) { /*--------------------------------------------------------------*/ /* Intercept diffuse radiation. */ /* We assume that the zone slope == patch slope. */ /* We also assume that radiation reflected into the upper */ /* hemisphere is lost. */ /* We do not make adjustements for chaanging gap fraction over */ /* the diurnal cycle - using a suitable mean gap fraction */ /* instead. */ /* We do take into account the patch level horizon which will */ /* allow simulation of clear-cuts/clearings with low sza's */ /* Note that for zone level temperature and radiation */ /* computation we took into account only zone level horizon*/ /* since we figured that climate above the zone was well */ /* mixed. */ /*--------------------------------------------------------------*/ if ( command_line[0].verbose_flag > 2 ){ printf("\n%4d %4d %4d -444.4 \n", current_date.day, current_date.month, current_date.year); printf("\n %f %f %f %f %f %f %f", Kdown_diffuse, Kdown_direct, -1*stratum[0].defaults[0][0].epc.ext_coef, stratum[0].gap_fraction, stratum[0].epv.proj_pai, basin[0].theta_noon, stratum[0].defaults[0][0].K_reflectance); printf("\n%4d %4d %4d -444.4b \n", current_date.day, current_date.month, current_date.year); } stratum[0].Kstar_diffuse = compute_diffuse_radiative_fluxes( command_line[0].verbose_flag, &(Kdown_diffuse), Kdown_direct, -1*stratum[0].defaults[0][0].epc.ext_coef, stratum[0].gap_fraction, stratum[0].epv.proj_pai, basin[0].theta_noon, stratum[0].defaults[0][0].K_reflectance); if ( command_line[0].verbose_flag > 2 ) printf("\n%8d -444.5 ",julday(current_date)-2449000); stratum[0].APAR_diffuse = compute_diffuse_radiative_PAR_fluxes( command_line[0].verbose_flag, &(PAR_diffuse), PAR_direct, -1*stratum[0].defaults[0][0].epc.ext_coef, stratum[0].gap_fraction, stratum[0].epv.proj_lai, basin[0].theta_noon, stratum[0].defaults[0][0].PAR_reflectance); /*--------------------------------------------------------------*/ /* Intercept direct radiation. */ /* hard to measure for each strata. We could use top */ /* of canopy albedo but this integrates the effect of the */ /* entire canopy. Furthermore, it requires in general */ /* knowledge of the canopy BRDF - which we want to avoid. */ /* Instead we assume a certain reflectance and */ /* transmittance for each strata's canopy elements. */ /* We assume that the zone slope == patch slope. */ /* We also assume that radiation reflected into the upper */ /* hemisphere is lost. */ /* We do not make adjustements for chaanging gap fraction over */ /* the diurnal cycle - using a suitable mean gap fraction */ /* instead. */ /* We do take into account the patch level horizon which will */ /* allow simulation of clear-cuts/clearings with low sza's */ /* Note that for zone level temperature and radiation */ /* computation we took into account only zone level horizon*/ /* since we figured that climate above the zone was well */ /* mixed. */ /*--------------------------------------------------------------*/ if ( command_line[0].verbose_flag > 2 ) printf("\n%8d -444.2 ",julday(current_date)-2449000); stratum[0].Kstar_direct = compute_direct_radiative_fluxes( command_line[0].verbose_flag, &(Kdown_direct), -1*stratum[0].defaults[0][0].epc.ext_coef, stratum[0].gap_fraction, stratum[0].epv.proj_pai, basin[0].theta_noon, stratum[0].defaults[0][0].K_reflectance, stratum[0].defaults[0][0].K_reflectance); if ( command_line[0].verbose_flag >2 ) printf("\n%d %d %d -444.3 ", current_date.year, current_date.month, current_date.day); stratum[0].APAR_direct = compute_direct_radiative_fluxes( command_line[0].verbose_flag, &(PAR_direct), -1*stratum[0].defaults[0][0].epc.ext_coef, stratum[0].gap_fraction, stratum[0].epv.proj_pai, basin[0].theta_noon, stratum[0].defaults[0][0].PAR_reflectance, stratum[0].defaults[0][0].PAR_reflectance); /*--------------------------------------------------------------*/ /* record fraction of PAR absorption */ /* and seasonal low water content */ /* (for use in dynamic version to limit allocation) */ /*--------------------------------------------------------------*/ stratum[0].epv.min_vwc = min((patch[0].unsat_storage / patch[0].sat_deficit), stratum[0].epv.min_vwc); if ( command_line[0].verbose_flag >2 ) printf("\n fparabs %f min_vwc %f",stratum[0].epv.max_fparabs, stratum[0].epv.min_vwc); if ( command_line[0].verbose_flag > 1 ) printf("\n%8d -444.6 ",julday(current_date)-2449000); /*--------------------------------------------------------------*/ /* Compute conductance aerodynamic. */ /*--------------------------------------------------------------*/ if ( patch[0].snowpack.height <= stratum[0].epv.height ){ /*--------------------------------------------------------------*/ /* Compute by brute force if usrat_overu given. */ /*--------------------------------------------------------------*/ if ( stratum[0].defaults[0][0].ustar_overu == -999.9 ){ /*--------------------------------------------------------------*/ /* Highest layer in patch. */ /*--------------------------------------------------------------*/ if ( stratum[0].epv.height == patch[0].layers[0].height ){ stratum[0].ga = 1.0 / compute_ra_overstory( command_line[0].verbose_flag, stratum[0].defaults[0][0].wind_attenuation_coeff, &(wind), zone[0].base_stations[0][0].screen_height, stratum[0].epv.height, layer[0].base, &(ga)); } /*--------------------------------------------------------------*/ /* Layer is not the highest and is >0.1highest ht. */ /*--------------------------------------------------------------*/ else if (stratum[0].epv.height > (patch[0].layers[0].height * 0.1) ){ stratum[0].ga = 1.0 / compute_ra_understory( command_line[0].verbose_flag, stratum[0].defaults[0][0].wind_attenuation_coeff, &(wind), stratum[0].epv.height, layer[0].base, &(ga)); } /*--------------------------------------------------------------*/ /* Layer is <0.1highest ht. in height. */ /*--------------------------------------------------------------*/ else{ stratum[0].ga = 1.0 / compute_ra_surface( command_line[0].verbose_flag, stratum[0].defaults[0][0].wind_attenuation_coeff, &(wind), stratum[0].epv.height, layer[0].base, &(ga)); } } else{ stratum[0].ga = pow(zone[0].wind * stratum[0].defaults[0][0].ustar_overu,2.0); ga = stratum[0].ga; } } else{ stratum[0].ga = 0.0; } /*--------------------------------------------------------------*/ /* Factor in stability correction. */ /*--------------------------------------------------------------*/ stratum[0].ga = stratum[0].ga * patch[0].stability_correction ; if ( command_line[0].verbose_flag > 1 ) printf("%8.6f ",stratum[0].ga); if ( command_line[0].verbose_flag > 1 ) printf("\n%8d -444.8 ",julday(current_date)-2449000); /*--------------------------------------------------------------*/ /* Determine non-vascular condductance to evaporation. */ /* This conductance represnets the inverse of an additional */ /* resistance to vapour flux from the stratum rian storage */ /* surface over and above aerodynamic resistances that also */ /* affect turbulent heat transfer. */ /* */ /* A linear relationship is currently assumed with the amount */ /* of relative rain stored - or with the patch unsat zone storage */ /* relative to water equiv depth top water table if roots are present */ /* . Parameters for the relationship */ /* are supplied via the stratum default file. */ /*--------------------------------------------------------------*/ if ( stratum[0].epv.all_pai > 0 ){ stratum[0].gsurf = compute_nonvascular_stratum_conductance( command_line[0].verbose_flag, stratum[0].rain_stored+rain_throughfall, stratum[0].epv.all_pai * stratum[0].defaults[0][0].specific_rain_capacity, stratum[0].defaults[0][0].epc.gl_c, stratum[0].defaults[0][0].gsurf_slope, stratum[0].defaults[0][0].gsurf_intercept); } else{ stratum[0].gsurf = compute_nonvascular_stratum_conductance( command_line[0].verbose_flag, patch[0].unsat_storage+rain_throughfall, patch[0].sat_deficit, stratum[0].defaults[0][0].epc.gl_c, stratum[0].defaults[0][0].gsurf_slope, stratum[0].defaults[0][0].gsurf_intercept); } if ( command_line[0].verbose_flag > 1 ) printf("%8.6f ",stratum[0].gs); if ( command_line[0].verbose_flag > 1 ) printf("\n%4d %4d %4d -444.9 \n ", current_date.day, current_date.month, current_date.year); if ( command_line[0].verbose_flag > 1 ) printf("%8.4f %8.4f %8.4f %8.4f \n ", stratum[0].Kstar_direct,stratum[0].Kstar_diffuse, stratum[0].APAR_direct,stratum[0].APAR_diffuse); if ( command_line[0].verbose_flag > 1 ) { printf("\n%4d %4d %4d -444.9.1 \n ",current_date.day, current_date.month, current_date.year); printf(" %f\n", stratum[0].snow_stored); } /*--------------------------------------------------------------*/ /* Update snow storage ( this also updates the patch level */ /* snow throughfall and the stratum level Kstar ) */ /* Snow on the canopy is first sublimated before any ET */ /* can take place. This may seem like we are hobbling */ /* the energy budget since the sublimation reduces the */ /* energy used for stomatal conductance etc. however we */ /* suggest that when it snows it is likely ET is small. */ /*--------------------------------------------------------------*/ stratum[0].snow_stored = compute_snow_stored( command_line[0].verbose_flag, zone[0].metv.tday, 1000.0, &(snow_throughfall), &(rain_throughfall), stratum); if ( command_line[0].verbose_flag > 1 ) printf("\n%8.4f %f ",stratum[0].snow_stored, stratum[0].sublimation); if ( command_line[0].verbose_flag > 1 ) printf("\n%8d -444.10 ",julday(current_date)-2449000); if ( command_line[0].verbose_flag > 1 ) printf("%8.4f %8.4f %8.4f %8.4f ",stratum[0].Kstar_direct, stratum[0].Kstar_diffuse,stratum[0].APAR_direct, stratum[0].APAR_diffuse); if (stratum[0].epv.proj_lai > ZERO) perc_sunlit = (stratum[0].epv.proj_lai_sunlit)/(stratum[0].epv.proj_lai); else perc_sunlit = 1.0; if (stratum[0].epv.proj_lai_shade > ZERO && zone[0].metv.dayl > ZERO) stratum[0].ppfd_shade = (stratum[0].APAR_diffuse * (1-perc_sunlit)) / zone[0].metv.dayl /stratum[0].epv.proj_lai_shade; else stratum[0].ppfd_shade = 0.0; if (stratum[0].epv.proj_lai_sunlit > ZERO && zone[0].metv.dayl > ZERO) stratum[0].ppfd_sunlit = (stratum[0].APAR_direct + stratum[0].APAR_diffuse * perc_sunlit) / zone[0].metv.dayl /stratum[0].epv.proj_lai_sunlit; else stratum[0].ppfd_sunlit = 0.0; /*--------------------------------------------------------------*/ /* Compute stratum conductance m/s */ /* */ /* */ /* Note that the APAR supplied reduces to the rate of */ /* APAR (kJ/sec) absorbed during the daytime. We do this */ /* since: */ /* */ /* gs is only meaningful in the day */ /* gs responds to the instantaneous rather than daily */ /* averaged APAR. */ /* */ /* Also note that we will not void a shorwtwave energy */ /* budget since stratum conductance is used to scale */ /* potnetial_evaporation; which we make sure is limited */ /* by the available energy. */ /* */ /* Note: PAR values are converted fro umol photon/m2*day to*/ /* umol photon/m2*sec */ /*--------------------------------------------------------------*/ /* if ( command_line[0].verbose_flag > 1 ) printf("%f ",stratum[0].APAR_direct/zone[0].metv.dayl+ stratum[0].APAR_diffuse/zone[0].metv.dayl); /*--------------------------------------------------------------*/ /* */ /* if there is still snow sitting on the canopy gs should be zero */ /* */ /*--------------------------------------------------------------*/ if (stratum[0].snow_stored < ZERO) { stratum[0].gs_sunlit = compute_vascular_stratum_conductance( command_line[0].verbose_flag, stratum[0].defaults[0][0].epc.psi_curve, stratum[0].defaults[0][0].epc.ppfd_coef, stratum[0].defaults[0][0].epc.gl_c, stratum[0].defaults[0][0].lai_stomatal_fraction, stratum[0].defaults[0][0].epc.psi_open, stratum[0].defaults[0][0].epc.psi_close, stratum[0].defaults[0][0].epc.psi_threshold, stratum[0].defaults[0][0].epc.psi_slp, stratum[0].defaults[0][0].epc.psi_intercpt, stratum[0].defaults[0][0].epc.gl_smax, stratum[0].defaults[0][0].epc.topt, stratum[0].defaults[0][0].epc.tcoef, stratum[0].defaults[0][0].epc.tmax, stratum[0].defaults[0][0].epc.vpd_open, stratum[0].defaults[0][0].epc.vpd_close, stratum[0].ppfd_sunlit, stratum[0].epv.proj_lai_sunlit, stratum[0].epv.psi, zone[0].metv.tsoil, zone[0].metv.tday, zone[0].metv.vpd, zone[0].CO2, stratum[0].defaults[0][0].epc.coef_CO2, stratum[0].ID, stratum, patch); m_APAR_sunlit = stratum[0].mult_conductance.APAR; m_tavg_sunlit = stratum[0].mult_conductance.tavg; m_LWP_sunlit = stratum[0].mult_conductance.LWP; m_CO2_sunlit = stratum[0].mult_conductance.CO2; m_tmin_sunlit = stratum[0].mult_conductance.tmin; m_vpd_sunlit = stratum[0].mult_conductance.vpd; stratum[0].potential_gs_sunlit = compute_vascular_stratum_conductance( command_line[0].verbose_flag, stratum[0].defaults[0][0].epc.psi_curve, stratum[0].defaults[0][0].epc.ppfd_coef, stratum[0].defaults[0][0].epc.gl_c, stratum[0].defaults[0][0].lai_stomatal_fraction, stratum[0].defaults[0][0].epc.psi_open, stratum[0].defaults[0][0].epc.psi_close, stratum[0].defaults[0][0].epc.psi_threshold, stratum[0].defaults[0][0].epc.psi_slp, stratum[0].defaults[0][0].epc.psi_intercpt, stratum[0].defaults[0][0].epc.gl_smax, stratum[0].defaults[0][0].epc.topt, stratum[0].defaults[0][0].epc.tcoef, stratum[0].defaults[0][0].epc.tmax, stratum[0].defaults[0][0].epc.vpd_open, stratum[0].defaults[0][0].epc.vpd_close, stratum[0].ppfd_sunlit, stratum[0].epv.proj_lai_sunlit, 9999.0, zone[0].metv.tsoil, stratum[0].defaults[0][0].epc.topt, stratum[0].defaults[0][0].epc.vpd_open-1.0, zone[0].CO2, stratum[0].defaults[0][0].epc.coef_CO2, stratum[0].ID, stratum, patch); stratum[0].gs_shade = compute_vascular_stratum_conductance( command_line[0].verbose_flag, stratum[0].defaults[0][0].epc.psi_curve, stratum[0].defaults[0][0].epc.ppfd_coef, stratum[0].defaults[0][0].epc.gl_c, stratum[0].defaults[0][0].lai_stomatal_fraction, stratum[0].defaults[0][0].epc.psi_open, stratum[0].defaults[0][0].epc.psi_close, stratum[0].defaults[0][0].epc.psi_threshold, stratum[0].defaults[0][0].epc.psi_slp, stratum[0].defaults[0][0].epc.psi_intercpt, stratum[0].defaults[0][0].epc.gl_smax, stratum[0].defaults[0][0].epc.topt, stratum[0].defaults[0][0].epc.tcoef, stratum[0].defaults[0][0].epc.tmax, stratum[0].defaults[0][0].epc.vpd_open, stratum[0].defaults[0][0].epc.vpd_close, stratum[0].ppfd_shade, stratum[0].epv.proj_lai_shade, stratum[0].epv.psi, zone[0].metv.tsoil, zone[0].metv.tday, zone[0].metv.vpd, zone[0].CO2, stratum[0].defaults[0][0].epc.coef_CO2, stratum[0].ID, stratum, patch); m_APAR_shade = stratum[0].mult_conductance.APAR; m_tavg_shade = stratum[0].mult_conductance.tavg; m_LWP_shade = stratum[0].mult_conductance.LWP; m_CO2_shade = stratum[0].mult_conductance.CO2; m_tmin_shade = stratum[0].mult_conductance.tmin; m_vpd_shade = stratum[0].mult_conductance.vpd; stratum[0].potential_gs_shade = compute_vascular_stratum_conductance( command_line[0].verbose_flag, stratum[0].defaults[0][0].epc.psi_curve, stratum[0].defaults[0][0].epc.ppfd_coef, stratum[0].defaults[0][0].epc.gl_c, stratum[0].defaults[0][0].lai_stomatal_fraction, stratum[0].defaults[0][0].epc.psi_open, stratum[0].defaults[0][0].epc.psi_close, stratum[0].defaults[0][0].epc.psi_threshold, stratum[0].defaults[0][0].epc.psi_slp, stratum[0].defaults[0][0].epc.psi_intercpt, stratum[0].defaults[0][0].epc.gl_smax, stratum[0].defaults[0][0].epc.topt, stratum[0].defaults[0][0].epc.tcoef, stratum[0].defaults[0][0].epc.tmax, stratum[0].defaults[0][0].epc.vpd_open, stratum[0].defaults[0][0].epc.vpd_close, stratum[0].ppfd_shade, stratum[0].epv.proj_lai_shade, 9999.0, zone[0].metv.tsoil, stratum[0].defaults[0][0].epc.topt, stratum[0].defaults[0][0].epc.vpd_open-1.0, zone[0].CO2, stratum[0].defaults[0][0].epc.coef_CO2, stratum[0].ID, stratum, patch); /* keep track of conductance multipliers actually used an indication of stress */ stratum[0].mult_conductance.APAR = (m_APAR_shade*stratum[0].epv.proj_lai_shade + m_APAR_sunlit * stratum[0].epv.proj_lai_sunlit) / (stratum[0].epv.proj_lai_shade+stratum[0].epv.proj_lai_sunlit); stratum[0].mult_conductance.tavg = (m_tavg_shade*stratum[0].epv.proj_lai_shade + m_tavg_sunlit * stratum[0].epv.proj_lai_sunlit) / (stratum[0].epv.proj_lai_shade+stratum[0].epv.proj_lai_sunlit); stratum[0].mult_conductance.LWP = (m_LWP_shade*stratum[0].epv.proj_lai_shade + m_LWP_sunlit * stratum[0].epv.proj_lai_sunlit) / (stratum[0].epv.proj_lai_shade+stratum[0].epv.proj_lai_sunlit); stratum[0].mult_conductance.CO2 = (m_CO2_shade*stratum[0].epv.proj_lai_shade + m_CO2_sunlit * stratum[0].epv.proj_lai_sunlit) / (stratum[0].epv.proj_lai_shade+stratum[0].epv.proj_lai_sunlit); stratum[0].mult_conductance.tmin = (m_tmin_shade*stratum[0].epv.proj_lai_shade + m_tmin_sunlit * stratum[0].epv.proj_lai_sunlit) / (stratum[0].epv.proj_lai_shade+stratum[0].epv.proj_lai_sunlit); stratum[0].mult_conductance.vpd = (m_vpd_shade*stratum[0].epv.proj_lai_shade + m_vpd_sunlit * stratum[0].epv.proj_lai_sunlit) / (stratum[0].epv.proj_lai_shade+stratum[0].epv.proj_lai_sunlit); } else { stratum[0].gs_sunlit = 0.0; stratum[0].gs_shade = 0.0; stratum[0].potential_gs_sunlit = 0.0; stratum[0].potential_gs_shade = 0.0; } stratum[0].gs = stratum[0].gs_sunlit + stratum[0].gs_shade; /*--------------------------------------------------------------*/ /* Determine heat flux between stratum and surface. */ /* representative of the surface temperature. Obviously */ /* for strata NOT at the surface one would have 0 heat cap */ /* kJ/day */ /* We had the current input of rain as well. */ /*--------------------------------------------------------------*/ if (stratum[0].epv.height == 0) { stratum[0].surface_heat_flux = -1 * compute_surface_heat_flux( command_line[0].verbose_flag, stratum[0].snow_stored, stratum[0].rain_stored+patch[0].rain_throughfall, stratum[0].epv.all_pai * stratum[0].defaults[0][0].specific_rain_capacity, zone[0].metv.tmin, zone[0].metv.tnightmax, zone[0].metv.tsoil, patch[0].soil_defaults[0][0].deltaz, stratum[0].defaults[0][0].min_heat_capacity, stratum[0].defaults[0][0].max_heat_capacity); } if ( command_line[0].verbose_flag > 2 ) printf("\n%8d -444.11 ",julday(current_date)-2449000); /*--------------------------------------------------------------*/ /* COmpute evaporation and transpiration RATES (m/s) */ /* for daylight period . */ /* The rainy rate assumes a vpd of 10Pa. */ /* Note if surface heat flux makes evap negative we */ /* have condensation. */ /*--------------------------------------------------------------*/ if (zone[0].metv.dayl > ZERO) rnet_evap = 1000 * (stratum[0].Kstar_direct + stratum[0].Kstar_diffuse + stratum[0].Lstar + stratum[0].surface_heat_flux) / zone[0].metv.dayl; else rnet_evap = 0.0; /*--------------------------------------------------------------*/ /* Estimate potential evap rates. */ /*--------------------------------------------------------------*/ if ((stratum[0].gsurf > ZERO) && (stratum[0].ga > ZERO) && (rnet_evap > ZERO)) { potential_evaporation_rate = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, zone[0].metv.vpd, rnet_evap, 1/stratum[0].gsurf, 1/stratum[0].ga, 2) ; potential_rainy_evaporation_rate = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, 0, rnet_evap, 1/stratum[0].gsurf, 1/stratum[0].ga, 2) ; } else { potential_evaporation_rate = 0.0; potential_rainy_evaporation_rate = 0.0; } potential_evaporation_rate = max(0,potential_evaporation_rate); potential_rainy_evaporation_rate = max(0,potential_rainy_evaporation_rate); /*--------------------------------------------------------------*/ /* Do not allow negative potential evap if it raining */ /* since condensation/dew dep is the same as rain */ /*--------------------------------------------------------------*/ if ( zone[0].rain > 0 ){ potential_evaporation_rate = max(0,potential_evaporation_rate); potential_rainy_evaporation_rate= max(0,potential_rainy_evaporation_rate); } if ( command_line[0].verbose_flag > 2 ) printf("\n%8d -444.12 ",julday(current_date)-2449000); /*--------------------------------------------------------------*/ /* Transpiration rate. */ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /* Reduce rnet for transpiration by ratio of lai to pai */ /*--------------------------------------------------------------*/ if (zone[0].metv.dayl > ZERO) { rnet_trans_sunlit = 1000 * ((stratum[0].Kstar_direct + (perc_sunlit)*stratum[0].Kstar_diffuse) * ( stratum[0].epv.proj_lai / stratum[0].epv.proj_pai ) + perc_sunlit* (stratum[0].Lstar + stratum[0].surface_heat_flux) ) / zone[0].metv.dayl; rnet_trans_shade = 1000 * (( (1.0-perc_sunlit)*stratum[0].Kstar_diffuse) * ( stratum[0].epv.proj_lai / stratum[0].epv.proj_pai ) + (1.0-perc_sunlit) * (stratum[0].Lstar + stratum[0].surface_heat_flux) ) / zone[0].metv.dayl; } else { rnet_trans_sunlit = 0.0; rnet_trans_shade = 0.0; } rnet_trans_shade = max(rnet_trans_shade, 0.0); rnet_trans_sunlit = max(rnet_trans_sunlit, 0.0); if ( (rnet_trans_sunlit > ZERO ) && (stratum[0].defaults[0][0].lai_stomatal_fraction > ZERO ) && (stratum[0].gs_sunlit > ZERO) && ( stratum[0].ga > ZERO) ){ transpiration_rate_sunlit = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, zone[0].metv.vpd, rnet_trans_sunlit, 1/stratum[0].gs_sunlit, 1/stratum[0].ga, 2) ; potential_transpiration_rate_sunlit = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, zone[0].metv.vpd, rnet_trans_sunlit, 1/stratum[0].potential_gs_sunlit, 1/stratum[0].ga, 2) ; } else{ transpiration_rate_sunlit = 0.0; potential_transpiration_rate_sunlit = 0.0; } if ( (rnet_trans_shade > ZERO ) && (stratum[0].defaults[0][0].lai_stomatal_fraction > ZERO ) && (stratum[0].gs_shade > ZERO) && ( stratum[0].ga > ZERO) ){ transpiration_rate_shade = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, zone[0].metv.vpd, rnet_trans_shade, 1/stratum[0].gs_shade, 1/stratum[0].ga, 2) ; potential_transpiration_rate_shade = penman_monteith( command_line[0].verbose_flag, zone[0].metv.tday, zone[0].metv.pa, zone[0].metv.vpd, rnet_trans_shade, 1/stratum[0].potential_gs_shade, 1/stratum[0].ga, 2) ; } else{ transpiration_rate_shade = 0.0; potential_transpiration_rate_shade = 0.0; } transpiration_rate = transpiration_rate_sunlit + transpiration_rate_shade; potential_transpiration_rate = potential_transpiration_rate_sunlit + potential_transpiration_rate_shade; /*--------------------------------------------------------------*/ /* Compute potential evaporation of stratum. */ /* Weighted by rain and non rain periods of the daytime */ /* m/day = m/s * (sec/day) */ /* */ /* Note that Kstar is converted from Kj/m2*day to W/m2 */ /*--------------------------------------------------------------*/ stratum[0].potential_evaporation = potential_evaporation_rate * (zone[0].metv.dayl - zone[0].daytime_rain_duration ) + potential_rainy_evaporation_rate * zone[0].daytime_rain_duration; /*--------------------------------------------------------------*/ /* If this stratum is on the surface and has a non-zero */ /* rootin gdepth we assume it first takes water from soil. */ /* In this case we move some of the potential */ /* evaporation to porential transpiration. The criteria */ /* used to determine how much is based on the */ /* estimated cap rise during the day. */ /*--------------------------------------------------------------*/ if ( (stratum[0].epv.height == 0 ) && ( stratum[0].rootzone.depth > 0 ) && (stratum[0].epv.proj_lai > ZERO) ){ if ( stratum[0].potential_evaporation > ZERO ){ transpiration = min(stratum[0].potential_evaporation, patch[0].cap_rise); potential_transpiration = min(stratum[0].potential_evaporation, patch[0].cap_rise); stratum[0].potential_evaporation -= transpiration; } else{ transpiration = 0.0; potential_transpiration = 0.0; } } if ( command_line[0].verbose_flag > 1 ) printf("\n%8d -444.13 ",julday(current_date)-2449000); if ( command_line[0].verbose_flag > 1 ) printf("%8.6f %8.6f %8.6f ",potential_evaporation_rate*1000, transpiration_rate*1000, stratum[0].potential_evaporation*1000 ); if ( command_line[0].verbose_flag > 2 ) printf("\n%4d %4d %4d -444.14 ",current_date.day, current_date.month, current_date.year); /*--------------------------------------------------------------*/ /* Update rain storage ( this also updates the patch level */ /* rain_throughfall and stratum[0].potential_evaporation */ /*--------------------------------------------------------------*/ stratum[0].rain_stored = compute_rain_stored( command_line[0].verbose_flag, &(rain_throughfall), stratum); if ( command_line[0].verbose_flag > 1 ) printf("\n%8d -444.15 ",julday(current_date)-2449000); if ( command_line[0].verbose_flag > 1 ) printf("%8.4f %8.4f %8.4f %8.4f ",stratum[0].Kstar_direct, stratum[0].Kstar_diffuse,stratum[0].APAR_direct, stratum[0].APAR_diffuse); /*--------------------------------------------------------------*/ /* Separate the evaporation into rainy and dry */ /* assuming rainy happens as much as it can. */ /*--------------------------------------------------------------*/ if ( stratum[0].evaporation > ZERO ){ rainy_evaporation = min(zone[0].daytime_rain_duration * potential_rainy_evaporation_rate, stratum[0].evaporation ); dry_evaporation = stratum[0].evaporation - rainy_evaporation; } else{ rainy_evaporation = 0; dry_evaporation = stratum[0].evaporation ; } /*--------------------------------------------------------------*/ /* Compute Canopy transpiration. m/day */ /* */ /* We assume the potential_evaporation has been */ /* reduced by the amount need to evaporate the storage */ /* and incident precipitation. */ /* */ /* we assume that part of the day */ /* which had a dry canopy which was transpiring. */ /* */ /* The advantage of doing it via potentia evaporation */ /* include: */ /* */ /* 1. the potential evaporation is computed once using */ /* the vpd and Rnet and ra of the WHOLE day. We do not */ /* reduce Rnet after we evaporate water stored but */ /* reduce the potential evap. directly. */ /* */ /* 2. more importantly, the leaf conductance is computed */ /* on the full value average daytime Rnet and the */ /* Rnet used in transpiration is the daily averaged value */ /* which properly reflects the balance in demand between */ /* Rnet and vpd. */ /* */ /* we assume no transpiration happens during evaporation. */ /* or rain hours. */ /* */ /* All of this is only done for vascular strata. */ /*--------------------------------------------------------------*/ if (stratum[0].defaults[0][0].lai_stomatal_fraction > ZERO){ if ( stratum[0].potential_evaporation > ZERO ){ transpiration = transpiration_rate * (zone[0].metv.dayl - zone[0].daytime_rain_duration - dry_evaporation / potential_evaporation_rate); potential_transpiration = potential_transpiration_rate * (zone[0].metv.dayl - zone[0].daytime_rain_duration - dry_evaporation / potential_evaporation_rate); } else{ transpiration = 0.0; potential_transpiration = 0.0; } } stratum[0].PET = potential_transpiration; /*--------------------------------------------------------------*/ /* Separate the transpiration into unsat and sat zone */ /* transpiration demands based on the rooting depth and */ /* the patch depth to water table. */ /* */ /* This transpiration may actually be reduced if there is */ /* not enough water i nthe respective zone. But that */ /* event should indicate that maybe the leaf water */ /* potential control on gs or the soil moisture control on */ /* gsurf (for bryophytes) is not well calibrated. */ /*--------------------------------------------------------------*/ if ( stratum[0].rootzone.depth > ZERO ){ stratum[0].transpiration_sat_zone = transpiration * max(0, 1 - ( patch[0].sat_deficit_z / stratum[0].rootzone.depth ) ); stratum[0].transpiration_unsat_zone = transpiration - stratum[0].transpiration_sat_zone; } else{ if ( patch[0].sat_deficit_z > ZERO ){ stratum[0].transpiration_unsat_zone = transpiration; stratum[0].transpiration_sat_zone = 0; } else{ stratum[0].transpiration_unsat_zone = 0; stratum[0].transpiration_sat_zone = transpiration; } } if ( command_line[0].verbose_flag > 1 ) printf("\n%8d -444.16 ",julday(current_date)-2449000); if ( command_line[0].verbose_flag > 1 ) printf("%8.6f ", transpiration); /*--------------------------------------------------------------*/ /* Do respiration and photosynthesis only for plants */ /*--------------------------------------------------------------*/ if (stratum[0].defaults[0][0].lai_stomatal_fraction > ZERO) { /*--------------------------------------------------------------*/ /* perform maintenance respiration */ /* only fluxes are computed here; stores are updated later */ /* in canopy_stratum_daily_growth */ /*--------------------------------------------------------------*/ if (compute_maint_resp( stratum[0].defaults[0][0].mrc.q10, stratum[0].defaults[0][0].mrc.per_N, &(stratum[0].cs), &(stratum[0].ns), &(stratum[0].defaults[0][0].epc), &(zone[0].metv), &(stratum[0].cdf) )){ fprintf(stderr,"Error in compute_maint_resp() from bbgc.c... Exiting\n"); exit(EXIT_FAILURE); } if ((stratum[0].epv.all_lai > ZERO) && (stratum[0].snow_stored < ZERO)) { /*--------------------------------------------------------------*/ /* convert maintenance resp from kg/m2*day to umol/m2*s */ /* only fluxes are computed here; stores are updated later */ /* in canopy_stratum_daily_growth */ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /* Set up input array for stratum assimilation */ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /* this all needs to be repeated for sunlit and for shaded */ /* and for potential and actual psn` */ /* note that at present potential only takes into account */ /* water (i.e not nitrogen) limitations */ /*--------------------------------------------------------------*/ /* potential sunlit psn */ /*--------------------------------------------------------------*/ if (stratum[0].defaults[0][0].epc.veg_type == C4GRASS) psnin.c3 = 0; else psnin.c3 = 1; if (zone[0].metv.dayl > ZERO) psnin.Rd = stratum[0].cdf.leaf_day_mr / (stratum[0].epv.proj_lai * zone[0].metv.dayl*12.011e-9); else psnin.Rd = 0.0; psnin.pa = zone[0].metv.pa; psnin.co2 = zone[0].CO2; psnin.flnr = stratum[0].defaults[0][0].epc.flnr; psnin.t = zone[0].metv.tday; psnin.irad = stratum[0].ppfd_sunlit; if ((stratum[0].cs.leafc > ZERO) && (stratum[0].epv.proj_sla_sunlit > ZERO)) psnin.lnc = stratum[0].ns.leafn / (stratum[0].cs.leafc * 1.0) / stratum[0].epv.proj_sla_sunlit; else psnin.lnc = 0.0; /*--------------------------------------------------------------*/ /* note multiply by 1000; accounted for in compute_farq_psn by a /1000 */ /* this is done for numerical precision */ /*--------------------------------------------------------------*/ psnin.g = max(stratum[0].defaults[0][0].epc.gl_smax , stratum[0].defaults[0][0].epc.gl_c ) * stratum[0].defaults[0][0].lai_stomatal_fraction * 1000 / 1.6; if ((psnin.lnc > 0.0) && (psnin.irad > 0.0)) compute_farq_psn(&psnin, &psnout, 1); else psnout.A = 0.0; assim_sunlit = psnout.A; /*--------------------------------------------------------------*/ /* potential shade psn */ /*--------------------------------------------------------------*/ if (zone[0].metv.dayl > ZERO) psnin.Rd = stratum[0].cdf.leaf_day_mr / (stratum[0].epv.proj_lai * zone[0].metv.dayl*12.011e-9); else psnin.Rd = 0.0; psnin.irad = stratum[0].ppfd_shade; if ((stratum[0].cs.leafc > ZERO) && (stratum[0].epv.proj_sla_shade > ZERO)) psnin.lnc = stratum[0].ns.leafn / (stratum[0].cs.leafc * 1.0) / stratum[0].epv.proj_sla_shade ; else psnin.lnc = 0.0; if ((psnin.lnc > 0.0) && (psnin.irad > 0.0)) compute_farq_psn(&psnin, &psnout, 1); else psnout.A = 0.0; assim_shade = psnout.A; /*--------------------------------------------------------------*/ /* total potential psn */ /* We add the daytime leaf mr to the assim since it has */ /* been subtracted in both the farq and accounted for in */ /* total mr. */ /*--------------------------------------------------------------*/ stratum[0].cdf.potential_psn_to_cpool = (assim_sunlit*stratum[0].epv.proj_lai_sunlit + assim_shade * stratum[0].epv.proj_lai_shade) *zone[0].metv.dayl*12.011e-9 + stratum[0].cdf.leaf_day_mr; /*--------------------------------------------------------------*/ /* actual sunlit psn */ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /* convert water vapour to co2 conductance. */ /*--------------------------------------------------------------*/ if (zone[0].metv.dayl > ZERO) psnin.Rd = stratum[0].cdf.leaf_day_mr / (stratum[0].epv.proj_lai * zone[0].metv.dayl*12.011e-9); else psnin.Rd = 0.0; /*--------------------------------------------------------------*/ /* note multiply by 1000; accounted for in compute_farq_psn by a /1000 */ /* this is done for numerical precision */ /*--------------------------------------------------------------*/ if (stratum[0].epv.proj_lai_sunlit > ZERO) psnin.g = stratum[0].gs_sunlit * 1000 / 1.6 / stratum[0].epv.proj_lai_sunlit; else psnin.g = 0.0; psnin.irad = stratum[0].ppfd_sunlit; if ((stratum[0].cs.leafc > ZERO) && (stratum[0].epv.proj_lai_sunlit > ZERO)) psnin.lnc = stratum[0].ns.leafn / (stratum[0].cs.leafc * 1.0) / stratum[0].epv.proj_sla_sunlit; else psnin.lnc = 0.0; if ((psnin.lnc > 0.0) && (psnin.irad > 0.0)) { if ( compute_farq_psn(&psnin, &psnout, 1)){ fprintf(stderr, "FATAL ERROR: in canopy_stratum_daily_F error in farquhar"); exit(EXIT_FAILURE); } } else psnout.A = 0.0; assim_sunlit = psnout.A; dC13_sunlit = psnout.dC13; /*--------------------------------------------------------------*/ /* actual shade psn */ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /* convert water vapour to co2 conductance. */ /*--------------------------------------------------------------*/ if (zone[0].metv.dayl > ZERO) psnin.Rd = stratum[0].cdf.leaf_day_mr / (stratum[0].epv.proj_lai * zone[0].metv.dayl*12.011e-9); else psnin.Rd = 0.0; /*--------------------------------------------------------------*/ /* note multiply by 1000; accounted for in compute_farq_psn by a /1000 */ /* this is done for numerical precision */ /*--------------------------------------------------------------*/ if (stratum[0].epv.proj_lai_shade > ZERO) psnin.g = stratum[0].gs_shade *1000 / 1.6 / stratum[0].epv.proj_lai_shade; else psnin.g = 0.0; psnin.irad = stratum[0].ppfd_shade; if ((stratum[0].cs.leafc > ZERO) && (stratum[0].epv.proj_lai_shade > ZERO)) psnin.lnc = stratum[0].ns.leafn / (stratum[0].cs.leafc * 1.0) / stratum[0].epv.proj_sla_shade; else psnin.lnc = 0.0; if ((psnin.lnc > 0.0) && (psnin.irad > 0.0)) { if ( compute_farq_psn(&psnin, &psnout, 1)){ fprintf(stderr, "FATAL ERROR: in canopy_stratum_daily_F error in farquhar"); exit(EXIT_FAILURE); } } else psnout.A = 0.0; assim_shade = psnout.A; dC13_shade = psnout.dC13; /*--------------------------------------------------------------*/ /* total actual psn */ /*--------------------------------------------------------------*/ stratum[0].cdf.psn_to_cpool = (assim_sunlit*stratum[0].epv.proj_lai_sunlit + assim_shade * stratum[0].epv.proj_lai_shade) *zone[0].metv.dayl*12.011e-9 + stratum[0].cdf.leaf_day_mr; if ((assim_sunlit + assim_shade) > ZERO) stratum[0].dC13 = (assim_sunlit * dC13_sunlit + assim_shade * dC13_shade)/(assim_sunlit+assim_shade); else stratum[0].dC13 = 0.0; /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ } /* end if LAI > O ** snow stored < 0*/ } /* end if stomatal_fraction > 0 */ else { stratum[0].cdf.psn_to_cpool = 0.0; stratum[0].cdf.potential_psn_to_cpool = 0.0; } /*--------------------------------------------------------------*/ /* perform growth related computations (if grow flag is on */ /*--------------------------------------------------------------*/ if ((command_line[0].grow_flag > 0) && (stratum[0].defaults[0][0].epc.veg_type != NON_VEG)) { /*--------------------------------------------------------------*/ /* compute N uptake from the soil */ /*--------------------------------------------------------------*/ switch(stratum[0].defaults[0][0].epc.allocation_flag) { case CONSTANT: /* constant allocation */ stratum[0].ndf.potential_N_uptake = compute_potential_N_uptake( stratum[0].defaults[0][0].epc, &(stratum[0].epv), &(stratum[0].cs), &(stratum[0].ns), &(stratum[0].cdf)); break; case DICKENSON: stratum[0].ndf.potential_N_uptake =compute_potential_N_uptake_Dickenson( stratum[0].defaults[0][0].epc, &(stratum[0].epv), &(stratum[0].cs), &(stratum[0].ns), &(stratum[0].cdf)); break; case WARING: stratum[0].ndf.potential_N_uptake =compute_potential_N_uptake_Waring( stratum[0].defaults[0][0].epc, &(stratum[0].epv), &(stratum[0].cs), &(stratum[0].ns), &(stratum[0].cdf)); break; } /* end switch */ } } /*--------------------------------------------------------------*/ /* Increment the transmitted fluxes from this patch layer */ /* by weighting the fluxes in this stratum by its cover */ /* fraction - we have check cover fractions sum to 1 in */ /* a layer when constructing the patch. */ /*--------------------------------------------------------------*/ patch[0].Kdown_direct_final += Kdown_direct * stratum[0].cover_fraction; patch[0].PAR_direct_final += PAR_direct * stratum[0].cover_fraction; patch[0].Kdown_diffuse_final += Kdown_diffuse * stratum[0].cover_fraction; patch[0].PAR_diffuse_final += PAR_diffuse * stratum[0].cover_fraction; patch[0].rain_throughfall_final += rain_throughfall * stratum[0].cover_fraction; patch[0].snow_throughfall_final += snow_throughfall * stratum[0].cover_fraction; patch[0].ga_final += ga * stratum[0].cover_fraction; patch[0].wind_final += wind * stratum[0].cover_fraction; /*--------------------------------------------------------------*/ /* update accumlator variables */ /*--------------------------------------------------------------*/ if((command_line[0].output_flags.monthly == 1)&&(command_line[0].c != NULL)){ stratum[0].acc_month.psn += stratum[0].cdf.psn_to_cpool - stratum[0].cdf.total_mr; stratum[0].acc_month.lwp += stratum[0].epv.psi; stratum[0].acc_month.length += 1; } if ((command_line[0].output_flags.yearly == 1) && (command_line[0].c != NULL)){ stratum[0].acc_year.psn += stratum[0].cdf.psn_to_cpool - stratum[0].cdf.total_mr; stratum[0].acc_year.lwp += stratum[0].epv.psi; if (stratum[0].acc_year.minNSC = -999) stratum[0].acc_year.minNSC = stratum[0].cs.cpool; else stratum[0].acc_year.minNSC = min(stratum[0].cs.cpool, stratum[0].acc_year.minNSC); stratum[0].acc_year.length += 1; } return; } /*end canopy_stratum_daily_F.c*/