Beispiel #1
0
 def returnFloodedFraction(self, volume):
     #-returns the flooded fraction given the flood volume and the associated water height
     # using a logistic smoother near intersections (K&K, 2007)
     #-find the match on the basis of the shortest distance to the available intersections or steps
     deltaXMin = self.floodVolume[self.nrEntries - 1]
     y_i = pcr.scalar(1.)
     k = [pcr.scalar(0.)] * 2
     mInt = pcr.scalar(0.)
     for iCnt in range(self.nrEntries - 1, 0, -1):
         #-find x_i for current volume and update match if applicable
         # also update slope and intercept
         deltaX = volume - self.floodVolume[iCnt]
         mask = pcr.abs(deltaX) < pcr.abs(deltaXMin)
         deltaXMin = pcr.ifthenelse(mask, deltaX, deltaXMin)
         y_i = pcr.ifthenelse(mask, self.areaFractions[iCnt], y_i)
         k[0] = pcr.ifthenelse(mask, self.kSlope[iCnt - 1], k[0])
         k[1] = pcr.ifthenelse(mask, self.kSlope[iCnt], k[1])
         mInt = pcr.ifthenelse(mask, self.mInterval[iCnt], mInt)
     #-all values returned, process data: calculate scaled deltaX and smoothed function
     # on the basis of the integrated logistic functions PHI(x) and 1-PHI(x)
     deltaX = deltaXMin
     deltaXScaled= pcr.ifthenelse(deltaX < 0.,pcr.scalar(-1.),1.)*\
      pcr.min(criterionKK,pcr.abs(deltaX/pcr.max(1.,mInt)))
     logInt = self.integralLogisticFunction(deltaXScaled)
     #-compute fractional flooded area and flooded depth
     floodedFraction= pcr.ifthenelse(volume > 0.,\
      pcr.ifthenelse(pcr.abs(deltaXScaled) < criterionKK,\
      y_i-k[0]*mInt*logInt[0]+k[1]*mInt*logInt[1],\
      y_i+pcr.ifthenelse(deltaX < 0.,k[0],k[1])*deltaX),0.)
     floodedFraction = pcr.max(0., pcr.min(1., floodedFraction))
     floodDepth = pcr.ifthenelse(floodedFraction > 0.,
                                 volume / (floodedFraction * self.cellArea),
                                 0.)
     return floodedFraction, floodDepth
Beispiel #2
0
def mapEllipse(r_a, r_b, azimuth, latC, lonC, lat, lon, numberStepsArc= 360):
	'''Maps an ellipse for the given spatial attributes using a predefined number \
of steps along the arc:
 r_a: length of semi_major axis
 r_b: length of semi_major axis
 azimuth: angle of semi_major axis with the centroid to north
 latC: latitude of centroid
 lonC: longitude of centroid
 lat: map of latitude
 lon: map of longitude
 numberStepsArc= 360 (default)

where r= r_a*r_b/(r_a**2*sin(theta)**2+r_b**2*cos(theta)**2)**0.5 \n'''
	#-compute theta as the azimuth and rotated towards the semi-major axis
	theta= np.linspace(0.,360.-360./numberStepsArc,numberStepsArc)
	radius= (r_a*r_b)/(r_a**2*(np.sin(theta*deg2Rad))**2+r_b**2*(np.cos(theta*deg2Rad))**2)**0.5
	theta= (theta+azimuth) % 360.
	lat1, lon1= getDestinationPoint(latC, lonC, radius, theta)
	ellipse= pcr.boolean(0)
	for iCnt in xrange(lat1.size):
		ellipse= ellipse | \
			(pcr.abs(lat-lat1[iCnt]) == pcr.mapminimum(pcr.abs(lat-lat1[iCnt]))) & \
			(pcr.abs(lon-lon1[iCnt]) == pcr.mapminimum(pcr.abs(lon-lon1[iCnt])))
	ellipse= pcr.ifthen(ellipse, ellipse)
	#-return ellipse
	return ellipse
	def returnFloodedFraction(self,volume):
		#-returns the flooded fraction given the flood volume and the associated water height
		# using a logistic smoother near intersections (K&K, 2007)
		#-find the match on the basis of the shortest distance to the available intersections or steps
		deltaXMin= self.floodVolume[self.nrEntries-1]
		y_i= pcr.scalar(1.)
		k= [pcr.scalar(0.)]*2
		mInt= pcr.scalar(0.)
		for iCnt in range(self.nrEntries-1,0,-1):
			#-find x_i for current volume and update match if applicable
			# also update slope and intercept
			deltaX= volume-self.floodVolume[iCnt]
			mask= pcr.abs(deltaX) < pcr.abs(deltaXMin)
			deltaXMin= pcr.ifthenelse(mask,deltaX,deltaXMin)
			y_i= pcr.ifthenelse(mask,self.areaFractions[iCnt],y_i)
			k[0]= pcr.ifthenelse(mask,self.kSlope[iCnt-1],k[0])
			k[1]= pcr.ifthenelse(mask,self.kSlope[iCnt],k[1])
			mInt= pcr.ifthenelse(mask,self.mInterval[iCnt],mInt)
		#-all values returned, process data: calculate scaled deltaX and smoothed function
		# on the basis of the integrated logistic functions PHI(x) and 1-PHI(x)
		deltaX= deltaXMin
		deltaXScaled= pcr.ifthenelse(deltaX < 0.,pcr.scalar(-1.),1.)*\
			pcr.min(criterionKK,pcr.abs(deltaX/pcr.max(1.,mInt)))
		logInt= self.integralLogisticFunction(deltaXScaled)
		#-compute fractional flooded area and flooded depth
		floodedFraction= pcr.ifthenelse(volume > 0.,\
			pcr.ifthenelse(pcr.abs(deltaXScaled) < criterionKK,\
			y_i-k[0]*mInt*logInt[0]+k[1]*mInt*logInt[1],\
			y_i+pcr.ifthenelse(deltaX < 0.,k[0],k[1])*deltaX),0.)
		floodedFraction= pcr.max(0.,pcr.min(1.,floodedFraction))
		floodDepth= pcr.ifthenelse(floodedFraction > 0.,volume/(floodedFraction*self.cellArea),0.)
		return floodedFraction, floodDepth
