Пример #1
0
    def dynamic(self):
        """
      *Required*
      
      This is where all the time dependent functions are executed. Time dependent
      output should also be saved here.
      """
        self.wf_updateparameters()  # read the temperature map for each step (see parameters())

        self.wf_multparameters()    # needed so parameters can be altered in the inifile under [variable_change_once]

        # snow routine
        snowfall = self.precipitation
        snowfall = pcr.scalar(self.temperature < 3.0) * snowfall
        self.snow = self.snow + snowfall
        melt = (self.meltf * self.temperature)
        melt = pcr.scalar(self.temperature > 3.0) * melt
        melt = pcr.max(0.0, pcr.min(self.snow, melt))
        self.snow = self.snow - melt
        self.precipitation = self.precipitation - snowfall + melt

        # soil storage
        self.PotenEvap = self.PET * self.cropf
        Peff = self.precipitation - self.PotenEvap
        Aw_1 = self.Available_water

        # Soil wetting below capacity
        self.whc = pcr.max(0.0, self.whc)
        self.below_cap = (Aw_1 + pcr.max(0.0, Peff)) <= self.whc
        self.available_water_below_cap = (self.Available_water * pcr.scalar(self.below_cap)) + (pcr.max(0.0, Peff) * pcr.scalar(self.below_cap))

        # Soil wetting above capacity
        self.above_cap = (Aw_1 + Peff) > self.whc
        self.excess = (Aw_1 * pcr.scalar(self.above_cap)) + (Peff * pcr.scalar(self.above_cap)) - (self.whc * pcr.scalar(self.above_cap))
        self.available_water_above_cap = (self.whc * pcr.scalar(self.above_cap))
        self.Available_water = self.available_water_below_cap + self.available_water_above_cap
        
        
        # soil drying
        self.drying = Peff <= 0.0
        self.exp_content = (Peff)/(self.whc)
        self.available_water_drying = (Aw_1 * pcr.scalar(self.drying)) * pcr.exp(self.exp_content)

        # soil that is not drying
        self.not_drying = Peff > 0.0
        self.Available_water = self.Available_water * pcr.scalar(self.not_drying)
        self.Available_water = self.Available_water + self.available_water_drying
        self.excess = self.excess * pcr.scalar(self.not_drying)

        # seepage to groundwater
        self.runoff = self.togwf * self.excess
        self.togw = self.excess - self.runoff

        # adding water to groundwater and taking water from groundwater
        self.Ground_water = self.Ground_water + self.togw
        self.sloflo = (self.Ground_water/self.C)
        self.Ground_water = self.Ground_water - self.sloflo

        # adding water from groundwater to runoff
        self.runoff = self.runoff + self.sloflo
Пример #2
0
def upscale_riverlength(ldd, order, factor):
    """
    Upscales the riverlength using 'factor'
    The resulting maps can be resampled (e.g. using resample.exe) by factor and should
    include the accurate length as determined with the original higher
    resolution maps.  This function is **depricated**,
    use are_riverlength instead as this version
    is very slow for large maps

    Input:
        - ldd
        - minimum streamorder to include

    Output:
        - distance per factor cells
    """

    strorder = pcr.streamorder(ldd)
    strorder = pcr.ifthen(strorder >= order, strorder)
    dist = pcr.cover(
        pcr.max(pcr.celllength(),
                pcr.ifthen(pcr.boolean(strorder), pcr.downstreamdist(ldd))),
        0,
    )
    totdist = pcr.max(
        pcr.ifthen(
            pcr.boolean(strorder),
            pcr.windowtotal(pcr.ifthen(pcr.boolean(strorder), dist),
                            pcr.celllength() * factor),
        ),
        dist,
    )

    return totdist
Пример #3
0
    def additional_post_processing(self):

        # estimate of total groundwwater storage that is accesible (based on the assumption of a certain limit of pumping depth)
        if "accesibleGroundwaterVolume" or "accesibleGroundwaterThickness" in self.variables_for_report:

            if self._model.modflow.number_of_layers == 1:                \
                               self.accesibleGroundwaterThickness = pcr.ifthen(self._model.landmask, \
                                                                               self._model.modflow.specific_yield_1 * \
                                                                               pcr.max(0.0, self.groundwaterHeadLayer1 - pcr.max(self._model.modflow.max_accesible_elevation, \
                                                                                                                                 self._model.modflow.bottom_layer_1)))

            if self._model.modflow.number_of_layers == 2:                \
                               self.accesibleGroundwaterThickness = pcr.ifthen(self._model.landmask, \
                                                                               self._model.modflow.specific_yield_1 * \
                                                                               pcr.max(0.0, self.groundwaterHeadLayer1 - pcr.max(self._model.modflow.max_accesible_elevation, \
                                                                                                                                 self._model.modflow.bottom_layer_1))) + \
                                                                    pcr.ifthen(self._model.landmask, \
                                                                               self._model.modflow.specific_yield_2 * \
                                                                               pcr.max(0.0, self.groundwaterHeadLayer1 - pcr.max(self._model.modflow.max_accesible_elevation, \
                                                                                                                                 self._model.modflow.bottom_layer_2)))
            self.accesibleGroundwaterVolume = self.accesibleGroundwaterThickness *\
                                              self._model.modflow.cellAreaMap

            # TODO: Make the reporting of accesibleGroundwaterThickness more generic.

        # report elevation in pcraster map
        self.top_uppermost_layer = pcr.ifthen(self._model.landmask,
                                              self._model.modflow.top_layer_2)
        self.bottom_uppermost_layer = pcr.ifthen(
            self._model.landmask, self._model.modflow.bottom_layer_2)
        self.bottom_lowermost_layer = pcr.ifthen(
            self._model.landmask, self._model.modflow.bottom_layer_1)
Пример #4
0
    def estimate_bottom_of_bank_storage(self):

        # influence zone depth (m)  # TODO: Define this one as part of 
        influence_zone_depth = 5.0
        
        # bottom_elevation > flood_plain elevation - influence zone
        bottom_of_bank_storage = self.dem_floodplain - influence_zone_depth

        # reducing noise (so we will not introduce unrealistic sinks)      # TODO: Define the window size as part of the configuration/ini file
        bottom_of_bank_storage = pcr.max(bottom_of_bank_storage,\
                                 pcr.windowaverage(bottom_of_bank_storage, 3.0 * pcr.clone().cellSize()))

        # bottom_elevation > river bed
        bottom_of_bank_storage = pcr.max(self.dem_riverbed, bottom_of_bank_storage)
        
        # reducing noise by comparing to its downstream value (so we will not introduce unrealistic sinks)
        bottom_of_bank_storage = pcr.max(bottom_of_bank_storage, \
                                        (bottom_of_bank_storage +
                                         pcr.cover(pcr.downstream(self.lddMap, bottom_of_bank_storage), bottom_of_bank_storage))/2.)

        # bottom_elevation >= 0.0 (must be higher than sea level)
        bottom_of_bank_storage = pcr.max(0.0, bottom_of_bank_storage)
         
        # bottom_elevation < dem_average (this is to drain overland flow)
        bottom_of_bank_storage = pcr.min(bottom_of_bank_storage, self.dem_average)
        bottom_of_bank_storage = pcr.cover(bottom_of_bank_storage, self.dem_average)

        # TODO: Check again this concept. 
        
        # TODO: We may want to improve this concept - by incorporating the following 
        # - smooth bottom_elevation
        # - upstream areas in the mountainous regions and above perrenial stream starting points may also be drained (otherwise water will accumulate) 
        # - bottom_elevation > minimum elevation that is estimated from the maximum of S3 from the PCR-GLOBWB simulation
        
        return bottom_of_bank_storage
    def estimate_bottom_of_bank_storage(self):

        # influence zone depth (m)
        influence_zone_depth = 0.50
        
        # bottom_elevation > flood_plain elevation - influence zone
        bottom_of_bank_storage = self.dem_floodplain - influence_zone_depth

        #~ # bottom_elevation > river bed
        #~ bottom_of_bank_storage = pcr.max(self.dem_riverbed, bottom_of_bank_storage)
        
        # bottom_elevation > its downstream value
        bottom_of_bank_storage = pcr.max(bottom_of_bank_storage, \
                                 pcr.cover(pcr.downstream(self.lddMap, bottom_of_bank_storage), bottom_of_bank_storage))

        # bottom_elevation >= 0.0 (must be higher than sea level)
        bottom_of_bank_storage = pcr.max(0.0, bottom_of_bank_storage)
         
        # reducing noise
        bottom_of_bank_storage = pcr.max(bottom_of_bank_storage,\
                                 pcr.windowaverage(bottom_of_bank_storage, 3.0 * pcr.clone().cellSize()))

        # bottom_elevation < dem_average
        bottom_of_bank_storage = pcr.min(bottom_of_bank_storage, self.dem_average)
        bottom_of_bank_storage = pcr.cover(bottom_of_bank_storage, self.dem_average)

        # TODO: Check again this concept. 
        
        # TODO: We may want to improve this concept - by incorporating the following 
        # - smooth bottom_elevation
        # - upstream areas in the mountainous regions and above perrenial stream starting points may also be drained (otherwise water will accumulate) 
        # - bottom_elevation > minimum elevation that is estimated from the maximum of S3 from the PCR-GLOBWB simulation
        
        return bottom_of_bank_storage
Пример #6
0
    def downscalePrecipitation(self,
                               currTimeStep,
                               useFactor=True,
                               minCorrelationCriteria=0.85):

        preSlope = 0.001 * vos.netcdf2PCRobjClone(\
                           self.precipLapseRateNC, 'precipitation',\
                           currTimeStep.month, useDoy = "Yes",\
                           cloneMapFileName=self.cloneMap,\
                           LatitudeLongitude = True)
        preSlope = pcr.cover(preSlope, 0.0)
        preSlope = pcr.max(0., preSlope)

        preCriteria = vos.netcdf2PCRobjClone(\
                     self.precipitCorrelNC, 'precipitation',\
                     currTimeStep.month, useDoy = "Yes",\
                     cloneMapFileName=self.cloneMap,\
                     LatitudeLongitude = True)
        preSlope = pcr.ifthenelse(preCriteria > minCorrelationCriteria,\
                   preSlope, 0.0)
        preSlope = pcr.cover(preSlope, 0.0)

        if useFactor == True:
            factor = pcr.max(0.,
                             self.precipitation + preSlope * self.anomalyDEM)
            factor = factor / \
                     pcr.areaaverage(factor, self.meteoDownscaleIds)
            factor = pcr.cover(factor, 1.0)
            self.precipitation = factor * self.precipitation
        else:
            self.precipitation = self.precipitation + preSlope * self.anomalyDEM

        self.precipitation = pcr.max(0.0, self.precipitation)
	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
Пример #8
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
Пример #9
0
    def moveFromChannelToWaterBody(self,\
                                   newStorageAtLakeAndReservoirs,\
                                   timestepsToAvgDischarge,\
                                   maxTimestepsToAvgDischargeShort,\
                                   length_of_time_step = vos.secondsPerDay()):
        
        # new lake and/or reservoir storages (m3)
        newStorageAtLakeAndReservoirs = pcr.cover(\
                                        pcr.areatotal(newStorageAtLakeAndReservoirs,\
                                                      self.waterBodyIds),0.0)

        # incoming volume (m3)
        self.inflow = newStorageAtLakeAndReservoirs - self.waterBodyStorage
        
        # inflowInM3PerSec (m3/s)
        inflowInM3PerSec = self.inflow / length_of_time_step

        # updating (short term) average inflow (m3/s) ; 
        # - needed to constrain lake outflow:
        #
        temp = pcr.max(1.0, pcr.min(maxTimestepsToAvgDischargeShort, self.timestepsToAvgDischarge - 1.0 + length_of_time_step / vos.secondsPerDay()))
        deltaInflow = inflowInM3PerSec - self.avgInflow  
        R = deltaInflow * ( length_of_time_step / vos.secondsPerDay() ) / temp
        self.avgInflow = self.avgInflow + R                
        self.avgInflow = pcr.max(0.0, self.avgInflow)
        #
        # for the reference, see the "weighted incremental algorithm" in http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance                        

        # updating waterBodyStorage (m3)
        self.waterBodyStorage = newStorageAtLakeAndReservoirs
Пример #10
0
def agriZone_Ep_Sa_beta(self, k):
    """
    - Potential evaporation is decreased by energy used for interception evaporation    
    - Formula for evaporation based on LP
    - Outgoing fluxes are determined based on (value in previous timestep + inflow) 
    and if this leads to negative storage, the outgoing fluxes are corrected to rato --> Eu is 
    no longer taken into account for this correction
    - Qa u is determined from overflow from Sa --> incorporation of beta function
    - Fa is based on storage in Sa
    - Code for ini-file: 6
    """

    JarvisCoefficients.calcEp(self, k)
    self.PotEvaporation = pcr.cover(
        pcr.ifthenelse(self.EpHour >= 0, self.EpHour, 0), 0)

    self.samax2 = self.samax[k] * pcr.scalar(self.catchArea)
    self.Qaadd = pcr.max(self.Sa_t[k] + self.Pe - self.samax2, 0)

    self.Sa[k] = self.Sa_t[k] + (self.Pe - self.Qaadd)
    self.SaN = pcr.min(pcr.max(self.Sa[k] / self.samax2, 0), 1)
    self.SuN = self.Su[k] / self.sumax[k]

    self.Ea1 = pcr.max((self.PotEvaporation - self.Ei), 0) * pcr.min(
        self.Sa[k] / (self.samax2 * self.LP[k]), 1)
    self.Qa1 = (self.Pe - self.Qaadd) * (1 - (1 - self.SaN)**self.beta[k])
    self.Fa1 = pcr.ifthenelse(
        self.SaN > 0,
        self.Fmin[k] + (self.Fmax[k] - self.Fmin[k]) * e**(-self.decF[k] *
                                                           (1 - self.SaN)),
        0,
    )
    self.Sa[k] = self.Sa_t[k] + (self.Pe -
                                 self.Qaadd) - self.Qa1 - self.Fa1 - self.Ea1

    self.Sa_diff = pcr.ifthenelse(self.Sa[k] < 0, self.Sa[k], 0)
    self.Qa = (self.Qa1 +
               (self.Qa1 / pcr.ifthenelse(self.Fa1 + self.Ea1 + self.Qa1 > 0,
                                          self.Fa1 + self.Ea1 + self.Qa1, 1)) *
               self.Sa_diff)
    self.Fa = (self.Fa1 +
               (self.Fa1 / pcr.ifthenelse(self.Fa1 + self.Ea1 + self.Qa1 > 0,
                                          self.Fa1 + self.Ea1 + self.Qa1, 1)) *
               self.Sa_diff)
    self.Ea = (self.Ea1 +
               (self.Ea1 / pcr.ifthenelse(self.Fa1 + self.Ea1 + self.Qa1 > 0,
                                          self.Fa1 + self.Ea1 + self.Qa1, 1)) *
               self.Sa_diff)
    self.Sa[k] = self.Sa_t[k] + (self.Pe -
                                 self.Qaadd) - self.Ea - self.Fa - self.Qa
    self.Sa[k] = pcr.ifthenelse(self.Sa[k] < 0, 0, self.Sa[k])
    self.Sa_diff2 = pcr.ifthen(self.Sa[k] < 0, self.Sa[k])

    self.wbSa_[k] = (self.Pe - self.Ea - self.Qa - self.Qaadd - self.Fa -
                     self.Sa[k] + self.Sa_t[k])

    self.Ea_[k] = self.Ea
    self.Qa_[k] = self.Qa + self.Qaadd
    self.Fa_[k] = self.Fa
