Пример #1
0
 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)
Пример #2
0
def extractDailyData(arcPath,arcFile,varPath,varList,leapYear):
	#-extracts daily data from tar file
	nDays= 365
	if leapYear: nDays= nDays+1
	arcList= []
	for var in varList:
		for day in range(1,nDays+1):
			arcList.append(generateNameT(var,day))
	archive= tarfile.open(os.path.join(arcPath,arcFile),'r:gz')
	for tarInfo in archive:
			if tarInfo.name in arcList:
				archive.extract(tarInfo,varPath)
	archive.close()
Пример #3
0
def extractDailyData(arcPath, arcFile, varPath, varList, leapYear):
    #-extracts daily data from tar file
    nDays = 365
    if leapYear: nDays = nDays + 1
    arcList = []
    for var in varList:
        for day in range(1, nDays + 1):
            arcList.append(generateNameT(var, day))
    archive = tarfile.open(os.path.join(arcPath, arcFile), 'r:gz')
    for tarInfo in archive:
        if tarInfo.name in arcList:
            archive.extract(tarInfo, varPath)
    archive.close()
	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)
Пример #5
0
def stackAverage(path,Root,StackStart,StackEnd):
	#calculates the average from a stack of maps, missing maps are skipped
	#Initialization
	MV= pcr.scalar(-999)
	NCount= pcr.scalar(0)
	SumStack= pcr.scalar(0)
	for StackNumber in range(StackStart,StackEnd):
		try:
			InMap= pcr.readmap(generateNameT(os.path.join(path,Root),StackNumber))
		except:
			InMap= MV;
		InMap= pcr.cover(InMap,MV)
		SumStack= SumStack+InMap
		NCount= NCount+pcr.ifthenelse(InMap <> MV,pcr.scalar(1),pcr.scalar(0))
	AvgStack= pcr.ifthenelse(NCount>0,SumStack/NCount,MV)
	return AvgStack
Пример #6
0
def stackAverage(path, Root, StackStart, StackEnd):
    #calculates the average from a stack of maps, missing maps are skipped
    #Initialization
    MV = pcr.scalar(-999)
    NCount = pcr.scalar(0)
    SumStack = pcr.scalar(0)
    for StackNumber in range(StackStart, StackEnd):
        try:
            InMap = pcr.readmap(
                generateNameT(os.path.join(path, Root), StackNumber))
        except:
            InMap = MV
        InMap = pcr.cover(InMap, MV)
        SumStack = SumStack + InMap
        NCount = NCount + pcr.ifthenelse(InMap <> MV, pcr.scalar(1),
                                         pcr.scalar(0))
    AvgStack = pcr.ifthenelse(NCount > 0, SumStack / NCount, MV)
    return AvgStack
	pcr.report(bankfulQ,targetFileName)
	targetFileName= os.path.join(pathIniSource,'qwat_avg_longterm.map')
	pcr.report(averageQWat,targetFileName)
#-define initital values for waterbodies
#-initializing class of water bodies for the first year
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,\
Пример #8
0
 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)
Пример #9
0
 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])