def fractionXY(surface):
  #-returns the fraction of transport in the x- and y-directions
  # given a gradient in a surface
  aspect= pcr.aspect(surface)
  noAspect= pcr.nodirection(pcr.directional(aspect))
  sinAspect= pcr.sin(aspect)
  cosAspect= pcr.cos(aspect)
  fracX= pcr.ifthenelse(noAspect,0.,sinAspect/(pcr.abs(sinAspect)+pcr.abs(cosAspect)))
  fracY= pcr.ifthenelse(noAspect,0.,cosAspect/(pcr.abs(sinAspect)+pcr.abs(cosAspect)))
  return fracX,fracY
Beispiel #5
0
def dayLength(doy,lat):
    """ daylength fraction of day  """
    lat = lat * pcr.scalar(math.pi) /  180.0
    M_PI_2 = pcr.spatial(pcr.scalar(math.pi / 2.0))
    dec = pcr.sin( (6.224111 + 0.017202  * doy) *  180. / math.pi)
    dec = pcr.scalar(0.39785 * pcr.sin ((4.868961 + .017203 *  doy + 0.033446 * pcr.sin (dec*   180 / math.pi)) *  180 / math.pi))
    dec = pcr.scalar(pcr.asin(dec))
    lat = pcr.ifthenelse(pcr.abs(lat) > M_PI_2, (M_PI_2 - pcr.scalar(0.01)) * pcr.ifthenelse(lat > 0,  pcr.scalar(1.0), pcr.scalar(-1.0))  ,lat )
    arg = pcr.tan(dec ) *  pcr.tan(lat * 180.0 / math.pi  ) * -1.0
    h = pcr.scalar( pcr.acos(arg ) )
    h = h / 180. * math.pi
    h = pcr.ifthenelse(arg > 1.0, 0.0,h) # /* sun stays below horizon */
    h = pcr.ifthenelse(arg <  -1.0 ,math.pi,h) # /* sun stays above horizon */
    return (h /  math.pi)
    def set_recharge_package(self, \
                             gwRecharge, gwAbstraction, 
                             gwAbstractionReturnFlow = 0.0):            # Note: We ignored the latter as MODFLOW should capture this part as well. 

        logger.info("Set the recharge package based on the given recharge, abstraction and abstraction return flow fields.")

        # specify the recharge package
        # + recharge/capillary rise (unit: m/day) from PCR-GLOBWB 
        # - groundwater abstraction (unit: m/day) from PCR-GLOBWB 
        # + return flow of groundwater abstraction (unit: m/day) from PCR-GLOBWB 
        net_recharge = gwRecharge - gwAbstraction + \
                       gwAbstractionReturnFlow

        # - correcting values (considering MODFLOW lat/lon cell properties)
        #   and pass them to the RCH package   
        net_RCH = pcr.cover(net_recharge * self.cellAreaMap/(pcr.clone().cellSize()*pcr.clone().cellSize()), 0.0)
        net_RCH = pcr.cover(pcr.ifthenelse(pcr.abs(net_RCH) < 1e-20, 0.0, net_RCH), 0.0)
        
        self.pcr_modflow.setRecharge(net_RCH, 1)
