void patch_hourly( 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 Declarations. */ /*--------------------------------------------------------------*/ void canopy_stratum_hourly ( struct world_object *, struct basin_object *, struct hillslope_object *, struct zone_object *, struct patch_object *, struct canopy_strata_object *, struct command_line_object *, struct tec_entry *, struct date); double compute_infiltration( int, double, double, double, double, double, double, double, double, double, double); /*--------------------------------------------------------------*/ /* Local Variable Declarations. */ /*--------------------------------------------------------------*/ int stratum; int layer; double net_inflow, duration, infiltration; /*--------------------------------------------------------------*/ /* process any hourly rainfall */ /*--------------------------------------------------------------*/ if ( zone[0].hourly_rain_flag == 1) patch[0].hourly[0].rain_throughfall = zone[0].hourly[0].rain; else patch[0].hourly[0].rain_throughfall = 0.0; /*--------------------------------------------------------------*/ /* Cycle through the canopy strata */ /* above the snowpack */ /*--------------------------------------------------------------*/ for ( layer=0 ; layer<patch[0].num_layers; layer++ ){ if ( (patch[0].layers[layer].height > patch[0].snowpack.height) ){ patch[0].rain_throughfall_final = 0.0; for (stratum=0 ;stratum<patch[0].layers[layer].count; stratum++ ){ canopy_stratum_hourly( world, basin, hillslope, zone, patch, patch[0].canopy_strata[stratum], command_line, event, current_date ); } /*--------------------------------------------------------------*/ /* process any hourly throughfallthat falls on a snowpack */ /*--------------------------------------------------------------*/ patch[0].hourly[0].rain_throughfall = patch[0].rain_throughfall_final; } } if (patch[0].snowpack.water_equivalent_depth > 0.0) { patch[0].snowpack.water_equivalent_depth += patch[0].hourly[0].rain_throughfall; patch[0].hourly[0].rain_throughfall = 0.0; } /*--------------------------------------------------------------*/ /* Cycle through the canopy strata */ /* below the snowpack */ /*--------------------------------------------------------------*/ for ( layer=0 ; layer<patch[0].num_layers; layer++ ){ patch[0].rain_throughfall_final = 0.0; if ( (patch[0].layers[layer].height <= patch[0].snowpack.height) ){ for ( stratum=0;stratum<patch[0].layers[layer].count; stratum++ ){ canopy_stratum_hourly( world, basin, hillslope, zone, patch, patch[0].canopy_strata[stratum], command_line, event, current_date ); } } patch[0].hourly[0].rain_throughfall = patch[0].rain_throughfall_final; } /*--------------------------------------------------------------*/ /* include any detention storage as throughfall */ /*--------------------------------------------------------------*/ if (zone[0].hourly_rain_flag == 1) { /*--------------------------------------------------------------*/ /* Above ground Hydrologic Processes */ /* compute infiltration into the soil */ /* from snowmelt or rain_throughfall */ /* for now assume that all water infilatrates */ /*--------------------------------------------------------------*/ net_inflow = patch[0].hourly[0].rain_throughfall; if (net_inflow > 0.0) { /*--------------------------------------------------------------*/ /* - if rain duration is zero, then input is from snow */ /* melt assume full daytime duration */ /*--------------------------------------------------------------*/ if (zone[0].hourly[0].rain_duration <= ZERO) duration = 60*60/(86400); else duration = zone[0].hourly[0].rain_duration/(86400); infiltration = compute_infiltration( command_line[0].verbose_flag, patch[0].sat_deficit_z, patch[0].rootzone.S, patch[0].Ksat_vertical, patch[0].soil_defaults[0][0].Ksat_0_v, patch[0].soil_defaults[0][0].mz_v, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, net_inflow, duration, patch[0].soil_defaults[0][0].theta_psi_curve); printf("hourly patch called \n"); } else infiltration = 0.0; if (infiltration < 0.0) printf("\nInfiltration %lf < 0 for %d on %d", infiltration, patch[0].ID, current_date.day); /*--------------------------------------------------------------*/ /* determine fate of hold infiltration excess in detention store */ /* infiltration excess will removed during routing portion */ /*--------------------------------------------------------------*/ patch[0].detention_store = (net_inflow - infiltration); if ( infiltration > patch[0].sat_deficit - patch[0].unsat_storage - patch[0].rz_storage){ /*--------------------------------------------------------------*/ /* Yes the unsat zone will be filled so we may */ /* as well treat the unsat_storage and infiltration*/ /* as water added to the water table. */ /*--------------------------------------------------------------*/ patch[0].sat_deficit -= (infiltration + patch[0].unsat_storage + patch[0].rz_storage); /*--------------------------------------------------------------*/ /* There is no unsat_storage left. */ /*--------------------------------------------------------------*/ patch[0].unsat_storage = 0; patch[0].rz_storage = 0; patch[0].field_capacity = 0; patch[0].rootzone.field_capacity =0; /*--------------------------------------------------------------*/ /* Reverse the cap rise as it likely did not happen*/ /*--------------------------------------------------------------*/ patch[0].potential_cap_rise += patch[0].cap_rise; patch[0].cap_rise = 0; } else if ((patch[0].sat_deficit_z > patch[0].rootzone.depth) && (infiltration > patch[0].rootzone.potential_sat - patch[0].rz_storage)) { /*----------------------------------------------------------------------*/ /* Just add the infiltration remains to the unsat_storage */ /*----------------------------------------------------------------------*/ patch[0].unsat_storage += infiltration - (patch[0].rootzone.potential_sat - patch[0].rz_storage); patch[0].rz_storage = patch[0].rootzone.potential_sat; } else if ((patch[0].sat_deficit_z > patch[0].rootzone.depth) && (infiltration <= patch[0].rootzone.potential_sat - patch[0].rz_storage)) { /*--------------------------------------------------------------*/ /* Just add the infiltration to the rz_storage */ /*--------------------------------------------------------------*/ patch[0].rz_storage += infiltration; } else if ((patch[0].sat_deficit_z <= patch[0].rootzone.depth) && (infiltration <= patch[0].sat_deficit - patch[0].rz_storage)) { patch[0].rz_storage += patch[0].unsat_storage; /* transfer left water in unsat storage to rootzone layer */ patch[0].unsat_storage = 0; patch[0].rz_storage += infiltration; patch[0].field_capacity = 0; } } /* end if rain throughfall */ /*--------------------------------------------------------------*/ /* Destroy the patch hourly object. */ /*--------------------------------------------------------------*/ return; } /*end patch_hourly.c*/
void compute_subsurface_routing_hourly( struct command_line_object *command_line, struct basin_object *basin, int n_timesteps, struct date current_date) { /*--------------------------------------------------------------*/ /* Local function definition. */ /*--------------------------------------------------------------*/ void update_drainage_stream(struct patch_object *, struct command_line_object *, double, int); void update_drainage_road(struct patch_object *, struct command_line_object *, double, int); void update_drainage_land(struct patch_object *, struct command_line_object *, double, int); double compute_infiltration(int, double, double, double, double, double, double, double, double, double, double); double compute_z_final(int, double, double, double, double, double); double compute_N_leached(int, double, double, double, double, double, double, double, double, double, double, double, double,double *); double compute_layer_field_capacity(int, int, double, double, double, double, double, double, double, double, double); double compute_unsat_zone_drainage(int, int, double, double, double, double, double, double); /*--------------------------------------------------------------*/ /* Local variable definition. */ /*--------------------------------------------------------------*/ int i, d; int j, k; int grow_flag, verbose_flag; double time_int, tmp; double theta, m, Ksat, Nout; double NO3_out, NH4_out, DON_out, DOC_out; double return_flow, excess; double water_balance, infiltration; double innundation_depth; double basin_outflow; double basin_rz_storage; double basin_unsat_storage; double basin_sat_deficit; double basin_return_flow; double basin_detention_store; double basin_area; double preday_basin_unsat_storage; double preday_basin_rz_storage; double preday_basin_sat_deficit; double preday_sat_deficit; double preday_basin_return_flow; double preday_basin_detention_store; double add_field_capacity, rz_drainage, unsat_drainage; double streamflow, Qout, Qin_total, Qstr_total; struct patch_object *patch; struct hillslope_object *hillslope; struct patch_object *neigh; struct litter_object *litter; d=0; /*--------------------------------------------------------------*/ /* initializations */ /*--------------------------------------------------------------*/ grow_flag = command_line[0].grow_flag; verbose_flag = command_line[0].verbose_flag; time_int = 1.0 / n_timesteps; if (current_date.hour==1) { basin_outflow = 0.0; basin_area = 0.0; basin_unsat_storage = 0.0; basin_rz_storage = 0.0; basin_sat_deficit = 0.0; basin_return_flow = 0.0; basin_detention_store = 0.0; preday_basin_rz_storage = 0.0; preday_basin_unsat_storage = 0.0; preday_basin_sat_deficit = 0.0; preday_basin_return_flow = 0.0; preday_basin_detention_store = 0.0; basin[0].basin_outflow = 0.0; basin[0].basin_area = 0.0; basin[0].basin_unsat_storage = 0.0; basin[0].basin_rz_storage = 0.0; basin[0].basin_sat_deficit = 0.0; basin[0].basin_return_flow = 0.0; basin[0].basin_detention_store = 0.0; basin[0].preday_basin_rz_storage = 0.0; basin[0].preday_basin_unsat_storage = 0.0; basin[0].preday_basin_sat_deficit = 0.0; basin[0].preday_basin_return_flow = 0.0; basin[0].preday_basin_detention_store = 0.0; streamflow = 0.0; Qin_total = 0.0; Qstr_total = 0.0; d = 0; // Note: this assumes that the set of patches in the surface routing table is identical to // the set of patches in the subsurface flow table for (i = 0; i < basin->route_list->num_patches; i++) { patch = basin->route_list->list[i]; patch[0].streamflow = 0.0; patch[0].return_flow = 0.0; patch[0].base_flow = 0.0; patch[0].infiltration_excess = 0.0; basin[0].preday_basin_rz_storage += patch[0].rz_storage * patch[0].area; basin[0].preday_basin_unsat_storage += patch[0].unsat_storage * patch[0].area; basin[0].preday_basin_sat_deficit += patch[0].sat_deficit * patch[0].area; basin[0].preday_basin_return_flow += patch[0].return_flow * patch[0].area; basin[0].preday_basin_detention_store += patch[0].detention_store * patch[0].area; basin[0].basin_area += patch[0].area; patch[0].Qin_total = 0.0; patch[0].Qout_total = 0.0; patch[0].Qin = 0.0; patch[0].Qout = 0.0; patch[0].surface_Qin = 0.0; patch[0].surface_Qout = 0.0; patch[0].overland_flow = 0.0; patch[0].interim_sat = patch[0].sat_deficit - patch[0].unsat_storage; if ((patch[0].sat_deficit - patch[0].unsat_storage) < ZERO) patch[0].S = 1.0; else patch[0].S = patch[0].unsat_storage / patch[0].sat_deficit; if (grow_flag > 0) { patch[0].soil_ns.NO3_Qin = 0.0; patch[0].soil_ns.NO3_Qout = 0.0; patch[0].soil_ns.NH4_Qin = 0.0; patch[0].soil_ns.NH4_Qout = 0.0; patch[0].soil_ns.NO3_Qin_total = 0.0; patch[0].soil_ns.NO3_Qout_total = 0.0; patch[0].soil_ns.NH4_Qin_total = 0.0; patch[0].soil_ns.NH4_Qout_total = 0.0; patch[0].streamflow_DON = 0.0; patch[0].streamflow_DOC = 0.0; patch[0].streamflow_NO3 = 0.0; patch[0].streamflow_NH4 = 0.0; patch[0].soil_ns.DON_Qin_total = 0.0; patch[0].soil_ns.DON_Qout_total = 0.0; patch[0].soil_cs.DOC_Qin_total = 0.0; patch[0].soil_cs.DOC_Qout_total = 0.0; patch[0].surface_DON_Qin_total = 0.0; patch[0].surface_DON_Qout_total = 0.0; patch[0].surface_DOC_Qin_total = 0.0; patch[0].surface_DOC_Qout_total = 0.0; patch[0].soil_ns.leach = 0.0; patch[0].surface_ns_leach = 0.0; patch[0].soil_ns.DON_Qout = 0.0; patch[0].soil_ns.DON_Qin = 0.0; patch[0].soil_cs.DOC_Qout = 0.0; patch[0].soil_cs.DOC_Qin = 0.0; patch[0].surface_DON_Qout = 0.0; patch[0].surface_DON_Qin = 0.0; patch[0].surface_DOC_Qout = 0.0; patch[0].surface_DOC_Qin = 0.0; patch[0].streamNO3_from_surface = 0.0; patch[0].streamNO3_from_sub = 0.0; } } } /*--------------------------------------------------------------*/ /* calculate Qout for each patch and add appropriate */ /* proportion of subsurface outflow to each neighbour */ /*--------------------------------------------------------------*/ for (i = 0; i < basin->route_list->num_patches; i++) { patch = basin->route_list->list[i]; patch[0].preday_sat_deficit = patch[0].sat_deficit; patch[0].preday_sat_deficit_z = compute_z_final(verbose_flag, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].soil_depth, 0.0, -1.0 * patch[0].sat_deficit); patch[0].hourly_subsur2stream_flow = 0; patch[0].hourly_sur2stream_flow = 0; patch[0].hourly_stream_flow = 0; patch[0].hourly[0].streamflow_NO3 = 0; patch[0].hourly[0].streamflow_NO3_from_sub = 0; patch[0].hourly[0].streamflow_NO3_from_surface = 0; } for (i = 0; i < basin->route_list->num_patches; i++) { patch = basin->route_list->list[i]; litter=&(patch[0].litter); /*--------------------------------------------------------------*/ /* for roads, saturated throughflow beneath road cut */ /* is routed to downslope patches; saturated throughflow */ /* above the cut and overland flow is routed to the stream */ /* */ /* for streams, no routing - all exported from basin */ /* */ /* regular land patches - route to downslope neighbours */ /*--------------------------------------------------------------*/ if ((patch[0].drainage_type == ROAD) && (command_line[0].road_flag == 1)) { update_drainage_road(patch, command_line, time_int, verbose_flag); } else if (patch[0].drainage_type == STREAM) { update_drainage_stream(patch, command_line, time_int, verbose_flag); } else { update_drainage_land(patch, command_line, time_int, verbose_flag); } } /* end i */ /*--------------------------------------------------------------*/ /* update soil moisture and nitrogen stores */ /* check water balance */ /*--------------------------------------------------------------*/ for (i = 0; i < basin->route_list->num_patches; i++) { patch = basin->route_list->list[i]; /*--------------------------------------------------------------*/ /* update subsurface */ /*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/ /* Recompute current actual depth to water table */ /*-------------------------------------------------------------------------*/ patch[0].sat_deficit += (patch[0].Qout - patch[0].Qin); // this part need to put into some where else patch[0].sat_deficit_z = compute_z_final(verbose_flag, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].soil_depth, 0.0, -1.0 * patch[0].sat_deficit); if (grow_flag > 0) { patch[0].soil_ns.nitrate += (patch[0].soil_ns.NO3_Qin - patch[0].soil_ns.NO3_Qout); patch[0].soil_ns.sminn += (patch[0].soil_ns.NH4_Qin - patch[0].soil_ns.NH4_Qout); patch[0].soil_cs.DOC += (patch[0].soil_cs.DOC_Qin - patch[0].soil_cs.DOC_Qout); patch[0].soil_ns.DON += (patch[0].soil_ns.DON_Qin - patch[0].soil_ns.DON_Qout); } /*--------------------------------------------------------------*/ /* Recompute soil moisture storage */ /*--------------------------------------------------------------*/ if (patch[0].sat_deficit > patch[0].rootzone.potential_sat) { patch[0].rootzone.S = min(patch[0].rz_storage / patch[0].rootzone.potential_sat, 1.0); patch[0].S = patch[0].unsat_storage / (patch[0].sat_deficit - patch[0].rootzone.potential_sat); } else { patch[0].rootzone.S = min((patch[0].rz_storage + patch[0].rootzone.potential_sat - patch[0].sat_deficit) / patch[0].rootzone.potential_sat, 1.0); patch[0].S = min(patch[0].rz_storage / patch[0].sat_deficit, 1.0); } /*--------------------------------------------------------------*/ /* reset iterative patch fluxes to zero */ /*--------------------------------------------------------------*/ patch[0].soil_ns.leach += (patch[0].soil_ns.DON_Qout + patch[0].soil_ns.NH4_Qout + patch[0].soil_ns.NO3_Qout - patch[0].soil_ns.NH4_Qin - patch[0].soil_ns.NO3_Qin - patch[0].soil_ns.DON_Qin); patch[0].surface_ns_leach += ((patch[0].surface_NO3_Qout - patch[0].surface_NO3_Qin) + (patch[0].surface_NH4_Qout - patch[0].surface_NH4_Qin) + (patch[0].surface_DON_Qout - patch[0].surface_DON_Qin)); patch[0].Qin_total += patch[0].Qin + patch[0].surface_Qin; patch[0].Qout_total += patch[0].Qout + patch[0].surface_Qout; patch[0].surface_Qin = 0.0; patch[0].surface_Qout = 0.0; patch[0].Qin = 0.0; patch[0].Qout = 0.0; if (grow_flag > 0) { patch[0].soil_cs.DOC_Qin_total += patch[0].soil_cs.DOC_Qin; patch[0].soil_cs.DOC_Qout_total += patch[0].soil_cs.DOC_Qout; patch[0].soil_ns.NH4_Qin_total += patch[0].soil_ns.NH4_Qin; patch[0].soil_ns.NH4_Qout_total += patch[0].soil_ns.NH4_Qout; patch[0].soil_ns.NO3_Qin_total += patch[0].soil_ns.NO3_Qin; patch[0].soil_ns.NO3_Qout_total += patch[0].soil_ns.NO3_Qout; patch[0].soil_ns.DON_Qin_total += patch[0].soil_ns.DON_Qin; patch[0].soil_ns.DON_Qout_total += patch[0].soil_ns.DON_Qout; patch[0].surface_DON_Qin_total += patch[0].surface_DON_Qin; patch[0].surface_DON_Qout_total += patch[0].surface_DON_Qout; patch[0].surface_DOC_Qin_total += patch[0].surface_DOC_Qin; patch[0].surface_DOC_Qout_total += patch[0].surface_DOC_Qout; patch[0].soil_ns.NH4_Qin = 0.0; patch[0].soil_ns.NH4_Qout = 0.0; patch[0].soil_ns.NO3_Qin = 0.0; patch[0].soil_ns.NO3_Qout = 0.0; patch[0].soil_ns.DON_Qout = 0.0; patch[0].soil_ns.DON_Qin = 0.0; patch[0].soil_cs.DOC_Qout = 0.0; patch[0].soil_cs.DOC_Qin = 0.0; patch[0].surface_NH4_Qout = 0.0; patch[0].surface_NH4_Qin = 0.0; patch[0].surface_NO3_Qout = 0.0; patch[0].surface_NO3_Qin = 0.0; patch[0].surface_DON_Qout = 0.0; patch[0].surface_DON_Qin = 0.0; patch[0].surface_DOC_Qout = 0.0; patch[0].surface_DOC_Qin = 0.0; } /*--------------------------------------------------------------*/ /* finalize streamflow and saturation deficits */ /* */ /* move any saturation excess into detention store */ /* (i.e this needs to be routed on the next time step) */ /* some streamflow may have already been accumulated from */ /* redirected streamflow */ /* water balance calculations */ /* only on last iteration */ /* **** note that streamflow is updated sequentially */ /* i.e not at the end; it is similar to Qout, in */ /* that it accumulates flux in from patches */ /* (roads) that direct water to the stream */ /*--------------------------------------------------------------*/ if ((patch[0].sat_deficit - (patch[0].unsat_storage + patch[0].rz_storage)) < -1.0 * ZERO) { excess = -1.0 * (patch[0].sat_deficit - patch[0].unsat_storage - patch[0].rz_storage); patch[0].detention_store += excess; patch[0].sat_deficit = 0.0; patch[0].unsat_storage = 0.0; patch[0].rz_storage = 0.0; if (grow_flag > 0) { Nout = compute_N_leached(verbose_flag, patch[0].soil_cs.DOC, excess, 0.0, 0.0, patch[0].m, patch[0].innundation_list[d].gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].DOM_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].DOC_adsorption_rate, patch[0].transmissivity_profile); patch[0].surface_DOC += Nout; patch[0].soil_cs.DOC -= Nout; } if (grow_flag > 0) { Nout = compute_N_leached(verbose_flag, patch[0].soil_ns.DON, excess, 0.0, 0.0, patch[0].m, patch[0].innundation_list[d].gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].DOM_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].DON_adsorption_rate, patch[0].transmissivity_profile); patch[0].surface_DON += Nout; patch[0].soil_ns.DON -= Nout; } if (grow_flag > 0) { Nout = compute_N_leached(verbose_flag, patch[0].soil_ns.nitrate, excess, 0.0, 0.0, patch[0].m, patch[0].innundation_list[d].gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].N_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].NO3_adsorption_rate, patch[0].transmissivity_profile); patch[0].surface_NO3 += Nout; patch[0].soil_ns.nitrate -= Nout; } if (grow_flag > 0) { Nout = compute_N_leached(verbose_flag, patch[0].soil_ns.sminn, excess, 0.0, 0.0, patch[0].m, patch[0].innundation_list[d].gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].N_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].NH4_adsorption_rate, patch[0].transmissivity_profile); patch[0].surface_NH4 += Nout; patch[0].soil_ns.sminn -= Nout; } } /*--------------------------------------------------------------*/ /* final overland flow routing */ /*--------------------------------------------------------------*/ if (((excess = patch[0].detention_store - patch[0].soil_defaults[0][0].detention_store_size) > ZERO) && (patch[0].detention_store > ZERO)) { if (patch[0].drainage_type == STREAM) { if (grow_flag > 0) { patch[0].streamflow_DON += (excess / patch[0].detention_store) * patch[0].surface_DON; patch[0].streamflow_DOC += (excess / patch[0].detention_store) * patch[0].surface_DOC; patch[0].streamflow_NO3 += (excess / patch[0].detention_store) * patch[0].surface_NO3; patch[0].streamNO3_from_surface +=(excess / patch[0].detention_store) * patch[0].surface_NO3; patch[0].hourly[0].streamflow_NO3 += (excess / patch[0].detention_store) * patch[0].surface_NO3; patch[0].hourly[0].streamflow_NO3_from_surface +=(excess / patch[0].detention_store) * patch[0].surface_NO3; patch[0].streamflow_NH4 += (excess / patch[0].detention_store) * patch[0].surface_NH4; patch[0].surface_DON -= (excess / patch[0].detention_store) * patch[0].surface_DON; patch[0].surface_DOC -= (excess / patch[0].detention_store) * patch[0].surface_DOC; patch[0].surface_NO3 -= (excess / patch[0].detention_store) * patch[0].surface_NO3; patch[0].surface_NH4 -= (excess / patch[0].detention_store) * patch[0].surface_NH4; } patch[0].return_flow += excess; patch[0].detention_store -= excess; patch[0].Qout_total += excess; patch[0].hourly_sur2stream_flow += excess; } else { /*--------------------------------------------------------------*/ /* determine which innundation depth to consider */ /*--------------------------------------------------------------*/ if (patch[0].num_innundation_depths > 0) { innundation_depth = patch[0].detention_store; d = 0; while ((innundation_depth > patch[0].innundation_list[d].critical_depth) && (d < patch[0].num_innundation_depths - 1)) { d++; } } else { d = 0; } for (j = 0; j < patch->surface_innundation_list[d].num_neighbours; j++) { neigh = patch->surface_innundation_list[d].neighbours[j].patch; Qout = excess * patch->surface_innundation_list[d].neighbours[j].gamma; if (grow_flag > 0) { NO3_out = Qout / patch[0].detention_store * patch[0].surface_NO3; NH4_out = Qout / patch[0].detention_store * patch[0].surface_NH4; DON_out = Qout / patch[0].detention_store * patch[0].surface_DON; DOC_out = Qout / patch[0].detention_store * patch[0].surface_DOC; Nout = NO3_out + NH4_out + DON_out; } if (neigh[0].drainage_type == STREAM) { neigh[0].Qin_total += Qout * patch[0].area / neigh[0].area; neigh[0].return_flow += Qout * patch[0].area / neigh[0].area; if (grow_flag > 0) { neigh[0].streamflow_DOC += (DOC_out * patch[0].area / neigh[0].area); neigh[0].streamflow_DON += (DON_out * patch[0].area / neigh[0].area); neigh[0].streamflow_NO3 += (NO3_out * patch[0].area / neigh[0].area); neigh[0].streamNO3_from_surface +=(NO3_out * patch[0].area / neigh[0].area); neigh[0].hourly[0].streamflow_NO3 += (NO3_out * patch[0].area / neigh[0].area); neigh[0].hourly[0].streamflow_NO3_from_sub +=(NO3_out * patch[0].area / neigh[0].area); neigh[0].streamflow_NH4 += (NH4_out * patch[0].area / neigh[0].area); neigh[0].surface_ns_leach += (Nout * patch[0].area / neigh[0].area); } } else { neigh[0].Qin_total += Qout * patch[0].area / neigh[0].area; neigh[0].detention_store += Qout * patch[0].area / neigh[0].area; if (grow_flag > 0) { neigh[0].surface_DOC += (DOC_out * patch[0].area / neigh[0].area); neigh[0].surface_DON += (DON_out * patch[0].area / neigh[0].area); neigh[0].surface_NO3 += (NO3_out * patch[0].area / neigh[0].area); neigh[0].surface_ns_leach -= (Nout * patch[0].area / neigh[0].area); neigh[0].surface_NH4 += (NH4_out * patch[0].area / neigh[0].area); } } } if (grow_flag > 0) { patch[0].surface_DOC -= (excess / patch[0].detention_store) * patch[0].surface_DOC; patch[0].surface_DON -= (excess / patch[0].detention_store) * patch[0].surface_DON; patch[0].surface_NO3 -= (excess / patch[0].detention_store) * patch[0].surface_NO3; patch[0].surface_NH4 -= (excess / patch[0].detention_store) * patch[0].surface_NH4; patch[0].surface_ns_leach += (excess / patch[0].detention_store) * patch[0].surface_NO3; } patch[0].detention_store -= excess; patch[0].Qout_total += excess; } } /*-------------------------------------------------------------------------*/ /*Recompute current actual depth to water table */ /*-------------------------------------------------------------------------*/ patch[0].sat_deficit_z = compute_z_final(verbose_flag, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].soil_depth, 0.0, -1.0 * patch[0].sat_deficit); /*--------------------------------------------------------------*/ /* leave behind field capacity */ /* if sat deficit has been lowered */ /* this should be an interactive process, we will use */ /* 0th order approximation */ /* we do not do this once sat def is below 0.9 soil depth */ /* we use 0.9 to prevent numerical instability */ /*--------------------------------------------------------------*/ if ((patch[0].sat_deficit_z > patch[0].preday_sat_deficit_z) && (patch[0].sat_deficit_z < patch[0].soil_defaults[0][0].soil_depth * 0.9)) { add_field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].sat_deficit_z, patch[0].preday_sat_deficit_z); add_field_capacity = max(add_field_capacity, 0.0); patch[0].sat_deficit += add_field_capacity; if ((patch[0].sat_deficit_z > patch[0].rootzone.depth) && (patch[0].preday_sat_deficit_z > patch[0].rootzone.depth)) patch[0].unsat_storage += add_field_capacity; else patch[0].rz_storage += add_field_capacity; } if (patch[0].rootzone.depth > ZERO) { if ((patch[0].sat_deficit > ZERO) && (patch[0].rz_storage == 0.0)) { add_field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].sat_deficit_z, 0.0); add_field_capacity = max(add_field_capacity, 0.0); patch[0].sat_deficit += add_field_capacity; patch[0].rz_storage += add_field_capacity; } } else { if ((patch[0].sat_deficit > ZERO) && (patch[0].unsat_storage == 0.0)) { add_field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].sat_deficit_z, 0.0); add_field_capacity = max(add_field_capacity, 0.0); patch[0].sat_deficit += add_field_capacity; patch[0].unsat_storage += add_field_capacity; } } /*--------------------------------------------------------------*/ /* try to infiltrate this water */ /* use time_int as duration */ /*--------------------------------------------------------------*/ if (patch[0].detention_store > ZERO) if (patch[0].rootzone.depth > ZERO) { infiltration = compute_infiltration(verbose_flag, patch[0].sat_deficit_z, patch[0].rootzone.S, patch[0].Ksat_vertical, patch[0].soil_defaults[0][0].Ksat_0_v, patch[0].soil_defaults[0][0].mz_v, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, (patch[0].detention_store), time_int, patch[0].soil_defaults[0][0].psi_air_entry); } else { infiltration = compute_infiltration(verbose_flag, patch[0].sat_deficit_z, patch[0].S, patch[0].Ksat_vertical, patch[0].soil_defaults[0][0].Ksat_0_v, patch[0].soil_defaults[0][0].mz_v, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, (patch[0].detention_store), time_int, patch[0].soil_defaults[0][0].psi_air_entry); } else infiltration = 0.0; /*--------------------------------------------------------------*/ /* added an surface N flux to surface N pool and */ /* allow infiltration of surface N */ /*--------------------------------------------------------------*/ if ((grow_flag > 0) && (infiltration > ZERO)) { patch[0].soil_ns.DON += ((infiltration / patch[0].detention_store) * patch[0].surface_DON); patch[0].soil_cs.DOC += ((infiltration / patch[0].detention_store) * patch[0].surface_DOC); patch[0].soil_ns.nitrate += ((infiltration / patch[0].detention_store) * patch[0].surface_NO3); patch[0].surface_NO3 -= ((infiltration / patch[0].detention_store) * patch[0].surface_NO3); patch[0].soil_ns.sminn += ((infiltration / patch[0].detention_store) * patch[0].surface_NH4); patch[0].surface_NH4 -= ((infiltration / patch[0].detention_store) * patch[0].surface_NH4); patch[0].surface_DOC -= ((infiltration / patch[0].detention_store) * patch[0].surface_DOC); patch[0].surface_DON -= ((infiltration / patch[0].detention_store) * patch[0].surface_DON); } /*--------------------------------------------------------------*/ /* Determine if the infifltration will fill up the unsat */ /* zone or not. */ /* We use the strict assumption that sat deficit is the */ /* amount of water needed to saturate the soil. */ /*--------------------------------------------------------------*/ if (infiltration > patch[0].sat_deficit - patch[0].unsat_storage - patch[0].rz_storage) { /*--------------------------------------------------------------*/ /* Yes the unsat zone will be filled so we may */ /* as well treat the unsat_storage and infiltration*/ /* as water added to the water table. */ /*--------------------------------------------------------------*/ patch[0].sat_deficit -= (infiltration + patch[0].unsat_storage + patch[0].rz_storage); /*--------------------------------------------------------------*/ /* There is no unsat_storage left. */ /*--------------------------------------------------------------*/ patch[0].unsat_storage = 0.0; patch[0].rz_storage = 0.0; patch[0].field_capacity = 0.0; patch[0].rootzone.field_capacity = 0.0; } else if ((patch[0].sat_deficit > patch[0].rootzone.potential_sat) && (infiltration > patch[0].rootzone.potential_sat - patch[0].rz_storage)) { /*------------------------------------------------------------------------------*/ /* Just add the infiltration to the rz_storage and unsat_storage */ /*------------------------------------------------------------------------------*/ patch[0].unsat_storage += infiltration - (patch[0].rootzone.potential_sat - patch[0].rz_storage); patch[0].rz_storage = patch[0].rootzone.potential_sat; } /* Only rootzone layer saturated - perched water table case */ else if ((patch[0].sat_deficit > patch[0].rootzone.potential_sat) && (infiltration <= patch[0].rootzone.potential_sat - patch[0].rz_storage)) { /*--------------------------------------------------------------*/ /* Just add the infiltration to the rz_storage */ /*--------------------------------------------------------------*/ patch[0].rz_storage += infiltration; } else if ((patch[0].sat_deficit <= patch[0].rootzone.potential_sat) && (infiltration <= patch[0].sat_deficit - patch[0].rz_storage - patch[0].unsat_storage)) { patch[0].rz_storage += patch[0].unsat_storage; /* transfer left water in unsat storage to rootzone layer */ patch[0].unsat_storage = 0; patch[0].rz_storage += infiltration; patch[0].field_capacity = 0; } if (patch[0].sat_deficit < 0.0) { patch[0].detention_store -= (patch[0].sat_deficit - patch[0].unsat_storage); patch[0].sat_deficit = 0.0; patch[0].unsat_storage = 0.0; } patch[0].detention_store -= infiltration; /*--------------------------------------------------------------*/ /* recompute saturation deficit */ /*--------------------------------------------------------------*/ patch[0].sat_deficit_z = compute_z_final(verbose_flag, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].soil_depth, 0.0, -1.0 * patch[0].sat_deficit); /*--------------------------------------------------------------*/ /* compute new field capacity */ /*--------------------------------------------------------------*/ if (patch[0].sat_deficit_z < patch[0].rootzone.depth) { patch[0].rootzone.field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].rootzone.depth, 0.0); patch[0].field_capacity = 0.0; } else { patch[0].rootzone.field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].rootzone.depth, 0.0); patch[0].field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].sat_deficit_z, 0) - patch[0].rootzone.field_capacity; } /*--------------------------------------------------------------*/ /* Recompute patch soil moisture storage */ /*--------------------------------------------------------------*/ if (patch[0].sat_deficit < ZERO) { patch[0].S = 1.0; patch[0].rootzone.S = 1.0; rz_drainage = 0.0; unsat_drainage = 0.0; } else if (patch[0].sat_deficit_z > patch[0].rootzone.depth) { /* Constant vertical profile of soil porosity */ /*-------------------------------------------------------*/ /* soil drainage and storage update */ /*-------------------------------------------------------*/ patch[0].rootzone.S = min(patch[0].rz_storage / patch[0].rootzone.potential_sat, 1.0); rz_drainage = compute_unsat_zone_drainage( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].pore_size_index, patch[0].rootzone.S, patch[0].soil_defaults[0][0].mz_v, patch[0].rootzone.depth, patch[0].soil_defaults[0][0].Ksat_0_v / n_timesteps / 2, patch[0].rz_storage - patch[0].rootzone.field_capacity); patch[0].rz_storage -= rz_drainage; patch[0].unsat_storage += rz_drainage; patch[0].S = min(patch[0].unsat_storage / (patch[0].sat_deficit - patch[0].rootzone.potential_sat), 1.0); unsat_drainage = compute_unsat_zone_drainage( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].pore_size_index, patch[0].S, patch[0].soil_defaults[0][0].mz_v, patch[0].sat_deficit_z, patch[0].soil_defaults[0][0].Ksat_0_v / n_timesteps / 2, patch[0].unsat_storage - patch[0].field_capacity); patch[0].unsat_storage -= unsat_drainage; patch[0].sat_deficit -= unsat_drainage; } else { patch[0].sat_deficit -= patch[0].unsat_storage; /* transfer left water in unsat storage to rootzone layer */ patch[0].unsat_storage = 0.0; patch[0].S = min(patch[0].rz_storage / patch[0].sat_deficit, 1.0); rz_drainage = compute_unsat_zone_drainage( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].pore_size_index, patch[0].S, patch[0].soil_defaults[0][0].mz_v, patch[0].sat_deficit_z, patch[0].soil_defaults[0][0].Ksat_0_v / n_timesteps / 2, patch[0].rz_storage - patch[0].rootzone.field_capacity); unsat_drainage = 0.0; patch[0].rz_storage -= rz_drainage; patch[0].sat_deficit -= rz_drainage; } patch[0].unsat_drainage += unsat_drainage; patch[0].rz_drainage += rz_drainage; if (patch[0].sat_deficit > patch[0].rootzone.potential_sat) patch[0].rootzone.S = min(patch[0].rz_storage / patch[0].rootzone.potential_sat, 1.0); else patch[0].rootzone.S = min((patch[0].rz_storage + patch[0].rootzone.potential_sat - patch[0].sat_deficit) / patch[0].rootzone.potential_sat, 1.0); /*-------------------c------------------------------------------------------*/ /* Recompute current actual depth to water table */ /*-------------------------------------------------------------------------*/ patch[0].sat_deficit_z = compute_z_final(verbose_flag, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].soil_depth, 0.0, -1.0 * patch[0].sat_deficit); /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ patch[0].hourly_stream_flow += patch[0].hourly_subsur2stream_flow + patch[0].hourly_sur2stream_flow; basin[0].basin_return_flow += (patch[0].return_flow) * patch[0].area; /* ******************************** */ /* accumulate the daily returnflow and baseflow calculated from update_drainage*/ /* The N calculation has been completed in update_drainage_***.c routing*/ if (current_date.hour == n_timesteps){ if (patch[0].drainage_type == STREAM) { patch[0].streamflow += patch[0].return_flow + patch[0].base_flow; } } } /* end i */ basin[0].basin_outflow /= basin[0].basin_area; basin[0].preday_basin_rz_storage /= basin[0].basin_area; basin[0].preday_basin_unsat_storage /= basin[0].basin_area; basin[0].preday_basin_detention_store /= basin[0].basin_area; basin[0].preday_basin_sat_deficit /= basin[0].basin_area; basin[0].basin_rz_storage /= basin[0].basin_area; basin[0].basin_unsat_storage /= basin[0].basin_area; basin[0].basin_detention_store /= basin[0].basin_area; basin[0].basin_sat_deficit /= basin[0].basin_area; water_balance = basin[0].preday_basin_rz_storage + basin[0].preday_basin_unsat_storage + basin[0].preday_basin_detention_store - basin[0].preday_basin_sat_deficit - (basin[0].basin_rz_storage + basin[0].basin_unsat_storage + basin[0].basin_detention_store - basin[0].basin_sat_deficit) - basin[0].basin_outflow; if ((command_line[0].output_flags.yearly == 1) && (command_line[0].b != NULL )) { if (basin[0].basin_outflow <= command_line[0].thresholds[STREAMFLOW]) basin[0].acc_year.num_threshold += 1; } return; } /*end compute_subsurface_routing_hourly.c*/
void update_drainage_land( struct patch_object *patch, struct command_line_object *command_line, double time_int, int verbose_flag) { /*--------------------------------------------------------------*/ /* Local function definition. */ /*--------------------------------------------------------------*/ double compute_delta_water( int, double, double, double, double, double); double compute_varbased_returnflow( double, double, double, struct litter_object *); double compute_varbased_flow( int, double, double, double, double, double *); double compute_N_leached(int, double, double, double, double, double, double, double, double, double, double, double, double, double *); double recompute_gamma( struct patch_object *, double); double compute_infiltration( int, double, double, double, double, double, double, double, double, double, double); /*--------------------------------------------------------------*/ /* Local variable definition. */ /*--------------------------------------------------------------*/ int j, d, idx; double tmp; double m, Ksat, std_scale; double NH4_leached_to_patch, NH4_leached_to_stream; double NO3_leached_to_patch, NO3_leached_to_stream; double DON_leached_to_patch, DON_leached_to_stream; double DOC_leached_to_patch, DOC_leached_to_stream; double NO3_leached_to_surface; /* kg/m2 */ double NH4_leached_to_surface; /* kg/m2 */ double DON_leached_to_surface; /* kg/m2 */ double DOC_leached_to_surface; /* kg/m2 */ double N_leached_total; /* kg/m2 */ double DON_leached_total; /* kg/m2 */ double DOC_leached_total; /* kg/m2 */ double route_to_surface; /* m3 */ double return_flow,route_to_patch ; /* m3 */ double available_sat_water; /* m3 */ double Qin, Qout; /* m */ double innundation_depth, infiltration; /* m */ double total_gamma; double Nin, Nout; /* kg/m2 */ double t1,t2,t3; struct patch_object *neigh; route_to_patch = 0.0; route_to_surface = 0.0; return_flow=0.0; DON_leached_to_patch = 0.0; DON_leached_to_stream = 0.0; DOC_leached_to_patch = 0.0; DOC_leached_to_stream = 0.0; NH4_leached_to_patch = 0.0; NH4_leached_to_stream = 0.0; NO3_leached_to_patch = 0.0; NO3_leached_to_stream = 0.0; NO3_leached_to_surface = 0.0; NH4_leached_to_surface = 0.0; DOC_leached_to_surface = 0.0; DON_leached_to_surface = 0.0; /*--------------------------------------------------------------*/ /* m and K are multiplied by sensitivity analysis variables */ /*--------------------------------------------------------------*/ m = patch[0].m ; Ksat = patch[0].soil_defaults[0][0].Ksat_0 ; d=0; /*--------------------------------------------------------------*/ /* recalculate gamma based on current saturation deficits */ /* to account the effect of changes in water table slope */ /*--------------------------------------------------------------*/ total_gamma = recompute_gamma(patch, patch[0].innundation_list[d].gamma); available_sat_water = max(((patch[0].soil_defaults[0][0].soil_water_cap - max(patch[0].sat_deficit,0.0)) * patch[0].area),0.0); /*------------------------------------------------------------*/ /* calculate amuount of water output to patches */ /* this only computes subsurface flow, not overland flow */ /*-----------------------------------------------------------*/ std_scale = command_line[0].std_scale; route_to_patch = time_int * compute_varbased_flow( patch[0].num_soil_intervals, patch[0].std * std_scale, patch[0].sat_deficit, total_gamma, patch[0].soil_defaults[0][0].interval_size, patch[0].transmissivity_profile); if (route_to_patch < 0.0) route_to_patch = 0.0; if ( route_to_patch > available_sat_water) route_to_patch *= (available_sat_water)/(route_to_patch); /*--------------------------------------------------------------*/ /* compute Nitrogen leaching amount */ /*--------------------------------------------------------------*/ if (command_line[0].grow_flag > 0) { Nout = compute_N_leached( verbose_flag, patch[0].soil_ns.nitrate, route_to_patch / patch[0].area, patch[0].sat_deficit, patch[0].soil_defaults[0][0].soil_water_cap, m, total_gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].N_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].NO3_adsorption_rate, patch[0].transmissivity_profile); NO3_leached_to_patch = Nout * patch[0].area; patch[0].soil_ns.NO3_Qout += Nout; Nout = compute_N_leached( verbose_flag, patch[0].soil_ns.sminn, route_to_patch / patch[0].area, patch[0].sat_deficit, patch[0].soil_defaults[0][0].soil_water_cap, m, total_gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].N_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].NH4_adsorption_rate, patch[0].transmissivity_profile); NH4_leached_to_patch = Nout * patch[0].area; patch[0].soil_ns.NH4_Qout += Nout; Nout = compute_N_leached( verbose_flag, patch[0].soil_ns.DON, route_to_patch / patch[0].area, patch[0].sat_deficit, patch[0].soil_defaults[0][0].soil_water_cap, m, total_gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].DOM_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].DON_adsorption_rate, patch[0].transmissivity_profile); DON_leached_to_patch = Nout * patch[0].area; patch[0].soil_ns.DON_Qout += Nout; Nout = compute_N_leached( verbose_flag, patch[0].soil_cs.DOC, route_to_patch / patch[0].area, patch[0].sat_deficit, patch[0].soil_defaults[0][0].soil_water_cap, m, total_gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].DOM_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].DOC_adsorption_rate, patch[0].transmissivity_profile); DOC_leached_to_patch = Nout * patch[0].area; patch[0].soil_cs.DOC_Qout += Nout; } patch[0].Qout += (route_to_patch / patch[0].area); /*--------------------------------------------------------------*/ /* calculate any return flow associated with this patch */ /* and route any infiltration excess */ /* return flow is flow leaving patch (i.e surface_Qout) */ /* note that return flow that becomes detention storage */ /* is added to surface_Qin */ /* similarly with associated nitrogen */ /* note we move unsat_storage into saturated storage in this case */ /* saturated zone will be updated in compute_subsurface_routing */ /* i.e becomes part of Qout */ /*--------------------------------------------------------------*/ if ((patch[0].sat_deficit-patch[0].rz_storage-patch[0].unsat_storage) < -1.0*ZERO) { return_flow = compute_varbased_returnflow(patch[0].std * std_scale, patch[0].rz_storage+patch[0].unsat_storage, patch[0].sat_deficit, &(patch[0].litter)); patch[0].detention_store += return_flow; patch[0].sat_deficit += (return_flow - (patch[0].unsat_storage+patch[0].rz_storage)); patch[0].unsat_storage = 0.0; patch[0].rz_storage = 0.0; } /*--------------------------------------------------------------*/ /* calculated any N-transport associated with return flow */ /* -note available N reduced by what has already been */ /* we assume that only nitrate follows return flow */ /* lost in subsurface flow routing */ /*--------------------------------------------------------------*/ if (command_line[0].grow_flag > 0) { Nout = compute_N_leached( verbose_flag, patch[0].soil_ns.nitrate - (NO3_leached_to_patch/patch[0].area), return_flow, 0.0, 0.0, m, total_gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].N_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].NO3_adsorption_rate, patch[0].transmissivity_profile); patch[0].surface_NO3 += Nout; patch[0].soil_ns.NO3_Qout += Nout; Nout = compute_N_leached( verbose_flag, patch[0].soil_ns.sminn - (NH4_leached_to_patch/patch[0].area), return_flow, 0.0, 0.0, m, total_gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].N_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].NH4_adsorption_rate, patch[0].transmissivity_profile); patch[0].surface_NH4 += Nout; patch[0].soil_ns.NH4_Qout += Nout; Nout = compute_N_leached( verbose_flag, patch[0].soil_ns.DON - (DON_leached_to_patch/patch[0].area), return_flow, 0.0, 0.0, m, total_gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].DOM_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].DON_adsorption_rate, patch[0].transmissivity_profile); patch[0].surface_DON += Nout; patch[0].soil_ns.DON_Qout += Nout; Nout = compute_N_leached( verbose_flag, patch[0].soil_cs.DOC - (DOC_leached_to_patch/patch[0].area), return_flow, 0.0, 0.0, m, total_gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].DOM_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].DOC_adsorption_rate, patch[0].transmissivity_profile); patch[0].surface_DOC += Nout; patch[0].soil_cs.DOC_Qout += Nout; } /*--------------------------------------------------------------*/ /* route water and nitrogen lossed due to infiltration excess */ /*--------------------------------------------------------------*/ if ( (patch[0].detention_store > patch[0].soil_defaults[0][0].detention_store_size) && (patch[0].detention_store > ZERO) ){ Qout = (patch[0].detention_store - patch[0].soil_defaults[0][0].detention_store_size); if (command_line[0].grow_flag > 0) { Nout = (min(1.0, (Qout/ patch[0].detention_store))) * patch[0].surface_DOC; DOC_leached_to_surface = Nout * patch[0].area; patch[0].surface_DOC -= Nout; Nout = (min(1.0, (Qout/ patch[0].detention_store))) * patch[0].surface_DON; DON_leached_to_surface = Nout * patch[0].area; patch[0].surface_DON -= Nout; Nout = (min(1.0, (Qout/ patch[0].detention_store))) * patch[0].surface_NO3; NO3_leached_to_surface = Nout * patch[0].area; patch[0].surface_NO3 -= Nout; Nout = (min(1.0, (Qout/ patch[0].detention_store))) * patch[0].surface_NH4; NH4_leached_to_surface = Nout * patch[0].area; patch[0].surface_NH4 -= Nout; } route_to_surface = (Qout * patch[0].area); patch[0].detention_store -= Qout; patch[0].surface_Qout += Qout; } if (NO3_leached_to_surface < 0.0) printf("WARNING %d %lf",patch[0].ID, NO3_leached_to_surface); /*--------------------------------------------------------------*/ /* route flow to neighbours */ /* route n_leaching if grow flag specfied */ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /* regular downslope routing */ /*--------------------------------------------------------------*/ if (command_line[0].noredist_flag == 0) { d=0; for (j = 0; j < patch[0].innundation_list[d].num_neighbours; j++) { neigh = patch[0].innundation_list[d].neighbours[j].patch; /*--------------------------------------------------------------*/ /* first transfer subsurface water and nitrogen */ /*--------------------------------------------------------------*/ Qin = (patch[0].innundation_list[d].neighbours[j].gamma * route_to_patch) / neigh[0].area; if (Qin < 0) printf("\n warning negative routing from patch %d with gamma %lf", patch[0].ID, total_gamma); if (command_line[0].grow_flag > 0) { Nin = (patch[0].innundation_list[d].neighbours[j].gamma * DON_leached_to_patch) / neigh[0].area; neigh[0].soil_ns.DON_Qin += Nin; Nin = (patch[0].innundation_list[d].neighbours[j].gamma * DOC_leached_to_patch) / neigh[0].area; neigh[0].soil_cs.DOC_Qin += Nin; Nin = (patch[0].innundation_list[d].neighbours[j].gamma * NO3_leached_to_patch) / neigh[0].area; neigh[0].soil_ns.NO3_Qin += Nin; Nin = (patch[0].innundation_list[d].neighbours[j].gamma * NH4_leached_to_patch) / neigh[0].area; neigh[0].soil_ns.NH4_Qin += Nin; } neigh[0].Qin += Qin; } /*--------------------------------------------------------------*/ /* surface downslope routing */ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /* determine which innundation depth to consider */ /*--------------------------------------------------------------*/ if (patch[0].num_innundation_depths > 0) { innundation_depth = patch[0].detention_store + route_to_surface/patch[0].area; d=0; while ((innundation_depth > patch[0].innundation_list[d].critical_depth) && (d < patch[0].num_innundation_depths-1)) { d++;} } else d=0; for (j = 0; j < patch[0].surface_innundation_list[d].num_neighbours; j++) { neigh = patch[0].surface_innundation_list[d].neighbours[j].patch; /*--------------------------------------------------------------*/ /* now transfer surface water and nitrogen */ /* - first nitrogen */ /*--------------------------------------------------------------*/ if (command_line[0].grow_flag > 0) { Nin = (patch[0].surface_innundation_list[d].neighbours[j].gamma * NO3_leached_to_surface) / neigh[0].area; neigh[0].surface_NO3 += Nin; Nin = (patch[0].surface_innundation_list[d].neighbours[j].gamma * NH4_leached_to_surface) / neigh[0].area; neigh[0].surface_NH4 += Nin; Nin = (patch[0].surface_innundation_list[d].neighbours[j].gamma * DON_leached_to_surface) / neigh[0].area; neigh[0].surface_DON += Nin; Nin = (patch[0].surface_innundation_list[d].neighbours[j].gamma * DOC_leached_to_surface) / neigh[0].area; neigh[0].surface_DOC += Nin; } /*--------------------------------------------------------------*/ /* - now surface water */ /* surface stores should be updated to facilitate transfer */ /* added net surface water transfer to detention store */ /*--------------------------------------------------------------*/ Qin = (patch[0].surface_innundation_list[d].neighbours[j].gamma * route_to_surface) / neigh[0].area; neigh[0].detention_store += Qin; neigh[0].surface_Qin += Qin; /*--------------------------------------------------------------*/ /* try to infiltrate this water */ /* use time_int as duration */ /*--------------------------------------------------------------*/ if (neigh[0].detention_store > ZERO) { if (neigh[0].rootzone.depth > ZERO) { infiltration = compute_infiltration( verbose_flag, neigh[0].sat_deficit_z, neigh[0].rootzone.S, neigh[0].Ksat_vertical, neigh[0].soil_defaults[0][0].Ksat_0_v, neigh[0].soil_defaults[0][0].mz_v, neigh[0].soil_defaults[0][0].porosity_0, neigh[0].soil_defaults[0][0].porosity_decay, (neigh[0].detention_store), time_int, neigh[0].soil_defaults[0][0].theta_psi_curve); } else { infiltration = compute_infiltration( verbose_flag, neigh[0].sat_deficit_z, neigh[0].S, neigh[0].Ksat_vertical, neigh[0].soil_defaults[0][0].Ksat_0_v, neigh[0].soil_defaults[0][0].mz_v, neigh[0].soil_defaults[0][0].porosity_0, neigh[0].soil_defaults[0][0].porosity_decay, (neigh[0].detention_store), time_int, neigh[0].soil_defaults[0][0].theta_psi_curve); } } else infiltration = 0.0; /*--------------------------------------------------------------*/ /* added an surface N flux to surface N pool and */ /* allow infiltration of surface N */ /*--------------------------------------------------------------*/ if ((command_line[0].grow_flag > 0 ) && (infiltration > ZERO)) { neigh[0].soil_cs.DOC_Qin += ((infiltration / neigh[0].detention_store) * neigh[0].surface_DOC); neigh[0].surface_DOC -= ((infiltration / neigh[0].detention_store) * neigh[0].surface_DOC); neigh[0].soil_ns.DON_Qin += ((infiltration / neigh[0].detention_store) * neigh[0].surface_DON); neigh[0].surface_DON -= ((infiltration / neigh[0].detention_store) * neigh[0].surface_DON); neigh[0].soil_ns.NO3_Qin += ((infiltration / neigh[0].detention_store) * neigh[0].surface_NO3); neigh[0].surface_NO3 -= ((infiltration / neigh[0].detention_store) * neigh[0].surface_NO3); neigh[0].soil_ns.NH4_Qin += ((infiltration / neigh[0].detention_store) * neigh[0].surface_NH4); neigh[0].surface_NH4 -= ((infiltration / neigh[0].detention_store) * neigh[0].surface_NH4); } if (infiltration > neigh[0].sat_deficit - neigh[0].unsat_storage - neigh[0].rz_storage) { neigh[0].sat_deficit -= (infiltration + neigh[0].unsat_storage + neigh[0].rz_storage); neigh[0].unsat_storage = 0.0; neigh[0].rz_storage = 0.0; neigh[0].field_capacity = 0.0; neigh[0].rootzone.field_capacity = 0.0; } else if ((neigh[0].sat_deficit > neigh[0].rootzone.potential_sat) && (infiltration > neigh[0].rootzone.potential_sat - neigh[0].rz_storage)) { /*------------------------------------------------------------------------------*/ /* Just add the infiltration to the rz_storage and unsat_storage */ /*------------------------------------------------------------------------------*/ neigh[0].unsat_storage += infiltration - (neigh[0].rootzone.potential_sat - neigh[0].rz_storage); neigh[0].rz_storage = neigh[0].rootzone.potential_sat; } /* Only rootzone layer saturated - perched water table case */ else if ((neigh[0].sat_deficit > neigh[0].rootzone.potential_sat) && (infiltration <= neigh[0].rootzone.potential_sat - neigh[0].rz_storage)) { /*--------------------------------------------------------------*/ /* Just add the infiltration to the rz_storage */ /*--------------------------------------------------------------*/ neigh[0].rz_storage += infiltration; } else if ((neigh[0].sat_deficit <= neigh[0].rootzone.potential_sat) && (infiltration <= neigh[0].sat_deficit - neigh[0].rz_storage - neigh[0].unsat_storage)) { neigh[0].rz_storage += neigh[0].unsat_storage; /* transfer left water in unsat storage to rootzone layer */ neigh[0].unsat_storage = 0; neigh[0].rz_storage += infiltration; neigh[0].field_capacity = 0; } neigh[0].detention_store -= infiltration; } } /* end if redistribution flag */ return; } /*end update_drainage_land.c*/
void compute_subsurface_routing(struct command_line_object *command_line, struct basin_object *basin, int n_timesteps, struct date current_date) { /*--------------------------------------------------------------*/ /* Local function definition. */ /*--------------------------------------------------------------*/ void update_drainage_stream(struct patch_object *, struct command_line_object *, double, int); void update_drainage_road(struct patch_object *, struct command_line_object *, double, int); void update_drainage_land(struct patch_object *, struct command_line_object *, double, int); double compute_infiltration(int, double, double, double, double, double, double, double, double, double, double); double compute_z_final(int, double, double, double, double, double); double compute_N_leached(int, double, double, double, double, double, double, double, double, double, double, double, double); double compute_layer_field_capacity(int, int, double, double, double, double, double, double, double, double, double); double compute_unsat_zone_drainage(int, int, double, double, double, double, double, double); /*--------------------------------------------------------------*/ /* Local variable definition. */ /*--------------------------------------------------------------*/ int i, d; int j, k; int grow_flag, verbose_flag; double time_int, tmp; double scale; double theta, m, Ksat, Nout; double NO3_out, NH4_out, DON_out, DOC_out; double return_flow, excess; double water_balance, infiltration; double innundation_depth; double basin_outflow; double basin_rz_storage; double basin_unsat_storage; double basin_sat_deficit; double basin_return_flow; double basin_detention_store; double basin_area; double preday_basin_unsat_storage; double preday_basin_rz_storage; double preday_basin_sat_deficit; double preday_sat_deficit; double preday_basin_return_flow; double preday_basin_detention_store; double add_field_capacity, rz_drainage, unsat_drainage; double streamflow, Qout, Qin_total, Qstr_total; struct patch_object *patch; struct hillslope_object *hillslope; struct patch_object *neigh; /*--------------------------------------------------------------*/ /* initializations */ /*--------------------------------------------------------------*/ grow_flag = command_line[0].grow_flag; verbose_flag = command_line[0].verbose_flag; time_int = 1.0 / n_timesteps; basin_outflow = 0.0; basin_area = 0.0; basin_unsat_storage = 0.0; basin_rz_storage = 0.0; basin_sat_deficit = 0.0; basin_return_flow = 0.0; basin_detention_store = 0.0; preday_basin_rz_storage = 0.0; preday_basin_unsat_storage = 0.0; preday_basin_sat_deficit = 0.0; preday_basin_return_flow = 0.0; preday_basin_detention_store = 0.0; streamflow = 0.0; Qin_total = 0.0; Qstr_total = 0.0; d = 0; // Note: this assumes that the set of patches in the surface routing table is identical to // the set of patches in the subsurface flow table for (i = 0; i < basin->route_list->num_patches; i++) { patch = basin->route_list->list[i]; patch[0].streamflow = 0.0; patch[0].return_flow = 0.0; patch[0].base_flow = 0.0; patch[0].infiltration_excess = 0.0; preday_basin_rz_storage += patch[0].rz_storage * patch[0].area; preday_basin_unsat_storage += patch[0].unsat_storage * patch[0].area; preday_basin_sat_deficit += patch[0].sat_deficit * patch[0].area; preday_basin_return_flow += patch[0].return_flow * patch[0].area; preday_basin_detention_store += patch[0].detention_store * patch[0].area; basin_area += patch[0].area; patch[0].Qin_total = 0.0; patch[0].Qout_total = 0.0; patch[0].Qin = 0.0; patch[0].Qout = 0.0; patch[0].surface_Qin = 0.0; patch[0].surface_Qout = 0.0; patch[0].preday_sat_deficit = patch[0].sat_deficit; patch[0].preday_sat_deficit_z = compute_z_final(verbose_flag, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].soil_depth, 0.0, -1.0 * patch[0].sat_deficit); patch[0].interim_sat = patch[0].sat_deficit - patch[0].unsat_storage; if ((patch[0].sat_deficit - patch[0].unsat_storage) < ZERO) patch[0].S = 1.0; else patch[0].S = patch[0].unsat_storage / patch[0].sat_deficit; if (grow_flag > 0) { patch[0].soil_ns.NO3_Qin = 0.0; patch[0].soil_ns.NO3_Qout = 0.0; patch[0].soil_ns.NH4_Qin = 0.0; patch[0].soil_ns.NH4_Qout = 0.0; patch[0].soil_ns.NO3_Qin_total = 0.0; patch[0].soil_ns.NO3_Qout_total = 0.0; patch[0].soil_ns.NH4_Qin_total = 0.0; patch[0].soil_ns.NH4_Qout_total = 0.0; patch[0].streamflow_DON = 0.0; patch[0].streamflow_DOC = 0.0; patch[0].streamflow_NO3 = 0.0; patch[0].streamflow_NH4 = 0.0; patch[0].soil_ns.DON_Qin_total = 0.0; patch[0].soil_ns.DON_Qout_total = 0.0; patch[0].soil_cs.DOC_Qin_total = 0.0; patch[0].soil_cs.DOC_Qout_total = 0.0; patch[0].surface_DON_Qin_total = 0.0; patch[0].surface_DON_Qout_total = 0.0; patch[0].surface_DOC_Qin_total = 0.0; patch[0].surface_DOC_Qout_total = 0.0; patch[0].soil_ns.leach = 0.0; patch[0].surface_ns_leach = 0.0; patch[0].soil_ns.DON_Qout = 0.0; patch[0].soil_ns.DON_Qin = 0.0; patch[0].soil_cs.DOC_Qout = 0.0; patch[0].soil_cs.DOC_Qin = 0.0; patch[0].surface_DON_Qout = 0.0; patch[0].surface_DON_Qin = 0.0; patch[0].surface_DOC_Qout = 0.0; patch[0].surface_DOC_Qin = 0.0; } } /*--------------------------------------------------------------*/ /* calculate Qout for each patch and add appropriate */ /* proportion of subsurface outflow to each neighbour */ /*--------------------------------------------------------------*/ for (k = 0; k < n_timesteps; k++) { for (i = 0; i < basin->route_list->num_patches; i++) { patch = basin->route_list->list[i]; /*--------------------------------------------------------------*/ /* for roads, saturated throughflow beneath road cut */ /* is routed to downslope patches; saturated throughflow */ /* above the cut and overland flow is routed to the stream */ /* */ /* for streams, no routing - all exported from basin */ /* */ /* regular land patches - route to downslope neighbours */ /*--------------------------------------------------------------*/ if ((patch[0].drainage_type == ROAD) && (command_line[0].road_flag == 1)) { update_drainage_road(patch, command_line, time_int, verbose_flag); } else if (patch[0].drainage_type == STREAM) { update_drainage_stream(patch, command_line, time_int, verbose_flag); } else { update_drainage_land(patch, command_line, time_int, verbose_flag); } } /* end i */ /*--------------------------------------------------------------*/ /* update soil moisture and nitrogen stores */ /* check water balance */ /*--------------------------------------------------------------*/ for (i = 0; i < basin->route_list->num_patches; i++) { patch = basin->route_list->list[i]; /*--------------------------------------------------------------*/ /* update subsurface */ /*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/ /* Recompute current actual depth to water table */ /*-------------------------------------------------------------------------*/ patch[0].sat_deficit += (patch[0].Qout - patch[0].Qin); patch[0].sat_deficit_z = compute_z_final(verbose_flag, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].soil_depth, 0.0, -1.0 * patch[0].sat_deficit); if (grow_flag > 0) { patch[0].soil_ns.nitrate += (patch[0].soil_ns.NO3_Qin - patch[0].soil_ns.NO3_Qout); patch[0].soil_ns.sminn += (patch[0].soil_ns.NH4_Qin - patch[0].soil_ns.NH4_Qout); patch[0].soil_cs.DOC += (patch[0].soil_cs.DOC_Qin - patch[0].soil_cs.DOC_Qout); patch[0].soil_ns.DON += (patch[0].soil_ns.DON_Qin - patch[0].soil_ns.DON_Qout); } /*--------------------------------------------------------------*/ /* Recompute soil moisture storage */ /*--------------------------------------------------------------*/ if (patch[0].sat_deficit > patch[0].rootzone.potential_sat) { patch[0].rootzone.S = min(patch[0].rz_storage / patch[0].rootzone.potential_sat, 1.0); patch[0].S = patch[0].unsat_storage / (patch[0].sat_deficit - patch[0].rootzone.potential_sat); } else { patch[0].rootzone.S = min((patch[0].rz_storage + patch[0].rootzone.potential_sat - patch[0].sat_deficit) / patch[0].rootzone.potential_sat, 1.0); patch[0].S = min(patch[0].rz_storage / patch[0].sat_deficit, 1.0); } /*--------------------------------------------------------------*/ /* reset iterative patch fluxes to zero */ /*--------------------------------------------------------------*/ patch[0].soil_ns.leach += (patch[0].soil_ns.DON_Qout + patch[0].soil_ns.NH4_Qout + patch[0].soil_ns.NO3_Qout - patch[0].soil_ns.NH4_Qin - patch[0].soil_ns.NO3_Qin - patch[0].soil_ns.DON_Qin); patch[0].surface_ns_leach += ((patch[0].surface_NO3_Qout - patch[0].surface_NO3_Qin) + (patch[0].surface_NH4_Qout - patch[0].surface_NH4_Qin) + (patch[0].surface_DON_Qout - patch[0].surface_DON_Qin)); patch[0].Qin_total += patch[0].Qin + patch[0].surface_Qin; patch[0].Qout_total += patch[0].Qout + patch[0].surface_Qout; patch[0].surface_Qin = 0.0; patch[0].surface_Qout = 0.0; patch[0].Qin = 0.0; patch[0].Qout = 0.0; if (grow_flag > 0) { patch[0].soil_cs.DOC_Qin_total += patch[0].soil_cs.DOC_Qin; patch[0].soil_cs.DOC_Qout_total += patch[0].soil_cs.DOC_Qout; patch[0].soil_ns.NH4_Qin_total += patch[0].soil_ns.NH4_Qin; patch[0].soil_ns.NH4_Qout_total += patch[0].soil_ns.NH4_Qout; patch[0].soil_ns.NO3_Qin_total += patch[0].soil_ns.NO3_Qin; patch[0].soil_ns.NO3_Qout_total += patch[0].soil_ns.NO3_Qout; patch[0].soil_ns.DON_Qin_total += patch[0].soil_ns.DON_Qin; patch[0].soil_ns.DON_Qout_total += patch[0].soil_ns.DON_Qout; patch[0].surface_DON_Qin_total += patch[0].surface_DON_Qin; patch[0].surface_DON_Qout_total += patch[0].surface_DON_Qout; patch[0].surface_DOC_Qin_total += patch[0].surface_DOC_Qin; patch[0].surface_DOC_Qout_total += patch[0].surface_DOC_Qout; patch[0].soil_ns.NH4_Qin = 0.0; patch[0].soil_ns.NH4_Qout = 0.0; patch[0].soil_ns.NO3_Qin = 0.0; patch[0].soil_ns.NO3_Qout = 0.0; patch[0].soil_ns.DON_Qout = 0.0; patch[0].soil_ns.DON_Qin = 0.0; patch[0].soil_cs.DOC_Qout = 0.0; patch[0].soil_cs.DOC_Qin = 0.0; patch[0].surface_NH4_Qout = 0.0; patch[0].surface_NH4_Qin = 0.0; patch[0].surface_NO3_Qout = 0.0; patch[0].surface_NO3_Qin = 0.0; patch[0].surface_DON_Qout = 0.0; patch[0].surface_DON_Qin = 0.0; patch[0].surface_DOC_Qout = 0.0; patch[0].surface_DOC_Qin = 0.0; } /*--------------------------------------------------------------*/ /* finalize streamflow and saturation deficits */ /* */ /* move any saturation excess into detention store */ /* (i.e this needs to be routed on the next time step) */ /* some streamflow may have already been accumulated from */ /* redirected streamflow */ /* water balance calculations */ /* only on last iteration */ /* **** note that streamflow is updated sequentially */ /* i.e not at the end; it is similar to Qout, in */ /* that it accumulates flux in from patches */ /* (roads) that direct water to the stream */ /*--------------------------------------------------------------*/ if (k == (n_timesteps - 1)) { if ((patch[0].sat_deficit - (patch[0].unsat_storage + patch[0].rz_storage)) < -1.0 * ZERO) { excess = -1.0 * (patch[0].sat_deficit - patch[0].unsat_storage - patch[0].rz_storage); patch[0].detention_store += excess; patch[0].sat_deficit = 0.0; patch[0].unsat_storage = 0.0; patch[0].rz_storage = 0.0; if (grow_flag > 0) { Nout = compute_N_leached(verbose_flag, patch[0].soil_cs.DOC, excess, 0.0, 0.0, patch[0].m, patch[0].innundation_list[d].gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].DOM_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].DOC_adsorption_rate); patch[0].surface_DOC += Nout; patch[0].soil_cs.DOC -= Nout; } if (grow_flag > 0) { Nout = compute_N_leached(verbose_flag, patch[0].soil_ns.DON, excess, 0.0, 0.0, patch[0].m, patch[0].innundation_list[d].gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].DOM_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].DON_adsorption_rate); patch[0].surface_DON += Nout; patch[0].soil_ns.DON -= Nout; } if (grow_flag > 0) { Nout = compute_N_leached(verbose_flag, patch[0].soil_ns.nitrate, excess, 0.0, 0.0, patch[0].m, patch[0].innundation_list[d].gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].N_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].NO3_adsorption_rate); patch[0].surface_NO3 += Nout; patch[0].soil_ns.nitrate -= Nout; } if (grow_flag > 0) { Nout = compute_N_leached(verbose_flag, patch[0].soil_ns.sminn, excess, 0.0, 0.0, patch[0].m, patch[0].innundation_list[d].gamma / patch[0].area * time_int, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].N_decay_rate, patch[0].soil_defaults[0][0].active_zone_z, patch[0].soil_defaults[0][0].soil_depth, patch[0].soil_defaults[0][0].NH4_adsorption_rate); patch[0].surface_NH4 += Nout; patch[0].soil_ns.sminn -= Nout; } } /*--------------------------------------------------------------*/ /* final overland flow routing */ /*--------------------------------------------------------------*/ if (((excess = patch[0].detention_store - patch[0].soil_defaults[0][0].detention_store_size) > ZERO) && (patch[0].detention_store > ZERO)) { if (patch[0].drainage_type == STREAM) { if (grow_flag > 0) { patch[0].streamflow_DON += (excess / patch[0].detention_store) * patch[0].surface_DON; patch[0].streamflow_DOC += (excess / patch[0].detention_store) * patch[0].surface_DOC; patch[0].streamflow_NO3 += (excess / patch[0].detention_store) * patch[0].surface_NO3; patch[0].streamflow_NH4 += (excess / patch[0].detention_store) * patch[0].surface_NH4; patch[0].surface_DON -= (excess / patch[0].detention_store) * patch[0].surface_DON; patch[0].surface_DOC -= (excess / patch[0].detention_store) * patch[0].surface_DOC; patch[0].surface_NO3 -= (excess / patch[0].detention_store) * patch[0].surface_NO3; patch[0].surface_NH4 -= (excess / patch[0].detention_store) * patch[0].surface_NH4; } patch[0].return_flow += excess; patch[0].detention_store -= excess; patch[0].Qout_total += excess; } else { /*--------------------------------------------------------------*/ /* determine which innundation depth to consider */ /*--------------------------------------------------------------*/ if (patch[0].num_innundation_depths > 0) { innundation_depth = patch[0].detention_store; d = 0; while ((innundation_depth > patch[0].innundation_list[d].critical_depth) && (d < patch[0].num_innundation_depths - 1)) { d++; } } else { d = 0; } for (j = 0; j < patch->surface_innundation_list[d].num_neighbours; j++) { neigh = patch->surface_innundation_list[d].neighbours[j].patch; Qout = excess * patch->surface_innundation_list[d].neighbours[j].gamma; if (grow_flag > 0) { NO3_out = Qout / patch[0].detention_store * patch[0].surface_NO3; NH4_out = Qout / patch[0].detention_store * patch[0].surface_NH4; DON_out = Qout / patch[0].detention_store * patch[0].surface_DON; DOC_out = Qout / patch[0].detention_store * patch[0].surface_DOC; Nout = NO3_out + NH4_out + DON_out; } if (neigh[0].drainage_type == STREAM) { neigh[0].Qin_total += Qout * patch[0].area / neigh[0].area; neigh[0].return_flow += Qout * patch[0].area / neigh[0].area; if (grow_flag > 0) { neigh[0].streamflow_DOC += (DOC_out * patch[0].area / neigh[0].area); neigh[0].streamflow_DON += (DON_out * patch[0].area / neigh[0].area); neigh[0].streamflow_NO3 += (NO3_out * patch[0].area / neigh[0].area); neigh[0].streamflow_NH4 += (NH4_out * patch[0].area / neigh[0].area); neigh[0].surface_ns_leach += (Nout * patch[0].area / neigh[0].area); } } else { neigh[0].Qin_total += Qout * patch[0].area / neigh[0].area; neigh[0].detention_store += Qout * patch[0].area / neigh[0].area; if (grow_flag > 0) { neigh[0].surface_DOC += (DOC_out * patch[0].area / neigh[0].area); neigh[0].surface_DON += (DON_out * patch[0].area / neigh[0].area); neigh[0].surface_NO3 += (NO3_out * patch[0].area / neigh[0].area); neigh[0].surface_ns_leach -= (Nout * patch[0].area / neigh[0].area); neigh[0].surface_NH4 += (NH4_out * patch[0].area / neigh[0].area); } } } if (grow_flag > 0) { patch[0].surface_DOC -= (excess / patch[0].detention_store) * patch[0].surface_DOC; patch[0].surface_DON -= (excess / patch[0].detention_store) * patch[0].surface_DON; patch[0].surface_NO3 -= (excess / patch[0].detention_store) * patch[0].surface_NO3; patch[0].surface_NH4 -= (excess / patch[0].detention_store) * patch[0].surface_NH4; patch[0].surface_ns_leach += (excess / patch[0].detention_store) * patch[0].surface_NO3; } patch[0].detention_store -= excess; patch[0].Qout_total += excess; } } /*-------------------------------------------------------------------------*/ /*Recompute current actual depth to water table */ /*-------------------------------------------------------------------------*/ patch[0].sat_deficit_z = compute_z_final(verbose_flag, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].soil_depth, 0.0, -1.0 * patch[0].sat_deficit); /*--------------------------------------------------------------*/ /* leave behind field capacity */ /* if sat deficit has been lowered */ /* this should be an interactive process, we will use */ /* 0th order approximation */ /* we do not do this once sat def is below 0.9 soil depth */ /* we use 0.9 to prevent numerical instability */ /*--------------------------------------------------------------*/ if ((patch[0].sat_deficit_z > patch[0].preday_sat_deficit_z) && (patch[0].sat_deficit_z < patch[0].soil_defaults[0][0].soil_depth * 0.9)) { add_field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].sat_deficit_z, patch[0].preday_sat_deficit_z); add_field_capacity = max(add_field_capacity, 0.0); patch[0].sat_deficit += add_field_capacity; if ((patch[0].sat_deficit_z > patch[0].rootzone.depth) && (patch[0].preday_sat_deficit_z > patch[0].rootzone.depth)) patch[0].unsat_storage += add_field_capacity; else patch[0].rz_storage += add_field_capacity; } if (patch[0].rootzone.depth > ZERO) { if ((patch[0].sat_deficit > ZERO) && (patch[0].rz_storage == 0.0)) { add_field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].sat_deficit_z, 0.0); add_field_capacity = max(add_field_capacity, 0.0); patch[0].sat_deficit += add_field_capacity; patch[0].rz_storage += add_field_capacity; } } else { if ((patch[0].sat_deficit > ZERO) && (patch[0].unsat_storage == 0.0)) { add_field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].sat_deficit_z, 0.0); add_field_capacity = max(add_field_capacity, 0.0); patch[0].sat_deficit += add_field_capacity; patch[0].unsat_storage += add_field_capacity; } } /*--------------------------------------------------------------*/ /* try to infiltrate this water */ /* use time_int as duration */ /*--------------------------------------------------------------*/ if (patch[0].detention_store > ZERO) if (patch[0].rootzone.depth > ZERO) { infiltration = compute_infiltration(verbose_flag, patch[0].sat_deficit_z, patch[0].rootzone.S, patch[0].Ksat_vertical, patch[0].soil_defaults[0][0].Ksat_0_v, patch[0].soil_defaults[0][0].mz_v, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, (patch[0].detention_store), time_int, patch[0].soil_defaults[0][0].psi_air_entry); } else { infiltration = compute_infiltration(verbose_flag, patch[0].sat_deficit_z, patch[0].S, patch[0].Ksat_vertical, patch[0].soil_defaults[0][0].Ksat_0_v, patch[0].soil_defaults[0][0].mz_v, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, (patch[0].detention_store), time_int, patch[0].soil_defaults[0][0].psi_air_entry); } else infiltration = 0.0; /*--------------------------------------------------------------*/ /* added an surface N flux to surface N pool and */ /* allow infiltration of surface N */ /*--------------------------------------------------------------*/ if ((grow_flag > 0) && (infiltration > ZERO)) { patch[0].soil_ns.DON += ((infiltration / patch[0].detention_store) * patch[0].surface_DON); patch[0].soil_cs.DOC += ((infiltration / patch[0].detention_store) * patch[0].surface_DOC); patch[0].soil_ns.nitrate += ((infiltration / patch[0].detention_store) * patch[0].surface_NO3); patch[0].surface_NO3 -= ((infiltration / patch[0].detention_store) * patch[0].surface_NO3); patch[0].soil_ns.sminn += ((infiltration / patch[0].detention_store) * patch[0].surface_NH4); patch[0].surface_NH4 -= ((infiltration / patch[0].detention_store) * patch[0].surface_NH4); patch[0].surface_DOC -= ((infiltration / patch[0].detention_store) * patch[0].surface_DOC); patch[0].surface_DON -= ((infiltration / patch[0].detention_store) * patch[0].surface_DON); } /*--------------------------------------------------------------*/ /* Determine if the infifltration will fill up the unsat */ /* zone or not. */ /* We use the strict assumption that sat deficit is the */ /* amount of water needed to saturate the soil. */ /*--------------------------------------------------------------*/ if (infiltration > patch[0].sat_deficit - patch[0].unsat_storage - patch[0].rz_storage) { /*--------------------------------------------------------------*/ /* Yes the unsat zone will be filled so we may */ /* as well treat the unsat_storage and infiltration*/ /* as water added to the water table. */ /*--------------------------------------------------------------*/ patch[0].sat_deficit -= (infiltration + patch[0].unsat_storage + patch[0].rz_storage); /*--------------------------------------------------------------*/ /* There is no unsat_storage left. */ /*--------------------------------------------------------------*/ patch[0].unsat_storage = 0.0; patch[0].rz_storage = 0.0; patch[0].field_capacity = 0.0; patch[0].rootzone.field_capacity = 0.0; } else if ((patch[0].sat_deficit > patch[0].rootzone.potential_sat) && (infiltration > patch[0].rootzone.potential_sat - patch[0].rz_storage)) { /*------------------------------------------------------------------------------*/ /* Just add the infiltration to the rz_storage and unsat_storage */ /*------------------------------------------------------------------------------*/ patch[0].unsat_storage += infiltration - (patch[0].rootzone.potential_sat - patch[0].rz_storage); patch[0].rz_storage = patch[0].rootzone.potential_sat; } /* Only rootzone layer saturated - perched water table case */ else if ((patch[0].sat_deficit > patch[0].rootzone.potential_sat) && (infiltration <= patch[0].rootzone.potential_sat - patch[0].rz_storage)) { /*--------------------------------------------------------------*/ /* Just add the infiltration to the rz_storage */ /*--------------------------------------------------------------*/ patch[0].rz_storage += infiltration; } else if ((patch[0].sat_deficit <= patch[0].rootzone.potential_sat) && (infiltration <= patch[0].sat_deficit - patch[0].rz_storage - patch[0].unsat_storage)) { patch[0].rz_storage += patch[0].unsat_storage; /* transfer left water in unsat storage to rootzone layer */ patch[0].unsat_storage = 0; patch[0].rz_storage += infiltration; patch[0].field_capacity = 0; } if (patch[0].sat_deficit < 0.0) { patch[0].detention_store -= (patch[0].sat_deficit - patch[0].unsat_storage); patch[0].sat_deficit = 0.0; patch[0].unsat_storage = 0.0; } patch[0].detention_store -= infiltration; /*--------------------------------------------------------------*/ /* recompute saturation deficit */ /*--------------------------------------------------------------*/ patch[0].sat_deficit_z = compute_z_final(verbose_flag, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].soil_depth, 0.0, -1.0 * patch[0].sat_deficit); /*--------------------------------------------------------------*/ /* compute new field capacity */ /*--------------------------------------------------------------*/ if (patch[0].sat_deficit_z < patch[0].rootzone.depth) { patch[0].rootzone.field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].rootzone.depth, 0.0); patch[0].field_capacity = 0.0; } else { patch[0].rootzone.field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].rootzone.depth, 0.0); patch[0].field_capacity = compute_layer_field_capacity( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].psi_air_entry, patch[0].soil_defaults[0][0].pore_size_index, patch[0].soil_defaults[0][0].p3, patch[0].soil_defaults[0][0].p4, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].sat_deficit_z, patch[0].sat_deficit_z, 0) - patch[0].rootzone.field_capacity; } /*--------------------------------------------------------------*/ /* Recompute patch soil moisture storage */ /*--------------------------------------------------------------*/ if (patch[0].sat_deficit < ZERO) { patch[0].S = 1.0; patch[0].rootzone.S = 1.0; rz_drainage = 0.0; unsat_drainage = 0.0; } else if (patch[0].sat_deficit_z > patch[0].rootzone.depth) { /* Constant vertical profile of soil porosity */ /*-------------------------------------------------------*/ /* soil drainage and storage update */ /*-------------------------------------------------------*/ patch[0].rootzone.S = min(patch[0].rz_storage / patch[0].rootzone.potential_sat, 1.0); rz_drainage = compute_unsat_zone_drainage( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].pore_size_index, patch[0].rootzone.S, patch[0].soil_defaults[0][0].mz_v, patch[0].rootzone.depth, patch[0].soil_defaults[0][0].Ksat_0 / n_timesteps / 2, patch[0].rz_storage - patch[0].rootzone.field_capacity); patch[0].rz_storage -= rz_drainage; patch[0].unsat_storage += rz_drainage; patch[0].S = min(patch[0].unsat_storage / (patch[0].sat_deficit - patch[0].rootzone.potential_sat), 1.0); unsat_drainage = compute_unsat_zone_drainage( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].pore_size_index, patch[0].S, patch[0].soil_defaults[0][0].mz_v, patch[0].sat_deficit_z, patch[0].soil_defaults[0][0].Ksat_0 / n_timesteps / 2, patch[0].unsat_storage - patch[0].field_capacity); patch[0].unsat_storage -= unsat_drainage; patch[0].sat_deficit -= unsat_drainage; } else { patch[0].sat_deficit -= patch[0].unsat_storage; /* transfer left water in unsat storage to rootzone layer */ patch[0].unsat_storage = 0.0; patch[0].S = min(patch[0].rz_storage / patch[0].sat_deficit, 1.0); rz_drainage = compute_unsat_zone_drainage( command_line[0].verbose_flag, patch[0].soil_defaults[0][0].theta_psi_curve, patch[0].soil_defaults[0][0].pore_size_index, patch[0].S, patch[0].soil_defaults[0][0].mz_v, patch[0].sat_deficit_z, patch[0].soil_defaults[0][0].Ksat_0 / n_timesteps / 2, patch[0].rz_storage - patch[0].rootzone.field_capacity); unsat_drainage = 0.0; patch[0].rz_storage -= rz_drainage; patch[0].sat_deficit -= rz_drainage; } patch[0].unsat_drainage += unsat_drainage; patch[0].rz_drainage += rz_drainage; if (patch[0].sat_deficit > patch[0].rootzone.potential_sat) patch[0].rootzone.S = min(patch[0].rz_storage / patch[0].rootzone.potential_sat, 1.0); else patch[0].rootzone.S = min((patch[0].rz_storage + patch[0].rootzone.potential_sat - patch[0].sat_deficit) / patch[0].rootzone.potential_sat, 1.0); /*-------------------c------------------------------------------------------*/ /* Recompute current actual depth to water table */ /*-------------------------------------------------------------------------*/ patch[0].sat_deficit_z = compute_z_final(verbose_flag, patch[0].soil_defaults[0][0].porosity_0, patch[0].soil_defaults[0][0].porosity_decay, patch[0].soil_defaults[0][0].soil_depth, 0.0, -1.0 * patch[0].sat_deficit); /*--------------------------------------------------------------*/ /* final stream flow calculations */ /*--------------------------------------------------------------*/ if (patch[0].drainage_type == STREAM) { patch[0].streamflow += patch[0].return_flow + patch[0].base_flow; } basin_outflow += (patch[0].streamflow) * patch[0].area; basin_unsat_storage += patch[0].unsat_storage * patch[0].area; basin_sat_deficit += patch[0].sat_deficit * patch[0].area; basin_rz_storage += patch[0].rz_storage * patch[0].area; basin_detention_store += patch[0].detention_store * patch[0].area; /*---------------------------------------------------------------------*/ /*update accumulator variables */ /*-----------------------------------------------------------------------*/ patch[0].acc_year_trans += (patch[0].transpiration_unsat_zone + patch[0].transpiration_sat_zone); if ((command_line[0].output_flags.monthly == 1) && (command_line[0].b != NULL )) { scale = patch[0].area / basin[0].area; basin[0].acc_month.streamflow += (patch[0].streamflow) * scale; basin[0].acc_month.et += (patch[0].transpiration_unsat_zone + patch[0].evaporation_surf + patch[0].exfiltration_unsat_zone + patch[0].exfiltration_sat_zone + patch[0].transpiration_sat_zone + patch[0].evaporation) * scale; basin[0].acc_month.denitrif += patch[0].ndf.denitrif * scale; basin[0].acc_month.nitrif += patch[0].ndf.sminn_to_nitrate * scale; basin[0].acc_month.mineralized += patch[0].ndf.net_mineralized * scale; basin[0].acc_month.uptake += patch[0].ndf.sminn_to_npool * scale; basin[0].acc_month.DON_loss += (patch[0].soil_ns.DON_Qout_total - patch[0].soil_ns.DON_Qin_total) * scale; basin[0].acc_month.DOC_loss += (patch[0].soil_cs.DOC_Qout_total - patch[0].soil_cs.DOC_Qin_total) * scale; basin[0].acc_month.length += 1; basin[0].acc_month.stream_NO3 += patch[0].streamflow_NO3 * scale; basin[0].acc_month.stream_NH4 += patch[0].streamflow_NH4 * scale; basin[0].acc_month.stream_DON += patch[0].streamflow_DON * scale; basin[0].acc_month.stream_DOC += patch[0].streamflow_DOC * scale; basin[0].acc_month.psn += patch[0].net_plant_psn * scale; basin[0].acc_month.lai += patch[0].lai * scale; basin[0].acc_month.leach += (patch[0].soil_ns.leach + patch[0].surface_ns_leach) * scale; } if ((command_line[0].output_flags.yearly == 1) && (command_line[0].b != NULL )) { scale = patch[0].area / basin[0].area; basin[0].acc_year.length += 1; basin[0].acc_year.leach += (patch[0].soil_ns.leach + patch[0].surface_ns_leach) * scale; basin[0].acc_year.stream_NH4 += patch[0].streamflow_NH4 * scale; basin[0].acc_year.stream_NO3 += patch[0].streamflow_NO3 * scale; basin[0].acc_year.denitrif += patch[0].ndf.denitrif * scale; basin[0].acc_year.nitrif += patch[0].ndf.sminn_to_nitrate * scale; basin[0].acc_year.mineralized += patch[0].ndf.net_mineralized * scale; basin[0].acc_year.uptake += patch[0].ndf.sminn_to_npool * scale; basin[0].acc_year.DON_loss += (patch[0].soil_ns.DON_Qout_total - patch[0].soil_ns.DON_Qin_total) * scale; basin[0].acc_year.DOC_loss += (patch[0].soil_cs.DOC_Qout_total - patch[0].soil_cs.DOC_Qin_total) * scale; basin[0].acc_year.stream_DON += patch[0].streamflow_DON * scale; basin[0].acc_year.stream_DOC += patch[0].streamflow_DOC * scale; basin[0].acc_year.psn += patch[0].net_plant_psn * scale; basin[0].acc_year.PET += (patch[0].PE + patch[0].PET) * scale; basin[0].acc_year.et += (patch[0].evaporation + patch[0].evaporation_surf + patch[0].exfiltration_unsat_zone + patch[0].exfiltration_sat_zone + patch[0].transpiration_unsat_zone + patch[0].transpiration_sat_zone) * scale; basin[0].acc_year.streamflow += (patch[0].streamflow) * scale; basin[0].acc_year.lai += patch[0].lai * scale; } if ((command_line[0].output_flags.monthly == 1) && (command_line[0].p != NULL )) { patch[0].acc_month.theta += patch[0].rootzone.S; patch[0].acc_month.sm_deficit += max(0.0, (patch[0].sat_deficit-patch[0].rz_storage-patch[0].unsat_storage)); patch[0].acc_month.et += (patch[0].transpiration_unsat_zone + patch[0].evaporation_surf + patch[0].exfiltration_unsat_zone + patch[0].exfiltration_sat_zone + +patch[0].transpiration_sat_zone + patch[0].evaporation); patch[0].acc_month.denitrif += patch[0].ndf.denitrif; patch[0].acc_month.nitrif += patch[0].ndf.sminn_to_nitrate; patch[0].acc_month.mineralized += patch[0].ndf.net_mineralized; patch[0].acc_month.uptake += patch[0].ndf.sminn_to_npool; patch[0].acc_month.DON_loss += (patch[0].soil_ns.DON_Qout_total - patch[0].soil_ns.DON_Qout_total); patch[0].acc_month.DOC_loss += (patch[0].soil_cs.DOC_Qout_total - patch[0].soil_cs.DOC_Qout_total); patch[0].acc_month.psn += patch[0].net_plant_psn; patch[0].acc_month.snowpack = max(patch[0].snowpack.water_equivalent_depth, patch[0].acc_month.snowpack); patch[0].acc_month.lai = max(patch[0].acc_month.lai, patch[0].lai); patch[0].acc_month.leach += (patch[0].soil_ns.leach + patch[0].surface_ns_leach); patch[0].acc_month.length += 1; } if ((command_line[0].output_flags.yearly == 1) && (command_line[0].p != NULL )) { patch[0].acc_year.length += 1; if ((patch[0].sat_deficit - patch[0].unsat_storage) > command_line[0].thresholds[SATDEF]) patch[0].acc_year.num_threshold += 1; patch[0].acc_year.theta += patch[0].rootzone.S; patch[0].acc_year.denitrif += patch[0].ndf.denitrif; patch[0].acc_year.nitrif += patch[0].ndf.sminn_to_nitrate; patch[0].acc_year.mineralized += patch[0].ndf.net_mineralized; patch[0].acc_year.uptake += patch[0].ndf.sminn_to_npool; patch[0].acc_year.leach += (patch[0].soil_ns.leach + patch[0].surface_ns_leach); patch[0].acc_year.DON_loss += (patch[0].soil_ns.DON_Qout_total - patch[0].soil_ns.DON_Qout_total); patch[0].acc_year.DOC_loss += (patch[0].soil_cs.DOC_Qout_total - patch[0].soil_cs.DOC_Qout_total); patch[0].acc_year.streamflow += patch[0].streamflow; patch[0].acc_year.Qout_total += patch[0].Qout_total; patch[0].acc_year.Qin_total += patch[0].Qin_total; patch[0].acc_year.psn += patch[0].net_plant_psn; patch[0].acc_year.PET += (patch[0].PE + patch[0].PET); patch[0].acc_year.burn += patch[0].burn; patch[0].acc_year.potential_recharge += patch[0].rain_throughfall; patch[0].acc_year.potential_recharge_wyd += patch[0].rain_throughfall * round(patch[0].acc_year.length); patch[0].acc_year.recharge += patch[0].recharge; patch[0].acc_year.recharge_wyd += patch[0].recharge * round(patch[0].acc_year.length); if ((patch[0].snowpack.water_equivalent_depth == 0) && (patch[0].acc_year.snowpack > 0)) { if (patch[0].acc_year.meltday < patch[0].acc_year.peaksweday) patch[0].acc_year.meltday = round( patch[0].acc_year.length); } if (patch[0].snowpack.water_equivalent_depth > patch[0].acc_year.snowpack) { patch[0].acc_year.peaksweday = round( patch[0].acc_year.length); } patch[0].acc_year.snowpack = max(patch[0].snowpack.water_equivalent_depth, patch[0].acc_year.snowpack); /* transpiration water stress computations */ tmp = (patch[0].transpiration_unsat_zone + patch[0].exfiltration_unsat_zone + patch[0].exfiltration_sat_zone + patch[0].evaporation_surf + +patch[0].transpiration_sat_zone + patch[0].evaporation); patch[0].acc_year.et += tmp; tmp = (patch[0].transpiration_unsat_zone + patch[0].transpiration_sat_zone); patch[0].acc_year.trans += tmp; patch[0].acc_year.day7trans = (tmp / 14 + 13 / 14 * patch[0].acc_year.day7trans); patch[0].acc_year.day7pet = (patch[0].PET + patch[0].PE) / 14 + 13 / 14 * patch[0].acc_year.day7pet; if (patch[0].acc_year.day7pet > patch[0].acc_year.maxpet) { patch[0].acc_year.maxpet = patch[0].acc_year.day7pet; patch[0].acc_year.rec_pet_wyd = 0; patch[0].acc_year.max_pet_wyd = patch[0].acc_year.wyd; } if ((patch[0].acc_year.day7trans > patch[0].acc_year.maxtrans)) { patch[0].acc_year.maxtrans = patch[0].acc_year.day7trans; patch[0].acc_year.rec_wyd = 0; } if ((patch[0].acc_year.rec_wyd == 0) && (patch[0].acc_year.day7trans < patch[0].acc_year.maxtrans * 0.5)) { patch[0].acc_year.rec_wyd = patch[0].acc_year.wyd; } if ((patch[0].acc_year.rec_pet_wyd == 0) && (patch[0].acc_year.day7pet < patch[0].acc_year.maxpet * 0.5)) { patch[0].acc_year.rec_pet_wyd = patch[0].acc_year.wyd; } tmp = (patch[0].transpiration_unsat_zone + patch[0].exfiltration_unsat_zone + patch[0].exfiltration_sat_zone + patch[0].evaporation_surf + +patch[0].transpiration_sat_zone + patch[0].evaporation); if ((patch[0].PET + patch[0].PE - tmp) > patch[0].acc_year.sm_deficit) patch[0].acc_year.sm_deficit = (patch[0].PET + patch[0].PE - tmp); patch[0].acc_year.lai = max(patch[0].acc_year.lai, patch[0].lai); tmp = patch[0].sat_deficit - patch[0].unsat_storage - patch[0].rz_storage; if (tmp <= 0) patch[0].acc_year.ndays_sat += 1; if (patch[0].rootzone.S > 0.7) patch[0].acc_year.ndays_sat70 += 1; tmp = max(0.0, (patch[0].rootzone.field_capacity/patch[0].rootzone.potential_sat - patch[0].wilting_point*patch[0].soil_defaults[0][0].porosity_0)) / 2.0 + patch[0].wilting_point * patch[0].soil_defaults[0][0].porosity_0; if ((patch[0].rootzone.S < tmp) && (current_date.month < 10) && (patch[0].acc_year.midsm_wyd == 0) && (patch[0].snowpack.water_equivalent_depth <= 0.0)) patch[0].acc_year.midsm_wyd = patch[0].acc_year.wyd; patch[0].acc_year.wyd = patch[0].acc_year.wyd + 1; } } basin_return_flow += (patch[0].return_flow) * patch[0].area; } /* end i */ } /* end k */ basin_outflow /= basin_area; preday_basin_rz_storage /= basin_area; preday_basin_unsat_storage /= basin_area; preday_basin_detention_store /= basin_area; preday_basin_sat_deficit /= basin_area; basin_rz_storage /= basin_area; basin_unsat_storage /= basin_area; basin_detention_store /= basin_area; basin_sat_deficit /= basin_area; water_balance = preday_basin_rz_storage + preday_basin_unsat_storage + preday_basin_detention_store - preday_basin_sat_deficit - (basin_rz_storage + basin_unsat_storage + basin_detention_store - basin_sat_deficit) - basin_outflow; if (abs(water_balance) > ZERO) printf("\n Water Balance is %lf for %ld %ld %ld", water_balance, current_date.day, current_date.month, current_date.year); if ((command_line[0].output_flags.yearly == 1) && (command_line[0].b != NULL )) { if (basin_outflow <= command_line[0].thresholds[STREAMFLOW]) basin[0].acc_year.num_threshold += 1; } return; } /*end compute_subsurface_routing.c*/