Пример #11
0
    def getWaterBodyOutflow(
            self,
            maxTimestepsToAvgDischargeLong,
            avgChannelDischarge,
            length_of_time_step=vos.secondsPerDay(),
            downstreamDemand=None,
    ):

        # outflow in volume from water bodies with lake type (m3):
        lakeOutflow = self.getLakeOutflow(avgChannelDischarge,
                                          length_of_time_step)

        # outflow in volume from water bodies with reservoir type (m3):
        if isinstance(downstreamDemand, types.NoneType):
            downstreamDemand = pcr.scalar(0.0)
        reservoirOutflow = self.getReservoirOutflow(avgChannelDischarge,
                                                    length_of_time_step,
                                                    downstreamDemand)

        # outgoing/release volume from lakes and/or reservoirs
        self.waterBodyOutflow = pcr.cover(reservoirOutflow, lakeOutflow)

        # make sure that all water bodies have outflow:
        self.waterBodyOutflow = pcr.max(0.,
                                        pcr.cover(self.waterBodyOutflow, 0.0))

        # limit outflow to available storage
        factor = 0.25  # to avoid flip flop
        self.waterBodyOutflow = pcr.min(self.waterBodyStorage * factor,
                                        self.waterBodyOutflow)  # unit: m3
        # use round values
        self.waterBodyOutflow = (pcr.rounddown(self.waterBodyOutflow / 1.) * 1.
                                 )  # unit: m3

        # outflow rate in m3 per sec
        waterBodyOutflowInM3PerSec = (self.waterBodyOutflow /
                                      length_of_time_step)  # unit: m3/s

        # updating (long term) average outflow (m3/s) ;
        # - needed to constrain/maintain reservoir outflow:
        #
        temp = pcr.max(
            1.0,
            pcr.min(
                maxTimestepsToAvgDischargeLong,
                self.timestepsToAvgDischarge - 1.0 +
                length_of_time_step / vos.secondsPerDay(),
            ),
        )
        deltaOutflow = waterBodyOutflowInM3PerSec - self.avgOutflow
        R = deltaOutflow * (length_of_time_step / vos.secondsPerDay()) / temp
        self.avgOutflow = self.avgOutflow + R
        self.avgOutflow = pcr.max(0.0, self.avgOutflow)
        #
        # for the reference, see the "weighted incremental algorithm" in http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance

        # update waterBodyStorage (after outflow):
        self.waterBodyStorage = self.waterBodyStorage - self.waterBodyOutflow
        self.waterBodyStorage = pcr.max(0.0, self.waterBodyStorage)
Пример #12
0
    def downscaleReferenceETPot(self, zeroCelciusInKelvin=273.15):

        temperatureInKelvin = self.temperature + zeroCelciusInKelvin
        factor = pcr.max(0.0, temperatureInKelvin)
        factor = factor / \
                 pcr.areaaverage(factor, self.meteoDownscaleIds)
        factor = pcr.cover(factor, 1.0)
        self.referencePotET = pcr.max(0.0, factor * self.referencePotET)
Пример #13
0
def SnowPackHBV(Snow, SnowWater, Precipitation, Temperature, TTI, TT, TTM,
                Cfmax, WHC):
    """
    HBV Type snowpack modelling using a Temperature degree factor. All correction
    factors (RFCF and SFCF) are set to 1. The refreezing efficiency factor is set to 0.05.

    :param Snow:
    :param SnowWater:
    :param Precipitation:
    :param Temperature:
    :param TTI:
    :param TT:
    :param TTM:
    :param Cfmax:
    :param WHC:
    :return: Snow,SnowMelt,Precipitation
    """

    RFCF = 1.0  # correction factor for rainfall
    CFR = 0.05000  # refreeing efficiency constant in refreezing of freewater in snow
    SFCF = 1.0  # correction factor for snowfall

    RainFrac = pcr.ifthenelse(
        1.0 * TTI == 0.0,
        pcr.ifthenelse(Temperature <= TT, pcr.scalar(0.0), pcr.scalar(1.0)),
        pcr.min((Temperature - (TT - TTI / 2)) / TTI, pcr.scalar(1.0)),
    )
    RainFrac = pcr.max(
        RainFrac,
        pcr.scalar(0.0))  # fraction of precipitation which falls as rain
    SnowFrac = 1 - RainFrac  # fraction of precipitation which falls as snow
    Precipitation = (SFCF * SnowFrac * Precipitation +
                     RFCF * RainFrac * Precipitation
                     )  # different correction for rainfall and snowfall

    SnowFall = SnowFrac * Precipitation  # snowfall depth
    RainFall = RainFrac * Precipitation  # rainfall depth
    PotSnowMelt = pcr.ifthenelse(
        Temperature > TTM, Cfmax * (Temperature - TTM),
        pcr.scalar(0.0))  # Potential snow melt, based on temperature
    PotRefreezing = pcr.ifthenelse(
        Temperature < TTM, Cfmax * CFR * (TTM - Temperature),
        0.0)  # Potential refreezing, based on temperature
    Refreezing = pcr.ifthenelse(Temperature < TTM,
                                pcr.min(PotRefreezing, SnowWater),
                                0.0)  # actual refreezing
    # No landuse correction here
    SnowMelt = pcr.min(PotSnowMelt, Snow)  # actual snow melt
    Snow = Snow + SnowFall + Refreezing - SnowMelt  # dry snow content
    SnowWater = SnowWater - Refreezing  # free water content in snow
    MaxSnowWater = Snow * WHC  # Max water in the snow
    SnowWater = (SnowWater + SnowMelt + RainFall
                 )  # Add all water and potentially supersaturate the snowpack
    RainFall = pcr.max(SnowWater - MaxSnowWater,
                       0.0)  # rain + surpluss snowwater
    SnowWater = SnowWater - RainFall

    return Snow, SnowWater, SnowMelt, RainFall, SnowFall
Пример #14
0
def volume_spread(ldd,
                  hand,
                  subcatch,
                  volume,
                  volume_thres=0.,
                  area_multiplier=1.,
                  iterations=15):
    """
    Estimate 2D flooding from a 1D simulation per subcatchment reach
    Input:
        ldd -- pcraster object direction, local drain directions
        hand -- pcraster object float32, elevation data normalised to nearest drain
        subcatch -- pcraster object ordinal, subcatchments with IDs
        volume -- pcraster object float32, scalar flood volume (i.e. m3 volume outside the river bank within subcatchment)
        volume_thres=0. -- scalar threshold, at least this amount of m3 of volume should be present in a catchment
        area_multiplier=1. -- in case the maps are not in m2, set a multiplier other than 1. to convert
        iterations=15 -- number of iterations to use
    Output:
        inundation -- pcraster object float32, scalar inundation estimate
    """
    #initial values
    pcr.setglobaloption("unittrue")
    dem_min = pcr.areaminimum(hand,
                              subcatch)  # minimum elevation in subcatchments
    # pcr.report(dem_min, 'dem_min.map')
    dem_norm = hand - dem_min
    # pcr.report(dem_norm, 'dem_norm.map')
    # surface of each subcatchment
    surface = pcr.areaarea(subcatch) * area_multiplier
    pcr.report(surface, 'surface.map')

    error_abs = pcr.scalar(1e10)  # initial error (very high)
    volume_catch = pcr.areatotal(volume, subcatch)
    # pcr.report(volume_catch, 'volume_catch.map')

    depth_catch = volume_catch / surface
    pcr.report(depth_catch, 'depth_catch.map')

    dem_max = pcr.ifthenelse(volume_catch > volume_thres, pcr.scalar(32.),
                             pcr.scalar(0))  # bizarre high inundation depth
    dem_min = pcr.scalar(0.)
    for n in range(iterations):
        print('Iteration: {:02d}'.format(n + 1))
        #####while np.logical_and(error_abs > error_thres, dem_min < dem_max):
        dem_av = (dem_min + dem_max) / 2
        # pcr.report(dem_av, 'dem_av00.{:03d}'.format(n + 1))
        # compute value at dem_av
        average_depth_catch = pcr.areaaverage(pcr.max(dem_av - dem_norm, 0),
                                              subcatch)
        # pcr.report(average_depth_catch, 'depth_c0.{:03d}'.format(n + 1))
        error = pcr.cover((depth_catch - average_depth_catch) / depth_catch,
                          depth_catch * 0)
        # pcr.report(error, 'error000.{:03d}'.format(n + 1))
        dem_min = pcr.ifthenelse(error > 0, dem_av, dem_min)
        dem_max = pcr.ifthenelse(error <= 0, dem_av, dem_max)
    # error_abs = np.abs(error)  # TODO: not needed probably, remove
    inundation = pcr.max(dem_av - dem_norm, 0)
    return inundation
def diffuseTransportXY(dMat,fracX,fracY):
  #-evaluates transport in the four cardinal directions with the
  # shift function (1: up, left; -1: right, down), returning the
  # resulting change at each location
  dMatWest=   pcr.max(0,pcr.shift0(-fracX*dMat, 0, 1))
  dMatEast=   pcr.max(0,pcr.shift0( fracX*dMat, 0,-1))
  dMatNorth=  pcr.max(0,pcr.shift0( fracY*dMat, 1, 0))
  dMatSouth=  pcr.max(0,pcr.shift0(-fracY*dMat,-1, 0))
  return -dMat+dMatNorth+dMatEast+dMatSouth+dMatWest
Пример #16
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)
 def possiblyAdjustSoilMoistureThickWhenRegolithThicknessChanges(self):
     amountOfMoistureThickAdded = pcr.max(
         0, self.wiltingPointThick - self.soilMoistureThick)
     amountOfMoistureThickRemoved = pcr.max(
         0, self.soilMoistureThick - self.soilPorosityThick)
     amountOfMoistureThickNetAdded = amountOfMoistureThickAdded - amountOfMoistureThickRemoved
     self.soilMoistureThick = pcr.min(
         pcr.max(self.soilMoistureThick, self.wiltingPointThick),
         self.soilPorosityThick)
     return amountOfMoistureThickNetAdded
Пример #18
0
    def getLakeOutflow(self,
                       avgChannelDischarge,
                       length_of_time_step=vos.secondsPerDay()):

        # waterHeight (m): temporary variable, a function of storage:
        minWaterHeight = (
            0.001
        )  # (m) Rens used 0.001 m as the limit # this is to make sure there is always lake outflow,
        # but it will be still limited by available self.waterBodyStorage
        waterHeight = pcr.cover(
            pcr.max(
                minWaterHeight,
                (self.waterBodyStorage - pcr.cover(self.waterBodyCap, 0.0)) /
                self.waterBodyArea,
            ),
            0.0,
        )

        # weirWidth (m) :
        # - estimated from avgOutflow (m3/s) using the bankfull discharge formula
        #
        avgOutflow = self.avgOutflow
        avgOutflow = pcr.ifthenelse(
            avgOutflow > 0.0,
            avgOutflow,
            pcr.max(avgChannelDischarge, self.avgInflow, 0.001),
        )  # This is needed when new lakes/reservoirs introduced (its avgOutflow is still zero).
        avgOutflow = pcr.areamaximum(avgOutflow, self.waterBodyIds)
        #
        bankfullWidth = pcr.cover(pcr.scalar(4.8) * ((avgOutflow)**(0.5)), 0.0)
        weirWidthUsed = bankfullWidth
        weirWidthUsed = pcr.max(
            weirWidthUsed, self.minWeirWidth
        )  # TODO: minWeirWidth based on the GRanD database
        weirWidthUsed = pcr.cover(
            pcr.ifthen(pcr.scalar(self.waterBodyIds) > 0.0, weirWidthUsed),
            0.0)

        # avgInflow <= lakeOutflow (weirFormula) <= waterBodyStorage
        lakeOutflowInM3PerSec = pcr.max(
            self.weirFormula(waterHeight, weirWidthUsed),
            self.avgInflow)  # unit: m3/s

        # estimate volume of water relased by lakes
        lakeOutflow = lakeOutflowInM3PerSec * length_of_time_step  # unit: m3
        lakeOutflow = pcr.min(self.waterBodyStorage, lakeOutflow)
        #
        lakeOutflow = pcr.ifthen(
            pcr.scalar(self.waterBodyIds) > 0.0, lakeOutflow)
        lakeOutflow = pcr.ifthen(
            pcr.scalar(self.waterBodyTyp) == 1, lakeOutflow)

        # TODO: Consider endorheic lake/basin. No outflow for endorheic lake/basin!

        return lakeOutflow
Пример #19
0
    def getICs(self, iniItems, iniConditions=None):

        #print iniItems.groundwaterOptions['storGroundwaterFossilIni']

        # initial condition for storGroundwater (unit: m)
        if iniConditions == None:  # when the model just start
            self.storGroundwater = vos.readPCRmapClone(\
                                         iniItems.groundwaterOptions['storGroundwaterIni'],
                                         self.cloneMap,self.tmpDir,self.inputDir)
            self.avgAbstraction  = vos.readPCRmapClone(\
                                         iniItems.groundwaterOptions['avgTotalGroundwaterAbstractionIni'],
                                         self.cloneMap,self.tmpDir,self.inputDir)
        else:  # during/after spinUp
            self.storGroundwater = iniConditions['groundwater'][
                'storGroundwater']
            self.avgAbstraction = iniConditions['groundwater'][
                'avgTotalGroundwaterAbstractionIni']

        # initial condition for storGroundwaterFossil (unit: m)
        #
        # Note that storGroundwaterFossil should not be depleted during the spin-up.
        #
        if iniItems.groundwaterOptions['storGroundwaterFossilIni'] != "Maximum":
            #logger.info("Using a pre-defined initial condition for fossil groundwater storage.")
            self.storGroundwaterFossil = vos.readPCRmapClone(\
                                         iniItems.groundwaterOptions['storGroundwaterFossilIni'],
                                         self.cloneMap,self.tmpDir,self.inputDir)
        #
        if self.limitFossilGroundwaterAbstraction and iniItems.groundwaterOptions[
                'storGroundwaterFossilIni'] != "Maximum":
            #logger.info("The pre-defined initial condition for fossil groundwater is limited by fossilWaterCap (full capacity).")
            self.storGroundwaterFossil = pcr.min(self.storGroundwaterFossil,
                                                 self.fossilWaterCap)
        #
        if self.limitFossilGroundwaterAbstraction and iniItems.groundwaterOptions[
                'storGroundwaterFossilIni'] == "Maximum":
            #logger.info("Assuming 'full' fossilWaterCap as the initial condition for fossil groundwater storage.")
            self.storGroundwaterFossil = self.fossilWaterCap

        # make sure that active storGroundwater and avgAbstraction cannot be negative
        #
        self.storGroundwater = pcr.cover(self.storGroundwater, 0.0)
        self.storGroundwater = pcr.max(0., self.storGroundwater)
        self.storGroundwater = pcr.ifthen(self.landmask,\
                                          self.storGroundwater)
        #
        self.avgAbstraction = pcr.cover(self.avgAbstraction, 0.0)
        self.avgAbstraction = pcr.max(0., self.avgAbstraction)
        self.avgAbstraction  = pcr.ifthen(self.landmask,\
                                          self.avgAbstraction)

        # storGroundwaterFossil can be negative (particularly if limitFossilGroundwaterAbstraction == False)
        self.storGroundwaterFossil = pcr.ifthen(self.landmask,\
                                                self.storGroundwaterFossil)
Пример #20
0
def agriZone_Ep_Sa_cropG(self, k):
    """
    - Potential evaporation is decreased by energy used for interception evaporation    
    - Formula for evaporation based on LP
    - Outgoing fluxes are determined based on (value in previous timestep + inflow) 
    and if this leads to negative storage, the outgoing fluxes are corrected to rato --> Eu is 
    no longer taken into account for this correction
    - Qa u is determined from overflow from Sa
    - Fa is based on storage in Sa
    - Code for ini-file: 4
    """
    JarvisCoefficients.calcEp(self, k)
    self.PotEvaporation = pcr.cover(pcr.ifthenelse(self.EpHour >= 0, self.EpHour, 0), 0)

    self.samax2 = self.samax[k] * self.cropG
    self.Qaadd = pcr.max(self.Sa_t[k] - self.samax2, 0)

    self.Qa = pcr.max(self.Pe - (self.samax2 - self.Sa_t[k]), 0) + self.Qaadd
    self.Sa[k] = self.Sa_t[k] + (self.Pe - self.Qa)
    self.SaN = pcr.min(self.Sa[k] / self.samax2, 1)
    self.SuN = self.Su[k] / self.sumax[k]

    self.Ea1 = pcr.max((self.PotEvaporation - self.Ei), 0) * pcr.min(
        self.Sa[k] / (self.samax2 * self.LP[k]), 1
    )

    self.Fa1 = pcr.ifthenelse(
        self.SaN > 0,
        self.Fmin[k]
        + (self.Fmax[k] - self.Fmin[k]) * e ** (-self.decF[k] * (1 - self.SaN)),
        0,
    )
    self.Sa[k] = self.Sa_t[k] + (self.Pe - self.Qa) - self.Fa1 - self.Ea1

    self.Sa_diff = pcr.ifthenelse(self.Sa[k] < 0, self.Sa[k], 0)
    self.Fa = (
        self.Fa1
        + (self.Fa1 / pcr.ifthenelse(self.Fa1 + self.Ea1 > 0, self.Fa1 + self.Ea1, 1))
        * self.Sa_diff
    )
    self.Ea = (
        self.Ea1
        + (self.Ea1 / pcr.ifthenelse(self.Fa1 + self.Ea1 > 0, self.Fa1 + self.Ea1, 1))
        * self.Sa_diff
    )
    self.Sa[k] = self.Sa_t[k] + (self.Pe - self.Qa) - self.Ea - self.Fa
    self.Sa[k] = pcr.ifthenelse(self.Sa[k] < 0, 0, self.Sa[k])
    self.Sa_diff2 = pcr.ifthen(self.Sa[k] < 0, self.Sa[k])

    self.wbSa_[k] = self.Pe - self.Ea - self.Qa - self.Fa - self.Sa[k] + self.Sa_t[k]

    self.Ea_[k] = self.Ea
    self.Qa_[k] = self.Qa
    self.Fa_[k] = self.Fa