Beispiel #7
0
def waterBalanceCheck(fluxesIn,fluxesOut,preStorages,endStorages,processName,PrintOnlyErrors,dateStr,threshold=1e-5,landmask=None):
    """ Returns the water balance for a list of input, output, and storage map files  """
    # modified by Edwin (22 Apr 2013)

    inMap   = pcr.spatial(pcr.scalar(0.0))
    outMap  = pcr.spatial(pcr.scalar(0.0))
    dsMap   = pcr.spatial(pcr.scalar(0.0))
    for fluxIn in fluxesIn:
        inMap   += fluxIn
    for fluxOut in fluxesOut:
        outMap  += fluxOut
    for preStorage in preStorages:
        dsMap   += preStorage
    for endStorage in endStorages:
        dsMap   -= endStorage

    a,b,c = getMinMaxMean(inMap + dsMap- outMap)
    if abs(a) > threshold or abs(b) > threshold:
        if PrintOnlyErrors: 
            print "WBError %s Min %f Max %f Mean %f" %(processName,a,b,c)
            print ""
            
    wb = inMap + dsMap - outMap
    maxWBError = pcr.cellvalue(pcr.mapmaximum(pcr.abs(wb)), 1, 1)[0]
    def identifyModelPixel(self,tmpDir,\
                                catchmentAreaAll,\
                                landMaskClass,\
                                xCoordinate,yCoordinate,id):     

        # TODO: Include an option to consider average discharge. 
        
        logger.info("Identify model pixel for the grdc station "+str(id)+".")
        
        # make a temporary directory:
        randomDir = self.makeRandomDir(tmpDir) 

        # coordinate of grdc station
        xCoord  = float(self.attributeGRDC["grdc_longitude_in_arc_degree"][str(id)])
        yCoord  = float(self.attributeGRDC["grdc_latitude_in_arc_degree"][str(id)])
        
        # identify the point at pcraster model
        point = pcr.ifthen((pcr.abs(xCoordinate - xCoord) == pcr.mapminimum(pcr.abs(xCoordinate - xCoord))) &\
                           (pcr.abs(yCoordinate - yCoord) == pcr.mapminimum(pcr.abs(yCoordinate - yCoord))), \
                            pcr.boolean(1))
        
        # expanding the point
        point = pcr.windowmajority(point, self.cell_size_in_arc_degree * 5.0)
        point = pcr.ifthen(catchmentAreaAll > 0, point)
        point = pcr.boolean(point)

        # values based on the model;
        modelCatchmentArea = pcr.ifthen(point, catchmentAreaAll)        # unit: km2
        model_x_ccordinate = pcr.ifthen(point, xCoordinate)             # unit: arc degree
        model_y_ccordinate = pcr.ifthen(point, yCoordinate)             # unit: arc degree
        
        # calculate (absolute) difference with GRDC data
        # - initiating all of them with the values of MV
        diffCatchArea = pcr.abs(pcr.scalar(vos.MV))        # difference between the model and grdc catchment area (unit: km2) 
        diffDistance  = pcr.abs(pcr.scalar(vos.MV))        # distance between the model pixel and grdc catchment station (unit: arc degree)
        diffLongitude = pcr.abs(pcr.scalar(vos.MV))        # longitude difference (unit: arc degree)
        diffLatitude  = pcr.abs(pcr.scalar(vos.MV))        # latitude difference (unit: arc degree)
        #
        # - calculate (absolute) difference with GRDC data
        try:
            diffCatchArea = pcr.abs(modelCatchmentArea-\
                            float(self.attributeGRDC["grdc_catchment_area_in_km2"][str(id)]))
        except:
            logger.info("The difference in the model and grdc catchment area cannot be calculated.")
        try:
            diffLongitude = pcr.abs(model_x_ccordinate - xCoord)
        except:
            logger.info("The difference in longitude cannot be calculated.")
        try:
            diffLatitude  = pcr.abs(model_y_ccordinate - yCoord)
        except:
            logger.info("The difference in latitude cannot be calculated.")
        try:
            diffDistance  = (diffLongitude**(2) + \
                              diffLatitude**(2))**(0.5)                 # TODO: calculate distance in meter
        except:
            logger.info("Distance cannot be calculated.")
        
        # identify  masks
        masks = pcr.ifthen(pcr.boolean(point), landMaskClass)                                          

        # export the difference to temporary files: maps and txt
        catchmentAreaMap = randomDir+"/"+vos.get_random_word()+".area.map"
        diffCatchAreaMap = randomDir+"/"+vos.get_random_word()+".dare.map"
        diffDistanceMap  = randomDir+"/"+vos.get_random_word()+".dist.map"
        diffLatitudeMap  = randomDir+"/"+vos.get_random_word()+".dlat.map"
        diffLongitudeMap = randomDir+"/"+vos.get_random_word()+".dlon.map"
        diffLatitudeMap  = randomDir+"/"+vos.get_random_word()+".dlat.map"
        #
        maskMap          = randomDir+"/"+vos.get_random_word()+".mask.map"
        diffColumnFile   = randomDir+"/"+vos.get_random_word()+".cols.txt" # output
        #
        pcr.report(pcr.ifthen(point,modelCatchmentArea), catchmentAreaMap)
        pcr.report(pcr.ifthen(point,diffCatchArea     ), diffCatchAreaMap)
        pcr.report(pcr.ifthen(point,diffDistance      ), diffDistanceMap )
        pcr.report(pcr.ifthen(point,diffLatitude      ), diffLongitudeMap)
        pcr.report(pcr.ifthen(point,diffLongitude     ), diffLatitudeMap )
        pcr.report(pcr.ifthen(point,masks             ), maskMap)
        #
        cmd = 'map2col '+catchmentAreaMap +' '+\
                         diffCatchAreaMap +' '+\
                         diffDistanceMap  +' '+\
                         diffLongitudeMap +' '+\
                         diffLatitudeMap  +' '+\
                         maskMap+' '+diffColumnFile
        print(cmd); os.system(cmd) 
        
        # use R to sort the file
        cmd = 'R -f saveIdentifiedPixels.R '+diffColumnFile
        print(cmd); os.system(cmd) 
        
        try:
            # read the output file (from R)
            f = open(diffColumnFile+".sel") ; allLines = f.read() ; f.close()
        
            # split the content of the file into several lines
            allLines = allLines.replace("\r",""); allLines = allLines.split("\n")
        
            selectedPixel = allLines[0].split(";")

            model_longitude_in_arc_degree = float(selectedPixel[0])
            model_latitude_in_arc_degree  = float(selectedPixel[1])
            model_catchment_area_in_km2   = float(selectedPixel[2])
            model_landmask                = str(selectedPixel[7])
            
            log_message  = "Model pixel for grdc station "+str(id)+" is identified (lat/lon in arc degree): "
            log_message += str(model_latitude_in_arc_degree) + " ; " +  str(model_longitude_in_arc_degree)
            logger.info(log_message)
            
            self.attributeGRDC["model_longitude_in_arc_degree"][str(id)] = model_longitude_in_arc_degree 
            self.attributeGRDC["model_latitude_in_arc_degree"][str(id)]  = model_latitude_in_arc_degree  
            self.attributeGRDC["model_catchment_area_in_km2"][str(id)]   = model_catchment_area_in_km2   
            self.attributeGRDC["model_landmask"][str(id)]                = model_landmask                

        except:
        
            logger.info("Model pixel for grdc station "+str(id)+" can NOT be identified.")
        
        self.cleanRandomDir(randomDir)
