def valueReport(val,valName,outDir): #-return global and country values #-open text files valNameFile= '%s\\%s.txt' % (outDir,valName) if year == staYear and month == staMonth: valName= open(valNameFile,'w') else: valName= open(valNameFile,'a') #-calculate country value (km3/year) cntValue= pcr.areatotal(val,country)/conv for nrCnt in range(cntTot+1): if year == staYear and month == staMonth: valName.write('%d ' % (nrCnt)) for nrCnt in range(cntTot+1): cntPoint= pcr.ifthen(countryLocations==int(nrCnt),cntValue) cntPoint= pcr.cellvalue(pcr.maptotal(cntPoint),int(1))[0] if nrCnt==int(0): valName.write('\n%04d %02d ' % (year,month)) else: valName.write('%02f ' % (cntPoint)) #-calculate global total (km3/year) glbValue= pcr.maptotal(val)/conv glbPoint= pcr.cellvalue(glbValue,int(1))[0] valName.write('%02f' % (glbPoint)) #-close text files valName.close() return cntValue,glbValue,valName
def sample(self, expression): """ Sampling the current values of 'expression' at the given locations for the current timestep """ arrayRowPos = self._userModel.currentTimeStep( ) - self._userModel.firstTimeStep() #if isinstance(expression, float): # expression = pcraster.scalar(expression) try: # store the data type for tss file header if self._spatialDatatype == None: self._spatialDatatype = str(expression.dataType()) except AttributeError as e: datatype, sep, tail = str(e).partition(" ") msg = "Argument must be a PCRaster map, type %s given. If necessary use data conversion functions like scalar()" % ( datatype) raise AttributeError(msg) if self._spatialIdGiven: if expression.dataType() == pcraster.Scalar or expression.dataType( ) == pcraster.Directional: tmp = pcraster.areaaverage(pcraster.spatial(expression), pcraster.spatial(self._spatialId)) else: tmp = pcraster.areamajority(pcraster.spatial(expression), pcraster.spatial(self._spatialId)) col = 0 for cellIndex in self._sampleAddresses: value, valid = pcraster.cellvalue(tmp, cellIndex) if not valid: value = Decimal("NaN") self._sampleValues[arrayRowPos][col] = value col += 1 else: if expression.dataType() == pcraster.Scalar or expression.dataType( ) == pcraster.Directional: tmp = pcraster.maptotal(pcraster.spatial(expression))\ / pcraster.maptotal(pcraster.scalar(pcraster.defined(pcraster.spatial(expression)))) else: tmp = pcraster.mapmaximum(pcraster.maptotal(pcraster.areamajority(pcraster.spatial(expression),\ pcraster.spatial(pcraster.nominal(1))))) value, valid = pcraster.cellvalue(tmp, 1) if not valid: value = Decimal("NaN") self._sampleValues[arrayRowPos] = value if self._userModel.currentTimeStep() == self._userModel.nrTimeSteps(): self._writeTssFile()
def sample(self, expression): """ Sampling the current values of 'expression' at the given locations for the current timestep """ arrayRowPos = self._userModel.currentTimeStep() - self._userModel.firstTimeStep() #if isinstance(expression, float): # expression = pcraster.scalar(expression) try: # store the data type for tss file header if self._spatialDatatype == None: self._spatialDatatype = str(expression.dataType()) except AttributeError as e: datatype, sep, tail = str(e).partition(" ") msg = "Argument must be a PCRaster map, type %s given. If necessary use data conversion functions like scalar()" % (datatype) raise AttributeError(msg) if self._spatialIdGiven: if expression.dataType() == pcraster.Scalar or expression.dataType() == pcraster.Directional: tmp = pcraster.areaaverage(pcraster.spatial(expression), pcraster.spatial(self._spatialId)) else: tmp = pcraster.areamajority(pcraster.spatial(expression), pcraster.spatial(self._spatialId)) col = 0 for cellIndex in self._sampleAddresses: value, valid = pcraster.cellvalue(tmp, cellIndex) if not valid: value = Decimal("NaN") self._sampleValues[arrayRowPos][col] = value col += 1 else: if expression.dataType() == pcraster.Scalar or expression.dataType() == pcraster.Directional: tmp = pcraster.maptotal(pcraster.spatial(expression))\ / pcraster.maptotal(pcraster.scalar(pcraster.defined(pcraster.spatial(expression)))) else: tmp = pcraster.mapmaximum(pcraster.maptotal(pcraster.areamajority(pcraster.spatial(expression),\ pcraster.spatial(pcraster.nominal(1))))) value, valid = pcraster.cellvalue(tmp, 1) if not valid: value = Decimal("NaN") self._sampleValues[arrayRowPos] = value if self._userModel.currentTimeStep() == self._userModel.nrTimeSteps(): self._writeTssFile()
def getMinMaxMean(mapFile,ignoreEmptyMap=False): mn = pcr.cellvalue(pcr.mapminimum(mapFile),1)[0] mx = pcr.cellvalue(pcr.mapmaximum(mapFile),1)[0] nrValues = pcr.cellvalue(pcr.maptotal(pcr.scalar(pcr.defined(mapFile))), 1 ) [0] #/ getNumNonMissingValues(mapFile) if nrValues == 0.0 and ignoreEmptyMap: return 0.0,0.0,0.0 else: return mn,mx,(getMapTotal(mapFile) / nrValues)
def budgetCheck(self, sample, timestep): # NOTE this is only valid if addition,subtraction are invoked ONCE EACH TIME STEP # NOTE use of maptotal, in case of ldd not covering whole area, absolute values may not be # comparable with other budgets. self.actualAdditionCum = pcr.scalar(self.actualAdditionCum + self.actualInfiltrationFlux * self.timeStepDuration) self.increaseInStore = self.store - self.initialStore budget = pcr.maptotal(self.actualAdditionCum - self.increaseInStore) pcr.report(budget, pcrfw.generateNameST('B-inf', sample, timestep)) return self.increaseInStore
def budgetCheck(self, sample, timestep): # NOTE this is only valid if addition,subtraction and lateral flow are invoked ONCE EACH TIME STEP # NOTE use of maptotal, in case of ldd not covering whole area, absolute values may not be # comparable with other budgets. # note self.changeAmount can be positive or negative and thus self.actualAdditionCum, too self.actualAdditionCum = self.actualAdditionCum + self.changeAmount self.increaseInStore = self.store - self.initialStore # budget=catchmenttotal(self.actualAdditionCum-self.actualAbstractionCum-self.increaseInStore) budget = pcr.maptotal(self.actualAdditionCum - self.increaseInStore) pcr.report(budget, pcrfw.generateNameST('B-sur', sample, timestep)) return self.increaseInStore
def budgetCheck(self, sample, timestep): # this should include setMaximumStore as this may result in throwing away of water # NOTE this is only valid if addition,subtraction and lateral flow are invoked ONCE EACH TIME STEP # NOTE use of maptotal, in case of ldd not covering whole area, absolute values may not be # comparable with other budgets. self.actualAdditionCum = self.actualAdditionCum + self.actualAdditionFlux * self.timeStepDuration self.actualAbstractionCum = self.actualAbstractionCum + self.actualAbstractionFlux * self.timeStepDuration self.increaseInStore = self.store - self.initialStore # budget=catchmenttotal(self.actualAdditionCum-self.actualAbstractionCum-self.increaseInStore) budget = pcr.maptotal(self.actualAdditionCum - self.actualAbstractionCum - self.increaseInStore) pcr.report(budget, pcrfw.generateNameST('B-int', sample, timestep)) return self.increaseInStore
def updateWeight(self): print('#### UPDATEWEIGHTING') print('filter period', self.filterPeriod()) print('filter timestep ', self._d_filterTimesteps[self.filterPeriod() - 1]) print('lijst ', self._d_filterTimesteps) print('filter sample ', self.currentSampleNumber()) modelledData = self.readmap('Rqs') observations = self.readDeterministic('observations/Rqs') #observations=pcr.ifthen(pit(self.ldd) != 0,syntheticData) measurementErrorSD = 3.0 * observations + 1.0 sum = pcr.maptotal(((modelledData - observations)**2) / (2.0 * (measurementErrorSD**2))) weight = pcr.exp(-sum) weightFloatingPoint, valid = pcr.cellvalue(weight, 1) return weightFloatingPoint
def getMinMaxMean(mapFile): mn = pcr.cellvalue(pcr.mapminimum(mapFile),1)[0] mx = pcr.cellvalue(pcr.mapmaximum(mapFile),1)[0] nrValues = pcr.cellvalue(pcr.maptotal(pcr.scalar(pcr.defined(mapFile))), 1 ) [0] #/ getNumNonMissingValues(mapFile) return mn,mx,(getMapTotal(mapFile) / nrValues)
def getMapTotal(mapFile): ''' outputs the sum of all values in a map file ''' total, valid= pcr.cellvalue(pcr.maptotal(mapFile),1) return total
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 main(): #-initialization # MVs MV= -999. # minimum catchment size to process catchmentSizeLimit= 0.0 # period of interest, start and end year startYear= 1961 endYear= 2010 # maps cloneMapFileName= '/data/hydroworld/PCRGLOBWB20/input30min/global/Global_CloneMap_30min.map' lddFileName= '/data/hydroworld/PCRGLOBWB20/input30min/routing/lddsound_30min.map' cellAreaFileName= '/data/hydroworld/PCRGLOBWB20/input30min/routing/cellarea30min.map' # set clone pcr.setclone(cloneMapFileName) # output outputPath= '/scratch/rens/reservedrecharge' percentileMapFileName= os.path.join(outputPath,'q%03d_cumsec.map') textFileName= os.path.join(outputPath,'groundwater_environmentalflow_%d.txt') fractionReservedRechargeMapFileName= os.path.join(outputPath,'fraction_reserved_recharge%d.map') fractionMinimumReservedRechargeMapFileName= os.path.join(outputPath,'minimum_fraction_reserved_recharge%d.map') # input inputPath= '/nfsarchive/edwin-emergency-backup-DO-NOT-DELETE/rapid/edwin/05min_runs_results/2015_04_27/non_natural_2015_04_27/global/netcdf/' # define data to be read from netCDF files ncData= {} variableName= 'totalRunoff' ncData[variableName]= {} ncData[variableName]['fileName']= os.path.join(inputPath,'totalRunoff_monthTot_output.nc') ncData[variableName]['fileRoot']= os.path.join(outputPath,'qloc') ncData[variableName]['annualAverage']= pcr.scalar(0) variableName= 'gwRecharge' ncData[variableName]= {} ncData[variableName]['fileName']= os.path.join(inputPath,'gwRecharge_monthTot_output.nc') ncData[variableName]['fileRoot']= os.path.join(outputPath,'gwrec') ncData[variableName]['annualAverage']= pcr.scalar(0) variableName= 'discharge' ncData[variableName]= {} ncData[variableName]['fileName']= os.path.join(inputPath,'totalRunoff_monthTot_output.nc') ncData[variableName]['fileRoot']= os.path.join(outputPath,'qc') ncData[variableName]['annualAverage']= pcr.scalar(0) ncData[variableName]['mapStack']= np.array([]) # percents and environmental flow condition set as percentile percents= range(10,110,10) environmentalFlowPercent= 10 if environmentalFlowPercent not in percents: percents.append(environmentalFlowPercent) percents.sort() #-start # obtain attributes pcr.setclone(cloneMapFileName) cloneSpatialAttributes= spatialAttributes(cloneMapFileName) years= range(startYear,endYear+1) # output path if not os.path.isdir(outputPath): os.makedirs(outputPath) os.chdir(outputPath) # compute catchments ldd= pcr.readmap(lddFileName) cellArea= pcr.readmap(cellAreaFileName) catchments= pcr.catchment(ldd,pcr.pit(ldd)) fractionWater= pcr.scalar(0.0) # temporary! lakeMask= pcr.boolean(0) # temporary! pcr.report(catchments,os.path.join(outputPath,'catchments.map')) maximumCatchmentID= int(pcr.cellvalue(pcr.mapmaximum(pcr.scalar(catchments)),1)[0]) # iterate over years weight= float(len(years))**-1 for year in years: #-echo year print ' - processing year %d' % year #-process data startDate= datetime.datetime(year,1,1) endDate= datetime.datetime(year,12,31) timeSteps= endDate.toordinal()-startDate.toordinal()+1 dynamicIncrement= 1 for variableName in ncData.keys(): print ' extracting %s' % variableName, ncFileIn= ncData[variableName]['fileName'] #-process data pcrDataSet= pcrObject(variableName, ncData[variableName]['fileRoot'],\ ncFileIn,cloneSpatialAttributes, pcrVALUESCALE= pcr.Scalar, resamplingAllowed= True,\ dynamic= True, dynamicStart= startDate, dynamicEnd= endDate, dynamicIncrement= dynamicIncrement, ncDynamicDimension= 'time') pcrDataSet.initializeFileInfo() pcrDataSet.processFileInfo() for fileInfo in pcrDataSet.fileProcessInfo.values()[0]: tempFileName= fileInfo[1] variableField= pcr.readmap(tempFileName) variableField= pcr.ifthen(pcr.defined(ldd),pcr.cover(variableField,0)) if variableName == 'discharge': dayNumber= int(os.path.splitext(tempFileName)[1].strip('.')) date= datetime.date(year,1,1)+datetime.timedelta(dayNumber-1) numberDays= calendar.monthrange(year,date.month)[1] variableField= pcr.max(0,pcr.catchmenttotal(variableField*cellArea,ldd)/(numberDays*24*3600)) ncData[variableName]['annualAverage']+= weight*variableField if 'mapStack' in ncData[variableName].keys(): tempArray= pcr2numpy(variableField,MV) mask= tempArray != MV if ncData[variableName]['mapStack'].size != 0: ncData[variableName]['mapStack']= np.vstack((ncData[variableName]['mapStack'],tempArray[mask])) else: ncData[variableName]['mapStack']= tempArray[mask] coordinates= np.zeros((ncData[variableName]['mapStack'].size,2)) pcr.setglobaloption('unitcell') tempArray= pcr2numpy(pcr.ycoordinate(pcr.boolean(1))+0.5,MV) coordinates[:,0]= tempArray[mask] tempArray= pcr2numpy(pcr.xcoordinate(pcr.boolean(1))+0.5,MV) coordinates[:,1]= tempArray[mask] os.remove(tempFileName) # delete object pcrDataSet= None del pcrDataSet # close line on screen print # report annual averages key= 'annualAverage' ncData['discharge'][key]/= 12 for variableName in ncData.keys(): ncData[variableName][key]= pcr.max(0,ncData[variableName][key]) pcr.report(ncData[variableName][key],\ os.path.join(outputPath,'%s_%s.map' % (variableName,key))) # remove aux.xml for tempFileName in os.listdir(outputPath): if 'aux.xml' in tempFileName: os.remove(tempFileName) # sort data print 'sorting discharge data' variableName= 'discharge' key= 'mapStack' indices= np.zeros((ncData[variableName][key].shape),np.uint) for iCnt in xrange(ncData[variableName][key].shape[1]): indices[:,iCnt]= ncData[variableName][key][:,iCnt].argsort(kind= 'mergesort') ncData[variableName][key][:,iCnt]= ncData[variableName][key][:,iCnt][indices[:,iCnt]] # extract values for percentiles print 'returning maps' for percent in percents: percentile= 0.01*percent index0= min(ncData[variableName][key].shape[0]-1,int(percentile*ncData[variableName][key].shape[0])) index1= min(ncData[variableName][key].shape[0]-1,int(percentile*ncData[variableName][key].shape[0])+1) x0= float(index0)/ncData[variableName][key].shape[0] x1= float(index1)/ncData[variableName][key].shape[0] if x0 <> x1: y= ncData[variableName][key][index0,:]+(percentile-x0)*\ (ncData[variableName][key][index1,:]-ncData[variableName][key][index0,:])/(x1-x0) else: y= ncData[variableName][key][index0,:] # convert a slice of the stack into an array tempArray= np.ones((cloneSpatialAttributes.numberRows,cloneSpatialAttributes.numberCols))*MV for iCnt in xrange(coordinates.shape[0]): row= coordinates[iCnt,0]-1 col= coordinates[iCnt,1]-1 tempArray[row,col]= y[iCnt] variableField= numpy2pcr(pcr.Scalar,tempArray,MV) pcr.report(variableField,percentileMapFileName % percent) if percent == environmentalFlowPercent: ncData[variableName]['environmentalFlow']= variableField tempArray= None; variableField= None del tempArray, variableField # process environmental flow # initialize map of reserved recharge fraction fractionReservedRechargeMap= pcr.ifthen(ncData[variableName]['environmentalFlow'] < 0,pcr.scalar(0)) fractionMinimumReservedRechargeMap= pcr.ifthen(ncData[variableName]['environmentalFlow'] < 0,pcr.scalar(0)) textFile= open(textFileName % environmentalFlowPercent,'w') hStr= 'Environmental flow analysis per basin, resulting in a map of renewable, exploitable recharge, for the %d%s quantile of discharge\n' % (environmentalFlowPercent,'%') hStr+= 'Returns Q_%d/R, the fraction of reserved recharge needed to sustain fully the environental flow requirement defined as the %d percentile,\n' % (environmentalFlowPercent, environmentalFlowPercent) hStr+= 'and Q*_%d/R, a reduced fraction that takes the availability of surface water into account\n' % environmentalFlowPercent textFile.write(hStr) print hStr # create header to display on screen and write to file # reported are: 1: ID, 2: Area, 3: average discharge, 4: environmental flow, 5: average recharge, # 6: Q_%d/Q, 7: Q_%d/R_Avg, 8: R_Avg/Q_Avg, 9: Q*_%d/R_Avg hStr= '%6s,%15s,%15s,%15s,%15s,%15s,%15s,%15s,%15s\n' % \ ('ID','Area [km2]','Q_Avg [m3]','Q_%d [m3]' % environmentalFlowPercent ,'R_Avg [m3]','Q_%d/Q_Avg [-]' % environmentalFlowPercent,\ 'Q_%d/Q_Avg [-]' % environmentalFlowPercent,'R_Avg/Q_Avg [-]','Q*_%d/Q_Avg [-]' % environmentalFlowPercent) textFile.write(hStr) print hStr for catchment in xrange(1,maximumCatchmentID+1): # create catchment mask and check whether it does not coincide with a lake catchmentMask= catchments == catchment catchmentSize= pcr.cellvalue(pcr.maptotal(pcr.ifthen(catchmentMask,cellArea*1.e-6)),1)[0] #~ ##~ if pcr.cellvalue(pcr.maptotal(pcr.ifthen(catchmentMask,pcr.scalar(lakeMask))),1) <> \ #~ ##~ pcr.cellvalue(pcr.maptotal(pcr.ifthen(catchmentMask,pcr.scalar(catchmentMask))),1)[0] and \ #~ ##~ catchmentSize > catchmentSizeLimit: key= 'annualAverage' variableName= 'discharge' if bool(pcr.cellvalue(pcr.maptotal(pcr.ifthen((ldd == 5) & catchmentMask,\ pcr.scalar(ncData[variableName][key] > 0))),1)[0]) and catchmentSize >= catchmentSizeLimit: # valid catchment, process # all volumes are in m3 per year key= 'annualAverage' catchmentAverageDischarge= pcr.cellvalue(pcr.mapmaximum(pcr.ifthen(catchmentMask & (ldd == 5),\ ncData[variableName][key])),1)[0]*365.25*3600*24 variableName= 'gwRecharge' catchmentRecharge= pcr.cellvalue(pcr.maptotal(pcr.ifthen(catchmentMask,ncData[variableName][key]*\ (1.-fractionWater)*cellArea)),1)[0] variableName= 'totalRunoff' catchmentRunoff= pcr.cellvalue(pcr.maptotal(pcr.ifthen(catchmentMask,ncData[variableName][key]*\ cellArea)),1)[0] key= 'environmentalFlow' variableName= 'discharge' catchmentEnvironmentalFlow= pcr.cellvalue(pcr.mapmaximum(pcr.ifthen(catchmentMask & (ldd == 5),\ ncData[variableName][key])),1)[0]*365.25*3600*24 catchmentRunoff= max(catchmentRunoff,catchmentEnvironmentalFlow) if catchmentAverageDischarge > 0.: fractionEnvironmentalFlow= catchmentEnvironmentalFlow/catchmentAverageDischarge fractionGroundWaterContribution= catchmentRecharge/catchmentAverageDischarge else: fractionEnvironmentalFlow= 0. fractionGroundWaterContribution= 0. if catchmentRecharge > 0: fractionReservedRecharge= min(1,catchmentEnvironmentalFlow/catchmentRecharge) else: fractionReservedRecharge= 1.0 fractionMinimumReservedRecharge= (fractionReservedRecharge+fractionGroundWaterContribution-\ fractionReservedRecharge*fractionGroundWaterContribution)*fractionReservedRecharge #~ # echo to screen, and write to file and map wStr= '%6s,%15.1f,%15.6g,%15.6g,%15.6g,%15.6f,%15.6f,%15.6f,%15.6f\n' % \ (catchment,catchmentSize,catchmentAverageDischarge,catchmentEnvironmentalFlow,catchmentRecharge,\ fractionEnvironmentalFlow,fractionReservedRecharge,fractionGroundWaterContribution,fractionMinimumReservedRecharge) print wStr textFile.write(wStr) # update maps fractionReservedRechargeMap= pcr.ifthenelse(catchmentMask,\ pcr.scalar(fractionReservedRecharge),fractionReservedRechargeMap) fractionMinimumReservedRechargeMap= pcr.ifthenelse(catchmentMask,\ pcr.scalar(fractionMinimumReservedRecharge),fractionMinimumReservedRechargeMap) #-report map and close text file pcr.report(fractionReservedRechargeMap,fractionReservedRechargeMapFileName % environmentalFlowPercent) pcr.report(fractionMinimumReservedRechargeMap,fractionMinimumReservedRechargeMapFileName % environmentalFlowPercent) # close text file textFile.close() # finished print 'all done!'
changedOutlet= (waterBodies.outlet != 0) ^ (clippedRead.get(os.path.join(tempDir,'waterbodyoutlet_%d.map' % year)) != 0) targetFileName= os.path.join(pathIniTarget,'updated_outlet.map') pcr.report(changedOutlet,targetFileName) try: targetFileName= os.path.join(pathIniTarget,'qavg_longterm.map') print targetFileName Q= stackAverage(pathRes,resStackList[iniOutVarStart],1,yearDays) print 1 averageQ= (1.-updateQWeight)*averageQ+updateQWeight*Q print 2 #averageQ= pcr.ifthenelse(changedOutlet,averageQIni,averageQ) print 3 pcr.report(averageQ,targetFileName) #-update wStr wStr+= 'total runoff [km3]: %.2e' % \ pcr.cellvalue(pcr.maptotal(pcr.ifthen(LDD == 5,Q*1.e-9*yearDays*timeSec)),1)[0] except: print sys.exc_info() wStr+= '\n - long-term discharge has not been updated!' if not initializeRoutingModel: #-read in maps with water body parameterization for initialization and initialize water bodies for next year del waterBodies waterBodies= pcrglobWaterBodies(os.path.join(tempDir,'waterbodyid_%d.map' % year),\ os.path.join(tempDir,'waterbodyoutlet_%d.map' % year),os.path.join(tempDir,'waterbodytype_%d.map' % year),\ 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' % year),timeSec,clippedRead) fractionWater= clippedRead.get(os.path.join(tempDir,'fracwat_%d.map' % year)) wStr+= '\n - waterbodies updated for %d' % (year+1) #-write log string to screen and file print wStr wStr+= '\n'
class TimeoutputTimeseries(object): """ Class to create pcrcalc timeoutput style timeseries """ def __init__(self, tssFilename, model, idMap=None, noHeader=False): """ """ if not isinstance(tssFilename, str): raise Exception( "timeseries output filename must be of type string") self._outputFilename = tssFilename self._maxId = 1 self._spatialId = None self._spatialDatatype = None self._spatialIdGiven = False self._userModel = model self._writeHeader = not noHeader # array to store the timestep values self._sampleValues = None _idMap = False if isinstance(idMap, str) or isinstance(idMap, pcraster._pcraster.Field): _idMap = True nrRows = self._userModel.nrTimeSteps() - self._userModel.firstTimeStep( ) + 1 if _idMap: self._spatialId = idMap if isinstance(idMap, str): self._spatialId = pcraster.readmap(idMap) _allowdDataTypes = [ pcraster.Nominal, pcraster.Ordinal, pcraster.Boolean ] if self._spatialId.dataType() not in _allowdDataTypes: raise Exception( "idMap must be of type Nominal, Ordinal or Boolean") if self._spatialId.isSpatial(): self._maxId, valid = pcraster.cellvalue( pcraster.mapmaximum(pcraster.ordinal(self._spatialId)), 1) else: self._maxId = 1 # cell indices of the sample locations self._sampleAddresses = [] for cellId in range(1, self._maxId + 1): self._sampleAddresses.append(self._getIndex(cellId)) self._spatialIdGiven = True nrCols = self._maxId self._sampleValues = [[Decimal("NaN")] * nrCols for _ in [0] * nrRows] else: self._sampleValues = [[Decimal("NaN")] * 1 for _ in [0] * nrRows] def _getIndex(self, cellId): """ returns the cell index of a sample location """ nrCells = pcraster.clone().nrRows() * pcraster.clone().nrCols() found = False cell = 1 index = 0 while found == False: if pcraster.cellvalue(self._spatialId, cell)[1] == True and pcraster.cellvalue( self._spatialId, cell)[0] == cellId: index = cell found = True cell += 1 if cell > nrCells: raise RuntimeError( "could not find a cell with the index number %d" % (cellId)) return index def sample(self, expression): """ Sampling the current values of 'expression' at the given locations for the current timestep """ arrayRowPos = self._userModel.currentTimeStep( ) - self._userModel.firstTimeStep() #if isinstance(expression, float): # expression = pcraster.scalar(expression) try: # store the data type for tss file header if self._spatialDatatype == None: self._spatialDatatype = str(expression.dataType()) except AttributeError, e: datatype, sep, tail = str(e).partition(" ") msg = "Argument must be a PCRaster map, type %s given. If necessary use data conversion functions like scalar()" % ( datatype) raise AttributeError(msg) if self._spatialIdGiven: if expression.dataType() == pcraster.Scalar or expression.dataType( ) == pcraster.Directional: tmp = pcraster.areaaverage(pcraster.spatial(expression), pcraster.spatial(self._spatialId)) else: tmp = pcraster.areamajority(pcraster.spatial(expression), pcraster.spatial(self._spatialId)) col = 0 for cellIndex in self._sampleAddresses: value, valid = pcraster.cellvalue(tmp, cellIndex) if not valid: value = Decimal("NaN") self._sampleValues[arrayRowPos][col] = value col += 1 else: if expression.dataType() == pcraster.Scalar or expression.dataType( ) == pcraster.Directional: tmp = pcraster.maptotal(pcraster.spatial(expression))\ / pcraster.maptotal(pcraster.scalar(pcraster.defined(pcraster.spatial(expression)))) else: tmp = pcraster.mapmaximum(pcraster.maptotal(pcraster.areamajority(pcraster.spatial(expression),\ pcraster.spatial(pcraster.nominal(1))))) value, valid = pcraster.cellvalue(tmp, 1) if not valid: value = Decimal("NaN") self._sampleValues[arrayRowPos] = value if self._userModel.currentTimeStep() == self._userModel.nrTimeSteps(): self._writeTssFile()
cost_correction = pd.read_csv(os.path.join(cost_dir, 'cost_correction.csv'), index_col=0, comment='#') #%% Test the cost calculation msr_name = 'sidechannel_everywhere' label = 'everywhere' msr_name = 'lowering_everywhere' label = 'everywhere' #msr_name = 'minemblowering_dummy-ID' #msr_name = 'groynelowering_dummy-ID' msr = read_measure(os.path.join(msr_map_dir, msr_name)) printing = True dh = dem - msr.dem vtot = pcr.maptotal(dh * 25**2) pcr.aguila(dh) ### Smoothing c_sm = CostSmoothing('dummy', smoothing_distr) sm_cost, sm_std = c_sm.overview(msr) if printing == True: print(sm_cost) print(sm_std) ### Earth work c_ew = CostEarthwork(label, minemb_ext_use_distr, minemb_int_use_distr, minemb_polluted_distr, dem, minemb, groyne, pollution_zones, cost_input_ew) ew_cost, ew_std = c_ew.overview(msr, pollution_threshold=2) if printing == True: print(ew_cost)
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)