Пример #21
0
    def readTopo(self, iniItems):

        # maps of elevation attributes:
        topoParams = ['tanslope', 'slopeLength', 'orographyBeta']
        if iniItems.landSurfaceOptions['topographyNC'] == str(None):
            for var in topoParams:
                input = iniItems.landSurfaceOptions[str(var)]
                vars(self)[var] = pcr.scalar(0.0)
                vars(self)[var] = vos.readPCRmapClone(input, self.cloneMap,
                                                      self.tmpDir,
                                                      self.inputDir)
                vars(self)[var] = pcr.cover(vars(self)[var], 0.0)
        else:
            topoPropertiesNC = vos.getFullPath(\
                               iniItems.landSurfaceOptions[\
                                               'topographyNC'],
                                                self.inputDir)
            for var in topoParams:
                vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(\
                                    topoPropertiesNC,var, \
                                    cloneMapFileName = self.cloneMap)
                vars(self)[var] = pcr.cover(vars(self)[var], 0.0)
        self.tanslope = pcr.max(self.tanslope, 0.00001)

        # maps of relative elevation above flood plains
        dzRel = [
            'dzRel0001', 'dzRel0005', 'dzRel0010', 'dzRel0020', 'dzRel0030',
            'dzRel0040', 'dzRel0050', 'dzRel0060', 'dzRel0070', 'dzRel0080',
            'dzRel0090', 'dzRel0100'
        ]
        if iniItems.landSurfaceOptions['topographyNC'] == str(None):
            for i in range(0, len(dzRel)):
                var = dzRel[i]
                input = iniItems.landSurfaceOptions[str(var)]
                vars(self)[var] = vos.readPCRmapClone(input, self.cloneMap,
                                                      self.tmpDir,
                                                      self.inputDir)
                vars(self)[var] = pcr.cover(vars(self)[var], 0.0)
                if i > 0:
                    vars(self)[var] = pcr.max(
                        vars(self)[var],
                        vars(self)[dzRel[i - 1]])
        else:
            for i in range(0, len(dzRel)):
                var = dzRel[i]
                vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(\
                                    topoPropertiesNC,var, \
                                    cloneMapFileName = self.cloneMap)
                vars(self)[var] = pcr.cover(vars(self)[var], 0.0)
                if i > 0:
                    vars(self)[var] = pcr.max(
                        vars(self)[var],
                        vars(self)[dzRel[i - 1]])
Пример #22
0
    def getLakeOutflow(
        self, avgChannelDischarge, length_of_time_step=vos.secondsPerDay()
    ):

        # waterHeight (m): temporary variable, a function of storage:
        minWaterHeight = (
            0.001
        )  # (m) Rens used 0.001 m as the limit # this is to make sure there is always lake outflow,
        # but it will be still limited by available self.waterBodyStorage
        waterHeight = pcr.cover(
            pcr.max(
                minWaterHeight,
                (self.waterBodyStorage - pcr.cover(self.waterBodyCap, 0.0))
                / self.waterBodyArea,
            ),
            0.0,
        )

        # weirWidth (m) :
        # - estimated from avgOutflow (m3/s) using the bankfull discharge formula
        #
        avgOutflow = self.avgOutflow
        avgOutflow = pcr.ifthenelse(
            avgOutflow > 0.0,
            avgOutflow,
            pcr.max(avgChannelDischarge, self.avgInflow, 0.001),
        )  # This is needed when new lakes/reservoirs introduced (its avgOutflow is still zero).
        avgOutflow = pcr.areamaximum(avgOutflow, self.waterBodyIds)
        #
        bankfullWidth = pcr.cover(pcr.scalar(4.8) * ((avgOutflow) ** (0.5)), 0.0)
        weirWidthUsed = bankfullWidth
        weirWidthUsed = pcr.max(
            weirWidthUsed, self.minWeirWidth
        )  # TODO: minWeirWidth based on the GRanD database
        weirWidthUsed = pcr.cover(
            pcr.ifthen(pcr.scalar(self.waterBodyIds) > 0.0, weirWidthUsed), 0.0
        )

        # avgInflow <= lakeOutflow (weirFormula) <= waterBodyStorage
        lakeOutflowInM3PerSec = pcr.max(
            self.weirFormula(waterHeight, weirWidthUsed), self.avgInflow
        )  # unit: m3/s

        # estimate volume of water relased by lakes
        lakeOutflow = lakeOutflowInM3PerSec * length_of_time_step  # unit: m3
        lakeOutflow = pcr.min(self.waterBodyStorage, lakeOutflow)
        #
        lakeOutflow = pcr.ifthen(pcr.scalar(self.waterBodyIds) > 0.0, lakeOutflow)
        lakeOutflow = pcr.ifthen(pcr.scalar(self.waterBodyTyp) == 1, lakeOutflow)

        # TODO: Consider endorheic lake/basin. No outflow for endorheic lake/basin!

        return lakeOutflow
Пример #23
0
def volume_spread(ldd,
                  hand,
                  subcatch,
                  volume,
                  volume_thres=0.,
                  cell_surface=1.,
                  iterations=15,
                  logging=logging,
                  order=0):
    """
    Estimate 2D flooding from a 1D simulation per subcatchment reach
    Input:
        ldd -- pcraster object direction, local drain directions
        hand -- pcraster object float32, elevation data normalised to nearest drain
        subcatch -- pcraster object ordinal, subcatchments with IDs
        volume -- pcraster object float32, scalar flood volume (i.e. m3 volume outside the river bank within subcatchment)
        volume_thres=0. -- scalar threshold, at least this amount of m3 of volume should be present in a catchment
        area_multiplier=1. -- in case the maps are not in m2, set a multiplier other than 1. to convert
        iterations=15 -- number of iterations to use
    Output:
        inundation -- pcraster object float32, scalar inundation estimate
    """
    #initial values
    pcr.setglobaloption("unitcell")
    dem_min = pcr.areaminimum(hand,
                              subcatch)  # minimum elevation in subcatchments
    dem_norm = hand - dem_min
    # surface of each subcatchment
    surface = pcr.areaarea(subcatch) * pcr.areaaverage(
        cell_surface, subcatch)  # area_multiplier
    error_abs = pcr.scalar(1e10)  # initial error (very high)
    volume_catch = pcr.areatotal(volume, subcatch)
    depth_catch = volume_catch / surface  # meters water disc averaged over subcatchment
    # ilt(depth_catch, 'depth_catch_{:02d}.map'.format(order))
    # pcr.report(volume, 'volume_{:02d}.map'.format(order))
    dem_max = pcr.ifthenelse(volume_catch > volume_thres, pcr.scalar(32.),
                             pcr.scalar(0))  # bizarre high inundation depth
    dem_min = pcr.scalar(0.)
    for n in range(iterations):
        logging.debug('Iteration: {:02d}'.format(n + 1))
        #####while np.logical_and(error_abs > error_thres, dem_min < dem_max):
        dem_av = (dem_min + dem_max) / 2
        # compute value at dem_av
        average_depth_catch = pcr.areaaverage(pcr.max(dem_av - dem_norm, 0),
                                              subcatch)
        error = pcr.cover((depth_catch - average_depth_catch) / depth_catch,
                          depth_catch * 0)
        dem_min = pcr.ifthenelse(error > 0, dem_av, dem_min)
        dem_max = pcr.ifthenelse(error <= 0, dem_av, dem_max)
    inundation = pcr.max(dem_av - dem_norm, 0)
    pcr.setglobaloption('unittrue')
    return inundation
Пример #24
0
    def dynamic(self):

        logger.info("Step 4: Monte Carlo simulation")

        # draw a random value (uniform for the entire map)
        z = pcr.mapnormal()
        #~ self.report(z,"z")

        # constraints, in order to make sure that random values are in the table of "lookup_table_average_thickness"
        z = pcr.max(-5.0, z)
        z = pcr.min(5.0, z)

        # assign average thickness (also uniform for the entire map) based on z
        self.Davg = pcr.lookupscalar(self.lookup_table_average_thickness, z)
        #
        self.report(self.Davg, "davg")
        self.lnDavg = pcr.ln(self.Davg)

        # sedimentary basin thickness (varying over cells and samples)
        lnD = self.F * (self.lnCV * self.lnDavg) + self.lnDavg

        # set the minimum depth (must be bigger than zero)
        minimum_depth = 0.005
        lnD = pcr.max(pcr.ln(minimum_depth), lnD)

        # extrapolation
        lnD = pcr.cover(lnD, \
              pcr.windowaverage(lnD, 1.50*vos.getMapAttributes(self.clone_map_file,"cellsize")))
        lnD = pcr.cover(lnD, \
              pcr.windowaverage(pcr.cover(lnD, pcr.ln(minimum_depth)), 3.00*vos.getMapAttributes(self.clone_map_file,"cellsize")))
        lnD = pcr.cover(lnD, \
              pcr.windowaverage(pcr.cover(lnD, pcr.ln(minimum_depth)), 0.50))

        # smoothing per quarter arc degree
        lnD = pcr.windowaverage(lnD, 0.25)

        # thickness in meter
        self.D = pcr.exp(lnD)

        #~ # smoothing  bottom elevation
        #~ dem_bottom = pcr.windowaverage(self.dem_average - self.D, 0.50)
        #~ # thickness in meter
        #~ self.D = pcr.max(0.0, self.dem_average - dem_bottom)

        #~ # smoothing
        #~ self.D = pcr.windowaverage(self.D, 1.50*vos.getMapAttributes(self.clone_map_file,"cellsize"))

        # accuracy until cm only
        self.D = pcr.rounddown(self.D * 100.) / 100.

        self.report(self.D, "damc")
Пример #25
0
    def readTopo(self, iniItems, optionDict):

        # a dictionary/section of options that will be used
        if optionDict == None: optionDict = iniItems._sections["landSurfaceOptions"]

        # maps of elevation attributes: 
        topoParams = ['tanslope','slopeLength','orographyBeta']
        if optionDict['topographyNC'] == str(None):
            for var in topoParams:
                input = configget(iniItems,"landSurfaceOptions",str(var),"None")
                vars(self)[var] = vos.readPCRmapClone(input,self.cloneMap,
                                                self.tmpDir,self.inputDir)
                if var != "slopeLength": vars(self)[var] = pcr.cover(vars(self)[var], 0.0)
        else:
            topoPropertiesNC = vos.getFullPath(\
                               optionDict['topographyNC'],
                                                self.inputDir)

            for var in topoParams:
                vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(\
                                    topoPropertiesNC,var, \
                                    cloneMapFileName = self.cloneMap)
                if var != "slopeLength": vars(self)[var] = pcr.cover(vars(self)[var], 0.0)

        #~ self.tanslope = pcr.max(self.tanslope, 0.00001)              # In principle, tanslope can be zero. Zero tanslope will provide zero TCL (no interflow)

        # covering slopeLength with its maximum value 
        self.slopeLength = pcr.cover(self.slopeLength, pcr.mapmaximum(self.slopeLength))
        
        # maps of relative elevation above flood plains 
        dzRel = ['dzRel0001','dzRel0005',
                 'dzRel0010','dzRel0020','dzRel0030','dzRel0040','dzRel0050',
                 'dzRel0060','dzRel0070','dzRel0080','dzRel0090','dzRel0100']
        if optionDict['topographyNC'] == str(None):
            for i in range(0, len(dzRel)):
                var = dzRel[i]
                input = optionDict[str(var)]
                vars(self)[var] = vos.readPCRmapClone(input,self.cloneMap,
                                                self.tmpDir,self.inputDir)
                vars(self)[var] = pcr.cover(vars(self)[var], 0.0)
                if i > 0: vars(self)[var] = pcr.max(vars(self)[var], vars(self)[dzRel[i-1]])
        else:
            for i in range(0, len(dzRel)):
                var = dzRel[i]
                vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(\
                                    topoPropertiesNC,var, \
                                    cloneMapFileName = self.cloneMap)
                vars(self)[var] = pcr.cover(vars(self)[var], 0.0)
                if i > 0: vars(self)[var] = pcr.max(vars(self)[var], vars(self)[dzRel[i-1]])
Пример #26
0
def volume_spread(ldd, hand, subcatch, volume, volume_thres=0., area_multiplier=1., iterations=15):
    """
    Estimate 2D flooding from a 1D simulation per subcatchment reach
    Input:
        ldd -- pcraster object direction, local drain directions
        hand -- pcraster object float32, elevation data normalised to nearest drain
        subcatch -- pcraster object ordinal, subcatchments with IDs
        volume -- pcraster object float32, scalar flood volume (i.e. m3 volume outside the river bank within subcatchment)
        volume_thres=0. -- scalar threshold, at least this amount of m3 of volume should be present in a catchment
        area_multiplier=1. -- in case the maps are not in m2, set a multiplier other than 1. to convert
        iterations=15 -- number of iterations to use
    Output:
        inundation -- pcraster object float32, scalar inundation estimate
    """
    #initial values
    pcr.setglobaloption("unittrue")
    dem_min = pcr.areaminimum(hand, subcatch)  # minimum elevation in subcatchments
    # pcr.report(dem_min, 'dem_min.map')
    dem_norm = hand - dem_min
    # pcr.report(dem_norm, 'dem_norm.map')
    # surface of each subcatchment
    surface = pcr.areaarea(subcatch)*area_multiplier
    pcr.report(surface, 'surface.map')

    error_abs = pcr.scalar(1e10)  # initial error (very high)
    volume_catch = pcr.areatotal(volume, subcatch)
    # pcr.report(volume_catch, 'volume_catch.map')

    depth_catch = volume_catch/surface
    pcr.report(depth_catch, 'depth_catch.map')

    dem_max = pcr.ifthenelse(volume_catch > volume_thres, pcr.scalar(32.),
                             pcr.scalar(0))  # bizarre high inundation depth
    dem_min = pcr.scalar(0.)
    for n in range(iterations):
        print('Iteration: {:02d}'.format(n + 1))
        #####while np.logical_and(error_abs > error_thres, dem_min < dem_max):
        dem_av = (dem_min + dem_max)/2
        # pcr.report(dem_av, 'dem_av00.{:03d}'.format(n + 1))
        # compute value at dem_av
        average_depth_catch = pcr.areaaverage(pcr.max(dem_av - dem_norm, 0), subcatch)
        # pcr.report(average_depth_catch, 'depth_c0.{:03d}'.format(n + 1))
        error = pcr.cover((depth_catch-average_depth_catch)/depth_catch, depth_catch*0)
        # pcr.report(error, 'error000.{:03d}'.format(n + 1))
        dem_min = pcr.ifthenelse(error > 0, dem_av, dem_min)
        dem_max = pcr.ifthenelse(error <= 0, dem_av, dem_max)
    # error_abs = np.abs(error)  # TODO: not needed probably, remove
    inundation = pcr.max(dem_av - dem_norm, 0)
    return inundation
	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)
Пример #28
0
    def getWaterBodyDimensions(self):

        # Lake properties max depth and total lake area
        lakeMaxDepth = ((3.0 * self.waterBodyStorage) /
                        (self.waterBodyShapeFactor**2))**(1. / 3.)
        lakeArea = (lakeMaxDepth * self.waterBodyShapeFactor)**2

        # reservoir properties max depth at outlet and total reservoir area
        reservoirMaxDepth = ((6.0 * self.waterBodyStorage) /
                             (self.waterBodyShapeFactor**2))**(1. / 3.)
        reservoirArea = 0.5 * (reservoirMaxDepth *
                               self.waterBodyShapeFactor)**2

        # dynamic waterbody area, cannot exceed static waterbody extent as defined by input
        self.dynamicArea = pcr.cover(pcr.ifthenelse(pcr.scalar(self.waterBodyTyp) == 1, lakeArea,\
                              pcr.ifthen(pcr.scalar(self.waterBodyTyp) == 2, reservoirArea)), 0.)

        self.dynamicArea = pcr.min(self.dynamicArea, self.waterBodyArea)

        # dynamic water fraction in gridcell
        self.dynamicFracWat = self.dynamicArea * self.waterBodyRelativeFrac / self.cellArea  #TODO check if this is correct

        self.dynamicFracWat = pcr.cover(
            pcr.min(pcr.max(self.dynamicFracWat, 0.), self.fracWat), 0.)
        self.dynamicFracWat = self.fracWat  #TODO remove this line
        self.dynamicFracWat = ifthen(self.landmask, self.dynamicFracWat)


        self.maxWaterDepth  = pcr.cover(pcr.ifthenelse(pcr.scalar(self.waterBodyTyp) == 1, lakeMaxDepth,\
                              pcr.ifthen(pcr.scalar(self.waterBodyTyp) == 2, reservoirMaxDepth)))
