void update_drainage_road( 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_N_leached(int, double, double, double, double, double, double, double, double, double, double, double, double, double *); double compute_varbased_flow( int, double, double, double, double, double *); double recompute_gamma( struct patch_object *, double); double compute_varbased_returnflow( double, double, double, struct litter_object *); /*--------------------------------------------------------------*/ /* Local variable definition. */ /*--------------------------------------------------------------*/ int i, j,k,d; double m, Ksat, return_flow; double NO3_leached_to_patch, NO3_leached_to_stream, NO3_surface_leached_to_stream; /* kg/m2 */ double NH4_leached_to_patch, NH4_leached_to_stream, NH4_surface_leached_to_stream; /* kg/m2 */ double N_leached_total; /* kg/m2 */ double DON_leached_to_patch, DON_leached_to_stream, DON_surface_leached_to_stream; /* kg/m2 */ double DON_leached_total; /* kg/m2 */ double DOC_leached_to_patch, DOC_leached_to_stream, DOC_surface_leached_to_stream; /* kg/m2 */ double DOC_leached_total; /* kg/m2 */ double route_to_stream; /* m3 */ double route_to_patch; /* m3 */ double road_int_depth; /* m of H2O */ double available_sat_water, route_total; /* m3 */ double Qin, Qout, Qstr_total; /* m */ double total_gamma, percent_loss; double Nin, Nout; /* kg/m2 */ double percent_tobe_routed; struct patch_object *neigh; DOC_leached_to_patch = 0.0; DOC_leached_to_stream = 0.0; DOC_surface_leached_to_stream = 0.0; DON_leached_to_patch = 0.0; DON_leached_to_stream = 0.0; DON_surface_leached_to_stream = 0.0; NH4_leached_to_patch = 0.0; NH4_leached_to_stream = 0.0; NH4_surface_leached_to_stream = 0.0; NO3_leached_to_patch = 0.0; NO3_leached_to_stream = 0.0; NO3_surface_leached_to_stream = 0.0; route_to_stream = 0.0; route_to_patch = 0.0; return_flow=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); /*--------------------------------------------------------------*/ /* 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 */ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /* calculate water_equivalent depth of road */ /*--------------------------------------------------------------*/ road_int_depth = compute_delta_water( 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, patch[0].road_cut_depth, 0.0); if (road_int_depth > patch[0].sat_deficit) { /*------------------------------------------------------------*/ /* calculate amuount of water output to patches */ /*-----------------------------------------------------------*/ route_to_patch = time_int * compute_varbased_flow( patch[0].num_soil_intervals, patch[0].std * command_line[0].std_scale, road_int_depth, total_gamma, patch[0].soil_defaults[0][0].interval_size, patch[0].transmissivity_profile); /*-----------------------------------------------------------*/ /* calculate amuount of water output to stream */ /*-----------------------------------------------------------*/ route_to_stream = time_int * compute_varbased_flow( patch[0].num_soil_intervals, patch[0].std * command_line[0].std_scale, patch[0].sat_deficit, total_gamma, patch[0].soil_defaults[0][0].interval_size, patch[0].transmissivity_profile) - route_to_patch; if (route_to_patch < 0.0) route_to_patch = 0.0; if (route_to_stream < 0.0) route_to_stream = 0.0; if ((route_to_stream + route_to_patch) > available_sat_water) { route_to_patch *= (available_sat_water)/(route_to_patch + route_to_stream); route_to_stream *= (available_sat_water)/(route_to_patch + route_to_stream); } /*--------------------------------------------------------------*/ /* compute Nitrogen leaching amount */ /*--------------------------------------------------------------*/ if (command_line[0].grow_flag > 0) { NO3_leached_to_patch = compute_N_leached( verbose_flag, patch[0].soil_ns.nitrate, route_to_patch / patch[0].area, road_int_depth, 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_stream = compute_N_leached( verbose_flag, patch[0].soil_ns.nitrate, route_to_stream / 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; if (NO3_leached_to_stream < 0.0) NO3_leached_to_stream = 0.0; patch[0].soil_ns.NO3_Qout += (NO3_leached_to_patch + NO3_leached_to_stream); NH4_leached_to_patch = compute_N_leached( verbose_flag, patch[0].soil_ns.sminn, route_to_patch / patch[0].area, road_int_depth, 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_stream = compute_N_leached( verbose_flag, patch[0].soil_ns.nitrate, route_to_stream / 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; if (NH4_leached_to_stream < 0.0) NH4_leached_to_stream = 0.0; patch[0].soil_ns.NH4_Qout += (NH4_leached_to_patch + NH4_leached_to_stream); DON_leached_to_patch = compute_N_leached( verbose_flag, patch[0].soil_ns.DON, route_to_patch / patch[0].area, road_int_depth, 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_stream = compute_N_leached( verbose_flag, patch[0].soil_ns.DON, route_to_stream / 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; if (DON_leached_to_stream < 0.0) DON_leached_to_stream = 0.0; patch[0].soil_ns.DON_Qout += (DON_leached_to_patch + DON_leached_to_stream); DOC_leached_to_patch = compute_N_leached( verbose_flag, patch[0].soil_cs.DOC, route_to_patch / patch[0].area, road_int_depth, 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_stream = compute_N_leached( verbose_flag, patch[0].soil_cs.DOC, route_to_stream / 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; if (DOC_leached_to_stream < 0.0) DOC_leached_to_stream = 0.0; patch[0].soil_cs.DOC_Qout += (DOC_leached_to_patch + DOC_leached_to_stream); } patch[0].Qout += ((route_to_patch + route_to_stream) / patch[0].area); } /*--------------------------------------------------------------*/ /* if road is below the water_table - no routing to the stream */ /*--------------------------------------------------------------*/ else { route_to_stream = 0.0; route_to_patch = time_int * compute_varbased_flow( patch[0].num_soil_intervals, patch[0].std * command_line[0].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; /*--------------------------------------------------------------*/ /* compute Nitrogen leaching amount */ /*--------------------------------------------------------------*/ if (command_line[0].grow_flag > 0) { NO3_leached_to_patch = 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_stream = 0.0; patch[0].soil_ns.NO3_Qout += (NO3_leached_to_patch + NO3_leached_to_stream); NH4_leached_to_patch = 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_stream = 0.0; patch[0].soil_ns.NH4_Qout += (NH4_leached_to_patch + NH4_leached_to_stream); DON_leached_to_patch = 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_stream = 0.0; patch[0].soil_ns.DON_Qout += (DON_leached_to_patch + DON_leached_to_stream); DOC_leached_to_patch = 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_stream = 0.0; patch[0].soil_cs.DOC_Qout += (DOC_leached_to_patch + DOC_leached_to_stream); } patch[0].Qout += ((route_to_patch + route_to_stream) / 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 * command_line[0].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 */ /* lost in subsurface flow routing */ /* - note only nitrate is assumed to follow return flow */ /*--------------------------------------------------------------*/ if (command_line[0].grow_flag > 0) { Nout = compute_N_leached( verbose_flag, patch[0].soil_ns.nitrate - NO3_leached_to_patch, 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, 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, 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, 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 */ /* note we assume that this happens before return_flow losses */ /*--------------------------------------------------------------*/ 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_NO3; patch[0].surface_NO3 -= Nout; patch[0].next_stream[0].streamflow_NO3 += (Nout * patch[0].area / patch[0].next_stream[0].area); Nout = (min(1.0, (Qout/ patch[0].detention_store))) * patch[0].surface_NH4; patch[0].surface_NH4 -= Nout; patch[0].next_stream[0].streamflow_NH4 += (Nout * patch[0].area / patch[0].next_stream[0].area); Nout = (min(1.0, (Qout/ patch[0].detention_store))) * patch[0].surface_DON; patch[0].surface_DON -= Nout; patch[0].next_stream[0].streamflow_DON += (Nout * patch[0].area / patch[0].next_stream[0].area); Nout = (min(1.0, (Qout/ patch[0].detention_store))) * patch[0].surface_DOC; patch[0].surface_DOC -= Nout; patch[0].next_stream[0].streamflow_DOC += (Nout * patch[0].area / patch[0].next_stream[0].area); } patch[0].next_stream[0].streamflow += (Qout * patch[0].area / patch[0].next_stream[0].area); patch[0].detention_store -= Qout; } /*--------------------------------------------------------------*/ /* route flow to neighbours */ /* route n_leaching if grow flag specfied */ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /* routing to stream i.e. diversion routing */ /* note all surface flows go to the stream */ /*--------------------------------------------------------------*/ patch[0].next_stream[0].streamflow += (route_to_stream) / patch[0].next_stream[0].area; patch[0].next_stream[0].surface_Qin += (route_to_stream) / patch[0].next_stream[0].area; if (command_line[0].grow_flag > 0) { Nin = (DON_leached_to_stream * patch[0].area) / patch[0].next_stream[0].area; patch[0].next_stream[0].streamflow_DON += Nin; Nin = (DOC_leached_to_stream * patch[0].area) / patch[0].next_stream[0].area; patch[0].next_stream[0].streamflow_DOC += Nin; Nin = (NO3_leached_to_stream * patch[0].area) / patch[0].next_stream[0].area; patch[0].next_stream[0].streamflow_NO3 += Nin; Nin = (NH4_leached_to_stream * patch[0].area) / patch[0].next_stream[0].area; patch[0].next_stream[0].streamflow_NH4 += Nin; } /*--------------------------------------------------------------*/ /* route flow to neighbours */ /* route n_leaching if grow flag specfied */ /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ /* regular downslope routing */ /*--------------------------------------------------------------*/ 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 (command_line[0].grow_flag > 0) { Nin = (patch[0].innundation_list[d].neighbours[j].gamma * NO3_leached_to_patch * patch[0].area) / neigh[0].area; neigh[0].soil_ns.NO3_Qin += Nin; Nin = (patch[0].innundation_list[d].neighbours[j].gamma * NH4_leached_to_patch * patch[0].area) / neigh[0].area; neigh[0].soil_ns.NH4_Qin += Nin; Nin = (patch[0].innundation_list[d].neighbours[j].gamma * DON_leached_to_patch * patch[0].area) / neigh[0].area; neigh[0].soil_ns.DON_Qin += Nin; Nin = (patch[0].innundation_list[d].neighbours[j].gamma * DOC_leached_to_patch * patch[0].area) / neigh[0].area; neigh[0].soil_cs.DOC_Qin += Nin; } neigh[0].Qin += Qin; } } /*end update_drainage_road.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*/
double top_model( int verbose_flag, int grow_flag, int num_timesteps, double sen1, double sen2, double std_scale, struct command_line_object *command_line, struct basin_object *basin, struct hillslope_object *hillslope, struct zone_object **zones, struct date current_date) { /*--------------------------------------------------------------*/ /* Local Function Declarations. */ /*--------------------------------------------------------------*/ double compute_z_final( int, double, double, double, double, double); double compute_varbased_returnflow( double, double, double, struct litter_object *); 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); double compute_delta_water( int, double, double, double, double, double); /*--------------------------------------------------------------*/ /* Local variable definition. */ /*--------------------------------------------------------------*/ int i,j,k; double base_flow, total_baseflow; double mean_sat_deficit, mean_sat_deficit_z, up_flow, down_flow; /* Taehee Hwang */ double new_mean_sat_deficit, new_mean_rz_storage, new_mean_unsat_storage; /* Taehee Hwang */ double preday_mean_sat_deficit, preday_mean_unsat_storage, preday_mean_rz_storage; /* Taehee Hwang */ double mean_hillslope_lna; double new_total_litter_store, new_total_detention_store; double total_detention_store, total_litter_store; double preday_total_detention_store; double preday_total_litter_store; double effective_sat_deficit; double Q_0; double rz_drainage, unsat_drainage; /* Taehee Hwang */ double area, scale; double water_balance, total_new_return_flow; double return_flow; double mean_N_leached, mean_nitrate; double preday_sat_deficit_z, add_field_capacity; struct patch_object *patch; /*--------------------------------------------------------------*/ /* allow for iteration at sub-daily time steps */ /*--------------------------------------------------------------*/ total_baseflow = 0.0; preday_mean_sat_deficit = 0.0; preday_mean_unsat_storage = 0.0; preday_mean_rz_storage = 0.0; /* Taehee Hwang */ preday_total_detention_store = 0.0; preday_total_litter_store = 0.0; /*--------------------------------------------------------------*/ /* compute initial conditions */ /*--------------------------------------------------------------*/ for ( i=0 ; i<hillslope[0].num_zones; i++ ){ for ( j=0; j< zones[i][0].num_patches; j++ ){ patch = zones[i][0].patches[j]; preday_mean_sat_deficit += zones[i][0].patches[j][0].sat_deficit * zones[i][0].patches[j][0].area; preday_mean_unsat_storage += zones[i][0].patches[j][0].unsat_storage * zones[i][0].patches[j][0].area; preday_mean_rz_storage += zones[i][0].patches[j][0].rz_storage * zones[i][0].patches[j][0].area; /* Taehee Hwang */ preday_total_detention_store += zones[i][0].patches[j][0].detention_store * zones[i][0].patches[j][0].area; preday_total_litter_store += patch[0].litter.rain_stored * zones[i][0].patches[j][0].area; } } for ( k=0; k< num_timesteps; ++k) { mean_sat_deficit = 0.0; mean_hillslope_lna = 0.0; mean_N_leached = 0.0; mean_nitrate = 0.0; new_total_detention_store = 0.0; total_detention_store = 0.0; new_total_litter_store = 0.0; total_litter_store = 0.0; area = 0.0; /*--------------------------------------------------------------*/ /* Compute Mean Hillslope Saturation Deficit */ /*--------------------------------------------------------------*/ for ( i=0 ; i<hillslope[0].num_zones; i++ ){ for ( j=0; j< zones[i][0].num_patches; j++ ){ /*--------------------------------------------------------------*/ /* get rid of any intial return flow from infiltration excess */ /*--------------------------------------------------------------*/ patch = zones[i][0].patches[j]; return_flow = 0.0; total_detention_store += patch[0].detention_store * patch[0].area; total_litter_store += patch[0].litter.rain_stored * patch[0].area; 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; } /*------------------------------------------------------------------*/ /* Distribute excess water between transmission and rootzone layer */ /*------------------------------------------------------------------*/ /* Only transmission layer saturated (SD changed) */ else if (patch[0].sat_deficit_z > patch[0].rootzone.depth) { if (patch[0].sat_deficit - patch[0].rootzone.potential_sat - patch[0].unsat_storage < -1.0*ZERO) { patch[0].sat_deficit -= patch[0].unsat_storage; patch[0].unsat_storage = 0.0; } if (patch[0].rootzone.potential_sat - patch[0].rz_storage < -1.0*ZERO) { patch[0].unsat_storage += patch[0].rz_storage - patch[0].rootzone.potential_sat; patch[0].rz_storage = patch[0].rootzone.potential_sat; /* fully saturated */ } } else { patch[0].sat_deficit -= patch[0].unsat_storage; patch[0].unsat_storage = 0.0; } if (patch[0].detention_store > patch[0].soil_defaults[0][0].detention_store_size) { return_flow = patch[0].detention_store - patch[0].soil_defaults[0][0].detention_store_size; patch[0].detention_store -= return_flow; patch[0].return_flow += return_flow; } /*--------------------------------------------------------------*/ /* compute mean soil moisture */ /*--------------------------------------------------------------*/ mean_sat_deficit += zones[i][0].patches[j][0].sat_deficit * zones[i][0].patches[j][0].area; if (grow_flag > 0) { mean_nitrate += zones[i][0].patches[j][0].soil_ns.nitrate * zones[i][0].patches[j][0].area; } area += zones[i][0].patches[j][0].area; mean_hillslope_lna += zones[i][0].patches[j][0].lna * zones[i][0].patches[j][0].area; } } mean_sat_deficit = mean_sat_deficit / area; mean_hillslope_lna = mean_hillslope_lna / area; /*--------------------------------------------------------------*/ /* Estimate Qo - discharge when mean sat deficit = 0. */ /* Note that Ambroise suggest that this condition results */ /* in a stored water volume of infinity in the hillslope. */ /* This is only valid for certain porosity with depth */ /* functions (e.g. constant or increasing ) */ /* We use a hillslope_area of 1 since we want base_flow in */ /* m water / day. */ /*--------------------------------------------------------------*/ Q_0 = hillslope[0].aggdefs.Ksat_0 * exp( -1 * mean_hillslope_lna ) / num_timesteps; /*--------------------------------------------------------------*/ /* Compute base flow. (m/day) */ /* */ /* Use the TOPMODEL theory to estimate the base_flow */ /* Note that there is nothing that stops us applying */ /* the theory if the sat deficit is negative except */ /* that we then buy into the space above the surface of */ /* regions with negative sat deficit having non-infinite */ /* lateral transmissivity. */ /* */ /* we compute an effective sat_deficit for baseflow as */ /* 0.5 * the min of sat_def */ /* water equivalent capillary fringe height */ /* this assumes that some of the water in the cap. fringe */ /* is able to contribute to baseflow */ /* */ /* we now limit the baseflow to only remove water above */ /* maximum soil depth for all patches */ /*--------------------------------------------------------------*/ effective_sat_deficit = mean_sat_deficit - min(0.5 * mean_sat_deficit , 0.5 * hillslope[0].aggdefs.psi_air_entry * hillslope[0].aggdefs.porosity_0); base_flow = Q_0 * exp( -1 * effective_sat_deficit / ( hillslope[0].aggdefs.m)); total_baseflow += base_flow; if (grow_flag > 0) { mean_nitrate = mean_nitrate / hillslope[0].area; mean_sat_deficit_z = compute_z_final( verbose_flag, hillslope[0].aggdefs.porosity_0, hillslope[0].aggdefs.porosity_decay, hillslope[0].aggdefs.soil_depth, 0.0, -1.0 * mean_sat_deficit); mean_N_leached = compute_N_leached( verbose_flag, mean_nitrate, base_flow, mean_sat_deficit, hillslope[0].aggdefs.soil_water_cap, hillslope[0].aggdefs.m, hillslope[0].aggdefs.Ksat_0 / num_timesteps, hillslope[0].aggdefs.porosity_0, hillslope[0].aggdefs.porosity_decay, hillslope[0].aggdefs.N_decay_rate, hillslope[0].aggdefs.active_zone_z, hillslope[0].aggdefs.soil_depth, hillslope[0].aggdefs.mobile_NO3_proportion, NULL); hillslope[0].streamflow_NO3 += mean_N_leached; mean_nitrate -= hillslope[0].streamflow_NO3; } /*--------------------------------------------------------------*/ /* Adjust the mean_sat_deficit for the base_flow. */ /*--------------------------------------------------------------*/ mean_sat_deficit += base_flow; /*--------------------------------------------------------------*/ /* Estimate new actual sat_deficit of each patch based */ /* on TOPMODEL and patch m. */ /* Note that if patch m varies one should use a lna and */ /* lambda that varies. */ /*--------------------------------------------------------------*/ new_mean_sat_deficit = 0.0; new_mean_unsat_storage = 0.0; new_mean_rz_storage = 0.0; /* Taehee Hwang */ total_new_return_flow = 0.0; for ( i=0 ; i<hillslope[0].num_zones; i++ ){ for ( j=0; j < zones[i][0].num_patches; j++ ){ patch = zones[i][0].patches[j]; 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); /*--------------------------------------------------------------*/ /* adjust local sat deficit relative to mean */ /*--------------------------------------------------------------*/ patch[0].sat_deficit = mean_sat_deficit - ( patch[0].lna - mean_hillslope_lna ) * hillslope[0].aggdefs.m ; /*--------------------------------------------------------------*/ /* Hillslope redistribution will have changed the */ /* actual water table depth. */ /*--------------------------------------------------------------*/ 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].sat_deficit_z, 0.0); patch[0].field_capacity = 0.0; } else { 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 = 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); } /*--------------------------------------------------------------*/ /* 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 / num_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 / num_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 / num_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 (grow_flag > 0) { patch[0].soil_ns.nitrate = mean_nitrate; } /*--------------------------------------------------------------*/ /* compute any saturation excess flow */ /*--------------------------------------------------------------*/ 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 = 0.0; patch[0].unsat_storage = 0.0; patch[0].rz_storage = 0.0; } /*------------------------------------------------------------------*/ /* Distribute excess water between transmission and rootzone layer */ /*------------------------------------------------------------------*/ /* Only transmission layer saturated (SD changed) */ else if (patch[0].sat_deficit_z > patch[0].rootzone.depth) { if (patch[0].sat_deficit - patch[0].rootzone.potential_sat - patch[0].unsat_storage < -1.0*ZERO) { patch[0].sat_deficit -= patch[0].unsat_storage; patch[0].unsat_storage = 0.0; } if (patch[0].rootzone.potential_sat - patch[0].rz_storage < -1.0*ZERO) { patch[0].unsat_storage += patch[0].rz_storage - patch[0].rootzone.potential_sat; patch[0].rz_storage = patch[0].rootzone.potential_sat; /* fully saturated */ } } else { patch[0].sat_deficit -= patch[0].unsat_storage; /* Make sure that there is no unsat_storage */ patch[0].unsat_storage = 0.0; } if (patch[0].detention_store > patch[0].soil_defaults[0][0].detention_store_size) { return_flow = patch[0].detention_store - patch[0].soil_defaults[0][0].detention_store_size; patch[0].detention_store -= return_flow; patch[0].return_flow += return_flow; } 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 */ /*--------------------------------------------------------------*/ if ((patch[0].sat_deficit_z > preday_sat_deficit_z) && (patch[0].sat_deficit > ZERO)) { 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, preday_sat_deficit_z); patch[0].sat_deficit += add_field_capacity; if ((patch[0].sat_deficit_z > patch[0].rootzone.depth) && (preday_sat_deficit_z > patch[0].rootzone.depth)) patch[0].unsat_storage += add_field_capacity; else if ((patch[0].sat_deficit_z <= patch[0].rootzone.depth) && (preday_sat_deficit_z <= patch[0].rootzone.depth)) patch[0].rz_storage += add_field_capacity; else { patch[0].rz_storage += add_field_capacity * (patch[0].rootzone.depth - preday_sat_deficit_z) / (patch[0].sat_deficit_z - preday_sat_deficit_z); patch[0].unsat_storage += add_field_capacity * (patch[0].sat_deficit_z - patch[0].rootzone.depth) / (patch[0].sat_deficit_z - preday_sat_deficit_z); } } /* ---------------------------------------------- */ /* Final rootzone saturation calculation */ /* ---------------------------------------------- */ 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); total_new_return_flow += patch[0].return_flow * patch[0].area; new_mean_sat_deficit += patch[0].sat_deficit * patch[0].area; new_mean_unsat_storage += patch[0].unsat_storage * patch[0].area; new_mean_rz_storage += patch[0].rz_storage * patch[0].area; /* Taehee Hwang */ new_total_detention_store += patch[0].detention_store * patch[0].area; new_total_litter_store += patch[0].litter.rain_stored * patch[0].area; patch[0].streamflow = patch[0].return_flow; 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); } /* end patches */ } /* end zones */ } /* end time step iterations */ /* for now water balance cannot be computed for multiple */ if (total_detention_store < ZERO) water_balance = ( -new_mean_sat_deficit + preday_mean_sat_deficit + new_mean_unsat_storage + new_mean_rz_storage + new_total_litter_store - preday_total_litter_store - preday_mean_unsat_storage - preday_mean_rz_storage + total_new_return_flow - preday_total_detention_store + new_total_detention_store) / hillslope[0].area + total_baseflow; else water_balance = 0.0; if ((water_balance > 0.0000001) || (water_balance < -0.0000001)) printf("\n Hill Water Balance is %12.8f on %d %d %d for Hill %d base %lf return %lf sd %lf %lf un %lf %lf rz %lf %lf litter %lf %lf det %lf %lf\n", water_balance, current_date.day, current_date.month, current_date.year, hillslope[0].ID, total_baseflow, total_new_return_flow /hillslope[0].area, preday_mean_sat_deficit /hillslope[0].area , new_mean_sat_deficit /hillslope[0].area, preday_mean_unsat_storage /hillslope[0].area , new_mean_unsat_storage /hillslope[0].area, preday_mean_rz_storage /hillslope[0].area , new_mean_rz_storage /hillslope[0].area, preday_total_litter_store /hillslope[0].area , new_total_litter_store /hillslope[0].area, preday_total_detention_store /hillslope[0].area , new_total_detention_store / hillslope[0].area ); /*--------------------------------------------------------------*/ /* now that redistribution is complete update output variables */ /*--------------------------------------------------------------*/ for ( i=0 ; i<hillslope[0].num_zones; i++ ){ for ( j=0; j < zones[i][0].num_patches; j++ ){ patch = zones[i][0].patches[j]; 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].return_flow) * scale; basin[0].acc_month.et += (patch[0].transpiration_unsat_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.DOC_loss += patch[0].cdf.total_DOC_loss * scale; basin[0].acc_month.DON_loss+= patch[0].ndf.total_DON_loss * 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.length += (1*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*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.DOC_loss += patch[0].cdf.total_DOC_loss * scale; basin[0].acc_year.DON_loss += patch[0].ndf.total_DON_loss * scale; basin[0].acc_year.psn += patch[0].net_plant_psn * scale; basin[0].acc_year.et += (patch[0].evaporation + 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.sm_deficit += (patch[0].sat_deficit - patch[0].unsat_storage); if (patch[0].sat_deficit > ZERO) patch[0].acc_month.theta += patch[0].unsat_storage / patch[0].sat_deficit; else patch[0].acc_month.theta = 1.0; patch[0].acc_month.et += (patch[0].transpiration_unsat_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.DOC_loss += patch[0].cdf.total_DOC_loss; patch[0].acc_month.DON_loss += patch[0].ndf.total_DON_loss; 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.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 > ZERO) patch[0].acc_year.theta += patch[0].unsat_storage / patch[0].sat_deficit; else patch[0].acc_year.theta = 1.0; 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.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.DOC_loss += patch[0].cdf.total_DOC_loss; patch[0].acc_year.DON_loss += patch[0].ndf.total_DON_loss; patch[0].acc_year.burn += patch[0].burn; patch[0].acc_year.psn += patch[0].net_plant_psn; patch[0].acc_year.snowpack = max( patch[0].snowpack.water_equivalent_depth, patch[0].acc_year.snowpack); patch[0].acc_year.et += (patch[0].transpiration_unsat_zone + patch[0].transpiration_sat_zone + patch[0].evaporation); patch[0].acc_year.lai = max(patch[0].acc_year.lai, patch[0].lai); } } } basin[0].acc_month.stream_NO3 += (hillslope[0].streamflow_NO3 * hillslope[0].area / basin[0].area); basin[0].acc_year.stream_NO3 += (hillslope[0].streamflow_NO3 * hillslope[0].area / basin[0].area); basin[0].acc_month.streamflow += (total_baseflow * hillslope[0].area / basin[0].area); basin[0].acc_year.streamflow += (total_baseflow * hillslope[0].area / basin[0].area); return(total_baseflow); } /*end top_model.c*/