Esempio n. 1
0
def checkerboard(mapin, fcc):
    """
    checkerboard create a checkerboard map with unique id's in a
    fcc*fcc cells area. The resulting map can be used
    to derive statistics for (later) upscaling of maps (using the fcc factor)

    .. warning: use with unitcell to get most reliable results!

    Input:
        - map (used to determine coordinates)
        - fcc (size of the areas in cells)

    Output:
        - checkerboard type map
    """
    msker = pcr.defined(mapin)
    ymin = pcr.mapminimum(pcr.ycoordinate(msker))
    yc = (pcr.ycoordinate((msker)) - ymin) / pcr.celllength()
    yc = pcr.rounddown(yc / fcc)
    # yc = yc/fcc
    xmin = pcr.mapminimum(pcr.xcoordinate((msker)))
    xc = (pcr.xcoordinate((msker)) - xmin) / pcr.celllength()
    xc = pcr.rounddown(xc / fcc)
    # xc = xc/fcc

    yc = yc * (pcr.mapmaximum(xc) + 1.0)

    xy = pcr.ordinal(xc + yc)

    return xy
Esempio n. 2
0
def checkerboard(mapin, fcc):
    """
    checkerboard create a checkerboard map with unique id's in a
    fcc*fcc cells area. The resulting map can be used
    to derive statistics for (later) upscaling of maps (using the fcc factor)

    .. warning: use with unitcell to get most reliable results!

    Input:
        - map (used to determine coordinates)
        - fcc (size of the areas in cells)

    Output:
        - checkerboard type map
    """
    msker = pcr.defined(mapin)
    ymin = pcr.mapminimum(pcr.ycoordinate(msker))
    yc = (pcr.ycoordinate((msker)) - ymin) / pcr.celllength()
    yc = pcr.rounddown(yc / fcc)
    # yc = yc/fcc
    xmin = pcr.mapminimum(pcr.xcoordinate((msker)))
    xc = (pcr.xcoordinate((msker)) - xmin) / pcr.celllength()
    xc = pcr.rounddown(xc / fcc)
    # xc = xc/fcc

    yc = yc * (pcr.mapmaximum(xc) + 1.0)

    xy = pcr.ordinal(xc + yc)

    return xy
Esempio n. 3
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)
Esempio n. 4
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)
Esempio n. 5
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")
Esempio n. 6
0
    def getICs(self, initial_condition):

        avgInflow = initial_condition["avgLakeReservoirInflowShort"]
        avgOutflow = initial_condition["avgLakeReservoirOutflowLong"]
        #
        if not isinstance(initial_condition["waterBodyStorage"],
                          types.NoneType):
            # 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)
Esempio n. 7
0
def area_percentile(inmap, area, n, order, percentile):
    """
  calculates percentile of inmap per area
  n is the number of points in each area,
  order, the sorter order of inmap per area (output of
  areaorder(inmap,area))
  n is the output of pcr.areatotal(pcr.spatial(pcr.scalar(1.0)),area)

  Input:
      - inmap
      - area map
      - n
      - order (riverorder)
      - percentile

  Output:
      - percentile map

  """
    i = pcr.rounddown((n * percentile) / 100.0 + 0.5)  # index in order map
    perc = pcr.ifthen(i == order, inmap)

    return pcr.areaaverage(perc, area)
Esempio n. 8
0
def area_percentile(inmap, area, n, order, percentile):
    """
  calculates percentile of inmap per area
  n is the number of points in each area,
  order, the sorter order of inmap per area (output of
  areaorder(inmap,area))
  n is the output of pcr.areatotal(pcr.spatial(pcr.scalar(1.0)),area)

  Input:
      - inmap
      - area map
      - n
      - order (riverorder)
      - percentile

  Output:
      - percentile map

  """
    i = pcr.rounddown((n * percentile) / 100.0 + 0.5)  # index in order map
    perc = pcr.ifthen(i == order, inmap)

    return pcr.areaaverage(perc, area)
Esempio n. 9
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)
Esempio n. 10
0
    def read_forcings(self, currTimeStep):
        # reading precipitation:
        self.precipitation = vos.netcdf2PCRobjClone(\
                                  self.preFileNC,'precipitation',\
                                  str(currTimeStep.fulldate),
                                  useDoy = None,
                                  cloneMapFileName=self.cloneMap,\
                                  LatitudeLongitude = True)

        precipitationCorrectionFactor = pcr.scalar(
            1.0
        )  # Since 19 Feb 2014, Edwin removed the support for correcting precipitation.
        self.precipitation = pcr.max(0.,self.precipitation*\
                precipitationCorrectionFactor)
        self.precipitation = pcr.cover(self.precipitation, 0.0)

        # ignore very small values of precipitation (less than 0.00001 m/day or less than 0.01 kg.m-2.day-1 )
        if self.usingDailyTimeStepForcingData:
            self.precipitation = pcr.rounddown(
                self.precipitation * 100000.) / 100000.

        # reading temperature
        self.temperature = vos.netcdf2PCRobjClone(\
                                 self.tmpFileNC,'temperature',\
                                 str(currTimeStep.fulldate),
                                 useDoy = None,
                                  cloneMapFileName=self.cloneMap,\
                                  LatitudeLongitude = True)

        # Downscaling precipitation and temperature
        if self.downscalePrecipitationOption:
            self.downscalePrecipitation(currTimeStep)
        if self.downscaleTemperatureOption:
            self.downscaleTemperature(currTimeStep)

        # calculate or obtain referencePotET
        if self.refETPotMethod == 'Hamon':            self.referencePotET = \
   refPotET.HamonPotET(self.temperature,\
                       currTimeStep.doy,\
                       self.latitudes)
        if self.refETPotMethod == 'Input':
            self.referencePotET = vos.netcdf2PCRobjClone(\
                                     self.etpFileNC,'evapotranspiration',\
                                     str(currTimeStep.fulldate),
                                     useDoy = None,
                                      cloneMapFileName=self.cloneMap,\
                                      LatitudeLongitude = True)

        # Downscaling referenceETPot (based on temperature)
        if self.downscaleReferenceETPotOption: self.downscaleReferenceETPot()

        # smoothing:
        if self.forcingSmoothing == True:
            logger.info("Forcing data are smoothed.")
            self.precipitation = pcr.windowaverage(self.precipitation,
                                                   self.smoothingWindowsLength)
            self.temperature = pcr.windowaverage(self.temperature,
                                                 self.smoothingWindowsLength)
            self.referencePotET = pcr.windowaverage(
                self.referencePotET, self.smoothingWindowsLength)

        # define precipitation, temperature and referencePotET ONLY at landmask area (for reporting):
        self.precipitation = pcr.ifthen(self.landmask, self.precipitation)
        self.temperature = pcr.ifthen(self.landmask, self.temperature)
        self.referencePotET = pcr.ifthen(self.landmask, self.referencePotET)

        if self.report == True:
            timeStamp = datetime.datetime(currTimeStep.year,\
                                          currTimeStep.month,\
                                          currTimeStep.day,\
                                          0)
            # writing daily output to netcdf files
            timestepPCR = currTimeStep.timeStepPCR
            if self.outDailyTotNC[0] != "None":
                for var in self.outDailyTotNC:
                    self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_dailyTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,timestepPCR-1)

            # writing monthly output to netcdf files
            # -cummulative
            if self.outMonthTotNC[0] != "None":
                for var in self.outMonthTotNC:

                    # introduce variables at the beginning of simulation or
                    #     reset variables at the beginning of the month
                    if currTimeStep.timeStepPCR == 1 or \
                       currTimeStep.day == 1:                        \
                                               vars(self)[var+'MonthTot'] = pcr.scalar(0.0)

                    # accumulating
                    vars(self)[var + 'MonthTot'] += vars(self)[var]

                    # reporting at the end of the month:
                    if currTimeStep.endMonth == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'MonthTot'),\
                           vos.MV),timeStamp,currTimeStep.monthIdx-1)
            # -average
            if self.outMonthAvgNC[0] != "None":
                for var in self.outMonthAvgNC:
                    # only if a accumulator variable has not been defined:
                    if var not in self.outMonthTotNC:

                        # introduce accumulator at the beginning of simulation or
                        #     reset accumulator at the beginning of the month
                        if currTimeStep.timeStepPCR == 1 or \
                           currTimeStep.day == 1:                            \
                                                       vars(self)[var+'MonthTot'] = pcr.scalar(0.0)
                        # accumulating
                        vars(self)[var + 'MonthTot'] += vars(self)[var]

                    # calculating average & reporting at the end of the month:
                    if currTimeStep.endMonth == True:
                        vars(self)[var+'MonthAvg'] = vars(self)[var+'MonthTot']/\
                                                     currTimeStep.day
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthAvg.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'MonthAvg'),\
                           vos.MV),timeStamp,currTimeStep.monthIdx-1)
            #
            # -last day of the month
            if self.outMonthEndNC[0] != "None":
                for var in self.outMonthEndNC:
                    # reporting at the end of the month:
                    if currTimeStep.endMonth == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthEnd.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,currTimeStep.monthIdx-1)

            # writing yearly output to netcdf files
            # -cummulative
            if self.outAnnuaTotNC[0] != "None":
                for var in self.outAnnuaTotNC:

                    # introduce variables at the beginning of simulation or
                    #     reset variables at the beginning of the month
                    if currTimeStep.timeStepPCR == 1 or \
                       currTimeStep.doy == 1:                        \
                                               vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0)

                    # accumulating
                    vars(self)[var + 'AnnuaTot'] += vars(self)[var]

                    # reporting at the end of the year:
                    if currTimeStep.endYear == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'AnnuaTot'),\
                           vos.MV),timeStamp,currTimeStep.annuaIdx-1)
            # -average
            if self.outAnnuaAvgNC[0] != "None":
                for var in self.outAnnuaAvgNC:
                    # only if a accumulator variable has not been defined:
                    if var not in self.outAnnuaTotNC:
                        # introduce accumulator at the beginning of simulation or
                        #     reset accumulator at the beginning of the year
                        if currTimeStep.timeStepPCR == 1 or \
                           currTimeStep.doy == 1:                            \
                                                       vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0)
                        # accumulating
                        vars(self)[var + 'AnnuaTot'] += vars(self)[var]
                    #
                    # calculating average & reporting at the end of the year:
                    if currTimeStep.endYear == True:
                        vars(self)[var+'AnnuaAvg'] = vars(self)[var+'AnnuaTot']/\
                                                     currTimeStep.doy
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaAvg.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'AnnuaAvg'),\
                           vos.MV),timeStamp,currTimeStep.annuaIdx-1)
            #
            # -last day of the year
            if self.outAnnuaEndNC[0] != "None":
                for var in self.outAnnuaEndNC:
                    # reporting at the end of the year:
                    if currTimeStep.endYear == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaEnd.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,currTimeStep.annuaIdx-1)