Beispiel #9
0
def waterBalance(  fluxesIn,  fluxesOut,  deltaStorages,  processName,   PrintOnlyErrors,  dateStr,threshold=1e-5):
    """ Returns the water balance for a list of input, output, and storage map files and """

    inMap = pcr.spatial(pcr.scalar(0.0))
    dsMap = pcr.spatial(pcr.scalar(0.0))
    outMap = pcr.spatial(pcr.scalar(0.0))
    inflow = 0
    outflow = 0
    deltaS = 0
    for fluxIn in fluxesIn:
        inflow += getMapTotal(fluxIn)
        inMap += fluxIn
    for fluxOut in fluxesOut:
        outflow += getMapTotal(fluxOut)
        outMap += fluxOut
    for deltaStorage in deltaStorages:
        deltaS += getMapTotal(deltaStorage)
        dsMap += deltaStorage

    #if PrintOnlyErrors:
    a,b,c = getMinMaxMean(inMap + dsMap- outMap)
    # if abs(a) > 1e-5 or abs(b) > 1e-5:
    # if abs(a) > 1e-4 or abs(b) > 1e-4:
    if abs(a) > threshold or abs(b) > threshold:
        print "WBError %s Min %f Max %f Mean %f" %(processName,a,b,c)
    #    if abs(inflow + deltaS - outflow) > 1e-5:
    #        print "Water balance Error for %s on %s: in = %f\tout=%f\tdeltaS=%f\tBalance=%f" \
    #        %(processName,dateStr,inflow,outflow,deltaS,inflow + deltaS - outflow)
    #else:
    #   print "Water balance for %s: on %s in = %f\tout=%f\tdeltaS=%f\tBalance=%f" \
    #        %(processName,dateStr,inflow,outflow,deltaS,inflow + deltaS - outflow)

    wb = inMap + dsMap - outMap
    maxWBError = pcr.cellvalue(pcr.mapmaximum(pcr.abs(wb)), 1, 1)[0]

    #if maxWBError > 0.001 / 1000:
        #row = 0
        #col = 0
        #cellID = 1
        #troubleCell = 0

        #print "Water balance for %s on %s: %f mm !!! " %(processName,dateStr,maxWBError * 1000)
        #pcr.report(wb,"%s-WaterBalanceError-%s" %(processName,dateStr))

        #npWBMError = pcr2numpy(wb, -9999)
        #(nr, nc) = np.shape(npWBMError)
        #for r in range(0, nr):
            #for c in range(0, nc):

                ## print r,c

                #if npWBMError[r, c] != -9999.0:
                    #val = npWBMError[r, c]
                    #if math.fabs(val) > 0.0001 / 1000:

                        ## print npWBMError[r,c]

                        #row = r
                        #col = c
                        #troubleCell = cellID
                #cellID += 1
        #print 'Water balance for %s on %s: %f mm row %i col %i cellID %i!!! ' % (
            #processName,
            #dateStr,
            #maxWBError * 1000,
            #row,
            #col,
            #troubleCell,
            #)

    return inMap + dsMap - outMap
    def report_summary(self, landWaterStoresAtBeginning, landWaterStoresAtEnd,\
                             surfaceWaterStoresAtBeginning, surfaceWaterStoresAtEnd):

        # set total to 0 on first day of the year                             
        if self._modelTime.doy == 1 or self._modelTime.isFirstTimestep():

            # set all accumulated variables to zero

            self.precipitationAcc  = pcr.ifthen(self.landmask, pcr.scalar(0.0)) 

            for var in self.landSurface.fluxVars: vars(self)[var+'Acc'] = pcr.ifthen(self.landmask, pcr.scalar(0.0))            

            self.baseflowAcc                  = pcr.ifthen(self.landmask, pcr.scalar(0.0))

            self.surfaceWaterInfAcc           = pcr.ifthen(self.landmask, pcr.scalar(0.0))

            self.runoffAcc                    = pcr.ifthen(self.landmask, pcr.scalar(0.0))
            self.unmetDemandAcc               = pcr.ifthen(self.landmask, pcr.scalar(0.0))

            self.waterBalanceAcc              = pcr.ifthen(self.landmask, pcr.scalar(0.0))
            self.absWaterBalanceAcc           = pcr.ifthen(self.landmask, pcr.scalar(0.0))

            # non irrigation water use (unit: m) 
            self.nonIrrigationWaterUseAcc     = pcr.ifthen(self.landmask, pcr.scalar(0.0))
            
            # non irrigation return flow to water body and water body evaporation (unit: m) 
            self.nonIrrReturnFlowAcc          = pcr.ifthen(self.landmask, pcr.scalar(0.0))
            self.waterBodyEvaporationAcc      = pcr.ifthen(self.landmask, pcr.scalar(0.0))

            # surface water input/loss volume (m3) and outgoing volume (m3) at pits 
            self.surfaceWaterInputAcc         = pcr.ifthen(self.landmask, pcr.scalar(0.0))
            self.dischargeAtPitAcc            = pcr.ifthen(self.landmask, pcr.scalar(0.0))
            
            # also save the storages at the first day of the year (or the first time step)
            # - land surface storage (unit: m)
            self.storageAtFirstDay            = pcr.ifthen(self.landmask, landWaterStoresAtBeginning)
            # - channel storages (unit: m3)
            self.channelVolumeAtFirstDay      = pcr.ifthen(self.landmask, surfaceWaterStoresAtBeginning)
            
        # accumulating until the last day of the year:
        self.precipitationAcc   += self.meteo.precipitation
        for var in self.landSurface.fluxVars: vars(self)[var+'Acc'] += vars(self.landSurface)[var]            

        self.baseflowAcc         += self.groundwater.baseflow

        self.surfaceWaterInfAcc  += self.groundwater.surfaceWaterInf
        
        self.runoffAcc           += self.routing.runoff
        self.unmetDemandAcc      += self.groundwater.unmetDemand

        self.waterBalance = \
          (landWaterStoresAtBeginning - landWaterStoresAtEnd +\
           self.meteo.precipitation + self.landSurface.irrGrossDemand + self.groundwater.surfaceWaterInf -\
           self.landSurface.actualET - self.routing.runoff - self.groundwater.nonFossilGroundwaterAbs)

        self.waterBalanceAcc    += self.waterBalance
        self.absWaterBalanceAcc += pcr.abs(self.waterBalance)

        # consumptive water use for non irrigation demand (m)
        self.nonIrrigationWaterUseAcc += self.routing.nonIrrWaterConsumption 
        
        self.nonIrrReturnFlowAcc      += self.routing.nonIrrReturnFlow
        self.waterBodyEvaporationAcc  += self.routing.waterBodyEvaporation

        self.surfaceWaterInputAcc     += self.routing.local_input_to_surface_water  # unit: m3
        self.dischargeAtPitAcc        += self.routing.outgoing_volume_at_pits       # unit: m3
        
	#TODO: hack for eWatercycle operational spinup
	#if self._modelTime.isLastDayOfMonth() or self._modelTime.isLastTimestep():
	#TODO: extra hack! dump every state
        self.dumpStateDir(self._configuration.endStateDir)


        if self._modelTime.isLastDayOfYear():
            self.dumpState(self._configuration.endStateDir)
            
            logger.info("")
            msg = 'The following summary values do not include storages in surface water bodies (lake, reservoir and channel storages).'
            logger.info(msg)                        # TODO: Improve these water balance checks. 

            totalCellArea = vos.getMapTotal(pcr.ifthen(self.landmask,self.routing.cellArea))
            msg = 'Total area = %e km2'\
                    % (totalCellArea/1e6)
            logger.info(msg)

            deltaStorageOneYear = vos.getMapVolume( \
                                     pcr.ifthen(self.landmask,landWaterStoresAtBeginning) - \
                                     pcr.ifthen(self.landmask,self.storageAtFirstDay),
                                     self.routing.cellArea)
            msg = 'Delta total storage days 1 to %i in %i = %e km3 = %e mm'\
                % (    int(self._modelTime.doy),\
                       int(self._modelTime.year),\
                       deltaStorageOneYear/1e9,\
                       deltaStorageOneYear*1000/totalCellArea)
            logger.info(msg)

            variableList = ['precipitation',
                            'baseflow',
                            'surfaceWaterInf',
                            'runoff',
                            'unmetDemand']
            variableList += self.landSurface.fluxVars
            variableList += ['waterBalance','absWaterBalance','irrigationWaterUse','nonIrrigationWaterUse']                

            # consumptive water use for irrigation (unit: m)
            self.irrigationWaterUseAcc = vos.getValDivZero(self.irrGrossDemandAcc,\
                                                           self.precipitationAcc + self.irrGrossDemandAcc) * self.actualETAcc

            for var in variableList:
                volume = vos.getMapVolume(\
                            self.__getattribute__(var + 'Acc'),\
                            self.routing.cellArea)
                msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\
                    % (var,int(self._modelTime.doy),\
                           int(self._modelTime.year),volume/1e9,volume*1000/totalCellArea)
                logger.info(msg)

            logger.info("")
            msg = 'The following summary is for surface water bodies.'
            logger.info(msg) 

            deltaChannelStorageOneYear = vos.getMapTotal( \
                                         pcr.ifthen(self.landmask,surfaceWaterStoresAtEnd) - \
                                         pcr.ifthen(self.landmask,self.channelVolumeAtFirstDay))
            msg = 'Delta surface water storage days 1 to %i in %i = %e km3 = %e mm'\
                % (    int(self._modelTime.doy),\
                       int(self._modelTime.year),\
                       deltaChannelStorageOneYear/1e9,\
                       deltaChannelStorageOneYear*1000/totalCellArea)
            logger.info(msg)
            
            variableList = ['nonIrrReturnFlow','waterBodyEvaporation']
            for var in variableList:
                volume = vos.getMapVolume(\
                            self.__getattribute__(var + 'Acc'),\
                            self.routing.cellArea)
                msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\
                    % (var,int(self._modelTime.doy),\
                           int(self._modelTime.year),volume/1e9,volume*1000/totalCellArea)
                logger.info(msg)


            # surface water balance check 
            surfaceWaterInputTotal = vos.getMapTotal(self.surfaceWaterInputAcc)
            msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\
                    % ("surfaceWaterInput",int(self._modelTime.doy),\
                           int(self._modelTime.year),surfaceWaterInputTotal/1e9,surfaceWaterInputTotal*1000/totalCellArea)
            logger.info(msg)

            dischargeAtPitTotal = vos.getMapTotal(self.dischargeAtPitAcc)
            msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\
                    % ("dischargeAtPitTotal",int(self._modelTime.doy),\
                           int(self._modelTime.year),dischargeAtPitTotal/1e9,      dischargeAtPitTotal*1000/totalCellArea)
            logger.info(msg)

            surfaceWaterBalance = surfaceWaterInputTotal - dischargeAtPitTotal + deltaChannelStorageOneYear 
            msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\
                    % ("surfaceWaterBalance",int(self._modelTime.doy),\
                           int(self._modelTime.year),surfaceWaterBalance/1e9,      surfaceWaterBalance*1000/totalCellArea)
            logger.info(msg)
