def dynamic(self): # update model time using the current pcraster timestep value self.modelTime.update(self.currentTimeStep()) # reading data_available = True if data_available: input_value = vos.netcdf2PCRobjClone(ncFile = self.input_netcdf['file_name'], varName = self.input_netcdf['variable_name'], dateInput = str(self.modelTime.fulldate), useDoy = None, cloneMapFileName = self.clone_map_file) data_available = True else: print "No values are available for this date: "+str(self.modelTime) data_available = False if data_available: output_value = input_value # upscaling if data_available and self.resample_factor > 1.0: # upscaling using cell area cell_area = pcr.ifthen(pcr.defined(output_value), self.cell_area) output_value_in_pcraster = \ vos.getValDivZero(\ pcr.areatotal(output_value*self.cell_area, self.unique_ids),\ pcr.areatotal(self.cell_area, self.unique_ids), vos.smallNumber) # resample to the output clone resolution output_value = vos.regridToCoarse(pcr.pcr2numpy(output_value_in_pcraster, vos.MV), self.resample_factor, "max", vos.MV) # reporting if data_available: # time stamp timestepPCR = self.modelTime.timeStepPCR timeStamp = datetime.datetime(self.modelTime.year,\ self.modelTime.month,\ self.modelTime.day,0) # write to netcdf self.output.data2NetCDF(self.output_netcdf['file_name'],\ self.output_netcdf['variable_name'],\ output_value,\ timeStamp) # closing the file at the end of if self.modelTime.isLastTimeStep(): self.output.close(self.output_netcdf['file_name'])
def dynamic(self): # re-calculate model time using current pcraster timestep value self.modelTime.update(self.currentTimeStep()) # processing / calculating only at the last day of the month: if self.modelTime.endMonth == True: #~ # open totalWaterStorageThickness (unit: m, monthly average values) #~ value_at_5min = vos.netcdf2PCRobjClone(\ #~ self.input_files["model_total_water_storage"],\ #~ "total_thickness_of_water_storage",\ #~ str(self.modelTime.fulldate), useDoy = "end-month") # open totalWaterStorageThickness (unit: m, monthly average values) value_at_5min = vos.netcdf2PCRobjClone(\ self.input_files["model_total_water_storage"],\ self.input_files["model_total_water_storage_variable_name"],\ str(self.modelTime.fulldate), useDoy = "end-month") # upscale to one degree resolution value_at_1deg_but_5min_cell = \ vos.getValDivZero(\ pcr.areatotal(self.cell_area*value_at_5min,\ self.one_degree_id),\ pcr.areatotal(self.cell_area,self.one_degree_id), vos.smallNumber) # resample from 5 arc minute cells to one degree cells value_at_1deg = vos.regridToCoarse(\ pcr.pcr2numpy(value_at_1deg_but_5min_cell,vos.MV),self.resample_factor,"max",vos.MV) # # reporting timestepPCR = self.modelTime.timeStepPCR timeStamp = datetime.datetime(self.modelTime.year,\ self.modelTime.month,\ self.modelTime.day,0) # write it to netcdf self.output.data2NetCDF(self.output_files['one_degree_tws']['model'],\ "pcrglobwb_tws",\ value_at_1deg,\ timeStamp)
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)
def report_summary(self, landWaterStoresAtBeginning, landWaterStoresAtEnd,\ surfaceWaterStoresAtBeginning, surfaceWaterStoresAtEnd): # set total to 0 on first day of the year if self._modelTime.doy == 1 or self._modelTime.isFirstTimestep(): # set all accumulated variables to zero self.precipitationAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) for var in self.landSurface.fluxVars: vars(self)[var+'Acc'] = pcr.ifthen(self.landmask, pcr.scalar(0.0)) self.baseflowAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) self.surfaceWaterInfAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) self.runoffAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) self.unmetDemandAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) self.waterBalanceAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) self.absWaterBalanceAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) # non irrigation water use (unit: m) self.nonIrrigationWaterUseAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) # non irrigation return flow to water body and water body evaporation (unit: m) self.nonIrrReturnFlowAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) self.waterBodyEvaporationAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) # surface water input/loss volume (m3) and outgoing volume (m3) at pits self.surfaceWaterInputAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) self.dischargeAtPitAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0)) # also save the storages at the first day of the year (or the first time step) # - land surface storage (unit: m) self.storageAtFirstDay = pcr.ifthen(self.landmask, landWaterStoresAtBeginning) # - channel storages (unit: m3) self.channelVolumeAtFirstDay = pcr.ifthen(self.landmask, surfaceWaterStoresAtBeginning) # accumulating until the last day of the year: self.precipitationAcc += self.meteo.precipitation for var in self.landSurface.fluxVars: vars(self)[var+'Acc'] += vars(self.landSurface)[var] self.baseflowAcc += self.groundwater.baseflow self.surfaceWaterInfAcc += self.groundwater.surfaceWaterInf self.runoffAcc += self.routing.runoff self.unmetDemandAcc += self.groundwater.unmetDemand self.waterBalance = \ (landWaterStoresAtBeginning - landWaterStoresAtEnd +\ self.meteo.precipitation + self.landSurface.irrGrossDemand + self.groundwater.surfaceWaterInf -\ self.landSurface.actualET - self.routing.runoff - self.groundwater.nonFossilGroundwaterAbs) self.waterBalanceAcc += self.waterBalance self.absWaterBalanceAcc += pcr.abs(self.waterBalance) # consumptive water use for non irrigation demand (m) self.nonIrrigationWaterUseAcc += self.routing.nonIrrWaterConsumption self.nonIrrReturnFlowAcc += self.routing.nonIrrReturnFlow self.waterBodyEvaporationAcc += self.routing.waterBodyEvaporation self.surfaceWaterInputAcc += self.routing.local_input_to_surface_water # unit: m3 self.dischargeAtPitAcc += self.routing.outgoing_volume_at_pits # unit: m3 #TODO: hack for eWatercycle operational spinup #if self._modelTime.isLastDayOfMonth() or self._modelTime.isLastTimestep(): #TODO: extra hack! dump every state self.dumpStateDir(self._configuration.endStateDir) if self._modelTime.isLastDayOfYear(): self.dumpState(self._configuration.endStateDir) logger.info("") msg = 'The following summary values do not include storages in surface water bodies (lake, reservoir and channel storages).' logger.info(msg) # TODO: Improve these water balance checks. totalCellArea = vos.getMapTotal(pcr.ifthen(self.landmask,self.routing.cellArea)) msg = 'Total area = %e km2'\ % (totalCellArea/1e6) logger.info(msg) deltaStorageOneYear = vos.getMapVolume( \ pcr.ifthen(self.landmask,landWaterStoresAtBeginning) - \ pcr.ifthen(self.landmask,self.storageAtFirstDay), self.routing.cellArea) msg = 'Delta total storage days 1 to %i in %i = %e km3 = %e mm'\ % ( int(self._modelTime.doy),\ int(self._modelTime.year),\ deltaStorageOneYear/1e9,\ deltaStorageOneYear*1000/totalCellArea) logger.info(msg) variableList = ['precipitation', 'baseflow', 'surfaceWaterInf', 'runoff', 'unmetDemand'] variableList += self.landSurface.fluxVars variableList += ['waterBalance','absWaterBalance','irrigationWaterUse','nonIrrigationWaterUse'] # consumptive water use for irrigation (unit: m) self.irrigationWaterUseAcc = vos.getValDivZero(self.irrGrossDemandAcc,\ self.precipitationAcc + self.irrGrossDemandAcc) * self.actualETAcc for var in variableList: volume = vos.getMapVolume(\ self.__getattribute__(var + 'Acc'),\ self.routing.cellArea) msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\ % (var,int(self._modelTime.doy),\ int(self._modelTime.year),volume/1e9,volume*1000/totalCellArea) logger.info(msg) logger.info("") msg = 'The following summary is for surface water bodies.' logger.info(msg) deltaChannelStorageOneYear = vos.getMapTotal( \ pcr.ifthen(self.landmask,surfaceWaterStoresAtEnd) - \ pcr.ifthen(self.landmask,self.channelVolumeAtFirstDay)) msg = 'Delta surface water storage days 1 to %i in %i = %e km3 = %e mm'\ % ( int(self._modelTime.doy),\ int(self._modelTime.year),\ deltaChannelStorageOneYear/1e9,\ deltaChannelStorageOneYear*1000/totalCellArea) logger.info(msg) variableList = ['nonIrrReturnFlow','waterBodyEvaporation'] for var in variableList: volume = vos.getMapVolume(\ self.__getattribute__(var + 'Acc'),\ self.routing.cellArea) msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\ % (var,int(self._modelTime.doy),\ int(self._modelTime.year),volume/1e9,volume*1000/totalCellArea) logger.info(msg) # surface water balance check surfaceWaterInputTotal = vos.getMapTotal(self.surfaceWaterInputAcc) msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\ % ("surfaceWaterInput",int(self._modelTime.doy),\ int(self._modelTime.year),surfaceWaterInputTotal/1e9,surfaceWaterInputTotal*1000/totalCellArea) logger.info(msg) dischargeAtPitTotal = vos.getMapTotal(self.dischargeAtPitAcc) msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\ % ("dischargeAtPitTotal",int(self._modelTime.doy),\ int(self._modelTime.year),dischargeAtPitTotal/1e9, dischargeAtPitTotal*1000/totalCellArea) logger.info(msg) surfaceWaterBalance = surfaceWaterInputTotal - dischargeAtPitTotal + deltaChannelStorageOneYear msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\ % ("surfaceWaterBalance",int(self._modelTime.doy),\ int(self._modelTime.year),surfaceWaterBalance/1e9, surfaceWaterBalance*1000/totalCellArea) logger.info(msg)
def getReservoirOutflow(self,\ avgChannelDischarge,length_of_time_step,downstreamDemand): # avgOutflow (m3/s) avgOutflow = self.avgOutflow # The following is needed when new lakes/reservoirs introduced (its avgOutflow is still zero). #~ # - alternative 1 #~ avgOutflow = pcr.ifthenelse(\ #~ avgOutflow > 0.,\ #~ avgOutflow, #~ pcr.max(avgChannelDischarge, self.avgInflow, 0.001)) # - alternative 2 avgOutflow = pcr.ifthenelse(\ avgOutflow > 0.,\ avgOutflow, pcr.max(avgChannelDischarge, self.avgInflow)) avgOutflow = pcr.ifthenelse(\ avgOutflow > 0.,\ avgOutflow, pcr.downstream(self.lddMap, avgOutflow)) avgOutflow = pcr.areamaximum(avgOutflow, self.waterBodyIds) # calculate resvOutflow (m2/s) (based on reservoir storage and avgDischarge): # - using reductionFactor in such a way that: # - if relativeCapacity < minResvrFrac : release is terminated # - if relativeCapacity > maxResvrFrac : longterm average reductionFactor = \ pcr.cover(\ pcr.min(1., pcr.max(0., \ self.waterBodyStorage - self.minResvrFrac*self.waterBodyCap)/\ (self.maxResvrFrac - self.minResvrFrac)*self.waterBodyCap),0.0) # resvOutflow = reductionFactor * avgOutflow * length_of_time_step # unit: m3 # maximum release <= average inflow (especially during dry condition) resvOutflow = pcr.max(0, pcr.min(resvOutflow, self.avgInflow * length_of_time_step)) # unit: m3 # downstream demand (m3/s) # reduce demand if storage < lower limit reductionFactor = vos.getValDivZero( downstreamDemand, self.minResvrFrac * self.waterBodyCap, vos.smallNumber) reductionFactor = pcr.cover(reductionFactor, 0.0) downstreamDemand = pcr.min(downstreamDemand, downstreamDemand * reductionFactor) # resvOutflow > downstreamDemand resvOutflow = pcr.max(resvOutflow, downstreamDemand * length_of_time_step) # unit: m3 # floodOutflow: additional release if storage > upper limit ratioQBankfull = 2.3 estmStorage = pcr.max(0., self.waterBodyStorage - resvOutflow) floodOutflow = \ pcr.max(0.0, estmStorage - self.waterBodyCap) +\ pcr.cover(\ pcr.max(0.0, estmStorage - self.maxResvrFrac*\ self.waterBodyCap)/\ ((1.-self.maxResvrFrac)*self.waterBodyCap),0.0)*\ pcr.max(0.0,ratioQBankfull*avgOutflow* vos.secondsPerDay()-\ resvOutflow) floodOutflow = pcr.max(0.0, pcr.min(floodOutflow,\ estmStorage - self.maxResvrFrac*\ self.waterBodyCap*0.75)) # maximum limit of floodOutflow: bring the reservoir storages only to 3/4 of upper limit capacities # update resvOutflow after floodOutflow resvOutflow = pcr.cover(resvOutflow , 0.0) +\ pcr.cover(floodOutflow, 0.0) # maximum release if storage > upper limit : bring the reservoir storages only to 3/4 of upper limit capacities resvOutflow = pcr.ifthenelse(self.waterBodyStorage > self.maxResvrFrac*self.waterBodyCap,\ pcr.min(resvOutflow,\ pcr.max(0,self.waterBodyStorage - \ self.maxResvrFrac*self.waterBodyCap*0.75)), resvOutflow) # if storage > upper limit : resvOutflow > avgInflow resvOutflow = pcr.ifthenelse(self.waterBodyStorage > self.maxResvrFrac*self.waterBodyCap,\ pcr.max(0.0, resvOutflow, self.avgInflow), resvOutflow) # resvOutflow < waterBodyStorage resvOutflow = pcr.min(self.waterBodyStorage, resvOutflow) resvOutflow = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0., resvOutflow) resvOutflow = pcr.ifthen( pcr.scalar(self.waterBodyTyp) == 2, resvOutflow) return (resvOutflow) # unit: m3
cloneMapFileName = cloneMapFileName, LatitudeLongitude = True, specificFillValue = None) else: output[var]['pcr_value'] = vos.netcdf2PCRobjClone(ncFile = inputFiles[var],\ varName = "Automatic",\ dateInput = fulldate, useDoy = "yearly", cloneMapFileName = cloneMapFileName, LatitudeLongitude = True, specificFillValue = None) # calculating irrigation water consumption 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)