Esempio n. 11
0
    def read_forcings(self, currTimeStep):

        #-----------------------------------------------------------------------
        # NOTE: RvB 13/07/2016 hard-coded reference to the variable names
        # preciptiation, temperature and evapotranspiration have been replaced
        # by the variable names used in the netCDF and passed from the ini file
        #-----------------------------------------------------------------------

        # method for finding time indexes in the precipitation netdf file:
        # - the default one
        method_for_time_index = None
        # - based on the ini/configuration file (if given)
        if 'time_index_method_for_precipitation_netcdf' in list(self.iniItems.meteoOptions.keys()) and\
                                                           self.iniItems.meteoOptions['time_index_method_for_precipitation_netcdf'] != "None":
            method_for_time_index = self.iniItems.meteoOptions[
                'time_index_method_for_precipitation_netcdf']

        # reading precipitation:
        if self.precipitation_set_per_year:
            #~ print currTimeStep.year
            nc_file_per_year = self.preFileNC % (float(
                currTimeStep.year), float(currTimeStep.year))
            self.precipitation = vos.netcdf2PCRobjClone(\
                                      nc_file_per_year, self.preVarName,\
                                      str(currTimeStep.fulldate),
                                      useDoy = method_for_time_index,
                                      cloneMapFileName = self.cloneMap,\
                                      LatitudeLongitude = True)
        else:
            self.precipitation = vos.netcdf2PCRobjClone(\
                                      self.preFileNC, self.preVarName,\
                                      str(currTimeStep.fulldate),
                                      useDoy = method_for_time_index,
                                      cloneMapFileName = self.cloneMap,\
                                      LatitudeLongitude = True)

        #-----------------------------------------------------------------------
        # NOTE: RvB 13/07/2016 added to automatically update precipitation
        self.precipitation = self.preConst + self.preFactor * pcr.ifthen(
            self.landmask, self.precipitation)
        #-----------------------------------------------------------------------

        # make sure that precipitation is always positive
        self.precipitation = pcr.max(0., self.precipitation)
        self.precipitation = pcr.cover(self.precipitation, 0.0)

        # ignore very small values of precipitation (less than 0.00001 m/day or less than 0.01 kg.m-2.day-1 )
        if self.usingDailyTimeStepForcingData:
            self.precipitation = pcr.rounddown(
                self.precipitation * 100000.) / 100000.

        # method for finding time index in the temperature netdf file:
        # - the default one
        method_for_time_index = None
        # - based on the ini/configuration file (if given)
        if 'time_index_method_for_temperature_netcdf' in list(self.iniItems.meteoOptions.keys()) and\
                                                         self.iniItems.meteoOptions['time_index_method_for_temperature_netcdf'] != "None":
            method_for_time_index = self.iniItems.meteoOptions[
                'time_index_method_for_temperature_netcdf']

        # reading temperature
        if self.temperature_set_per_year:
            nc_file_per_year = self.tmpFileNC % (int(
                currTimeStep.year), int(currTimeStep.year))
            self.temperature = vos.netcdf2PCRobjClone(\
                                      nc_file_per_year, self.tmpVarName,\
                                      str(currTimeStep.fulldate),
                                      useDoy = method_for_time_index,
                                      cloneMapFileName = self.cloneMap,\
                                      LatitudeLongitude = True)
        else:
            self.temperature = vos.netcdf2PCRobjClone(\
                                 self.tmpFileNC,self.tmpVarName,\
                                 str(currTimeStep.fulldate),
                                 useDoy = method_for_time_index,
                                 cloneMapFileName=self.cloneMap,\
                                 LatitudeLongitude = True)

        #-----------------------------------------------------------------------
        # NOTE: RvB 13/07/2016 added to automatically update temperature
        self.temperature = self.tmpConst + self.tmpFactor * pcr.ifthen(
            self.landmask, self.temperature)
        #-----------------------------------------------------------------------

        # Downscaling precipitation and temperature
        if self.downscalePrecipitationOption:
            self.downscalePrecipitation(currTimeStep)
        if self.downscaleTemperatureOption:
            self.downscaleTemperature(currTimeStep)

        # calculate or obtain referencePotET
        if self.refETPotMethod == 'Hamon':            self.referencePotET = \
   refPotET.HamonPotET(self.temperature,\
                       currTimeStep.doy,\
                       self.latitudes)
        if self.refETPotMethod == 'Input':

            # method for finding time indexes in the precipitation netdf file:
            # - the default one
            method_for_time_index = None
            # - based on the ini/configuration file (if given)
            if 'time_index_method_for_ref_pot_et_netcdf' in list(self.iniItems.meteoOptions.keys()) and\
                                                            self.iniItems.meteoOptions['time_index_method_for_ref_pot_et_netcdf'] != "None":
                method_for_time_index = self.iniItems.meteoOptions[
                    'time_index_method_for_ref_pot_et_netcdf']

            if self.refETPotFileNC_set_per_year:
                nc_file_per_year = self.etpFileNC % (int(
                    currTimeStep.year), int(currTimeStep.year))
                self.referencePotET = vos.netcdf2PCRobjClone(\
                                      nc_file_per_year, self.refETPotVarName,\
                                      str(currTimeStep.fulldate),
                                      useDoy = method_for_time_index,
                                      cloneMapFileName = self.cloneMap,\
                                      LatitudeLongitude = True)
            else:
                self.referencePotET = vos.netcdf2PCRobjClone(\
                                      self.etpFileNC,self.refETPotVarName,\
                                      str(currTimeStep.fulldate),
                                      useDoy = method_for_time_index,
                                      cloneMapFileName=self.cloneMap,\
                                      LatitudeLongitude = True)
            #-----------------------------------------------------------------------
            # NOTE: RvB 13/07/2016 added to automatically update reference potential evapotranspiration
            self.referencePotET = self.refETPotConst + self.refETPotFactor * pcr.ifthen(
                self.landmask, self.referencePotET)
            #-----------------------------------------------------------------------

        # Downscaling referenceETPot (based on temperature)
        if self.downscaleReferenceETPotOption: self.downscaleReferenceETPot()

        # smoothing:
        if self.forcingSmoothing == True:
            logger.debug("Forcing data are smoothed.")
            self.precipitation = pcr.windowaverage(self.precipitation,
                                                   self.smoothingWindowsLength)
            self.temperature = pcr.windowaverage(self.temperature,
                                                 self.smoothingWindowsLength)
            self.referencePotET = pcr.windowaverage(
                self.referencePotET, self.smoothingWindowsLength)

        # rounding temperature values to minimize numerical errors (note only to minimize, not remove)
        self.temperature = pcr.roundoff(self.temperature * 1000.) / 1000.

        # ignore snow by setting temperature to 25 deg C
        if self.ignore_snow: self.temperature = pcr.spatial(pcr.scalar(25.))

        # define precipitation, temperature and referencePotET ONLY at landmask area (for reporting):
        self.precipitation = pcr.ifthen(self.landmask, self.precipitation)
        self.temperature = pcr.ifthen(self.landmask, self.temperature)
        self.referencePotET = pcr.ifthen(self.landmask, self.referencePotET)

        # make sure precipitation and referencePotET are always positive:
        self.precipitation = pcr.max(0.0, self.precipitation)
        self.referencePotET = pcr.max(0.0, self.referencePotET)

        if self.report == True:
            timeStamp = datetime.datetime(currTimeStep.year,\
                                          currTimeStep.month,\
                                          currTimeStep.day,\
                                          0)
            # writing daily output to netcdf files
            timestepPCR = currTimeStep.timeStepPCR
            if self.outDailyTotNC[0] != "None":
                for var in self.outDailyTotNC:
                    self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_dailyTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,timestepPCR-1)

            # writing monthly output to netcdf files
            # -cummulative
            if self.outMonthTotNC[0] != "None":
                for var in self.outMonthTotNC:

                    # introduce variables at the beginning of simulation or
                    #     reset variables at the beginning of the month
                    if currTimeStep.timeStepPCR == 1 or \
                       currTimeStep.day == 1:                        \
                                               vars(self)[var+'MonthTot'] = pcr.scalar(0.0)

                    # accumulating
                    vars(self)[var + 'MonthTot'] += vars(self)[var]

                    # reporting at the end of the month:
                    if currTimeStep.endMonth == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'MonthTot'),\
                           vos.MV),timeStamp,currTimeStep.monthIdx-1)
            # -average
            if self.outMonthAvgNC[0] != "None":
                for var in self.outMonthAvgNC:
                    # only if a accumulator variable has not been defined:
                    if var not in self.outMonthTotNC:

                        # introduce accumulator at the beginning of simulation or
                        #     reset accumulator at the beginning of the month
                        if currTimeStep.timeStepPCR == 1 or \
                           currTimeStep.day == 1:                            \
                                                       vars(self)[var+'MonthTot'] = pcr.scalar(0.0)
                        # accumulating
                        vars(self)[var + 'MonthTot'] += vars(self)[var]

                    # calculating average & reporting at the end of the month:
                    if currTimeStep.endMonth == True:
                        vars(self)[var+'MonthAvg'] = vars(self)[var+'MonthTot']/\
                                                     currTimeStep.day
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthAvg.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'MonthAvg'),\
                           vos.MV),timeStamp,currTimeStep.monthIdx-1)
            #
            # -last day of the month
            if self.outMonthEndNC[0] != "None":
                for var in self.outMonthEndNC:
                    # reporting at the end of the month:
                    if currTimeStep.endMonth == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthEnd.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,currTimeStep.monthIdx-1)

            # writing yearly output to netcdf files
            # -cummulative
            if self.outAnnuaTotNC[0] != "None":
                for var in self.outAnnuaTotNC:

                    # introduce variables at the beginning of simulation or
                    #     reset variables at the beginning of the month
                    if currTimeStep.timeStepPCR == 1 or \
                       currTimeStep.doy == 1:                        \
                                               vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0)

                    # accumulating
                    vars(self)[var + 'AnnuaTot'] += vars(self)[var]

                    # reporting at the end of the year:
                    if currTimeStep.endYear == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'AnnuaTot'),\
                           vos.MV),timeStamp,currTimeStep.annuaIdx-1)
            # -average
            if self.outAnnuaAvgNC[0] != "None":
                for var in self.outAnnuaAvgNC:
                    # only if a accumulator variable has not been defined:
                    if var not in self.outAnnuaTotNC:
                        # introduce accumulator at the beginning of simulation or
                        #     reset accumulator at the beginning of the year
                        if currTimeStep.timeStepPCR == 1 or \
                           currTimeStep.doy == 1:                            \
                                                       vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0)
                        # accumulating
                        vars(self)[var + 'AnnuaTot'] += vars(self)[var]
                    #
                    # calculating average & reporting at the end of the year:
                    if currTimeStep.endYear == True:
                        vars(self)[var+'AnnuaAvg'] = vars(self)[var+'AnnuaTot']/\
                                                     currTimeStep.doy
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaAvg.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'AnnuaAvg'),\
                           vos.MV),timeStamp,currTimeStep.annuaIdx-1)
            #
            # -last day of the year
            if self.outAnnuaEndNC[0] != "None":
                for var in self.outAnnuaEndNC:
                    # reporting at the end of the year:
                    if currTimeStep.endYear == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaEnd.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,currTimeStep.annuaIdx-1)