Beispiel #11
0
    def report(self, storesAtBeginning, storesAtEnd):
        #report the state. which states are written when is based on the configuration

        #set total to 0 on first day of the year                             
        if self._modelTime.doy == 1 or self._modelTime.isFirstTimestep():

            # set all accumulated variables to zero
            self.precipitationAcc  = pcr.ifthen(self.landmask, pcr.scalar(0.0)) 

            for var in self.landSurface.fluxVars: vars(self)[var+'Acc'] = pcr.ifthen(self.landmask, pcr.scalar(0.0))            

            self.nonFossilGroundwaterAbsAcc   = pcr.ifthen(self.landmask, pcr.scalar(0.0))
            self.allocNonFossilGroundwaterAcc = pcr.ifthen(self.landmask, pcr.scalar(0.0))
            self.baseflowAcc                  = pcr.ifthen(self.landmask, pcr.scalar(0.0))

            self.surfaceWaterInfAcc           = pcr.ifthen(self.landmask, pcr.scalar(0.0))

            self.runoffAcc                    = pcr.ifthen(self.landmask, pcr.scalar(0.0))
            self.unmetDemandAcc               = pcr.ifthen(self.landmask, pcr.scalar(0.0))

            self.waterBalanceAcc              = pcr.ifthen(self.landmask, pcr.scalar(0.0))
            self.absWaterBalanceAcc           = pcr.ifthen(self.landmask, pcr.scalar(0.0))

            # also save the storage at the first day of the year (or the first time step)
            self.storageAtFirstDay  = pcr.ifthen(self.landmask, storesAtBeginning) 
            
        # accumulating until the last day of the year:
        self.precipitationAcc   += self.meteo.precipitation
        for var in self.landSurface.fluxVars: vars(self)[var+'Acc'] += vars(self.landSurface)[var]            

        self.nonFossilGroundwaterAbsAcc += self.groundwater.nonFossilGroundwaterAbs
        self.allocNonFossilGroundwaterAcc += self.groundwater.allocNonFossilGroundwater
        self.baseflowAcc         += self.groundwater.baseflow

        self.surfaceWaterInfAcc += self.groundwater.surfaceWaterInf
        
        self.runoffAcc           += self.routing.runoff
        self.unmetDemandAcc      += self.groundwater.unmetDemand

        self.waterBalance = \
          (storesAtBeginning - storesAtEnd +\
           self.meteo.precipitation + self.landSurface.irrGrossDemand + self.groundwater.surfaceWaterInf -\
           self.landSurface.actualET - self.routing.runoff - self.groundwater.nonFossilGroundwaterAbs)

        self.waterBalanceAcc    =    self.waterBalanceAcc + self.waterBalance
        self.absWaterBalanceAcc = self.absWaterBalanceAcc + pcr.abs(self.waterBalance)

        if self._modelTime.isLastDayOfYear():
            self.dumpState(self._configuration.endStateDir)
            
            msg = 'The following waterBalance checks assume fracWat = 0 for all cells (not including surface water bodies).'
            logging.getLogger("model").info(msg)                        # TODO: Improve these water balance checks. 

            totalCellArea = vos.getMapTotal(pcr.ifthen(self.landmask,self.routing.cellArea))
            msg = 'Total area = %e km2'\
                    % (totalCellArea/1e6)
            logging.getLogger("model").info(msg)

            deltaStorageOneYear = vos.getMapVolume( \
                                     pcr.ifthen(self.landmask,storesAtEnd) - \
                                     pcr.ifthen(self.landmask,self.storageAtFirstDay),
                                     self.routing.cellArea)
            msg = 'Delta total storage days 1 to %i in %i = %e km3 = %e mm'\
                % (    int(self._modelTime.doy),\
                       int(self._modelTime.year),\
                       deltaStorageOneYear/1e9,\
                       deltaStorageOneYear*1000/totalCellArea)
            logging.getLogger("model").info(msg)

            # reporting the endStates at the end of the Year:
            variableList = ['precipitation',
                            'nonFossilGroundwaterAbs',
                            'allocNonFossilGroundwater',
                            'baseflow',
                            'surfaceWaterInf',
                            'runoff',
                            'unmetDemand']
            variableList += self.landSurface.fluxVars
            variableList += ['waterBalance','absWaterBalance']                

            for var in variableList:
                volume = vos.getMapVolume(\
                            self.__getattribute__(var + 'Acc'),\
                            self.routing.cellArea)
                msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\
                    % (var,int(self._modelTime.doy),\
                           int(self._modelTime.year),volume/1e9,volume*1000/totalCellArea)
                logging.getLogger("model").info(msg)