Пример #29
0
    def downscaleTemperature(self,
                             currTimeStep,
                             useFactor=False,
                             maxCorrelationCriteria=-0.75,
                             zeroCelciusInKelvin=273.15):

        tmpSlope = 1.000 * vos.netcdf2PCRobjClone(\
                           self.temperLapseRateNC, 'temperature',\
                           currTimeStep.month, useDoy = "Yes",\
                           cloneMapFileName=self.cloneMap,\
                           LatitudeLongitude = True)
        tmpSlope = pcr.min(0., tmpSlope)  # must be negative
        tmpCriteria = vos.netcdf2PCRobjClone(\
                      self.temperatCorrelNC, 'temperature',\
                      currTimeStep.month, useDoy = "Yes",\
                      cloneMapFileName=self.cloneMap,\
                      LatitudeLongitude = True)
        tmpSlope = pcr.ifthenelse(tmpCriteria < maxCorrelationCriteria,\
                   tmpSlope, 0.0)
        tmpSlope = pcr.cover(tmpSlope, 0.0)

        if useFactor == True:
            temperatureInKelvin = self.temperature + zeroCelciusInKelvin
            factor = pcr.max(0.0,
                             temperatureInKelvin + tmpSlope * self.anomalyDEM)
            factor = factor / \
                     pcr.areaaverage(factor, self.meteoDownscaleIds)
            factor = pcr.cover(factor, 1.0)
            self.temperature = factor * temperatureInKelvin - zeroCelciusInKelvin
        else:
            self.temperature = self.temperature + tmpSlope * self.anomalyDEM
Пример #30
0
def getValDivZero(x,y,y_lim=smallNumber,z_def= 0.):
  #-returns the result of a division that possibly involves a zero
  # denominator; in which case, a default value is substituted:
  # x/y= z in case y > y_lim,
  # x/y= z_def in case y <= y_lim, where y_lim -> 0.
  # z_def is set to zero if not otherwise specified
  return pcr.ifthenelse(y > y_lim,x/pcr.max(y_lim,y),z_def)
Пример #31
0
def getValDivZero(x,y,y_lim=smallNumber,z_def= 0.):
  #-returns the result of a division that possibly involves a zero
  # denominator; in which case, a default value is substituted:
  # x/y= z in case y > y_lim,
  # x/y= z_def in case y <= y_lim, where y_lim -> 0.
  # z_def is set to zero if not otherwise specified
  return pcr.ifthenelse(y > y_lim,x/pcr.max(y_lim,y),z_def)
Пример #32
0
    def getICs(self, initial_condition):

        avgInflow = initial_condition['avgLakeReservoirInflowShort']
        avgOutflow = initial_condition['avgLakeReservoirOutflowLong']

        if initial_condition['waterBodyStorage'] is not None:
            # read directly
            waterBodyStorage = initial_condition['waterBodyStorage']
        else:
            # calculate waterBodyStorage at cells where lakes and/or reservoirs are defined
            #
            storageAtLakeAndReservoirs = pcr.cover(\
             pcr.ifthen(pcr.scalar(self.waterBodyIds) > 0., initial_condition['channelStorage']), 0.0)
            #
            # - move only non negative values and use rounddown values
            storageAtLakeAndReservoirs = pcr.max(
                0.00, pcr.rounddown(storageAtLakeAndReservoirs))
            #
            # lake and reservoir storages = waterBodyStorage (m3) ; values are given for the entire lake / reservoir cells
            waterBodyStorage = pcr.ifthen(pcr.scalar(self.waterBodyIds) > 0., \
                                          pcr.areatotal(storageAtLakeAndReservoirs,\
                                                        self.waterBodyIds))

        self.avgInflow = pcr.cover(avgInflow, 0.0)  # unit: m3/s
        self.avgOutflow = pcr.cover(avgOutflow, 0.0)  # unit: m3/s
        self.waterBodyStorage = pcr.cover(waterBodyStorage, 0.0)  # unit: m3

        self.avgInflow = pcr.ifthen(self.landmask, self.avgInflow)
        self.avgOutflow = pcr.ifthen(self.landmask, self.avgOutflow)
        self.waterBodyStorage = pcr.ifthen(self.landmask,
                                           self.waterBodyStorage)
Пример #33
0
 def weirFormula(self, waterHeight, weirWidth):  # output: m3/s
     sillElev = pcr.scalar(0.0)
     weirCoef = pcr.scalar(1.0)
     weirFormula = \
      (1.7*weirCoef*pcr.max(0,waterHeight-sillElev)**1.5) *\
          weirWidth # m3/s
     return (weirFormula)
Пример #34
0
 def weirFormula(self, waterHeight, weirWidth):  # output: m3/s
     sillElev = pcr.scalar(0.0)
     weirCoef = pcr.scalar(1.0)
     weirFormula = (
         1.7 * weirCoef * pcr.max(0, waterHeight - sillElev) ** 1.5
     ) * weirWidth  # m3/s
     return weirFormula
Пример #35
0
def volume_spread(ldd, hand, subcatch, volume, volume_thres=0., cell_surface=1., iterations=15, logging=logging, order=0, neg_HAND=None):
    """
    Estimate 2D flooding from a 1D simulation per subcatchment reach
    Input:
        ldd -- pcraster object direction, local drain directions
        hand -- pcraster object float32, elevation data normalised to nearest drain
        subcatch -- pcraster object ordinal, subcatchments with IDs
        volume -- pcraster object float32, scalar flood volume (i.e. m3 volume outside the river bank within subcatchment)
        volume_thres=0. -- scalar threshold, at least this amount of m3 of volume should be present in a catchment
        area_multiplier=1. -- in case the maps are not in m2, set a multiplier other than 1. to convert
        iterations=15 -- number of iterations to use
        neg_HAND -- if set to 1, HAND maps can have negative values when elevation outside of stream is lower than
        stream (for example when there are natural embankments)
    Output:
        inundation -- pcraster object float32, scalar inundation estimate
    """
    #initial values
    pcr.setglobaloption("unitcell")
    dem_min = pcr.areaminimum(hand, subcatch)  # minimum elevation in subcatchments
    dem_norm = hand - dem_min
    # surface of each subcatchment
    surface = pcr.areaarea(subcatch)*pcr.areaaverage(cell_surface, subcatch) # area_multiplier
    error_abs = pcr.scalar(1e10)  # initial error (very high)
    volume_catch = pcr.areatotal(volume, subcatch)
    depth_catch = volume_catch/surface  # meters water disc averaged over subcatchment
    # ilt(depth_catch, 'depth_catch_{:02d}.map'.format(order))
    # pcr.report(volume, 'volume_{:02d}.map'.format(order))
    if neg_HAND == 1:
        dem_max = pcr.ifthenelse(volume_catch > volume_thres, pcr.scalar(32.),
                             pcr.scalar(-32.))  # bizarre high inundation depth☻
        dem_min = pcr.scalar(-32.)
    else:
        dem_max = pcr.ifthenelse(volume_catch > volume_thres, pcr.scalar(32.),
                             pcr.scalar(0.))  # bizarre high inundation depth☻
        dem_min = pcr.scalar(0.)
    for n in range(iterations):
        logging.debug('Iteration: {:02d}'.format(n + 1))
        #####while np.logical_and(error_abs > error_thres, dem_min < dem_max):
        dem_av = (dem_min + dem_max)/2
        # compute value at dem_av
        average_depth_catch = pcr.areaaverage(pcr.max(dem_av - dem_norm, 0), subcatch)
        error = pcr.cover((depth_catch-average_depth_catch)/depth_catch, depth_catch*0)
        dem_min = pcr.ifthenelse(error > 0, dem_av, dem_min)
        dem_max = pcr.ifthenelse(error <= 0, dem_av, dem_max)
    inundation = pcr.max(dem_av - dem_norm, 0)
    pcr.setglobaloption('unittrue')
    return inundation
 def calculateThicknessOfSaturatedLayer(self):
     # thickness of saturated layer in m water depth (no pores)
     self.saturatedLayerThick = pcr.max(
         self.soilMoistureThick -
         self.fieldCapacityFraction * self.regolithThickness,
         pcr.scalar(0.0))
     # thickness of saturated layer in m (including pores)
     self.saturatedLayerThickness = self.saturatedLayerThick / self.soilPorosityFraction
Пример #37
0
def derive_HAND(dem,
                ldd,
                accuThreshold,
                rivers=None,
                basin=None,
                up_area=None):
    """
    Function derives Height-Above-Nearest-Drain.
    See http://www.sciencedirect.com/science/article/pii/S003442570800120X
    Input:
        dem -- pcraster object float32, elevation data
        ldd -- pcraster object direction, local drain directions
        accuThreshold -- upstream amount of cells as threshold for river
            delineation
        rivers=None -- you can provide a rivers layer here. Pixels that are
                        identified as river should have a value > 0, other
                        pixels a value of zero.
        basin=None -- set a boolean pcraster map where areas with True are estimated using the nearest drain in ldd distance
                        and areas with False by means of the nearest friction distance. Friction distance estimated using the
                        upstream area as weight (i.e. drains with a bigger upstream area have a lower friction)
                        the spreadzone operator is used in this case.
        up_area=None -- provide the upstream area (if not assigned a guesstimate is prepared, assuming the LDD covers a
                        full catchment area)
    Output:
        hand -- pcraster bject float32, height, normalised to nearest stream
        dist -- distance to nearest stream measured in cell lengths
            according to D8 directions
    """
    if rivers is None:
        # prepare stream from a strahler threshold
        stream = pcr.ifthenelse(
            pcr.accuflux(ldd, 1) >= accuThreshold, pcr.boolean(1),
            pcr.boolean(0))
    else:
        # convert stream network to boolean
        stream = pcr.boolean(pcr.cover(rivers, 0))
    # determine height in river (in DEM*100 unit as ordinal)
    height_river = pcr.ifthenelse(stream, pcr.ordinal(dem * 100), 0)
    if basin is None:
        up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river))
    else:
        # use basin to allocate areas outside basin to the nearest stream. Nearest is weighted by upstream area
        if up_area is None:
            up_area = pcr.accuflux(ldd, 1)
        up_area = pcr.ifthen(stream, up_area)  # mask areas outside streams
        friction = 1. / pcr.scalar(
            pcr.spreadzone(pcr.cover(pcr.ordinal(up_area), 0), 0, 0))
        # if basin, use nearest river within subcatchment, if outside basin, use weighted-nearest river
        up_elevation = pcr.ifthenelse(
            basin, pcr.scalar(pcr.subcatchment(ldd, height_river)),
            pcr.scalar(pcr.spreadzone(height_river, 0, friction)))
        # replace areas outside of basin by a spread zone calculation.
    hand = pcr.max(pcr.scalar(pcr.ordinal(dem * 100)) - up_elevation,
                   0) / 100  # convert back to float in DEM units
    # hand = (pcr.scalar(pcr.ordinal(dem*100))-up_elevation)/100  # convert back to float in DEM units
    dist = pcr.ldddist(ldd, stream, 1)  # compute horizontal distance estimate
    return hand, dist
Пример #38
0
def rainfall_interception_gash(Cmax,
                               EoverR,
                               CanopyGapFraction,
                               Precipitation,
                               CanopyStorage,
                               maxevap=9999):
    """
    Interception according to the Gash model (For daily timesteps). 
    """
    # TODO:  add other rainfall interception method (lui)
    # TODO: Include subdaily Gash model
    # TODO: add LAI variation in year
    # Hack for stemflow

    pt = 0.1 * CanopyGapFraction

    P_sat = pcr.max(
        pcr.scalar(0.0),
        pcr.cover(
            (-Cmax / EoverR) * pcr.ln(1.0 - (EoverR /
                                             (1.0 - CanopyGapFraction - pt))),
            pcr.scalar(0.0),
        ),
    )

    # large storms P > P_sat
    largestorms = Precipitation > P_sat

    Iwet = pcr.ifthenelse(
        largestorms,
        ((1 - CanopyGapFraction - pt) * P_sat) - Cmax,
        Precipitation * (1 - CanopyGapFraction - pt),
    )
    Isat = pcr.ifthenelse(largestorms, (EoverR) * (Precipitation - P_sat), 0.0)
    Idry = pcr.ifthenelse(largestorms, Cmax, 0.0)
    Itrunc = 0

    StemFlow = pt * Precipitation

    ThroughFall = Precipitation - Iwet - Idry - Isat - Itrunc - StemFlow
    Interception = Iwet + Idry + Isat + Itrunc

    # Non corect for area without any Interception (say open water Cmax -- zero)
    CmaxZero = Cmax <= 0.0
    ThroughFall = pcr.ifthenelse(CmaxZero, Precipitation, ThroughFall)
    Interception = pcr.ifthenelse(CmaxZero, pcr.scalar(0.0), Interception)
    StemFlow = pcr.ifthenelse(CmaxZero, pcr.scalar(0.0), StemFlow)

    # Now corect for maximum potential evap
    OverEstimate = pcr.ifthenelse(Interception > maxevap,
                                  Interception - maxevap, pcr.scalar(0.0))
    Interception = pcr.min(Interception, maxevap)
    # Add surpluss to the thoughdfall
    ThroughFall = ThroughFall + OverEstimate

    return ThroughFall, Interception, StemFlow, CanopyStorage
Пример #39
0
    def get_satDegUpp000005_from_observation(self):

        # assumption for observation values
        # - this should be replaced by values from the ECV soil moisture value (sattelite data)
        # - uncertainty should be included here
        # - note that the value should be between 0.0 and 1.0
        observed_satDegUpp000005 = pcr.min(1.0,\
                                   pcr.max(0.0,\
                                   pcr.normal(pcr.boolean(1)) + 1.0))
        return observed_satDegUpp000005                           
Пример #40
0
def rainfall_interception_modrut(
    Precipitation, PotEvap, CanopyStorage, CanopyGapFraction, Cmax
):
    """
    Interception according to a modified Rutter model. The model is solved
    explicitly and there is no drainage below Cmax.
    
    Returns:
        - NetInterception: P - TF - SF (may be different from the actual wet canopy evaporation)
        - ThroughFall:
        - StemFlow:
        - LeftOver: Amount of potential eveporation not used
        - Interception: Actual wet canopy evaporation in this thimestep
        - CanopyStorage: Canopy storage at the end of the timestep
    
    """

    ##########################################################################
    # Interception according to a modified Rutter model with hourly timesteps#
    ##########################################################################

    p = CanopyGapFraction
    pt = 0.1 * p

    # Amount of P that falls on the canopy
    Pfrac = pcr.max((1 - p - pt), 0) * Precipitation

    # S cannot be larger than Cmax, no gravity drainage below that
    DD = pcr.ifthenelse(CanopyStorage > Cmax, CanopyStorage - Cmax, 0.0)
    CanopyStorage = CanopyStorage - DD

    # Add the precipitation that falls on the canopy to the store
    CanopyStorage = CanopyStorage + Pfrac

    # Now do the Evap, make sure the store does not get negative
    dC = -1 * pcr.min(CanopyStorage, PotEvap)
    CanopyStorage = CanopyStorage + dC

    LeftOver = PotEvap + dC
    # Amount of evap not used

    # Now drain the canopy storage again if needed...
    D = pcr.ifthenelse(CanopyStorage > Cmax, CanopyStorage - Cmax, 0.0)
    CanopyStorage = CanopyStorage - D

    # Calculate throughfall
    ThroughFall = DD + D + p * Precipitation
    StemFlow = Precipitation * pt

    # Calculate interception, this is NET Interception
    NetInterception = Precipitation - ThroughFall - StemFlow
    Interception = -dC

    return NetInterception, ThroughFall, StemFlow, LeftOver, Interception, CanopyStorage
	def kinAlphaDynamic(self,watStor):
		#-given the total water storage in the cell, returns the Q-A relationship
		# for the kinematic wave and required parameters
		floodVol= pcr.max(0,watStor-self.channelStorageCapacity)
		floodFrac, floodZ= self.returnFloodedFraction(floodVol)
		#-wetted perimeter, cross-sectional area and
		# corresponding mannings' n
		wetA= watStor/self.channelLength
		#-wetted perimeter, alpha and composite manning's n
		wetPFld= pcr.max(0.,floodFrac*self.cellArea/self.channelLength-\
			self.channelWidth)+2.*floodZ
		wetPCh= self.channelWidth+\
			2.*pcr.min(self.channelDepth,watStor/self.channelArea)
		wetP= wetPFld+wetPCh
		manQ= (wetPCh/wetP*self.channelManN**1.5+\
			wetPFld/wetP*self.floodplainManN**1.5)**(2./3.)
		alphaQ= (manQ*wetP**(2./3.)*self.channelGradient**-0.5)**self.betaQ
		#-returning variables of interest: flooded fraction, cross-sectional area
		# and alphaQ
		return floodFrac,floodZ,wetA,alphaQ