Esempio n. 12
0
    def set_river_package(self, discharge, currTimeStep):

        logger.info("Set the river package.")
        
        # - surface water river bed/bottom elevation and conductance 
        need_to_define_surface_water_bed = False
        if currTimeStep == None:
            # this is for a steady state simulation (no currTimeStep define)
            need_to_define_surface_water_bed = True
        else:    
            # only at the first month of the model simulation or the first month of the year
            if self.firstMonthOfSimulation or currTimeStep.month == 1:
                need_to_define_surface_water_bed = True
                self.firstMonthOfSimulation = False          # This part becomes False as we don't need it anymore. 

        if need_to_define_surface_water_bed:

            logger.info("Estimating the surface water bed elevation and surface water bed conductance.")
        
            #~ # - for lakes and resevoirs, alternative 1: make the bottom elevation deep --- Shall we do this? 
            #~ additional_depth = 500.
            #~ surface_water_bed_elevation = pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, \
                                                     #~ self.dem_riverbed - additional_depth)
            #
            # - for lakes and resevoirs, estimate bed elevation from dem and bankfull depth
            surface_water_bed_elevation  = pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, self.dem_average)
            surface_water_bed_elevation  = pcr.areaaverage(surface_water_bed_elevation, self.WaterBodies.waterBodyIds)
            surface_water_bed_elevation -= pcr.areamaximum(self.bankfull_depth, self.WaterBodies.waterBodyIds) 
            #
            surface_water_bed_elevation  = pcr.cover(surface_water_bed_elevation, self.dem_riverbed)
            #~ surface_water_bed_elevation = self.dem_riverbed # This is an alternative, if we do not want to introduce very deep bottom elevations of lakes and/or reservoirs.   
            #
            # rounding values for surface_water_bed_elevation
            self.surface_water_bed_elevation = pcr.roundup(surface_water_bed_elevation * 1000.)/1000.
            #
            # - river bed condutance (unit: m2/day)
            bed_surface_area = pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, \
                                                     self.WaterBodies.fracWat * self.cellAreaMap)   # TODO: Incorporate the concept of dynamicFracWat # I have problem with the convergence if I use this one. 
            bed_surface_area = pcr.min(bed_surface_area,\
                               pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, \
                                          pcr.areaaverage(self.bankfull_width * self.channelLength, self.WaterBodies.waterBodyIds)))
            bed_surface_area = pcr.cover(bed_surface_area, \
                                         self.bankfull_width * self.channelLength)
            #~ bed_surface_area = self.bankfull_width * self.channelLength
            bed_conductance = (1.0/self.bed_resistance) * bed_surface_area
            bed_conductance = pcr.ifthenelse(bed_conductance < 1e-20, 0.0, \
                                             bed_conductance) 
            self.bed_conductance = pcr.cover(bed_conductance, 0.0)
             

            logger.info("Estimating outlet widths of lakes and/or reservoirs.")
            # - 'channel width' for lakes and reservoirs 
            channel_width = pcr.areamaximum(self.bankfull_width, self.WaterBodies.waterBodyIds)
            self.channel_width = pcr.cover(channel_width, self.bankfull_width)
        

        logger.info("Estimating surface water elevation.")
        
        # - convert discharge value to surface water elevation (m)
        river_water_height = (self.channel_width**(-3/5)) * (discharge**(3/5)) * ((self.gradient)**(-3/10)) *(self.manningsN**(3/5))
        surface_water_elevation = self.dem_riverbed + \
                                  river_water_height
        #
        # - calculating water level (unit: m) above the flood plain   # TODO: Improve this concept (using Rens's latest innundation scheme) 
        #----------------------------------------------------------
        water_above_fpl  = pcr.max(0.0, surface_water_elevation - self.dem_floodplain)  # unit: m, water level above the floodplain (not distributed)
        water_above_fpl *= self.bankfull_depth * self.bankfull_width / self.cellAreaMap  # unit: m, water level above the floodplain (distributed within the cell)
        # TODO: Improve this concept using Rens's latest scheme
        #
        # - corrected surface water elevation
        surface_water_elevation = pcr.ifthenelse(surface_water_elevation > self.dem_floodplain, \
                                                                           self.dem_floodplain + water_above_fpl, \
                                                                           surface_water_elevation)
        # - surface water elevation for lakes and reservoirs:
        lake_reservoir_water_elevation = pcr.ifthen(self.WaterBodies.waterBodyOut, surface_water_elevation)
        lake_reservoir_water_elevation = pcr.areamaximum(lake_reservoir_water_elevation, self.WaterBodies.waterBodyIds)
        lake_reservoir_water_elevation = pcr.cover(lake_reservoir_water_elevation, \
                                         pcr.areaaverage(surface_water_elevation, self.WaterBodies.waterBodyIds))
        # - maximum and minimum values for lake_reservoir_water_elevation
        lake_reservoir_water_elevation = pcr.min(self.dem_floodplain, lake_reservoir_water_elevation)
        lake_reservoir_water_elevation = pcr.max(self.surface_water_bed_elevation, lake_reservoir_water_elevation)
        # - smoothing
        lake_reservoir_water_elevation = pcr.areaaverage(surface_water_elevation, self.WaterBodies.waterBodyIds)
        # 
        # - merge lake and reservoir water elevation
        surface_water_elevation = pcr.cover(lake_reservoir_water_elevation, surface_water_elevation)
        #
        # - covering the missing values and rounding
        surface_water_elevation = pcr.cover(surface_water_elevation, self.surface_water_bed_elevation)
        surface_water_elevation = pcr.rounddown(surface_water_elevation * 1000.)/1000.
        #
        # - make sure that HRIV >= RBOT ; no infiltration if HRIV = RBOT (and h < RBOT)  
        self.surface_water_elevation = pcr.max(surface_water_elevation, self.surface_water_bed_elevation)
        #
        # - pass the values to the RIV package 
        self.pcr_modflow.setRiver(self.surface_water_elevation, self.surface_water_bed_elevation, self.bed_conductance, 1)