Пример #10
0
    def dynamic(self):
        self.counter += 1
        print(
            str(self.curdate.day) + '-' + str(self.curdate.month) + '-' +
            str(self.curdate.year) + '  t = ' + str(self.counter))

        #-Snow and rain fraction settings for non-glacier part of model cell
        SnowFrac = pcr.ifthenelse(self.SnowStore > 0,
                                  pcr.scalar(1 - self.GlacFrac), 0)
        RainFrac = pcr.ifthenelse(self.SnowStore == 0,
                                  pcr.scalar(1 - self.GlacFrac), 0)

        #-Read the precipitation time-series
        if self.precNetcdfFLAG == 1:
            #-read forcing by netcdf input
            Precip = self.netcdf2PCraster.netcdf2pcrDynamic(self, pcr, 'Prec')
        else:
            #-read forcing by map input
            Precip = pcr.readmap(pcrm.generateNameT(self.Prec, self.counter))
        PrecipTot = Precip
        #-Report Precip
        self.reporting.reporting(self, pcr, 'TotPrec', Precip)
        self.reporting.reporting(self, pcr, 'TotPrecF',
                                 Precip * (1 - self.GlacFrac))

        #-Temperature and determine reference evapotranspiration
        if self.tempNetcdfFLAG == 1:
            #-read forcing by netcdf input
            Temp = self.netcdf2PCraster.netcdf2pcrDynamic(self, pcr, 'Temp')
        else:
            #-read forcing by map input
            Temp = pcr.readmap(pcrm.generateNameT(self.Tair, self.counter))

        if self.ETREF_FLAG == 0:
            if self.TminNetcdfFLAG == 1:
                #-read forcing by netcdf input
                TempMin = self.netcdf2PCraster.netcdf2pcrDynamic(
                    self, pcr, 'Tmin')
            else:
                #-read forcing by map input
                TempMin = pcr.readmap(
                    pcrm.generateNameT(self.Tmin, self.counter))
            if self.TmaxNetcdfFLAG == 1:
                #-read forcing by netcdf input
                TempMax = self.netcdf2PCraster.netcdf2pcrDynamic(
                    self, pcr, 'Tmax')
            else:
                #-read forcing by map input
                TempMax = pcr.readmap(
                    pcrm.generateNameT(self.Tmax, self.counter))
            ETref = self.Hargreaves.Hargreaves(
                pcr, self.Hargreaves.extrarad(self, pcr), Temp, TempMax,
                TempMin)
        else:
            ETref = pcr.readmap(pcrm.generateNameT(self.ETref, self.counter))
        self.reporting.reporting(self, pcr, 'TotETref', ETref)
        self.reporting.reporting(self, pcr, 'TotETrefF',
                                 ETref * (1 - self.GlacFrac))

        #-Interception and effective precipitation
        if self.DynVegFLAG == 1:
            #-read dynamic processes dynamic vegetation
            Precip = self.dynamic_veg.dynamic(self, pcr, pcrm, np, Precip,
                                              ETref)

        elif self.KcStatFLAG == 0:
            #-Try to read the KC map series
            try:
                self.Kc = pcr.readmap(
                    pcrm.generateNameT(self.Kcmaps, self.counter))
                self.KcOld = self.Kc
            except:
                self.Kc = self.KcOld
        #-report mm effective precipitation for sub-basin averages
        if self.mm_rep_FLAG == 1 and self.Prec_mm_FLAG == 1 and (
                self.RoutFLAG == 1 or self.ResFLAG == 1 or self.LakeFLAG == 1):
            self.PrecSubBasinTSS.sample(
                pcr.catchmenttotal(Precip *
                                   (1 - self.GlacFrac), self.FlowDir) /
                pcr.catchmenttotal(1, self.FlowDir))

        #-Snow, rain, and glacier calculations for glacier fraction of cell
        if self.GlacFLAG:
            #-read dynamic processes glacier
            Rain_GLAC, Snow_GLAC, ActSnowMelt_GLAC, SnowR_GLAC, GlacMelt, GlacPerc, self.GlacR = self.glacier.dynamic(
                self, pcr, pd, Temp, Precip)
        #-If glacier module is not used, then
        else:
            Rain_GLAC = 0
            Snow_GLAC = 0
            ActSnowMelt_GLAC = 0
            self.TotalSnowStore_GLAC = 0
            SnowR_GLAC = 0
            self.GlacR = 0
            GlacMelt = 0
            GlacPerc = 0

        # Calculate snow and rain for non-glacier part of cell
        if self.SnowFLAG == 1:
            #-read dynamic processes snow
            Rain, self.SnowR, OldTotalSnowStore = self.snow.dynamic(
                self, pcr, Temp, Precip, Snow_GLAC, ActSnowMelt_GLAC, SnowFrac,
                RainFrac, SnowR_GLAC)
        else:
            Rain = Precip
            self.SnowR = 0
            OldTotalSnowStore = 0
            self.TotalSnowStore = 0
        #-Report Rain
        self.reporting.reporting(self, pcr, 'TotRain', Rain)
        self.reporting.reporting(self, pcr, 'TotRainF',
                                 Rain * (1 - self.GlacFrac) +
                                 Rain_GLAC)  # for entire cell

        #-Potential evapotranspiration
        ETpot = self.ET.ETpot(ETref, self.Kc)
        if self.ETOpenWaterFLAG == 1:
            self.ETOpenWater = self.ET.ETpot(ETref, self.kcOpenWater)
        #-Report ETpot
        self.reporting.reporting(self, pcr, 'TotETpot', ETpot)
        self.reporting.reporting(self, pcr, 'TotETpotF', ETpot * RainFrac)

        #-Rootzone calculations
        self.RootWater = self.RootWater + self.CapRise
        #-Calculate rootzone runoff
        tempvar = self.rootzone.RootRunoff(self, pcr, RainFrac, Rain)
        #-Rootzone runoff
        RootRunoff = tempvar[0]
        #-Infiltration
        Infil = tempvar[1]
        #-Report infiltration
        self.reporting.reporting(self, pcr, 'Infil', Infil)
        #-Updated rootwater content
        self.RootWater = pcr.ifthenelse(RainFrac > 0, self.RootWater + Infil,
                                        self.RootWater)

        #-Actual evapotranspiration
        if self.PlantWaterStressFLAG == 1:
            etreddry = self.ET.ks(self, pcr, ETpot)
        else:
            etreddry = pcr.max(
                pcr.min((self.RootWater - self.RootDry) /
                        (self.RootWilt - self.RootDry), 1), 0)
        self.reporting.reporting(self, pcr, 'PlantStress', 1 - etreddry)
        ETact = self.ET.ETact(pcr, ETpot, self.RootWater, self.RootSat,
                              etreddry, RainFrac)
        #-Report the actual evapotranspiration
        self.reporting.reporting(
            self, pcr, 'TotETact',
            ETact * (1 - self.openWaterFrac) +
            self.ETOpenWater * self.openWaterFrac)
        #-Actual evapotranspiration, corrected for rain fraction
        ActETact = ETact * RainFrac
        #-Report the actual evapotranspiration, corrected for rain fraction
        self.reporting.reporting(self, pcr, 'TotETactF', ActETact)
        if self.mm_rep_FLAG == 1 and self.ETa_mm_FLAG == 1 and (
                self.RoutFLAG == 1 or self.ResFLAG == 1 or self.LakeFLAG == 1):
            self.ETaSubBasinTSS.sample(
                pcr.catchmenttotal(ActETact, self.FlowDir) /
                pcr.catchmenttotal(1, self.FlowDir))
        #-Update rootwater content
        self.RootWater = pcr.max(self.RootWater - ETact, 0)

        #-Calculate drainage
        temp_RootDrain = self.rootzone.RootDrainage(
            pcr, self.RootWater, self.RootDrain, self.RootField, self.RootSat,
            self.RootDrainVel, self.RootTT)
        #-Calculate percolation
        temp_rootperc = self.rootzone.RootPercolation(pcr, self.RootWater,
                                                      self.SubWater,
                                                      self.RootField,
                                                      self.RootTT, self.SubSat)
        #-Total sum of water able to leave the soil
        RootOut = temp_RootDrain + temp_rootperc
        #-Calculate new values for drainage and percolation (to be used when RootOut > RootExcess)
        newdrain, newperc = self.rootzone.CalcFrac(pcr, self.RootWater,
                                                   self.RootField,
                                                   temp_RootDrain,
                                                   temp_rootperc)
        #-Determine whether the new values need to be used
        rootexcess = pcr.max(self.RootWater - self.RootField, 0)
        self.RootDrain = pcr.ifthenelse(RootOut > rootexcess, newdrain,
                                        temp_RootDrain)
        rootperc = pcr.ifthenelse(RootOut > rootexcess, newperc, temp_rootperc)
        #-Update the RootWater content
        # Roottemp = self.RootWater
        self.RootWater = self.RootWater - (self.RootDrain + rootperc)

        #-Report rootzone percolation, corrected for fraction
        self.reporting.reporting(self, pcr, 'TotRootPF',
                                 rootperc * (1 - self.GlacFrac))
        #-Report rootwater content
        self.reporting.reporting(self, pcr, 'StorRootW',
                                 self.RootWater * (1 - self.openWaterFrac))

        #-Sub soil calculations
        self.SubWater = self.SubWater + rootperc
        if self.GroundFLAG == 0:
            if self.SeepStatFLAG == 0:
                try:
                    self.SeePage = pcr.readmap(
                        pcrm.generateNameT(self.Seepmaps, self.counter))
                    self.SeepOld = self.SeePage
                except:
                    self.SeePage = self.SeepOld

            #-Report seepage
            self.reporting.reporting(self, pcr, 'TotSeepF',
                                     pcr.scalar(self.SeePage))
            self.SubWater = pcr.min(pcr.max(self.SubWater - self.SeePage, 0),
                                    self.SubSat)
            if self.mm_rep_FLAG == 1 and self.Seep_mm_FLAG == 1 and (
                    self.RoutFLAG == 1 or self.ResFLAG == 1
                    or self.LakeFLAG == 1):
                self.SeepSubBasinTSS.sample(
                    pcr.catchmenttotal(self.SeePage, self.FlowDir) /
                    pcr.catchmenttotal(1, self.FlowDir))
        #-Capillary rise
        self.CapRise = self.subzone.CapilRise(pcr, self.SubField,
                                              self.SubWater, self.CapRiseMax,
                                              self.RootWater, self.RootSat,
                                              self.RootField)
        #-Report capillary rise, corrected for fraction
        self.reporting.reporting(self, pcr, 'TotCapRF',
                                 self.CapRise * (1 - self.GlacFrac))
        #-Update sub soil water content
        self.SubWater = self.SubWater - self.CapRise
        if self.GroundFLAG == 1:  # sub percolation will be calculated instead of subdrainage
            subperc = self.subzone.SubPercolation(pcr, self.SubWater,
                                                  self.SubField, self.SubTT,
                                                  self.Gw, self.GwSat)
            ActSubPerc = subperc * (1 - self.GlacFrac)
            #-Report the subzone percolation, corrected for the fraction
            self.reporting.reporting(self, pcr, 'TotSubPF', ActSubPerc)
            #-Update sub soil water content
            self.SubWater = self.SubWater - subperc
        else:  # sub drainage will be calculated instead of sub percolation
            self.SubDrain = self.subzone.SubDrainage(pcr, self.SubWater,
                                                     self.SubField,
                                                     self.SubSat,
                                                     self.SubDrainVel,
                                                     self.SubDrain, self.SubTT)
            #-Report drainage from subzone
            self.reporting.reporting(self, pcr, 'TotSubDF', self.SubDrain)
            #-Update sub soil water content
            self.SubWater = self.SubWater - self.SubDrain
        #-Report rootwater content
        self.reporting.reporting(self, pcr, 'StorSubW',
                                 self.SubWater * (1 - self.openWaterFrac))

        #-Changes in soil water storage
        OldSoilWater = self.SoilWater
        self.SoilWater = (self.RootWater + self.SubWater) * (1 - self.GlacFrac)

        #-Rootzone runoff
        self.RootRR = RootRunoff * RainFrac * (1 - self.openWaterFrac)
        #-Report rootzone runoff, corrected for fraction
        self.reporting.reporting(self, pcr, 'TotRootRF', self.RootRR)
        #-Rootzone drainage
        self.RootDR = self.RootDrain * (1 - self.GlacFrac) * (
            1 - self.openWaterFrac)
        #-Report rootzone drainage, corrected for fraction
        self.reporting.reporting(self, pcr, 'TotRootDF', self.RootDR)
        #-Rain runoff
        self.RainR = self.RootRR + self.RootDR
        #-Report rain runoff
        self.reporting.reporting(self, pcr, 'TotRainRF', self.RainR)

        #-Groundwater calculations
        if self.GroundFLAG == 1:
            #-read dynamic processes groundwater
            self.groundwater.dynamic(self, pcr, ActSubPerc, GlacPerc)
        else:
            #-Use drainage from subsoil as baseflow
            self.BaseR = self.SubDrain
            #-Groundwater level as scaled between min and max measured gwl
            SoilAct = self.RootWater + self.SubWater
            SoilRel = (SoilAct - self.SoilMin) / (
                self.SoilMax - self.SoilMin
            )  # scale between 0 (dry) and 1 (wet)
            GWL = self.GWL_base - (SoilRel - 0.5) * self.GWL_base
            #-Report groundwater
            self.reporting.reporting(self, pcr, 'GWL', GWL)

        #-Report Total runoff
        TotR = self.BaseR + self.RainR + self.SnowR + self.GlacR
        self.reporting.reporting(self, pcr, 'TotRF', TotR)

        #-Routing for lake and/or reservoir modules
        if self.LakeFLAG == 1 or self.ResFLAG == 1:
            #-read dynamic processes advanced routing
            Q = self.advanced_routing.dynamic(self, pcr, pcrm, config, TotR,
                                              self.ETOpenWater, PrecipTot)

        #-Normal routing module
        elif self.RoutFLAG == 1:
            self.routing.dynamic(self, pcr, TotR)

            if self.GlacFLAG:
                #-read dynamic reporting processes glacier
                self.glacier.dynamic_reporting(self, pcr, pd, np)

        #-Water balance
        if self.GlacFLAG and self.GlacRetreat == 1:
            GlacTable_MODid = self.GlacTable.loc[:, ['FRAC_GLAC', 'ICE_DEPTH']]
            GlacTable_MODid['ICE_DEPTH'] = GlacTable_MODid[
                'ICE_DEPTH'] * GlacTable_MODid['FRAC_GLAC']
            GlacTable_MODid = GlacTable_MODid.groupby(
                GlacTable_MODid.index).sum()
            GlacTable_MODid.fillna(0., inplace=True)
            #-Report pcraster map of glacier depth
            iceDepth = pcr.numpy.zeros(self.ModelID_1d.shape)
            iceDepth[self.GlacierKeys] = GlacTable_MODid['ICE_DEPTH']
            iceDepth = iceDepth.reshape(self.ModelID.shape)
            iceDepth = pcr.numpy2pcr(pcr.Scalar, iceDepth, self.MV)
            iceDepth = pcr.ifthen(
                self.clone, iceDepth)  #-only use values where clone is True
            iceDepth = iceDepth * 1000  # in mm
            #-change in storage
            dS = ((self.RootWater - self.oldRootWater) + (self.SubWater - self.oldSubWater)) * (1-self.GlacFrac) + (self.Gw - self.oldGw) + \
             (self.TotalSnowStore-OldTotalSnowStore) + (iceDepth - self.oldIceDepth)
            #-set old state variables for glacier
            self.oldIceDepth = iceDepth
            iceDepth = None
            del iceDepth
            GlacTable_MODid = None
            del GlacTable_MODid
        elif self.GroundFLAG:
            #-change in storage
            dS = ((self.RootWater - self.oldRootWater) + (self.SubWater - self.oldSubWater)) * (1-self.GlacFrac) + (self.Gw - self.oldGw) + \
             (self.TotalSnowStore-OldTotalSnowStore)
            # set old state variables for groundwater
            self.oldGw = self.Gw
        else:
            #-change in storage
            dS = ((self.RootWater - self.oldRootWater) +
                  (self.SubWater - self.oldSubWater)) * (1 - self.GlacFrac) + (
                      self.TotalSnowStore - OldTotalSnowStore)

        #-water balance per time step
        if self.GroundFLAG:
            waterbalance = Precip - ActETact - self.BaseR - self.RainR - self.SnowR - self.GlacR - dS
        else:
            waterbalance = Precip - ActETact - self.BaseR - self.RainR - self.SnowR - dS - self.SeePage
        self.reporting.reporting(self, pcr, 'wbal', waterbalance)

        #-total water balance
        self.waterbalanceTot = self.waterbalanceTot + waterbalance
        #-report water balance and accumulated water balance
        if self.wbal_TSS_FLAG and (self.RoutFLAG == 1 or self.ResFLAG == 1
                                   or self.LakeFLAG == 1):
            self.wbalTSS.sample(
                pcr.catchmenttotal(waterbalance, self.FlowDir) /
                pcr.catchmenttotal(1., self.FlowDir))
            self.wbalTotTSS.sample(
                pcr.catchmenttotal(self.waterbalanceTot, self.FlowDir) /
                pcr.catchmenttotal(1., self.FlowDir))
        # set old state variables
        self.oldRootWater = self.RootWater
        self.oldSubWater = self.SubWater
        waterbalance = None
        del waterbalance
        dS = None
        del dS
        #-End of water balance calculations

        #-Sediment yield
        if self.SedFLAG == 1:
            #-determine runoff in mm per day
            if self.RoutFLAG == 1 or self.ResFLAG == 1 or self.LakeFLAG == 1:
                Runoff = (Q * 3600 * 24) / pcr.cellarea() * 1000
            else:
                Runoff = TotR

            #-MUSLE
            if self.SedModel == 1:
                #-read dynamic processes musle
                self.musle.dynamic(self, pcr, Runoff)

                #-sediment transport
                if self.SedTransFLAG == 1:
                    #-read dynamic sediment transport processes musle
                    self.sediment_transport.dynamic_musle(self, pcr)

            #-Modified Morgan-Morgan-Finney model
            if self.SedModel == 2:
                #-determine soil erosion in transport (G)
                G = self.mmf.dynamic(self, pcr, Precip, Runoff)

                #-sediment transport
                if self.SedTransFLAG == 1:
                    #-read dynamic sediment transport processes mmf
                    self.sediment_transport.dynamic_mmf(
                        self, pcr, Runoff, np, G)

        #-update current date
        self.curdate = self.curdate + self.datetime.timedelta(days=1)
	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 __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])