Пример #42
0
def rainfall_interception_gash(
    Cmax, EoverR, CanopyGapFraction, Precipitation, CanopyStorage, maxevap=9999
):
    """
    Interception according to the Gash model (For daily timesteps). 
    """
    # TODO:  add other rainfall interception method (lui)
    # TODO: Include subdaily Gash model
    # TODO: add LAI variation in year
    # Hack for stemflow

    pt = 0.1 * CanopyGapFraction

    P_sat = pcr.max(
        pcr.scalar(0.0),
        pcr.cover(
            (-Cmax / EoverR) * pcr.ln(1.0 - (EoverR / (1.0 - CanopyGapFraction - pt))),
            pcr.scalar(0.0),
        ),
    )

    # large storms P > P_sat
    largestorms = Precipitation > P_sat

    Iwet = pcr.ifthenelse(
        largestorms,
        ((1 - CanopyGapFraction - pt) * P_sat) - Cmax,
        Precipitation * (1 - CanopyGapFraction - pt),
    )
    Isat = pcr.ifthenelse(largestorms, (EoverR) * (Precipitation - P_sat), 0.0)
    Idry = pcr.ifthenelse(largestorms, Cmax, 0.0)
    Itrunc = 0

    StemFlow = pt * Precipitation

    ThroughFall = Precipitation - Iwet - Idry - Isat - Itrunc - StemFlow
    Interception = Iwet + Idry + Isat + Itrunc

    # Non corect for area without any Interception (say open water Cmax -- zero)
    CmaxZero = Cmax <= 0.0
    ThroughFall = pcr.ifthenelse(CmaxZero, Precipitation, ThroughFall)
    Interception = pcr.ifthenelse(CmaxZero, pcr.scalar(0.0), Interception)
    StemFlow = pcr.ifthenelse(CmaxZero, pcr.scalar(0.0), StemFlow)

    # Now corect for maximum potential evap
    OverEstimate = pcr.ifthenelse(
        Interception > maxevap, Interception - maxevap, pcr.scalar(0.0)
    )
    Interception = pcr.min(Interception, maxevap)
    # Add surpluss to the thoughdfall
    ThroughFall = ThroughFall + OverEstimate

    return ThroughFall, Interception, StemFlow, CanopyStorage
Пример #43
0
    def moveFromChannelToWaterBody(
        self,
        newStorageAtLakeAndReservoirs,
        timestepsToAvgDischarge,
        maxTimestepsToAvgDischargeShort,
        length_of_time_step=vos.secondsPerDay(),
    ):

        # new lake and/or reservoir storages (m3)
        newStorageAtLakeAndReservoirs = pcr.cover(
            pcr.areatotal(newStorageAtLakeAndReservoirs, self.waterBodyIds), 0.0
        )

        # incoming volume (m3)
        self.inflow = newStorageAtLakeAndReservoirs - self.waterBodyStorage

        # inflowInM3PerSec (m3/s)
        inflowInM3PerSec = self.inflow / length_of_time_step

        # updating (short term) average inflow (m3/s) ;
        # - needed to constrain lake outflow:
        #
        temp = pcr.max(
            1.0,
            pcr.min(
                maxTimestepsToAvgDischargeShort,
                self.timestepsToAvgDischarge
                - 1.0
                + length_of_time_step / vos.secondsPerDay(),
            ),
        )
        deltaInflow = inflowInM3PerSec - self.avgInflow
        R = deltaInflow * (length_of_time_step / vos.secondsPerDay()) / temp
        self.avgInflow = self.avgInflow + R
        self.avgInflow = pcr.max(0.0, self.avgInflow)
        #
        # for the reference, see the "weighted incremental algorithm" in http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance

        # updating waterBodyStorage (m3)
        self.waterBodyStorage = newStorageAtLakeAndReservoirs
Пример #44
0
def derive_HAND(dem, ldd, accuThreshold, rivers=None, basin=None, up_area=None, neg_HAND=None):
    """
    Function derives Height-Above-Nearest-Drain.
    See http://www.sciencedirect.com/science/article/pii/S003442570800120X
    Input:
        dem -- pcraster object float32, elevation data
        ldd -- pcraster object direction, local drain directions
        accuThreshold -- upstream amount of cells as threshold for river
            delineation
        rivers=None -- you can provide a rivers layer here. Pixels that are
                        identified as river should have a value > 0, other
                        pixels a value of zero.
        basin=None -- set a boolean pcraster map where areas with True are estimated using the nearest drain in ldd distance
                        and areas with False by means of the nearest friction distance. Friction distance estimated using the
                        upstream area as weight (i.e. drains with a bigger upstream area have a lower friction)
                        the spreadzone operator is used in this case.
        up_area=None -- provide the upstream area (if not assigned a guesstimate is prepared, assuming the LDD covers a
                        full catchment area)
        neg_HAND=None -- if set to 1, HAND maps can have negative values when elevation outside of stream is lower than
                        stream (for example when there are natural embankments)
    Output:
        hand -- pcraster bject float32, height, normalised to nearest stream
        dist -- distance to nearest stream measured in cell lengths
            according to D8 directions
    """
    if rivers is None:
        # prepare stream from a strahler threshold
        stream = pcr.ifthenelse(pcr.accuflux(ldd, 1) >= accuThreshold,
                                pcr.boolean(1), pcr.boolean(0))
    else:
        # convert stream network to boolean
        stream = pcr.boolean(pcr.cover(rivers, 0))
    # determine height in river (in DEM*100 unit as ordinal)
    height_river = pcr.ifthenelse(stream, pcr.ordinal(dem*100), 0)
    if basin is None:
        up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river))
    else:
        # use basin to allocate areas outside basin to the nearest stream. Nearest is weighted by upstream area
        if up_area is None:
            up_area = pcr.accuflux(ldd, 1)
        up_area = pcr.ifthen(stream, up_area)  # mask areas outside streams
        friction = 1./pcr.scalar(pcr.spreadzone(pcr.cover(pcr.ordinal(up_area), 0), 0, 0))
        # if basin, use nearest river within subcatchment, if outside basin, use weighted-nearest river
        up_elevation = pcr.ifthenelse(basin, pcr.scalar(pcr.subcatchment(ldd, height_river)), pcr.scalar(pcr.spreadzone(height_river, 0, friction)))
        # replace areas outside of basin by a spread zone calculation.
    # make negative HANDS also possible
    if neg_HAND == 1:
        hand = (pcr.scalar(pcr.ordinal(dem*100))-up_elevation)/100  # convert back to float in DEM units
    else:
        hand = pcr.max(pcr.scalar(pcr.ordinal(dem*100))-up_elevation, 0)/100  # convert back to float in DEM units
    dist = pcr.ldddist(ldd, stream, 1)  # compute horizontal distance estimate
    return hand, dist
def inverse_gumbel(p_zero, loc, scale, return_period):
    """
    This function computes values for a given return period using the zero probability, location and shape
    parameters given. 
    """

    p = pcr.scalar(1. - 1./return_period)
    
    # p_residual is the probability density function of the population consisting of any values above zero
    p_residual = pcr.min(pcr.max((p - p_zero) / (1.0 - p_zero), 0.0), 1.0) 

    #~ # - alternative equation found on:  https://repos.deltares.nl/repos/Hydrology/trunk/GLOFRIS/src/rp_bias_corr.py (see the method inv_gumbel)
    #~ p_residual = np.minimum(np.maximum((p-p_zero)/(1-p_zero), 0), np.float64(1-1./1e9))  # I think this is the correct equation"""
    
    reduced_variate = -pcr.ln(-pcr.ln(p_residual))

    flvol = reduced_variate * scale + loc

    # infinite numbers can occur. reduce these to zero!
    # if any values become negative due to the statistical extrapolation, fix them to zero (may occur if the sample size for fitting was small and a small return period is requested)
    flvol = pcr.max(0.0, pcr.cover(flvol, 0.0))

    return flvol
Пример #46
0
def upscale_riverlength(ldd, order, factor):
    """
    Upscales the riverlength using 'factor'
    The resulting maps can be resampled (e.g. using resample.exe) by factor and should
    include the accurate length as determined with the original higher
    resolution maps.  This function is **depricated**,
    use are_riverlength instead as this version
    is very slow for large maps

    Input:
        - ldd
        - minimum streamorder to include

    Output:
        - distance per factor cells
    """

    strorder = pcr.streamorder(ldd)
    strorder = pcr.ifthen(strorder >= order, strorder)
    dist = pcr.cover(
        pcr.max(
            pcr.celllength(), pcr.ifthen(pcr.boolean(strorder), pcr.downstreamdist(ldd))
        ),
        0,
    )
    totdist = pcr.max(
        pcr.ifthen(
            pcr.boolean(strorder),
            pcr.windowtotal(
                pcr.ifthen(pcr.boolean(strorder), dist), pcr.celllength() * factor
            ),
        ),
        dist,
    )

    return totdist
Пример #47
0
def derive_HAND(dem, ldd, accuThreshold, rivers=None, basin=None):
    """
    Function derives Height-Above-Nearest-Drain.
    See http://www.sciencedirect.com/science/article/pii/S003442570800120X
    Input:
        dem -- pcraster object float32, elevation data
        ldd -- pcraster object direction, local drain directions
        accuThreshold -- upstream amount of cells as threshold for river
            delineation
        rivers=None -- you can provide a rivers layer here. Pixels that are
                        identified as river should have a value > 0, other
                        pixels a value of zero.
        basin=None -- set a boolean pcraster map where areas with True are estimated using the nearest drain in ldd distance
                        and areas with False by means of the nearest friction distance. Friction distance estimated using the
                        upstream area as weight (i.e. drains with a bigger upstream area have a lower friction)
                        the spreadzone operator is used in this case.
    Output:
        hand -- pcraster bject float32, height, normalised to nearest stream
        dist -- distance to nearest stream measured in cell lengths
            according to D8 directions
    """
    if rivers is None:
        stream = pcr.ifthenelse(
            pcr.accuflux(ldd, 1) >= accuThreshold, pcr.boolean(1), pcr.boolean(0)
        )
    else:
        stream = pcr.boolean(pcr.cover(rivers, 0))

    height_river = pcr.ifthenelse(stream, pcr.ordinal(dem * 100), 0)
    if basin is None:
        up_elevation = pcr.scalar(pcr.subcatchment(ldd, height_river))
    else:
        drainage_surf = pcr.ifthen(rivers, pcr.accuflux(ldd, 1))
        weight = 1.0 / pcr.scalar(
            pcr.spreadzone(pcr.cover(pcr.ordinal(drainage_surf), 0), 0, 0)
        )
        up_elevation = pcr.ifthenelse(
            basin,
            pcr.scalar(pcr.subcatchment(ldd, height_river)),
            pcr.scalar(pcr.spreadzone(height_river, 0, weight)),
        )
        # replace areas outside of basin by a spread zone calculation.
    hand = pcr.max(pcr.scalar(pcr.ordinal(dem * 100)) - up_elevation, 0) / 100
    dist = pcr.ldddist(ldd, stream, 1)

    return hand, dist
Пример #48
0
def agriZone_Jarvis(self, k):
    """
    - Potential evaporation is decreased by energy used for interception evaporation    
    - Formula for evaporation based on Jarvis stress functions
    - Outgoing fluxes are determined based on (value in previous timestep + inflow) 
    and if this leads to negative storage, the outgoing fluxes are corrected to rato --> Eu is 
    no longer taken into account for this correction
    - Qa u is determined from overflow from Sa
    - Code for ini-file: 1
    """
    self.Qa = pcr.max(self.Pe - (self.samax[k] - self.Sa_t[k]), 0)
    self.Sa[k] = self.Sa_t[k] + (self.Pe - self.Qa)
    self.SaN = pcr.min(self.Sa[k] / self.samax2, 1)
    self.SuN = self.Su[k] / self.sumax[k]

    JarvisCoefficients.calcEu(
        self, k, 1
    )  # calculation of Ea based on Jarvis stress functions
    self.Ea1 = self.Eu

    self.Fa1 = self.Fmin[k] + (self.Fmax[k] - self.Fmin[k]) * e ** (
        -self.decF[k] * self.SuN
    )
    self.Sa[k] = self.Sa_t[k] + (self.Pe - self.Qa) - self.Fa1 - self.Ea1

    self.Sa_diff = pcr.ifthenelse(self.Sa[k] < 0, self.Sa[k], 0)
    self.Fa = (
        self.Fa1
        + (self.Fa1 / pcr.ifthenelse(self.Fa1 + self.Ea1 > 0, self.Fa1 + self.Ea1, 1))
        * self.Sa_diff
    )
    self.Ea = (
        self.Ea1
        + (self.Ea1 / pcr.ifthenelse(self.Fa1 + self.Ea1 > 0, self.Fa1 + self.Ea1, 1))
        * self.Sa_diff
    )
    self.Sa[k] = self.Sa_t[k] + (self.Pe - self.Qa) - self.Ea - self.Fa
    self.Sa[k] = pcr.ifthenelse(self.Sa[k] < 0, 0, self.Sa[k])
    self.Sa_diff2 = pcr.ifthen(self.Sa[k] < 0, self.Sa[k])

    self.wbSa_[k] = self.Pe - self.Ea - self.Qa - self.Fa - self.Sa[k] + self.Sa_t[k]

    self.Ea_[k] = self.Ea
    self.Qa_[k] = self.Qa
    self.Fa_[k] = self.Fa
Пример #49
0
def riverlength(ldd, order):
    """
    Determines the length of a river using the ldd.
    only determined for order and higher.

    Input:
        - ldd, order (streamorder)

    Returns:
        - totallength,lengthpercell, streamorder
    """
    strorder = pcr.streamorder(ldd)
    strorder = pcr.ifthen(strorder >= pcr.ordinal(order), strorder)
    dist = pcr.max(
        pcr.celllength(), pcr.ifthen(pcr.boolean(strorder), pcr.downstreamdist(ldd))
    )

    return pcr.catchmenttotal(pcr.cover(dist, 0), ldd), dist, strorder
Пример #50
0
def agriZone_no_reservoir(self, k):
    """
    This function is used when no unsaturated zone reservoir is used and only
    passes fluxes from the upper reservoirs to the lower
    self.Qa_[k] = 0.
    self.Ea_[k] = 0.
    self.Sa[k] = 0.
    self.Fa_[k] = Pe
    Storage in unsaturated zone = 0.
    """
    self.Qa_[k] = 0.0
    self.Ea_[k] = 0.0
    self.Sa[k] = 0.0
    self.Fa_[k] = pcr.max(self.Pe_[k], 0)
    self.wbSa_[k] = (
        self.Pe_[k]
        - self.Ea_[k]
        - self.Qa_[k]
        - self.Fa_[k]
        - self.Sa[k]
        + self.Sa_t[k]
    )
Пример #51
0
    def getICs(self, initial_condition):

        avgInflow = initial_condition["avgLakeReservoirInflowShort"]
        avgOutflow = initial_condition["avgLakeReservoirOutflowLong"]
        #
        if not isinstance(initial_condition["waterBodyStorage"], type(None)):
            # read directly
            waterBodyStorage = initial_condition["waterBodyStorage"]
        else:
            # calculate waterBodyStorage at cells where lakes and/or reservoirs are defined
            #
            storageAtLakeAndReservoirs = pcr.cover(
                pcr.ifthen(
                    pcr.scalar(self.waterBodyIds) > 0.0,
                    initial_condition["channelStorage"],
                ),
                0.0,
            )
            #
            # - move only non negative values and use rounddown values
            storageAtLakeAndReservoirs = pcr.max(
                0.00, pcr.rounddown(storageAtLakeAndReservoirs)
            )
            #
            # lake and reservoir storages = waterBodyStorage (m3) ; values are given for the entire lake / reservoir cells
            waterBodyStorage = pcr.ifthen(
                pcr.scalar(self.waterBodyIds) > 0.0,
                pcr.areatotal(storageAtLakeAndReservoirs, self.waterBodyIds),
            )

        self.avgInflow = pcr.cover(avgInflow, 0.0)  # unit: m3/s
        self.avgOutflow = pcr.cover(avgOutflow, 0.0)  # unit: m3/s
        self.waterBodyStorage = pcr.cover(waterBodyStorage, 0.0)  # unit: m3

        self.avgInflow = pcr.ifthen(self.landmask, self.avgInflow)
        self.avgOutflow = pcr.ifthen(self.landmask, self.avgOutflow)
        self.waterBodyStorage = pcr.ifthen(self.landmask, self.waterBodyStorage)