Esempio n. 13
0
def waterAbstractionAndAllocation(water_demand_volume,available_water_volume,allocation_zones,\
                                  zone_area = None,
                                  high_volume_treshold = 1000000.,
                                  debug_water_balance = True,\
                                  extra_info_for_water_balance_reporting = "",
                                  ignore_small_values = True):

    logger.debug("Allocation of abstraction.")

    # demand volume in each cell (unit: m3)
    if ignore_small_values:  # ignore small values to avoid runding error
        cellVolDemand = pcr.rounddown(pcr.max(0.0, water_demand_volume))
    else:
        cellVolDemand = pcr.max(0.0, water_demand_volume)

    # total demand volume in each zone/segment (unit: m3)
    zoneVolDemand = pcr.areatotal(cellVolDemand, allocation_zones)

    # total available water volume in each cell
    if ignore_small_values:  # ignore small values to avoid runding error
        cellAvlWater = pcr.rounddown(pcr.max(0.00, available_water_volume))
    else:
        cellAvlWater = pcr.max(0.00, available_water_volume)

    # total available water volume in each zone/segment (unit: m3)
    # - to minimize numerical errors, separating cellAvlWater
    if not isinstance(high_volume_treshold, types.NoneType):
        # mask: 0 for small volumes ; 1 for large volumes (e.g. in lakes and reservoirs)
        mask = pcr.cover(\
               pcr.ifthen(cellAvlWater > high_volume_treshold, pcr.boolean(1)), pcr.boolean(0))
        zoneAvlWater = pcr.areatotal(pcr.ifthenelse(mask, 0.0, cellAvlWater),
                                     allocation_zones)
        zoneAvlWater += pcr.areatotal(pcr.ifthenelse(mask, cellAvlWater, 0.0),
                                      allocation_zones)
    else:
        zoneAvlWater = pcr.areatotal(cellAvlWater, allocation_zones)

    # total actual water abstraction volume in each zone/segment (unit: m3)
    # - limited to available water
    zoneAbstraction = pcr.min(zoneAvlWater, zoneVolDemand)

    # actual water abstraction volume in each cell (unit: m3)
    cellAbstraction = getValDivZero(\
                      cellAvlWater, zoneAvlWater, smallNumber)*zoneAbstraction
    cellAbstraction = pcr.min(cellAbstraction, cellAvlWater)
    if ignore_small_values:  # ignore small values to avoid runding error
        cellAbstraction = pcr.rounddown(pcr.max(0.00, cellAbstraction))
    # to minimize numerical errors, separating cellAbstraction
    if not isinstance(high_volume_treshold, types.NoneType):
        # mask: 0 for small volumes ; 1 for large volumes (e.g. in lakes and reservoirs)
        mask = pcr.cover(\
               pcr.ifthen(cellAbstraction > high_volume_treshold, pcr.boolean(1)), pcr.boolean(0))
        zoneAbstraction = pcr.areatotal(
            pcr.ifthenelse(mask, 0.0, cellAbstraction), allocation_zones)
        zoneAbstraction += pcr.areatotal(
            pcr.ifthenelse(mask, cellAbstraction, 0.0), allocation_zones)
    else:
        zoneAbstraction = pcr.areatotal(cellAbstraction, allocation_zones)

    # allocation water to meet water demand (unit: m3)
    cellAllocation  = getValDivZero(\
                      cellVolDemand, zoneVolDemand, smallNumber)*zoneAbstraction

    #~ # extraAbstraction to minimize numerical errors:
    #~ zoneDeficitAbstraction = pcr.max(0.0,\
    #~ pcr.areatotal(cellAllocation , allocation_zones) -\
    #~ pcr.areatotal(cellAbstraction, allocation_zones))
    #~ remainingCellAvlWater = pcr.max(0.0, cellAvlWater - cellAbstraction)
    #~ cellAbstraction      += zoneDeficitAbstraction * getValDivZero(\
    #~ remainingCellAvlWater,
    #~ pcr.areatotal(remainingCellAvlWater, allocation_zones),
    #~ smallNumber)
    #~ #
    #~ # extraAllocation to minimize numerical errors:
    #~ zoneDeficitAllocation = pcr.max(0.0,\
    #~ pcr.areatotal(cellAbstraction, allocation_zones) -\
    #~ pcr.areatotal(cellAllocation , allocation_zones))
    #~ remainingCellDemand = pcr.max(0.0, cellVolDemand - cellAllocation)
    #~ cellAllocation     += zoneDeficitAllocation * getValDivZero(\
    #~ remainingCellDemand,
    #~ pcr.areatotal(remainingCellDemand, allocation_zones),
    #~ smallNumber)

    if debug_water_balance and not isinstance(zone_area, types.NoneType):

        zoneAbstraction = pcr.cover(
            pcr.areatotal(cellAbstraction, allocation_zones) / zone_area, 0.0)
        zoneAllocation = pcr.cover(
            pcr.areatotal(cellAllocation, allocation_zones) / zone_area, 0.0)

        waterBalanceCheck([zoneAbstraction],\
                          [zoneAllocation],\
                          [pcr.scalar(0.0)],\
                          [pcr.scalar(0.0)],\
                          'abstraction - allocation per zone/segment (PS: Error here may be caused by rounding error.)' ,\
                           True,\
                           extra_info_for_water_balance_reporting,threshold=1e-4)

    return cellAbstraction, cellAllocation
