def areastat(Var, Area): """ Calculate several statistics of *Var* for each unique id in *Area* Input: - Var - Area Output: - Standard_Deviation,Average,Max,Min """ Avg = pcr.areaaverage(Var, Area) Sq = (Var - Avg) ** 2 N = pcr.areatotal(pcr.spatial(pcr.cellarea()), Area) / pcr.cellarea() Sd = (pcr.areatotal(Sq, Area) / N) ** 0.5 Max = pcr.areamaximum(Var, Area) Min = pcr.areaminimum(Var, Area) return Sd, Avg, Max, Min
def volume_spread(ldd, hand, subcatch, volume, volume_thres=0., area_multiplier=1., iterations=15): """ Estimate 2D flooding from a 1D simulation per subcatchment reach Input: ldd -- pcraster object direction, local drain directions hand -- pcraster object float32, elevation data normalised to nearest drain subcatch -- pcraster object ordinal, subcatchments with IDs volume -- pcraster object float32, scalar flood volume (i.e. m3 volume outside the river bank within subcatchment) volume_thres=0. -- scalar threshold, at least this amount of m3 of volume should be present in a catchment area_multiplier=1. -- in case the maps are not in m2, set a multiplier other than 1. to convert iterations=15 -- number of iterations to use Output: inundation -- pcraster object float32, scalar inundation estimate """ #initial values pcr.setglobaloption("unittrue") dem_min = pcr.areaminimum(hand, subcatch) # minimum elevation in subcatchments # pcr.report(dem_min, 'dem_min.map') dem_norm = hand - dem_min # pcr.report(dem_norm, 'dem_norm.map') # surface of each subcatchment surface = pcr.areaarea(subcatch)*area_multiplier pcr.report(surface, 'surface.map') error_abs = pcr.scalar(1e10) # initial error (very high) volume_catch = pcr.areatotal(volume, subcatch) # pcr.report(volume_catch, 'volume_catch.map') depth_catch = volume_catch/surface pcr.report(depth_catch, 'depth_catch.map') dem_max = pcr.ifthenelse(volume_catch > volume_thres, pcr.scalar(32.), pcr.scalar(0)) # bizarre high inundation depth dem_min = pcr.scalar(0.) for n in range(iterations): print('Iteration: {:02d}'.format(n + 1)) #####while np.logical_and(error_abs > error_thres, dem_min < dem_max): dem_av = (dem_min + dem_max)/2 # pcr.report(dem_av, 'dem_av00.{:03d}'.format(n + 1)) # compute value at dem_av average_depth_catch = pcr.areaaverage(pcr.max(dem_av - dem_norm, 0), subcatch) # pcr.report(average_depth_catch, 'depth_c0.{:03d}'.format(n + 1)) error = pcr.cover((depth_catch-average_depth_catch)/depth_catch, depth_catch*0) # pcr.report(error, 'error000.{:03d}'.format(n + 1)) dem_min = pcr.ifthenelse(error > 0, dem_av, dem_min) dem_max = pcr.ifthenelse(error <= 0, dem_av, dem_max) # error_abs = np.abs(error) # TODO: not needed probably, remove inundation = pcr.max(dem_av - dem_norm, 0) return inundation
def initial(self): ##################### # * initial section # ##################### #-constants # betaQ [-]: constant of kinematic wave momentum equation self.betaQ= 0.6 #-channel LDD self.channelLDD= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ldd(5),self.LDD) #-channel area and storage self.channelArea= self.channelWidth*self.channelLength self.channelStorageCapacity= pcr.ifthenelse(self.waterBodies.distribution == 0,\ self.channelArea*self.channelDepth,pcr.scalar(0.)) #-basin outlets self.basinOutlet= pcr.pit(self.LDD) != 0 #-read initial conditions self.Q= clippedRead.get(self.QIniMap) self.actualStorage= clippedRead.get(self.actualStorageIniMap) self.actualStorage= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(self.actualStorage,self.waterBodies.distribution),0),\ self.actualStorage) self.waterBodies.actualStorage= self.waterBodies.retrieveMapValue(self.actualStorage) #-update targets of average and bankful discharge self.waterBodies.averageQ= self.waterBodies.retrieveMapValue(self.averageQ) self.waterBodies.bankfulQ= self.waterBodies.retrieveMapValue(self.bankfulQ) #-return the parameters for the kinematic wave, # including alpha, wetted area, flood fraction, flood volume and depth # and the corresponding land area floodedFraction,floodedDepth,\ self.wettedArea,self.alphaQ= self.kinAlphaComposite(self.actualStorage,self.floodplainMask) self.wettedArea= self.waterBodies.returnMapValue(self.wettedArea,\ self.waterBodies.channelWidth+2.*self.waterBodies.updateWaterHeight()) self.waterFraction= pcr.ifthenelse(self.waterBodies.distribution == 0,\ pcr.max(self.waterFractionMask,floodedFraction),self.waterFractionMask) self.landFraction= pcr.max(0.,1.-self.waterFraction) #-update on velocity and check on Q - NOTE: does not work in case of reservoirs! self.flowVelocity= pcr.ifthenelse(self.wettedArea > 0,self.Q/self.wettedArea,0.) pcr.report(self.flowVelocity,pcrm.generateNameT(flowVelocityFileName,0).replace('.000','.ini')) #-setting initial values for specific runoff and surface water extraction self.landSurfaceQ= pcr.scalar(0.) self.potWaterSurfaceQ= pcr.scalar(0.) self.surfaceWaterExtraction= pcr.scalar(0.) #-budget check: setting initial values for cumulative discharge and # net cumulative input, including initial storage [m3] self.totalDischarge= pcr.scalar(0.) self.cumulativeDeltaStorage= pcr.catchmenttotal(self.actualStorage,self.LDD)
def volume_spread(ldd, hand, subcatch, volume, volume_thres=0., cell_surface=1., iterations=15, logging=logging, order=0, neg_HAND=None): """ Estimate 2D flooding from a 1D simulation per subcatchment reach Input: ldd -- pcraster object direction, local drain directions hand -- pcraster object float32, elevation data normalised to nearest drain subcatch -- pcraster object ordinal, subcatchments with IDs volume -- pcraster object float32, scalar flood volume (i.e. m3 volume outside the river bank within subcatchment) volume_thres=0. -- scalar threshold, at least this amount of m3 of volume should be present in a catchment area_multiplier=1. -- in case the maps are not in m2, set a multiplier other than 1. to convert iterations=15 -- number of iterations to use neg_HAND -- if set to 1, HAND maps can have negative values when elevation outside of stream is lower than stream (for example when there are natural embankments) Output: inundation -- pcraster object float32, scalar inundation estimate """ #initial values pcr.setglobaloption("unitcell") dem_min = pcr.areaminimum(hand, subcatch) # minimum elevation in subcatchments dem_norm = hand - dem_min # surface of each subcatchment surface = pcr.areaarea(subcatch)*pcr.areaaverage(cell_surface, subcatch) # area_multiplier error_abs = pcr.scalar(1e10) # initial error (very high) volume_catch = pcr.areatotal(volume, subcatch) depth_catch = volume_catch/surface # meters water disc averaged over subcatchment # ilt(depth_catch, 'depth_catch_{:02d}.map'.format(order)) # pcr.report(volume, 'volume_{:02d}.map'.format(order)) if neg_HAND == 1: dem_max = pcr.ifthenelse(volume_catch > volume_thres, pcr.scalar(32.), pcr.scalar(-32.)) # bizarre high inundation depth☻ dem_min = pcr.scalar(-32.) else: dem_max = pcr.ifthenelse(volume_catch > volume_thres, pcr.scalar(32.), pcr.scalar(0.)) # bizarre high inundation depth☻ dem_min = pcr.scalar(0.) for n in range(iterations): logging.debug('Iteration: {:02d}'.format(n + 1)) #####while np.logical_and(error_abs > error_thres, dem_min < dem_max): dem_av = (dem_min + dem_max)/2 # compute value at dem_av average_depth_catch = pcr.areaaverage(pcr.max(dem_av - dem_norm, 0), subcatch) error = pcr.cover((depth_catch-average_depth_catch)/depth_catch, depth_catch*0) dem_min = pcr.ifthenelse(error > 0, dem_av, dem_min) dem_max = pcr.ifthenelse(error <= 0, dem_av, dem_max) inundation = pcr.max(dem_av - dem_norm, 0) pcr.setglobaloption('unittrue') return inundation
def moveFromChannelToWaterBody( self, newStorageAtLakeAndReservoirs, timestepsToAvgDischarge, maxTimestepsToAvgDischargeShort, length_of_time_step=vos.secondsPerDay(), ): # new lake and/or reservoir storages (m3) newStorageAtLakeAndReservoirs = pcr.cover( pcr.areatotal(newStorageAtLakeAndReservoirs, self.waterBodyIds), 0.0 ) # incoming volume (m3) self.inflow = newStorageAtLakeAndReservoirs - self.waterBodyStorage # inflowInM3PerSec (m3/s) inflowInM3PerSec = self.inflow / length_of_time_step # updating (short term) average inflow (m3/s) ; # - needed to constrain lake outflow: # temp = pcr.max( 1.0, pcr.min( maxTimestepsToAvgDischargeShort, self.timestepsToAvgDischarge - 1.0 + length_of_time_step / vos.secondsPerDay(), ), ) deltaInflow = inflowInM3PerSec - self.avgInflow R = deltaInflow * (length_of_time_step / vos.secondsPerDay()) / temp self.avgInflow = self.avgInflow + R self.avgInflow = pcr.max(0.0, self.avgInflow) # # for the reference, see the "weighted incremental algorithm" in http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance # updating waterBodyStorage (m3) self.waterBodyStorage = newStorageAtLakeAndReservoirs
def moveFromChannelToWaterBody( self, newStorageAtLakeAndReservoirs, timestepsToAvgDischarge, maxTimestepsToAvgDischargeShort, length_of_time_step=vos.secondsPerDay(), ): # new lake and/or reservoir storages (m3) newStorageAtLakeAndReservoirs = pcr.cover( pcr.areatotal(newStorageAtLakeAndReservoirs, self.waterBodyIds), 0.0) # incoming volume (m3) self.inflow = newStorageAtLakeAndReservoirs - self.waterBodyStorage # inflowInM3PerSec (m3/s) inflowInM3PerSec = self.inflow / length_of_time_step # updating (short term) average inflow (m3/s) ; # - needed to constrain lake outflow: # temp = pcr.max( 1.0, pcr.min( maxTimestepsToAvgDischargeShort, self.timestepsToAvgDischarge - 1.0 + length_of_time_step / vos.secondsPerDay(), ), ) deltaInflow = inflowInM3PerSec - self.avgInflow R = deltaInflow * (length_of_time_step / vos.secondsPerDay()) / temp self.avgInflow = self.avgInflow + R self.avgInflow = pcr.max(0.0, self.avgInflow) # # for the reference, see the "weighted incremental algorithm" in http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance # updating waterBodyStorage (m3) self.waterBodyStorage = newStorageAtLakeAndReservoirs
def getICs(self, initial_condition): avgInflow = initial_condition["avgLakeReservoirInflowShort"] avgOutflow = initial_condition["avgLakeReservoirOutflowLong"] # if not isinstance(initial_condition["waterBodyStorage"], types.NoneType): # read directly waterBodyStorage = initial_condition["waterBodyStorage"] else: # calculate waterBodyStorage at cells where lakes and/or reservoirs are defined # storageAtLakeAndReservoirs = pcr.cover( pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0., initial_condition["channelStorage"], ), 0.0, ) # # - move only non negative values and use rounddown values storageAtLakeAndReservoirs = pcr.max( 0.00, pcr.rounddown(storageAtLakeAndReservoirs)) # # lake and reservoir storages = waterBodyStorage (m3) ; values are given for the entire lake / reservoir cells waterBodyStorage = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0., pcr.areatotal(storageAtLakeAndReservoirs, self.waterBodyIds), ) self.avgInflow = pcr.cover(avgInflow, 0.0) # unit: m3/s self.avgOutflow = pcr.cover(avgOutflow, 0.0) # unit: m3/s self.waterBodyStorage = pcr.cover(waterBodyStorage, 0.0) # unit: m3 self.avgInflow = pcr.ifthen(self.landmask, self.avgInflow) self.avgOutflow = pcr.ifthen(self.landmask, self.avgOutflow) self.waterBodyStorage = pcr.ifthen(self.landmask, self.waterBodyStorage)
def getICs(self, initial_condition): avgInflow = initial_condition["avgLakeReservoirInflowShort"] avgOutflow = initial_condition["avgLakeReservoirOutflowLong"] # if not isinstance(initial_condition["waterBodyStorage"], type(None)): # read directly waterBodyStorage = initial_condition["waterBodyStorage"] else: # calculate waterBodyStorage at cells where lakes and/or reservoirs are defined # storageAtLakeAndReservoirs = pcr.cover( pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0.0, initial_condition["channelStorage"], ), 0.0, ) # # - move only non negative values and use rounddown values storageAtLakeAndReservoirs = pcr.max( 0.00, pcr.rounddown(storageAtLakeAndReservoirs) ) # # lake and reservoir storages = waterBodyStorage (m3) ; values are given for the entire lake / reservoir cells waterBodyStorage = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0.0, pcr.areatotal(storageAtLakeAndReservoirs, self.waterBodyIds), ) self.avgInflow = pcr.cover(avgInflow, 0.0) # unit: m3/s self.avgOutflow = pcr.cover(avgOutflow, 0.0) # unit: m3/s self.waterBodyStorage = pcr.cover(waterBodyStorage, 0.0) # unit: m3 self.avgInflow = pcr.ifthen(self.landmask, self.avgInflow) self.avgOutflow = pcr.ifthen(self.landmask, self.avgOutflow) self.waterBodyStorage = pcr.ifthen(self.landmask, self.waterBodyStorage)
def area_riverlength_factor(ldd, Area, Clength): """ ceates correction factors for riverlength for the largest streamorder in each area Input: - ldd - Area - Clength (1d length of a cell (pcr.sqrt(Area)) Output: - distance per area """ strorder = pcr.streamorder(ldd) strordermax = pcr.areamaximum(strorder, Area) dist = pcr.downstreamdist(ldd) # count nr of strorder cells in each area nr = pcr.areatotal(pcr.ifthen(strorder == strordermax, dist), Area) # N = pcr.sqrt(pcr.areatotal(pcr.scalar(pcr.boolean(Area)),Area)) N = Clength factor = nr / N return factor
def pcr_coast(dem, points): """ project points to coast with nearest neighbourhood finds coastal cells based on dem with NoDataValues and the locations of boundary conditions at sea using pcr spread the a nearest neighbor interpolation of the point ids is done for coastal cells :param dem: pcr dem :param points: pcrmap with ids in cells :returns: pcr map with location ids projected to coastline """ # clump areas based on NoDataValues in dem dem_NoDataValues = pcr.cover(pcr.ifthenelse(dem > -9999, pcr.boolean(0), pcr.boolean(1)), pcr.boolean(1)) # find number of boundary conditions in area where dem_novalue pcr.setglobaloption("nondiagonal") # only top, bottom, left, right area_nbounds = pcr.areatotal(pcr.scalar(points), pcr.clump(dem_NoDataValues)) * pcr.scalar(dem_NoDataValues) pcr.setglobaloption("diagonal") # diagonal again # make sea (True) and land (False) mask if np.any(pcr.pcr2numpy(area_nbounds,-9999) > 0): sea = pcr.ifthenelse(area_nbounds > 0, pcr.boolean(1), pcr.boolean(0)) else: sea = dem_NoDataValues # find coast based on sea in neighboring cells and at land (sea = 0) coast = pcr.ifthenelse((pcr.window4total(pcr.scalar(sea)) > pcr.scalar(0)) & (sea == pcr.boolean(0)), pcr.boolean(1), pcr.boolean(0)) # move points to nearest sea cell(s) point_dist = pcr.ifthenelse(sea, pcr.spread(points, 0, 1), 1E31) # distance from each point for sea cells nnpoints = pcr.ifthenelse(sea, pcr.spreadzone(points, 0, 1), 0) # closest point for sea cells dist2sea = pcr.areaminimum(point_dist, nnpoints) # shortest distance to each point to sea points_in_sea = pcr.nominal(pcr.ifthenelse(dist2sea == point_dist, nnpoints, 0)) # map points to nearest sea cell # map point at sea to coastline according to shortest distance over sea res = pcr.ifthenelse((pcr.scalar(sea) + pcr.scalar(coast)) >= 1, pcr.scalar(1), 1E31) # mask out non sea or coast cells ids_coastline = pcr.scalar(pcr.spreadzone(points_in_sea, 0, res)) * pcr.scalar(coast) return ids_coastline, points_in_sea
outlet = pcr.nominal( pcr.uniqueid( pcr.ifthen(upstream_area == upstream_area_maximum, pcr.boolean(1.0)))) # - ignoring outlets with small upstream areas threshold = 50. * 1000. * 1000. # unit: m2 outlet = pcr.ifthen(upstream_area_maximum > threshold, outlet) #~ pcr.aguila(outlet) outlet = pcr.cover(outlet, pcr.nominal(0.0)) # - recalculate the basin basin_map = pcr.nominal(pcr.subcatchment(ldd, outlet)) basin_map = pcr.clump(basin_map) basin_map = pcr.ifthen(landmask, basin_map) pcr.report(basin_map, "basin_map.map") #~ pcr.aguila(basin_map) # - calculate the basin area basin_area = pcr.areatotal(cell_area, basin_map) pcr.report(basin_area, "basin_area.map") #~ pcr.aguila(basin_area) # finding the month that give the maximum discharge (from the climatology time series) msg = "Identifying the month with peak discharge (from climatology time series):" logger.info(msg) # - read the maximum monthly discharge for every basin maximum_discharge = vos.netcdf2PCRobjClone(input_files['maximumClimatologyDischargeMonthAvg'], \ "discharge", 1,\ useDoy = "Yes", cloneMapFileName = clone_map_file,\ LatitudeLongitude = True,\ specificFillValue = None) maximum_discharge = pcr.areamaximum(\ pcr.cover(maximum_discharge, 0.0), basin_map)
def forcingDownscalingOptions(self, iniItems): self.downscalePrecipitationOption = False self.downscaleTemperatureOption = False self.downscaleReferenceETPotOption = False if 'meteoDownscalingOptions' in iniItems.allSections: # downscaling options if iniItems.meteoDownscalingOptions[ 'downscalePrecipitation'] == "True": self.downscalePrecipitationOption = True logger.info( "Precipitation forcing will be downscaled to the cloneMap resolution." ) if iniItems.meteoDownscalingOptions[ 'downscaleTemperature'] == "True": self.downscaleTemperatureOption = True logger.info( "Temperature forcing will be downscaled to the cloneMap resolution." ) if iniItems.meteoDownscalingOptions[ 'downscaleReferenceETPot'] == "True" and self.refETPotMethod != 'Hamon': self.downscaleReferenceETPotOption = True logger.info( "Reference potential evaporation will be downscaled to the cloneMap resolution." ) # Note that for the Hamon method: referencePotET will be calculated based on temperature, # therefore, we do not have to downscale it (particularly if temperature is already provided at high resolution). if self.downscalePrecipitationOption or\ self.downscaleTemperatureOption or\ self.downscaleReferenceETPotOption: # creating anomaly DEM highResolutionDEM = vos.readPCRmapClone(\ iniItems.meteoDownscalingOptions['highResolutionDEM'], self.cloneMap,self.tmpDir,self.inputDir) highResolutionDEM = pcr.cover(highResolutionDEM, 0.0) highResolutionDEM = pcr.max(highResolutionDEM, 0.0) self.meteoDownscaleIds = vos.readPCRmapClone(\ iniItems.meteoDownscalingOptions['meteoDownscaleIds'], self.cloneMap,self.tmpDir,self.inputDir,isLddMap=False,cover=None,isNomMap=True) self.cellArea = vos.readPCRmapClone(\ iniItems.routingOptions['cellAreaMap'], self.cloneMap,self.tmpDir,self.inputDir) loweResolutionDEM = pcr.areatotal(pcr.cover(highResolutionDEM*self.cellArea, 0.0),\ self.meteoDownscaleIds)/\ pcr.areatotal(pcr.cover(self.cellArea, 0.0),\ self.meteoDownscaleIds) self.anomalyDEM = highResolutionDEM - loweResolutionDEM # unit: meter # temperature lapse rate (netCDF) file self.temperLapseRateNC = vos.getFullPath(iniItems.meteoDownscalingOptions[\ 'temperLapseRateNC'],self.inputDir) self.temperatCorrelNC = vos.getFullPath(iniItems.meteoDownscalingOptions[\ 'temperatCorrelNC'],self.inputDir) # TODO: Remove this criteria. # precipitation lapse rate (netCDF) file self.precipLapseRateNC = vos.getFullPath(iniItems.meteoDownscalingOptions[\ 'precipLapseRateNC'],self.inputDir) self.precipitCorrelNC = vos.getFullPath(iniItems.meteoDownscalingOptions[\ 'precipitCorrelNC'],self.inputDir) # TODO: Remove this criteria. else: logger.info("No forcing downscaling is implemented.") # forcing smoothing options: - THIS is still experimental. PS: MUST BE TESTED. self.forcingSmoothing = False if 'meteoDownscalingOptions' in iniItems.allSections and \ 'smoothingWindowsLength' in list(iniItems.meteoDownscalingOptions.keys()): if float(iniItems.meteoDownscalingOptions['smoothingWindowsLength'] ) > 0.0: self.forcingSmoothing = True self.smoothingWindowsLength = vos.readPCRmapClone(\ iniItems.meteoDownscalingOptions['smoothingWindowsLength'], self.cloneMap,self.tmpDir,self.inputDir) msg = "Forcing data will be smoothed with 'windowaverage' using the window length:" + str( iniItems.meteoDownscalingOptions['smoothingWindowsLength']) logger.info(msg)
clone_map_file, output_files['tmp_folder'], None, False, None, True)) # set the cell areas for 5 arc-min and half arc-degree cells msg = "Setting the cell areas for 5 arc-min and half arc-degree cells" + ":" logger.info(msg) # - 5 arc-min cell_area = vos.readPCRmapClone(input_files['cell_area_05min'], clone_map_file, output_files['tmp_folder']) cell_area = pcr.ifthen(landmask, cell_area) # - 30 arc-min cell_area_30min = pcr.areatotal(cell_area, cell_ids_30min) # upscaling factor upscaling_factor = np.int(30.0 / 5.0) # netcdf general setup: netcdf_setup = {} netcdf_setup['format'] = "NETCDF4" netcdf_setup['zlib'] = True netcdf_setup[ 'institution'] = "Utrecht University, Department of Physical Geography ; Deltares ; World Resources Institute" netcdf_setup[ 'title'] = "PCR-GLOBWB 2 output (post-processed for the Aqueduct Flood Analyzer): Annual Maxima of River Depth" netcdf_setup['created by'] = "Edwin H. Sutanudjaja ([email protected])" netcdf_setup['description'] = 'The annual river depth maxima for each year/period starting from October of the year until September of its following year (for normal hydrological years) or ' +\ 'for each year/period starting from July of the year until June of its following year (for alternative hydrological years). "'
def waterAbstractionAndAllocation(water_demand_volume,available_water_volume,allocation_zones,\ zone_area = None, high_volume_treshold = 1000000., debug_water_balance = True,\ extra_info_for_water_balance_reporting = "", ignore_small_values = True): logger.debug("Allocation of abstraction.") # demand volume in each cell (unit: m3) if ignore_small_values: # ignore small values to avoid runding error cellVolDemand = pcr.rounddown(pcr.max(0.0, water_demand_volume)) else: cellVolDemand = pcr.max(0.0, water_demand_volume) # total demand volume in each zone/segment (unit: m3) zoneVolDemand = pcr.areatotal(cellVolDemand, allocation_zones) # total available water volume in each cell if ignore_small_values: # ignore small values to avoid runding error cellAvlWater = pcr.rounddown(pcr.max(0.00, available_water_volume)) else: cellAvlWater = pcr.max(0.00, available_water_volume) # total available water volume in each zone/segment (unit: m3) # - to minimize numerical errors, separating cellAvlWater if not isinstance(high_volume_treshold, types.NoneType): # mask: 0 for small volumes ; 1 for large volumes (e.g. in lakes and reservoirs) mask = pcr.cover(\ pcr.ifthen(cellAvlWater > high_volume_treshold, pcr.boolean(1)), pcr.boolean(0)) zoneAvlWater = pcr.areatotal(pcr.ifthenelse(mask, 0.0, cellAvlWater), allocation_zones) zoneAvlWater += pcr.areatotal(pcr.ifthenelse(mask, cellAvlWater, 0.0), allocation_zones) else: zoneAvlWater = pcr.areatotal(cellAvlWater, allocation_zones) # total actual water abstraction volume in each zone/segment (unit: m3) # - limited to available water zoneAbstraction = pcr.min(zoneAvlWater, zoneVolDemand) # actual water abstraction volume in each cell (unit: m3) cellAbstraction = getValDivZero(\ cellAvlWater, zoneAvlWater, smallNumber)*zoneAbstraction cellAbstraction = pcr.min(cellAbstraction, cellAvlWater) if ignore_small_values: # ignore small values to avoid runding error cellAbstraction = pcr.rounddown(pcr.max(0.00, cellAbstraction)) # to minimize numerical errors, separating cellAbstraction if not isinstance(high_volume_treshold, types.NoneType): # mask: 0 for small volumes ; 1 for large volumes (e.g. in lakes and reservoirs) mask = pcr.cover(\ pcr.ifthen(cellAbstraction > high_volume_treshold, pcr.boolean(1)), pcr.boolean(0)) zoneAbstraction = pcr.areatotal( pcr.ifthenelse(mask, 0.0, cellAbstraction), allocation_zones) zoneAbstraction += pcr.areatotal( pcr.ifthenelse(mask, cellAbstraction, 0.0), allocation_zones) else: zoneAbstraction = pcr.areatotal(cellAbstraction, allocation_zones) # allocation water to meet water demand (unit: m3) cellAllocation = getValDivZero(\ cellVolDemand, zoneVolDemand, smallNumber)*zoneAbstraction #~ # extraAbstraction to minimize numerical errors: #~ zoneDeficitAbstraction = pcr.max(0.0,\ #~ pcr.areatotal(cellAllocation , allocation_zones) -\ #~ pcr.areatotal(cellAbstraction, allocation_zones)) #~ remainingCellAvlWater = pcr.max(0.0, cellAvlWater - cellAbstraction) #~ cellAbstraction += zoneDeficitAbstraction * getValDivZero(\ #~ remainingCellAvlWater, #~ pcr.areatotal(remainingCellAvlWater, allocation_zones), #~ smallNumber) #~ # #~ # extraAllocation to minimize numerical errors: #~ zoneDeficitAllocation = pcr.max(0.0,\ #~ pcr.areatotal(cellAbstraction, allocation_zones) -\ #~ pcr.areatotal(cellAllocation , allocation_zones)) #~ remainingCellDemand = pcr.max(0.0, cellVolDemand - cellAllocation) #~ cellAllocation += zoneDeficitAllocation * getValDivZero(\ #~ remainingCellDemand, #~ pcr.areatotal(remainingCellDemand, allocation_zones), #~ smallNumber) if debug_water_balance and not isinstance(zone_area, types.NoneType): zoneAbstraction = pcr.cover( pcr.areatotal(cellAbstraction, allocation_zones) / zone_area, 0.0) zoneAllocation = pcr.cover( pcr.areatotal(cellAllocation, allocation_zones) / zone_area, 0.0) waterBalanceCheck([zoneAbstraction],\ [zoneAllocation],\ [pcr.scalar(0.0)],\ [pcr.scalar(0.0)],\ 'abstraction - allocation per zone/segment (PS: Error here may be caused by rounding error.)' ,\ True,\ extra_info_for_water_balance_reporting,threshold=1e-4) return cellAbstraction, cellAllocation
def main(): # output folder (and tmp folder) clean_out_folder = True if os.path.exists(out_folder): if clean_out_folder: shutil.rmtree(out_folder) os.makedirs(out_folder) else: os.makedirs(out_folder) os.chdir(out_folder) os.system("pwd") # set the clone map print("set the clone") pcr.setclone(global_ldd_30min_inp_file) # define the landmask print("define the landmask") # - based on the 30min input landmask_30min = define_landmask(input_file = global_landmask_30min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_30min_only") # - based on the 05min input landmask_05min = define_landmask(input_file = global_landmask_05min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_05min_only") # - based on the 30sec input landmask_30sec = define_landmask(input_file = global_landmask_30sec_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_30sec_only") # - based on the 30sec input landmask_03sec = define_landmask(input_file = global_landmask_03sec_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_03sec_only") # # - merge all landmasks landmask = pcr.cover(landmask_30min, landmask_05min, landmask_30sec, landmask_03sec) pcr.report(landmask, "global_landmask_30min_final.map") # ~ pcr.aguila(landmask) # extend ldd print("extend/define the ldd") ldd_map = pcr.readmap(global_ldd_30min_inp_file) ldd_map = pcr.ifthen(landmask, pcr.cover(ldd_map, pcr.ldd(5))) pcr.report(ldd_map, "global_ldd_final.map") # ~ pcr.aguila(ldd_map) # identify small islands print("identify small islands") # - maps of islands smaller than 10000 cells (at half arc degree resolution) island_map = pcr.ifthen(landmask, pcr.clump(pcr.defined(ldd_map))) island_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), island_map) island_map = pcr.ifthen(island_size < 10000., island_map) UNTIL_THIS # identify the biggest island for every group of small islands within the windows 10x10 arcdeg cells # - sort from the largest catchment catchment_pits_boolean = pcr.ifthen( pcr.scalar(pcr.pit(ldd_map)) > 0.0, pcr.boolean(1.0)) catchment_pits_boolean = pcr.ifthen(catchment_pits_boolean, catchment_pits_boolean) pcr.aguila(catchment_pits_boolean) catchment_map = pcr.nominal( pcr.areaorder(catchment_size * -1.0, pcr.nominal(catchment_pits_boolean))) island_map = pcr.ifthen(island_size == pcr.windowmaximum(island_size, 10.), island_map) pcr.aguila(island_map) # identify big catchments # merge biggest islands and big catchments # make catchment and island map print("make catchment and island map") # - catchment map catchment_map = pcr.catchment(ldd_map, pcr.pit(ldd_map)) pcr.report(catchment_map, "global_catchment_not_sorted.map") os.system("mapattr -p global_catchment_not_sorted.map") num_of_catchments = int(vos.getMinMaxMean(pcr.scalar(catchment_map))[1]) # - maps of islands smaller than 10000 cells island_map = pcr.ifthen(landmask, pcr.clump(pcr.defined(ldd_map))) island_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), island_map) island_map = pcr.ifthen(island_size < 10000., island_map) island_map = pcr.nominal( pcr.scalar(pcr.ifthen(landmask, pcr.clump(island_map))) + pcr.scalar(num_of_catchments) * 100.) pcr.aguila(island_map) island_size = pcr.ifthen(pcr.defined(island_map), island_size) island_map = pcr.ifthen(island_size == pcr.windowmaximum(island_size, 10.), island_map) pcr.aguila(island_map) catchment_map = pcr.cover(island_map, catchment_map) catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) # - calculate the size catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) # - sort from the largest catchment catchment_pits_boolean = pcr.ifthen( pcr.scalar(pcr.pit(ldd_map)) > 0.0, pcr.boolean(1.0)) catchment_pits_boolean = pcr.ifthen(catchment_pits_boolean, catchment_pits_boolean) pcr.aguila(catchment_pits_boolean) catchment_map = pcr.nominal( pcr.areaorder(catchment_size * -1.0, pcr.nominal(catchment_pits_boolean))) catchment_map = pcr.catchment(ldd_map, catchment_map) pcr.report(catchment_map, "global_catchment_final.map") os.system("mapattr -p global_catchment_final.map") # - calculate the size catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) pcr.report(catchment_size, "global_catchment_size_in_number_of_cells.map") # number of catchments num_of_catchments = int(vos.getMinMaxMean(pcr.scalar(catchment_map))[1]) # size of the largest catchment catchment_size_max = vos.getMinMaxMean(catchment_size)[1] print("") print(str(float(catchment_size_max))) print("") # identify all large catchments with size >= 50 cells (at the resolution of 30 arcmin) = 50 x (50^2) km2 = 125000 km2 print("identify catchments with the minimum size of 50 cells") catchment_map_ge_50 = pcr.ifthen(catchment_size >= 50, catchment_map) pcr.report(catchment_map_ge_50, "global_catchment_ge_50_cells.map") # include the island catchment_map_ge_50 = pcr.cover(island_map, catchment_map_ge_50) # perform cdo fillmiss2 in order to merge the small catchments to the nearest large catchments cmd = "gdal_translate -of NETCDF global_catchment_ge_50_cells.map global_catchment_ge_50_cells.nc" print(cmd) os.system(cmd) cmd = "cdo fillmiss2 global_catchment_ge_50_cells.nc global_catchment_ge_50_cells_filled.nc" print(cmd) os.system(cmd) cmd = "cdo fillmiss2 global_catchment_ge_50_cells_filled.nc global_catchment_ge_50_cells_filled.nc" print(cmd) os.system(cmd) cmd = "gdal_translate -of PCRaster global_catchment_ge_50_cells_filled.nc global_catchment_ge_50_cells_filled.map" print(cmd) os.system(cmd) cmd = "mapattr -c " + global_ldd_30min_inp_file + " " + "global_catchment_ge_50_cells_filled.map" print(cmd) os.system(cmd) # - initial subdomains subdomains_initial = pcr.nominal( pcr.readmap("global_catchment_ge_50_cells_filled.map")) subdomains_initial = pcr.areamajority(subdomains_initial, catchment_map) pcr.aguila(subdomains_initial) # - initial subdomains clump subdomains_initial_clump = pcr.clump(subdomains_initial) pcr.aguila(subdomains_initial_clump) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[0]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[1]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial_clump))[0]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial_clump))[1]))) # - remove temporay files (not used) cmd = "rm global_catchment_ge_50_cells_filled*" print(cmd) os.system(cmd) # clone code that will be assigned assigned_number = 0
if class_map_file_name == "aquifer": class_map_file_name = class_map_default_folder + "/why_wgs1984_BUENO.map" if class_map_file_name == "country": class_map_file_name = "/home/sutan101/data/country_shp_from_tianyi/World_Polys_High.map" # reading the class map class_map = pcr.nominal(pcr.uniqueid(landmask)) if class_map_file_name != "pixel": class_map = vos.readPCRmapClone(class_map_file_name, clone_map, tmp_directory, None, False, None, True, False) class_map = pcr.ifthen(pcr.scalar(class_map) > 0.0, pcr.nominal(class_map)) # time selection start_year = int(sys.argv[3]) end_year = int(sys.argv[4]) # cell_area (unit: m2) cell_area = pcr.readmap("/data/hydroworld/PCRGLOBWB20/input5min/routing/cellsize05min.correct.map") segment_cell_area = pcr.areatotal(cell_area, class_map) # extent of aquifer/sedimentary basins: sedimentary_basin = pcr.cover(pcr.scalar(pcr.readmap("/home/sutan101/data/sed_extent/sed_extent.map")), 0.0) cell_area = sedimentary_basin * cell_area #~ cell_area = pcr.ifthenelse(pcr.areatotal(cell_area, class_map) > 0.25 * segment_cell_area, cell_area, 0.0) # we only use pixels belonging to the sedimentary basin class_map_all = class_map class_map = pcr.ifthen(sedimentary_basin > 0, class_map) # fraction for groundwater recharge to be reserved to meet the environmental flow fraction_reserved_recharge = pcr.readmap("/nfsarchive/edwin-emergency-backup-DO-NOT-DELETE/rapid/edwin/05min_runs_results/2015_04_27/non_natural_2015_04_27/global/analysis/reservedrecharge/fraction_reserved_recharge10.5min.map") # - extrapolation fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \ pcr.windowaverage(fraction_reserved_recharge, 0.5))
def main(): # output folder (and tmp folder) clean_out_folder = True if os.path.exists(out_folder): if clean_out_folder: shutil.rmtree(out_folder) os.makedirs(out_folder) else: os.makedirs(out_folder) os.chdir(out_folder) os.system("pwd") # set the clone map print("set the clone") pcr.setclone(global_ldd_30min_inp_file) # define the landmask print("define the landmask") # - based on the 30min input landmask_30min = define_landmask(input_file = global_landmask_30min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_30min_only.map") # - based on the 05min input landmask_05min = define_landmask(input_file = global_landmask_05min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_05min_only.map") # - based on the 06min input landmask_06min = define_landmask(input_file = global_landmask_06min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_06min_only.map") # - based on the 30sec input landmask_30sec = define_landmask(input_file = global_landmask_30sec_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_30sec_only.map") # - based on the 30sec input landmask_03sec = define_landmask(input_file = global_landmask_03sec_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_03sec_only.map") # # - merge all landmasks landmask = pcr.cover(landmask_30min, landmask_05min, landmask_06min, landmask_30sec, landmask_03sec) pcr.report(landmask, "global_landmask_extended_30min.map") # ~ pcr.aguila(landmask) # extend ldd print("extend/define the ldd") ldd_map = pcr.readmap(global_ldd_30min_inp_file) ldd_map = pcr.ifthen(landmask, pcr.cover(ldd_map, pcr.ldd(5))) pcr.report(ldd_map, "global_ldd_extended_30min.map") # ~ pcr.aguila(ldd_map) # catchment map and size catchment_map = pcr.catchment(ldd_map, pcr.pit(ldd_map)) catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) # ~ pcr.aguila(catchment_size) # identify small islands print("identify small islands") # - maps of islands smaller than 15000 cells (at half arc degree resolution) island_map = pcr.ifthen(landmask, pcr.clump(pcr.defined(ldd_map))) island_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), island_map) island_map = pcr.ifthen(island_size < 15000., island_map) # ~ # - use catchments (instead of islands) # ~ island_map = catchment_map # ~ island_size = catchment_size # ~ island_map = pcr.ifthen(island_size < 10000., island_map) # - sort from the largest island # -- take one cell per island as a representative island_map_rep_size = pcr.ifthen( pcr.areaorder(island_size, island_map) == 1.0, island_size) # -- sort from the largest island island_map_rep_ids = pcr.areaorder( island_map_rep_size * -1.00, pcr.ifthen(pcr.defined(island_map_rep_size), pcr.nominal(1.0))) # -- map of smaller islands, sorted from the largest one island_map = pcr.areamajority(pcr.nominal(island_map_rep_ids), island_map) # identify the biggest island for every group of small islands within a certain window (arcdeg cells) print("the biggest island for every group of small islands") large_island_map = pcr.ifthen( pcr.scalar(island_map) == pcr.windowminimum(pcr.scalar(island_map), 15.), island_map) # ~ pcr.aguila(large_island_map) # identify big catchments print("identify large catchments") catchment_map = pcr.catchment(ldd_map, pcr.pit(ldd_map)) catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) # ~ # - identify all large catchments with size >= 50 cells (at the resolution of 30 arcmin) = 50 x (50^2) km2 = 125000 km2 # ~ large_catchment_map = pcr.ifthen(catchment_size >= 50, catchment_map) # ~ # - identify all large catchments with size >= 10 cells (at the resolution of 30 arcmin) # ~ large_catchment_map = pcr.ifthen(catchment_size >= 10, catchment_map) # ~ # - identify all large catchments with size >= 5 cells (at the resolution of 30 arcmin) # ~ large_catchment_map = pcr.ifthen(catchment_size >= 5, catchment_map) # ~ # - identify all large catchments with size >= 20 cells (at the resolution of 30 arcmin) # ~ large_catchment_map = pcr.ifthen(catchment_size >= 20, catchment_map) # - identify all large catchments with size >= 25 cells (at the resolution of 30 arcmin) large_catchment_map = pcr.ifthen(catchment_size >= 25, catchment_map) # - give the codes that are different than islands large_catchment_map = pcr.nominal( pcr.scalar(large_catchment_map) + 10. * vos.getMinMaxMean(pcr.scalar(large_island_map))[1]) # merge biggest islands and big catchments print("merge large catchments and islands") large_catchment_and_island_map = pcr.cover(large_catchment_map, large_island_map) # ~ large_catchment_and_island_map = pcr.cover(large_island_map, large_catchment_map) large_catchment_and_island_map_size = pcr.areatotal( pcr.spatial(pcr.scalar(1.0)), large_catchment_and_island_map) # - sort from the largest one # -- take one cell per island as a representative large_catchment_and_island_map_rep_size = pcr.ifthen( pcr.areaorder(large_catchment_and_island_map_size, large_catchment_and_island_map) == 1.0, large_catchment_and_island_map_size) # -- sort from the largest large_catchment_and_island_map_rep_ids = pcr.areaorder( large_catchment_and_island_map_rep_size * -1.00, pcr.ifthen(pcr.defined(large_catchment_and_island_map_rep_size), pcr.nominal(1.0))) # -- map of largest catchments and islands, sorted from the largest one large_catchment_and_island_map = pcr.areamajority( pcr.nominal(large_catchment_and_island_map_rep_ids), large_catchment_and_island_map) # ~ pcr.report(large_catchment_and_island_map, "large_catchments_and_islands.map") # ~ # perform cdo fillmiss2 in order to merge the small catchments to the nearest large catchments # ~ print("spatial interpolation/extrapolation using cdo fillmiss2 to get initial subdomains") # ~ cmd = "gdal_translate -of NETCDF large_catchments_and_islands.map large_catchments_and_islands.nc" # ~ print(cmd); os.system(cmd) # ~ cmd = "cdo fillmiss2 large_catchments_and_islands.nc large_catchments_and_islands_filled.nc" # ~ print(cmd); os.system(cmd) # ~ cmd = "gdal_translate -of PCRaster large_catchments_and_islands_filled.nc large_catchments_and_islands_filled.map" # ~ print(cmd); os.system(cmd) # ~ cmd = "mapattr -c " + global_ldd_30min_inp_file + " " + "large_catchments_and_islands_filled.map" # ~ print(cmd); os.system(cmd) # ~ # - initial subdomains # ~ subdomains_initial = pcr.nominal(pcr.readmap("large_catchments_and_islands_filled.map")) # ~ subdomains_initial = pcr.areamajority(subdomains_initial, catchment_map) # ~ pcr.aguila(subdomains_initial) # spatial interpolation/extrapolation in order to merge the small catchments to the nearest large catchments print("spatial interpolation/extrapolation to get initial subdomains") field = large_catchment_and_island_map cellID = pcr.nominal(pcr.uniqueid(pcr.defined(field))) zoneID = pcr.spreadzone(cellID, 0, 1) field = pcr.areamajority(field, zoneID) subdomains_initial = field subdomains_initial = pcr.areamajority(subdomains_initial, catchment_map) pcr.aguila(subdomains_initial) pcr.report(subdomains_initial, "global_subdomains_30min_initial.map") print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[0]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[1]))) # ~ print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial_clump))[0]))) # ~ print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial_clump))[1]))) print("Checking all subdomains, avoid too large subdomains") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[1]) # clone code that will be assigned assigned_number = 0 subdomains_final = pcr.ifthen( pcr.scalar(subdomains_initial) < -7777, pcr.nominal(0)) for nr in range(1, num_of_masks + 1, 1): msg = "Processing the landmask %s" % (str(nr)) print(msg) mask_selected_boolean = pcr.ifthen(subdomains_initial == nr, pcr.boolean(1.0)) # ~ if nr == 1: pcr.aguila(mask_selected_boolean) xmin, ymin, xmax, ymax = boundingBox(mask_selected_boolean) area_in_degree2 = (xmax - xmin) * (ymax - ymin) # ~ print(str(area_in_degree2)) # check whether the size of bounding box is ok # - initial check value check_ok = True reference_area_in_degree2 = 2500. if area_in_degree2 > 1.50 * reference_area_in_degree2: check_ok = False if (xmax - xmin) > 10 * (ymax - ymin): check_ok = False if check_ok == True: msg = "Clump is not needed." msg = "\n\n" + str(msg) + "\n\n" print(msg) # assign the clone code assigned_number = assigned_number + 1 # update global landmask for river and land mask_selected_nominal = pcr.ifthen(mask_selected_boolean, pcr.nominal(assigned_number)) subdomains_final = pcr.cover(subdomains_final, mask_selected_nominal) if check_ok == False: msg = "Clump is needed." msg = "\n\n" + str(msg) + "\n\n" print(msg) # make clump clump_ids = pcr.nominal(pcr.clump(mask_selected_boolean)) # merge clumps that are close together clump_ids_window_majority = pcr.windowmajority(clump_ids, 10.0) clump_ids = pcr.areamajority(clump_ids_window_majority, clump_ids) # ~ pcr.aguila(clump_ids) # minimimum and maximum values min_clump_id = int( pcr.cellvalue(pcr.mapminimum(pcr.scalar(clump_ids)), 1)[0]) max_clump_id = int( pcr.cellvalue(pcr.mapmaximum(pcr.scalar(clump_ids)), 1)[0]) for clump_id in range(min_clump_id, max_clump_id + 1, 1): msg = "Processing the clump %s of %s from the landmask %s" % ( str(clump_id), str(max_clump_id), str(nr)) msg = "\n\n" + str(msg) + "\n\n" print(msg) # identify mask based on the clump mask_selected_boolean_from_clump = pcr.ifthen( clump_ids == pcr.nominal(clump_id), mask_selected_boolean) mask_selected_boolean_from_clump = pcr.ifthen( mask_selected_boolean_from_clump, mask_selected_boolean_from_clump) # check whether the clump is empty check_mask_selected_boolean_from_clump = pcr.ifthen( mask_selected_boolean, mask_selected_boolean_from_clump) check_if_empty = float( pcr.cellvalue( pcr.mapmaximum( pcr.scalar( pcr.defined( check_mask_selected_boolean_from_clump))), 1)[0]) if check_if_empty == 0.0: msg = "Map is empty !" msg = "\n\n" + str(msg) + "\n\n" print(msg) else: msg = "Map is NOT empty !" msg = "\n\n" + str(msg) + "\n\n" print(msg) # assign the clone code assigned_number = assigned_number + 1 # update global landmask for river and land mask_selected_nominal = pcr.ifthen( mask_selected_boolean_from_clump, pcr.nominal(assigned_number)) subdomains_final = pcr.cover(subdomains_final, mask_selected_nominal) # ~ # kill all aguila processes if exist # ~ os.system('killall aguila') pcr.aguila(subdomains_final) print("") print("") print("") print("The subdomain map is READY.") pcr.report(subdomains_final, "global_subdomains_30min_final.map") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_final))[1]) print(num_of_masks) print("") print("") print("") for nr in range(1, num_of_masks + 1, 1): mask_selected_boolean = pcr.ifthen(subdomains_final == nr, pcr.boolean(1.0)) xmin, ymin, xmax, ymax = boundingBox(mask_selected_boolean) area_in_degree2 = (xmax - xmin) * (ymax - ymin) print( str(nr) + " ; " + str(area_in_degree2) + " ; " + str((xmax - xmin)) + " ; " + str((ymax - ymin))) print("") print("") print("") print("Number of subdomains: " + str(num_of_masks)) print("") print("") print("") # spatial extrapolation in order to cover the entire map print("spatial interpolation/extrapolation to cover the entire map") field = subdomains_final cellID = pcr.nominal(pcr.uniqueid(pcr.defined(field))) zoneID = pcr.spreadzone(cellID, 0, 1) field = pcr.areamajority(field, zoneID) subdomains_final_filled = field pcr.aguila(subdomains_final_filled) pcr.report(subdomains_final_filled, "global_subdomains_30min_final_filled.map")
def dynamic(self): ##################### # * dynamic section # ##################### #-evaluation of the current date: return current month and the time step used #-reading in fluxes over land and water area for current time step [m/d] # and read in reservoir demand and surface water extraction [m3] try: self.landSurfaceQ = clippedRead.get( pcrm.generateNameT(landSurfaceQFileName, self.currentTimeStep())) except: pass try: self.potWaterSurfaceQ = clippedRead.get( pcrm.generateNameT(waterSurfaceQFileName, self.currentTimeStep())) except: pass #-surface water extraction and reservoir demand currently set to zero, should # be computed automatically and updated to reservoirs self.potSurfaceWaterExtraction = pcr.spatial(pcr.scalar(0.)) #self.waterBodies.demand= #self.reservoirDemandTSS.assignID(self.waterBodies.ID,self.currentTimeStep(),0.)*self.timeSec #-initialization of cumulative values of actual water extractions self.actWaterSurfaceQ = pcr.spatial(pcr.scalar(0.)) self.actSurfaceWaterExtraction = pcr.spatial(pcr.scalar(0.)) #-definition of sub-loop for routing scheme - explicit scheme has to satisfy Courant condition timeLimit= pcr.cellvalue(pcr.mapminimum((pcr.cover(pcr.ifthen(self.waterBodies.distribution == 0,\ self.channelLength/self.flowVelocity),\ self.timeSec/self.nrIterDefault)*self.timeSec/self.nrIterDefault)**0.5),1)[0] nrIter = int(self.timeSec / timeLimit) nrIter = min(nrIter, int(self.timeSec / 300.)) while float(self.timeSec / nrIter) % 1 <> 0: nrIter += 1 deltaTime = self.timeSec / nrIter #-sub-loop for current time step if self.currentDate.day == 1 or nrIter >= 24: print '\n*\tprocessing %s, currently using %d substeps of %d seconds\n' % \ (self.currentDate.date(),nrIter,deltaTime) #-update discharge and storage for nrICur in range(nrIter): #-initializing discharge for the current sub-timestep and fill in values # for channels and at outlets of waterbodies # * channels * estQ= pcr.ifthenelse((self.actualStorage > 0.) & (self.waterBodies.distribution == 0) ,\ (self.wettedArea/self.alphaQ)**(1./self.betaQ),0.) #estQ= pcr.ifthenelse((self.actualStorage > 0.) & (self.waterBodies.distribution == 0) ,\ #0.5*(self.Q+(self.wettedArea/self.alphaQ)**(1./self.betaQ)),0.) #estQ= pcr.min(estQ,self.actualStorage/deltaTime) self.report(estQ, 'results/qest') self.Q = pcr.spatial(pcr.scalar(0.)) self.Q= pcr.ifthenelse(self.waterBodies.distribution == 0,\ pcr.kinematic(self.channelLDD,estQ,0.,self.alphaQ,\ self.betaQ,1,deltaTime,self.channelLength),self.Q) # * water bodies * self.waterBodies.dischargeUpdate() self.Q = self.waterBodies.returnMapValue(self.Q, self.waterBodies.actualQ) #-fluxes and resulting change in storage: first the local fluxes are evaluated # and aggregated over the water bodies where applicable; this includes the specific runoff [m/day/m2] # from input and the estimated extraction from surface water as volume per day [m3/day]; # specific runoff from the land surface is always positive whereas the fluxes over the water surface # are potential, including discharge, and are adjusted to match the availabe storage; to this end, # surface water storage and fluxes over water bodies are totalized and assigned to the outlet; # discharge is updated in a separate step, after vertical fluxes are compared to the actual storage deltaActualStorage= ((self.landFraction*self.landSurfaceQ+\ self.waterFraction*self.potWaterSurfaceQ)*self.cellArea-\ self.potSurfaceWaterExtraction)*float(self.duration)/nrIter deltaActualStorage= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(deltaActualStorage,self.waterBodies.distribution),0),\ deltaActualStorage) adjustmentRatio= pcr.ifthenelse(deltaActualStorage < 0.,\ pcr.min(1.,-self.actualStorage/deltaActualStorage),1.) self.actWaterSurfaceQ += adjustmentRatio * self.potWaterSurfaceQ self.actSurfaceWaterExtraction += adjustmentRatio * self.actSurfaceWaterExtraction deltaActualStorage *= adjustmentRatio #-local water balance check if testLocalWaterBalance: differenceActualStorage = self.actualStorage differenceActualStorage += deltaActualStorage #-overall water balance check: net input self.cumulativeDeltaStorage += pcr.catchmenttotal( deltaActualStorage, self.LDD) #-update storage first with local changes, then balance discharge with storage and update storage # with lateral flow and return value to water bodies self.actualStorage += deltaActualStorage self.actualStorage = pcr.max(0., self.actualStorage) self.Q = pcr.min(self.Q, self.actualStorage / deltaTime) deltaActualStorage = (-self.Q + pcr.upstream(self.LDD, self.Q)) * deltaTime deltaActualStorage= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(deltaActualStorage,self.waterBodies.distribution),0),\ deltaActualStorage) self.actualStorage += deltaActualStorage self.actualStorage = pcr.max(0., self.actualStorage) self.waterBodies.actualStorage = self.waterBodies.retrieveMapValue( self.actualStorage) #-flooded fraction returned floodedFraction,floodedDepth,\ self.wettedArea,self.alphaQ= self.kinAlphaComposite(self.actualStorage,self.floodplainMask) self.wettedArea= self.waterBodies.returnMapValue(self.wettedArea,\ self.waterBodies.channelWidth+2.*self.waterBodies.updateWaterHeight()) self.waterFraction= pcr.ifthenelse(self.waterBodies.distribution == 0,\ pcr.max(self.waterFractionMask,floodedFraction),self.waterFractionMask) self.landFraction = pcr.max(0., 1. - self.waterFraction) self.flowVelocity = pcr.ifthenelse(self.wettedArea > 0, self.Q / self.wettedArea, 0.) #-local water balance check if testLocalWaterBalance: differenceActualStorage += deltaActualStorage differenceActualStorage -= self.actualStorage totalDifference = pcr.cellvalue( pcr.maptotal(differenceActualStorage), 1)[0] minimumDifference = pcr.cellvalue( pcr.mapminimum(differenceActualStorage), 1)[0] maximumDifference = pcr.cellvalue( pcr.mapmaximum(differenceActualStorage), 1)[0] if abs(totalDifference) > 1.e-3: print 'water balance error: total %e; min %e; max %e' %\ (totalDifference,minimumDifference,maximumDifference) if reportLocalWaterBalance: pcr.report(differenceActualStorage, 'mbe_%s.map' % self.currentDate.date()) #-overall water balance check: updating cumulative discharge and total storage [m3] self.totalDischarge += self.Q * deltaTime self.totalStorage = pcr.catchmenttotal(self.actualStorage, self.LDD) #-check on occurrence of last day and report mass balance if self.currentDate == self.endDate: #-report initial maps pcr.report(self.Q, self.QIniMap) pcr.report(self.actualStorage, self.actualStorageIniMap) #-return relative and absolute water balance error per cell and # as total at basin outlets self.totalDischarge= pcr.ifthen((self.waterBodies.distribution == 0) | \ (self.waterBodies.location != 0),self.totalDischarge) self.cumulativeDeltaStorage= pcr.ifthen((self.waterBodies.distribution == 0) | \ (self.waterBodies.location != 0),self.cumulativeDeltaStorage) massBalanceError= self.totalStorage+self.totalDischarge-\ self.cumulativeDeltaStorage relMassBalanceError = 1. + pcr.ifthenelse( self.cumulativeDeltaStorage <> 0., massBalanceError / self.cumulativeDeltaStorage, 0.) totalMassBalanceError= pcr.cellvalue(pcr.maptotal(pcr.ifthen(self.basinOutlet,\ massBalanceError)),1)[0] totalCumulativeDeltaStorage= pcr.cellvalue(pcr.maptotal(pcr.ifthen(self.basinOutlet,\ self.cumulativeDeltaStorage)),1)[0] if totalCumulativeDeltaStorage > 0: totalRelativeMassBalanceError = 1. + totalMassBalanceError / totalCumulativeDeltaStorage else: totalRelativeMassBalanceError = 1. #-report maps and echo value pcr.report(massBalanceError, mbeFileName) pcr.report(relMassBalanceError, mbrFileName) print '\n*\ttotal global mass balance error [m3]: %8.3g' % totalMassBalanceError print '\n*\trelative global mass balance error [-]: %5.3f' % totalRelativeMassBalanceError #-echo to screen: total mass balance error and completion of run print '\trun completed' #-end of day: return states and fluxes #-get surface water attributes? if getSurfaceWaterAttributes: #-compute the following secondary variables: # surface water area [m2]: area given dynamic surface water fraction # residence time [days]: volume over discharge, assigned -1 in case discharge is zero # surface water depth [m], weighed by channel and floodplain volume surfaceWaterArea = self.waterFraction * self.cellArea surfaceWaterArea= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(surfaceWaterArea,self.waterBodies.distribution),0),\ surfaceWaterArea) surfaceWaterResidenceTime = pcr.ifthenelse( self.Q > 0., self.actualStorage / (self.Q * self.timeSec), -1) surfaceWaterDepth= pcr.ifthenelse(self.actualStorage > 0.,\ pcr.max(0.,self.actualStorage-self.channelStorageCapacity)**2/\ (self.actualStorage*surfaceWaterArea),0.) surfaceWaterDepth+= pcr.ifthenelse(self.actualStorage > 0.,\ pcr.min(self.channelStorageCapacity,self.actualStorage)**2/(self.waterFractionMask*\ self.cellArea*self.actualStorage),0.) #-reports: values at outlet of lakes or reservoirs are assigned to their full extent self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterArea,self.waterBodies.distribution),surfaceWaterArea),\ surfaceWaterAreaFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterResidenceTime,self.waterBodies.distribution),surfaceWaterResidenceTime),\ surfaceWaterResidenceTimeFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterDepth,self.waterBodies.distribution),surfaceWaterDepth),\ surfaceWaterDepthFileName) #-reports on standard output: values at outlet of lakes or reservoirs are assigned to their full extent self.report( pcr.ifthenelse( self.waterBodies.distribution != 0, pcr.areamaximum(self.flowVelocity, self.waterBodies.distribution), self.flowVelocity), flowVelocityFileName) self.report( pcr.ifthenelse( self.waterBodies.distribution != 0, pcr.areamaximum(self.Q, self.waterBodies.distribution), self.Q), QFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution == 0,\ floodedFraction,0.),floodedFractionFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution == 0,\ floodedDepth,0.),floodedDepthFileName) self.report(self.actualStorage, actualStorageFileName) #-update date for time step and report relevant daily output self.currentDate = self.currentDate + datetime.timedelta(self.duration)
hydro_stats_all.columns.name = None hydro_stats_all.rename(index={'reference_FM_dQdh': 'reference'}, inplace=True) hydro_stats_all = pd.concat([hydro_stats_all, dikeraise_km], axis=1) print hydro_stats_all #%% calculate number of owners involved in the measure. restraints_dir = os.path.join(input_dir, 'restraints') owner_nr = pcr.readmap(os.path.join(restraints_dir, 'owner_nr.map')) # Rasterized from 'Nr_Gerechtigde' from cadastral map, removes multiple owners owners_per_cell = pcr.readmap( os.path.join(restraints_dir, 'owner_point_number.map')) # number of owners per cell, from dissolve >> point >> point2raster (count) # mask out areas from owner_nr with multiple ownners owner_total = pcr.areatotal(owners_per_cell, owner_nr) import gdal, ogr def pcr2Shapefile(srcMap, dstShape, fieldName): """ polygonize a pcraster map into a shapefile srcMap: string, path to PCRaster map dstShape: string, path to shapefile fieldName: string, name of the item in the shapefile """ gdal.UseExceptions() #-create a new shapefile driver = ogr.GetDriverByName("ESRI Shapefile")
def __init__(self, startDate, endDate, nrIterDefault=12.): pcrm.DynamicModel.__init__(self) ############## # * __init__ # ############## #-echo to screen print 'PCR-GLOBWB dynamic floodplain model - version 3.0 June 2012' print '\tbeta version with smoothed floodplain elevations' print '\tincluding lakes and reservoirs' #-constants: duration of time step (day) in seconds self.timeSec = duration * timeSec #-passing global variables to local ones #-cloone and cell area self.clone = clone self.cellArea = cellArea #-model settings self.nrIterDefault = nrIterDefault self.duration = duration self.currentDate = startDate self.endDate = endDate self.areaFractions = areaFractions self.relZFileName = os.path.join(mapsDir, relZFileName) self.reductionKK = reductionKK self.criterionKK = criterionKK #-number of entries in list and derived slopes and volumes self.nrEntries = len(self.areaFractions) self.relZ = [0.] * self.nrEntries self.floodVolume = [0.] * (self.nrEntries) #-flood plain and channel characteristics self.channelGradient = pcr.max(1.e-7, channelGradient) self.LDD = LDD self.channelWidth = channelWidth self.channelLength = channelLength self.channelDepth = channelDepth self.channelManN = channelManN self.floodplainManN = floodplainManN self.floodplainMask = floodplainMask self.waterFractionMask = fractionWater #-waterBodies self.waterBodies = waterBodies self.waterBodies.actualArea= self.waterBodies.retrieveMapValue(pcr.areatotal(self.waterFractionMask*\ self.cellArea,self.waterBodies.distribution)) #self.reservoirDemandTSS= readTSS(reservoirDemandTSS) #-map names: initial maps of discharge and storage self.QIniMap = pcrm.generateNameT(QFileName, 0).replace('.000', '.ini') self.actualStorageIniMap = pcrm.generateNameT(actualStorageFileName, 0).replace( '.000', '.ini') self.averageQ = averageQ self.bankfulQ = bankfulQ #-patch elevations: those that are part of sills are updated on the basis of the floodplain gradient # using local distances deltaX per increment upto z[N] and the sum over sills #-fill all lists including smoothing interval and slopes for iCnt in range(1, self.nrEntries): self.relZ[iCnt]= clippedRead.get(self.relZFileName %\ (self.areaFractions[iCnt]*100)) #-minimum slope of floodplain, being defined as the longest sill, first used to retrieve # longest cumulative distance deltaX = [self.cellArea**0.5] * self.nrEntries deltaX[0] = 0. sumX = deltaX[:] minSlope = 0. for iCnt in range(self.nrEntries): if iCnt < self.nrEntries - 1: deltaX[iCnt] = (self.areaFractions[iCnt + 1]**0.5 - self.areaFractions[iCnt]**0.5) * deltaX[iCnt] else: deltaX[iCnt] = ( 1. - self.areaFractions[iCnt - 1]**0.5) * deltaX[iCnt] if iCnt > 0: sumX[iCnt] = pcr.ifthenelse( self.relZ[iCnt] == self.relZ[iCnt - 1], sumX[iCnt - 1] + deltaX[iCnt], 0.) minSlope= pcr.ifthenelse(self.relZ[iCnt] == self.relZ[iCnt-1],\ pcr.max(sumX[iCnt],minSlope),minSlope) minSlope = pcr.min(self.channelGradient, 0.5 * pcr.max(deltaX[1], minSlope)**-1.) #-add small increment to elevations to each sill except in the case of lakes for iCnt in range(self.nrEntries): self.relZ[iCnt]= self.relZ[iCnt]+sumX[iCnt]*pcr.ifthenelse(self.relZ[self.nrEntries-1] > 0.,\ minSlope,0.) #-set slope and smoothing interval between dy= y(i+1)-y(i) and dx= x(i+1)-x(i) # on the basis of volume #-slope and smoothing interval self.kSlope = [0.] * (self.nrEntries) self.mInterval = [0.] * (self.nrEntries) for iCnt in range(1, self.nrEntries): self.floodVolume[iCnt]= self.floodVolume[iCnt-1]+\ 0.5*(self.areaFractions[iCnt]+self.areaFractions[iCnt-1])*\ (self.relZ[iCnt]-self.relZ[iCnt-1])*self.cellArea self.kSlope[iCnt-1]= (self.areaFractions[iCnt]-self.areaFractions[iCnt-1])/\ pcr.max(0.001,self.floodVolume[iCnt]-self.floodVolume[iCnt-1]) for iCnt in range(1, self.nrEntries): if iCnt < (self.nrEntries - 1): self.mInterval[iCnt]= 0.5*self.reductionKK*pcr.min(self.floodVolume[iCnt+1]-self.floodVolume[iCnt],\ self.floodVolume[iCnt]-self.floodVolume[iCnt-1]) else: self.mInterval[iCnt] = 0.5 * self.reductionKK * ( self.floodVolume[iCnt] - self.floodVolume[iCnt - 1])
def __init__(self, distributionMap, outletMap, typeMap, channelBreadthMap, averageQMap, bankfulQMap, LDDMap, parameterTBL, deltaTime, clippedRead): #-clippedRead self.clippedRead = clippedRead #-constants self.deltaTime = deltaTime self.MV = -999.9 self.cLake = 1.7 self.minLimit = 0.0 #-spatial field of nominal IDs delineating the extent of the respective waterbodies self.distribution = self.clippedRead.get(distributionMap, 'nominal') self.outlet = self.clippedRead.get(outletMap, 'nominal') waterBodiesType = self.clippedRead.get(typeMap, 'nominal') LDD = self.clippedRead.get(LDDMap, 'ldd') endorheicLakes= pcr.ifthen((pcr.areatotal(pcr.scalar(self.outlet != 0),self.distribution) == 0) & (self.distribution != 0),\ self.distribution) self.location= pcr.cover(pcr.ifthen(self.outlet != 0,self.outlet),\ pcr.ifthenelse((self.distribution != 0) & (LDD == 5),self.distribution,0)) pcr.report(self.location, 'maps/waterbodies_reportlocations.map') #-extract ID and location as row and column number for outlets; these are subsequently used to extract type from other maps tempIDArray = pcr2numpy(self.location, self.MV) nrRows, nrCols = tempIDArray.shape iCnt = 0 self.ID = np.ones((1)) * self.MV self.coordinates = np.ones((2)) * self.MV for row in xrange(nrRows): for col in xrange(nrCols): if tempIDArray[row, col] > 0: iCnt += 1 if iCnt > 1: self.ID = np.append(self.ID, tempIDArray[row, col]) self.coordinates= np.vstack((self.coordinates,\ np.array([row,col]))) else: self.ID = np.array([tempIDArray[row, col]]) self.coordinates = np.array([row, col]) #-process valid entries if self.ID[0] <> self.MV: #-reset nrRows to nr of rowwise entries in ID self.nrEntries = self.ID.shape[0] #-sort on ID indices = self.ID.argsort() self.ID = self.ID[indices] self.coordinates = self.coordinates[indices] else: self.nrEntries = None self.coordinates = np.array([]) #-read from maps: type, channel breadth and average discharge self.type = self.retrieveMapValue( self.clippedRead.get(typeMap, 'nominal')) self.channelWidth = self.retrieveMapValue( self.clippedRead.get(channelBreadthMap)) self.averageQ = self.retrieveMapValue( self.clippedRead.get(averageQMap)) self.bankfulQ = self.retrieveMapValue( self.clippedRead.get(bankfulQMap)) self.endorheic = self.retrieveMapValue(pcr.cover(endorheicLakes, 0)) #-set to zero, to be updated in script self.demand = np.zeros((self.nrEntries)) self.actualStorage = np.zeros((self.nrEntries)) self.actualArea = np.zeros((self.nrEntries)) self.actualQ = np.zeros((self.nrEntries)) #-read from table self.capacity = np.ones((self.nrEntries)) * self.MV self.maxLimit = np.ones((self.nrEntries)) * self.MV self.avParameter = np.ones((self.nrEntries)) * self.MV tempIDArray = np.loadtxt(parameterTBL) if self.nrEntries <> None: for iCnt in xrange(self.nrEntries): ID = self.ID[iCnt] mask = tempIDArray[:, 0] == ID if np.any(mask): #-entry in table with reservoir properties #-set capacity, fractional maximum storage limit and area-volume parameter self.capacity[iCnt] = tempIDArray[:, 1][mask] self.maxLimit[iCnt] = tempIDArray[:, 2][mask] self.avParameter[iCnt] = tempIDArray[:, 3][mask] else: #-lake or wetland: set capacity and upper limit to zero and the area-volume parameter # to default values self.capacity[iCnt] = 0. self.maxLimit[iCnt] = 0. if self.type[iCnt] == 1: #-lake self.avParameter[iCnt] = 210.5 else: #-wetland self.avParameter[iCnt] = 1407.2
def __init__(self,distributionMap,outletMap,typeMap,channelBreadthMap,averageQMap,bankfulQMap,LDDMap,parameterTBL,deltaTime,clippedRead): #-clippedRead self.clippedRead= clippedRead #-constants self.deltaTime= deltaTime self.MV= -999.9 self.cLake= 1.7 self.minLimit= 0.0 #-spatial field of nominal IDs delineating the extent of the respective waterbodies self.distribution= self.clippedRead.get(distributionMap,'nominal') self.outlet= self.clippedRead.get(outletMap,'nominal') waterBodiesType= self.clippedRead.get(typeMap,'nominal') LDD= self.clippedRead.get(LDDMap,'ldd') endorheicLakes= pcr.ifthen((pcr.areatotal(pcr.scalar(self.outlet != 0),self.distribution) == 0) & (self.distribution != 0),\ self.distribution) self.location= pcr.cover(pcr.ifthen(self.outlet != 0,self.outlet),\ pcr.ifthenelse((self.distribution != 0) & (LDD == 5),self.distribution,0)) pcr.report(self.location,'maps/waterbodies_reportlocations.map') #-extract ID and location as row and column number for outlets; these are subsequently used to extract type from other maps tempIDArray= pcr2numpy(self.location,self.MV) nrRows,nrCols= tempIDArray.shape iCnt= 0 self.ID= np.ones((1))*self.MV self.coordinates= np.ones((2))*self.MV for row in xrange(nrRows): for col in xrange(nrCols): if tempIDArray[row,col] > 0: iCnt+= 1 if iCnt > 1: self.ID= np.append(self.ID,tempIDArray[row,col]) self.coordinates= np.vstack((self.coordinates,\ np.array([row,col]))) else: self.ID= np.array([tempIDArray[row,col]]) self.coordinates= np.array([row,col]) #-process valid entries if self.ID[0] <> self.MV: #-reset nrRows to nr of rowwise entries in ID self.nrEntries= self.ID.shape[0] #-sort on ID indices= self.ID.argsort() self.ID= self.ID[indices] self.coordinates= self.coordinates[indices] else: self.nrEntries= None self.coordinates= np.array([]) #-read from maps: type, channel breadth and average discharge self.type= self.retrieveMapValue(self.clippedRead.get(typeMap,'nominal')) self.channelWidth= self.retrieveMapValue(self.clippedRead.get(channelBreadthMap)) self.averageQ= self.retrieveMapValue(self.clippedRead.get(averageQMap)) self.bankfulQ= self.retrieveMapValue(self.clippedRead.get(bankfulQMap)) self.endorheic= self.retrieveMapValue(pcr.cover(endorheicLakes,0)) #-set to zero, to be updated in script self.demand= np.zeros((self.nrEntries)) self.actualStorage= np.zeros((self.nrEntries)) self.actualArea= np.zeros((self.nrEntries)) self.actualQ= np.zeros((self.nrEntries)) #-read from table self.capacity= np.ones((self.nrEntries))*self.MV self.maxLimit= np.ones((self.nrEntries))*self.MV self.avParameter= np.ones((self.nrEntries))*self.MV tempIDArray= np.loadtxt(parameterTBL) if self.nrEntries <> None: for iCnt in xrange(self.nrEntries): ID= self.ID[iCnt] mask= tempIDArray[:,0] == ID if np.any(mask): #-entry in table with reservoir properties #-set capacity, fractional maximum storage limit and area-volume parameter self.capacity[iCnt]= tempIDArray[:,1][mask] self.maxLimit[iCnt]= tempIDArray[:,2][mask] self.avParameter[iCnt]= tempIDArray[:,3][mask] else: #-lake or wetland: set capacity and upper limit to zero and the area-volume parameter # to default values self.capacity[iCnt]= 0. self.maxLimit[iCnt]= 0. if self.type[iCnt] == 1: #-lake self.avParameter[iCnt]= 210.5 else: #-wetland self.avParameter[iCnt]= 1407.2
dem = pcr.cover(dem,linescover,pointscover) #pcr.report(dem,'dem1.map') dem = dem + burn #pcr.report(dem,'dem2.map') ldd = pcr.lddcreate(dem,float("1E35"),float("1E35"),float("1E35"),float("1E35")) else: ldd = pcr.lddcreate(dem,burnvalue/2,float("1E35"),float("1E35"),float("1E35")) streamorder = pcr.ordinal(pcr.streamorder(ldd)) river = pcr.boolean(pcr.ifthen(streamorder >= int(min(np.max(pcr.pcr2numpy(streamorder,-9999)),minorder)), streamorder)) outlets = pcr.ifthen(pcr.ordinal(ldd) == 5, pcr.boolean(1)) outlets = pcr.nominal(pcr.uniqueid(outlets)) catchments = pcr.nominal(pcr.catchment(ldd, outlets)) if not keepall: catchments = pcr.nominal(pcr.ifthen(pcr.mapmaximum(pcr.areatotal(pcr.scalar(catchments)*0+1,pcr.nominal(catchments))) == pcr.areatotal(pcr.scalar(catchments)*0+1,pcr.nominal(catchments)),catchments)) pcr.report(ldd,ldd_map) pcr.report(streamorder,streamorder_map) pcr.report(river,river_map) pcr.report(catchments,catchments_map) if not EPSG == None: call(('gdal_translate','-of','GTiff','-stats','-a_srs',EPSG,'-ot','Float32',catchments_map,catchments_tif)) else: call(('gdal_translate','-of','GTiff','-stats','-ot','Float32',catchments_map,catchments_tif)) wt.Raster2Pol(catchments_tif,catchshp,srs) riversid_map = workdir + 'riverid.map' drain_map = workdir + 'drain.map' ldd_mask = pcr.ifthen(river, ldd) upstream = pcr.upstream(ldd_mask, pcr.scalar(river)) downstream = pcr.downstream(ldd_mask, upstream)
def dynamic(self): ##################### # * dynamic section # ##################### #-evaluation of the current date: return current month and the time step used #-reading in fluxes over land and water area for current time step [m/d] # and read in reservoir demand and surface water extraction [m3] try: self.landSurfaceQ= clippedRead.get(pcrm.generateNameT(landSurfaceQFileName,self.currentTimeStep())) except: pass try: self.potWaterSurfaceQ= clippedRead.get(pcrm.generateNameT(waterSurfaceQFileName,self.currentTimeStep())) except: pass #-surface water extraction and reservoir demand currently set to zero, should # be computed automatically and updated to reservoirs self.potSurfaceWaterExtraction= pcr.spatial(pcr.scalar(0.)) #self.waterBodies.demand= #self.reservoirDemandTSS.assignID(self.waterBodies.ID,self.currentTimeStep(),0.)*self.timeSec #-initialization of cumulative values of actual water extractions self.actWaterSurfaceQ= pcr.spatial(pcr.scalar(0.)) self.actSurfaceWaterExtraction= pcr.spatial(pcr.scalar(0.)) #-definition of sub-loop for routing scheme - explicit scheme has to satisfy Courant condition timeLimit= pcr.cellvalue(pcr.mapminimum((pcr.cover(pcr.ifthen(self.waterBodies.distribution == 0,\ self.channelLength/self.flowVelocity),\ self.timeSec/self.nrIterDefault)*self.timeSec/self.nrIterDefault)**0.5),1)[0] nrIter= int(self.timeSec/timeLimit) nrIter= min(nrIter,int(self.timeSec/300.)) while float(self.timeSec/nrIter) % 1 <> 0: nrIter+= 1 deltaTime= self.timeSec/nrIter #-sub-loop for current time step if self.currentDate.day == 1 or nrIter >= 24: print '\n*\tprocessing %s, currently using %d substeps of %d seconds\n' % \ (self.currentDate.date(),nrIter,deltaTime) #-update discharge and storage for nrICur in range(nrIter): #-initializing discharge for the current sub-timestep and fill in values # for channels and at outlets of waterbodies # * channels * estQ= pcr.ifthenelse((self.actualStorage > 0.) & (self.waterBodies.distribution == 0) ,\ (self.wettedArea/self.alphaQ)**(1./self.betaQ),0.) #estQ= pcr.ifthenelse((self.actualStorage > 0.) & (self.waterBodies.distribution == 0) ,\ #0.5*(self.Q+(self.wettedArea/self.alphaQ)**(1./self.betaQ)),0.) #estQ= pcr.min(estQ,self.actualStorage/deltaTime) self.report(estQ,'results/qest') self.Q= pcr.spatial(pcr.scalar(0.)) self.Q= pcr.ifthenelse(self.waterBodies.distribution == 0,\ pcr.kinematic(self.channelLDD,estQ,0.,self.alphaQ,\ self.betaQ,1,deltaTime,self.channelLength),self.Q) # * water bodies * self.waterBodies.dischargeUpdate() self.Q= self.waterBodies.returnMapValue(self.Q,self.waterBodies.actualQ) #-fluxes and resulting change in storage: first the local fluxes are evaluated # and aggregated over the water bodies where applicable; this includes the specific runoff [m/day/m2] # from input and the estimated extraction from surface water as volume per day [m3/day]; # specific runoff from the land surface is always positive whereas the fluxes over the water surface # are potential, including discharge, and are adjusted to match the availabe storage; to this end, # surface water storage and fluxes over water bodies are totalized and assigned to the outlet; # discharge is updated in a separate step, after vertical fluxes are compared to the actual storage deltaActualStorage= ((self.landFraction*self.landSurfaceQ+\ self.waterFraction*self.potWaterSurfaceQ)*self.cellArea-\ self.potSurfaceWaterExtraction)*float(self.duration)/nrIter deltaActualStorage= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(deltaActualStorage,self.waterBodies.distribution),0),\ deltaActualStorage) adjustmentRatio= pcr.ifthenelse(deltaActualStorage < 0.,\ pcr.min(1.,-self.actualStorage/deltaActualStorage),1.) self.actWaterSurfaceQ+= adjustmentRatio*self.potWaterSurfaceQ self.actSurfaceWaterExtraction+= adjustmentRatio*self.actSurfaceWaterExtraction deltaActualStorage*= adjustmentRatio #-local water balance check if testLocalWaterBalance: differenceActualStorage= self.actualStorage differenceActualStorage+= deltaActualStorage #-overall water balance check: net input self.cumulativeDeltaStorage+= pcr.catchmenttotal(deltaActualStorage,self.LDD) #-update storage first with local changes, then balance discharge with storage and update storage # with lateral flow and return value to water bodies self.actualStorage+= deltaActualStorage self.actualStorage= pcr.max(0.,self.actualStorage) self.Q= pcr.min(self.Q,self.actualStorage/deltaTime) deltaActualStorage= (-self.Q+pcr.upstream(self.LDD,self.Q))*deltaTime deltaActualStorage= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(deltaActualStorage,self.waterBodies.distribution),0),\ deltaActualStorage) self.actualStorage+= deltaActualStorage self.actualStorage= pcr.max(0.,self.actualStorage) self.waterBodies.actualStorage= self.waterBodies.retrieveMapValue(self.actualStorage) #-flooded fraction returned floodedFraction,floodedDepth,\ self.wettedArea,self.alphaQ= self.kinAlphaComposite(self.actualStorage,self.floodplainMask) self.wettedArea= self.waterBodies.returnMapValue(self.wettedArea,\ self.waterBodies.channelWidth+2.*self.waterBodies.updateWaterHeight()) self.waterFraction= pcr.ifthenelse(self.waterBodies.distribution == 0,\ pcr.max(self.waterFractionMask,floodedFraction),self.waterFractionMask) self.landFraction= pcr.max(0.,1.-self.waterFraction) self.flowVelocity= pcr.ifthenelse(self.wettedArea > 0,self.Q/self.wettedArea,0.) #-local water balance check if testLocalWaterBalance: differenceActualStorage+= deltaActualStorage differenceActualStorage-= self.actualStorage totalDifference= pcr.cellvalue(pcr.maptotal(differenceActualStorage),1)[0] minimumDifference= pcr.cellvalue(pcr.mapminimum(differenceActualStorage),1)[0] maximumDifference= pcr.cellvalue(pcr.mapmaximum(differenceActualStorage),1)[0] if abs(totalDifference) > 1.e-3: print 'water balance error: total %e; min %e; max %e' %\ (totalDifference,minimumDifference,maximumDifference) if reportLocalWaterBalance: pcr.report(differenceActualStorage,'mbe_%s.map' % self.currentDate.date()) #-overall water balance check: updating cumulative discharge and total storage [m3] self.totalDischarge+= self.Q*deltaTime self.totalStorage= pcr.catchmenttotal(self.actualStorage,self.LDD) #-check on occurrence of last day and report mass balance if self.currentDate == self.endDate: #-report initial maps pcr.report(self.Q,self.QIniMap) pcr.report(self.actualStorage,self.actualStorageIniMap) #-return relative and absolute water balance error per cell and # as total at basin outlets self.totalDischarge= pcr.ifthen((self.waterBodies.distribution == 0) | \ (self.waterBodies.location != 0),self.totalDischarge) self.cumulativeDeltaStorage= pcr.ifthen((self.waterBodies.distribution == 0) | \ (self.waterBodies.location != 0),self.cumulativeDeltaStorage) massBalanceError= self.totalStorage+self.totalDischarge-\ self.cumulativeDeltaStorage relMassBalanceError= 1.+pcr.ifthenelse(self.cumulativeDeltaStorage <> 0., massBalanceError/self.cumulativeDeltaStorage,0.) totalMassBalanceError= pcr.cellvalue(pcr.maptotal(pcr.ifthen(self.basinOutlet,\ massBalanceError)),1)[0] totalCumulativeDeltaStorage= pcr.cellvalue(pcr.maptotal(pcr.ifthen(self.basinOutlet,\ self.cumulativeDeltaStorage)),1)[0] if totalCumulativeDeltaStorage > 0: totalRelativeMassBalanceError= 1.+totalMassBalanceError/totalCumulativeDeltaStorage else: totalRelativeMassBalanceError= 1. #-report maps and echo value pcr.report(massBalanceError,mbeFileName) pcr.report(relMassBalanceError,mbrFileName) print '\n*\ttotal global mass balance error [m3]: %8.3g' % totalMassBalanceError print '\n*\trelative global mass balance error [-]: %5.3f' % totalRelativeMassBalanceError #-echo to screen: total mass balance error and completion of run print '\trun completed' #-end of day: return states and fluxes #-get surface water attributes? if getSurfaceWaterAttributes: #-compute the following secondary variables: # surface water area [m2]: area given dynamic surface water fraction # residence time [days]: volume over discharge, assigned -1 in case discharge is zero # surface water depth [m], weighed by channel and floodplain volume surfaceWaterArea= self.waterFraction*self.cellArea surfaceWaterArea= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(surfaceWaterArea,self.waterBodies.distribution),0),\ surfaceWaterArea) surfaceWaterResidenceTime= pcr.ifthenelse(self.Q > 0.,self.actualStorage/(self.Q*self.timeSec),-1) surfaceWaterDepth= pcr.ifthenelse(self.actualStorage > 0.,\ pcr.max(0.,self.actualStorage-self.channelStorageCapacity)**2/\ (self.actualStorage*surfaceWaterArea),0.) surfaceWaterDepth+= pcr.ifthenelse(self.actualStorage > 0.,\ pcr.min(self.channelStorageCapacity,self.actualStorage)**2/(self.waterFractionMask*\ self.cellArea*self.actualStorage),0.) #-reports: values at outlet of lakes or reservoirs are assigned to their full extent self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterArea,self.waterBodies.distribution),surfaceWaterArea),\ surfaceWaterAreaFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterResidenceTime,self.waterBodies.distribution),surfaceWaterResidenceTime),\ surfaceWaterResidenceTimeFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterDepth,self.waterBodies.distribution),surfaceWaterDepth),\ surfaceWaterDepthFileName) #-reports on standard output: values at outlet of lakes or reservoirs are assigned to their full extent self.report(pcr.ifthenelse(self.waterBodies.distribution != 0, pcr.areamaximum(self.flowVelocity,self.waterBodies.distribution),self.flowVelocity),flowVelocityFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution != 0, pcr.areamaximum(self.Q,self.waterBodies.distribution),self.Q),QFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution == 0,\ floodedFraction,0.),floodedFractionFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution == 0,\ floodedDepth,0.),floodedDepthFileName) self.report(self.actualStorage,actualStorageFileName) #-update date for time step and report relevant daily output self.currentDate= self.currentDate+datetime.timedelta(self.duration)
def getParameterFiles( self, currTimeStep, cellArea, ldd, initial_condition_dictionary=None ): # parameters for Water Bodies: fracWat # waterBodyIds # waterBodyOut # waterBodyArea # waterBodyTyp # waterBodyCap # cell surface area (m2) and ldd self.cellArea = cellArea ldd = pcr.ifthen(self.landmask, ldd) # date used for accessing/extracting water body information date_used = currTimeStep.fulldate year_used = currTimeStep.year if self.onlyNaturalWaterBodies == True: date_used = self.dateForNaturalCondition year_used = self.dateForNaturalCondition[0:4] # fracWat = fraction of surface water bodies (dimensionless) self.fracWat = pcr.scalar(0.0) if self.useNetCDF: self.fracWat = vos.netcdf2PCRobjClone( self.ncFileInp, "fracWaterInp", date_used, useDoy="yearly", cloneMapFileName=self.cloneMap, ) else: self.fracWat = vos.readPCRmapClone( self.fracWaterInp + str(year_used) + ".map", self.cloneMap, self.tmpDir, self.inputDir, ) self.fracWat = pcr.cover(self.fracWat, 0.0) self.fracWat = pcr.max(0.0, self.fracWat) self.fracWat = pcr.min(1.0, self.fracWat) self.waterBodyIds = pcr.nominal(0) # waterBody ids self.waterBodyOut = pcr.boolean(0) # waterBody outlets self.waterBodyArea = pcr.scalar(0.0) # waterBody surface areas # water body ids if self.useNetCDF: self.waterBodyIds = vos.netcdf2PCRobjClone( self.ncFileInp, "waterBodyIds", date_used, useDoy="yearly", cloneMapFileName=self.cloneMap, ) else: self.waterBodyIds = vos.readPCRmapClone( self.waterBodyIdsInp + str(year_used) + ".map", self.cloneMap, self.tmpDir, self.inputDir, False, None, True, ) # self.waterBodyIds = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0.0, pcr.nominal(self.waterBodyIds) ) # water body outlets (correcting outlet positions) wbCatchment = pcr.catchmenttotal(pcr.scalar(1), ldd) self.waterBodyOut = pcr.ifthen( wbCatchment == pcr.areamaximum(wbCatchment, self.waterBodyIds), self.waterBodyIds, ) # = outlet ids self.waterBodyOut = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0.0, self.waterBodyOut ) # TODO: Please also consider endorheic lakes! # correcting water body ids self.waterBodyIds = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0.0, pcr.subcatchment(ldd, self.waterBodyOut), ) # boolean map for water body outlets: self.waterBodyOut = pcr.ifthen( pcr.scalar(self.waterBodyOut) > 0.0, pcr.boolean(1) ) # reservoir surface area (m2): if self.useNetCDF: resSfArea = ( 1000.0 * 1000.0 * vos.netcdf2PCRobjClone( self.ncFileInp, "resSfAreaInp", date_used, useDoy="yearly", cloneMapFileName=self.cloneMap, ) ) else: resSfArea = ( 1000.0 * 1000.0 * vos.readPCRmapClone( self.resSfAreaInp + str(year_used) + ".map", self.cloneMap, self.tmpDir, self.inputDir, ) ) resSfArea = pcr.areaaverage(resSfArea, self.waterBodyIds) resSfArea = pcr.cover(resSfArea, 0.0) # water body surface area (m2): (lakes and reservoirs) self.waterBodyArea = pcr.max( pcr.areatotal( pcr.cover(self.fracWat * self.cellArea, 0.0), self.waterBodyIds ), pcr.areaaverage(pcr.cover(resSfArea, 0.0), self.waterBodyIds), ) self.waterBodyArea = pcr.ifthen(self.waterBodyArea > 0.0, self.waterBodyArea) # correcting water body ids and outlets (exclude all water bodies with surfaceArea = 0) self.waterBodyIds = pcr.ifthen(self.waterBodyArea > 0.0, self.waterBodyIds) self.waterBodyOut = pcr.ifthen( pcr.boolean(self.waterBodyIds), self.waterBodyOut ) # water body types: # - 2 = reservoirs (regulated discharge) # - 1 = lakes (weirFormula) # - 0 = non lakes or reservoirs (e.g. wetland) self.waterBodyTyp = pcr.nominal(0) if self.useNetCDF: self.waterBodyTyp = vos.netcdf2PCRobjClone( self.ncFileInp, "waterBodyTyp", date_used, useDoy="yearly", cloneMapFileName=self.cloneMap, ) else: self.waterBodyTyp = vos.readPCRmapClone( self.waterBodyTypInp + str(year_used) + ".map", self.cloneMap, self.tmpDir, self.inputDir, False, None, True, ) # excluding wetlands (waterBodyTyp = 0) in all functions related to lakes/reservoirs # self.waterBodyTyp = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0, pcr.nominal(self.waterBodyTyp) ) self.waterBodyTyp = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0, pcr.nominal(self.waterBodyTyp) ) self.waterBodyTyp = pcr.areamajority( self.waterBodyTyp, self.waterBodyIds ) # choose only one type: either lake or reservoir self.waterBodyTyp = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0, pcr.nominal(self.waterBodyTyp) ) self.waterBodyTyp = pcr.ifthen( pcr.boolean(self.waterBodyIds), self.waterBodyTyp ) # correcting lakes and reservoirs ids and outlets self.waterBodyIds = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0, self.waterBodyIds ) self.waterBodyOut = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0, self.waterBodyOut ) # reservoir maximum capacity (m3): self.resMaxCap = pcr.scalar(0.0) self.waterBodyCap = pcr.scalar(0.0) if self.useNetCDF: self.resMaxCap = ( 1000.0 * 1000.0 * vos.netcdf2PCRobjClone( self.ncFileInp, "resMaxCapInp", date_used, useDoy="yearly", cloneMapFileName=self.cloneMap, ) ) else: self.resMaxCap = ( 1000.0 * 1000.0 * vos.readPCRmapClone( self.resMaxCapInp + str(year_used) + ".map", self.cloneMap, self.tmpDir, self.inputDir, ) ) self.resMaxCap = pcr.ifthen(self.resMaxCap > 0, self.resMaxCap) self.resMaxCap = pcr.areaaverage(self.resMaxCap, self.waterBodyIds) # water body capacity (m3): (lakes and reservoirs) self.waterBodyCap = pcr.cover( self.resMaxCap, 0.0 ) # Note: Most of lakes have capacities > 0. self.waterBodyCap = pcr.ifthen( pcr.boolean(self.waterBodyIds), self.waterBodyCap ) # correcting water body types: # Reservoirs that have zero capacities will be assumed as lakes. self.waterBodyTyp = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0.0, self.waterBodyTyp ) self.waterBodyTyp = pcr.ifthenelse( self.waterBodyCap > 0.0, self.waterBodyTyp, pcr.ifthenelse( pcr.scalar(self.waterBodyTyp) == 2, pcr.nominal(1), self.waterBodyTyp ), ) # final corrections: self.waterBodyTyp = pcr.ifthen( self.waterBodyArea > 0.0, self.waterBodyTyp ) # make sure that all lakes and/or reservoirs have surface areas self.waterBodyTyp = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0.0, self.waterBodyTyp ) # make sure that only types 1 and 2 will be considered in lake/reservoir functions self.waterBodyIds = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0.0, self.waterBodyIds ) # make sure that all lakes and/or reservoirs have ids self.waterBodyOut = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0.0, self.waterBodyOut ) # make sure that all lakes and/or reservoirs have outlets # for a natural run (self.onlyNaturalWaterBodies == True) # which uses only the year 1900, assume all reservoirs are lakes if ( self.onlyNaturalWaterBodies == True and date_used == self.dateForNaturalCondition ): logger.info( "Using only natural water bodies identified in the year 1900. All reservoirs in 1900 are assumed as lakes." ) self.waterBodyTyp = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0.0, pcr.nominal(1) ) # check that all lakes and/or reservoirs have types, ids, surface areas and outlets: test = ( pcr.defined(self.waterBodyTyp) & pcr.defined(self.waterBodyArea) & pcr.defined(self.waterBodyIds) & pcr.boolean( pcr.areamaximum(pcr.scalar(self.waterBodyOut), self.waterBodyIds) ) ) a, b, c = vos.getMinMaxMean(pcr.cover(pcr.scalar(test), 1.0) - pcr.scalar(1.0)) threshold = 1e-3 if abs(a) > threshold or abs(b) > threshold: logger.warning("Missing information in some lakes and/or reservoirs.") # at the beginning of simulation period (timeStepPCR = 1) # - we have to define/get the initial conditions # if currTimeStep.timeStepPCR == 1: self.getICs(initial_condition_dictionary) # For each new reservoir (introduced at the beginning of the year) # initiating storage, average inflow and outflow # self.waterBodyStorage = pcr.cover(self.waterBodyStorage, 0.0) self.avgInflow = pcr.cover(self.avgInflow, 0.0) self.avgOutflow = pcr.cover(self.avgOutflow, 0.0) # cropping only in the landmask region: self.fracWat = pcr.ifthen(self.landmask, self.fracWat) self.waterBodyIds = pcr.ifthen(self.landmask, self.waterBodyIds) self.waterBodyOut = pcr.ifthen(self.landmask, self.waterBodyOut) self.waterBodyArea = pcr.ifthen(self.landmask, self.waterBodyArea) self.waterBodyTyp = pcr.ifthen(self.landmask, self.waterBodyTyp) self.waterBodyCap = pcr.ifthen(self.landmask, self.waterBodyCap) self.waterBodyStorage = pcr.ifthen(self.landmask, self.waterBodyStorage) self.avgInflow = pcr.ifthen(self.landmask, self.avgInflow) self.avgOutflow = pcr.ifthen(self.landmask, self.avgOutflow)
# # water body outlet wbCatchment = pcr.catchmenttotal(pcr.scalar(1), ldd_map_low_resolution) water_body_outlet = pcr.ifthen(wbCatchment ==\ pcr.areamaximum(wbCatchment, \ water_body_id),\ water_body_id) # = outlet ids # This may give more than two outlets, particularly if there are more than one cells that have largest upstream areas # - make sure that there is only one outlet for each water body water_body_outlet = pcr.ifthen(\ pcr.areaorder(pcr.scalar( water_body_outlet), \ water_body_outlet) == 1., water_body_outlet) water_body_outlet = pcr.ifthen(\ pcr.scalar(water_body_outlet) > 0., water_body_outlet) # calculate overbank volume from reservoirs (and lakes) lake_reservoir_volume = pcr.areatotal(extreme_value_map, water_body_id) lake_reservoir_overbank_volume = pcr.cover( pcr.max(0.0, lake_reservoir_volume - reservoir_capacity), 0.0) #~ pcr.aguila(lake_reservoir_overbank_volume) # # transfer 75% of overbank volume to the downstream (several cells downstream) transfer_to_downstream = pcr.cover(\ pcr.ifthen(pcr.scalar(water_body_outlet) > 0., lake_reservoir_overbank_volume * 0.50), 0.0) transfer_to_downstream = pcr.upstream(ldd_map_low_resolution, transfer_to_downstream) transfer_to_downstream = pcr.upstream(ldd_map_low_resolution, transfer_to_downstream) transfer_to_downstream = pcr.upstream(ldd_map_low_resolution, transfer_to_downstream) extreme_value_map = transfer_to_downstream + \ pcr.ifthenelse(pcr.cover(pcr.scalar(water_body_id), 0.0) > 0.00, 0.00, extreme_value_map) # # the remaining overbank volume (50%) will be distributed to the shores lake_reservoir_overbank_volume = lake_reservoir_overbank_volume * 0.50
output['irrigation_water_consumption']['pcr_value'] = output['evaporation_from_irrigation']['pcr_value'] * \ vos.getValDivZero(output['irrigation_water_withdrawal']['pcr_value'], \ output['irrigation_water_withdrawal']['pcr_value'] +\ output['precipitation_at_irrigation']['pcr_value']) # upscaling to the class (country) units and writing to netcdf files and a table for var in output.keys(): print var # covering the map with zero pcrValue = pcr.cover(output[var]['pcr_value'], 0.0) # upscaling to the class (country) units and converting the units to km3/year if var != "area_equipped_with_irrigation": pcrValue = pcr.areatotal(pcrValue, uniqueIDs) / (1000. * 1000. * 1000.) else: pcrValue = pcr.areatotal(pcrValue, uniqueIDs) # write values to a netcdf file ncFileName = output[var]['file_name'] varField = pcr.pcr2numpy(pcrValue, vos.MV) tssNetCDF.writePCR2NetCDF(ncFileName, var, varField, timeStamp, posCnt = index - 1) # plot the values at sample cells only and write values to a temporary pcraster map pcrFileName = str(tmp_directory) + "/" + str(var) + ".tmp" pcr.report(pcr.ifthen(pcr.defined(uniqueIDs_sample), pcrValue), pcrFileName) # write class values to a table # - command line to call map2col cmd = 'map2col -x 1 -y 2 -m NA sample.ids'
def __init__(self,startDate,endDate,nrIterDefault= 12.): pcrm.DynamicModel.__init__(self) ############## # * __init__ # ############## #-echo to screen print 'PCR-GLOBWB dynamic floodplain model - version 3.0 June 2012' print '\tbeta version with smoothed floodplain elevations' print '\tincluding lakes and reservoirs' #-constants: duration of time step (day) in seconds self.timeSec= duration*timeSec #-passing global variables to local ones #-cloone and cell area self.clone= clone self.cellArea= cellArea #-model settings self.nrIterDefault= nrIterDefault self.duration= duration self.currentDate= startDate self.endDate= endDate self.areaFractions= areaFractions self.relZFileName= os.path.join(mapsDir,relZFileName) self.reductionKK= reductionKK self.criterionKK= criterionKK #-number of entries in list and derived slopes and volumes self.nrEntries= len(self.areaFractions) self.relZ= [0.]*self.nrEntries self.floodVolume= [0.]*(self.nrEntries) #-flood plain and channel characteristics self.channelGradient= pcr.max(1.e-7,channelGradient) self.LDD= LDD self.channelWidth= channelWidth self.channelLength= channelLength self.channelDepth= channelDepth self.channelManN= channelManN self.floodplainManN= floodplainManN self.floodplainMask= floodplainMask self.waterFractionMask= fractionWater #-waterBodies self.waterBodies= waterBodies self.waterBodies.actualArea= self.waterBodies.retrieveMapValue(pcr.areatotal(self.waterFractionMask*\ self.cellArea,self.waterBodies.distribution)) #self.reservoirDemandTSS= readTSS(reservoirDemandTSS) #-map names: initial maps of discharge and storage self.QIniMap= pcrm.generateNameT(QFileName,0).replace('.000','.ini') self.actualStorageIniMap= pcrm.generateNameT(actualStorageFileName,0).replace('.000','.ini') self.averageQ= averageQ self.bankfulQ= bankfulQ #-patch elevations: those that are part of sills are updated on the basis of the floodplain gradient # using local distances deltaX per increment upto z[N] and the sum over sills #-fill all lists including smoothing interval and slopes for iCnt in range(1,self.nrEntries): self.relZ[iCnt]= clippedRead.get(self.relZFileName %\ (self.areaFractions[iCnt]*100)) #-minimum slope of floodplain, being defined as the longest sill, first used to retrieve # longest cumulative distance deltaX= [self.cellArea**0.5]*self.nrEntries deltaX[0]= 0. sumX= deltaX[:] minSlope= 0. for iCnt in range(self.nrEntries): if iCnt < self.nrEntries-1: deltaX[iCnt]= (self.areaFractions[iCnt+1]**0.5-self.areaFractions[iCnt]**0.5)*deltaX[iCnt] else: deltaX[iCnt]= (1.-self.areaFractions[iCnt-1]**0.5)*deltaX[iCnt] if iCnt > 0: sumX[iCnt]= pcr.ifthenelse(self.relZ[iCnt] == self.relZ[iCnt-1],sumX[iCnt-1]+deltaX[iCnt],0.) minSlope= pcr.ifthenelse(self.relZ[iCnt] == self.relZ[iCnt-1],\ pcr.max(sumX[iCnt],minSlope),minSlope) minSlope= pcr.min(self.channelGradient,0.5*pcr.max(deltaX[1],minSlope)**-1.) #-add small increment to elevations to each sill except in the case of lakes for iCnt in range(self.nrEntries): self.relZ[iCnt]= self.relZ[iCnt]+sumX[iCnt]*pcr.ifthenelse(self.relZ[self.nrEntries-1] > 0.,\ minSlope,0.) #-set slope and smoothing interval between dy= y(i+1)-y(i) and dx= x(i+1)-x(i) # on the basis of volume #-slope and smoothing interval self.kSlope= [0.]*(self.nrEntries) self.mInterval= [0.]*(self.nrEntries) for iCnt in range(1,self.nrEntries): self.floodVolume[iCnt]= self.floodVolume[iCnt-1]+\ 0.5*(self.areaFractions[iCnt]+self.areaFractions[iCnt-1])*\ (self.relZ[iCnt]-self.relZ[iCnt-1])*self.cellArea self.kSlope[iCnt-1]= (self.areaFractions[iCnt]-self.areaFractions[iCnt-1])/\ pcr.max(0.001,self.floodVolume[iCnt]-self.floodVolume[iCnt-1]) for iCnt in range(1,self.nrEntries): if iCnt < (self.nrEntries-1): self.mInterval[iCnt]= 0.5*self.reductionKK*pcr.min(self.floodVolume[iCnt+1]-self.floodVolume[iCnt],\ self.floodVolume[iCnt]-self.floodVolume[iCnt-1]) else: self.mInterval[iCnt]= 0.5*self.reductionKK*(self.floodVolume[iCnt]-self.floodVolume[iCnt-1])
def __init__(self, iniItems,landmask,spinUp): object.__init__(self) self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask # option to activate water balance check self.debugWaterBalance = True if iniItems.routingOptions['debugWaterBalance'] == "False": self.debugWaterBalance = False if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign the recession coefficient parameter(s) self.recessionCoeff = vos.readPCRmapClone(\ iniItems.groundwaterOptions['recessionCoeff'], self.cloneMap,self.tmpDir,self.inputDir) else: groundwaterPropertiesNC = vos.getFullPath(\ iniItems.groundwaterOptions[\ 'groundwaterPropertiesNC'], self.inputDir) self.recessionCoeff = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'recessionCoeff',\ cloneMapFileName = self.cloneMap) # groundwater recession coefficient (day-1_ self.recessionCoeff = pcr.cover(self.recessionCoeff,0.00) self.recessionCoeff = pcr.min(1.0000,self.recessionCoeff) # if 'minRecessionCoeff' in iniItems.groundwaterOptions.keys(): minRecessionCoeff = float(iniItems.groundwaterOptions['minRecessionCoeff']) else: minRecessionCoeff = 1.0e-4 # This is the minimum value used in Van Beek et al. (2011). self.recessionCoeff = pcr.max(minRecessionCoeff,self.recessionCoeff) if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign aquifer specific yield self.specificYield = vos.readPCRmapClone(\ iniItems.groundwaterOptions['specificYield'], self.cloneMap,self.tmpDir,self.inputDir) else: self.specificYield = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'specificYield',\ cloneMapFileName = self.cloneMap) self.specificYield = pcr.cover(self.specificYield,0.0) self.specificYield = pcr.max(0.010,self.specificYield) # TODO: TO BE CHECKED: The resample process of specificYield self.specificYield = pcr.min(1.000,self.specificYield) if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign aquifer saturated conductivity self.kSatAquifer = vos.readPCRmapClone(\ iniItems.groundwaterOptions['kSatAquifer'], self.cloneMap,self.tmpDir,self.inputDir) else: self.kSatAquifer = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'kSatAquifer',\ cloneMapFileName = self.cloneMap) self.kSatAquifer = pcr.cover(self.kSatAquifer,0.0) self.kSatAquifer = pcr.max(0.010,self.kSatAquifer) # limitAbstraction options self.limitAbstraction = False if iniItems.landSurfaceOptions['limitAbstraction'] == "True": self.limitAbstraction = True # option for limitting fossil groundwater abstractions - This option is only defined for IWMI project self.limitFossilGroundwaterAbstraction = False if self.limitAbstraction == False and\ "extraOptionsforProjectWithIWMI" in iniItems.allSections and\ iniItems.extraOptionsforProjectWithIWMI['limitFossilGroundWaterAbstraction'] == "True": logger.info('Fossil groundwater abstraction limit is used (IWMI project).') self.limitFossilGroundwaterAbstraction = True # estimate of thickness (unit: mm) of aceesible groundwater: shallow and deep totalGroundwaterThickness = vos.readPCRmapClone(\ iniItems.extraOptionsforProjectWithIWMI['estimateOfTotalGroundwaterThickness'], self.cloneMap,self.tmpDir,self.inputDir) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 1.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 1.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 2.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 5.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 7.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.mapmaximum(totalGroundwaterThickness)) # set minimum thickness to 50 m: totalGroundwaterThickness = pcr.max(50.0, totalGroundwaterThickness) # estimate of capacity (unit: m) of renewable groundwater (shallow) storGroundwaterCap = pcr.cover( vos.readPCRmapClone(\ iniItems.extraOptionsforProjectWithIWMI['estimateOfRenewableGroundwaterCapacity'], self.cloneMap,self.tmpDir,self.inputDir),\ 0.0) # fossil groundwater capacity (unit: m) self.fossilWaterCap = pcr.max(0.0,\ totalGroundwaterThickness*self.specificYield - storGroundwaterCap) # option for limitting regional groundwater abstractions - This option is only defined self.limitRegionalAnnualGroundwaterAbstraction = False if "extraOptionsforProjectWithIWMI" in iniItems.allSections and\ iniItems.extraOptionsforProjectWithIWMI['limitRegionalAnnualGroundwaterAbstraction'] == "True": logger.info('Limit for regional groundwater abstraction is used (IWMI project).') self.limitRegionalAnnualGroundwaterAbstraction = True region_ids = vos.readPCRmapClone(\ iniItems.extraOptionsforProjectWithIWMI['regionIds'], self.cloneMap,self.tmpDir,self.inputDir) self.region_ids = pcr.nominal(region_ids) self.region_ids = pcr.ifthen(self.landmask, self.region_ids) self.regionalAnnualGroundwaterAbstractionLimit = vos.readPCRmapClone(\ iniItems.extraOptionsforProjectWithIWMI['pumpingCapacity'], self.cloneMap,self.tmpDir,self.inputDir) self.regionalAnnualGroundwaterAbstractionLimit = pcr.roundup(self.regionalAnnualGroundwaterAbstractionLimit*1000.)/1000. self.regionalAnnualGroundwaterAbstractionLimit = pcr.cover(self.regionalAnnualGroundwaterAbstractionLimit, 0.0) self.regionalAnnualGroundwaterAbstractionLimit *= 1000. * 1000. * 1000. # unit: m3/year self.regionalAnnualGroundwaterAbstractionLimit = pcr.ifthen(self.landmask,\ self.regionalAnnualGroundwaterAbstractionLimit) # zones at which water allocation (surface and groundwater allocation) is determined self.usingAllocSegments = False if iniItems.landSurfaceOptions['allocationSegmentsForGroundSurfaceWater'] != "None": self.usingAllocSegments = True # incorporating groundwater distribution network: if self.usingAllocSegments and self.limitAbstraction == False: self.allocSegments = vos.readPCRmapClone(\ iniItems.landSurfaceOptions['allocationSegmentsForGroundSurfaceWater'], self.cloneMap,self.tmpDir,self.inputDir,isLddMap=False,cover=None,isNomMap=True) self.allocSegments = pcr.ifthen(self.landmask, self.allocSegments) cellArea = vos.readPCRmapClone(\ iniItems.routingOptions['cellAreaMap'], self.cloneMap,self.tmpDir,self.inputDir) cellArea = pcr.ifthen(self.landmask, cellArea) # TODO: integrate this one with the one coming from the routing module self.segmentArea = pcr.areatotal(pcr.cover(cellArea, 0.0), self.allocSegments) self.segmentArea = pcr.ifthen(self.landmask, self.segmentArea) self.report = True try: self.outDailyTotNC = iniItems.groundwaterOptions['outDailyTotNC'].split(",") self.outMonthTotNC = iniItems.groundwaterOptions['outMonthTotNC'].split(",") self.outMonthAvgNC = iniItems.groundwaterOptions['outMonthAvgNC'].split(",") self.outMonthEndNC = iniItems.groundwaterOptions['outMonthEndNC'].split(",") self.outAnnuaTotNC = iniItems.groundwaterOptions['outAnnuaTotNC'].split(",") self.outAnnuaAvgNC = iniItems.groundwaterOptions['outAnnuaAvgNC'].split(",") self.outAnnuaEndNC = iniItems.groundwaterOptions['outAnnuaEndNC'].split(",") except: self.report = False if self.report == True: self.outNCDir = iniItems.outNCDir self.netcdfObj = PCR2netCDF(iniItems) # # daily output in netCDF files: if self.outDailyTotNC[0] != "None": for var in self.outDailyTotNC: # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_dailyTot.nc",\ var,"undefined") # MONTHly output in netCDF files: # - cummulative if self.outMonthTotNC[0] != "None": for var in self.outMonthTotNC: # initiating monthlyVarTot (accumulator variable): vars(self)[var+'MonthTot'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthTot.nc",\ var,"undefined") # - average if self.outMonthAvgNC[0] != "None": for var in self.outMonthAvgNC: # initiating monthlyTotAvg (accumulator variable) vars(self)[var+'MonthTot'] = None # initiating monthlyVarAvg: vars(self)[var+'MonthAvg'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthAvg.nc",\ var,"undefined") # - last day of the month if self.outMonthEndNC[0] != "None": for var in self.outMonthEndNC: # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthEnd.nc",\ var,"undefined") # YEARly output in netCDF files: # - cummulative if self.outAnnuaTotNC[0] != "None": for var in self.outAnnuaTotNC: # initiating yearly accumulator variable: vars(self)[var+'AnnuaTot'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaTot.nc",\ var,"undefined") # - average if self.outAnnuaAvgNC[0] != "None": for var in self.outAnnuaAvgNC: # initiating annualyVarAvg: vars(self)[var+'AnnuaAvg'] = None # initiating annualyTotAvg (accumulator variable) vars(self)[var+'AnnuaTot'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaAvg.nc",\ var,"undefined") # - last day of the year if self.outAnnuaEndNC[0] != "None": for var in self.outAnnuaEndNC: # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaEnd.nc",\ var,"undefined") #get initial conditions self.getICs(iniItems,spinUp)
# # water body outlet wbCatchment = pcr.catchmenttotal(pcr.scalar(1), ldd_map_low_resolution) water_body_outlet = pcr.ifthen(wbCatchment ==\ pcr.areamaximum(wbCatchment, \ water_body_id),\ water_body_id) # = outlet ids # This may give more than two outlets, particularly if there are more than one cells that have largest upstream areas # - make sure that there is only one outlet for each water body water_body_outlet = pcr.ifthen(\ pcr.areaorder(pcr.scalar( water_body_outlet), \ water_body_outlet) == 1., water_body_outlet) water_body_outlet = pcr.ifthen(\ pcr.scalar(water_body_outlet) > 0., water_body_outlet) # calculate overbank volume from reservoirs (and lakes) lake_reservoir_volume = pcr.areatotal(extreme_value_map, water_body_id) lake_reservoir_overbank_volume = pcr.cover( pcr.max(0.0, lake_reservoir_volume - reservoir_capacity), 0.0) #~ pcr.aguila(lake_reservoir_overbank_volume) # # transfer 75% of overbank volume to the downstream (several cells downstream) transfer_to_downstream = pcr.cover(\ pcr.ifthen(pcr.scalar(water_body_outlet) > 0., lake_reservoir_overbank_volume * 0.50), 0.0) transfer_to_downstream = pcr.upstream(ldd_map_low_resolution, transfer_to_downstream) transfer_to_downstream = pcr.upstream(ldd_map_low_resolution, transfer_to_downstream) transfer_to_downstream = pcr.upstream(ldd_map_low_resolution, transfer_to_downstream) extreme_value_map = transfer_to_downstream + \ pcr.ifthenelse(pcr.cover(pcr.scalar(water_body_id), 0.0) > 0.00, 0.00, extreme_value_map)
print fulldate monthRange = float(calendar.monthrange(int(iYear), int(iMonth))[1]) print(monthRange) index = index + 1 for iVar in range(0,len(varNames)): # reading values from the input netcdf files (30min) demand_volume_30min = vos.netcdf2PCRobjClone(inputDirectory+inputFiles[iVar],\ inputVarNames[iVar], fulldate, None, cloneMapFileName) * 1000.*1000./ monthRange # unit: m3/day demand_volume_30min = pcr.ifthen(landmask, demand_volume_30min) # demand in m/day demand = demand_volume_30min /\ pcr.areatotal(cellArea, uniqueIDs30min) # covering the map with zero pcrValue = pcr.cover(demand, 0.0) # unit: m/day # convert values to pcraster object varField = pcr.pcr2numpy(pcrValue, vos.MV) # write values to netcdf files tssNetCDF.writePCR2NetCDF(ncFileName,varNames[iVar],varField,timeStamp,posCnt = index - 1)
def getParameterFiles(self,currTimeStep,cellArea,ldd,\ initial_condition_dictionary = None,\ currTimeStepInDateTimeFormat = False): # parameters for Water Bodies: fracWat # waterBodyIds # waterBodyOut # waterBodyArea # waterBodyTyp # waterBodyCap # cell surface area (m2) and ldd self.cellArea = cellArea ldd = pcr.ifthen(self.landmask, ldd) # date used for accessing/extracting water body information if currTimeStepInDateTimeFormat: date_used = currTimeStep year_used = currTimeStep.year else: date_used = currTimeStep.fulldate year_used = currTimeStep.year if self.onlyNaturalWaterBodies == True: date_used = self.dateForNaturalCondition year_used = self.dateForNaturalCondition[0:4] # fracWat = fraction of surface water bodies (dimensionless) self.fracWat = pcr.scalar(0.0) if self.useNetCDF: self.fracWat = vos.netcdf2PCRobjClone(self.ncFileInp,'fracWaterInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.fracWat = vos.readPCRmapClone(\ self.fracWaterInp+str(year_used)+".map", self.cloneMap,self.tmpDir,self.inputDir) self.fracWat = pcr.cover(self.fracWat, 0.0) self.fracWat = pcr.max(0.0, self.fracWat) self.fracWat = pcr.min(1.0, self.fracWat) self.waterBodyIds = pcr.nominal(0) # waterBody ids self.waterBodyOut = pcr.boolean(0) # waterBody outlets self.waterBodyArea = pcr.scalar(0.) # waterBody surface areas # water body ids if self.useNetCDF: self.waterBodyIds = vos.netcdf2PCRobjClone(self.ncFileInp,'waterBodyIds', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.waterBodyIds = vos.readPCRmapClone(\ self.waterBodyIdsInp+str(year_used)+".map",\ self.cloneMap,self.tmpDir,self.inputDir,False,None,True) # self.waterBodyIds = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ pcr.nominal(self.waterBodyIds)) # water body outlets (correcting outlet positions) wbCatchment = pcr.catchmenttotal(pcr.scalar(1), ldd) self.waterBodyOut = pcr.ifthen(wbCatchment ==\ pcr.areamaximum(wbCatchment, \ self.waterBodyIds),\ self.waterBodyIds) # = outlet ids # This may give more than two outlets, particularly if there are more than one cells that have largest upstream areas # - make sure that there is only one outlet for each water body self.waterBodyOut = pcr.ifthen(\ pcr.areaorder(pcr.scalar(self.waterBodyOut), \ self.waterBodyOut) == 1., self.waterBodyOut) self.waterBodyOut = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ self.waterBodyOut) # TODO: Please also consider endorheic lakes! # correcting water body ids self.waterBodyIds = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ pcr.subcatchment(ldd,self.waterBodyOut)) # boolean map for water body outlets: self.waterBodyOut = pcr.ifthen(\ pcr.scalar(self.waterBodyOut) > 0.,\ pcr.boolean(1)) # reservoir surface area (m2): if self.useNetCDF: resSfArea = 1000. * 1000. * \ vos.netcdf2PCRobjClone(self.ncFileInp,'resSfAreaInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: resSfArea = 1000. * 1000. * vos.readPCRmapClone( self.resSfAreaInp+str(year_used)+".map",\ self.cloneMap,self.tmpDir,self.inputDir) resSfArea = pcr.areaaverage(resSfArea, self.waterBodyIds) resSfArea = pcr.cover(resSfArea, 0.) # water body surface area (m2): (lakes and reservoirs) self.waterBodyArea = pcr.max(pcr.areatotal(\ pcr.cover(\ self.fracWat*self.cellArea, 0.0), self.waterBodyIds), pcr.areaaverage(\ pcr.cover(resSfArea, 0.0) , self.waterBodyIds)) self.waterBodyArea = pcr.ifthen(self.waterBodyArea > 0.,\ self.waterBodyArea) # correcting water body ids and outlets (exclude all water bodies with surfaceArea = 0) self.waterBodyIds = pcr.ifthen(self.waterBodyArea > 0., self.waterBodyIds) self.waterBodyOut = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyOut) # water body types: # - 2 = reservoirs (regulated discharge) # - 1 = lakes (weirFormula) # - 0 = non lakes or reservoirs (e.g. wetland) self.waterBodyTyp = pcr.nominal(0) if self.useNetCDF: self.waterBodyTyp = vos.netcdf2PCRobjClone(self.ncFileInp,'waterBodyTyp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.waterBodyTyp = vos.readPCRmapClone( self.waterBodyTypInp+str(year_used)+".map",\ self.cloneMap,self.tmpDir,self.inputDir,False,None,True) # excluding wetlands (waterBodyTyp = 0) in all functions related to lakes/reservoirs # self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyTyp) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.areamajority(self.waterBodyTyp,\ self.waterBodyIds) # choose only one type: either lake or reservoir self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyTyp) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyTyp) # correcting lakes and reservoirs ids and outlets self.waterBodyIds = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0, self.waterBodyIds) self.waterBodyOut = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0, self.waterBodyOut) # reservoir maximum capacity (m3): self.resMaxCap = pcr.scalar(0.0) self.waterBodyCap = pcr.scalar(0.0) if self.useNetCDF: self.resMaxCap = 1000. * 1000. * \ vos.netcdf2PCRobjClone(self.ncFileInp,'resMaxCapInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.resMaxCap = 1000. * 1000. * vos.readPCRmapClone(\ self.resMaxCapInp+str(year_used)+".map", \ self.cloneMap,self.tmpDir,self.inputDir) self.resMaxCap = pcr.ifthen(self.resMaxCap > 0,\ self.resMaxCap) self.resMaxCap = pcr.areaaverage(self.resMaxCap,\ self.waterBodyIds) # water body capacity (m3): (lakes and reservoirs) self.waterBodyCap = pcr.cover( self.resMaxCap, 0.0) # Note: Most of lakes have capacities > 0. self.waterBodyCap = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyCap) # correcting water body types: # Reservoirs that have zero capacities will be assumed as lakes. self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyTyp) self.waterBodyTyp = pcr.ifthenelse(self.waterBodyCap > 0.,\ self.waterBodyTyp,\ pcr.ifthenelse(pcr.scalar(self.waterBodyTyp) == 2,\ pcr.nominal(1),\ self.waterBodyTyp)) # final corrections: self.waterBodyTyp = pcr.ifthen(self.waterBodyArea > 0.,\ self.waterBodyTyp) # make sure that all lakes and/or reservoirs have surface areas self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyTyp) # make sure that only types 1 and 2 will be considered in lake/reservoir functions self.waterBodyIds = pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyIds) # make sure that all lakes and/or reservoirs have ids self.waterBodyOut = pcr.ifthen(pcr.scalar(self.waterBodyIds) > 0.,\ self.waterBodyOut) # make sure that all lakes and/or reservoirs have outlets # for a natural run (self.onlyNaturalWaterBodies == True) # which uses only the year 1900, assume all reservoirs are lakes if self.onlyNaturalWaterBodies == True and date_used == self.dateForNaturalCondition: logger.info( "Using only natural water bodies identified in the year 1900. All reservoirs in 1900 are assumed as lakes." ) self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ pcr.nominal(1)) # check that all lakes and/or reservoirs have types, ids, surface areas and outlets: test = pcr.defined(self.waterBodyTyp) & pcr.defined(self.waterBodyArea) &\ pcr.defined(self.waterBodyIds) & pcr.boolean(pcr.areamaximum(pcr.scalar(self.waterBodyOut), self.waterBodyIds)) a, b, c = vos.getMinMaxMean( pcr.cover(pcr.scalar(test), 1.0) - pcr.scalar(1.0)) threshold = 1e-3 if abs(a) > threshold or abs(b) > threshold: logger.warning( "Missing information in some lakes and/or reservoirs.") # at the beginning of simulation period (timeStepPCR = 1) # - we have to define/get the initial conditions # if initial_condition_dictionary != None and currTimeStep.timeStepPCR == 1: self.getICs(initial_condition_dictionary) # For each new reservoir (introduced at the beginning of the year) # initiating storage, average inflow and outflow # PS: THIS IS NOT NEEDED FOR OFFLINE MODFLOW RUN! # try: self.waterBodyStorage = pcr.cover(self.waterBodyStorage, 0.0) self.avgInflow = pcr.cover(self.avgInflow, 0.0) self.avgOutflow = pcr.cover(self.avgOutflow, 0.0) self.waterBodyStorage = pcr.ifthen(self.landmask, self.waterBodyStorage) self.avgInflow = pcr.ifthen(self.landmask, self.avgInflow) self.avgOutflow = pcr.ifthen(self.landmask, self.avgOutflow) except: # PS: FOR OFFLINE MODFLOW RUN! pass # TODO: Remove try and except # cropping only in the landmask region: self.fracWat = pcr.ifthen(self.landmask, self.fracWat) self.waterBodyIds = pcr.ifthen(self.landmask, self.waterBodyIds) self.waterBodyOut = pcr.ifthen(self.landmask, self.waterBodyOut) self.waterBodyArea = pcr.ifthen(self.landmask, self.waterBodyArea) self.waterBodyTyp = pcr.ifthen(self.landmask, self.waterBodyTyp) self.waterBodyCap = pcr.ifthen(self.landmask, self.waterBodyCap)
if not initializeRoutingModel: pathIniSource= os.path.join(pathIni,modelSignature,'ini_%04d' % startYear) fractionWater= clippedRead.get(os.path.join(tempDir,'fracwat_%d.map' % initYear)) waterBodies= pcrglobWaterBodies(os.path.join(tempDir,'waterbodyid_%d.map' % initYear),\ os.path.join(tempDir,'waterbodyoutlet_%d.map' % initYear),os.path.join(tempDir,'waterbodytype_%d.map' % initYear),\ os.path.join(mapsDir,'channel_width.map'),os.path.join(pathIniSource,'qavg_longterm.map'),\ os.path.join(pathIniSource,'qbank_longterm.map'),LDDMap,os.path.join(tempDir,'reservoirparameters_%d_30min_.tbl' % initYear),timeSec,clippedRead) #-create initial files if the routing model is initialized if initializeRoutingModel: for variable in resStackList[iniOutVarStart:addOutVarStart]: targetFileName= os.path.join(pathIniSource,pcrm.generateNameT(variable,0).replace('.000','.ini')) if 'qc' in variable: pcr.report(pcr.scalar(0),targetFileName) elif 'wst'in variable: waterBodiesType= pcr.nominal(waterBodies.returnMapValue(pcr.spatial(pcr.scalar(0.)),waterBodies.type)) endorheicLakes= pcr.ifthenelse((pcr.areatotal(pcr.scalar(waterBodies.outlet != 0),waterBodies.distribution) == 0) & \ (waterBodies.distribution != 0),waterBodies.distribution,0) #-storage of water bodies is assigned at outlets #-storage over endorheic lakes actualStorage= pcr.ifthen(endorheicLakes != 0,\ pcr.upstream(LDD,pcr.ifthenelse((endorheicLakes == 0) & ((waterBodies.distribution == 0) | (waterBodies.outlet != 0)),\ averageQ,0))) actualStorage= pcr.ifthen((waterBodies.location != 0) & (endorheicLakes != 0),\ pcr.max(0.,pcr.areatotal(pcr.cover(actualStorage*timeSec*365.25+averageQWat,0),endorheicLakes))) #-storage over other water bodies actualStorage= pcr.cover(actualStorage,\ pcr.ifthen((waterBodiesType == 2) & (waterBodies.location != 0),\ waterBodies.returnMapValue(pcr.spatial(pcr.scalar(0.)),waterBodies.capacity*waterBodies.maxLimit)),\ pcr.ifthen((waterBodiesType == 1) & (waterBodies.location != 0),\ pcr.areatotal(fractionWater*cellArea,waterBodies.distribution)*(averageQ/(waterBodies.cLake*channelWidth))**(2./3.))) actualStorage= pcr.ifthen(waterBodies.distribution != 0,pcr.cover(actualStorage,0))
def __init__(self, iniItems,landmask,spinUp): object.__init__(self) self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask # option to activate water balance check self.debugWaterBalance = True if iniItems.routingOptions['debugWaterBalance'] == "False": self.debugWaterBalance = False if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign the recession coefficient parameter(s) self.recessionCoeff = vos.readPCRmapClone(\ iniItems.groundwaterOptions['recessionCoeff'], self.cloneMap,self.tmpDir,self.inputDir) else: groundwaterPropertiesNC = vos.getFullPath(\ iniItems.groundwaterOptions[\ 'groundwaterPropertiesNC'], self.inputDir) self.recessionCoeff = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'recessionCoeff',\ cloneMapFileName = self.cloneMap) # groundwater recession coefficient (day-1) self.recessionCoeff = pcr.cover(self.recessionCoeff,0.00) self.recessionCoeff = pcr.min(1.0000,self.recessionCoeff) # if 'minRecessionCoeff' in iniItems.groundwaterOptions.keys(): minRecessionCoeff = float(iniItems.groundwaterOptions['minRecessionCoeff']) else: minRecessionCoeff = 1.0e-4 # This is the minimum value used in Van Beek et al. (2011). self.recessionCoeff = pcr.max(minRecessionCoeff,self.recessionCoeff) if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign aquifer specific yield self.specificYield = vos.readPCRmapClone(\ iniItems.groundwaterOptions['specificYield'], self.cloneMap,self.tmpDir,self.inputDir) else: self.specificYield = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'specificYield',\ cloneMapFileName = self.cloneMap) self.specificYield = pcr.cover(self.specificYield,0.0) self.specificYield = pcr.max(0.010,self.specificYield) # TODO: TO BE CHECKED: The resample process of specificYield self.specificYield = pcr.min(1.000,self.specificYield) if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign aquifer saturated conductivity self.kSatAquifer = vos.readPCRmapClone(\ iniItems.groundwaterOptions['kSatAquifer'], self.cloneMap,self.tmpDir,self.inputDir) else: self.kSatAquifer = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'kSatAquifer',\ cloneMapFileName = self.cloneMap) self.kSatAquifer = pcr.cover(self.kSatAquifer,0.0) self.kSatAquifer = pcr.max(0.010,self.kSatAquifer) # limitAbstraction options self.limitAbstraction = False if iniItems.landSurfaceOptions['limitAbstraction'] == "True": self.limitAbstraction = True # option for limitting regional groundwater abstractions if iniItems.groundwaterOptions['pumpingCapacityNC'] != "None": logger.info('Limit for annual regional groundwater abstraction is used.') self.limitRegionalAnnualGroundwaterAbstraction = True self.pumpingCapacityNC = vos.getFullPath(\ iniItems.groundwaterOptions['pumpingCapacityNC'],self.inputDir,False) else: logger.warning('NO LIMIT for regional groundwater (annual) pumping. It may result too high groundwater abstraction.') self.limitRegionalAnnualGroundwaterAbstraction = False # option for limitting fossil groundwater abstractions: self.limitFossilGroundwaterAbstraction = False # # estimate of fossil groundwater capacity: if iniItems.groundwaterOptions['limitFossilGroundWaterAbstraction'] == "True": logger.info('Fossil groundwater abstractions are allowed with LIMIT.') self.limitFossilGroundwaterAbstraction = True # estimate of thickness (unit: m) of accesible groundwater: shallow and deep totalGroundwaterThickness = vos.readPCRmapClone(\ iniItems.groundwaterOptions['estimateOfTotalGroundwaterThickness'], self.cloneMap,self.tmpDir,self.inputDir) # extrapolation totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 1.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 1.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 2.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 5.0)) # totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, 0.0) # # set minimum thickness minimumThickness = pcr.scalar(float(\ iniItems.groundwaterOptions['minimumTotalGroundwaterThickness'])) totalGroundwaterThickness = pcr.max(minimumThickness, totalGroundwaterThickness) # # estimate of capacity (unit: m) of renewable groundwater (shallow) storGroundwaterCap = pcr.cover( vos.readPCRmapClone(\ iniItems.groundwaterOptions['estimateOfRenewableGroundwaterCapacity'], self.cloneMap,self.tmpDir,self.inputDir), 0.0) # # fossil groundwater capacity (unit: m) self.fossilWaterCap = pcr.ifthen(self.landmask,\ pcr.max(0.0,\ totalGroundwaterThickness*self.specificYield - storGroundwaterCap)) # zones at which groundwater allocations are determined self.usingAllocSegments = False if iniItems.landSurfaceOptions['allocationSegmentsForGroundSurfaceWater'] != "None": self.usingAllocSegments = True # incorporating groundwater distribution network: if self.usingAllocSegments: self.allocSegments = vos.readPCRmapClone(\ iniItems.landSurfaceOptions['allocationSegmentsForGroundSurfaceWater'], self.cloneMap,self.tmpDir,self.inputDir,isLddMap=False,cover=None,isNomMap=True) self.allocSegments = pcr.ifthen(self.landmask, self.allocSegments) cellArea = vos.readPCRmapClone(\ iniItems.routingOptions['cellAreaMap'], self.cloneMap,self.tmpDir,self.inputDir) cellArea = pcr.ifthen(self.landmask, cellArea) # TODO: integrate this one with the one coming from the routing module self.segmentArea = pcr.areatotal(pcr.cover(cellArea, 0.0), self.allocSegments) self.segmentArea = pcr.ifthen(self.landmask, self.segmentArea) # get initial conditions self.getICs(iniItems,spinUp) # initiate old style reporting # TODO: remove this! self.initiate_old_style_groundwater_reporting(iniItems)
output_files['tmp_folder'], None, False, None, True)) # set the cell areas for 5 arc-min and half arc-degree cells msg = "Setting the cell areas for 5 arc-min and half arc-degree cells" + ":" logger.info(msg) # - 5 arc-min cell_area = vos.readPCRmapClone(input_files['cell_area_05min'], clone_map_file, output_files['tmp_folder']) cell_area = pcr.ifthen(landmask, cell_area) # - 30 arc-min cell_area_30min = pcr.areatotal(cell_area, cell_ids_30min) # upscaling factor upscaling_factor = np.int(30.0 / 5.0) # netcdf general setup: netcdf_setup = {} netcdf_setup['format'] = "NETCDF4" netcdf_setup['zlib'] = True netcdf_setup['institution'] = "Utrecht University, Department of Physical Geography ; Deltares ; World Resources Institute" netcdf_setup['title' ] = "PCR-GLOBWB 2 output (post-processed for the Aqueduct Flood Analyzer): Annual Maxima of River Depth" netcdf_setup['created by' ] = "Edwin H. Sutanudjaja ([email protected])" netcdf_setup['description'] = 'The annual river depth maxima for each year/period starting from October of the year until September of its following year (for normal hydrological years) or ' +\ 'for each year/period starting from July of the year until June of its following year (for alternative hydrological years). "' netcdf_setup['source' ] = "Utrecht University, Department of Physical Geography - contact: Edwin H. Sutanudjaja ([email protected])" netcdf_setup['references' ] = "Sutanudjaja et al., in prep."
def volume_spread(ldd, hand, subcatch, volume, volume_thres=0., cell_surface=1., iterations=15, logging=logging, order=0, neg_HAND=None): """ Estimate 2D flooding from a 1D simulation per subcatchment reach Input: ldd -- pcraster object direction, local drain directions hand -- pcraster object float32, elevation data normalised to nearest drain subcatch -- pcraster object ordinal, subcatchments with IDs volume -- pcraster object float32, scalar flood volume (i.e. m3 volume outside the river bank within subcatchment) volume_thres=0. -- scalar threshold, at least this amount of m3 of volume should be present in a catchment area_multiplier=1. -- in case the maps are not in m2, set a multiplier other than 1. to convert iterations=15 -- number of iterations to use neg_HAND -- if set to 1, HAND maps can have negative values when elevation outside of stream is lower than stream (for example when there are natural embankments) Output: inundation -- pcraster object float32, scalar inundation estimate """ #initial values pcr.setglobaloption("unitcell") dem_min = pcr.areaminimum(hand, subcatch) # minimum elevation in subcatchments dem_norm = hand - dem_min # surface of each subcatchment surface = pcr.areaarea(subcatch) * pcr.areaaverage( cell_surface, subcatch) # area_multiplier error_abs = pcr.scalar(1e10) # initial error (very high) volume_catch = pcr.areatotal(volume, subcatch) depth_catch = volume_catch / surface # meters water disc averaged over subcatchment # ilt(depth_catch, 'depth_catch_{:02d}.map'.format(order)) # pcr.report(volume, 'volume_{:02d}.map'.format(order)) if neg_HAND == 1: dem_max = pcr.ifthenelse( volume_catch > volume_thres, pcr.scalar(32.), pcr.scalar(-32.)) # bizarre high inundation depth☻ dem_min = pcr.scalar(-32.) else: dem_max = pcr.ifthenelse( volume_catch > volume_thres, pcr.scalar(32.), pcr.scalar(0.)) # bizarre high inundation depth☻ dem_min = pcr.scalar(0.) for n in range(iterations): logging.debug('Iteration: {:02d}'.format(n + 1)) #####while np.logical_and(error_abs > error_thres, dem_min < dem_max): dem_av = (dem_min + dem_max) / 2 # compute value at dem_av average_depth_catch = pcr.areaaverage(pcr.max(dem_av - dem_norm, 0), subcatch) error = pcr.cover((depth_catch - average_depth_catch) / depth_catch, depth_catch * 0) dem_min = pcr.ifthenelse(error > 0, dem_av, dem_min) dem_max = pcr.ifthenelse(error <= 0, dem_av, dem_max) inundation = pcr.max(dem_av - dem_norm, 0) pcr.setglobaloption('unittrue') return inundation
def dynamic(self): """ dynamic part of the indicator calculation module """ settings = LisSettings.instance() binding = settings.binding option = settings.options maskinfo = MaskInfo.instance() if option['TransientLandUseChange']: self.var.Population = readnetcdf(binding['PopulationMaps'], self.var.currentTimeStep()) self.var.RegionPopulation = np.take( np.bincount(self.var.WUseRegionC, weights=self.var.Population), self.var.WUseRegionC) # population sum in Regions if option['wateruse'] and option['indicator']: # check if it is the last monthly or annual time step next_date_time = self.var.CalendarDate + datetime.timedelta( seconds=int(binding["DtSec"])) self.var.monthend = next_date_time.month != self.var.CalendarDate.month self.var.yearend = next_date_time.year != self.var.CalendarDate.year # sum up every day self.var.DayCounter = self.var.DayCounter + 1.0 self.var.MonthETpotMM = self.var.MonthETpotMM + self.var.ETRef self.var.MonthETactMM = self.var.MonthETactMM + self.var.deffraction( self.var.TaInterception ) + self.var.TaPixel + self.var.ESActPixel if option['openwaterevapo']: self.var.MonthETactMM += self.var.EvaAddM3 * self.var.M3toMM self.var.MonthETdifMM = np.maximum( (self.var.MonthETpotMM - self.var.MonthETactMM) * self.var.LandUseMask, maskinfo.in_zero()) # ; land use mask can be used to mask out deserts and high mountains, where no agriculture is possible self.var.MonthWDemandM3 = self.var.MonthWDemandM3 + self.var.TotalDemandM3 self.var.MonthWAbstractionM3 = self.var.MonthWAbstractionM3 + self.var.TotalAbstractionFromSurfaceWaterM3 + self.var.ReservoirAbstractionM3 + self.var.LakeAbstractionM3 + self.var.TotalAbstractionFromGroundwaterM3 self.var.MonthWConsumptionM3 = self.var.MonthWConsumptionM3 + self.var.WUseAddM3 + self.var.ReservoirAbstractionM3 + self.var.LakeAbstractionM3 + self.var.TotalAbstractionFromGroundwaterM3 self.var.MonthDisM3 = self.var.MonthDisM3 + self.var.ChanQAvg * self.var.DtSec self.var.MonthWaterAbstractedfromLakesReservoirsM3 = self.var.MonthWaterAbstractedfromLakesReservoirsM3 + self.var.ReservoirAbstractionM3 + self.var.LakeAbstractionM3 self.var.RegionMonthIrrigationShortageM3 = self.var.RegionMonthIrrigationShortageM3 + self.var.AreatotalIrrigationShortageM3 # INTERNAL FLOW self.var.MonthInternalFlowM3 = self.var.MonthInternalFlowM3 + self.var.ToChanM3Runoff # -------------------------------------------------------------------------- if self.var.monthend: # INTERNAL FLOW if option['simulateReservoirs'] or option['simulateLakes']: # available LakeStorageM3 and ReservoirStorageM3 for potential abstraction at end of month in region self.var.RegionMonthReservoirAndLakeStorageM3 = np.take( np.bincount(self.var.WUseRegionC, weights=(self.var.ReservoirStorageM3 + self.var.LakeStorageM3)), self.var.WUseRegionC) # monthly abstraction from lakes and reservoirs self.var.RegionMonthWaterAbstractedfromLakesReservoirsM3 = np.take( np.bincount(self.var.WUseRegionC, weights=self.var. MonthWaterAbstractedfromLakesReservoirsM3), self.var.WUseRegionC) #PerMonthInternalFlowM3 = areatotal(cover(decompress(self.var.MonthInternalFlow),0.0),wreg) self.var.RegionMonthInternalFlowM3 = np.take( np.bincount(self.var.WUseRegionC, weights=self.var.MonthInternalFlowM3), self.var.WUseRegionC) # note Reservoir and Lake storage need to be taken into account seperately # EXTERNAL FLOW wreg = decompress(self.var.WUseRegionC) # to pcraster map because of the following expression! self.var.RegionMonthExternalInflowM3 = compressArray( areatotal( cover( ifthen( self.var.WaterRegionInflowPoints != 0, upstream(self.var.LddStructuresKinematic, decompress(self.var.MonthDisM3))), 0), wreg)) self.var.RegionMonthWAbstractionM3 = np.take( np.bincount(self.var.WUseRegionC, weights=self.var.MonthWAbstractionM3), self.var.WUseRegionC) self.var.RegionMonthWConsumptionM3 = np.take( np.bincount(self.var.WUseRegionC, weights=self.var.MonthWConsumptionM3), self.var.WUseRegionC) self.var.RegionMonthWDemandM3 = np.take( np.bincount(self.var.WUseRegionC, weights=self.var.MonthWDemandM3), self.var.WUseRegionC) # Calculation of WEI: everything in m3, totalled over the water region UpstreamInflowM3 = self.var.RegionMonthExternalInflowM3 LocalFreshwaterM3 = self.var.RegionMonthInternalFlowM3 # still to be decided if reservoir and lake water availability is added here LocalTotalWaterDemandM3 = self.var.RegionMonthWDemandM3 RemainingDemandM3 = np.maximum( LocalTotalWaterDemandM3 - LocalFreshwaterM3, 0.0) # this is the demand that cannot be met by local water supply UpstreamInflowUsedM3 = np.minimum(RemainingDemandM3, UpstreamInflowM3) # the amount of upstream water an area really depends on FossilGroundwaterUsedM3 = np.maximum( RemainingDemandM3 - UpstreamInflowUsedM3, 0.0) # the amount of water that cannot be met locally nor with international water # likely this is the amount of water drawn from deep groundwater self.var.WEI_Cns = np.where( (UpstreamInflowM3 + LocalFreshwaterM3) > 0.0, self.var.RegionMonthWConsumptionM3 / (UpstreamInflowM3 + LocalFreshwaterM3), 0.0) self.var.WEI_Abs = np.where( (UpstreamInflowM3 + LocalFreshwaterM3) > 0.0, self.var.RegionMonthWAbstractionM3 / (UpstreamInflowM3 + LocalFreshwaterM3), 0.0) self.var.WEI_Dem = np.where( (UpstreamInflowM3 + LocalFreshwaterM3) > 0.0, self.var.RegionMonthWDemandM3 / (UpstreamInflowM3 + LocalFreshwaterM3), 0.0) self.var.WaterSustainabilityIndex = np.where( LocalTotalWaterDemandM3 > 0.0, FossilGroundwaterUsedM3 / (LocalTotalWaterDemandM3 + 1), 0.0) # De Roo 2015: WTI, if above zero, indicates that situation is unsustainable # if index is 0 means sustainable situtation: no groundwater or desalination water used # if index is 1 means area relies completely on groundwater or desalination water # the '+1' is to prevent division by small values, leading to very large and misleading indicator values self.var.WaterDependencyIndex = np.where( LocalTotalWaterDemandM3 > 0.0, UpstreamInflowUsedM3 / (LocalTotalWaterDemandM3 + 1), 0.0) # De Roo 2015: WDI, dependency on upstreamwater, as a fraction of the total local demand # the '+1' is to prevent division by small values, leading to very large and misleading indicator values self.var.WaterSecurityIndex = np.where( UpstreamInflowM3 > 0.0, UpstreamInflowUsedM3 / (UpstreamInflowM3 + 1), 0.0) # De Roo 2015: WSI, indicates the vulnerability to the available upstream water; # if only 10% of upstream inflow is use, WSI would be 0.1 indicating low vulnerability # if WSI is close to 1, situation is very vulnerable # the '+1' is to prevent division by small values, leading to very large and misleading indicator values self.var.FalkenmarkM3Capita1 = np.where( self.var.RegionPopulation > 0.0, self.var.RegionMonthInternalFlowM3 * 12 / self.var.RegionPopulation, maskinfo.in_zero()) self.var.FalkenmarkM3Capita2 = np.where( self.var.RegionPopulation > 0.0, LocalFreshwaterM3 * 12 / self.var.RegionPopulation, maskinfo.in_zero()) self.var.FalkenmarkM3Capita3 = np.where( self.var.RegionPopulation > 0.0, (UpstreamInflowM3 + LocalFreshwaterM3) * 12 / self.var.RegionPopulation, maskinfo.in_zero())
def checkWaterBalance(self, storesAtBeginning, storesAtEnd): # for the entire modules: snow + interception + soil + groundwater + waterDemand # except: river/routing irrGrossDemand = pcr.ifthen(self.landmask,\ self.landSurface.irrGrossDemand) # unit: m nonIrrGrossDemand = \ pcr.ifthen(self.landmask,\ self.landSurface.nonIrrGrossDemand) # unit: m precipitation = pcr.ifthen(self.landmask,\ self.meteo.precipitation) # unit: m surfaceWaterInf = pcr.ifthen(self.landmask,\ self.groundwater.surfaceWaterInf) surfaceWaterAbstraction = \ pcr.ifthen(self.landmask,\ self.landSurface.actSurfaceWaterAbstract) nonFossilGroundwaterAbs = pcr.ifthen(self.landmask,self.groundwater.nonFossilGroundwaterAbs) unmetDemand = pcr.ifthen(self.landmask,\ self.groundwater.unmetDemand) # PS: We assume that unmetDemand is extracted (only) to satisfy local demand. runoff = pcr.ifthen(self.landmask,self.routing.runoff) actualET = pcr.ifthen(self.landmask,\ self.landSurface.actualET) vos.waterBalanceCheck([precipitation,surfaceWaterInf,irrGrossDemand],\ [actualET,runoff,nonFossilGroundwaterAbs],\ [storesAtBeginning],\ [storesAtEnd],\ 'all modules (including water demand), but except river/routing',\ True,\ self._modelTime.fulldate,threshold=1e-3) if self.landSurface.usingAllocSegments: allocSurfaceWaterAbstract = \ pcr.ifthen(self.landmask,\ self.landSurface.allocSurfaceWaterAbstract) allocNonFossilGroundwaterAbs = \ pcr.ifthen(self.landmask,\ self.groundwater.allocNonFossilGroundwater) allocUnmetDemand = unmetDemand # PS: We assume that unmetDemand is extracted (only) to satisfy local demand. segTotalDemand = pcr.areatotal( pcr.cover((irrGrossDemand+nonIrrGrossDemand) * self.routing.cellArea, 0.0), self.landSurface.allocSegments) / self.landSurface.segmentArea segAllocSurfaceWaterAbstract = pcr.areatotal( pcr.cover(allocSurfaceWaterAbstract * self.routing.cellArea, 0.0), self.landSurface.allocSegments) / self.landSurface.segmentArea segAllocNonFossilGroundwaterAbs = pcr.areatotal( pcr.cover(allocNonFossilGroundwaterAbs * self.routing.cellArea, 0.0), self.landSurface.allocSegments) / self.landSurface.segmentArea segAllocUnmetDemand = pcr.areatotal( pcr.cover(allocUnmetDemand * self.routing.cellArea, 0.0), self.landSurface.allocSegments) / self.landSurface.segmentArea vos.waterBalanceCheck([segTotalDemand],\ [segAllocSurfaceWaterAbstract,segAllocNonFossilGroundwaterAbs,segAllocUnmetDemand],\ [pcr.scalar(0.0)],\ [pcr.scalar(0.0)],\ 'Water balance error in water allocation (per zone). Note that error here is most likely due to rounding error (32 bit implementation of pcraster)',\ True,\ self._modelTime.fulldate,threshold=5e-3) else: vos.waterBalanceCheck([irrGrossDemand,nonIrrGrossDemand],\ [surfaceWaterAbstraction,nonFossilGroundwaterAbs,unmetDemand],\ [pcr.scalar(0.0)],\ [pcr.scalar(0.0)],\ 'Water balance error in water allocation.',\ True,\ self._modelTime.fulldate,threshold=1e-3)
def getParameterFiles(self, date_given, cellArea, ldd): # parameters for Water Bodies: fracWat # waterBodyIds # waterBodyOut # waterBodyArea # waterBodyTyp # waterBodyCap # cell surface area (m2) and ldd self.cellArea = cellArea ldd = pcr.ifthen(self.landmask, ldd) # date and year used for accessing/extracting water body information date_used = date_given if self.onlyNaturalWaterBodies == True: date_used = self.dateForNaturalCondition year_used = date_used[0:4] # fracWat = fraction of surface water bodies (dimensionless) self.fracWat = pcr.scalar(0.0) if self.useNetCDF: self.fracWat = vos.netcdf2PCRobjClone(self.ncFileInp,'fracWaterInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) self.fracWat = pcr.cover(self.fracWat, 0.0) self.fracWat = pcr.max(0.0, self.fracWat) self.fracWat = pcr.min(1.0, self.fracWat) self.waterBodyIds = pcr.nominal(0) # waterBody ids self.waterBodyOut = pcr.boolean(0) # waterBody outlets self.waterBodyArea = pcr.scalar(0.) # waterBody surface areas # water body ids if self.useNetCDF: self.waterBodyIds = vos.netcdf2PCRobjClone(self.ncFileInp,'waterBodyIds', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) self.waterBodyIds = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ pcr.nominal(self.waterBodyIds)) # water body outlets (correcting outlet positions) wbCatchment = pcr.catchmenttotal(pcr.scalar(1), ldd) self.waterBodyOut = pcr.ifthen(wbCatchment ==\ pcr.areamaximum(wbCatchment, \ self.waterBodyIds),\ self.waterBodyIds) # = outlet ids self.waterBodyOut = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ self.waterBodyOut) # TODO: Please also consider endorheic lakes! # correcting water body ids self.waterBodyIds = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ pcr.subcatchment(ldd,self.waterBodyOut)) # boolean map for water body outlets: self.waterBodyOut = pcr.ifthen(\ pcr.scalar(self.waterBodyOut) > 0.,\ pcr.boolean(1)) # reservoir surface area (m2): if self.useNetCDF: resSfArea = 1000. * 1000. * \ vos.netcdf2PCRobjClone(self.ncFileInp,'resSfAreaInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) resSfArea = pcr.areaaverage(resSfArea, self.waterBodyIds) resSfArea = pcr.cover(resSfArea, 0.) # water body surface area (m2): (lakes and reservoirs) self.waterBodyArea = pcr.max(pcr.areatotal(\ pcr.cover(\ self.fracWat*self.cellArea, 0.0), self.waterBodyIds), pcr.areaaverage(\ pcr.cover(resSfArea, 0.0) , self.waterBodyIds)) self.waterBodyArea = pcr.ifthen(self.waterBodyArea > 0.,\ self.waterBodyArea) # correcting water body ids and outlets (exclude all water bodies with surfaceArea = 0) self.waterBodyIds = pcr.ifthen(self.waterBodyArea > 0., self.waterBodyIds) self.waterBodyOut = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyOut) # water body types: # - 2 = reservoirs (regulated discharge) # - 1 = lakes (weirFormula) # - 0 = non lakes or reservoirs (e.g. wetland) self.waterBodyTyp = pcr.nominal(0) if self.useNetCDF: self.waterBodyTyp = vos.netcdf2PCRobjClone(self.ncFileInp,'waterBodyTyp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) # excluding wetlands (waterBodyTyp = 0) in all functions related to lakes/reservoirs # self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyTyp) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.areamajority(self.waterBodyTyp,\ self.waterBodyIds) # choose only one type: either lake or reservoir self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyTyp) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyTyp) # correcting lakes and reservoirs ids and outlets self.waterBodyIds = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0, self.waterBodyIds) self.waterBodyOut = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0, self.waterBodyOut) # reservoir maximum capacity (m3): self.resMaxCap = pcr.scalar(0.0) self.waterBodyCap = pcr.scalar(0.0) if self.useNetCDF: self.resMaxCap = 1000. * 1000. * \ vos.netcdf2PCRobjClone(self.ncFileInp,'resMaxCapInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) self.resMaxCap = pcr.ifthen(self.resMaxCap > 0,\ self.resMaxCap) self.resMaxCap = pcr.areaaverage(self.resMaxCap,\ self.waterBodyIds) # water body capacity (m3): (lakes and reservoirs) self.waterBodyCap = pcr.cover( self.resMaxCap, 0.0) # Note: Most of lakes have capacities > 0. self.waterBodyCap = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyCap) # correcting water body types: # Reservoirs that have zero capacities will be assumed as lakes. self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyTyp) self.waterBodyTyp = pcr.ifthenelse(self.waterBodyCap > 0.,\ self.waterBodyTyp,\ pcr.ifthenelse(pcr.scalar(self.waterBodyTyp) == 2,\ pcr.nominal(1),\ self.waterBodyTyp)) # final corrections: self.waterBodyTyp = pcr.ifthen(self.waterBodyArea > 0.,\ self.waterBodyTyp) # make sure that all lakes and/or reservoirs have surface areas self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyTyp) # make sure that only types 1 and 2 will be considered in lake/reservoir functions self.waterBodyIds = pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyIds) # make sure that all lakes and/or reservoirs have ids self.waterBodyOut = pcr.ifthen(pcr.scalar(self.waterBodyIds) > 0.,\ self.waterBodyOut) # make sure that all lakes and/or reservoirs have outlets # for a natural run (self.onlyNaturalWaterBodies == True) # which uses only the year 1900, assume all reservoirs are lakes if self.onlyNaturalWaterBodies == True and date_used == self.dateForNaturalCondition: logger.info( "Using only natural water bodies identified in the year 1900. All reservoirs in 1900 are assumed as lakes." ) self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ pcr.nominal(1)) # check that all lakes and/or reservoirs have types, ids, surface areas and outlets: test = pcr.defined(self.waterBodyTyp) & pcr.defined(self.waterBodyArea) &\ pcr.defined(self.waterBodyIds) & pcr.boolean(pcr.areamaximum(pcr.scalar(self.waterBodyOut), self.waterBodyIds)) a, b, c = vos.getMinMaxMean( pcr.cover(pcr.scalar(test), 1.0) - pcr.scalar(1.0)) threshold = 1e-3 if abs(a) > threshold or abs(b) > threshold: logger.warning( "Missing information in some lakes and/or reservoirs.") # cropping only in the landmask region: self.fracWat = pcr.ifthen(self.landmask, self.fracWat) self.waterBodyIds = pcr.ifthen(self.landmask, self.waterBodyIds) self.waterBodyOut = pcr.ifthen(self.landmask, self.waterBodyOut) self.waterBodyArea = pcr.ifthen(self.landmask, self.waterBodyArea) self.waterBodyTyp = pcr.ifthen(self.landmask, self.waterBodyTyp) self.waterBodyCap = pcr.ifthen(self.landmask, self.waterBodyCap)
def main(): """ :ivar masterdem: digital elevation model :ivar dem: digital elevation model :ivar river: optional river map """ # Default values strRiver = 8 masterdem = "dem.map" step1dir = "step1" step2dir = "step2" workdir = "." inifile = "wflow_prepare.ini" recreate = False snapgaugestoriver = False try: opts, args = getopt.getopt(sys.argv[1:], "W:hI:f",['version']) except getopt.error as msg: usage(msg) for o, a in opts: if o == "-W": workdir = a if o == "-I": inifile = a if o == "-h": usage() if o == "-f": recreate = True if o == "--version": import wflow print("wflow version: ", wflow.__version__) sys.exit(0) pcr.setglobaloption("unitcell") os.chdir(workdir) config = OpenConf(workdir + "/" + inifile) masterdem = configget(config, "files", "masterdem", "dem.map") pcr.setclone(masterdem) strRiver = int(configget(config, "settings", "riverorder", "4")) try: gauges_x = config.get("settings", "gauges_x") gauges_y = config.get("settings", "gauges_y") except: print("gauges_x and gauges_y are required entries in the ini file") sys.exit(1) step1dir = configget(config, "directories", "step1dir", "step1") step2dir = configget(config, "directories", "step2dir", "step2") # upscalefactor = float(config.get("settings","upscalefactor")) corevolume = float(configget(config, "settings", "corevolume", "1E35")) catchmentprecipitation = float( configget(config, "settings", "catchmentprecipitation", "1E35") ) corearea = float(configget(config, "settings", "corearea", "1E35")) outflowdepth = float(configget(config, "settings", "lddoutflowdepth", "1E35")) initialscale = int(configget(config, "settings", "initialscale", "1")) csize = float(configget(config, "settings", "cellsize", "1")) snapgaugestoriver = bool( int(configget(config, "settings", "snapgaugestoriver", "1")) ) lddglobaloption = configget(config, "settings", "lddglobaloption", "lddout") pcr.setglobaloption(lddglobaloption) lu_water = configget(config, "files", "lu_water", "") lu_paved = configget(config, "files", "lu_paved", "") # X/Y coordinates of the gauges the system X = np.fromstring(gauges_x, sep=',') Y = np.fromstring(gauges_y, sep=',') tr.Verbose = 1 # make the directories to save results in if not os.path.isdir(step1dir + "/"): os.makedirs(step1dir) if not os.path.isdir(step2dir): os.makedirs(step2dir) if initialscale > 1: print("Initial scaling of DEM...") os.system( "resample -r " + str(initialscale) + " " + masterdem + " " + step1dir + "/dem_scaled.map" ) print("Reading dem...") dem = pcr.readmap(step1dir + "/dem_scaled.map") ldddem = dem else: print ("Reading dem...") dem = pcr.readmap(masterdem) ldddem = dem try: catchmask = config.get("files", "catchment_mask") except: print("No catchment mask...") else: print("clipping DEM with mask.....") mask = pcr.readmap(catchmask) ldddem = pcr.ifthen(pcr.boolean(mask), ldddem) dem = pcr.ifthen(pcr.boolean(mask), dem) # See if there is a shape file of the river to burn in try: rivshp = config.get("files", "river") except: print("no river file specified") outletpointX = float(configget(config, "settings", "outflowpointX", "0.0")) outletpointY = float(configget(config, "settings", "outflowpointY", "0.0")) else: print("river file specified.....") try: outletpointX = float(configget(config, "settings", "outflowpointX", "0.0")) outletpointY = float(configget(config, "settings", "outflowpointY", "0.0")) except: print( "Need to specify the river outletpoint (a point at the end of the river within the current map)" ) exit(1) outletpointmap = tr.points_to_map(dem, outletpointX, outletpointY, 0.5) pcr.report(outletpointmap, step1dir + "/outletpoint.map") # rivshpattr = config.get("files","riverattr") pcr.report(dem * 0.0, step1dir + "/nilmap.map") thestr = ( "gdal_translate -of GTiff " + step1dir + "/nilmap.map " + step1dir + "/riverburn.tif" ) os.system(thestr) rivshpattr = os.path.splitext(os.path.basename(rivshp))[0] os.system( "gdal_rasterize -burn 1 -l " + rivshpattr + " " + rivshp + " " + step1dir + "/riverburn.tif" ) thestr = ( "gdal_translate -of PCRaster " + step1dir + "/riverburn.tif " + step1dir + "/riverburn.map" ) os.system(thestr) riverburn = pcr.readmap(step1dir + "/riverburn.map") # Determine regional slope assuming that is the way the river should run # Determine regional slope assuming that is the way the river should run # pcr.setglobaloption("unitcell") # demregional=pcr.windowaverage(dem,100) ldddem = pcr.ifthenelse(riverburn >= 1.0, dem - 1000, dem) pcr.setglobaloption("unittrue") upscalefactor = int(csize / pcr.celllength()) print("Creating ldd...") ldd = tr.lddcreate_save( step1dir + "/ldd.map", ldddem, recreate, outflowdepth=outflowdepth, corevolume=corevolume, catchmentprecipitation=catchmentprecipitation, corearea=corearea, ) print("Determining streamorder...") stro = pcr.streamorder(ldd) pcr.report(stro, step1dir + "/streamorder.map") strdir = pcr.ifthen(stro >= strRiver, stro) pcr.report(strdir, step1dir + "/streamorderrive.map") pcr.report(pcr.boolean(pcr.ifthen(stro >= strRiver, stro)), step1dir + "/rivers.map") pcr.setglobaloption("unittrue") # outlet (and other gauges if given) # TODO: check is x/y set if not skip this print("Outlet...") outlmap = tr.points_to_map(dem, X, Y, 0.5) if snapgaugestoriver: print("Snapping gauges to nearest river cells...") pcr.report(outlmap, step1dir + "/orggauges.map") outlmap = tr.snaptomap(outlmap, strdir) # noutletmap = tr.points_to_map(dem,XX,YY,0.5) # pcr.report(noutletmap,'noutlet.map') pcr.report(outlmap, step1dir + "/gauges.map") # check if there is a pre-define catchment map try: catchmask = config.get("files", "catchment_mask") except: print("No catchment mask, finding outlet") # Find catchment (overall) outlet = tr.find_outlet(ldd) sub = tr.subcatch(ldd, outlet) pcr.report(sub, step1dir + "/catchment_overall.map") else: print("reading and converting catchment mask.....") os.system( "resample -r " + str(initialscale) + " " + catchmask + " " + step1dir + "/catchment_overall.map" ) sub = pcr.readmap(step1dir + "/catchment_overall.map") print("Scatch...") sd = tr.subcatch(ldd, pcr.ifthen(outlmap > 0, outlmap)) pcr.report(sd, step1dir + "/scatch.map") pcr.setglobaloption("unitcell") print("Upscalefactor: " + str(upscalefactor)) if upscalefactor > 1: gc.collect() print("upscale river length1 (checkerboard map)...") ck = tr.checkerboard(dem, upscalefactor) pcr.report(ck, step1dir + "/ck.map") pcr.report(dem, step1dir + "/demck.map") print("upscale river length2...") fact = tr.area_riverlength_factor(ldd, ck, upscalefactor) pcr.report(fact, step1dir + "/riverlength_fact.map") # print("make dem statistics...") dem_ = pcr.areaaverage(dem, ck) pcr.report(dem_, step1dir + "/demavg.map") print("Create DEM statistics...") dem_ = pcr.areaminimum(dem, ck) pcr.report(dem_, step1dir + "/demmin.map") dem_ = pcr.areamaximum(dem, ck) pcr.report(dem_, step1dir + "/demmax.map") # calculate percentiles order = pcr.areaorder(dem, ck) n = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), ck) #: calculate 25 percentile perc = tr.area_percentile(dem, ck, n, order, 25.0) pcr.report(perc, step1dir + "/dem25.map") perc = tr.area_percentile(dem, ck, n, order, 10.0) pcr.report(perc, step1dir + "/dem10.map") perc = tr.area_percentile(dem, ck, n, order, 50.0) pcr.report(perc, step1dir + "/dem50.map") perc = tr.area_percentile(dem, ck, n, order, 33.0) pcr.report(perc, step1dir + "/dem33.map") perc = tr.area_percentile(dem, ck, n, order, 66.0) pcr.report(perc, step1dir + "/dem66.map") perc = tr.area_percentile(dem, ck, n, order, 75.0) pcr.report(perc, step1dir + "/dem75.map") perc = tr.area_percentile(dem, ck, n, order, 90.0) pcr.report(perc, step1dir + "/dem90.map") else: print("No fancy scaling done. Going strait to step2....") pcr.report(dem, step1dir + "/demavg.map") Xul = float(config.get("settings", "Xul")) Yul = float(config.get("settings", "Yul")) Xlr = float(config.get("settings", "Xlr")) Ylr = float(config.get("settings", "Ylr")) gdalstr = ( "gdal_translate -projwin " + str(Xul) + " " + str(Yul) + " " + str(Xlr) + " " + str(Ylr) + " -of PCRaster " ) # gdalstr = "gdal_translate -a_ullr " + str(Xul) + " " + str(Yul) + " " +str(Xlr) + " " +str(Ylr) + " -of PCRaster " print(gdalstr) pcr.report(pcr.cover(1.0), step1dir + "/wflow_riverlength_fact.map") # Now us gdat tp convert the maps os.system( gdalstr + step1dir + "/wflow_riverlength_fact.map" + " " + step2dir + "/wflow_riverlength_fact.map" ) os.system( gdalstr + step1dir + "/demavg.map" + " " + step2dir + "/wflow_dem.map" ) os.system( gdalstr + step1dir + "/demavg.map" + " " + step2dir + "/wflow_demmin.map" ) os.system( gdalstr + step1dir + "/demavg.map" + " " + step2dir + "/wflow_demmax.map" ) os.system( gdalstr + step1dir + "/gauges.map" + " " + step2dir + "/wflow_gauges.map" ) os.system( gdalstr + step1dir + "/rivers.map" + " " + step2dir + "/wflow_river.map" ) os.system( gdalstr + step1dir + "/streamorder.map" + " " + step2dir + "/wflow_streamorder.map" ) os.system( gdalstr + step1dir + "/gauges.map" + " " + step2dir + "/wflow_outlet.map" ) os.system( gdalstr + step1dir + "/scatch.map" + " " + step2dir + "/wflow_catchment.map" ) os.system(gdalstr + step1dir + "/ldd.map" + " " + step2dir + "/wflow_ldd.map") os.system( gdalstr + step1dir + "/scatch.map" + " " + step2dir + "/wflow_subcatch.map" ) if lu_water: os.system(gdalstr + lu_water + " " + step2dir + "/WaterFrac.map") if lu_paved: os.system(gdalstr + lu_paved + " " + step2dir + "/PathFrac.map") try: lumap = config.get("files", "landuse") except: print("no landuse map...creating uniform map") # clone=pcr.readmap(step2dir + "/wflow_dem.map") pcr.setclone(step2dir + "/wflow_dem.map") pcr.report(pcr.nominal(1), step2dir + "/wflow_landuse.map") else: os.system( "resample --clone " + step2dir + "/wflow_dem.map " + lumap + " " + step2dir + "/wflow_landuse.map" ) try: soilmap = config.get("files", "soil") except: print("no soil map..., creating uniform map") pcr.setclone(step2dir + "/wflow_dem.map") pcr.report(pcr.nominal(1), step2dir + "/wflow_soil.map") else: os.system( "resample --clone " + step2dir + "/wflow_dem.map " + soilmap + " " + step2dir + "/wflow_soil.map" )
streamorder = pcr.ordinal(pcr.streamorder(ldd)) river = pcr.boolean( pcr.ifthen( streamorder >= int( min(np.max(pcr.pcr2numpy(streamorder, -9999)), minorder)), streamorder)) outlets = pcr.ifthen(pcr.ordinal(ldd) == 5, pcr.boolean(1)) outlets = pcr.nominal(pcr.uniqueid(outlets)) catchments = pcr.nominal(pcr.catchment(ldd, outlets)) if not keepall: catchments = pcr.nominal( pcr.ifthen( pcr.mapmaximum( pcr.areatotal( pcr.scalar(catchments) * 0 + 1, pcr.nominal(catchments))) == pcr.areatotal( pcr.scalar(catchments) * 0 + 1, pcr.nominal(catchments)), catchments)) pcr.report(ldd, ldd_map) pcr.report(streamorder, streamorder_map) pcr.report(river, river_map) pcr.report(catchments, catchments_map) if not EPSG == None: call(('gdal_translate', '-of', 'GTiff', '-stats', '-a_srs', EPSG, '-ot', 'Float32', catchments_map, catchments_tif)) else: call(('gdal_translate', '-of', 'GTiff', '-stats', '-ot', 'Float32', catchments_map, catchments_tif)) wt.Raster2Pol(catchments_tif, catchshp, srs)
def update(self,landSurface,routing,currTimeStep): if self.debugWaterBalance: preStorGroundwater = self.storGroundwater preStorGroundwaterFossil = self.storGroundwaterFossil # get riverbed infiltration from the previous time step (from routing) self.surfaceWaterInf = routing.riverbedExchange/routing.cellArea # m self.storGroundwater += self.surfaceWaterInf # get net recharge (percolation-capRise) and update storage: self.storGroundwater = pcr.max(0.,\ self.storGroundwater + landSurface.gwRecharge) # potential groundwater abstraction (unit: m) potGroundwaterAbstract = landSurface.totalPotentialGrossDemand -\ landSurface.allocSurfaceWaterAbstract if self.usingAllocSegments == False or self.limitAbstraction: # Note: For simplicity, no network for a run with limitAbstraction. logger.info("Groundwater abstraction is only to satisfy local demand. No network for distributing groundwater.") # nonFossil groundwater abstraction (unit: m) to fulfill water demand # - assumption: Groundwater is only abstracted to satisfy local demand. self.nonFossilGroundwaterAbs = \ pcr.max(0.0, pcr.min(self.storGroundwater,\ potGroundwaterAbstract)) # self.allocNonFossilGroundwater = self.nonFossilGroundwaterAbs if self.usingAllocSegments and self.limitAbstraction == False: # Note: Incorporating distribution network of groundwater source is possible only if limitAbstraction = False. logger.info("Using groundwater source allocation.") # gross/potential demand volume in each cell (unit: m3) cellVolGrossDemand = potGroundwaterAbstract*routing.cellArea # total gross demand volume in each segment/zone (unit: m3) segTtlGrossDemand = pcr.areatotal(cellVolGrossDemand, self.allocSegments) # total available groundwater water volume in each cell - ignore small values (less than 1 m3) cellAvlGroundwater = pcr.max(0.00, self.storGroundwater* routing.cellArea) cellAvlGroundwater = pcr.rounddown( cellAvlGroundwater/1.)*1. # total available surface water volume in each segment/zone (unit: m3) segAvlGroundwater = pcr.areatotal(cellAvlGroundwater, self.allocSegments) segAvlGroundwater = pcr.max(0.00, segAvlGroundwater) # total actual surface water abstraction volume in each segment/zone (unit: m3) # # - not limited to available water - ignore small values (less than 1 m3) segActGroundwaterAbs = pcr.max(0.0,\ pcr.rounddown(segTtlGrossDemand)) # # - limited to available water segActGroundwaterAbs = pcr.min(segAvlGroundwater, segActGroundwaterAbs) # actual surface water abstraction volume in each cell (unit: m3) volActGroundwaterAbstract = vos.getValDivZero(\ cellAvlGroundwater, segAvlGroundwater, vos.smallNumber) * \ segActGroundwaterAbs volActGroundwaterAbstract = pcr.min(cellAvlGroundwater , volActGroundwaterAbstract) # unit: m3 # actual non fossil groundwater abstraction volume in meter (unit: m) self.nonFossilGroundwaterAbs = pcr.ifthen(self.landmask, volActGroundwaterAbstract) /\ routing.cellArea # unit: m # allocation non fossil groundwater abstraction volume to each cell (unit: m3) self.volAllocGroundwaterAbstract = vos.getValDivZero(\ cellVolGrossDemand, segTtlGrossDemand, vos.smallNumber) *\ segActGroundwaterAbs # unit: m3 # allocation surface water abstraction in meter (unit: m) self.allocNonFossilGroundwater = pcr.ifthen(self.landmask, self.volAllocGroundwaterAbstract)/\ routing.cellArea # unit: m if self.debugWaterBalance == str('True'): abstraction = pcr.cover(pcr.areatotal(self.nonFossilGroundwaterAbs *routing.cellArea, self.allocSegments)/self.segmentArea, 0.0) allocation = pcr.cover(pcr.areatotal(self.allocNonFossilGroundwater*routing.cellArea, self.allocSegments)/self.segmentArea, 0.0) vos.waterBalanceCheck([abstraction],\ [allocation],\ [pcr.scalar(0.0)],\ [pcr.scalar(0.0)],\ 'non fossil groundwater abstraction - allocation per zone/segment (PS: Error here may be caused by rounding error.)' ,\ True,\ "",threshold=5e-4) # update storGoundwater after self.nonFossilGroundwaterAbs self.storGroundwater = pcr.max(0.,self.storGroundwater - self.nonFossilGroundwaterAbs) # unmetDemand (m), satisfied by fossil gwAbstractions # TODO: Include desalinization self.unmetDemand = pcr.max(0.0, potGroundwaterAbstract - \ self.allocNonFossilGroundwater) # m (equal to zero if limitAbstraction = True) if self.limitAbstraction: logger.info("No fossil groundwater abstraction is allowed") # TODO: check that self.unmetDemand = 0.0 # correcting unmetDemand with available fossil groundwater # Note: For simplicity, limitFossilGroundwaterAbstraction can only be combined with local source assumption if self.usingAllocSegments == False and self.limitFossilGroundwaterAbstraction: self.unmetDemand = pcr.min(pcr.max(0.0, self.storGroundwaterFossil), self.unmetDemand) # calculate the average groundwater abstraction (m/day) from the last 365 days: totalAbstraction = self.unmetDemand + self.nonFossilGroundwaterAbs deltaAbstraction = totalAbstraction - self.avgAbstraction self.avgAbstraction = self.avgAbstraction +\ deltaAbstraction/\ pcr.min(365., pcr.max(1.0, routing.timestepsToAvgDischarge)) self.avgAbstraction = pcr.max(0.0, self.avgAbstraction) # update storGroundwaterFossil after unmetDemand self.storGroundwaterFossil -= self.unmetDemand # calculate baseflow and update storage: self.baseflow = pcr.max(0.,\ pcr.min(self.storGroundwater,\ self.recessionCoeff* \ self.storGroundwater)) self.storGroundwater = pcr.max(0.,\ self.storGroundwater - self.baseflow) # PS: baseflow must be calculated at the end (to ensure the availability of storGroundwater to support nonFossilGroundwaterAbs) if self.debugWaterBalance: vos.waterBalanceCheck([self.surfaceWaterInf,\ landSurface.gwRecharge],\ [self.baseflow,\ self.nonFossilGroundwaterAbs],\ [ preStorGroundwater],\ [self.storGroundwater],\ 'storGroundwater',\ True,\ currTimeStep.fulldate,threshold=1e-4) if self.debugWaterBalance: vos.waterBalanceCheck([pcr.scalar(0.0)],\ [self.unmetDemand],\ [ preStorGroundwaterFossil],\ [self.storGroundwaterFossil],\ 'storGroundwaterFossil',\ True,\ currTimeStep.fulldate,threshold=1e-3) if self.debugWaterBalance and self.limitFossilGroundwaterAbstraction: vos.waterBalanceCheck([pcr.scalar(0.0)],\ [self.unmetDemand],\ [pcr.max(0.0, preStorGroundwaterFossil)],\ [pcr.max(0.0,self.storGroundwaterFossil)],\ 'storGroundwaterFossil (with limitFossilGroundwaterAbstraction)',\ True,\ currTimeStep.fulldate,threshold=1e-3) if self.debugWaterBalance and landSurface.limitAbstraction: vos.waterBalanceCheck([potGroundwaterAbstract],\ [self.nonFossilGroundwaterAbs],\ [pcr.scalar(0.)],\ [pcr.scalar(0.)],\ 'non fossil groundwater abstraction',\ True,\ currTimeStep.fulldate,threshold=1e-4) if self.debugWaterBalance: vos.waterBalanceCheck([self.unmetDemand, self.allocNonFossilGroundwater, landSurface.allocSurfaceWaterAbstract],\ [landSurface.totalPotentialGrossDemand],\ [pcr.scalar(0.)],\ [pcr.scalar(0.)],\ 'water demand allocation (from surface water, groundwater and unmetDemand)',\ True,\ currTimeStep.fulldate,threshold=1e-4) if self.report == True: timeStamp = datetime.datetime(currTimeStep.year,\ currTimeStep.month,\ currTimeStep.day,\ 0) # writing daily output to netcdf files timestepPCR = currTimeStep.timeStepPCR if self.outDailyTotNC[0] != "None": for var in self.outDailyTotNC: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_dailyTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,timestepPCR-1) # writing monthly output to netcdf files # -cummulative if self.outMonthTotNC[0] != "None": for var in self.outMonthTotNC: # introduce variables at the beginning of simulation or # reset variables at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.day == 1:\ vars(self)[var+'MonthTot'] = pcr.scalar(0.0) # accumulating vars(self)[var+'MonthTot'] += vars(self)[var] # reporting at the end of the month: if currTimeStep.endMonth == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'MonthTot'),\ vos.MV),timeStamp,currTimeStep.monthIdx-1) # -average if self.outMonthAvgNC[0] != "None": for var in self.outMonthAvgNC: # only if a accumulator variable has not been defined: if var not in self.outMonthTotNC: # introduce accumulator at the beginning of simulation or # reset accumulator at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.day == 1:\ vars(self)[var+'MonthTot'] = pcr.scalar(0.0) # accumulating vars(self)[var+'MonthTot'] += vars(self)[var] # calculating average & reporting at the end of the month: if currTimeStep.endMonth == True: vars(self)[var+'MonthAvg'] = vars(self)[var+'MonthTot']/\ currTimeStep.day self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthAvg.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'MonthAvg'),\ vos.MV),timeStamp,currTimeStep.monthIdx-1) # # -last day of the month if self.outMonthEndNC[0] != "None": for var in self.outMonthEndNC: # reporting at the end of the month: if currTimeStep.endMonth == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthEnd.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,currTimeStep.monthIdx-1) # writing yearly output to netcdf files # -cummulative if self.outAnnuaTotNC[0] != "None": for var in self.outAnnuaTotNC: # introduce variables at the beginning of simulation or # reset variables at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.doy == 1:\ vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0) # accumulating vars(self)[var+'AnnuaTot'] += vars(self)[var] # reporting at the end of the year: if currTimeStep.endYear == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'AnnuaTot'),\ vos.MV),timeStamp,currTimeStep.annuaIdx-1) # -average if self.outAnnuaAvgNC[0] != "None": for var in self.outAnnuaAvgNC: # only if a accumulator variable has not been defined: if var not in self.outAnnuaTotNC: # introduce accumulator at the beginning of simulation or # reset accumulator at the beginning of the year if currTimeStep.timeStepPCR == 1 or \ currTimeStep.doy == 1:\ vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0) # accumulating vars(self)[var+'AnnuaTot'] += vars(self)[var] # # calculating average & reporting at the end of the year: if currTimeStep.endYear == True: vars(self)[var+'AnnuaAvg'] = vars(self)[var+'AnnuaTot']/\ currTimeStep.doy self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaAvg.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'AnnuaAvg'),\ vos.MV),timeStamp,currTimeStep.annuaIdx-1) # # -last day of the year if self.outAnnuaEndNC[0] != "None": for var in self.outAnnuaEndNC: # reporting at the end of the year: if currTimeStep.endYear == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaEnd.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,currTimeStep.annuaIdx-1)
upstream_area_maximum = pcr.areamaximum(upstream_area, basin_map) # - identify the outlet of every basin (in order to rederive the basin so that it is consistent with the ldd) outlet = pcr.nominal(pcr.uniqueid(pcr.ifthen(upstream_area == upstream_area_maximum, pcr.boolean(1.0)))) # - ignoring outlets with small upstream areas threshold = 50. * 1000. * 1000. # unit: m2 outlet = pcr.ifthen(upstream_area_maximum > threshold, outlet) #~ pcr.aguila(outlet) outlet = pcr.cover(outlet, pcr.nominal(0.0)) # - recalculate the basin basin_map = pcr.nominal(pcr.subcatchment(ldd, outlet)) basin_map = pcr.clump(basin_map) basin_map = pcr.ifthen(landmask, basin_map) pcr.report(basin_map , "basin_map.map") #~ pcr.aguila(basin_map) # - calculate the basin area basin_area = pcr.areatotal(cell_area, basin_map) pcr.report(basin_area, "basin_area.map") #~ pcr.aguila(basin_area) # finding the month that give the maximum discharge (from the climatology time series) msg = "Identifying the month with peak discharge (from climatology time series):" logger.info(msg) # - read the maximum monthly discharge for every basin maximum_discharge = vos.netcdf2PCRobjClone(input_files['maximumClimatologyDischargeMonthAvg'], \ "discharge", 1,\ useDoy = "Yes", cloneMapFileName = clone_map_file,\ LatitudeLongitude = True,\ specificFillValue = None) maximum_discharge = pcr.areamaximum(\
streamorder = pcr.ordinal(pcr.streamorder(ldd)) river = pcr.boolean( pcr.ifthen( streamorder >= int(min(np.max(pcr.pcr2numpy(streamorder, -9999)), minorder)), streamorder, ) ) outlets = pcr.ifthen(pcr.ordinal(ldd) == 5, pcr.boolean(1)) outlets = pcr.nominal(pcr.uniqueid(outlets)) catchments = pcr.nominal(pcr.catchment(ldd, outlets)) if not keepall: catchments = pcr.nominal( pcr.ifthen( pcr.mapmaximum( pcr.areatotal(pcr.scalar(catchments) * 0 + 1, pcr.nominal(catchments)) ) == pcr.areatotal(pcr.scalar(catchments) * 0 + 1, pcr.nominal(catchments)), catchments, ) ) pcr.report(ldd, ldd_map) pcr.report(streamorder, streamorder_map) pcr.report(river, river_map) pcr.report(catchments, catchments_map) if not EPSG == None: call( ( "gdal_translate", "-of",
def main(): """ :ivar masterdem: digital elevation model :ivar dem: digital elevation model :ivar river: optional river map """ # Default values strRiver = 8 masterdem = "dem.map" step1dir = "step1" step2dir = "step2" workdir = "." inifile = "wflow_prepare.ini" recreate = False snapgaugestoriver = False try: opts, args = getopt.getopt(sys.argv[1:], "W:hI:f") except getopt.error as msg: usage(msg) for o, a in opts: if o == "-W": workdir = a if o == "-I": inifile = a if o == "-h": usage() if o == "-f": recreate = True pcr.setglobaloption("unitcell") os.chdir(workdir) config = OpenConf(workdir + "/" + inifile) masterdem = configget(config, "files", "masterdem", "dem.map") pcr.setclone(masterdem) strRiver = int(configget(config, "settings", "riverorder", "4")) try: gauges_x = config.get("settings", "gauges_x") gauges_y = config.get("settings", "gauges_y") except: print("gauges_x and gauges_y are required entries in the ini file") sys.exit(1) step1dir = configget(config, "directories", "step1dir", "step1") step2dir = configget(config, "directories", "step2dir", "step2") # upscalefactor = float(config.get("settings","upscalefactor")) corevolume = float(configget(config, "settings", "corevolume", "1E35")) catchmentprecipitation = float( configget(config, "settings", "catchmentprecipitation", "1E35")) corearea = float(configget(config, "settings", "corearea", "1E35")) outflowdepth = float( configget(config, "settings", "lddoutflowdepth", "1E35")) initialscale = int(configget(config, "settings", "initialscale", "1")) csize = float(configget(config, "settings", "cellsize", "1")) snapgaugestoriver = bool( int(configget(config, "settings", "snapgaugestoriver", "1"))) lddglobaloption = configget(config, "settings", "lddglobaloption", "lddout") pcr.setglobaloption(lddglobaloption) lu_water = configget(config, "files", "lu_water", "") lu_paved = configget(config, "files", "lu_paved", "") # X/Y coordinates of the gauges the system exec("X=tr.array(" + gauges_x + ")") exec("Y=tr.array(" + gauges_y + ")") tr.Verbose = 1 # make the directories to save results in mkoutputdirs(step1dir, step2dir) ldddem = readdem(initialscale, masterdem, step1dir) dem = ldddem try: catchmask = config.get("files", "catchment_mask") except: print("No catchment mask...") else: print("clipping DEM with mask.....") mask = pcr.readmap(catchmask) ldddem = pcr.ifthen(pcr.boolean(mask), ldddem) dem = pcr.ifthen(pcr.boolean(mask), dem) # See if there is a shape file of the river to burn in try: rivshp = config.get("files", "river") except: print("no river file specified") outletpointX = float( configget(config, "settings", "outflowpointX", "0.0")) outletpointY = float( configget(config, "settings", "outflowpointY", "0.0")) else: print("river file specified.....") try: outletpointX = float( configget(config, "settings", "outflowpointX", "0.0")) outletpointY = float( configget(config, "settings", "outflowpointY", "0.0")) except: print( "Need to specify the river outletpoint (a point at the end of the river within the current map)" ) exit(1) outletpointmap = tr.points_to_map(dem, outletpointX, outletpointY, 0.5) pcr.report(outletpointmap, step1dir + "/outletpoint.map") rivshpattr = config.get("files", "riverattr") pcr.report(dem * 0.0, step1dir + "/nilmap.map") thestr = ("gdal_translate -of GTiff " + step1dir + "/nilmap.map " + step1dir + "/riverburn.tif") os.system(thestr) os.system("gdal_rasterize -burn 1 -l " + rivshpattr + " " + rivshp + " " + step1dir + "/riverburn.tif") thestr = ("gdal_translate -of PCRaster " + step1dir + "/riverburn.tif " + step1dir + "/riverburn.map") os.system(thestr) riverburn = pcr.readmap(step1dir + "/riverburn.map") # Determine regional slope assuming that is the way the river should run pcr.setglobaloption("unitcell") demregional = pcr.windowaverage(dem, 100) ldddem = pcr.ifthenelse(riverburn >= 1.0, demregional - 1000, dem) pcr.setglobaloption("unittrue") upscalefactor = int(csize / pcr.celllength()) print("Creating ldd...") ldd = tr.lddcreate_save( step1dir + "/ldd.map", ldddem, recreate, outflowdepth=outflowdepth, corevolume=corevolume, catchmentprecipitation=catchmentprecipitation, corearea=corearea, ) print("Determining streamorder...") stro = pcr.streamorder(ldd) pcr.report(stro, step1dir + "/streamorder.map") strdir = pcr.ifthen(stro >= strRiver, stro) pcr.report(strdir, step1dir + "/streamorderrive.map") pcr.report(pcr.boolean(pcr.ifthen(stro >= strRiver, stro)), step1dir + "/rivers.map") pcr.setglobaloption("unittrue") # outlet (and other gauges if given) # TODO: check is x/y set if not skip this print("Outlet...") outlmap = tr.points_to_map(dem, X, Y, 0.5) if snapgaugestoriver: print("Snapping gauges to nearest river cells...") pcr.report(outlmap, step1dir + "/orggauges.map") outlmap = tr.snaptomap(outlmap, strdir) # noutletmap = tr.points_to_map(dem,XX,YY,0.5) # pcr.report(noutletmap,'noutlet.map') pcr.report(outlmap, step1dir + "/gauges.map") # check if there is a pre-define catchment map try: catchmask = config.get("files", "catchment_mask") except: print("No catchment mask, finding outlet") # Find catchment (overall) outlet = tr.find_outlet(ldd) sub = pcr.subcatch(ldd, outlet) pcr.report(sub, step1dir + "/catchment_overall.map") else: print("reading and converting catchment mask.....") os.system("resample -r " + str(initialscale) + " " + catchmask + " " + step1dir + "/catchment_overall.map") sub = pcr.readmap(step1dir + "/catchment_overall.map") print("Scatch...") sd = pcr.subcatch(ldd, pcr.ifthen(outlmap > 0, outlmap)) pcr.report(sd, step1dir + "/scatch.map") pcr.setglobaloption("unitcell") print("Upscalefactor: " + str(upscalefactor)) if upscalefactor > 1: gc.collect() print("upscale river length1 (checkerboard map)...") ck = tr.checkerboard(dem, upscalefactor) pcr.report(ck, step1dir + "/ck.map") pcr.report(dem, step1dir + "/demck.map") print("upscale river length2...") fact = tr.area_riverlength_factor(ldd, ck, upscalefactor) pcr.report(fact, step1dir + "/riverlength_fact.map") # print("make dem statistics...") dem_ = pcr.areaaverage(dem, ck) pcr.report(dem_, step1dir + "/demavg.map") print("Create DEM statistics...") dem_ = pcr.areaminimum(dem, ck) pcr.report(dem_, step1dir + "/demmin.map") dem_ = pcr.areamaximum(dem, ck) pcr.report(dem_, step1dir + "/demmax.map") # calculate percentiles order = pcr.areaorder(dem, ck) n = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), ck) #: calculate 25 percentile perc = tr.area_percentile(dem, ck, n, order, 25.0) pcr.report(perc, step1dir + "/dem25.map") perc = tr.area_percentile(dem, ck, n, order, 10.0) pcr.report(perc, step1dir + "/dem10.map") perc = tr.area_percentile(dem, ck, n, order, 50.0) pcr.report(perc, step1dir + "/dem50.map") perc = tr.area_percentile(dem, ck, n, order, 33.0) pcr.report(perc, step1dir + "/dem33.map") perc = tr.area_percentile(dem, ck, n, order, 66.0) pcr.report(perc, step1dir + "/dem66.map") perc = tr.area_percentile(dem, ck, n, order, 75.0) pcr.report(perc, step1dir + "/dem75.map") perc = tr.area_percentile(dem, ck, n, order, 90.0) pcr.report(perc, step1dir + "/dem90.map") else: print("No fancy scaling done. Going strait to step2....") pcr.report(dem, step1dir + "/demavg.map") Xul = float(config.get("settings", "Xul")) Yul = float(config.get("settings", "Yul")) Xlr = float(config.get("settings", "Xlr")) Ylr = float(config.get("settings", "Ylr")) gdalstr = ("gdal_translate -projwin " + str(Xul) + " " + str(Yul) + " " + str(Xlr) + " " + str(Ylr) + " -of PCRaster ") # gdalstr = "gdal_translate -a_ullr " + str(Xul) + " " + str(Yul) + " " +str(Xlr) + " " +str(Ylr) + " -of PCRaster " print(gdalstr) pcr.report(pcr.cover(1.0), step1dir + "/wflow_riverlength_fact.map") # Now us gdat tp convert the maps os.system(gdalstr + step1dir + "/wflow_riverlength_fact.map" + " " + step2dir + "/wflow_riverlength_fact.map") os.system(gdalstr + step1dir + "/demavg.map" + " " + step2dir + "/wflow_dem.map") os.system(gdalstr + step1dir + "/demavg.map" + " " + step2dir + "/wflow_demmin.map") os.system(gdalstr + step1dir + "/demavg.map" + " " + step2dir + "/wflow_demmax.map") os.system(gdalstr + step1dir + "/gauges.map" + " " + step2dir + "/wflow_gauges.map") os.system(gdalstr + step1dir + "/rivers.map" + " " + step2dir + "/wflow_river.map") os.system(gdalstr + step1dir + "/streamorder.map" + " " + step2dir + "/wflow_streamorder.map") os.system(gdalstr + step1dir + "/gauges.map" + " " + step2dir + "/wflow_outlet.map") os.system(gdalstr + step1dir + "/scatch.map" + " " + step2dir + "/wflow_catchment.map") os.system(gdalstr + step1dir + "/ldd.map" + " " + step2dir + "/wflow_ldd.map") os.system(gdalstr + step1dir + "/scatch.map" + " " + step2dir + "/wflow_subcatch.map") if lu_water: os.system(gdalstr + lu_water + " " + step2dir + "/WaterFrac.map") if lu_paved: os.system(gdalstr + lu_paved + " " + step2dir + "/PathFrac.map") try: lumap = config.get("files", "landuse") except: print("no landuse map...creating uniform map") # clone=pcr.readmap(step2dir + "/wflow_dem.map") pcr.setclone(step2dir + "/wflow_dem.map") pcr.report(pcr.nominal(1), step2dir + "/wflow_landuse.map") else: os.system("resample --clone " + step2dir + "/wflow_dem.map " + lumap + " " + step2dir + "/wflow_landuse.map") try: soilmap = config.get("files", "soil") except: print("no soil map..., creating uniform map") pcr.setclone(step2dir + "/wflow_dem.map") pcr.report(pcr.nominal(1), step2dir + "/wflow_soil.map") else: os.system("resample --clone " + step2dir + "/wflow_dem.map " + soilmap + " " + step2dir + "/wflow_soil.map") ################################## # Step 2 starts here ################################## pcr.setclone(step2dir + "/cutout.map") strRiver = int(configget(config, "settings", "riverorder_step2", "4")) corevolume = float(configget(config, "settings", "corevolume", "1E35")) catchmentprecipitation = float( configget(config, "settings", "catchmentprecipitation", "1E35")) corearea = float(configget(config, "settings", "corearea", "1E35")) outflowdepth = float( configget(config, "settings", "lddoutflowdepth", "1E35")) lddmethod = configget(config, "settings", "lddmethod", "dem") lddglobaloption = configget(config, "settings", "lddglobaloption", "lddout") pcr.setglobaloption(lddglobaloption) nrrow = round(abs(Yul - Ylr) / csize) nrcol = round(abs(Xlr - Xul) / csize) mapstr = ("mapattr -s -S -R " + str(nrrow) + " -C " + str(nrcol) + " -l " + str(csize) + " -x " + str(Xul) + " -y " + str(Yul) + " -P yb2t " + step2dir + "/cutout.map") os.system(mapstr) pcr.setclone(step2dir + "/cutout.map") lu_water = configget(config, "files", "lu_water", "") lu_paved = configget(config, "files", "lu_paved", "") if lu_water: os.system("resample --clone " + step2dir + "/cutout.map " + lu_water + " " + step2dir + "/wflow_waterfrac.map") if lu_paved: os.system("resample --clone " + step2dir + "/cutout.map " + lu_paved + " " + step2dir + "/PathFrac.map") # try: lumap = config.get("files", "landuse") except: print("no landuse map...creating uniform map") clone = pcr.readmap(step2dir + "/cutout.map") pcr.report(pcr.nominal(clone), step2dir + "/wflow_landuse.map") else: os.system("resample --clone " + step2dir + "/cutout.map " + lumap + " " + step2dir + "/wflow_landuse.map") try: soilmap = config.get("files", "soil") except: print("no soil map..., creating uniform map") clone = pcr.readmap(step2dir + "/cutout.map") pcr.report(pcr.nominal(clone), step2dir + "/wflow_soil.map") else: os.system("resample --clone " + step2dir + "/cutout.map " + soilmap + " " + step2dir + "/wflow_soil.map") resamplemaps(step1dir, step2dir) dem = pcr.readmap(step2dir + "/wflow_dem.map") demmin = pcr.readmap(step2dir + "/wflow_demmin.map") demmax = pcr.readmap(step2dir + "/wflow_demmax.map") catchcut = pcr.readmap(step2dir + "/catchment_cut.map") # now apply the area of interest (catchcut) to the DEM # dem=pcr.ifthen(catchcut >=1 , dem) # # See if there is a shape file of the river to burn in try: rivshp = config.get("files", "river") except: print("no river file specified") riverburn = pcr.readmap(step2dir + "/wflow_riverburnin.map") else: print("river file speficied.....") rivshpattr = config.get("files", "riverattr") pcr.report(dem * 0.0, step2dir + "/nilmap.map") thestr = ("gdal_translate -of GTiff " + step2dir + "/nilmap.map " + step2dir + "/wflow_riverburnin.tif") os.system(thestr) os.system("gdal_rasterize -burn 1 -l " + rivshpattr + " " + rivshp + " " + step2dir + "/wflow_riverburnin.tif") thestr = ("gdal_translate -of PCRaster " + step2dir + "/wflow_riverburnin.tif " + step2dir + "/wflow_riverburnin.map") os.system(thestr) riverburn = pcr.readmap(step2dir + "/wflow_riverburnin.map") # ldddem = pcr.ifthenelse(riverburn >= 1.0, dem -1000 , dem) # Only burn within the original catchment riverburn = pcr.ifthen(pcr.scalar(catchcut) >= 1, riverburn) # Now setup a very high wall around the catchment that is scale # based on the distance to the catchment so that it slopes away from the # catchment if lddmethod != "river": print("Burning in highres-river ...") disttocatch = pcr.spread(pcr.nominal(catchcut), 0.0, 1.0) demmax = pcr.ifthenelse( pcr.scalar(catchcut) >= 1.0, demmax, demmax + (pcr.celllength() * 100.0) / disttocatch, ) pcr.setglobaloption("unitcell") demregional = pcr.windowaverage(demmin, 100) demburn = pcr.cover( pcr.ifthen(pcr.boolean(riverburn), demregional - 100.0), demmax) else: print("using average dem..") demburn = dem ldd = tr.lddcreate_save( step2dir + "/ldd.map", demburn, True, outflowdepth=outflowdepth, corevolume=corevolume, catchmentprecipitation=catchmentprecipitation, corearea=corearea, ) # Find catchment (overall) outlet = tr.find_outlet(ldd) sub = pcr.subcatch(ldd, outlet) pcr.report(sub, step2dir + "/wflow_catchment.map") pcr.report(outlet, step2dir + "/wflow_outlet.map") # make river map strorder = pcr.streamorder(ldd) pcr.report(strorder, step2dir + "/wflow_streamorder.map") river = pcr.ifthen(pcr.boolean(strorder >= strRiver), strorder) pcr.report(river, step2dir + "/wflow_river.map") # make subcatchments # os.system("col2map --clone " + step2dir + "/cutout.map gauges.col " + step2dir + "/wflow_gauges.map") exec("X=tr.array(" + gauges_x + ")") exec("Y=tr.array(" + gauges_y + ")") pcr.setglobaloption("unittrue") outlmap = tr.points_to_map(dem, X, Y, 0.5) pcr.report(outlmap, step2dir + "/wflow_gauges_.map") if snapgaugestoriver: print("Snapping gauges to river") pcr.report(outlmap, step2dir + "/wflow_orggauges.map") outlmap = tr.snaptomap(outlmap, river) outlmap = pcr.ifthen(outlmap > 0, outlmap) pcr.report(outlmap, step2dir + "/wflow_gauges.map") scatch = pcr.subcatch(ldd, outlmap) pcr.report(scatch, step2dir + "/wflow_subcatch.map")
def waterAbstractionAndAllocation(water_demand_volume,available_water_volume,allocation_zones,\ zone_area = None, high_volume_treshold = 1000000., debug_water_balance = True,\ extra_info_for_water_balance_reporting = "", ignore_small_values = True): logger.debug("Allocation of abstraction.") # demand volume in each cell (unit: m3) if ignore_small_values: # ignore small values to avoid runding error cellVolDemand = pcr.rounddown(pcr.max(0.0, water_demand_volume)) else: cellVolDemand = pcr.max(0.0, water_demand_volume) # total demand volume in each zone/segment (unit: m3) zoneVolDemand = pcr.areatotal(cellVolDemand, allocation_zones) # total available water volume in each cell if ignore_small_values: # ignore small values to avoid runding error cellAvlWater = pcr.rounddown(pcr.max(0.00, available_water_volume)) else: cellAvlWater = pcr.max(0.00, available_water_volume) # total available water volume in each zone/segment (unit: m3) # - to minimize numerical errors, separating cellAvlWater if not isinstance(high_volume_treshold,types.NoneType): # mask: 0 for small volumes ; 1 for large volumes (e.g. in lakes and reservoirs) mask = pcr.cover(\ pcr.ifthen(cellAvlWater > high_volume_treshold, pcr.boolean(1)), pcr.boolean(0)) zoneAvlWater = pcr.areatotal( pcr.ifthenelse(mask, 0.0, cellAvlWater), allocation_zones) zoneAvlWater += pcr.areatotal( pcr.ifthenelse(mask, cellAvlWater, 0.0), allocation_zones) else: zoneAvlWater = pcr.areatotal(cellAvlWater, allocation_zones) # total actual water abstraction volume in each zone/segment (unit: m3) # - limited to available water zoneAbstraction = pcr.min(zoneAvlWater, zoneVolDemand) # actual water abstraction volume in each cell (unit: m3) cellAbstraction = getValDivZero(\ cellAvlWater, zoneAvlWater, smallNumber)*zoneAbstraction cellAbstraction = pcr.min(cellAbstraction, cellAvlWater) if ignore_small_values: # ignore small values to avoid runding error cellAbstraction = pcr.rounddown(pcr.max(0.00, cellAbstraction)) # to minimize numerical errors, separating cellAbstraction if not isinstance(high_volume_treshold,types.NoneType): # mask: 0 for small volumes ; 1 for large volumes (e.g. in lakes and reservoirs) mask = pcr.cover(\ pcr.ifthen(cellAbstraction > high_volume_treshold, pcr.boolean(1)), pcr.boolean(0)) zoneAbstraction = pcr.areatotal( pcr.ifthenelse(mask, 0.0, cellAbstraction), allocation_zones) zoneAbstraction += pcr.areatotal( pcr.ifthenelse(mask, cellAbstraction, 0.0), allocation_zones) else: zoneAbstraction = pcr.areatotal(cellAbstraction, allocation_zones) # allocation water to meet water demand (unit: m3) cellAllocation = getValDivZero(\ cellVolDemand, zoneVolDemand, smallNumber)*zoneAbstraction #~ # extraAbstraction to minimize numerical errors: #~ zoneDeficitAbstraction = pcr.max(0.0,\ #~ pcr.areatotal(cellAllocation , allocation_zones) -\ #~ pcr.areatotal(cellAbstraction, allocation_zones)) #~ remainingCellAvlWater = pcr.max(0.0, cellAvlWater - cellAbstraction) #~ cellAbstraction += zoneDeficitAbstraction * getValDivZero(\ #~ remainingCellAvlWater, #~ pcr.areatotal(remainingCellAvlWater, allocation_zones), #~ smallNumber) #~ # #~ # extraAllocation to minimize numerical errors: #~ zoneDeficitAllocation = pcr.max(0.0,\ #~ pcr.areatotal(cellAbstraction, allocation_zones) -\ #~ pcr.areatotal(cellAllocation , allocation_zones)) #~ remainingCellDemand = pcr.max(0.0, cellVolDemand - cellAllocation) #~ cellAllocation += zoneDeficitAllocation * getValDivZero(\ #~ remainingCellDemand, #~ pcr.areatotal(remainingCellDemand, allocation_zones), #~ smallNumber) if debug_water_balance and not isinstance(zone_area,types.NoneType): zoneAbstraction = pcr.cover(pcr.areatotal(cellAbstraction, allocation_zones)/zone_area, 0.0) zoneAllocation = pcr.cover(pcr.areatotal(cellAllocation , allocation_zones)/zone_area, 0.0) waterBalanceCheck([zoneAbstraction],\ [zoneAllocation],\ [pcr.scalar(0.0)],\ [pcr.scalar(0.0)],\ 'abstraction - allocation per zone/segment (PS: Error here may be caused by rounding error.)' ,\ True,\ extra_info_for_water_balance_reporting,threshold=1e-4) return cellAbstraction, cellAllocation