def calculate(mouth_dict, basin, load, traveltime, sumtime, avgtime, sumload): ''' This function calculates the the sum and the average of the product of residence_time and load. This must be an index for the travel time of the load in a river basin. sumtime,avgtime and sumload are attributes which are in mouth_dict. They must be given as text. ''' loadtime = ascraster.duplicategrid(traveltime) # Calculate the travel time for the N load loadtime.multiply(load, default_nodata_value=0.0) # Check whether sumtime is a valid attribute of the mouth_dict dictionairy. for key in list(mouth_dict.keys()): try: sumtime_riv = getattr(mouth_dict[key], sumtime) except AttributeError: # Make attribute in the mouth_dict dictionary setattr(mouth_dict[key], sumtime, 0.0) # Aggregate traveltime over the river basin. aggregate.aggregate_grid(basin, loadtime, mouth_dict, item=sumtime) # Calculate the average traveltime for each river basin for key in list(mouth_dict.keys()): try: sumtime_riv = getattr(mouth_dict[key], sumtime) sumload_riv = getattr(mouth_dict[key], sumload) setattr(mouth_dict[key], avgtime, sumtime_riv / sumload_riv) except ZeroDivisionError: setattr(mouth_dict[key], avgtime, 0.0)
def calculate(mouth_dict, basin, load, traveltime, sumtime, avgtime, sumload): """ This function calculates the the sum and the average of the product of residence_time and load. This must be an index for the travel time of the load in a river basin. sumtime,avgtime and sumload are attributes which are in mouth_dict. They must be given as text. """ loadtime = ascraster.duplicategrid(traveltime) # Calculate the travel time for the N load loadtime.multiply(load, default_nodata_value=0.0) # Check whether sumtime is a valid attribute of the mouth_dict dictionairy. for key in mouth_dict.keys(): try: sumtime_riv = getattr(mouth_dict[key], sumtime) except AttributeError: # Make attribute in the mouth_dict dictionary setattr(mouth_dict[key], sumtime, 0.0) # Aggregate traveltime over the river basin. aggregate.aggregate_grid(basin, loadtime, mouth_dict, item=sumtime) # Calculate the average traveltime for each river basin for key in mouth_dict.keys(): try: sumtime_riv = getattr(mouth_dict[key], sumtime) sumload_riv = getattr(mouth_dict[key], sumload) setattr(mouth_dict[key], avgtime, sumtime_riv / sumload_riv) except ZeroDivisionError: setattr(mouth_dict[key], avgtime, 0.0)
def calculate(params, mask, mouth_dict, lake_icell_dict, basin, discharge, lddmap, Pload): ''' This function calculates the retention in the grid cells. ''' # Read in the PCGLOBWB files water_storage_file = params.water_storage water_storage = ascraster.Asciigrid(ascii_file=water_storage_file,\ mask=mask,numtype=float) flooding_depth_file = params.flooding_depth flooding_depth = ascraster.Asciigrid(ascii_file=flooding_depth_file,\ mask=mask,numtype=float) flooding_fraction = ascraster.Asciigrid(ascii_file=params.flooding_fraction,\ mask=mask,numtype=float) fraction_water_grid = ascraster.Asciigrid(ascii_file=params.fraction_water,\ mask=mask,numtype=float) cellarea_grid = ascraster.Asciigrid(ascii_file=params.cellarea,\ mask=mask,numtype=float) lakeid_grid = ascraster.Asciigrid(ascii_file=params.lakeid,\ mask=mask,numtype=int) outlakeid_grid = ascraster.Asciigrid(ascii_file=params.outlakeid,\ mask=mask,numtype=int) water_area_grid = ascraster.Asciigrid(ascii_file=params.water_area,\ mask=mask,numtype=int) # Water volume flooding area volume_flooding_grid = ascraster.duplicategrid(flooding_depth) volume_flooding_grid.multiply(flooding_fraction, default_nodata_value=0.0) volume_flooding_grid.multiply(cellarea_grid, default_nodata_value=0.0) volume_flooding_grid.write_ascii_file( os.path.join(params.outputdir, "volume_flooding_grid.asc")) # Water volume of river. volume_river_grid = ascraster.duplicategrid(water_storage) volume_river_grid.write_ascii_file( os.path.join(params.outputdir, "volume_river_grid.asc")) # Area water of river. area_river_grid = ascraster.duplicategrid(cellarea_grid) area_river_grid.multiply(fraction_water_grid, default_nodata_value=0.0) area_river_grid.write_ascii_file( os.path.join(params.outputdir, "area_river_grid.asc")) # Correct river volume and area when there is a reservoir or a lake. for icell in range(lakeid_grid.length): id = lakeid_grid.get_data(icell, -1) if (id > 0): # It is a lake or reservoir # Check whether it is a outlet of a lake or reservoir id = outlakeid_grid.get_data(icell, -1) if (id > 0): # It is an outlet. So put lake properties into the gridcell volume_river_grid.set_data(icell, water_storage.get_data(icell, 0.0)) area_river_grid.set_data(icell, water_area_grid.get_data(icell, 0.0)) else: # It is not an outlet. So remove the calculated river properties. volume_river_grid.set_data(icell, 0.0) area_river_grid.set_data(icell, 0.0) volume_river_grid.write_ascii_file( os.path.join(params.outputdir, "volume_river_grid_with_lakes.asc")) area_river_grid.write_ascii_file( os.path.join(params.outputdir, "area_river_grid_with_lakes.asc")) # Depth water of river in metres depth_river_grid = ascraster.duplicategrid(volume_river_grid) depth_river_grid.divide(area_river_grid, default_nodata_value=0.0) depth_river_grid.write_ascii_file( os.path.join(params.outputdir, "depth_river_grid.asc")) # Change water_storage from m3 into km3 volume_river_grid.multiply(1.0e-9) volume_flooding_grid.multiply(1.0e-9) # Residence time is the volume divided by discharge. # Water storage is in km3. Discharge is km3/yr. So residence time is in years. residence_time_river_grid = ascraster.duplicategrid(volume_river_grid) residence_time_flooding_grid = ascraster.duplicategrid( volume_flooding_grid) # Calculate residence times by dividing water_storage through discharge. residence_time_river_grid.divide(discharge, default_nodata_value=0.0) residence_time_flooding_grid.divide( discharge, default_nodata_value=0.0, maximum=params.max_residence_time_per_cell) # If residence times are very high (e.g in dry areas), # set the residence time to a maximum # Apply maximum on gridcells which are not the outlet of a reservoir or lake. # In the flooding map there are no lakes/reservoirs for icell in range(residence_time_river_grid.length): resi = residence_time_river_grid.get_data(icell, -1) if (resi > params.max_residence_time_per_cell): # Check whether this is a outlet of a lake or reservoir try: outcell = lake_icell_dict[icell].outcell if (outcell == 1): # Outlet of a lake/reservoir if (resi > params.max_residence_time_per_lake): resi = params.max_residence_time_per_lake else: resi = params.max_residence_time_per_cell residence_time_river_grid.set_data(icell, resi) except KeyError: # This is no reservoir or lake residence_time_river_grid.set_data( icell, params.max_residence_time_per_cell) residence_time_river_grid.write_ascii_file( os.path.join(params.outputdir, "residence_time_river_grid.asc")) residence_time_flooding_grid.write_ascii_file( os.path.join(params.outputdir, "residence_time_flooding_grid.asc")) # Put residence time of the water body (lakes and reservoirs) in the grid. for icell in lake_icell_dict: if (lake_icell_dict[icell].outcell == 1): lake_icell_dict[ icell].residence_time = residence_time_river_grid.get_data( icell, 0.0) # Calculate the water volume in the grid cell volume_grid = ascraster.duplicategrid(volume_flooding_grid) volume_grid.add(volume_river_grid, default_nodata_value=0.0) volume_grid.write_ascii_file( os.path.join(params.outputdir, "volume_grid.asc")) # Calculate the average residence time with as weighing factors the volumes of the flooding - river residence_time_grid = ascraster.duplicategrid(volume_river_grid) residence_time_grid.multiply(residence_time_river_grid, default_nodata_value=0.0) temp_grid = ascraster.duplicategrid(volume_flooding_grid) temp_grid.multiply(residence_time_flooding_grid, default_nodata_value=0.0) residence_time_grid.add(temp_grid, default_nodata_value=0.0) residence_time_grid.divide(volume_grid, default_nodata_value=0.0) del temp_grid # Write residence_time to output file: residence_time_grid.write_ascii_file( os.path.join(params.outputdir, "residence_time.asc")) # Calculate the travel time of each grid cell to the river mouth traveltime = accuflux.accutime(lddmap, residence_time_grid, lake_icell_dict) traveltime.write_ascii_file( os.path.join(params.outputdir, "traveltime.asc")) # Aggregate traveltime over the river basin. aggregate.aggregate_grid(basin, traveltime, mouth_dict, item="sum_traveltime") # Calculate the average traveltime for each river basin for key in list(mouth_dict.keys()): try: mouth_dict[key].avg_traveltime = mouth_dict[ key].sum_traveltime / mouth_dict[key].number_of_cells except ZeroDivisionError: mouth_dict[key].avg_traveltime = 0.0 except AttributeError: pass # Calculate the hydraulic load (Hl = depth/residence_time) hydraulic_load_flooding_grid = ascraster.duplicategrid(flooding_depth) hydraulic_load_flooding_grid.divide(residence_time_flooding_grid, default_nodata_value=0.0) hydraulic_load_river_grid = ascraster.duplicategrid(depth_river_grid) hydraulic_load_river_grid.divide(residence_time_river_grid, default_nodata_value=0.0) hydraulic_load_river_grid.write_ascii_file( os.path.join(params.outputdir, "hydraulic_load_river.asc")) hydraulic_load_flooding_grid.write_ascii_file( os.path.join(params.outputdir, "hydraulic_load_flooding.asc")) # Calculate the average hydraulic load with as weighing factors the volumes of the flooding - river hydraulic_load_grid = ascraster.duplicategrid(volume_river_grid) hydraulic_load_grid.multiply(hydraulic_load_river_grid, default_nodata_value=0.0) temp_grid = ascraster.duplicategrid(volume_flooding_grid) temp_grid.multiply(hydraulic_load_flooding_grid, default_nodata_value=0.0) hydraulic_load_grid.add(temp_grid, default_nodata_value=0.0) hydraulic_load_grid.divide(volume_grid, default_nodata_value=0.0) del temp_grid # Write hydraulic load to output file: hydraulic_load_grid.write_ascii_file( os.path.join(params.outputdir, "hydraulic_load.asc")) temperature_grid = ascraster.Asciigrid(ascii_file=params.water_temperature,\ mask=mask,numtype=float) # Read endoreic lakes endo_lakes_grid = ascraster.Asciigrid(ascii_file=params.endo_lakes,\ mask=mask,numtype=int) # Calculate the retention for rivers. retention_river_grid = ascraster.duplicategrid(volume_river_grid) for icell in range(retention_river_grid.length): id = endo_lakes_grid.get_data(icell, 0) if (id > 0): # This is an endoreic lake. So the calculation retention_river_grid.set_data(icell, 1.0) continue vol = volume_river_grid.get_data(icell, -1) if (vol > 0): temperature = temperature_grid.get_data(icell, 20.0) hydraulic_load = hydraulic_load_river_grid.get_data(icell, 0.0) ret = calculate_retention(params, hydraulic_load, vol, temperature) retention_river_grid.set_data(icell, ret) else: retention_river_grid.set_data(icell, 0.0) # Calculate the retention for flood planes. retention_flooding_grid = ascraster.duplicategrid(volume_flooding_grid) for icell in range(retention_flooding_grid.length): vol = volume_flooding_grid.get_data(icell, -1) if (vol > 0): temperature = temperature_grid.get_data(icell, 20.0) hydraulic_load = hydraulic_load_flooding_grid.get_data(icell, 0.0) ret = calculate_retention(params, hydraulic_load, vol, temperature) retention_flooding_grid.set_data(icell, ret) else: retention_flooding_grid.set_data(icell, 0.0) # Calculate the average retention with as weighing factors the volumes of the flooding - river retention_grid = ascraster.duplicategrid(volume_river_grid) retention_grid.multiply(retention_river_grid, default_nodata_value=0.0) temp_grid = ascraster.duplicategrid(volume_flooding_grid) temp_grid.multiply(retention_flooding_grid, default_nodata_value=0.0) retention_grid.add(temp_grid, default_nodata_value=0.0) retention_grid.divide(water_storage, default_nodata_value=0.0) del temp_grid # Set the lake database for icell in range(outlakeid_grid.length): if (id > 0): # It is an outlet. So put lake properties into the gridcell # Recalculate the temperature temp = 0.0 number_of_cells = len(lake_icell_dict[icell].cells) for item in range(number_of_cells): icell_lake = lake_icell_dict[icell].cells[item] temp += temperature.get_data(icell_lake, 0.0) # Take average over the cells. temperature_cell = temp / float(number_of_cells) ret_cell = retention_river_grid.get_data(icell, 0.0) setattr(lake_icell_dict[icell], "retention", ret_cell) setattr(lake_icell_dict[icell], "fraction_water", -99) setattr(lake_icell_dict[icell], "temperature", temperature_cell) accuPload = P_accuflux(params, mask, lake_icell_dict, lddmap, Pload, retention_grid) return residence_time_grid, traveltime, retention_grid, accuPload, hydraulic_load_grid
def calculate(params, mask, mouth_dict, basin): """ Calculates the area of each grass and arable land use cell. It returns two ascraster object with the area grass and area arable land in ha """ # Read grass files gras1 = ascraster.Asciigrid(ascii_file=params.pgrass, mask=mask, numtype=float) if params.ldebug: print params.pgrass + " has been read." gras2 = ascraster.Asciigrid(ascii_file=params.igrass, mask=mask, numtype=float) if params.ldebug: print params.igrass + " has been read." # Read crop files crop1 = ascraster.Asciigrid(ascii_file=params.cropmixp, mask=mask, numtype=float) if params.ldebug: print params.cropmixp + " has been read." crop2 = ascraster.Asciigrid(ascii_file=params.croppasp, mask=mask, numtype=float) if params.ldebug: print params.croppasp + " has been read." # Read land area landarea = ascraster.Asciigrid(ascii_file=params.landarea, mask=mask, numtype=float) if params.ldebug: print params.landarea + " has been read." # Aggregate landarea on river basin scale aggregate.aggregate_grid(basin, landarea, mouth_dict, item="landarea") # Make a copy (alias not a deepcopy) of the return values area_grass = gras1 area_crop = crop1 area_natural = landarea # Calculate the total grass and crop land in ha. Because the LU file are in percentage, and the # landarea is in km2, the product of (crop1_cell+crop2_cell) * landarea_cell is then in ha. for icell in range(crop1.length): crop1_cell = crop1.get_data(icell, 0.0) crop2_cell = crop2.get_data(icell, 0.0) gras1_cell = gras1.get_data(icell, 0.0) gras2_cell = gras2.get_data(icell, 0.0) landarea_cell = landarea.get_data(icell, 0.0) # Put result in crop1 and gras1 crop_area = landarea_cell * (crop1_cell + crop2_cell) gras_area = landarea_cell * (gras1_cell + gras2_cell) if (crop_area + gras_area) - (100.0 * landarea_cell) > params.epsilon: print "Crop and grass area is too large: ", crop_area + gras_area, 100.0 * landarea_cell, ( crop_area + gras_area ) - (100.0 * landarea_cell) try: fac = (100 * landarea_cell) / (crop_area + gras_area) except ZeroDivisionError: fac = 0.0 crop_area *= fac gras_area *= fac nat_area = max(0.0, (100.0 * landarea_cell) - crop_area - gras_area) # Put result in the maps in km2 (factor 0.01) area_crop.set_data(icell, 0.01 * crop_area) area_grass.set_data(icell, 0.01 * gras_area) area_natural.set_data(icell, 0.01 * nat_area) # Aggregate landarea on river basin scale aggregate.aggregate_grid(basin, area_crop, mouth_dict, item="croparea") aggregate.aggregate_grid(basin, area_grass, mouth_dict, item="grasarea") aggregate.aggregate_grid(basin, area_natural, mouth_dict, item="natarea") # Calculate the number of cells in a region/basin one = ascraster.duplicategrid(landarea) # Set all cells to one. one.add_values(one.length * [1.0]) aggregate.aggregate_grid(basin, one, mouth_dict, item="number_of_cells") # Delete the grid objects which are used anymore del crop1 del crop2 del gras1 del gras2 del landarea del one return area_grass, area_crop, area_natural
def calculate_subgrid_retention(params,mask,mouth_dict,basin,lake_icell_dict,load,\ water_body,pnet,vf): ''' The subgrid retention is based on Wollheim (2006, GBC). This method is based on the stream order. In each cell, which is not a lake or reservoir, the subgrid retention is calculated. Only the local situation is used. For the load only the diffuse source from this cell are used. The runoff is used (so only local water). Also the concentration effect or temperature effect on retention is not used here. ''' # Make the subgrid stream order properties. # Setup the stream order river length,area and distribution and flowpath. Everything is stored in params. define_subgrid_streamorder(params) # Set the relation between concentration and net uptake velocity try: accuflux_retention.set_conc_relation_retention(params) except AttributeError: # This function is only for N and not for P pass # Make output rasters load_grid = ascraster.duplicategrid(load) retention = ascraster.duplicategrid(load) # Make nodata on all cells. retention.add_values(retention.length*[retention.nodata_value]) retentionload = ascraster.duplicategrid(retention) # Read water temperature temperature = ascraster.Asciigrid(ascii_file=params.water_temperature,mask=mask,numtype=float) # Loop over all cells: for icell in range(load_grid.length): # Get mass flux at the cell. load_cell = load_grid.get_data(icell) if (load_cell == None): # No data value continue if load_cell < 0.0: print("Negative mass flow of " + str(load_cell) + " at cell: " + str(icell)) # Go to next cell. continue # Retention in cell water_body_cell = water_body.get_data(icell,0) if (water_body_cell > 0): runoff_cell = pnet.get_data(icell,0.0) # Check whether this cell is an outflow of a lake/reservoir try: loutflow = lake_icell_dict[icell].outcell except KeyError: # No lake or reservoir loutflow = -1 try: if (loutflow == -1): # Normal cell, no lake or reservoir. # Default temperature of 20C because then temperature has no effect. temperature_cell = temperature.get_data(icell,20.0) ret_cell = calculate_localretention(params,runoff_cell,vf,load_cell,temperature_cell) else: #TODO: local retention when it is a lake or reservoir. For example as normal retention * fr_land. # Lake or reservoir. ret_cell = 0.0 except OverflowError: raise OverflowError else: ret_cell = 0.0 # Fill retention grid with retention value and retention load retention.set_data(icell,ret_cell) retentionload.set_data(icell,load_cell*ret_cell) # Write to output files retention.write_ascii_file(os.path.join(params.outputdir,"retention_subgrid.asc")) retentionload.write_ascii_file(os.path.join(params.outputdir,"removed_subgridload.asc")) # Write in mouth_dict database aggregate.aggregate_grid(basin,retentionload,mouth_dict,item="retentionload_subgrid") aggregate.aggregate_grid(basin,load_grid,mouth_dict,item="subgrid_load") # Put the retention_subgrid of the river in the mouth database for key in list(mouth_dict.keys()): try: mouth_dict[key].retention_subgrid = mouth_dict[key].retentionload_subgrid/mouth_dict[key].subgrid_load except ZeroDivisionError: mouth_dict[key].retention_subgrid = 0.0 return retentionload,retention
def calculate(params,mask,mouth_dict,lake_icell_dict,basin,discharge,lddmap): ''' This function calculates the residence time in the grid cells. ''' # Read in the PCGLOBWB files water_storage_file = params.water_storage water_storage = ascraster.Asciigrid(ascii_file=water_storage_file,\ mask=mask,numtype=float) # Change water_storage from m3 into km3 water_storage.multiply(1.0e-9) # Residence time is the volume divided by discharge. # Water storage is in km3. Discharge is km3/yr. So residence time is in years. residence_time_grid = ascraster.duplicategrid(water_storage) # Calculate residence times by dividing water_storage through discharge. residence_time_grid.divide(discharge,default_nodata_value = 0.0) # If residence times are very high (e.g in dry areas), # set the residence time to a maximum # Apply maximum on gridcells which are not the outlet of a reservoir or lake. for icell in xrange(residence_time_grid.length): resi = residence_time_grid.get_data(icell,-1) if (resi > params.max_residence_time_per_cell): # Check whether this is a outlet of a lake or reservoir try: outcell = lake_icell_dict[icell].outcell if (outcell == 1): # Outlet of a lake/reservoir if (resi > params.max_residence_time_per_lake): resi = params.max_residence_time_per_lake # Change also the dictionary value of this waterbody lake_icell_dict[icell].residence_time = resi else: resi = params.max_residence_time_per_cell residence_time_grid.set_data(icell,resi) except KeyError: # This is no reservoir or lake residence_time_grid.set_data(icell,params.max_residence_time_per_cell) # Put residence time of the water body (lakes and reservoirs) in the grid. for icell in lake_icell_dict: if (lake_icell_dict[icell].outcell == 1): residence_time_grid.set_data(icell,lake_icell_dict[icell].residence_time) # Write residence_time to output file: residence_time_grid.write_ascii_file(os.path.join(params.outputdir,"residence_time.asc")) # Calculate the travel time of each grid cell to the river mouth traveltime = accuflux.accutime(lddmap,residence_time_grid,lake_icell_dict) traveltime.write_ascii_file(os.path.join(params.outputdir,"traveltime.asc")) # Aggregate traveltime over the river basin. aggregate.aggregate_grid(basin,traveltime,mouth_dict,item="sum_traveltime") # Calculate the average traveltime for each river basin for key in mouth_dict.keys(): try: mouth_dict[key].avg_traveltime = mouth_dict[key].sum_traveltime/mouth_dict[key].number_of_cells except ZeroDivisionError: mouth_dict[key].avg_traveltime = 0.0 except AttributeError: pass return residence_time_grid,traveltime
def calculate(params, mask, mouth_dict, basin): ''' Calculates the area of each grass and arable land use cell. It returns two ascraster object with the area grass and area arable land in ha ''' # Read grass files gras1 = ascraster.Asciigrid(ascii_file=params.pgrass, mask=mask, numtype=float) if params.ldebug: print(params.pgrass + " has been read.") gras2 = ascraster.Asciigrid(ascii_file=params.igrass, mask=mask, numtype=float) if params.ldebug: print(params.igrass + " has been read.") # Read crop files crop1 = ascraster.Asciigrid(ascii_file=params.cropmixp, mask=mask, numtype=float) if params.ldebug: print(params.cropmixp + " has been read.") crop2 = ascraster.Asciigrid(ascii_file=params.croppasp, mask=mask, numtype=float) if params.ldebug: print(params.croppasp + " has been read.") # Read land area landarea = ascraster.Asciigrid(ascii_file=params.landarea, mask=mask, numtype=float) if params.ldebug: print(params.landarea + " has been read.") # Aggregate landarea on river basin scale aggregate.aggregate_grid(basin, landarea, mouth_dict, item="landarea") # Make a copy (alias not a deepcopy) of the return values area_grass = gras1 area_crop = crop1 area_natural = landarea # Calculate the total grass and crop land in ha. Because the LU file are in percentage, and the # landarea is in km2, the product of (crop1_cell+crop2_cell) * landarea_cell is then in ha. for icell in range(crop1.length): crop1_cell = crop1.get_data(icell, 0.0) crop2_cell = crop2.get_data(icell, 0.0) gras1_cell = gras1.get_data(icell, 0.0) gras2_cell = gras2.get_data(icell, 0.0) landarea_cell = landarea.get_data(icell, 0.0) # Put result in crop1 and gras1 crop_area = landarea_cell * (crop1_cell + crop2_cell) gras_area = landarea_cell * (gras1_cell + gras2_cell) if ((crop_area + gras_area) - (100.0 * landarea_cell) > 1.): print("Crop and grass area is too large: ", crop_area + gras_area, 100. * landarea_cell, (crop_area + gras_area) - (100.0 * landarea_cell)) try: fac = (100 * landarea_cell) / (crop_area + gras_area) except ZeroDivisionError: fac = 0.0 crop_area *= fac gras_area *= fac nat_area = max(0.0, (100.0 * landarea_cell) - crop_area - gras_area) # Put result in the maps in km2 (factor 0.01) area_crop.set_data(icell, 0.01 * crop_area) area_grass.set_data(icell, 0.01 * gras_area) area_natural.set_data(icell, 0.01 * nat_area) # Aggregate landarea on river basin scale aggregate.aggregate_grid(basin, area_crop, mouth_dict, item="croparea") aggregate.aggregate_grid(basin, area_grass, mouth_dict, item="grasarea") aggregate.aggregate_grid(basin, area_natural, mouth_dict, item="natarea") # Calculate the number of cells in a region/basin one = ascraster.duplicategrid(landarea) # Set all cells to one. one.add_values(one.length * [1.0]) aggregate.aggregate_grid(basin, one, mouth_dict, item="number_of_cells") # Delete the grid objects which are used anymore del crop1 del crop2 del gras1 del gras2 del landarea del one return area_grass, area_crop, area_natural
def calculate(params,mask,mouth_dict,lake_icell_dict,basin,discharge,lddmap): ''' This function calculates the residence time in the grid cells. ''' # Read water storage of rivers and lakes/reservoirs. water_storage = ascraster.Asciigrid(ascii_file=params.water_storage,\ mask=mask,numtype=float) # Read rivers and lakes/reservoirs areas as fraction of the cellarea. fraction_waterbody_grid = ascraster.Asciigrid(ascii_file=params.fraction_water,\ mask=mask,numtype=float) # Read water depth of flooding areas. flooding_depth = ascraster.Asciigrid(ascii_file=params.flooding_depth,\ mask=mask,numtype=float) # Read flooding areas as fraction of the cellarea. flooding_fraction = ascraster.Asciigrid(ascii_file=params.flooding_fraction,\ mask=mask,numtype=float) # Read the cellarea cellarea_grid = ascraster.Asciigrid(ascii_file=params.cellarea,\ mask=mask,numtype=float) # Read lake/reservoir id lakeid_grid = ascraster.Asciigrid(ascii_file=params.lakeid,\ mask=mask,numtype=int) # Read outlet cell of lake/reservoir id. Only outlet cell is filled. outlakeid_grid = ascraster.Asciigrid(ascii_file=params.outlakeid,\ mask=mask,numtype=int) # Read area of lakes/reservoirs. waterbody_area_grid = ascraster.Asciigrid(ascii_file=params.water_area,\ mask=mask,numtype=int) # Water volume flooding area in m3 volume_flooding_grid = ascraster.duplicategrid(flooding_depth) volume_flooding_grid.multiply(flooding_fraction,default_nodata_value = -1.0) volume_flooding_grid.multiply(cellarea_grid,default_nodata_value = -1.0) # Water volume of waterbody (river,lakes or reservoir) in m3 as left over of water_storage minus flooding volume. volume_waterbody_grid = ascraster.duplicategrid(water_storage) volume_waterbody_grid.substract(volume_flooding_grid,default_nodata_value = -1.0) # Area water of river in m2. area_waterbody_grid = ascraster.duplicategrid(cellarea_grid) area_waterbody_grid.multiply(fraction_waterbody_grid,default_nodata_value = -1.0) # Correct river volume and area when there is a reservoir or a lake. for icell in range(lakeid_grid.length): id = lakeid_grid.get_data(icell,-1) if (id > 0): # It is a lake or reservoir # Check whether it is a outlet of a lake or reservoir id_lake = outlakeid_grid.get_data(icell,-1) if (id_lake > 0): # It is an outlet. So put lake properties into the gridcell volume_waterbody_grid.set_data(icell,water_storage.get_data(icell,0.0)) area_waterbody_grid.set_data(icell,waterbody_area_grid.get_data(icell,0.0)) else: # It is not an outlet. So remove the calculated river properties. volume_waterbody_grid.set_data(icell,0.0) area_waterbody_grid.set_data(icell,0.0) #volume_waterbody_grid.write_ascii_file(os.path.join(params.outputdir,"volume_waterbody_grid_negative.asc")) # Correct all the volumes which are negative. for icell in range(volume_waterbody_grid.length): if (volume_waterbody_grid.get_data(icell,1.0) < 0.0): #print "Negative waterbody volume: ", volume_waterbody_grid.get_data(icell),\ # flooding_depth.get_data(icell),flooding_fraction.get_data(icell),\ # cellarea_grid.get_data(icell),water_storage.get_data(icell),fraction_waterbody_grid.get_data(icell) # When this happenes, we assume that the flooding is not correct. So the waterbody volume is equal to the water storage. # Water volume flooding is zero. volume_waterbody_grid.set_data(icell,water_storage.get_data(icell,0.0)) volume_flooding_grid.set_data(icell,0.0) # Write volume in m3 and area in m2 to outputfile volume_waterbody_grid.write_ascii_file(os.path.join(params.outputdir,"volume_waterbody_grid.asc")) volume_flooding_grid.write_ascii_file(os.path.join(params.outputdir,"volume_flooding_grid.asc")) area_waterbody_grid.write_ascii_file(os.path.join(params.outputdir,"area_waterbody_grid.asc")) # Depth water of river in metres depth_waterbody_grid = ascraster.duplicategrid(volume_waterbody_grid) depth_waterbody_grid.divide(area_waterbody_grid,default_nodata_value = -1.0) depth_waterbody_grid.write_ascii_file(os.path.join(params.outputdir,"depth_waterbody_grid.asc")) # Calculate the water volume in m3 in the grid cell volume_grid = ascraster.duplicategrid(volume_flooding_grid) volume_grid.add(volume_waterbody_grid,default_nodata_value = -1.0) volume_grid.write_ascii_file(os.path.join(params.outputdir,"volume_grid.asc")) # Change water_storage from m3 into km3 volume_waterbody_grid.multiply(1.0e-9) volume_flooding_grid.multiply(1.0e-9) volume_grid.multiply(1.0e-9) # Residence time is the volume divided by discharge. # Calculate the residence time as volume water body divided by corrected discharge # Corrected discharge is the discharge minus the water volume of the flooded area. # If residence times are very high (e.g in dry areas), # set the residence time to a maximum # Apply maximum on gridcells which are not the outlet of a reservoir or lake. residence_time_grid = ascraster.duplicategrid(volume_flooding_grid) for icell in range(residence_time_grid.length): # Check whether it is a lake/reservoir id = lakeid_grid.get_data(icell,-1) if (id > 0): # It is a lake or reservoir # Check whether it is a outlet of a lake or reservoir id_lake = outlakeid_grid.get_data(icell,-1) if (id_lake > 0): try: resi = lake_icell_dict[icell].residence_time # It is an outlet. So put lake properties into the gridcell if (lake_icell_dict[icell].residence_time > params.max_residence_time_per_lake): # Change also the dictionary value of this waterbody lake_icell_dict[icell].residence_time = params.max_residence_time_per_lake resi = params.max_residence_time_per_lake except KeyError: print(id , " has no residence time") resi = 0.0 else: # Lake or reservoir but no outflow cell resi = 0.0 residence_time_grid.set_data(icell,resi) else: # This is no reservoir or lake dis = discharge.get_data(icell,0.0) volume_flooded = volume_flooding_grid.get_data(icell,0.0) volume_waterbody = volume_waterbody_grid.get_data(icell,0.0) discharge_corrected = dis - volume_flooded if (dis <= 0.0): resi = 0.0 elif (discharge_corrected > volume_waterbody or volume_flooded <= 0.0): # Here we assume that there is enough water to feed the channel. resi = volume_waterbody/discharge_corrected else: # There is not enough water to feed the channel. # Now we take an volume weighed average of both residence times. volume_total = volume_waterbody + volume_flooded if (volume_total > 0.0): try: frac_flooded = volume_flooded/volume_total resi_flooded = frac_flooded * volume_flooded/dis except ZeroDivisionError: frac_flooded = 0.0 resi_flooded = 0.0 try: frac_waterbody = volume_waterbody/volume_total resi_waterbody = frac_waterbody * volume_waterbody/dis except ZeroDivisionError: frac_waterbody = 0.0 resi_waterbody = 0.0 resi = resi_flooded + resi_waterbody else: resi = 0.0 resi = min(resi,params.max_residence_time_per_cell) residence_time_grid.set_data(icell,resi) # Write residence_time to output file: residence_time_grid.write_ascii_file(os.path.join(params.outputdir,"residence_time.asc")) # Calculate the travel time of each grid cell to the river mouth traveltime = accuflux.accutime(lddmap,residence_time_grid,lake_icell_dict) traveltime.write_ascii_file(os.path.join(params.outputdir,"traveltime.asc")) # Aggregate traveltime over the river basin. aggregate.aggregate_grid(basin,traveltime,mouth_dict,item="sum_traveltime") # Calculate the average traveltime for each river basin for key in list(mouth_dict.keys()): try: mouth_dict[key].avg_traveltime = mouth_dict[key].sum_traveltime/mouth_dict[key].number_of_cells except ZeroDivisionError: mouth_dict[key].avg_traveltime = 0.0 except AttributeError: pass return residence_time_grid,traveltime