Esempio n. 14
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, type(None)):
            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.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.0) * 1.0
        )  # 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)
Esempio n. 15
0
    def update(self,landSurface,routing,currTimeStep):

        if self.debugWaterBalance:
            preStorGroundwater       = self.storGroundwater
            preStorGroundwaterFossil = self.storGroundwaterFossil
                
        # get riverbed infiltration from the previous time step (from routing)
        self.surfaceWaterInf  = routing.riverbedExchange/routing.cellArea     # m
        self.storGroundwater += self.surfaceWaterInf

        # get net recharge (percolation-capRise) and update storage:
        self.storGroundwater  = pcr.max(0.,\
                                self.storGroundwater + landSurface.gwRecharge)         
                        
        # potential groundwater abstraction (unit: m)
        potGroundwaterAbstract = landSurface.totalPotentialGrossDemand -\
                                 landSurface.allocSurfaceWaterAbstract 


        if self.usingAllocSegments == False or self.limitAbstraction:   
             
            # Note: For simplicity, no network for a run with limitAbstraction. 
        
            logger.info("Groundwater abstraction is only to satisfy local demand. No network for distributing groundwater.")

            # nonFossil groundwater abstraction (unit: m) to fulfill water demand 
            # - assumption: Groundwater is only abstracted to satisfy local demand.
            self.nonFossilGroundwaterAbs = \
                                           pcr.max(0.0,
                                           pcr.min(self.storGroundwater,\
                                           potGroundwaterAbstract)) 
            #
            self.allocNonFossilGroundwater = self.nonFossilGroundwaterAbs
        
        if self.usingAllocSegments and self.limitAbstraction == False:

            # Note: Incorporating distribution network of groundwater source is possible only if limitAbstraction = False.  

            logger.info("Using groundwater source allocation.")

            # gross/potential demand volume in each cell (unit: m3)
            cellVolGrossDemand = potGroundwaterAbstract*routing.cellArea
            
            # total gross demand volume in each segment/zone (unit: m3)
            segTtlGrossDemand  = pcr.areatotal(cellVolGrossDemand, self.allocSegments)
            
            # total available groundwater water volume in each cell - ignore small values (less than 1 m3)
            cellAvlGroundwater = pcr.max(0.00, self.storGroundwater* routing.cellArea)
            cellAvlGroundwater = pcr.rounddown( cellAvlGroundwater/1.)*1.
            
            # total available surface water volume in each segment/zone  (unit: m3)
            segAvlGroundwater  = pcr.areatotal(cellAvlGroundwater, self.allocSegments)
            segAvlGroundwater  = pcr.max(0.00,  segAvlGroundwater)
            
            # total actual surface water abstraction volume in each segment/zone (unit: m3)
            #
            # - not limited to available water - ignore small values (less than 1 m3)
            segActGroundwaterAbs = pcr.max(0.0,\
                                   pcr.rounddown(segTtlGrossDemand))
            # 
            # - limited to available water
            segActGroundwaterAbs = pcr.min(segAvlGroundwater, segActGroundwaterAbs)
            
            # actual surface water abstraction volume in each cell (unit: m3)
            volActGroundwaterAbstract = vos.getValDivZero(\
                                        cellAvlGroundwater, segAvlGroundwater, vos.smallNumber) * \
                                        segActGroundwaterAbs                                                 
            volActGroundwaterAbstract = pcr.min(cellAvlGroundwater , volActGroundwaterAbstract)              # unit: m3
            
            # actual non fossil groundwater abstraction volume in meter (unit: m)
            self.nonFossilGroundwaterAbs = pcr.ifthen(self.landmask, volActGroundwaterAbstract) /\
                                                                     routing.cellArea                        # unit: m
            
            # allocation non fossil groundwater abstraction volume to each cell (unit: m3)
            self.volAllocGroundwaterAbstract = vos.getValDivZero(\
                                               cellVolGrossDemand, segTtlGrossDemand, vos.smallNumber) *\
                                               segActGroundwaterAbs                                          # unit: m3 
            
            # allocation surface water abstraction in meter (unit: m)
            self.allocNonFossilGroundwater   = pcr.ifthen(self.landmask, self.volAllocGroundwaterAbstract)/\
                                                                         routing.cellArea                    # unit: m

            if self.debugWaterBalance == str('True'):
    
                abstraction = pcr.cover(pcr.areatotal(self.nonFossilGroundwaterAbs  *routing.cellArea, self.allocSegments)/self.segmentArea, 0.0)
                allocation  = pcr.cover(pcr.areatotal(self.allocNonFossilGroundwater*routing.cellArea, self.allocSegments)/self.segmentArea, 0.0)
            
                vos.waterBalanceCheck([abstraction],\
                                      [allocation],\
                                      [pcr.scalar(0.0)],\
                                      [pcr.scalar(0.0)],\
                                      'non fossil groundwater abstraction - allocation per zone/segment (PS: Error here may be caused by rounding error.)' ,\
                                       True,\
                                       "",threshold=5e-4)

        # update storGoundwater after self.nonFossilGroundwaterAbs
        self.storGroundwater  = pcr.max(0.,self.storGroundwater - self.nonFossilGroundwaterAbs)

        # unmetDemand (m), satisfied by fossil gwAbstractions           # TODO: Include desalinization
        self.unmetDemand = pcr.max(0.0,
                           potGroundwaterAbstract - \
                           self.allocNonFossilGroundwater)              # m (equal to zero if limitAbstraction = True)
        
        if self.limitAbstraction:
            logger.info("No fossil groundwater abstraction is allowed")
            # TODO: check that self.unmetDemand = 0.0

        # correcting unmetDemand with available fossil groundwater
        # Note: For simplicity, limitFossilGroundwaterAbstraction can only be combined with local source assumption
        if self.usingAllocSegments == False and self.limitFossilGroundwaterAbstraction:
            self.unmetDemand = pcr.min(pcr.max(0.0, self.storGroundwaterFossil), self.unmetDemand)

        # calculate the average groundwater abstraction (m/day) from the last 365 days:
        totalAbstraction    = self.unmetDemand + self.nonFossilGroundwaterAbs
        deltaAbstraction    = totalAbstraction - self.avgAbstraction  
        self.avgAbstraction = self.avgAbstraction +\
                                 deltaAbstraction/\
                              pcr.min(365., pcr.max(1.0, routing.timestepsToAvgDischarge))
        self.avgAbstraction = pcr.max(0.0, self.avgAbstraction)                                    

        # update storGroundwaterFossil after unmetDemand 
        self.storGroundwaterFossil -= self.unmetDemand
        
        # calculate baseflow and update storage:
        self.baseflow         = pcr.max(0.,\
                                pcr.min(self.storGroundwater,\
                                        self.recessionCoeff* \
                                        self.storGroundwater))
        self.storGroundwater  = pcr.max(0.,\
                                self.storGroundwater - self.baseflow)
        # PS: baseflow must be calculated at the end (to ensure the availability of storGroundwater to support nonFossilGroundwaterAbs)


        if self.debugWaterBalance:
            vos.waterBalanceCheck([self.surfaceWaterInf,\
                                   landSurface.gwRecharge],\
                                  [self.baseflow,\
                                   self.nonFossilGroundwaterAbs],\
                                  [  preStorGroundwater],\
                                  [self.storGroundwater],\
                                       'storGroundwater',\
                                   True,\
                                   currTimeStep.fulldate,threshold=1e-4)

        if self.debugWaterBalance:
            vos.waterBalanceCheck([pcr.scalar(0.0)],\
                                  [self.unmetDemand],\
                                  [  preStorGroundwaterFossil],\
                                  [self.storGroundwaterFossil],\
                                       'storGroundwaterFossil',\
                                   True,\
                                   currTimeStep.fulldate,threshold=1e-3)

        if self.debugWaterBalance and self.limitFossilGroundwaterAbstraction:
            vos.waterBalanceCheck([pcr.scalar(0.0)],\
                                  [self.unmetDemand],\
                                  [pcr.max(0.0,  preStorGroundwaterFossil)],\
                                  [pcr.max(0.0,self.storGroundwaterFossil)],\
                                       'storGroundwaterFossil (with limitFossilGroundwaterAbstraction)',\
                                   True,\
                                   currTimeStep.fulldate,threshold=1e-3)

        if self.debugWaterBalance and landSurface.limitAbstraction:
            vos.waterBalanceCheck([potGroundwaterAbstract],\
                                  [self.nonFossilGroundwaterAbs],\
                                  [pcr.scalar(0.)],\
                                  [pcr.scalar(0.)],\
                                  'non fossil groundwater abstraction',\
                                   True,\
                                   currTimeStep.fulldate,threshold=1e-4)

        if self.debugWaterBalance:
            vos.waterBalanceCheck([self.unmetDemand, self.allocNonFossilGroundwater, landSurface.allocSurfaceWaterAbstract],\
                                  [landSurface.totalPotentialGrossDemand],\
                                  [pcr.scalar(0.)],\
                                  [pcr.scalar(0.)],\
                                  'water demand allocation (from surface water, groundwater and unmetDemand)',\
                                   True,\
                                   currTimeStep.fulldate,threshold=1e-4)


        if self.report == True:
            timeStamp = datetime.datetime(currTimeStep.year,\
                                          currTimeStep.month,\
                                          currTimeStep.day,\
                                          0)
            # writing daily output to netcdf files
            timestepPCR = currTimeStep.timeStepPCR
            if self.outDailyTotNC[0] != "None":
                for var in self.outDailyTotNC:
                    self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_dailyTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,timestepPCR-1)

            # writing monthly output to netcdf files
            # -cummulative
            if self.outMonthTotNC[0] != "None":
                for var in self.outMonthTotNC:

                    # introduce variables at the beginning of simulation or
                    #     reset variables at the beginning of the month
                    if currTimeStep.timeStepPCR == 1 or \
                       currTimeStep.day == 1:\
                       vars(self)[var+'MonthTot'] = pcr.scalar(0.0)

                    # accumulating
                    vars(self)[var+'MonthTot'] += vars(self)[var]

                    # reporting at the end of the month:
                    if currTimeStep.endMonth == True: 
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'MonthTot'),\
                           vos.MV),timeStamp,currTimeStep.monthIdx-1)
            # -average
            if self.outMonthAvgNC[0] != "None":
                for var in self.outMonthAvgNC:
                    # only if a accumulator variable has not been defined: 
                    if var not in self.outMonthTotNC: 

                        # introduce accumulator at the beginning of simulation or
                        #     reset accumulator at the beginning of the month
                        if currTimeStep.timeStepPCR == 1 or \
                           currTimeStep.day == 1:\
                           vars(self)[var+'MonthTot'] = pcr.scalar(0.0)
                        # accumulating
                        vars(self)[var+'MonthTot'] += vars(self)[var]

                    # calculating average & reporting at the end of the month:
                    if currTimeStep.endMonth == True:
                        vars(self)[var+'MonthAvg'] = vars(self)[var+'MonthTot']/\
                                                     currTimeStep.day  
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthAvg.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'MonthAvg'),\
                           vos.MV),timeStamp,currTimeStep.monthIdx-1)
            #
            # -last day of the month
            if self.outMonthEndNC[0] != "None":
                for var in self.outMonthEndNC:
                    # reporting at the end of the month:
                    if currTimeStep.endMonth == True: 
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthEnd.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,currTimeStep.monthIdx-1)

            # writing yearly output to netcdf files
            # -cummulative
            if self.outAnnuaTotNC[0] != "None":
                for var in self.outAnnuaTotNC:

                    # introduce variables at the beginning of simulation or
                    #     reset variables at the beginning of the month
                    if currTimeStep.timeStepPCR == 1 or \
                       currTimeStep.doy == 1:\
                       vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0)

                    # accumulating
                    vars(self)[var+'AnnuaTot'] += vars(self)[var]

                    # reporting at the end of the year:
                    if currTimeStep.endYear == True: 
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'AnnuaTot'),\
                           vos.MV),timeStamp,currTimeStep.annuaIdx-1)
            # -average
            if self.outAnnuaAvgNC[0] != "None":
                for var in self.outAnnuaAvgNC:
                    # only if a accumulator variable has not been defined: 
                    if var not in self.outAnnuaTotNC: 
                        # introduce accumulator at the beginning of simulation or
                        #     reset accumulator at the beginning of the year
                        if currTimeStep.timeStepPCR == 1 or \
                           currTimeStep.doy == 1:\
                           vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0)
                        # accumulating
                        vars(self)[var+'AnnuaTot'] += vars(self)[var]
                    #
                    # calculating average & reporting at the end of the year:
                    if currTimeStep.endYear == True:
                        vars(self)[var+'AnnuaAvg'] = vars(self)[var+'AnnuaTot']/\
                                                     currTimeStep.doy  
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaAvg.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'AnnuaAvg'),\
                           vos.MV),timeStamp,currTimeStep.annuaIdx-1)
            #
            # -last day of the year
            if self.outAnnuaEndNC[0] != "None":
                for var in self.outAnnuaEndNC:
                    # reporting at the end of the year:
                    if currTimeStep.endYear == True: 
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaEnd.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,currTimeStep.annuaIdx-1)
def returnPrecision(pcrMap,precisionValue= -6.):
  #-returns the precision of a PCRaster map relative to the log10 base
  # specified by the precisionValue
  return 10.**(precisionValue+pcr.rounddown(pcr.log10(pcrMap)))
