def set_river_package(self, discharge): logger.info("Set the river package.") # specify the river package # # - surface water river bed/bottom elevation # # - for lakes and resevoirs, make the bottom elevation deep --- Shall we do this? #~ additional_depth = 500. #~ surface_water_bed_elevation = pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, \ #~ self.dem_riverbed - additional_depth) #~ surface_water_bed_elevation = pcr.cover(surface_water_bed_elevation, self.dem_riverbed) # surface_water_bed_elevation = self.dem_riverbed # This is an alternative, if we do not want to introduce very deep bottom elevations of lakes and/or reservoirs. # # rounding values for surface_water_bed_elevation self.surface_water_bed_elevation = pcr.roundup( surface_water_bed_elevation * 1000.) / 1000. # # - river bed condutance (unit: m2/day) bed_surface_area = pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, \ self.WaterBodies.fracWat * self.cellAreaMap) # TODO: Incorporate the concept of dynamicFracWat bed_surface_area = pcr.cover(bed_surface_area, \ self.bankfull_width * self.channelLength) bed_surface_area = self.bankfull_width * self.channelLength bed_conductance = (1.0 / self.bed_resistance) * bed_surface_area bed_conductance = pcr.ifthenelse(bed_conductance < 1e-20, 0.0, \ bed_conductance) self.bed_conductance = pcr.cover(bed_conductance, 0.0) # # - 'channel width' for lakes and reservoirs channel_width = pcr.areamaximum(self.bankfull_width, self.WaterBodies.waterBodyIds) channel_width = pcr.cover(channel_width, self.bankfull_width) # # - convert discharge value to surface water elevation (m) river_water_height = (channel_width**(-3 / 5)) * (discharge**( 3 / 5)) * ((self.gradient)**(-3 / 10)) * (self.manningsN**(3 / 5)) surface_water_elevation = self.dem_riverbed + \ river_water_height # # - calculating water level (unit: m) above the flood plain # TODO: Improve this concept (using Rens's latest innundation scheme) #---------------------------------------------------------- water_above_fpl = pcr.max( 0.0, surface_water_elevation - self.dem_floodplain ) # unit: m, water level above the floodplain (not distributed) water_above_fpl *= self.bankfull_depth * self.bankfull_width / self.cellAreaMap # unit: m, water level above the floodplain (distributed within the cell) # TODO: Improve this concept using Rens's latest scheme # # - corrected surface water elevation surface_water_elevation = pcr.ifthenelse(surface_water_elevation > self.dem_floodplain, \ self.dem_floodplain + water_above_fpl, \ surface_water_elevation) # - surface water elevation for lakes and reservoirs: lake_reservoir_water_elevation = pcr.ifthen( self.WaterBodies.waterBodyOut, surface_water_elevation) lake_reservoir_water_elevation = pcr.areamaximum( lake_reservoir_water_elevation, self.WaterBodies.waterBodyIds) lake_reservoir_water_elevation = pcr.cover(lake_reservoir_water_elevation, \ pcr.areaaverage(surface_water_elevation, self.WaterBodies.waterBodyIds)) # - maximum and minimum values for lake_reservoir_water_elevation lake_reservoir_water_elevation = pcr.min( self.dem_floodplain, lake_reservoir_water_elevation) lake_reservoir_water_elevation = pcr.max( surface_water_bed_elevation, lake_reservoir_water_elevation) # - smoothing lake_reservoir_water_elevation = pcr.areaaverage( surface_water_elevation, self.WaterBodies.waterBodyIds) # # - merge lake and reservoir water elevation surface_water_elevation = pcr.cover(lake_reservoir_water_elevation, surface_water_elevation) # # - pass values to the river package surface_water_elevation = pcr.cover(surface_water_elevation, self.surface_water_bed_elevation) surface_water_elevation = pcr.rounddown( surface_water_elevation * 1000.) / 1000. # # - make sure that HRIV >= RBOT ; no infiltration if HRIV = RBOT (and h < RBOT) self.surface_water_elevation = pcr.max( surface_water_elevation, self.surface_water_bed_elevation) # # - pass the values to the RIV package self.pcr_modflow.setRiver(self.surface_water_elevation, \ self.surface_water_bed_elevation, self.bed_conductance, 2)
def set_river_package(self, discharge, currTimeStep): logger.info("Set the river package.") # - surface water river bed/bottom elevation and conductance need_to_define_surface_water_bed = False if currTimeStep == None: # this is for a steady state simulation (no currTimeStep define) need_to_define_surface_water_bed = True else: # only at the first month of the model simulation or the first month of the year if self.firstMonthOfSimulation or currTimeStep.month == 1: need_to_define_surface_water_bed = True self.firstMonthOfSimulation = False # This part becomes False as we don't need it anymore. if need_to_define_surface_water_bed: logger.info("Estimating the surface water bed elevation and surface water bed conductance.") #~ # - for lakes and resevoirs, alternative 1: make the bottom elevation deep --- Shall we do this? #~ additional_depth = 500. #~ surface_water_bed_elevation = pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, \ #~ self.dem_riverbed - additional_depth) # # - for lakes and resevoirs, estimate bed elevation from dem and bankfull depth surface_water_bed_elevation = pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, self.dem_average) surface_water_bed_elevation = pcr.areaaverage(surface_water_bed_elevation, self.WaterBodies.waterBodyIds) surface_water_bed_elevation -= pcr.areamaximum(self.bankfull_depth, self.WaterBodies.waterBodyIds) # surface_water_bed_elevation = pcr.cover(surface_water_bed_elevation, self.dem_riverbed) #~ surface_water_bed_elevation = self.dem_riverbed # This is an alternative, if we do not want to introduce very deep bottom elevations of lakes and/or reservoirs. # # rounding values for surface_water_bed_elevation self.surface_water_bed_elevation = pcr.roundup(surface_water_bed_elevation * 1000.)/1000. # # - river bed condutance (unit: m2/day) bed_surface_area = pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, \ self.WaterBodies.fracWat * self.cellAreaMap) # TODO: Incorporate the concept of dynamicFracWat # I have problem with the convergence if I use this one. bed_surface_area = pcr.min(bed_surface_area,\ pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, \ pcr.areaaverage(self.bankfull_width * self.channelLength, self.WaterBodies.waterBodyIds))) bed_surface_area = pcr.cover(bed_surface_area, \ self.bankfull_width * self.channelLength) #~ bed_surface_area = self.bankfull_width * self.channelLength bed_conductance = (1.0/self.bed_resistance) * bed_surface_area bed_conductance = pcr.ifthenelse(bed_conductance < 1e-20, 0.0, \ bed_conductance) self.bed_conductance = pcr.cover(bed_conductance, 0.0) logger.info("Estimating outlet widths of lakes and/or reservoirs.") # - 'channel width' for lakes and reservoirs channel_width = pcr.areamaximum(self.bankfull_width, self.WaterBodies.waterBodyIds) self.channel_width = pcr.cover(channel_width, self.bankfull_width) logger.info("Estimating surface water elevation.") # - convert discharge value to surface water elevation (m) river_water_height = (self.channel_width**(-3/5)) * (discharge**(3/5)) * ((self.gradient)**(-3/10)) *(self.manningsN**(3/5)) surface_water_elevation = self.dem_riverbed + \ river_water_height # # - calculating water level (unit: m) above the flood plain # TODO: Improve this concept (using Rens's latest innundation scheme) #---------------------------------------------------------- water_above_fpl = pcr.max(0.0, surface_water_elevation - self.dem_floodplain) # unit: m, water level above the floodplain (not distributed) water_above_fpl *= self.bankfull_depth * self.bankfull_width / self.cellAreaMap # unit: m, water level above the floodplain (distributed within the cell) # TODO: Improve this concept using Rens's latest scheme # # - corrected surface water elevation surface_water_elevation = pcr.ifthenelse(surface_water_elevation > self.dem_floodplain, \ self.dem_floodplain + water_above_fpl, \ surface_water_elevation) # - surface water elevation for lakes and reservoirs: lake_reservoir_water_elevation = pcr.ifthen(self.WaterBodies.waterBodyOut, surface_water_elevation) lake_reservoir_water_elevation = pcr.areamaximum(lake_reservoir_water_elevation, self.WaterBodies.waterBodyIds) lake_reservoir_water_elevation = pcr.cover(lake_reservoir_water_elevation, \ pcr.areaaverage(surface_water_elevation, self.WaterBodies.waterBodyIds)) # - maximum and minimum values for lake_reservoir_water_elevation lake_reservoir_water_elevation = pcr.min(self.dem_floodplain, lake_reservoir_water_elevation) lake_reservoir_water_elevation = pcr.max(self.surface_water_bed_elevation, lake_reservoir_water_elevation) # - smoothing lake_reservoir_water_elevation = pcr.areaaverage(surface_water_elevation, self.WaterBodies.waterBodyIds) # # - merge lake and reservoir water elevation surface_water_elevation = pcr.cover(lake_reservoir_water_elevation, surface_water_elevation) # # - covering the missing values and rounding surface_water_elevation = pcr.cover(surface_water_elevation, self.surface_water_bed_elevation) surface_water_elevation = pcr.rounddown(surface_water_elevation * 1000.)/1000. # # - make sure that HRIV >= RBOT ; no infiltration if HRIV = RBOT (and h < RBOT) self.surface_water_elevation = pcr.max(surface_water_elevation, self.surface_water_bed_elevation) # # - pass the values to the RIV package self.pcr_modflow.setRiver(self.surface_water_elevation, self.surface_water_bed_elevation, self.bed_conductance, 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)
cellArea = pcr.ifthen(landmask,cellArea) for iYear in range(staYear,endYear+1): # time stamp timeStamp = datetime.datetime(int(iYear),int(1),int(1),int(0)) fulldate = '%4i-%02i-%02i' %(int(iYear),int(1),int(1)) print fulldate # index for time object in the netcdf file: index = index + 1 # reading values from the input netcdf files (30min) abstraction_volume_30min = pcr.roundup( vos.netcdf2PCRobjClone(inputDirectory+inputFiles,\ inputVarNames, fulldate, None, cloneMapFileName)) * 0.001 # unit: bcm/year abstraction = pcr.cover(abstraction_volume_30min, 0.0) # use window maximum to be in the conservative side: window_size = 1.0 abstraction = pcr.windowmaximum(abstraction, 1.0) # covering the map with zero pcrValue = pcr.cover(abstraction, 0.0) # unit: m/day # the value should be higher than the previous year value if iYear > staYear: pcrValue = pcr.max(preValue, pcrValue) preValue = pcrValue