def calculate_yearly_load(load_cell, year_start, year_end): ''' Calculates a yearly time series from year_start to year_end (should be integers) ''' #year_start = int(load_cell[0][0]) #year_end = int(load_cell[-1][0]) load_yearly = [] # The value attributed to the first year is the first available value #load_yearly.append(load_cell[0]) for year in range(year_start, year_end+1): val = interpolate_list.calculate(year, load_cell, extrapol=1) load_yearly.append([year, val[1]]) return load_yearly
def calculate_subgrid_hydro(lsteady,params,species,timeint,yearstart,yearend,runoff_in,\ discharge_in,volume_in,water_area_in,\ depth_in,width_in,volume_fp_in,vel_in,depth_fp_in,\ llake,llakeout,lendolake,args_strahler_cell=None): # Get strahler characteristics if not (args_strahler_cell == None): riverarea = args_strahler_cell.get_val("riverarea") riverlength = args_strahler_cell.get_val("riverlength") slope = args_strahler_cell.get_val("slope") else: riverarea = params.riverarea riverlength = params.riverlength slope = [params.slope] * params.norder # construct list of times with startyear, endyear and timesteps timeint = [] if (lsteady): # only for steady state calculation # steady state calculation is performed on start time. timeint.append(params.starttime) else: time = yearstart while time < yearend: timeint.append(time) time += params.timestep timeint.append(yearend) runoff_cell = [] discharge_cell = [] water_area_cell = [] volume_cell = [] depth_cell = [] dvoldt_cell = [] vel_cell = [] volume_fp_cell = [] depth_fp_cell = [] dvoldt_fp_cell = [] # volume at timestep 0 (= startyear) vol_t = interpolate_list.calculate(timeint[0], volume_in, extrapol=1) #for calculation of dvoldt vol_prev = vol_t vol_next = vol_t # volume of floodplain at timestep 0 (=startyear) vol_fp_t = interpolate_list.calculate( timeint[0], volume_fp_in, extrapol=1) #for calculation of dvoldt vol_fp_prev = vol_fp_t vol_fp_next = vol_fp_t # iterate through list of times (from startyear to endyear, with timesteps params.timestep) for time in timeint: runoff_cell.append( interpolate_list.calculate(time, runoff_in, extrapol=1)) discharge_cell.append( interpolate_list.calculate(time, discharge_in, extrapol=1)) water_area_cell.append( interpolate_list.calculate(time, water_area_in, extrapol=1)) volume_cell.append( interpolate_list.calculate(time, volume_in, extrapol=1)) depth_cell.append( interpolate_list.calculate(time, depth_in, extrapol=1)) vel_cell.append(interpolate_list.calculate(time, vel_in, extrapol=1)) #LV 14-02-2018 volume_fp_cell.append( interpolate_list.calculate(time, volume_fp_in, extrapol=1)) depth_fp_cell.append( interpolate_list.calculate(time, depth_fp_in, extrapol=1)) # Calculation of dvoldt dvoldt = 0.0 # no dvoldt at steady state if (lsteady): dvoldt_cell.append([time, 0.0]) else: vol_next = interpolate_list.calculate(time + params.timestep, volume_in, extrapol=1) dvoldt = (vol_next[-1] - vol_prev[-1]) / 2 * params.timestep dvoldt_cell.append([time, dvoldt]) vol_prev = vol_t vol_t = vol_next # Calculation of dvoldt in floodplain dvoldt_fp = 0.0 # no dvoldt in floodplain at steady state if (lsteady): dvoldt_fp_cell.append([time, 0.0]) else: vol_fp_next = interpolate_list.calculate(time + params.timestep, volume_fp_in, extrapol=1) dvoldt_fp = (vol_fp_next[-1] - vol_fp_prev[-1]) / 2 * params.timestep dvoldt_fp_cell.append([time, dvoldt_fp]) vol_fp_prev = vol_fp_t vol_fp_t = vol_fp_next # Calculate the hydrological properties for the lower Strahler orders Q0 = [] Q = [] for item in range(len(timeint)): # Q zero order in m3/s,area in km2, runoff is in mm/yr, so conversion of 1000.0 runoff_local = max(0.0, 1000 * runoff_cell[item][1] / year2second) Q0.append(params.A0 * runoff_local) # Q for all streams in m3/s Q.append([]) for iorder in range(params.norder): Q[-1].append(riverarea[iorder] * runoff_local) # Determine the flux at the midpoint of the stream section [m3/s]. Qmid = [] depth = [] dvoldt = [] width = [] vel = [] volume = [] volume_fp = [] depth_fp = [] dvoldt_fp = [] vol_t = [None] * params.norder vol_prev = [None] * params.norder vol_next = [None] * params.norder Qmid_next = [None] * params.norder for item in range(len(timeint)): depth.append([]) dvoldt.append([]) width.append([]) vel.append([]) #LV 14-02-2018 Qmid.append([]) #for one stream only volume.append([]) #for one stream only volume_fp.append([]) depth_fp.append([]) dvoldt_fp.append([]) # If the cell is a lake, set everything to zero, else calculate hydrology in small streams # LV added 21-02-2017 if (llake): for iorder in range(params.norder): depth[-1].append(0.) dvoldt[-1].append(0.) width[-1].append(0.) vel[-1].append(0.) #LV 14-02-2018 Qmid[-1].append(0.) volume[-1].append(0.) else: if (item == 0): #Qmid at 1st time step Qmid[-1].append(Q0[item] + 0.5 * Q[item][0]) for iorder in range(1, params.norder): Qmid[-1].append(Q[item][iorder - 1] + 0.5 * Q[item][iorder]) else: for iorder in range(0, params.norder): Qmid[-1].append(Qmid_next[iorder]) # Calculate Qmid at next time step if (item + 1 < len(timeint)): Qmid_next[0] = Q0[item + 1] + 0.5 * Q[item + 1][0] for iorder in range(1, params.norder): Qmid_next[iorder] = (Q[item + 1][iorder - 1] + 0.5 * Q[item + 1][iorder]) for iorder in range(params.norder): # Stream width and depth for each order [m] and volume in m3. if (Qmid[item][iorder] < 0.0): print("Qmid is negative: ", Qmid[item][iorder], " Runoff is: ", runoff_local) print( "***********************************************************" ) width[-1].append(params.width_factor * (Qmid[item][iorder]**params.width_exponent)) depth[-1].append(params.depth_factor * (Qmid[item][iorder]**params.depth_exponent)) if (item == 0): #volume at 1st time step vol_t[iorder] = params.width_factor * (Qmid[item][iorder]**params.width_exponent)\ * params.depth_factor * (Qmid[item][iorder]**params.depth_exponent)\ * params.riverlength[iorder] * 1000. volume[-1].append(vol_t[iorder]) if (params.lmanning): #LV 01-03-2018 vel[-1].append(params.manning_ks * (depth[-1][-1]**(2. / 3.)) * (slope[iorder]**0.5)) else: wetarea = (params.depth_factor * (Qmid[item][iorder]**params.depth_exponent)\ * params.width_factor * (Qmid[item][iorder]**params.width_exponent)) if (wetarea > 0.): vel[-1].append(Qmid[item][iorder] / wetarea) #LV 14-02-2018 #print('Qmid[item][iorder]=', Qmid[item][iorder]) #print('wetarea=', wetarea) #print('vel=', vel[-1][-1]*3600) else: vel[-1].append(0.) # Calculate dvoldt if (lsteady): dvoldt[-1].append(0.0) else: if (item + 1 < len(timeint)): # Calculate volume at next time step vol_next[iorder] = params.width_factor * ((Qmid_next[iorder]/params.number_of_rivers[iorder])**params.width_exponent)\ * params.depth_factor * ((Qmid_next[iorder]/params.number_of_rivers[iorder])**params.depth_exponent)\ * params.riverlength[iorder] * 1000. dvoldt_i = (vol_next[iorder] - vol_t[iorder]) / params.timestep else: dvoldt_i = (vol_t[iorder] - vol_prev[iorder]) / params.timestep dvoldt[-1].append(dvoldt_i) vol_prev[iorder] = vol_t[iorder] vol_t[iorder] = vol_next[iorder] # Conversion of Qmid from m3/s to km3/yr and volume from m3 to km3 for iorder in range(params.norder): Qmid[-1][iorder] *= year2second * 1.0e-9 volume[-1][iorder] *= 1.0e-9 dvoldt[-1][iorder] *= 1.0e-9 # from m/s to km/yr vel[-1][iorder] *= year2second * 1.0e-3 # floodplains are only available for main stream volume_fp[item] = volume_fp_cell[item][-1] depth_fp[item] = depth_fp_cell[item][-1] dvoldt_fp[item] = dvoldt_fp_cell[item][-1] for iorder in range(params.norder): # Replace properties of sixth order streams by information of PCRGLOBWB if (iorder == params.norder - 1): for item in range(len(timeint)): if (llake): #LV 29-11-2017 width[item][iorder] = math.pow(water_area_cell[item][-1], 0.5) else: width[item][iorder] = width_in Qmid[item][iorder] = discharge_cell[item][-1] volume[item][iorder] = volume_cell[item][-1] depth[item][iorder] = depth_cell[item][-1] dvoldt[item][iorder] = dvoldt_cell[item][-1] vel[item][iorder] = vel_cell[item][-1] return Qmid, volume, depth, width, vel, dvoldt, volume_fp, depth_fp, dvoldt_fp
def calculate_cell(lsteady,lock,icell,params,species,proc,sources,tmpdir,next_cell,\ yearstart,yearend,timeperiod,runoff_in,load_src,temperature_in,globrad_in,\ discharge_in,volume_in,water_area_in,depth_in,width_in,slope,volume_fp_in,depth_fp_in,vel_in,low_veg_fr,high_veg_fr,\ llake,llakeout,lendolake,args_strahler_cell=None): ''' Calculates all processes in the subgrid in all stream orders ''' print("icell " + str(icell)) timeint = [] if (lsteady): # Steady state calculation is perfomed on starttime timeint.append(params.starttime) else: # Make a list of all the time steps that we want to keep in years time = yearstart while time < yearend: timeint.append(time) time += params.timestep timeint.append(yearend) # Get strahler characteristics if not (args_strahler_cell == None): load_distribution = args_strahler_cell.get_val("load_distribution") flowpath_distribution = args_strahler_cell.get_val( "flowpath_distribution") riverlength = args_strahler_cell.get_val("riverlength") number_of_rivers = args_strahler_cell.get_val("number_of_rivers") else: load_distribution = params.load_distribution flowpath_distribution = params.flowpath_distribution riverlength = params.riverlength number_of_rivers = params.number_of_rivers # initialize load lists load_out = [] load_in = [] # initialize file pointer fp_in = None # initialize arguments arguments = make_args.do() length_spec = len(species) # For each time point interpolate runoff, temperature and loads for all the sources (values in main channel) Qmid,volume,depth,width,vel,dvoldt,volume_fp,depth_fp,dvoldt_fp = calculate_subgrid_hydro.calculate_subgrid_hydro(lsteady,params,species,\ timeint,yearstart,yearend,runoff_in,discharge_in,volume_in,water_area_in,\ depth_in,width_in,volume_fp_in,vel_in,depth_fp_in,llake,\ llakeout,lendolake,args_strahler_cell=args_strahler_cell) # Get the previous load data_prev_period = [] if (lsteady): for iorder in range(params.norder): data_prev_period.append(make_y0.make_y0(params, species)) # for floodplain if (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): data_prev_period[-1].extend(make_y0.make_y0(params, species)) else: data_prev_period = [] fp_in = open( os.path.join(tmpdir, str(icell) + "_" + str(timeperiod - 1) + ".pkl"), "rb") for line in general_func.pickleLoader(fp_in): # Remove the time data_prev_period.append(line[1:]) fp_in.close() # Initialize budgets if (params.lbudget): xbud = general_func.initialize_budget(params, species, proc) # Output list of cell: [[time0,src0, ..., srcn],[time1,src0, ..., srcn],....,[time100,src0, ..., srcn]] load_src_cell = [] temperature_cell = [] globrad_cell = [] high_veg_fr_cell = [] low_veg_fr_cell = [] for time in timeint: load_src_cell.append( interpolate_list.calculate(time, load_src[0], extrapol=1)) for isrc in range(1, len(sources)): val = interpolate_list.calculate(time, load_src[isrc], extrapol=1) load_src_cell[-1].append(val[1]) temperature_cell.append( interpolate_list.calculate(time, temperature_in, extrapol=1)) globrad_cell.append( interpolate_list.calculate(time, globrad_in, extrapol=1)) high_veg_fr_cell.append( interpolate_list.calculate(time, high_veg_fr, extrapol=1)) low_veg_fr_cell.append( interpolate_list.calculate(time, low_veg_fr, extrapol=1)) # Correct air temperature above freezing as a proxy for water temperature temperature_cell[-1][1] = max(0.0, temperature_cell[-1][1]) # Read the load from other cells in Mmol/yr load_other_stream = [] linput_other_stream = False if (os.path.isfile( os.path.join(tmpdir, "load_" + str(icell) + "_" + str(timeperiod) + ".pkl"))): # Read the load fp_in = open( os.path.join(tmpdir, "load_" + str(icell) + "_" + str(timeperiod) + ".pkl"), "rb") for line in general_func.pickleLoader(fp_in): load_other_stream.append(line) linput_other_stream = True fp_in.close() # Open output file for concentration and load at the end of the time period fp_out = open( os.path.join(tmpdir, str(icell) + "_" + str(timeperiod) + ".pkl"), "wb") fp_conc = open( os.path.join(tmpdir, "conc_" + str(icell) + "_" + str(timeperiod) + ".pkl"), "wb") # filepointer for the cell budget pkl fp_bud = None if (params.lbudget == 1): fp_bud = open( os.path.join( tmpdir, "budget_" + str(icell) + "_" + str(timeperiod) + ".pkl"), "wb") # filepointer for the cell argument list pkl fp_args = None if (params.largs == 1): fp_args = open( os.path.join( tmpdir, "arguments_" + str(icell) + "_" + str(timeperiod) + ".pkl"), "wb") # Solve the system for each Strahler order load_out = [] for iorder in range(params.norder): if (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): floodplain_arguments = deepcopy(arguments) # Determine the load for this Strahler order load = [] srcload = [] upstrload = [] # Take the local load from the cell (load_cell) and put the direct load # to the streams of this iorder in load array. # Load: [[time0,spec0, ..., specn],[time1,spec0, ..., specn],....,[time100,spec0, ..., specn]] dt = 0. #LV 19-11-2018 for item in range(len(timeint)): if (item > 0): dt = timeint[item] - timeint[item - 1] # Start with time. load.append([load_src_cell[item][0]]) srcload.append([load_src_cell[item][0]]) upstrload.append([load_src_cell[item][0]]) # Initialize loads of all species to zero - modif LV 22-07-2016 for j in range(length_spec): load[-1].append(0.0) srcload[-1].append(0.0) if iorder == params.norder - 1 and params.lfloodplains == 1: load[-1].append(0.0) srcload[-1].append(0.0) upstrload[-1].append(0.0) # Calculate loads of species, depending on sources and order # If the cell is a lake, no small orders if (iorder <= params.norder - 1) and (not llake): # LV added 21-02-2017 for isrc in range(len(sources)): for j in range(len(species)): specname = species[j].get_name() if (('fr_' + specname) in sources[isrc].get_attrib()): if ('orders' in sources[isrc].get_attrib()): try: minorder = int( sources[isrc].get_val('orders')) - 1 except (ValueError): minorder = sources[isrc].get_val('orders') try: dummy_bool = (iorder >= (minorder)) except (TypeError): dummy_bool = (minorder == 'floodplain') if dummy_bool: # Apply fraction load_spec = load_src_cell[item][ isrc + 1] * sources[isrc].get_val('fr_' + specname) if load_spec is not np.ma.masked: # If cell isn't a lake, apply order distribution if (minorder == 0): load_spec *= params.load_distribution[ iorder] load[item][j + 1] += load_spec if minorder != 'floodplain': load_spec *= params.flowpath_distribution[ minorder - 1][iorder] load[item][j + 1] += load_spec if (iorder == params.norder - 1) and ( params.lfloodplains == 1) and (minorder == 'floodplain'): load[item][j + 1 + len(species)] += load_spec if (params.lbudget) and (dt > 0.): general_func.add_budget_load( xbud, iorder, j, "load_src", load_spec * dt) if (iorder == params.norder - 1) and ( params.lfloodplains == 1) and (minorder == 'floodplain'): general_func.add_budget_load( xbud, iorder + 1, j, "load_src", load_spec * dt) elif (iorder == params.norder - 1) and (llake): # LV added 21-02-2017 for isrc in range(len(sources)): for j in range(len(species)): specname = species[j].get_name() if (('fr_' + specname) in sources[isrc].get_attrib()): if ('orders' in sources[isrc].get_attrib()): try: minorder = int( sources[isrc].get_val('orders')) - 1 except (ValueError): minorder = sources[isrc].get_val('orders') try: dummy_bool = (iorder >= (minorder)) except (TypeError): dummy_bool = (minorder == 'floodplain') if dummy_bool: load_spec = load_src_cell[item][ isrc + 1] * sources[isrc].get_val('fr_' + specname) if np.isnan(load_spec ) or type(load_spec) != np.float64: load_spec = 0 if (iorder == params.norder - 1) and ( params.lfloodplains == 1) and (minorder == 'floodplain'): load[item][j + 1 + len(species)] += load_spec general_func.add_budget_load( xbud, iorder + 1, j, "load_src", load_spec * dt) else: load[item][j + 1] += load_spec general_func.add_budget_load( xbud, iorder, j, "load_src", load_spec * dt) # Add all the output of the lower order Strahler to the list if not (llake): # LV added 21-02-2017 for i in range(iorder): for item in range(len(timeint)): for j in range(length_spec): try: outflow1 = flowpath_distribution[i][ iorder] * load_out[i][item][j] * dt except (FloatingPointError): outflow1 = 0. try: load[item][j + 1] += flowpath_distribution[i][ iorder] * load_out[i][item][j] except (FloatingPointError): load[item][j + 1] += 0. if (params.lbudget) and (dt > 0.): general_func.add_budget_load( xbud, iorder, j, "load_hw", outflow1) # Add all the output of the other streams (only sixth order) if (linput_other_stream and (iorder == params.norder - 1)): for item in range(len(timeint)): for j in range(length_spec): load[item][j + 1] += load_other_stream[item][j] if (params.lbudget) and (dt > 0.): try: outflow2 = load_other_stream[item][j] * dt except (FloatingPointError): outflow2 = 0. general_func.add_budget_load(xbud, iorder, j, "load_up", outflow2) # Take amounts for iorder out of data_prev_period to proceed. y0 = [] for i in range(len(data_prev_period[iorder])): try: y0.append(data_prev_period[iorder][i] / number_of_rivers[iorder]) except (FloatingPointError): y0.append(0.) #y0 = np.divide(data_prev_period[iorder], number_of_rivers[iorder]).tolist() if (params.lfloodplains == 1) and (iorder == params.norder - 1) and ( llake == False) and (not len(y0) == 2 * len(species)): for i in range(len(data_prev_period[iorder + 1])): try: y0.extend([ data_prev_period[iorder + 1][i] / number_of_rivers[iorder] ]) except (FloatingPointError): y0.extend([0.]) except: print('i=', i) print('data_prev_period[iorder+1]=', data_prev_period[iorder + 1]) #y0.extend(np.divide(data_prev_period[iorder+1], number_of_rivers[iorder]).tolist()) # Add load to load_out for this order. load_out.append([]) if (lsteady): istart = 0 else: # Fill first element of load_out. Is not used. load_out[-1] = [len(y0) * [0.0]] istart = 1 outdict = None # dictionnary with outputs from odeint for item in range(istart, len(timeint)): # Make time range for this run timerange = [timeint[item - 1], timeint[item]] dt = timeint[item] - timeint[item - 1] # LV 28-11-2017 - Determine whether it's an endorheic water body # Other lake/reservoir cells are calculated as rivers if (iorder == params.norder - 1): if (llake): # This cell is a lake/reservoir if (lendolake): # Retention is set to 1.0. So nothing is in the system. load_out[-1].append(len(load[item][1:]) * [0.0]) for item1 in range(len(Y[-1])): Y[-1][item1] = 0.0 # Set y0 for the next small timestep y0 = deepcopy(Y[-1]) # Save total load (no load out) if (params.lbudget) and (dt > 0.): for ispec in range(len(species)): general_func.add_budget_load( xbud, iorder, ispec, "loadIN", load[item][ispec + 1] * dt) continue if (depth[item][iorder] == 0.0 ) or volume[item][iorder] < params.minimal_watervolume or Qmid[ item][iorder] < 1e-6: # There is no water volume, so skip this calculation. load_out[-1].append(list(map(positive, load[item][1:]))) Y = [[]] for item1 in range(len(y0)): Y[-1].append(0.0) Y = np.array(Y) # Set y0 for the next small timestep y0 = deepcopy(Y[-1]) # Save total load (in and out) if (params.lbudget) and (dt > 0.): for ispec in range(len(species)): general_func.add_budget_load( xbud, iorder, ispec, "loadIN", load[item][ispec + 1] * dt) general_func.add_budget_load( xbud, iorder, ispec, "loadOUT", load_out[-1][item][ispec] * dt) continue arguments.set_val( "temperature", temperature_cell[item][-1] + params.tempcorrection) arguments.set_val("windspeed", params.windspeed) arguments.set_val("globrad", globrad_cell[item][-1]) arguments.set_val("dvoldt", dvoldt[item][iorder]) arguments.set_val("vol", volume[item][iorder]) arguments.set_val("width", width[item][iorder]) arguments.set_val("slope", slope * 1e-5) arguments.set_val("discharge", Qmid[item][iorder]) arguments.set_val("residence_time", arguments.get_val("vol") / Qmid[item][iorder]) arguments.set_val( "area", arguments.get_val("vol") / (depth[item][iorder] * 1e-3)) arguments.set_val("depth", depth[item][iorder]) arguments.set_val("length", (arguments.get_val("area") * 1e6) / width[item][iorder]) arguments.set_val("icell", icell) arguments.set_val("next_cell", next_cell) arguments.set_val("flow_velocity", vel[item][iorder]) if params.lsensitivity == 1: arguments.set_val( "temperature", (temperature_cell[item][-1] + params.tempcorrection) + params.temperature_add) arguments.set_val("windspeed", params.windspeed * params.windspeed_factor) arguments.set_val( "globrad", globrad_cell[item][-1] * params.global_radiation_factor) arguments.set_val("slope", slope * 1e-5 * params.slope_factor) Qmid[item][ iorder] = Qmid[item][iorder] * params.discharge_factor arguments.set_val("discharge", Qmid[item][iorder]) arguments.set_val( "residence_time", arguments.get_val("vol") / Qmid[item][iorder]) arguments.set_val( "flow_velocity", Qmid[item][iorder] / (arguments.get_val("width") * arguments.get_val("depth") * 1e-6)) if (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): floodplain_arguments = deepcopy(arguments) floodplain_arguments.set_val("dvoldt", dvoldt_fp[item]) floodplain_arguments.set_val("vol", volume_fp[item]) floodplain_arguments.set_val("depth", depth_fp[item]) if (floodplain_arguments.get_val("vol") > 0.) and (floodplain_arguments.get_val("depth") > 0.): floodplain_arguments.set_val( "area", floodplain_arguments.get_val("vol") / (floodplain_arguments.get_val("depth") * 1e-3)) floodplain_arguments.set_val( "width", (floodplain_arguments.get_val('area') * 1e6) / arguments.get_val('length')) # flow velocity in floodplain is assumed to be a fraction (between 0 and 1) of the flow velocity of the main stream floodplain_arguments.set_val( "flow_velocity", vel[item][iorder] * params.fp_vel_fraction) floodplain_arguments.set_val( "discharge", (floodplain_arguments.get_val("depth") * floodplain_arguments.get_val("width") * 1e-6) * floodplain_arguments.get_val('flow_velocity')) floodplain_arguments.set_val( "windspeed", params.windspeed * (params.fp_wind_reduc_factor * high_veg_fr_cell[item][-1] + (1 - high_veg_fr_cell[item][-1]))) else: floodplain_arguments.set_val("area", 0) floodplain_arguments.set_val("width", 0) floodplain_arguments.set_val("length", 0) floodplain_arguments.set_val("discharge", 0) floodplain_arguments.set_val("flow_velocity", 0) if params.lsensitivity == 1: floodplain_arguments.set_val( "flow_velocity", arguments.get_val("flow_velocity") * params.fp_vel_fraction * params.fp_vel_factor) floodplain_arguments.set_val( "discharge", (floodplain_arguments.get_val("depth") * floodplain_arguments.get_val("width") * 1e-6) * floodplain_arguments.get_val('flow_velocity')) high_veg_fraction = params.high_veg_fr_factor * high_veg_fr_cell[ item][-1] floodplain_arguments.set_val( "windspeed", params.windspeed * (params.fp_wind_reduc_factor * params.windspeed_reduction_factor * high_veg_fraction + (1 - high_veg_fraction))) setattr(params, 'debug', False) x_args = list() # wj201709 for arg in sorted(arguments.get_attrib()): # wj201709 x_args.append(arguments.get_val(arg)) # wj201709 if timeint[0] == params.starttime and lsteady: timerange = [timeint[0], timeint[0] + params.outputtime] dt = timerange[-1] - timerange[0] load_reach = [ ] #LV 01-01-2017: loads only for one river reach (not total length of one order) for ispec in range(len(species)): load_reach.append(load[item][ispec + 1] / number_of_rivers[iorder]) if params.lfloodplains == 1 and iorder == params.norder - 1: for ispec in range(len(species)): load_reach.append( load[item][ispec + 1 + len(species)] / number_of_rivers[iorder]) for i_y in range(len(species)): y0[i_y] = species[i_y].get_val( 'amount') * arguments.get_val('vol') if ((params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False)): y0[i_y + len(species)] = species[i_y].get_val( 'amount') * arguments.get_val('vol') if params.lfloodplains == 0 or iorder < params.norder - 1 or llake == True: Y1,outdict = itg.odeint(reactions.dy, y0,\ timerange,\ args=(params,species,proc,load_reach,\ Qmid[item][iorder],arguments), full_output=True,printmessg=False,mxstep=5000) Y = [] Y.append(list(map(positive, Y1[-1]))) # Make numpy array Y = np.array(Y) ''' Y1 = opt.fsolve(reactions.dy_steady, y0,\ args=(params,species,proc,load_reach,\ Qmid[item][iorder],arguments),xtol=1.e-6) #LV 01-09-2017 Y = [] Y.append(list(map(positive,Y1))) # Make numpy array Y = np.array(Y) ''' elif (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): Y1,outdict = itg.odeint(reactions.dy, y0,\ timerange,\ args=(params,species,proc,load_reach,\ Qmid[item][iorder],arguments,floodplain_arguments), full_output=True,printmessg=False,mxstep=8760, rtol=1e-3, atol=1e-3) Y = [] Y.append(list(map(positive, Y1[-1]))) # Make numpy array Y = np.array(Y) ''' Y1 = opt.fsolve(reactions.dy_steady, y0,\ args=(params,species,proc,load_reach,\ Qmid[item][iorder],arguments,floodplain_arguments),xtol=1.e-6) #LV 01-09-2017 Y = [] Y.append(list(map(positive,Y1))) # Make numpy array Y = np.array(Y) ''' else: load_reach = [ ] #LV 01-01-2017: loads only for one river reach (not total length of one order) for ispec in range(len(species)): load_reach.append(load[item][ispec + 1] / number_of_rivers[iorder]) if params.lfloodplains == 1 and iorder == params.norder - 1: for ispec in range(len(species)): load_reach.append( load[item][ispec + 1 + len(species)] / number_of_rivers[iorder]) if params.lfloodplains == 0 or iorder < params.norder - 1 or llake == True: Y,outdict = itg.odeint(reactions.dy, y0,\ timerange,\ args=(params,species,proc,load_reach,\ Qmid[item][iorder],arguments), full_output=True,printmessg=False,mxstep=8760, rtol=1e-3, atol=1e-3) elif (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): Y,outdict = itg.odeint(reactions.dy, y0,\ timerange,\ args=(params,species,proc,load_reach,\ Qmid[item][iorder],arguments,floodplain_arguments), full_output=True,printmessg=False,mxstep=8760, rtol=1e-3, atol=1e-3) setattr(params, 'debug', False) # Convert to load # Convert amount (Mmol) Qmid(km3/yr) and volume (km3) into load (Mmol/yr) # Y[-1][0:len(species)] to account for the transporting streams only and exclude the floodplain transport in the extended Y (in the highest order only) load_out[-1].append([]) for i in range(len(Y[-1][:len(species)])): try: load_out[-1][-1].append( (Qmid[item][iorder] / volume[item][iorder]) * Y[-1][:len(species)][i] * params.number_of_rivers[iorder]) #load_out[-1][-1].append((Qmid[item][iorder]/arguments.get_val('vol')*Y[-1][:len(species)][i]*params.number_of_rivers[iorder]) except (FloatingPointError): load_out[-1][-1].append(0.) #if iorder==5: # print('load_out[-1]=', load_out[-1][0][0]) #load_out[-1].append(((Qmid[item][iorder]/volume[item][iorder])*Y[-1][:len(species)]*params.number_of_rivers[iorder]).tolist()) # Set outflow to zero for benthic species - LV 17-07-2017 for ispec in range(len(species)): if (species[ispec].get_name().endswith("_benth")): load_out[-1][item][ispec] = 0. for i in range(len(load_out[-1][-1])): if load_out[-1][-1][i] < 0.: load_out[-1][-1][i] = 0 # Set y0 for the next small timestep y0 = deepcopy(Y[-1]) # Add budget fluxes for current internal timestep if (params.lbudget) and (dt > 0.): for ispec in range(len(species)): try: load_dt = load[item][ispec + 1] * dt except (FloatingPointError): load_dt = 0. general_func.add_budget_load(xbud, iorder, ispec, "loadIN", load_dt) try: load_out_dt = load_out[-1][item][ispec] * dt except (FloatingPointError): load_out_dt = 0. general_func.add_budget_load(xbud, iorder, ispec, "loadOUT", load_out_dt) #general_func.add_budget_load(xbud, iorder, ispec, "dvoldt", arguments.dvoldt * Y[-1][ispec]/volume[item][iorder] * dt) # to add: src_load for floodplains if (params.lfloodplains == 1) and (iorder == params.norder - 1) and ( llake == False) and volume_fp[item] > 0: general_func.add_budget_load( xbud, iorder, ispec, "loadIN", load_reach[ispec + len(species)]) #if (Y[-1][ispec+len(species)]>0) and (llake==False) and ('benth' not in species[ispec].get_val('name')): # try: # general_func.add_budget_load(xbud, iorder+1, ispec, "dvoldt", floodplain_arguments.dvoldt * Y[-1][ispec+len(species)]/volume_fp[item] * dt) # except(FloatingPointError): # general_func.add_budget_load(xbud, iorder+1, ispec, "dvoldt", 0.) #else: # general_func.add_budget_load(xbud, iorder+1, ispec, "dvoldt", floodplain_arguments.dvoldt * 0 * dt) proc_rates = reactions.procfunc(Y[-1][0:len(species)],params,species,proc,\ Qmid[item][iorder],arguments) #LV 02-08-2017 general_func.add_budget_procs(species, xbud, iorder, number_of_rivers[iorder], dt, proc_rates) if (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): proc_rates_fp = reactions.procfunc(Y[-1][-len(species):],params,species,proc,\ 0,floodplain_arguments) #LV 02-08-2017 general_func.add_budget_procs(species, xbud, iorder + 1, 1, dt, proc_rates_fp) else: general_func.add_budget_procs(species, xbud, iorder, 1, dt, len(proc_rates) * [0]) # Save last state situation # Y is a numpy array, so first make it a list. x = Y[-1][0:len(species)].tolist() xtot = [] for i in range(len(Y[-1][0:len(species)])): try: xtot.append(number_of_rivers[iorder] * Y[-1][i]) except (FloatingPointError): xtot.append(0.) if (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): x_floodplains = Y[-1][-len(species):].tolist() # Calculate concentration for all species for last order. # Change Mmol/km3 to mg/l is 10^9 mg/10^12 l = 1e-3 as conversion # !!! For benthic species, xconc is not the concentration but amount in the benthic layer per volume of water column xconc = [] for ispec in range(len(x)): if volume[-1][iorder] > params.minimal_watervolume: try: xconc.append(1e-3 * x[ispec] * species[ispec].get_molarmass() / volume[item][iorder]) except (FloatingPointError): xconc.append(0.) else: xconc.append(0) if (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): xconc_floodplains = [] for ispec in range(len(x_floodplains)): if volume_fp[-1] > 0: try: xconc_floodplains.append( 1e-3 * x_floodplains[ispec] * species[ispec].get_molarmass() / volume_fp[-1]) except (FloatingPointError): xconc_floodplains.append(0.) else: xconc_floodplains.append(0) # Add time to the list x.insert(0, timerange[-1]) xtot.insert(0, timerange[-1]) pickle.dump(xtot, fp_out, -1) if (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): x_floodplains.insert(0, timerange[-1]) pickle.dump(x_floodplains, fp_out, -1) elif (params.lfloodplains == 1) and (iorder == params.norder - 1): x_floodplains = [0] * len(species) x_floodplains.insert(0, timerange[-1]) pickle.dump(x_floodplains, fp_out, -1) # Add time to the list xconc.insert(0, timerange[-1]) pickle.dump(xconc, fp_conc, -1) if (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): xconc_floodplains.insert(0, timerange[-1]) pickle.dump(xconc_floodplains, fp_conc, -1) elif (params.lfloodplains == 1) and (iorder == params.norder - 1): xconc_floodplains = [0] * len(species) xconc_floodplains.insert(0, timerange[-1]) pickle.dump(xconc_floodplains, fp_conc, -1) # Save budget if (params.lbudget == 1): xbud[iorder].insert(0, timerange[-1]) pickle.dump(xbud[iorder], fp_bud, -1) if (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): xbud[iorder + 1].insert(0, timerange[-1]) pickle.dump(xbud[iorder + 1], fp_bud, -1) elif (params.lfloodplains == 1) and (iorder == params.norder - 1): xbud[iorder + 1] = [0] * len( general_func.get_all_header_budget_names( species, proc, line=[])) xbud[iorder + 1].insert(0, timerange[-1]) pickle.dump(xbud[iorder + 1], fp_bud, -1) # Save arguments if (params.largs == 1): x_args = [] for arg in sorted(arguments.get_attrib()): x_args.append(arguments.get_val(arg)) # Add time to the list x_args.insert(0, timerange[-1]) # Write to file pickle.dump(x_args, fp_args, -1) if (params.lfloodplains == 1) and (iorder == params.norder - 1) and (llake == False): x_floodplain_args = [] for flpl_arg in sorted(floodplain_arguments.get_attrib()): x_floodplain_args.append( floodplain_arguments.get_val(flpl_arg)) x_floodplain_args.insert(0, timerange[-1]) pickle.dump(x_floodplain_args, fp_args, -1) elif (params.lfloodplains == 1) and (iorder == params.norder - 1): x_floodplain_args = [] for arg in sorted(arguments.get_attrib()): x_floodplain_args.append(0) x_floodplain_args.insert(0, timerange[-1]) pickle.dump(x_floodplain_args, fp_args, -1) fp_out.close() fp_conc.close() if (params.lbudget == 1): fp_bud.close() if (params.largs == 1): fp_args.close() # Remove the previous timeperiod file of this cell. It is not needed anymore. filename = os.path.join(tmpdir, str(icell) + "_" + str(timeperiod - 1) + ".pkl") if (os.path.isfile(filename)): my_sys.my_removefile(filename) filename = os.path.join( tmpdir, "load_" + str(icell) + "_" + str(timeperiod - 1) + ".pkl") if (os.path.isfile(filename)): my_sys.my_removefile(filename) filename = os.path.join( tmpdir, "conc_" + str(icell) + "_" + str(timeperiod - 1) + ".pkl") if (os.path.isfile(filename)): my_sys.my_removefile(filename) if (params.lbudget == 1): filename = os.path.join( tmpdir, "budget_" + str(icell) + "_" + str(timeperiod - 1) + ".pkl") if (os.path.isfile(filename)): my_sys.my_removefile(filename) if (params.largs == 1): #wj201709 filename = os.path.join(tmpdir, "arguments_" + str(icell) + "_" + str(timeperiod - 1) + ".pkl") #wj201709 if (os.path.isfile(filename)): #wj201709 my_sys.my_removefile(filename) #wj201709 # Write load output of this cell to the output file. # Acquire the lock. if lock != None: lock.acquire() # Open output file for the load of the next cell. filename = os.path.join( tmpdir, "load_" + str(next_cell) + "_" + str(timeperiod) + ".pkl") if (os.path.isfile(filename)): # Read the file and add this load to it. fp_out = open( os.path.join( tmpdir, "load_" + str(next_cell) + "_" + str(timeperiod) + ".pkl"), "rb") load_other = [] for line in general_func.pickleLoader(fp_out): load_other.append(line) fp_out.close() # Write it again. fp_out = open( os.path.join( tmpdir, "load_" + str(next_cell) + "_" + str(timeperiod) + ".pkl"), "wb") for item in range(len(timeint)): added_list = list(map(add, load_other[item], load_out[-1][item])) pickle.dump(added_list, fp_out, -1) fp_out.close() else: #print(" Load is stored for cell from ", icell,"to ",next_cell) fp_out = open( os.path.join( tmpdir, "load_" + str(next_cell) + "_" + str(timeperiod) + ".pkl"), "wb") for item in range(len(timeint)): pickle.dump(load_out[-1][item], fp_out, -1) fp_out.close() # Release lock if lock != None: lock.release()
def calculate(params, mask, tmpdir, pointer1, outlakes_dict, jobid=None, loutputfile=False): ''' This function calculates the volume and the depth of water in the main channel and floodplain in the grid cells ''' print('Starting volume/depth calculations') water_root = params.water_inputdir # Read discharge for velocity calculations - LV 14-02-2018 discharge = get_dynamic_gridinfo.get_dynamic_gridinfo( params, pointer1, os.path.join(water_root, params.discharge), params.discharge_varname, temp_distrib=None, outputfile=None) # Read channel width grid for velocity calculations - LV 14-02-2018 channel_width_grid = ascraster.Asciigrid(ascii_file=os.path.join( water_root, params.channel_width), mask=mask, numtype=float) # Read water storage of rivers and lakes/reservoirs water_storage = get_dynamic_gridinfo.get_dynamic_gridinfo( params, pointer1, os.path.join(water_root, params.water_storage), params.water_storage_varname, temp_distrib=None, outputfile=None) # Read rivers and lakes/reservoirs areas as fraction of the cellarea fraction_waterbody_grid = get_dynamic_gridinfo.get_dynamic_gridinfo( params, pointer1, os.path.join(water_root, params.fraction_water), params.fraction_water_varname, temp_distrib=None, outputfile=None) # Read water depth of flooding areas flooding_depth = get_dynamic_gridinfo.get_dynamic_gridinfo( params, pointer1, os.path.join(water_root, params.flooding_depth), params.flooding_depth_varname, temp_distrib=None, outputfile=None) # Read flooding areas as fraction of the cellarea flooding_fraction = get_dynamic_gridinfo.get_dynamic_gridinfo( params, pointer1, os.path.join(water_root, params.flooding_fraction), params.flooding_fraction_varname, temp_distrib=None, outputfile=None) # Read the cellarea - constant (contained in ASCII file) cellarea_grid = ascraster.Asciigrid(ascii_file=os.path.join( water_root, params.cellarea), mask=mask, numtype=float) # Read lake/reservoir id lakeid_grid = get_dynamic_gridinfo.get_dynamic_gridinfo( params, pointer1, os.path.join(water_root, params.lakeid), params.lakeid_varname, temp_distrib=None, outputfile=None) # Read outlet cell of lake/reservoir id. Only outlet cell is filled outlakeid_grid = get_dynamic_gridinfo.get_dynamic_gridinfo( params, pointer1, os.path.join(water_root, params.outlakeid), params.outlakeid_varname, temp_distrib=None, outputfile=None) # Read area of lakes/reservoirs waterbody_area_grid = get_dynamic_gridinfo.get_dynamic_gridinfo( params, pointer1, os.path.join(water_root, params.water_area), params.water_area_varname, temp_distrib=None, outputfile=None) # Read maximal depth of channels - constant (contained in ASCII file) channel_depth_grid = ascraster.Asciigrid(ascii_file=os.path.join( water_root, params.channel_depth), mask=mask, numtype=float) # Check if all read time series have the same length and if all variables are available at the same dates ndates = len(water_storage[0]) #print('ndates ' + str(ndates)) #print('water_storage ' + str(water_storage)) #print('lakeid_grid ' + str(lakeid_grid)) if not(len(flooding_depth[0]) == ndates) or\ not(len(flooding_fraction[0]) == ndates): raise MyError( "Water storage, flooding fraction and flooding depth files should have the same number of time steps\n" ) for itime in range(ndates): if not(flooding_depth[0][itime][0] == water_storage[0][itime][0]) or\ not(flooding_fraction[0][itime][0] == water_storage[0][itime][0]): raise MyError( "Dates available in water storage, flooding fraction and flooding depth files are not all the same\n" ) # Make empty lists of volumes and depths for all cells vol_c = {} depth_c = {} vol_fp = {} depth_fp = {} vel = {} #LV 14-02-2018 for item in range(len(pointer1)): icell = pointer1[item].get_local_index() vol_c[icell] = [] depth_c[icell] = [] vol_fp[icell] = [] depth_fp[icell] = [] vel[icell] = [] #LV 14-02-2018 # Calculate volume and depth for each cell for item in range(len(pointer1)): #print 'icell ' + str(icell) icell = pointer1[item].get_local_index() cellarea = cellarea_grid.get_data(icell, 0.0) max_depth = channel_depth_grid.get_data(icell, -1) for itime in range(ndates): year = water_storage[0][itime][0] #print('year ' + str(year)) vol_waterbody = 0. vol_flooding_waterbody = 0. width = 0. #LV 14-02-2018 # When there is a reservoir or a lake, apply volume and surface area values to outlet cell only #id = lakeid_grid[item][itime][1] id = iround( (interpolate_list.find_closest(year, lakeid_grid[icell]))[-1]) fraction_waterbody = (interpolate_list.calculate( year, fraction_waterbody_grid[icell], extrapol=1))[-1] #data not available monthly area_waterbody = cellarea * fraction_waterbody if (id > 0): # It is a lake or reservoir # Check whether it is a outlet of a lake or reservoir #id_lake = outlakeid_grid[item][itime][1] #id_lake = (interpolate_list.find_closest(year, outlakeid_grid[icell]))[-1] #print(outlakes_dict) try: #LV 09-05-2018: there was a problem if it is an endorheic lake with no volume (no "outlet") icell_out = interpolate_list.find_closest( year, outlakes_dict[id])[-1] #LV 29-11-2017 # Total lake volume * swarea_cell / total lake swarea vol_waterbody = water_storage[icell_out][itime][1] tot_lake_area = (interpolate_list.calculate( year, waterbody_area_grid[icell_out], extrapol=1))[-1] vol_waterbody *= area_waterbody / tot_lake_area width = math.pow(tot_lake_area, 0.5) #LV 14-02-2018 except: vol_waterbody = 0. width = 0. #print(icell, id, icell_out) ''' #LV 29-11-2017 # Total lake volume * swarea_cell / total lake swarea vol_waterbody = water_storage[icell_out][itime][1] tot_lake_area = (interpolate_list.calculate(year, waterbody_area_grid[icell_out], extrapol=1))[-1] vol_waterbody *= area_waterbody / tot_lake_area width = math.pow(tot_lake_area,0.5) #LV 14-02-2018 ''' else: flood_frac = flooding_fraction[icell][itime][1] width = channel_width_grid.get_data(icell, 0.0) #LV 14-02-2018 if (flood_frac > 0.0): if (max_depth > 0.0): # Water body volume total_volume = water_storage[icell][itime][1] volume_waterbody = max_depth * area_waterbody flood_volume = total_volume - volume_waterbody if (flood_volume < 0.0): # There is no flooding flood_volume = 0.0 volume_waterbody = total_volume vol_waterbody = volume_waterbody vol_flooding_waterbody = flood_volume else: # We need another method for calculation the flooding volume and waterbody volume # Now use flooding fraction instead of channel depth total_volume = water_storage[icell][itime][1] fl_depth = flooding_depth[icell][itime][1] fl_frac = flooding_fraction[icell][itime][1] flood_volume = fl_frac * fl_depth * cellarea volume_waterbody = total_volume - flood_volume if (volume_waterbody < 0.0): # We assume there is no flooding flood_volume = 0.0 volume_waterbody = total_volume vol_waterbody = volume_waterbody vol_flooding_waterbody = flood_volume else: vol_waterbody = water_storage[icell][itime][1] vol_flooding_waterbody = 0. # Water depth of river in metres depth_waterbody = 0.0 if (area_waterbody > 0.0): depth_waterbody = vol_waterbody / area_waterbody # Velocity - LV 14-02-2018 velocity = 0.0 if ((depth_waterbody * width) > 0.0): velocity = discharge[icell][itime][1] * 1.0e6 / ( depth_waterbody * width) #print("velocity " + str(velocity)) # Change water volume from m3 into km3 vol_waterbody *= 1.0e-9 vol_flooding_waterbody *= 1.0e-9 vol_c[icell].append([year, vol_waterbody]) depth_c[icell].append([year, depth_waterbody]) vol_fp[icell].append([year, vol_flooding_waterbody]) depth_fp[icell].append([year, flooding_depth[icell][itime][1]]) vel[icell].append([year, velocity]) #print("vel[icell] " + str(vel[icell])) # If loutputfile, print in temporary pkl file if (loutputfile): fp_vol_c = open( os.path.join(tmpdir, "volume_c_" + str(jobid) + ".pkl"), "wb") pickle.dump(vol_c, fp_vol_c, -1) fp_vol_c.close() fp_depth_c = open( os.path.join(tmpdir, "depth_c_" + str(jobid) + ".pkl"), "wb") pickle.dump(depth_c, fp_depth_c, -1) fp_vol_fp = open( os.path.join(tmpdir, "volume_fp_" + str(jobid) + ".pkl"), "wb") pickle.dump(vol_fp, fp_vol_fp, -1) fp_vol_fp.close() fp_depth_fp = open( os.path.join(tmpdir, "depth_fp_" + str(jobid) + ".pkl"), "wb") pickle.dump(depth_fp, fp_depth_fp, -1) fp_depth_fp.close() #LV 14-02-2018 fp_vel = open(os.path.join(tmpdir, "velocity_" + str(jobid) + ".pkl"), "wb") pickle.dump(vel, fp_vel, -1) fp_vel.close() # Else return vol & depth objects else: return vol_c, depth_c, vol_fp, depth_fp, vel
def calculate_subgrid_hydro(lsteady,params,species,timeint,runoff_in,\ discharge_in,volume_in,water_area_in,\ depth_in,volume_fp_in,vel_in,depth_fp_in,\ llake,llakeout,lendolake,args_strahler_cell=None): # Get strahler characteristics if not(args_strahler_cell == None): riverarea = args_strahler_cell.get_val("riverarea") riverlength = args_strahler_cell.get_val("riverlength") slope = args_strahler_cell.get_val("slope") else: riverarea = params.riverarea riverlength = params.riverlength slope = [params.slope]*params.norder runoff_cell = [] discharge_cell = [] water_area_cell = [] volume_cell = [] depth_cell = [] vel_cell = [] #LV 14-02-2018 volume_fp_cell = [] #LV 06-02-2017 depth_fp_cell = [] #LV 06-02-2017 for time in timeint: runoff_cell.append(interpolate_list.calculate(time,runoff_in,extrapol=1)) discharge_cell.append(interpolate_list.calculate(time,discharge_in,extrapol=1)) water_area_cell.append(interpolate_list.calculate(time,water_area_in,extrapol=1)) volume_cell.append(interpolate_list.calculate(time,volume_in,extrapol=1)) depth_cell.append(interpolate_list.calculate(time,depth_in,extrapol=1)) vel_cell.append(interpolate_list.calculate(time,vel_in,extrapol=1)) #LV 14-02-2018 volume_fp_cell.append(interpolate_list.calculate(time,volume_fp_in,extrapol=1)) depth_fp_cell.append(interpolate_list.calculate(time,depth_fp_in,extrapol=1)) # Calculate the hydrological properties for the lower Strahler orders Q0 = [] Q = [] for item in range(len(timeint)): # Q zero order in m3/s,area in km2, runoff is in mm/yr, so conversion of 1000.0 runoff_local = max(0.0,1000*runoff_cell[item][1]/year2second) #print 'runoff_local ' + str(runoff_local) Q0.append(params.A0 * runoff_local) # Q for all streams in m3/s Q.append([]) for iorder in range(params.norder): Q[-1].append(riverarea[iorder] * runoff_local) # Determine the flux at the midpoint of the stream section [m3/s]. Qmid = [] depth = [] vel = [] #LV 14-02-2018 volume = [] volume_fp = [] #LV 06-02-2017 depth_fp = [] #LV 06-02-2017 Qmid_next = [None] * params.norder for item in range(len(timeint)): depth.append([]) vel.append([]) #LV 14-02-2018 Qmid.append([]) #for one stream only volume.append([]) #for one stream only volume_fp.append([None]*params.norder) depth_fp.append([None]*params.norder) # If the cell is a lake, set everything to zero, else calculate hydrology in small streams # LV added 21-02-2017 if (llake): for iorder in range(params.norder): depth[-1].append(0.) vel[-1].append(0.) #LV 14-02-2018 Qmid[-1].append(0.) volume[-1].append(0.) else: if (item == 0): #Qmid at 1st time step Qmid[-1].append(Q0[item] + 0.5 * Q[item][0]) for iorder in range(1,params.norder): Qmid[-1].append(Q[item][iorder-1] + 0.5 * Q[item][iorder]) else: for iorder in range(0,params.norder): Qmid[-1].append(Qmid_next[iorder]) # Calculate Qmid at next time step if (item+1 < len(timeint)): Qmid_next[0] = Q0[item+1] + 0.5 * Q[item+1][0] for iorder in range(1,params.norder): Qmid_next[iorder] = Q[item+1][iorder-1] + 0.5 * Q[item+1][iorder] for iorder in range(params.norder): # Stream width and depth for each order [m] and volume in m3. if (Qmid[item][iorder] < 0.0): print("Qmid is negative: ",Qmid[item][iorder]," Runoff is: ", runoff_local) print("***********************************************************") depth[-1].append(params.depth_factor * (Qmid[item][iorder]**params.depth_exponent)) if (params.lmanning): #LV 01-03-2018 vel[-1].append(params.manning_ks*(depth[-1][-1]**(2./3.))*(slope[iorder]**0.5)) else: wetarea = (params.depth_factor * (Qmid[item][iorder]**params.depth_exponent)\ * params.width_factor * (Qmid[item][iorder]**params.width_exponent)) if (wetarea > 0.): vel[-1].append(Qmid[item][iorder]/ wetarea) #LV 14-02-2018 else: vel[-1].append(0.) volume[-1].append(params.width_factor * (Qmid[item][iorder]**params.width_exponent)\ * params.depth_factor * (Qmid[item][iorder]**params.depth_exponent)\ * riverlength[iorder] * 1000.) #conversion from km to m # Conversion of Qmid from m3/s to km3/yr and volume from m3 to km3 for iorder in range(params.norder): Qmid[-1][iorder] *= year2second * 1.0e-9 vel[-1][iorder] *= year2second * 1.0e-3 volume[-1][iorder] *= 1.0e-9 for iorder in range(params.norder): # Replace properties of sixth order streams by information of PCRGLOBWB if (iorder == params.norder-1): for item in range(len(timeint)): Qmid[item][iorder] = discharge_cell[item][-1] volume[item][iorder] = volume_cell[item][-1] depth[item][iorder] = depth_cell[item][-1] vel[item][iorder] = vel_cell[item][-1] #LV 14-02-2018 volume_fp[item][iorder] = volume_fp_cell[item][-1] #LV 06-02-2017 depth_fp[item][iorder] = depth_fp_cell[item][-1] #LV 06-02-2017 return Qmid, volume, depth, vel, volume_fp, depth_fp