Esempio n. 17
0
    def read_forcings(self, currTimeStep):

        # reading precipitation:
        if self.precipitation_set_per_year:
            #~ print currTimeStep.year
            nc_file_per_year = self.preFileNC % (float(
                currTimeStep.year), float(currTimeStep.year))
            self.precipitation = vos.netcdf2PCRobjClone(\
                                      nc_file_per_year, 'precipitation',\
                                      str(currTimeStep.fulldate),
                                      useDoy = None,
                                      cloneMapFileName = self.cloneMap,\
                                      LatitudeLongitude = True)
        else:
            #self.precipitation = vos.netcdf2PCRobjClone(\
            #                          self.preFileNC, 'precipitation',\
            #                          str(currTimeStep.fulldate),
            #                          useDoy = None,
            #                          cloneMapFileName = self.cloneMap,\
            #                          LatitudeLongitude = True)

            # reading precip when ISI-MIP is used
            precipitation = vos.netcdf2PCRobjClone(\
                                      self.preFileNC, 'pr',\
                                      str(currTimeStep.fulldate),
                                      useDoy = None,
                                      cloneMapFileName = self.cloneMap,\
                                      LatitudeLongitude = True)
            # unit original km m-2 s-1 to m d-1
            # soortelijk gewicht water = 998 km/m3
        self.precipitation = (precipitation / 998.0) * (60. * 60. * 24)

        precipitationCorrectionFactor = pcr.scalar(
            1.0
        )  # Since 19 Feb 2014, Edwin removed the support for correcting precipitation.
        self.precipitation = pcr.max(0.,self.precipitation*\
                precipitationCorrectionFactor)
        self.precipitation = pcr.cover(self.precipitation, 0.0)

        # ignore very small values of precipitation (less than 0.00001 m/day or less than 0.01 kg.m-2.day-1 )
        if self.usingDailyTimeStepForcingData:
            self.precipitation = pcr.rounddown(
                self.precipitation * 100000.) / 100000.

        # reading temperature
        if self.temperature_set_per_year:
            nc_file_per_year = self.tmpFileNC % (int(
                currTimeStep.year), int(currTimeStep.year))
            self.temperature = vos.netcdf2PCRobjClone(\
                                      nc_file_per_year, 'temperature',\
                                      str(currTimeStep.fulldate),
                                      useDoy = None,
                                      cloneMapFileName = self.cloneMap,\
                                      LatitudeLongitude = True)
        else:
            # updated to temp when using ISI-MIP projection
            temperature = vos.netcdf2PCRobjClone(\
                                 self.tmpFileNC,'tas',\
                                 str(currTimeStep.fulldate),
                                 useDoy = None,
                                 cloneMapFileName=self.cloneMap,\
                                 LatitudeLongitude = True)