Пример #52
0
def agriZone_Ep_Sa_beta_frostSamax_surfTemp(self, k):
    """
    - Potential evaporation is decreased by energy used for interception evaporation    
    - Formula for evaporation based on LP
    - Outgoing fluxes are determined based on (value in previous timestep + inflow) 
    and if this leads to negative storage, the outgoing fluxes are corrected to rato --> Eu is 
    no longer taken into account for this correction
    - Qa u is determined from overflow from Sa --> incorporation of beta function
    - Fa is based on storage in Sa
    - Fa is decreased in case of frozen soil
    - Code for ini-file: 13
    """

    JarvisCoefficients.calcEp(self, k)
    self.PotEvaporation = self.EpHour

    self.FrDur[k] = pcr.min(
        self.FrDur[k]
        + pcr.ifthenelse(
            self.TempSurf > 0, self.ratFT[k] * self.TempSurf, self.TempSurf
        )
        * self.dayDeg[k],
        0,
    )
    self.Ft = pcr.min(
        pcr.max(
            self.FrDur[k] / (self.FrDur1[k] - self.FrDur0[k])
            - self.FrDur0[k] / (self.FrDur1[k] - self.FrDur0[k]),
            self.samin[k],
        ),
        1,
    )

    self.samax2 = self.samax[k] * pcr.scalar(self.catchArea) * self.Ft
    self.Qaadd = pcr.max(self.Sa_t[k] + self.Pe - self.samax2, 0)

    self.Sa[k] = self.Sa_t[k] + (self.Pe - self.Qaadd)
    self.SaN = pcr.min(self.Sa[k] / self.samax2, 1)
    self.SuN = self.Su[k] / self.sumax[k]

    self.Ea1 = pcr.max((self.PotEvaporation - self.Ei), 0) * pcr.min(
        self.Sa[k] / (self.samax2 * self.LP[k]), 1
    )
    self.Qa1 = (self.Pe - self.Qaadd) * (1 - (1 - self.SaN) ** self.beta[k])

    self.Fa1 = pcr.ifthenelse(
        self.SaN > 0,
        self.Fmin[k]
        + (self.Fmax[k] - self.Fmin[k]) * e ** (-self.decF[k] * (1 - self.SaN)),
        0,
    )

    self.Sa[k] = self.Sa_t[k] + (self.Pe - self.Qaadd) - self.Qa1 - self.Fa1 - self.Ea1

    self.Sa_diff = pcr.ifthenelse(self.Sa[k] < 0, self.Sa[k], 0)
    self.Qa = (
        self.Qa1
        + (
            self.Qa1
            / pcr.ifthenelse(
                self.Fa1 + self.Ea1 + self.Qa1 > 0, self.Fa1 + self.Ea1 + self.Qa1, 1
            )
        )
        * self.Sa_diff
    )
    self.Fa = (
        self.Fa1
        + (
            self.Fa1
            / pcr.ifthenelse(
                self.Fa1 + self.Ea1 + self.Qa1 > 0, self.Fa1 + self.Ea1 + self.Qa1, 1
            )
        )
        * self.Sa_diff
    )
    self.Ea = (
        self.Ea1
        + (
            self.Ea1
            / pcr.ifthenelse(
                self.Fa1 + self.Ea1 + self.Qa1 > 0, self.Fa1 + self.Ea1 + self.Qa1, 1
            )
        )
        * self.Sa_diff
    )
    self.Sa[k] = self.Sa_t[k] + (self.Pe - self.Qaadd) - self.Ea - self.Fa - self.Qa
    self.Sa[k] = pcr.ifthenelse(self.Sa[k] < 0, 0, self.Sa[k])
    self.Sa_diff2 = pcr.ifthen(self.Sa[k] < 0, self.Sa[k])

    self.wbSa_[k] = (
        self.Pe - self.Ea - self.Qa - self.Qaadd - self.Fa - self.Sa[k] + self.Sa_t[k]
    )

    self.Ea_[k] = self.Ea
    self.Qa_[k] = self.Qa + self.Qaadd
    self.Fa_[k] = self.Fa
    self.Ft_[k] = self.Ft
Пример #53
0
    def readTopo(self, iniItems, optionDict):

        # a dictionary/section of options that will be used
        if optionDict == None:
            optionDict = iniItems._sections["landSurfaceOptions"]

        # maps of elevation attributes:
        topoParams = ["tanslope", "slopeLength", "orographyBeta"]
        if optionDict["topographyNC"] == str(None):
            for var in topoParams:
                input = configget(iniItems, "landSurfaceOptions", str(var), "None")
                vars(self)[var] = vos.readPCRmapClone(
                    input, self.cloneMap, self.tmpDir, self.inputDir
                )
                if var != "slopeLength":
                    vars(self)[var] = pcr.cover(vars(self)[var], 0.0)
        else:
            topoPropertiesNC = vos.getFullPath(
                optionDict["topographyNC"], self.inputDir
            )

            for var in topoParams:
                vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(
                    topoPropertiesNC, var, cloneMapFileName=self.cloneMap
                )
                if var != "slopeLength":
                    vars(self)[var] = pcr.cover(vars(self)[var], 0.0)

        # ~ self.tanslope = pcr.max(self.tanslope, 0.00001)              # In principle, tanslope can be zero. Zero tanslope will provide zero TCL (no interflow)

        # covering slopeLength with its maximum value
        self.slopeLength = pcr.cover(self.slopeLength, pcr.mapmaximum(self.slopeLength))

        # maps of relative elevation above flood plains
        dzRel = [
            "dzRel0001",
            "dzRel0005",
            "dzRel0010",
            "dzRel0020",
            "dzRel0030",
            "dzRel0040",
            "dzRel0050",
            "dzRel0060",
            "dzRel0070",
            "dzRel0080",
            "dzRel0090",
            "dzRel0100",
        ]
        if optionDict["topographyNC"] == str(None):
            for i in range(0, len(dzRel)):
                var = dzRel[i]
                input = optionDict[str(var)]
                vars(self)[var] = vos.readPCRmapClone(
                    input, self.cloneMap, self.tmpDir, self.inputDir
                )
                vars(self)[var] = pcr.cover(vars(self)[var], 0.0)
                if i > 0:
                    vars(self)[var] = pcr.max(vars(self)[var], vars(self)[dzRel[i - 1]])
        else:
            for i in range(0, len(dzRel)):
                var = dzRel[i]
                vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(
                    topoPropertiesNC, var, cloneMapFileName=self.cloneMap
                )
                vars(self)[var] = pcr.cover(vars(self)[var], 0.0)
                if i > 0:
                    vars(self)[var] = pcr.max(vars(self)[var], vars(self)[dzRel[i - 1]])
                                       pcr.windowaverage(fraction_reserved_recharge, 0.5))
fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \
                                       pcr.windowaverage(fraction_reserved_recharge, 0.5))
fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \
                                       pcr.windowaverage(fraction_reserved_recharge, 0.5))
fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \
                                       pcr.windowaverage(fraction_reserved_recharge, 0.5))
fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \
                                       pcr.windowaverage(fraction_reserved_recharge, 0.5))
fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \
                                       pcr.windowaverage(fraction_reserved_recharge, 0.5))
fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \
                                       pcr.windowaverage(fraction_reserved_recharge, 0.5))
fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, 0.1)
# - set minimum value to 0.10
fraction_reserved_recharge = pcr.max(0.10, fraction_reserved_recharge)
# - set maximum value to 0.75
fraction_reserved_recharge = pcr.min(0.75, fraction_reserved_recharge)

# areal_groundwater_abstraction (unit: m/year)
#~ groundwater_abstraction = pcr.cover(pcr.readmap("/nfsarchive/edwin-emergency-backup-DO-NOT-DELETE/rapid/edwin/05min_runs_results/2015_04_27/non_natural_2015_04_27/global/analysis/avg_values_1990_to_2010/totalGroundwaterAbstraction_annuaTot_output_1990to2010.map"), 0.0)
groundwater_abstraction = pcr.scalar(0.0)
for year in range(start_year, end_year + 1, 1):
    date_input_in_string = str(year) + "-12-31"
    netcdf_file   = "/nfsarchive/edwin-emergency-backup-DO-NOT-DELETE/rapid/edwin/05min_runs_results/2015_04_27/non_natural_2015_04_27/global/netcdf/totalGroundwaterAbstraction_annuaTot_output_1981to2010.nc"
    variable_name = "total_groundwater_abstraction"
    groundwater_abstraction += vos.netcdf2PCRobjClone(ncFile = netcdf_file, varName = variable_name, dateInput = date_input_in_string,\
                                                      useDoy = None,
                                                      cloneMapFileName  = None,\
                                                      LatitudeLongitude = True,\
                                                      specificFillValue = None)