Beispiel #12
0
def waterBalance(  fluxesIn,  fluxesOut,  deltaStorages,  processName,   PrintOnlyErrors,  dateStr,threshold=1e-5):
    """ Returns the water balance for a list of input, output, and storage map files and """

    inMap = pcr.spatial(pcr.scalar(0.0))
    dsMap = pcr.spatial(pcr.scalar(0.0))
    outMap = pcr.spatial(pcr.scalar(0.0))
    inflow = 0
    outflow = 0
    deltaS = 0
    for fluxIn in fluxesIn:
        inflow += getMapTotal(fluxIn)
        inMap += fluxIn
    for fluxOut in fluxesOut:
        outflow += getMapTotal(fluxOut)
        outMap += fluxOut
    for deltaStorage in deltaStorages:
        deltaS += getMapTotal(deltaStorage)
        dsMap += deltaStorage

    #if PrintOnlyErrors:
    a,b,c = getMinMaxMean(inMap + dsMap- outMap)
    # if abs(a) > 1e-5 or abs(b) > 1e-5:
    # if abs(a) > 1e-4 or abs(b) > 1e-4:
    if abs(a) > threshold or abs(b) > threshold:
        print "WBError %s Min %f Max %f Mean %f" %(processName,a,b,c)
    #    if abs(inflow + deltaS - outflow) > 1e-5:
    #        print "Water balance Error for %s on %s: in = %f\tout=%f\tdeltaS=%f\tBalance=%f" \
    #        %(processName,dateStr,inflow,outflow,deltaS,inflow + deltaS - outflow)
    #else:
    #   print "Water balance for %s: on %s in = %f\tout=%f\tdeltaS=%f\tBalance=%f" \
    #        %(processName,dateStr,inflow,outflow,deltaS,inflow + deltaS - outflow)

    wb = inMap + dsMap - outMap
    maxWBError = pcr.cellvalue(pcr.mapmaximum(pcr.abs(wb)), 1, 1)[0]

    #if maxWBError > 0.001 / 1000:
        #row = 0
        #col = 0
        #cellID = 1
        #troubleCell = 0

        #print "Water balance for %s on %s: %f mm !!! " %(processName,dateStr,maxWBError * 1000)
        #pcr.report(wb,"%s-WaterBalanceError-%s" %(processName,dateStr))

        #npWBMError = pcr2numpy(wb, -9999)
        #(nr, nc) = np.shape(npWBMError)
        #for r in range(0, nr):
            #for c in range(0, nc):

                ## print r,c

                #if npWBMError[r, c] != -9999.0:
                    #val = npWBMError[r, c]
                    #if math.fabs(val) > 0.0001 / 1000:

                        ## print npWBMError[r,c]

                        #row = r
                        #col = c
                        #troubleCell = cellID
                #cellID += 1
        #print 'Water balance for %s on %s: %f mm row %i col %i cellID %i!!! ' % (
            #processName,
            #dateStr,
            #maxWBError * 1000,
            #row,
            #col,
            #troubleCell,
            #)

    return inMap + dsMap - outMap
    os.system(cmd)
    edwin_code = pcr.readmap("edwin_code.map")

    # usgs_drain_area.map: col2map --clone lddsound_05min.map -S -x 3 -y 2 -v 4 one_line_from_edwin_code_and_usgs_drain_area_km2.txt usgs_drain_area.map
    cmd = "col2map --clone " + ldd_file_name + \
          " -S -x 3 -y 2 -v 4 " + "one_line.tmp" + " usgs_drain_area.map"
    print(cmd)
    os.system(cmd)
    usgs_drain_area_km2 = pcr.readmap("usgs_drain_area.map")

    # pcrglobwb catchment area
    edwin_code_pcrglobwb_catchment_area_km2 = pcr.ifthen(
        pcr.defined(edwin_code), pcrglobwb_catchment_area_km2)

    # calculate the absolute difference
    abs_diff = pcr.abs(usgs_drain_area_km2 -
                       edwin_code_pcrglobwb_catchment_area_km2)

    # make correction if required
    abs_diff_value = pcr.cellvalue(pcr.mapmaximum(abs_diff), 1)[0]
    usgs_drain_area_km2 = pcr.cellvalue(pcr.mapmaximum(usgs_drain_area_km2),
                                        1)[0]

    if (usgs_drain_area_km2 > 1000.0) and \
       (abs_diff_value > 0.10 * usgs_drain_area_km2):

        # class within 0.1 arc degree windows
        edwin_code = pcr.windowmajority(edwin_code, 0.1)

        # find the most accurate cell:
        areaorder = pcr.areaorder(
            pcr.windowmaximum(pcr.spatial(pcr.scalar(usgs_drain_area_km2)),
Beispiel #14
0
    def identifyModelPixel(self,tmpDir,\
                                catchmentAreaAll,\
                                landMaskClass,\
                                xCoordinate,yCoordinate,id):     

        # TODO: Include an option to consider average discharge. 
        
        logger.info("Identify model pixel for the grdc station "+str(id)+".")
        
        # make a temporary directory:
        randomDir = self.makeRandomDir(tmpDir) 

        # coordinate of grdc station
        xCoord  = float(self.attributeGRDC["grdc_longitude_in_arc_degree"][str(id)])
        yCoord  = float(self.attributeGRDC["grdc_latitude_in_arc_degree"][str(id)])
        
        # identify the point at pcraster model
        point = pcr.ifthen((pcr.abs(xCoordinate - xCoord) == pcr.mapminimum(pcr.abs(xCoordinate - xCoord))) &\
                           (pcr.abs(yCoordinate - yCoord) == pcr.mapminimum(pcr.abs(yCoordinate - yCoord))), \
                            pcr.boolean(1))
        
        # expanding the point
        point = pcr.windowmajority(point, self.cell_size_in_arc_degree * 5.0)
        point = pcr.ifthen(catchmentAreaAll > 0, point)
        point = pcr.boolean(point)

        # values based on the model;
        modelCatchmentArea = pcr.ifthen(point, catchmentAreaAll)        # unit: km2
        model_x_ccordinate = pcr.ifthen(point, xCoordinate)             # unit: arc degree
        model_y_ccordinate = pcr.ifthen(point, yCoordinate)             # unit: arc degree
        
        # calculate (absolute) difference with GRDC data
        # - initiating all of them with the values of MV
        diffCatchArea = pcr.abs(pcr.scalar(vos.MV))        # difference between the model and grdc catchment area (unit: km2) 
        diffDistance  = pcr.abs(pcr.scalar(vos.MV))        # distance between the model pixel and grdc catchment station (unit: arc degree)
        diffLongitude = pcr.abs(pcr.scalar(vos.MV))        # longitude difference (unit: arc degree)
        diffLatitude  = pcr.abs(pcr.scalar(vos.MV))        # latitude difference (unit: arc degree)
        #
        # - calculate (absolute) difference with GRDC data
        try:
            diffCatchArea = pcr.abs(modelCatchmentArea-\
                            float(self.attributeGRDC["grdc_catchment_area_in_km2"][str(id)]))
        except:
            logger.info("The difference in the model and grdc catchment area cannot be calculated.")
        try:
            diffLongitude = pcr.abs(model_x_ccordinate - xCoord)
        except:
            logger.info("The difference in longitude cannot be calculated.")
        try:
            diffLatitude  = pcr.abs(model_y_ccordinate - yCoord)
        except:
            logger.info("The difference in latitude cannot be calculated.")
        try:
            diffDistance  = (diffLongitude**(2) + \
                              diffLatitude**(2))**(0.5)                 # TODO: calculate distance in meter
        except:
            logger.info("Distance cannot be calculated.")
        
        # identify  masks
        masks = pcr.ifthen(pcr.boolean(point), landMaskClass)                                          

        # export the difference to temporary files: maps and txt
        catchmentAreaMap = randomDir+"/"+vos.get_random_word()+".area.map"
        diffCatchAreaMap = randomDir+"/"+vos.get_random_word()+".dare.map"
        diffDistanceMap  = randomDir+"/"+vos.get_random_word()+".dist.map"
        diffLatitudeMap  = randomDir+"/"+vos.get_random_word()+".dlat.map"
        diffLongitudeMap = randomDir+"/"+vos.get_random_word()+".dlon.map"
        diffLatitudeMap  = randomDir+"/"+vos.get_random_word()+".dlat.map"
        #
        maskMap          = randomDir+"/"+vos.get_random_word()+".mask.map"
        diffColumnFile   = randomDir+"/"+vos.get_random_word()+".cols.txt" # output
        #
        pcr.report(pcr.ifthen(point,modelCatchmentArea), catchmentAreaMap)
        pcr.report(pcr.ifthen(point,diffCatchArea     ), diffCatchAreaMap)
        pcr.report(pcr.ifthen(point,diffDistance      ), diffDistanceMap )
        pcr.report(pcr.ifthen(point,diffLatitude      ), diffLongitudeMap)
        pcr.report(pcr.ifthen(point,diffLongitude     ), diffLatitudeMap )
        pcr.report(pcr.ifthen(point,masks             ), maskMap)
        #
        cmd = 'map2col '+catchmentAreaMap +' '+\
                         diffCatchAreaMap +' '+\
                         diffDistanceMap  +' '+\
                         diffLongitudeMap +' '+\
                         diffLatitudeMap  +' '+\
                         maskMap+' '+diffColumnFile
        print(cmd); os.system(cmd) 
        
        # use R to sort the file
        cmd = 'R -f saveIdentifiedPixels.R '+diffColumnFile
        print(cmd); os.system(cmd) 
        
        try:
            # read the output file (from R)
            f = open(diffColumnFile+".sel") ; allLines = f.read() ; f.close()
        
            # split the content of the file into several lines
            allLines = allLines.replace("\r",""); allLines = allLines.split("\n")
        
            selectedPixel = allLines[0].split(";")

            model_longitude_in_arc_degree = float(selectedPixel[0])
            model_latitude_in_arc_degree  = float(selectedPixel[1])
            model_catchment_area_in_km2   = float(selectedPixel[2])
            model_landmask                = str(selectedPixel[7])
            
            log_message  = "Model pixel for grdc station "+str(id)+" is identified (lat/lon in arc degree): "
            log_message += str(model_latitude_in_arc_degree) + " ; " +  str(model_longitude_in_arc_degree)
            logger.info(log_message)
            
            self.attributeGRDC["model_longitude_in_arc_degree"][str(id)] = model_longitude_in_arc_degree 
            self.attributeGRDC["model_latitude_in_arc_degree"][str(id)]  = model_latitude_in_arc_degree  
            self.attributeGRDC["model_catchment_area_in_km2"][str(id)]   = model_catchment_area_in_km2   
            self.attributeGRDC["model_landmask"][str(id)]                = model_landmask                

        except:
        
            logger.info("Model pixel for grdc station "+str(id)+" can NOT be identified.")
        
        self.cleanRandomDir(randomDir)