# unit K to C
        self.temperature = temperature - 273.15

        # Downscaling precipitation and temperature
        if self.downscalePrecipitationOption:
            self.downscalePrecipitation(currTimeStep)
        if self.downscaleTemperatureOption:
            self.downscaleTemperature(currTimeStep)

        # calculate or obtain referencePotET
        if self.refETPotMethod == 'Hamon':            self.referencePotET = \
   refPotET.HamonPotET(self.temperature,\
                       currTimeStep.doy,\
                       self.latitudes)
        if self.refETPotMethod == 'Input':
            if self.refETPotFileNC_set_per_year:
                nc_file_per_year = self.etpFileNC % (int(
                    currTimeStep.year), int(currTimeStep.year))
                self.referencePotET = vos.netcdf2PCRobjClone(\
                                      nc_file_per_year, 'evapotranspiration',\
                                      str(currTimeStep.fulldate),
                                      useDoy = None,
                                      cloneMapFileName = self.cloneMap,\
                                      LatitudeLongitude = True)
            else:
                self.referencePotET = vos.netcdf2PCRobjClone(\
                                      self.etpFileNC,'evapotranspiration',\
                                      str(currTimeStep.fulldate),
                                      useDoy = None,
                                      cloneMapFileName=self.cloneMap,\
                                      LatitudeLongitude = True)

        # Downscaling referenceETPot (based on temperature)
        if self.downscaleReferenceETPotOption: self.downscaleReferenceETPot()

        # smoothing:
        if self.forcingSmoothing == True:
            logger.debug("Forcing data are smoothed.")
            self.precipitation = pcr.windowaverage(self.precipitation,
                                                   self.smoothingWindowsLength)
            self.temperature = pcr.windowaverage(self.temperature,
                                                 self.smoothingWindowsLength)
            self.referencePotET = pcr.windowaverage(
                self.referencePotET, self.smoothingWindowsLength)

        # make sure precipitation is always positive:
        self.precipitation = pcr.max(0.0, self.precipitation)

        # rounding temperature values to minimize numerical errors (note only to minimize, not remove)
        self.temperature = pcr.roundoff(self.temperature * 1000.) / 1000.

        # ignore snow by setting temperature to 25 deg C
        if self.ignore_snow: self.temperature = pcr.spatial(pcr.scalar(25.))

        # define precipitation, temperature and referencePotET ONLY at landmask area (for reporting):
        self.precipitation = pcr.ifthen(self.landmask, self.precipitation)
        self.temperature = pcr.ifthen(self.landmask, self.temperature)
        self.referencePotET = pcr.ifthen(self.landmask, self.referencePotET)

        if self.report == True:
            timeStamp = datetime.datetime(currTimeStep.year,\
                                          currTimeStep.month,\
                                          currTimeStep.day,\
                                          0)
            # writing daily output to netcdf files
            timestepPCR = currTimeStep.timeStepPCR
            if self.outDailyTotNC[0] != "None":
                for var in self.outDailyTotNC:
                    self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_dailyTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,timestepPCR-1)

            # writing monthly output to netcdf files
            # -cummulative
            if self.outMonthTotNC[0] != "None":
                for var in self.outMonthTotNC:

                    # introduce variables at the beginning of simulation or
                    #     reset variables at the beginning of the month
                    if currTimeStep.timeStepPCR == 1 or \
                       currTimeStep.day == 1:                        \
                                               vars(self)[var+'MonthTot'] = pcr.scalar(0.0)

                    # accumulating
                    vars(self)[var + 'MonthTot'] += vars(self)[var]

                    # reporting at the end of the month:
                    if currTimeStep.endMonth == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'MonthTot'),\
                           vos.MV),timeStamp,currTimeStep.monthIdx-1)
            # -average
            if self.outMonthAvgNC[0] != "None":
                for var in self.outMonthAvgNC:
                    # only if a accumulator variable has not been defined:
                    if var not in self.outMonthTotNC:

                        # introduce accumulator at the beginning of simulation or
                        #     reset accumulator at the beginning of the month
                        if currTimeStep.timeStepPCR == 1 or \
                           currTimeStep.day == 1:                            \
                                                       vars(self)[var+'MonthTot'] = pcr.scalar(0.0)
                        # accumulating
                        vars(self)[var + 'MonthTot'] += vars(self)[var]

                    # calculating average & reporting at the end of the month:
                    if currTimeStep.endMonth == True:
                        vars(self)[var+'MonthAvg'] = vars(self)[var+'MonthTot']/\
                                                     currTimeStep.day
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthAvg.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'MonthAvg'),\
                           vos.MV),timeStamp,currTimeStep.monthIdx-1)
            #
            # -last day of the month
            if self.outMonthEndNC[0] != "None":
                for var in self.outMonthEndNC:
                    # reporting at the end of the month:
                    if currTimeStep.endMonth == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_monthEnd.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,currTimeStep.monthIdx-1)

            # writing yearly output to netcdf files
            # -cummulative
            if self.outAnnuaTotNC[0] != "None":
                for var in self.outAnnuaTotNC:

                    # introduce variables at the beginning of simulation or
                    #     reset variables at the beginning of the month
                    if currTimeStep.timeStepPCR == 1 or \
                       currTimeStep.doy == 1:                        \
                                               vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0)

                    # accumulating
                    vars(self)[var + 'AnnuaTot'] += vars(self)[var]

                    # reporting at the end of the year:
                    if currTimeStep.endYear == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaTot.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'AnnuaTot'),\
                           vos.MV),timeStamp,currTimeStep.annuaIdx-1)
            # -average
            if self.outAnnuaAvgNC[0] != "None":
                for var in self.outAnnuaAvgNC:
                    # only if a accumulator variable has not been defined:
                    if var not in self.outAnnuaTotNC:
                        # introduce accumulator at the beginning of simulation or
                        #     reset accumulator at the beginning of the year
                        if currTimeStep.timeStepPCR == 1 or \
                           currTimeStep.doy == 1:                            \
                                                       vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0)
                        # accumulating
                        vars(self)[var + 'AnnuaTot'] += vars(self)[var]
                    #
                    # calculating average & reporting at the end of the year:
                    if currTimeStep.endYear == True:
                        vars(self)[var+'AnnuaAvg'] = vars(self)[var+'AnnuaTot']/\
                                                     currTimeStep.doy
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaAvg.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var+'AnnuaAvg'),\
                           vos.MV),timeStamp,currTimeStep.annuaIdx-1)
            #
            # -last day of the year
            if self.outAnnuaEndNC[0] != "None":
                for var in self.outAnnuaEndNC:
                    # reporting at the end of the year:
                    if currTimeStep.endYear == True:
                        self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \
                                         str(var)+"_annuaEnd.nc",\
                                         var,\
                          pcr2numpy(self.__getattribute__(var),vos.MV),\
                                         timeStamp,currTimeStep.annuaIdx-1)
    def set_river_package(self, discharge):

        logger.info("Set the river package.")

        # specify the river package
        #
        # - surface water river bed/bottom elevation
        #
        # - for lakes and resevoirs, make the bottom elevation deep --- Shall we do this?
        #~ additional_depth = 500.
        #~ surface_water_bed_elevation = pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, \
        #~ self.dem_riverbed - additional_depth)
        #~ surface_water_bed_elevation = pcr.cover(surface_water_bed_elevation, self.dem_riverbed)
        #
        surface_water_bed_elevation = self.dem_riverbed  # This is an alternative, if we do not want to introduce very deep bottom elevations of lakes and/or reservoirs.
        #
        # rounding values for surface_water_bed_elevation
        self.surface_water_bed_elevation = pcr.roundup(
            surface_water_bed_elevation * 1000.) / 1000.
        #
        # - river bed condutance (unit: m2/day)
        bed_surface_area = pcr.ifthen(pcr.scalar(self.WaterBodies.waterBodyIds) > 0.0, \
                                                 self.WaterBodies.fracWat * self.cellAreaMap)   # TODO: Incorporate the concept of dynamicFracWat
        bed_surface_area = pcr.cover(bed_surface_area, \
                                     self.bankfull_width * self.channelLength)
        bed_surface_area = self.bankfull_width * self.channelLength
        bed_conductance = (1.0 / self.bed_resistance) * bed_surface_area
        bed_conductance = pcr.ifthenelse(bed_conductance < 1e-20, 0.0, \
                                         bed_conductance)
        self.bed_conductance = pcr.cover(bed_conductance, 0.0)
        #
        # - 'channel width' for lakes and reservoirs
        channel_width = pcr.areamaximum(self.bankfull_width,
                                        self.WaterBodies.waterBodyIds)
        channel_width = pcr.cover(channel_width, self.bankfull_width)
        #
        # - convert discharge value to surface water elevation (m)
        river_water_height = (channel_width**(-3 / 5)) * (discharge**(
            3 / 5)) * ((self.gradient)**(-3 / 10)) * (self.manningsN**(3 / 5))
        surface_water_elevation = self.dem_riverbed + \
                                  river_water_height
        #
        # - calculating water level (unit: m) above the flood plain   # TODO: Improve this concept (using Rens's latest innundation scheme)
        #----------------------------------------------------------
        water_above_fpl = pcr.max(
            0.0, surface_water_elevation - self.dem_floodplain
        )  # unit: m, water level above the floodplain (not distributed)
        water_above_fpl *= self.bankfull_depth * self.bankfull_width / self.cellAreaMap  # unit: m, water level above the floodplain (distributed within the cell)
        # TODO: Improve this concept using Rens's latest scheme
        #
        # - corrected surface water elevation
        surface_water_elevation = pcr.ifthenelse(surface_water_elevation > self.dem_floodplain, \
                                                                           self.dem_floodplain + water_above_fpl, \
                                                                           surface_water_elevation)
        # - surface water elevation for lakes and reservoirs:
        lake_reservoir_water_elevation = pcr.ifthen(
            self.WaterBodies.waterBodyOut, surface_water_elevation)
        lake_reservoir_water_elevation = pcr.areamaximum(
            lake_reservoir_water_elevation, self.WaterBodies.waterBodyIds)
        lake_reservoir_water_elevation = pcr.cover(lake_reservoir_water_elevation, \
                                         pcr.areaaverage(surface_water_elevation, self.WaterBodies.waterBodyIds))
        # - maximum and minimum values for lake_reservoir_water_elevation
        lake_reservoir_water_elevation = pcr.min(
            self.dem_floodplain, lake_reservoir_water_elevation)
        lake_reservoir_water_elevation = pcr.max(
            surface_water_bed_elevation, lake_reservoir_water_elevation)
        # - smoothing
        lake_reservoir_water_elevation = pcr.areaaverage(
            surface_water_elevation, self.WaterBodies.waterBodyIds)
        #
        # - merge lake and reservoir water elevation
        surface_water_elevation = pcr.cover(lake_reservoir_water_elevation,
                                            surface_water_elevation)
        #
        # - pass values to the river package
        surface_water_elevation = pcr.cover(surface_water_elevation,
                                            self.surface_water_bed_elevation)
        surface_water_elevation = pcr.rounddown(
            surface_water_elevation * 1000.) / 1000.
        #
        # - make sure that HRIV >= RBOT ; no infiltration if HRIV = RBOT (and h < RBOT)
        self.surface_water_elevation = pcr.max(
            surface_water_elevation, self.surface_water_bed_elevation)
        #
        # - pass the values to the RIV package
        self.pcr_modflow.setRiver(self.surface_water_elevation, \
                                  self.surface_water_bed_elevation, self.bed_conductance, 2)