Пример #55
0
def main():
    ### Read input arguments #####
    parser = OptionParser()
    usage = "usage: %prog [options]"
    parser = OptionParser(usage=usage)
    parser.add_option('-q', '--quiet',
                      dest='verbose', default=True, action='store_false',
                      help='do not print status messages to stdout')
    parser.add_option('-i', '--ini', dest='inifile',
                      default='hand_contour_inun.ini', nargs=1,
                      help='ini configuration file')
    parser.add_option('-f', '--flood_map',
                      nargs=1, dest='flood_map',
                      help='Flood map file (NetCDF point time series file')
    parser.add_option('-v', '--flood_variable',
                      nargs=1, dest='flood_variable',
                      default='water_level',
                      help='variable name of flood water level')
    parser.add_option('-b', '--bankfull_map',
                      dest='bankfull_map', default='',
                      help='Map containing bank full level (is subtracted from flood map, in NetCDF)')
    parser.add_option('-c', '--catchment',
                      dest='catchment_strahler', default=7, type='int',
                      help='Strahler order threshold >= are selected as catchment boundaries')
    parser.add_option('-t', '--time',
                      dest='time', default='',
                      help='time in YYYYMMDDHHMMSS, overrides time in NetCDF input if set')
    # parser.add_option('-s', '--hand_strahler',
    #                   dest='hand_strahler', default=7, type='int',
    #                   help='Strahler order threshold >= selected as riverine')
    parser.add_option('-m', '--max_strahler',
                      dest = 'max_strahler', default=1000, type='int',
                      help='Maximum Strahler order to loop over')
    parser.add_option('-d', '--destination',
                      dest='dest_path', default='inun',
                      help='Destination path')
    parser.add_option('-H', '--hand_file_prefix',
                      dest='hand_file_prefix', default='',
                      help='optional HAND file prefix of already generated HAND files')
    parser.add_option('-n', '--neg_HAND',
                      dest='neg_HAND', default=0, type='int',
                      help='if set to 1, allow for negative HAND values in HAND maps')
    (options, args) = parser.parse_args()

    if not os.path.exists(options.inifile):
        print 'path to ini file cannot be found'
        sys.exit(1)
    options.dest_path = os.path.abspath(options.dest_path)

    if not(os.path.isdir(options.dest_path)):
        os.makedirs(options.dest_path)

    # set up the logger
    flood_name = os.path.split(options.flood_map)[1].split('.')[0]
    # case_name = 'inun_{:s}_hand_{:02d}_catch_{:02d}'.format(flood_name, options.hand_strahler, options.catchment_strahler)
    case_name = 'inun_{:s}_catch_{:02d}'.format(flood_name, options.catchment_strahler)
    logfilename = os.path.join(options.dest_path, 'hand_contour_inun.log')
    logger, ch = inun_lib.setlogger(logfilename, 'HAND_INUN', options.verbose)
    logger.info('$Id: $')
    logger.info('Flood map: {:s}'.format(options.flood_map))
    logger.info('Bank full map: {:s}'.format(options.bankfull_map))
    logger.info('Destination path: {:s}'.format(options.dest_path))
    # read out ini file
    ### READ CONFIG FILE
    # open config-file
    config = inun_lib.open_conf(options.inifile)
    
    # read settings
    options.dem_file = inun_lib.configget(config, 'HighResMaps',
                                  'dem_file',
                                  True)
    options.ldd_file = inun_lib.configget(config, 'HighResMaps',
                                'ldd_file',
                                 True)
    options.stream_file = inun_lib.configget(config, 'HighResMaps',
                                'stream_file',
                                 True)
    options.riv_length_fact_file = inun_lib.configget(config, 'wflowResMaps',
                                'riv_length_fact_file',
                                 True)
    options.ldd_wflow = inun_lib.configget(config, 'wflowResMaps',
                                'ldd_wflow',
                                True)
    options.riv_width_file = inun_lib.configget(config, 'wflowResMaps',
                                'riv_width_file',
                                 True)
    options.file_format = inun_lib.configget(config, 'file_settings',
                                'file_format', 0, datatype='int')
    options.out_format = inun_lib.configget(config, 'file_settings',
                                'out_format', 0, datatype='int')
    options.latlon = inun_lib.configget(config, 'file_settings',
                                 'latlon', 0, datatype='int')
    options.x_tile = inun_lib.configget(config, 'tiling',
                                  'x_tile', 10000, datatype='int')
    options.y_tile = inun_lib.configget(config, 'tiling',
                                  'y_tile', 10000, datatype='int')
    options.x_overlap = inun_lib.configget(config, 'tiling',
                                  'x_overlap', 1000, datatype='int')
    options.y_overlap = inun_lib.configget(config, 'tiling',
                                  'y_overlap', 1000, datatype='int')
    options.iterations = inun_lib.configget(config, 'inundation',
                                  'iterations', 20, datatype='int')
    options.initial_level = inun_lib.configget(config, 'inundation',
                                  'initial_level', 32., datatype='float')
    options.flood_volume_type = inun_lib.configget(config, 'inundation',
                                  'flood_volume_type', 0, datatype='int')

    # options.area_multiplier = inun_lib.configget(config, 'inundation',
    #                               'area_multiplier', 1., datatype='float')
    logger.info('DEM file: {:s}'.format(options.dem_file))
    logger.info('LDD file: {:s}'.format(options.ldd_file))
    logger.info('Columns per tile: {:d}'.format(options.x_tile))
    logger.info('Rows per tile: {:d}'.format(options.y_tile))
    logger.info('Columns overlap: {:d}'.format(options.x_overlap))
    logger.info('Rows overlap: {:d}'.format(options.y_overlap))
    metadata_global = {}
    # add metadata from the section [metadata]
    meta_keys = config.options('metadata_global')
    for key in meta_keys:
        metadata_global[key] = config.get('metadata_global', key)
    # add a number of metadata variables that are mandatory
    metadata_global['config_file'] = os.path.abspath(options.inifile)
    metadata_var = {}
    metadata_var['units'] = 'm'
    metadata_var['standard_name'] = 'water_surface_height_above_reference_datum'
    metadata_var['long_name'] = 'flooding'
    metadata_var['comment'] = 'water_surface_reference_datum_altitude is given in file {:s}'.format(options.dem_file)
    if not os.path.exists(options.dem_file):
        logger.error('path to dem file {:s} cannot be found'.format(options.dem_file))
        sys.exit(1)
    if not os.path.exists(options.ldd_file):
        logger.error('path to ldd file {:s} cannot be found'.format(options.ldd_file))
        sys.exit(1)

    # Read extent from a GDAL compatible file
    try:
        extent = inun_lib.get_gdal_extent(options.dem_file)
    except:
        msg = 'Input file {:s} not a gdal compatible file'.format(options.dem_file)
        inun_lib.close_with_error(logger, ch, msg)
        sys.exit(1)

    try:
        x, y = inun_lib.get_gdal_axes(options.dem_file, logging=logger)
        srs = inun_lib.get_gdal_projection(options.dem_file, logging=logger)
    except:
        msg = 'Input file {:s} not a gdal compatible file'.format(options.dem_file)
        inun_lib.close_with_error(logger, ch, msg)
        sys.exit(1)

    # read history from flood file
    if options.file_format == 0:
        a = nc.Dataset(options.flood_map, 'r')
        metadata_global['history'] = 'Created by: $Id: $, boundary conditions from {:s},\nhistory: {:s}'.format(os.path.abspath(options.flood_map), a.history)
        a.close()
    else:
        metadata_global['history'] = 'Created by: $Id: $, boundary conditions from {:s},\nhistory: {:s}'.format(os.path.abspath(options.flood_map), 'PCRaster file, no history')

    # first write subcatch maps and hand maps
    ############### TODO ######
    # setup a HAND file for each strahler order

    max_s = inun_lib.define_max_strahler(options.stream_file, logging=logger)
    stream_max = np.minimum(max_s, options.max_strahler)

    for hand_strahler in range(options.catchment_strahler, stream_max + 1, 1):
        dem_name = os.path.split(options.dem_file)[1].split('.')[0]
        if os.path.isfile('{:s}_{:02d}.tif'.format(options.hand_file_prefix, hand_strahler)):
            hand_file = '{:s}_{:02d}.tif'.format(options.hand_file_prefix, hand_strahler)
        else:
            logger.info('No HAND files with HAND prefix were found, checking {:s}_hand_strahler_{:02d}.tif'.format(dem_name, hand_strahler))
            hand_file = os.path.join(options.dest_path, '{:s}_hand_strahler_{:02d}.tif'.format(dem_name, hand_strahler))
        if not(os.path.isfile(hand_file)):
        # hand file does not exist yet! Generate it, otherwise skip!
            logger.info('HAND file {:s} not found, start setting up...please wait...'.format(hand_file))
            hand_file_tmp = os.path.join(options.dest_path, '{:s}_hand_strahler_{:02d}.tif.tmp'.format(dem_name, hand_strahler))
            ds_hand, band_hand = inun_lib.prepare_gdal(hand_file_tmp, x, y, logging=logger, srs=srs)
            # band_hand = ds_hand.GetRasterBand(1)

            # Open terrain data for reading
            ds_dem, rasterband_dem = inun_lib.get_gdal_rasterband(options.dem_file)
            ds_ldd, rasterband_ldd = inun_lib.get_gdal_rasterband(options.ldd_file)
            ds_stream, rasterband_stream = inun_lib.get_gdal_rasterband(options.stream_file)
            n = 0
            for x_loop in range(0, len(x), options.x_tile):
                x_start = np.maximum(x_loop, 0)
                x_end = np.minimum(x_loop + options.x_tile, len(x))
                # determine actual overlap for cutting
                for y_loop in range(0, len(y), options.y_tile):
                    x_overlap_min = x_start - np.maximum(x_start - options.x_overlap, 0)
                    x_overlap_max = np.minimum(x_end + options.x_overlap, len(x)) - x_end
                    n += 1
                    # print('tile {:001d}:'.format(n))
                    y_start = np.maximum(y_loop, 0)
                    y_end = np.minimum(y_loop + options.y_tile, len(y))
                    y_overlap_min = y_start - np.maximum(y_start - options.y_overlap, 0)
                    y_overlap_max = np.minimum(y_end + options.y_overlap, len(y)) - y_end
                    # cut out DEM
                    logger.debug('Computing HAND for xmin: {:d} xmax: {:d} ymin {:d} ymax {:d}'.format(x_start, x_end,y_start, y_end))
                    terrain = rasterband_dem.ReadAsArray(x_start - x_overlap_min,
                                                         y_start - y_overlap_min,
                                                         (x_end + x_overlap_max) - (x_start - x_overlap_min),
                                                         (y_end + y_overlap_max) - (y_start - y_overlap_min)
                                                         )

                    drainage = rasterband_ldd.ReadAsArray(x_start - x_overlap_min,
                                                         y_start - y_overlap_min,
                                                         (x_end + x_overlap_max) - (x_start - x_overlap_min),
                                                         (y_end + y_overlap_max) - (y_start - y_overlap_min)
                                                         )
                    stream = rasterband_stream.ReadAsArray(x_start - x_overlap_min,
                                                           y_start - y_overlap_min,
                                                           (x_end + x_overlap_max) - (x_start - x_overlap_min),
                                                           (y_end + y_overlap_max) - (y_start - y_overlap_min)
                                                           )
                    # write to temporary file
                    terrain_temp_file = os.path.join(options.dest_path, 'terrain_temp.map')
                    drainage_temp_file = os.path.join(options.dest_path, 'drainage_temp.map')
                    stream_temp_file = os.path.join(options.dest_path, 'stream_temp.map')
                    if rasterband_dem.GetNoDataValue() is not None:
                        inun_lib.gdal_writemap(terrain_temp_file, 'PCRaster',
                                          np.arange(0, terrain.shape[1]),
                                          np.arange(0, terrain.shape[0]),
                                          terrain, rasterband_dem.GetNoDataValue(),
                                          gdal_type=gdal.GDT_Float32,
                                          logging=logger)
                    else:
                        # in case no nodata value is found
                        logger.warning('No nodata value found in {:s}. assuming -9999'.format(options.dem_file))
                        inun_lib.gdal_writemap(terrain_temp_file, 'PCRaster',
                                          np.arange(0, terrain.shape[1]),
                                          np.arange(0, terrain.shape[0]),
                                          terrain, -9999.,
                                          gdal_type=gdal.GDT_Float32,
                                          logging=logger)

                    inun_lib.gdal_writemap(drainage_temp_file, 'PCRaster',
                                      np.arange(0, terrain.shape[1]),
                                      np.arange(0, terrain.shape[0]),
                                      drainage, rasterband_ldd.GetNoDataValue(),
                                      gdal_type=gdal.GDT_Int32,
                                      logging=logger)
                    inun_lib.gdal_writemap(stream_temp_file, 'PCRaster',
                                      np.arange(0, terrain.shape[1]),
                                      np.arange(0, terrain.shape[0]),
                                      stream, rasterband_ldd.GetNoDataValue(),
                                      gdal_type=gdal.GDT_Int32,
                                      logging=logger)
                    # read as pcr objects
                    pcr.setclone(terrain_temp_file)
                    terrain_pcr = pcr.readmap(terrain_temp_file)
                    drainage_pcr = pcr.lddrepair(pcr.ldd(pcr.readmap(drainage_temp_file)))  # convert to ldd type map
                    stream_pcr = pcr.scalar(pcr.readmap(stream_temp_file))  # convert to ldd type map

                    #check if the highest stream order of the tile is below the hand_strahler
                    # if the highest stream order of the tile is smaller than hand_strahler, than DEM values are taken instead of HAND values.
                    max_stream_tile = inun_lib.define_max_strahler(stream_temp_file, logging=logger)
                    if max_stream_tile < hand_strahler:
                        hand_pcr = terrain_pcr
                        logger.info('For this tile, DEM values are used instead of HAND because there is no stream order larger than {:02d}'.format(hand_strahler))
                    else:
                    # compute streams
                        stream_ge, subcatch = inun_lib.subcatch_stream(drainage_pcr, hand_strahler, stream=stream_pcr) # generate streams
                        # compute basins
                        stream_ge_dummy, subcatch = inun_lib.subcatch_stream(drainage_pcr, options.catchment_strahler, stream=stream_pcr) # generate streams
                        basin = pcr.boolean(subcatch)
                        hand_pcr, dist_pcr = inun_lib.derive_HAND(terrain_pcr, drainage_pcr, 3000,
                                                                  rivers=pcr.boolean(stream_ge), basin=basin, neg_HAND=options.neg_HAND)
                    # convert to numpy
                    hand = pcr.pcr2numpy(hand_pcr, -9999.)
                    # cut relevant part
                    if y_overlap_max == 0:
                        y_overlap_max = -hand.shape[0]
                    if x_overlap_max == 0:
                        x_overlap_max = -hand.shape[1]
                    hand_cut = hand[0+y_overlap_min:-y_overlap_max, 0+x_overlap_min:-x_overlap_max]

                    band_hand.WriteArray(hand_cut, x_start, y_start)
                    os.unlink(terrain_temp_file)
                    os.unlink(drainage_temp_file)
                    os.unlink(stream_temp_file)
                    band_hand.FlushCache()
            ds_dem = None
            ds_ldd = None
            ds_stream = None
            band_hand.SetNoDataValue(-9999.)
            ds_hand = None
            logger.info('Finalizing {:s}'.format(hand_file))
            # rename temporary file to final hand file
            os.rename(hand_file_tmp, hand_file)
        else:
            logger.info('HAND file {:s} already exists...skipping...'.format(hand_file))

    #####################################################################################
    #  HAND file has now been prepared, moving to flood mapping part                    #
    #####################################################################################
    # set the clone
    pcr.setclone(options.ldd_wflow)
    # read wflow ldd as pcraster object
    ldd_pcr = pcr.readmap(options.ldd_wflow)
    xax, yax, riv_width, fill_value = inun_lib.gdal_readmap(options.riv_width_file, 'GTiff', logging=logger)

    # determine cell length in meters using ldd_pcr as clone (if latlon=True, values are converted to m2
    x_res, y_res, reallength_wflow = pcrut.detRealCellLength(pcr.scalar(ldd_pcr), not(bool(options.latlon)))
    cell_surface_wflow = pcr.pcr2numpy(x_res * y_res, 0)

    if options.flood_volume_type == 0:
        # load the staticmaps needed to estimate volumes across all
        # xax, yax, riv_length, fill_value = inun_lib.gdal_readmap(options.riv_length_file, 'GTiff', logging=logger)
        # riv_length = np.ma.masked_where(riv_length==fill_value, riv_length)
        xax, yax, riv_width, fill_value = inun_lib.gdal_readmap(options.riv_width_file, 'GTiff', logging=logger)
        riv_width[riv_width == fill_value] = 0

        # read river length factor file (multiplier)
        xax, yax, riv_length_fact, fill_value = inun_lib.gdal_readmap(options.riv_length_fact_file, 'GTiff', logging=logger)
        riv_length_fact = np.ma.masked_where(riv_length_fact==fill_value, riv_length_fact)
        drain_length = wflow_lib.detdrainlength(ldd_pcr, x_res, y_res)

        # compute river length in each cell
        riv_length = pcr.pcr2numpy(drain_length, 0) * riv_length_fact
        # riv_length_pcr = pcr.numpy2pcr(pcr.Scalar, riv_length, 0)

    flood_folder = os.path.join(options.dest_path, case_name)
    flood_vol_map = os.path.join(flood_folder, '{:s}_vol.tif'.format(os.path.split(options.flood_map)[1].split('.')[0]))
    if not(os.path.isdir(flood_folder)):
        os.makedirs(flood_folder)
    if options.out_format == 0:
        inun_file_tmp = os.path.join(flood_folder, '{:s}.tif.tmp'.format(case_name))
        inun_file = os.path.join(flood_folder, '{:s}.tif'.format(case_name))
    else:
        inun_file_tmp = os.path.join(flood_folder, '{:s}.nc.tmp'.format(case_name))
        inun_file = os.path.join(flood_folder, '{:s}.nc'.format(case_name))

    hand_temp_file = os.path.join(flood_folder, 'hand_temp.map')
    drainage_temp_file = os.path.join(flood_folder, 'drainage_temp.map')
    stream_temp_file = os.path.join(flood_folder, 'stream_temp.map')
    flood_vol_temp_file = os.path.join(flood_folder, 'flood_warp_temp.tif')
    # load the data with river levels and compute the volumes
    if options.file_format == 0:
        # assume we need the maximum value in a NetCDF time series grid
        logger.info('Reading flood from {:s} NetCDF file'.format(options.flood_map))
        a = nc.Dataset(options.flood_map, 'r')
        if options.latlon == 0:
            xax = a.variables['x'][:]
            yax = a.variables['y'][:]
        else:
            xax = a.variables['lon'][:]
            yax = a.variables['lat'][:]
        if options.time == '':
            time_list = nc.num2date(a.variables['time'][:], units = a.variables['time'].units, calendar=a.variables['time'].calendar)
            time = [time_list[len(time_list)/2]]
        else:
            time = [dt.datetime.strptime(options.time, '%Y%m%d%H%M%S')]

        flood_series = a.variables[options.flood_variable][:]
        flood_data = flood_series.max(axis=0)
        if np.ma.is_masked(flood_data):
            flood = flood_data.data
            flood[flood_data.mask] = 0
        if yax[-1] > yax[0]:
            yax = np.flipud(yax)
            flood = np.flipud(flood)
        a.close()
    elif options.file_format == 1:
        logger.info('Reading flood from {:s} PCRaster file'.format(options.flood_map))
        xax, yax, flood, flood_fill_value = inun_lib.gdal_readmap(options.flood_map, 'PCRaster', logging=logger)
        flood = np.ma.masked_equal(flood, flood_fill_value)
        if options.time == '':
            options.time = '20000101000000'
        time = [dt.datetime.strptime(options.time, '%Y%m%d%H%M%S')]

        flood[flood==flood_fill_value] = 0.
    # load the bankfull depths
    if options.bankfull_map == '':
        bankfull = np.zeros(flood.shape)
    else:
        if options.file_format == 0:
            logger.info('Reading bankfull from {:s} NetCDF file'.format(options.bankfull_map))
            a = nc.Dataset(options.bankfull_map, 'r')
            xax = a.variables['x'][:]
            yax = a.variables['y'][:]

            bankfull_series = a.variables[options.flood_variable][:]
            bankfull_data = bankfull_series.max(axis=0)
            if np.ma.is_masked(bankfull_data):
                bankfull = bankfull_data.data
                bankfull[bankfull_data.mask] = 0
            if yax[-1] > yax[0]:
                yax = np.flipud(yax)
                bankfull = np.flipud(bankfull)
            a.close()
        elif options.file_format == 1:
            logger.info('Reading bankfull from {:s} PCRaster file'.format(options.bankfull_map))
            xax, yax, bankfull, bankfull_fill_value = inun_lib.gdal_readmap(options.bankfull_map, 'PCRaster', logging=logger)
            bankfull = np.ma.masked_equal(bankfull, bankfull_fill_value)
