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 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
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)
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)
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)
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)
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)),