Esempio n. 19
0
def waterAbstractionAndAllocation(water_demand_volume,available_water_volume,allocation_zones,\
                                  zone_area = None,
                                  high_volume_treshold = 1000000.,
                                  debug_water_balance = True,\
                                  extra_info_for_water_balance_reporting = "",
                                  ignore_small_values = True):

    logger.debug("Allocation of abstraction.")
    
    # demand volume in each cell (unit: m3)
    if ignore_small_values: # ignore small values to avoid runding error
        cellVolDemand = pcr.rounddown(pcr.max(0.0, water_demand_volume))
    else:
        cellVolDemand = pcr.max(0.0, water_demand_volume)
    
    # total demand volume in each zone/segment (unit: m3)
    zoneVolDemand = pcr.areatotal(cellVolDemand, allocation_zones)
    
    # total available water volume in each cell
    if ignore_small_values: # ignore small values to avoid runding error
        cellAvlWater = pcr.rounddown(pcr.max(0.00, available_water_volume))
    else:
        cellAvlWater = pcr.max(0.00, available_water_volume)
    
    # total available water volume in each zone/segment (unit: m3)
    # - to minimize numerical errors, separating cellAvlWater 
    if not isinstance(high_volume_treshold,types.NoneType):
        # mask: 0 for small volumes ; 1 for large volumes (e.g. in lakes and reservoirs)
        mask = pcr.cover(\
               pcr.ifthen(cellAvlWater > high_volume_treshold, pcr.boolean(1)), pcr.boolean(0))
        zoneAvlWater  = pcr.areatotal(
                        pcr.ifthenelse(mask, 0.0, cellAvlWater), allocation_zones)
        zoneAvlWater += pcr.areatotal(                
                        pcr.ifthenelse(mask, cellAvlWater, 0.0), allocation_zones)
    else:
        zoneAvlWater  = pcr.areatotal(cellAvlWater, allocation_zones)
    
    # total actual water abstraction volume in each zone/segment (unit: m3)
    # - limited to available water
    zoneAbstraction = pcr.min(zoneAvlWater, zoneVolDemand)
    
    # actual water abstraction volume in each cell (unit: m3)
    cellAbstraction = getValDivZero(\
                      cellAvlWater, zoneAvlWater, smallNumber)*zoneAbstraction
    cellAbstraction = pcr.min(cellAbstraction, cellAvlWater)                                                                   
    if ignore_small_values: # ignore small values to avoid runding error
        cellAbstraction = pcr.rounddown(pcr.max(0.00, cellAbstraction))
    # to minimize numerical errors, separating cellAbstraction 
    if not isinstance(high_volume_treshold,types.NoneType):
        # mask: 0 for small volumes ; 1 for large volumes (e.g. in lakes and reservoirs)
        mask = pcr.cover(\
               pcr.ifthen(cellAbstraction > high_volume_treshold, pcr.boolean(1)), pcr.boolean(0))
        zoneAbstraction  = pcr.areatotal(
                           pcr.ifthenelse(mask, 0.0, cellAbstraction), allocation_zones)
        zoneAbstraction += pcr.areatotal(                
                           pcr.ifthenelse(mask, cellAbstraction, 0.0), allocation_zones)
    else:
        zoneAbstraction  = pcr.areatotal(cellAbstraction, allocation_zones)    
    
    # allocation water to meet water demand (unit: m3)
    cellAllocation  = getValDivZero(\
                      cellVolDemand, zoneVolDemand, smallNumber)*zoneAbstraction 
    
    #~ # extraAbstraction to minimize numerical errors:
    #~ zoneDeficitAbstraction = pcr.max(0.0,\
                                     #~ pcr.areatotal(cellAllocation , allocation_zones) -\
                                     #~ pcr.areatotal(cellAbstraction, allocation_zones))
    #~ remainingCellAvlWater = pcr.max(0.0, cellAvlWater - cellAbstraction)
    #~ cellAbstraction      += zoneDeficitAbstraction * getValDivZero(\
                            #~ remainingCellAvlWater, 
                            #~ pcr.areatotal(remainingCellAvlWater, allocation_zones), 
                            #~ smallNumber)                        
    #~ # 
    #~ # extraAllocation to minimize numerical errors:
    #~ zoneDeficitAllocation = pcr.max(0.0,\
                                    #~ pcr.areatotal(cellAbstraction, allocation_zones) -\
                                    #~ pcr.areatotal(cellAllocation , allocation_zones))
    #~ remainingCellDemand = pcr.max(0.0, cellVolDemand - cellAllocation)
    #~ cellAllocation     += zoneDeficitAllocation * getValDivZero(\
                          #~ remainingCellDemand, 
                          #~ pcr.areatotal(remainingCellDemand, allocation_zones), 
                          #~ smallNumber)                        
    
    if debug_water_balance and not isinstance(zone_area,types.NoneType):

        zoneAbstraction = pcr.cover(pcr.areatotal(cellAbstraction, allocation_zones)/zone_area, 0.0)
        zoneAllocation  = pcr.cover(pcr.areatotal(cellAllocation , allocation_zones)/zone_area, 0.0)
    
        waterBalanceCheck([zoneAbstraction],\
                          [zoneAllocation],\
                          [pcr.scalar(0.0)],\
                          [pcr.scalar(0.0)],\
                          'abstraction - allocation per zone/segment (PS: Error here may be caused by rounding error.)' ,\
                           True,\
                           extra_info_for_water_balance_reporting,threshold=1e-4)
    
    return cellAbstraction, cellAllocation