#     flood = bankfull*2
    # res_x = 2000
    # res_y = 2000
    # subtract the bankfull water level to get flood levels (above bankfull)
    flood_vol = np.maximum(flood-bankfull, 0)
    if options.flood_volume_type == 0:
        flood_vol_m = riv_length*riv_width*flood_vol/cell_surface_wflow  # volume expressed in meters water disc
        flood_vol_m_pcr = pcr.numpy2pcr(pcr.Scalar, flood_vol_m, 0)
    else:
        flood_vol_m = flood_vol/cell_surface_wflow
    flood_vol_m_data = flood_vol_m.data
    flood_vol_m_data[flood_vol_m.mask] = -999.
    logger.info('Saving water layer map to {:s}'.format(flood_vol_map))
    # write to a tiff file
    inun_lib.gdal_writemap(flood_vol_map, 'GTiff', xax, yax, np.maximum(flood_vol_m_data, 0), -999., logging=logger)
    # this is placed later in the hand loop
    # ds_hand, rasterband_hand = inun_lib.get_gdal_rasterband(hand_file)
    ds_ldd, rasterband_ldd = inun_lib.get_gdal_rasterband(options.ldd_file)
    ds_stream, rasterband_stream = inun_lib.get_gdal_rasterband(options.stream_file)

    logger.info('Preparing flood map in {:s} ...please wait...'.format(inun_file))
    if options.out_format == 0:
        ds_inun, band_inun = inun_lib.prepare_gdal(inun_file_tmp, x, y, logging=logger, srs=srs)
        # band_inun = ds_inun.GetRasterBand(1)
    else:
        ds_inun, band_inun = inun_lib.prepare_nc(inun_file_tmp, time, x, np.flipud(y), metadata=metadata_global,
                                                 metadata_var=metadata_var, logging=logger)
    # loop over all the tiles
    n = 0
    for x_loop in range(0, len(x), options.x_tile):
        x_start = np.maximum(x_loop, 0)
        x_end = np.minimum(x_loop + options.x_tile, len(x))
        # determine actual overlap for cutting
        for y_loop in range(0, len(y), options.y_tile):
            x_overlap_min = x_start - np.maximum(x_start - options.x_overlap, 0)
            x_overlap_max = np.minimum(x_end + options.x_overlap, len(x)) - x_end
            n += 1
            # print('tile {:001d}:'.format(n))
            y_start = np.maximum(y_loop, 0)
            y_end = np.minimum(y_loop + options.y_tile, len(y))
            y_overlap_min = y_start - np.maximum(y_start - options.y_overlap, 0)
            y_overlap_max = np.minimum(y_end + options.y_overlap, len(y)) - y_end
            x_tile_ax = x[x_start - x_overlap_min:x_end + x_overlap_max]
            y_tile_ax = y[y_start - y_overlap_min:y_end + y_overlap_max]
            # cut out DEM
            logger.debug('handling xmin: {:d} xmax: {:d} ymin {:d} ymax {:d}'.format(x_start, x_end, y_start, y_end))


            drainage = rasterband_ldd.ReadAsArray(x_start - x_overlap_min,
                                                 y_start - y_overlap_min,
                                                 (x_end + x_overlap_max) - (x_start - x_overlap_min),
                                                 (y_end + y_overlap_max) - (y_start - y_overlap_min)
                                                 )
            stream = rasterband_stream.ReadAsArray(x_start - x_overlap_min,
                                                   y_start - y_overlap_min,
                                                   (x_end + x_overlap_max) - (x_start - x_overlap_min),
                                                   (y_end + y_overlap_max) - (y_start - y_overlap_min)
                                                   )

            # stream_max = np.minimum(stream.max(), options.max_strahler)


            inun_lib.gdal_writemap(drainage_temp_file, 'PCRaster',
                              x_tile_ax,
                              y_tile_ax,
                              drainage, rasterband_ldd.GetNoDataValue(),
                              gdal_type=gdal.GDT_Int32,
                              logging=logger)
            inun_lib.gdal_writemap(stream_temp_file, 'PCRaster',
                              x_tile_ax,
                              y_tile_ax,
                              stream, rasterband_stream.GetNoDataValue(),
                              gdal_type=gdal.GDT_Int32,
                              logging=logger)


            # read as pcr objects
            pcr.setclone(stream_temp_file)
            drainage_pcr = pcr.lddrepair(pcr.ldd(pcr.readmap(drainage_temp_file)))  # convert to ldd type map
            stream_pcr = pcr.scalar(pcr.readmap(stream_temp_file))  # convert to ldd type map

            # warp of flood volume to inundation resolution
            inun_lib.gdal_warp(flood_vol_map, stream_temp_file, flood_vol_temp_file, gdal_interp=gdalconst.GRA_NearestNeighbour) # ,
            x_tile_ax, y_tile_ax, flood_meter, fill_value = inun_lib.gdal_readmap(flood_vol_temp_file, 'GTiff', logging=logger)
            # make sure that the option unittrue is on !! (if unitcell was is used in another function)
            x_res_tile, y_res_tile, reallength = pcrut.detRealCellLength(pcr.scalar(stream_pcr), not(bool(options.latlon)))
            cell_surface_tile = pcr.pcr2numpy(x_res_tile * y_res_tile, 0)

            # convert meter depth to volume [m3]
            flood_vol = pcr.numpy2pcr(pcr.Scalar, flood_meter*cell_surface_tile, fill_value)

            # first prepare a basin map, belonging to the lowest order we are looking at
            inundation_pcr = pcr.scalar(stream_pcr) * 0
            for hand_strahler in range(options.catchment_strahler, stream_max + 1, 1):
                # hand_temp_file = os.path.join(flood_folder, 'hand_temp.map')
                if os.path.isfile(os.path.join(options.dest_path, '{:s}_hand_strahler_{:02d}.tif'.format(dem_name, hand_strahler))):
                    hand_file = os.path.join(options.dest_path, '{:s}_hand_strahler_{:02d}.tif'.format(dem_name, hand_strahler))
                else:
                    hand_file = '{:s}_{:02d}.tif'.format(options.hand_file_prefix, hand_strahler)
                ds_hand, rasterband_hand = inun_lib.get_gdal_rasterband(hand_file)
                hand = rasterband_hand.ReadAsArray(x_start - x_overlap_min,
                                             y_start - y_overlap_min,
                                             (x_end + x_overlap_max) - (x_start - x_overlap_min),
                                             (y_end + y_overlap_max) - (y_start - y_overlap_min)
                                             )
                print('len x-ax: {:d} len y-ax {:d} x-shape {:d} y-shape {:d}'.format(len(x_tile_ax), len(y_tile_ax), hand.shape[1], hand.shape[0]))

                inun_lib.gdal_writemap(hand_temp_file, 'PCRaster',
                          x_tile_ax,
                          y_tile_ax,
                          hand, rasterband_hand.GetNoDataValue(),
                          gdal_type=gdal.GDT_Float32,
                          logging=logger)

                hand_pcr = pcr.readmap(hand_temp_file)

                stream_ge_hand, subcatch_hand = inun_lib.subcatch_stream(drainage_pcr, options.catchment_strahler, stream=stream_pcr)
                # stream_ge_hand, subcatch_hand = inun_lib.subcatch_stream(drainage_pcr, hand_strahler, stream=stream_pcr)
                stream_ge, subcatch = inun_lib.subcatch_stream(drainage_pcr,
                                                               options.catchment_strahler,
                                                               stream=stream_pcr,
                                                               basin=pcr.boolean(pcr.cover(subcatch_hand, 0)),
                                                               assign_existing=True,
                                                               min_strahler=hand_strahler,
                                                               max_strahler=hand_strahler) # generate subcatchments, only within basin for HAND
                flood_vol_strahler = pcr.ifthenelse(pcr.boolean(pcr.cover(subcatch, 0)), flood_vol, 0) # mask the flood volume map with the created subcatch map for strahler order = hand_strahler

                inundation_pcr_step = inun_lib.volume_spread(drainage_pcr, hand_pcr,
                                                             pcr.subcatchment(drainage_pcr, subcatch), # to make sure backwater effects can occur from higher order rivers to lower order rivers
                                                             flood_vol_strahler,
                                                             volume_thres=0.,
                                                             iterations=options.iterations,
                                                             cell_surface=pcr.numpy2pcr(pcr.Scalar, cell_surface_tile, -9999),
                                                             logging=logger,
                                                             order=hand_strahler,
                                                             neg_HAND=options.neg_HAND) # 1166400000.
                # use maximum value of inundation_pcr_step and new inundation for higher strahler order
                inundation_pcr = pcr.max(inundation_pcr, inundation_pcr_step)
            inundation = pcr.pcr2numpy(inundation_pcr, -9999.)
            # cut relevant part
            if y_overlap_max == 0:
                y_overlap_max = -inundation.shape[0]
            if x_overlap_max == 0:
                x_overlap_max = -inundation.shape[1]
            inundation_cut = inundation[0+y_overlap_min:-y_overlap_max, 0+x_overlap_min:-x_overlap_max]
            # inundation_cut
            if options.out_format == 0:
                band_inun.WriteArray(inundation_cut, x_start, y_start)
                band_inun.FlushCache()
            else:
                # with netCDF, data is up-side-down.
                inun_lib.write_tile_nc(band_inun, inundation_cut, x_start, y_start)
            # clean up
            os.unlink(flood_vol_temp_file)
            os.unlink(drainage_temp_file)
            os.unlink(hand_temp_file)
            os.unlink(stream_temp_file)     #also remove temp stream file from output folder

            # if n == 35:
            #     band_inun.SetNoDataValue(-9999.)
            #     ds_inun = None
            #     sys.exit(0)
    # os.unlink(flood_vol_map)

    logger.info('Finalizing {:s}'.format(inun_file))
    # add the metadata to the file and band
    # band_inun.SetNoDataValue(-9999.)
    # ds_inun.SetMetadata(metadata_global)
    # band_inun.SetMetadata(metadata_var)
    if options.out_format == 0:
        ds_inun = None
        ds_hand = None
    else:
        ds_inun.close()

    ds_ldd = None
    # rename temporary file to final hand file
    if os.path.isfile(inun_file):
        # remove an old result if available
        os.unlink(inun_file)
    os.rename(inun_file_tmp, inun_file)

    logger.info('Done! Thank you for using hand_contour_inun.py')
    logger, ch = inun_lib.closeLogger(logger, ch)
    del logger, ch
    sys.exit(0)
        wbCatchment        = pcr.catchmenttotal(pcr.scalar(1), ldd_map_low_resolution)
        water_body_outlet  = pcr.ifthen(wbCatchment ==\
                             pcr.areamaximum(wbCatchment, \
                             water_body_id),\
                             water_body_id) # = outlet ids      # This may give more than two outlets, particularly if there are more than one cells that have largest upstream areas      
        # - make sure that there is only one outlet for each water body 
        water_body_outlet  = pcr.ifthen(\
                             pcr.areaorder(pcr.scalar( water_body_outlet), \
                             water_body_outlet) == 1., water_body_outlet)
        water_body_outlet  = pcr.ifthen(\
                             pcr.scalar(water_body_outlet) > 0., water_body_outlet)

        # calculate overbank volume from reservoirs (and lakes)
        lake_reservoir_volume          = pcr.areatotal(extreme_value_map, water_body_id)
        lake_reservoir_overbank_volume = pcr.cover(
                                         pcr.max(0.0, lake_reservoir_volume - reservoir_capacity), 0.0)
        #~ pcr.aguila(lake_reservoir_overbank_volume)
        #
        # transfer 75% of overbank volume to the downstream (several cells downstream)
        transfer_to_downstream = pcr.cover(\
                                 pcr.ifthen(pcr.scalar(water_body_outlet) > 0., lake_reservoir_overbank_volume * 0.50), 0.0)
        transfer_to_downstream = pcr.upstream(ldd_map_low_resolution, transfer_to_downstream)
        transfer_to_downstream = pcr.upstream(ldd_map_low_resolution, transfer_to_downstream)
        transfer_to_downstream = pcr.upstream(ldd_map_low_resolution, transfer_to_downstream)
        extreme_value_map      = transfer_to_downstream + \
                                 pcr.ifthenelse(pcr.cover(pcr.scalar(water_body_id), 0.0) > 0.00, 0.00, extreme_value_map) 
        #
        # the remaining overbank volume (50%) will be distributed to the shores
        lake_reservoir_overbank_volume = lake_reservoir_overbank_volume * 0.50                         
        land_area = cell_area * pcr.max(0.0, 1.0 - fracwat)
        land_area_average = pcr.areaaverage(land_area, water_body_id) 
     logger.info(msg)
     return_period_historical = glofris.get_return_period_gumbel(p_zero["historical"], location["historical"], scale["historical"], extreme_values["including_bias"][return_period])
     extreme_values['return_period_historical'][return_period] = return_period_historical
     
     #~ pcr.report(return_period_historical, "return_period_historical.map")
     #~ cmd = "aguila " + "return_period_historical.map"
     #~ os.system(cmd)
     
     # bias corrected extreme values
     msg = "Calculate the bias corrected extreme values: Using the return period based on the historical gumbel fit/parameters and the gumbel fit/parameters of the baseline run."
     logger.info(msg)
     # 
     extreme_value_map = glofris.inverse_gumbel(p_zero["baseline"], location["baseline"], scale["baseline"], return_period_historical)
     #
     # - make sure that we have positive extreme values - this is not necessary, but to make sure
     extreme_value_map = pcr.max(extreme_value_map, 0.0)
     #
     # - make sure that extreme value maps increasing over return period - this is not necessary, but to make sure
     if i_return_period >  0: extreme_value_map = pcr.max(previous_return_period_map, extreme_value_map) 
     previous_return_period_map = extreme_value_map
     #
     # - saving extreme values in the dictionary  
     extreme_values["bias_corrected"][return_period] = extreme_value_map
 
 # time bounds in a netcdf file
 lowerTimeBound = datetime.datetime(str_year,  1,  1, 0)
 upperTimeBound = datetime.datetime(end_year, 12, 31, 0)
 timeBounds = [lowerTimeBound, upperTimeBound]
 
 # reporting/saving extreme values in netcdf and pcraster files
 for bias_type in ['including_bias', 'bias_corrected']:
    def dynamic(self):
        
        # re-calculate current model time using current pcraster timestep value
        self.modelTime.update(self.currentTimeStep())

        # for variables other than temperature and maximum temperature, just read them directly
        if self.output['variable_name'] != "temperature" and self.output['variable_name'] != "maximum_temperature":
            
            pcraster_map_file_name = pcr.framework.frameworkBase.generateNameT(self.pcraster_file_name,\
                                                                               self.modelTime.timeStepPCR) 
            pcr_map_values = vos.readPCRmapClone(v = pcraster_map_file_name,\
                                                 cloneMapFileName = self.cloneMapFileName,\
                                                 tmpDir = self.tmpDir,\
                                                 absolutePath = None, isLddMap = False,\
                                                 cover = None,\
                                                 isNomMap = False,\
                                                 inputEPSG = self.inputEPSG,\
                                                 outputEPSG = self.outputEPSG,\
                                                 method = self.resample_method)

        # for temperature and maximum temperature, we have to make sure that maximum temperature is higher than minimum temperature
        if self.output['variable_name'] == "temperature" or self.output['variable_name'] == "maximum_temperature":
            
            min_map_file_name = pcr.framework.frameworkBase.generateNameT(self.pcraster_files['directory']+"/tn", self.modelTime.timeStepPCR)
            max_map_file_name = pcr.framework.frameworkBase.generateNameT(self.pcraster_files['directory']+"/tx", self.modelTime.timeStepPCR)
            min_map_values = vos.readPCRmapClone(v = min_map_file_name,\
                                                 cloneMapFileName = self.cloneMapFileName,\
                                                 tmpDir = self.tmpDir,\
                                                 absolutePath = None, isLddMap = False,\
                                                 cover = None,\
                                                 isNomMap = False,\
                                                 inputEPSG = self.inputEPSG,\
                                                 outputEPSG = self.outputEPSG,\
                                                 method = self.resample_method)
            max_map_values = vos.readPCRmapClone(v = max_map_file_name,\
                                                 cloneMapFileName = self.cloneMapFileName,\
                                                 tmpDir = self.tmpDir,\
                                                 absolutePath = None, isLddMap = False,\
                                                 cover = None,\
                                                 isNomMap = False,\
                                                 inputEPSG = self.inputEPSG,\
                                                 outputEPSG = self.outputEPSG,\
                                                 method = self.resample_method)
            
            # make sure that maximum values are higher than minimum values
            max_map_values = pcr.max(min_map_values, max_map_values)
            
            if self.output['variable_name'] == "temperature": pcr_map_values = 0.50*(min_map_values + \
                                                                                     max_map_values)
            if self.output['variable_name'] == "maximum_temperature": pcr_map_values = pcr.max(min_map_values, max_map_values)
        
        # for precipitation, converting the unit from mm.day-1 to m.day-1
        if self.output['variable_name'] == "precipitation": pcr_map_values *= 0.001
        
        # reporting
        timeStamp = datetime.datetime(self.modelTime.year,\
                                      self.modelTime.month,\
                                      self.modelTime.day,0)
        self.netcdf_report.data2NetCDF(self.output['file_name'],\
                                       self.output['variable_name'],\
                                       pcr.pcr2numpy(pcr_map_values,vos.MV),\
                                       timeStamp)
    # variable name
    variable_name = str(return_period) + "_of_" + varDict.netcdf_short_name[var_name]

    msg = "Writing " + str(variable_name)
    logger.info(msg)
    
    # read from pcraster files
    #
    inundation_file_name = output_directory + "/global/maps/" + "inun_" + str(return_period) + "_of_flood_inundation_volume_catch_" + strahler_order_option + ".tif.map"
    if map_type_name == "channel_storage.map": inundation_file_name = output_directory + "/global/maps/" + "inun_" + str(return_period) + "_of_channel_storage_catch_" + strahler_order_option + ".tif.map"
    #
    inundation_map = pcr.readmap(inundation_file_name)
    inundation_map = pcr.cover(inundation_map, 0.0)
    #
    # - make sure that we have positive extreme values - this is not necessary, but to make sure
    inundation_map = pcr.max(inundation_map, 0.0)
    #
    # - make sure that extreme value maps increasing over return period - this is not necessary, but to make sure
    if i_return_period >  0: inundation_map = pcr.max(previous_return_period_map, inundation_map) 
    previous_return_period_map = inundation_map
    
    # using values in the landmask only and masking out permanent water bodies
    inundation_map = pcr.ifthen(landmask_used, inundation_map)
    inundation_map = pcr.ifthen(non_permanent_water_bodies, inundation_map)
    
    # report in pcraster maps
    pcr.report(inundation_map, inundation_file_name + ".masked_out.map")
    
    # write to netcdf files
    netcdf_report.data_to_netcdf(file_name, variable_name, pcr.pcr2numpy(inundation_map, vos.MV), timeBounds, timeStamp = None, posCnt = 0)
    channel_storage = vos.netcdf2PCRobjClone(input_files['file_name']['channelStorage'], \
                                             "channel_storage", time_index_in_netcdf_file,\
                                             useDoy = "Yes", \
                                             cloneMapFileName  = clone_map_file,\
                                             LatitudeLongitude = True,\
                                             specificFillValue = None)
    channel_storage = pcr.ifthen(landmask, pcr.cover(channel_storage, 0.0))
    
    # read fraction_of_surface_water (dimensionless)
    fraction_of_surface_water = vos.netcdf2PCRobjClone(input_files['file_name']['dynamicFracWat'], \
                                                       "fraction_of_surface_water", time_index_in_netcdf_file,\
                                                       useDoy = "Yes", \
                                                       cloneMapFileName  = clone_map_file,\
                                                       LatitudeLongitude = True,\
                                                       specificFillValue = None)
    fraction_of_surface_water = pcr.ifthen(landmask, pcr.cover(fraction_of_surface_water, 0.0))
    
    # calculate surface water level
    surface_water_level = channel_storage / (pcr.max(fraction_of_surface_water, minimum_fraction_of_surface_water) * cell_area)

    # convert it to arrays
    surface_water_level = pcr.pcr2numpy(surface_water_level, vos.MV)

    # save it to netcdf file
    ncFileName = netcdf_file[var_name]['file_name']
    msg = "Saving to the netcdf file: " + str(netcdf_file[var_name]['file_name'])
    logger.info(msg)
    time_stamp_used = datetime.datetime(i_year, 12, 31, 0)
    netcdf_report.data2NetCDF(ncFileName, varDict.netcdf_short_name[var_name], surface_water_level, time_stamp_used)