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

    Input:
        - ldd
        - minimum streamorder to include

    Output:
        - distance per factor cells
    """

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

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

    Input:
        - ldd
        - minimum streamorder to include

    Output:
        - distance per factor cells
    """

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

    return totdist
    def dynamic(self):
        """ dynamic part of the water use module
            init water use before sub step routing
        """
        settings = LisSettings.instance()
        option = settings.options
        binding = settings.binding
        maskinfo = MaskInfo.instance()
        if option['wateruse']:
            # ************************************************************
            # ***** READ WATER DEMAND DATA *****************************
            # ************************************************************

            if option['TransientWaterDemandChange']:
                if option['readNetcdfStack']:
                    if option['useWaterDemandAveYear']:
                        # using average year in NetCDF file format
                        self.var.DomesticDemandMM = readnetcdf(
                            binding['DomesticDemandMaps'],
                            self.var.currentTimeStep(),
                            timestampflag='closest',
                            averageyearflag=True) * self.var.DtDay
                        self.var.IndustrialDemandMM = readnetcdf(
                            binding['IndustrialDemandMaps'],
                            self.var.currentTimeStep(),
                            timestampflag='closest',
                            averageyearflag=True) * self.var.DtDay
                        self.var.LivestockDemandMM = readnetcdf(
                            binding['LivestockDemandMaps'],
                            self.var.currentTimeStep(),
                            timestampflag='closest',
                            averageyearflag=True) * self.var.DtDay
                        self.var.EnergyDemandMM = readnetcdf(
                            binding['EnergyDemandMaps'],
                            self.var.currentTimeStep(),
                            timestampflag='closest',
                            averageyearflag=True) * self.var.DtDay
                    else:
                        # Read from stack of maps in NetCDF format. Get time step corresponding to model step.
                        # added management for sub-daily model time steps
                        self.var.DomesticDemandMM = readnetcdf(
                            binding['DomesticDemandMaps'],
                            self.var.currentTimeStep(),
                            timestampflag='closest') * self.var.DtDay
                        self.var.IndustrialDemandMM = readnetcdf(
                            binding['IndustrialDemandMaps'],
                            self.var.currentTimeStep(),
                            timestampflag='closest') * self.var.DtDay
                        self.var.LivestockDemandMM = readnetcdf(
                            binding['LivestockDemandMaps'],
                            self.var.currentTimeStep(),
                            timestampflag='closest') * self.var.DtDay
                        self.var.EnergyDemandMM = readnetcdf(
                            binding['EnergyDemandMaps'],
                            self.var.currentTimeStep(),
                            timestampflag='closest') * self.var.DtDay
                else:
                    # Read from stack of maps in Pcraster format
                    self.var.DomesticDemandMM = readmapsparse(
                        binding['DomesticDemandMaps'],
                        self.var.currentTimeStep(),
                        self.var.DomesticDemandMM) * self.var.DtDay
                    self.var.IndustrialDemandMM = readmapsparse(
                        binding['IndustrialDemandMaps'],
                        self.var.currentTimeStep(),
                        self.var.IndustrialDemandMM) * self.var.DtDay
                    self.var.LivestockDemandMM = readmapsparse(
                        binding['LivestockDemandMaps'],
                        self.var.currentTimeStep(),
                        self.var.LivestockDemandMM) * self.var.DtDay
                    self.var.EnergyDemandMM = readmapsparse(
                        binding['EnergyDemandMaps'],
                        self.var.currentTimeStep(),
                        self.var.EnergyDemandMM) * self.var.DtDay

            # ************************************************************
            # ***** LIVESTOCK ********************************************
            # ************************************************************

            self.var.LivestockAbstractionMM = self.var.LivestockDemandMM
            self.var.LivestockConsumptiveUseMM = self.var.LivestockAbstractionMM * self.var.LivestockConsumptiveUseFraction
            # the amount that is not returned to the hydrological cycle

            LivestockAbstractionFromGroundwaterM3 = np.where(
                self.var.GroundwaterBodies > 0,
                self.var.FractionGroundwaterUsed *
                self.var.LivestockConsumptiveUseMM * self.var.MMtoM3,
                maskinfo.in_zero())
            LivestockAbstractionFromNonConventionalWaterM3 = self.var.FractionNonConventionalWaterUsed * self.var.LivestockConsumptiveUseMM * self.var.MMtoM3
            LivestockAbstractionFromSurfaceWaterM3 = self.var.LivestockConsumptiveUseMM * self.var.MMtoM3 - LivestockAbstractionFromGroundwaterM3 - LivestockAbstractionFromNonConventionalWaterM3

            self.var.TotalLivestockAbstractionM3 += LivestockAbstractionFromGroundwaterM3 + LivestockAbstractionFromSurfaceWaterM3 + LivestockAbstractionFromNonConventionalWaterM3

            # ************************************************************
            # ***** DOMESTIC *********************************************
            # ************************************************************

            self.var.DomesticAbstractionMM = self.var.DomesticDemandMM * self.var.DomesticWaterSavingConstant * self.var.DomesticLeakageConstant
            # Domestic Water Abstraction (mm per day), already taking into account water saving in households and leakage of the supply network
            # Domestic water abstraction is larger if there is leakage, but is smaller if there is water savings
            self.var.LeakageMM = (
                self.var.DomesticLeakageConstant - 1
            ) * self.var.DomesticDemandMM * self.var.DomesticWaterSavingConstant
            # Leakage in mm per day
            self.var.LeakageLossMM = self.var.LeakageMM * self.var.LeakageWaterLossFraction
            # The leakage amount that is lost (evaporated)
            self.var.LeakageSoilMM = self.var.LeakageMM - self.var.LeakageLossMM
            self.var.DomesticConsumptiveUseMM = self.var.DomesticDemandMM * self.var.DomesticWaterSavingConstant * self.var.DomesticConsumptiveUseFraction + self.var.LeakageLossMM
            # DomesticConsumptiveUseMM is the amount that disappears from the waterbalance
            # Assumption here is that leakage is partially lost/evaporated (LeakageWaterLoss fraction)

            DomAbstractionFromGroundwaterM3 = np.where(
                self.var.GroundwaterBodies > 0,
                self.var.FractionGroundwaterUsed *
                self.var.DomesticConsumptiveUseMM * self.var.MMtoM3,
                maskinfo.in_zero())
            DomAbstractionFromNonConventionalWaterM3 = self.var.FractionNonConventionalWaterUsed * self.var.DomesticConsumptiveUseMM * self.var.MMtoM3
            DomAbstractionFromSurfaceWaterM3 = self.var.DomesticConsumptiveUseMM * self.var.MMtoM3 - DomAbstractionFromGroundwaterM3 - DomAbstractionFromNonConventionalWaterM3

            # ************************************************************
            # ***** INDUSTRY *********************************************
            # ************************************************************

            self.var.IndustrialAbstractionMM = self.var.IndustrialDemandMM * (
                1 - self.var.WaterReUseFraction)
            self.var.IndustrialConsumptiveUseMM = self.var.IndustrialAbstractionMM * self.var.IndustryConsumptiveUseFraction
            # IndustrialAbstractionMM = scalar(timeinputsparse(IndustrialAbstractionMaps)) * (1-WaterReUseFraction);
            # Industrial Water Demand (mm per day)
            # WaterReUseFraction: Fraction of water re-used in industry (e.g. 50% = 0.5 = half of the water is re-used, used twice (baseline=0, maximum=1)
            # IndustrialConsumptiveUseMM is the amount that evaporates etc
            # only 1 map so this one is loaded in initial!

            IndustrialWaterAbstractionM3 = self.var.IndustrialConsumptiveUseMM * self.var.MMtoM3
            IndustrialAbstractionFromGroundwaterM3 = np.where(
                self.var.GroundwaterBodies > 0,
                self.var.FractionGroundwaterUsed *
                IndustrialWaterAbstractionM3, maskinfo.in_zero())
            IndustrialAbstractionFromNonConventionalWaterM3 = self.var.FractionNonConventionalWaterUsed * IndustrialWaterAbstractionM3
            IndustrialAbstractionFromSurfaceWaterM3 = IndustrialWaterAbstractionM3 - IndustrialAbstractionFromGroundwaterM3 - IndustrialAbstractionFromNonConventionalWaterM3

            # ************************************************************
            # ***** ENERGY ***********************************************
            # ************************************************************

            self.var.EnergyAbstractionMM = self.var.EnergyDemandMM
            self.var.EnergyConsumptiveUseMM = self.var.EnergyAbstractionMM * self.var.EnergyConsumptiveUseFraction
            # EnergyConsumptiveUseMM is the amount that evaporates etc

            EnergyAbstractionFromSurfaceWaterM3 = self.var.EnergyConsumptiveUseMM * self.var.MMtoM3
            # all taken from surface water

            # ************************************************************
            # ***** IRRIGATION *******************************************
            # ************************************************************

            # water demand from loop3 = irrigated zone
            self.var.Ta[2] = np.maximum(
                np.minimum(self.var.RWS[2] * self.var.TranspirMaxCorrected,
                           self.var.W1[2] - self.var.WWP1[2]),
                maskinfo.in_zero())

            IrrigationWaterDemandMM = (
                self.var.TranspirMaxCorrected -
                self.var.Ta[2]) * self.var.IrrigationMult
            #  a factor (IrrigationMult) add some water (to prevent salinisation)
            # irrigationWaterNeed assumed to be equal to potential transpiration minus actual transpiration
            # in mm here, assumed for the entire pixel, thus later to be corrected with IrrigationFraction
            # IrrigationType (value between 0 and 1) is used here to distinguish between additional adding water until fieldcapacity (value set to 1) or not (value set to 0)
            IrrigationWaterDemandMM = np.where(
                self.var.FrostIndex > self.var.FrostIndexThreshold,
                maskinfo.in_zero(), IrrigationWaterDemandMM)
            # IrrigationWaterDemand is 0 when soil is frozen

            IrrigationWaterAbstractionMM = np.where(
                (self.var.IrrigationEfficiency * self.var.ConveyanceEfficiency)
                > 0, IrrigationWaterDemandMM * self.var.IrrigationFraction /
                (self.var.IrrigationEfficiency *
                 self.var.ConveyanceEfficiency), maskinfo.in_zero())
            self.var.IrrigationWaterAbstractionM3 = np.maximum(
                IrrigationWaterAbstractionMM * self.var.MMtoM3,
                maskinfo.in_zero())
            # irrigation efficiency max 1, ~0.90 drip irrigation, ~0.75 sprinkling
            # conveyance efficiency, around 0.80 for average channel
            # multiplied by actual irrigated area (fraction) and cellsize(MMtoM3) in M3 per pixel

            IrrigationAbstractionFromGroundwaterM3 = np.where(
                self.var.GroundwaterBodies > 0,
                self.var.FractionGroundwaterUsed *
                self.var.IrrigationWaterAbstractionM3, maskinfo.in_zero())
            IrrigationAbstractionFromSurfaceWaterM3 = np.maximum(
                self.var.IrrigationWaterAbstractionM3 -
                IrrigationAbstractionFromGroundwaterM3, maskinfo.in_zero())

            # ************************************************************
            # ***** TOTAL ABSTRACTIONS (DEMANDED) ************************
            # ************************************************************

            self.var.TotalAbstractionFromGroundwaterM3 = IrrigationAbstractionFromGroundwaterM3 + DomAbstractionFromGroundwaterM3 + LivestockAbstractionFromGroundwaterM3 + IndustrialAbstractionFromGroundwaterM3
            self.var.TotalAbstractionFromSurfaceWaterM3 = IrrigationAbstractionFromSurfaceWaterM3 + self.var.PaddyRiceWaterAbstractionFromSurfaceWaterM3 + DomAbstractionFromSurfaceWaterM3 + LivestockAbstractionFromSurfaceWaterM3 + IndustrialAbstractionFromSurfaceWaterM3 + EnergyAbstractionFromSurfaceWaterM3

            PaddyRiceWaterAbstractionFromSurfaceWaterMM = self.var.PaddyRiceWaterAbstractionFromSurfaceWaterM3 * self.var.M3toMM
            # taken from paddy rice routine

            self.var.TotalDemandM3 = (
                self.var.LivestockAbstractionMM +
                self.var.DomesticAbstractionMM + IrrigationWaterAbstractionMM +
                PaddyRiceWaterAbstractionFromSurfaceWaterMM +
                self.var.IndustrialAbstractionMM +
                self.var.EnergyAbstractionMM) * self.var.MMtoM3

            self.var.TotalIrrigationAbstractionM3 += IrrigationAbstractionFromGroundwaterM3 + IrrigationAbstractionFromSurfaceWaterM3
            self.var.TotalPaddyRiceIrrigationAbstractionM3 += self.var.PaddyRiceWaterAbstractionFromSurfaceWaterM3
            # totals calculated for reporting, for comparing with national reported values and possible calibration

            # ************************************************************
            # ***** ABSTRACTION FROM GROUNDWATER *************************
            # ************************************************************

            self.var.LZ = self.var.LZ - self.var.TotalAbstractionFromGroundwaterM3 * self.var.M3toMM
            self.var.IrriLossCUM = self.var.IrriLossCUM + self.var.TotalAbstractionFromGroundwaterM3
            # Abstraction is taken from lower groundwater zone
            # for mass balance calculation also summed up in IrrilossCUM (in M3)

            # ***********************************************************************
            # ***** ABSTRACTION SUPPLIED BY NONCONVENTIONAL SOURCES (DESALINATION) **
            # ***********************************************************************

            self.var.NonConventionalWaterM3 = DomAbstractionFromNonConventionalWaterM3 + LivestockAbstractionFromNonConventionalWaterM3 + IndustrialAbstractionFromNonConventionalWaterM3
            # Non conventional water producted is not abstracted from surface water

            # ************************************************************
            # ***** ABSTRACTION FROM LAKES AND RESERVOIRS ****************
            # ************************************************************

            if option['simulateReservoirs']:
                # PotentialAbstractionFromReservoirsM3 = np.minimum(0.02 * self.var.ReservoirStorageM3, 0.01*self.var.TotalReservoirStorageM3C) #original
                PotentialAbstractionFromReservoirsM3 = np.minimum(
                    0.02 * self.var.ReservoirStorageM3,
                    0.01 * self.var.TotalReservoirStorageM3C) * self.var.DtDay

                PotentialAbstractionFromReservoirsM3 = np.where(
                    np.isnan(PotentialAbstractionFromReservoirsM3), 0,
                    PotentialAbstractionFromReservoirsM3)
            else:
                PotentialAbstractionFromReservoirsM3 = maskinfo.in_zero()

            if option['simulateLakes']:
                # CM
                # PotentialAbstractionFromLakesM3 = 0.10 * self.var.LakeStorageM3  #original
                PotentialAbstractionFromLakesM3 = 0.10 * self.var.LakeStorageM3 * self.var.DtDay

                PotentialAbstractionFromLakesM3 = np.where(
                    np.isnan(PotentialAbstractionFromLakesM3), 0,
                    PotentialAbstractionFromLakesM3)
            else:
                PotentialAbstractionFromLakesM3 = maskinfo.in_zero()

            if option['simulateReservoirs'] or option['simulateLakes']:
                PotentialAbstractionFromLakesAndReservoirsM3 = PotentialAbstractionFromLakesM3 + PotentialAbstractionFromReservoirsM3
                # potential total m3 that can be extracted from all lakes and reservoirs in a pixel
            else:
                PotentialAbstractionFromLakesAndReservoirsM3 = maskinfo.in_zero(
                )

            AreatotalPotentialAbstractionFromLakesAndReservoirsM3 = np.take(
                np.bincount(
                    self.var.WUseRegionC,
                    weights=PotentialAbstractionFromLakesAndReservoirsM3),
                self.var.WUseRegionC)
            # potential total m3 that can be extracted from all lakes and reservoirs in the water region

            AreatotalWaterAbstractionFromAllSurfaceSourcesM3 = np.take(
                np.bincount(
                    self.var.WUseRegionC,
                    weights=self.var.TotalAbstractionFromSurfaceWaterM3),
                self.var.WUseRegionC)
            # the total amount that needs to be extracted from surface water, lakes and reservoirs in the water region
            # self.var.FractionAllSurfaceWaterUsed = np.maximum(1 - self.var.FractionGroundwaterUsed - self.var.FractionNonConventionalWaterUsed,maskinfo.in_zero())
            # self.var.FractionSurfaceWaterUsed = np.maximum(1 - self.var.FractionGroundwaterUsed - self.var.FractionNonConventionalWaterUsed-self.var.FractionLakeReservoirWaterUsed,maskinfo.in_zero())
            # AreatotalWaterToBeAbstractedfromLakesReservoirsM3 = np.where( (self.var.FractionSurfaceWaterUsed+self.var.FractionLakeReservoirWaterUsed)> 0, (self.var.FractionLakeReservoirWaterUsed / (self.var.FractionSurfaceWaterUsed+self.var.FractionLakeReservoirWaterUsed)) * AreatotalWaterAbstractionFromAllSurfaceSourcesM3,maskinfo.in_zero())
            AreatotalWaterToBeAbstractedfromLakesReservoirsM3 = self.var.FractionLakeReservoirWaterUsed * AreatotalWaterAbstractionFromAllSurfaceSourcesM3
            self.var.AreatotalWaterAbstractedfromLakesReservoirsM3 = np.minimum(
                AreatotalWaterToBeAbstractedfromLakesReservoirsM3,
                AreatotalPotentialAbstractionFromLakesAndReservoirsM3)
            # total amount of m3 abstracted from all lakes and reservoirs in the water regions
            FractionAbstractedByLakesReservoirs = np.where(
                AreatotalWaterAbstractionFromAllSurfaceSourcesM3 > 0,
                self.var.AreatotalWaterAbstractedfromLakesReservoirsM3 /
                AreatotalWaterAbstractionFromAllSurfaceSourcesM3,
                maskinfo.in_zero())

            self.var.TotalAbstractionFromSurfaceWaterM3 = self.var.TotalAbstractionFromSurfaceWaterM3 * (
                1 - FractionAbstractedByLakesReservoirs)
            # the original surface water abstraction amount is corrected for what is now already abstracted by lakes and reservoirs

            FractionLakesReservoirsEmptying = np.where(
                AreatotalPotentialAbstractionFromLakesAndReservoirsM3 > 0,
                self.var.AreatotalWaterAbstractedfromLakesReservoirsM3 /
                AreatotalPotentialAbstractionFromLakesAndReservoirsM3,
                maskinfo.in_zero())

            self.var.LakeAbstractionM3 = PotentialAbstractionFromLakesM3 * FractionLakesReservoirsEmptying
            if option['simulateLakes']:
                self.var.LakeStorageM3 = self.var.LakeStorageM3 - self.var.LakeAbstractionM3

            self.var.ReservoirAbstractionM3 = PotentialAbstractionFromReservoirsM3 * FractionLakesReservoirsEmptying
            if option['simulateReservoirs']:
                self.var.ReservoirStorageM3 = self.var.ReservoirStorageM3 - self.var.ReservoirAbstractionM3
                # subtract abstracted water from lakes and reservoir storage

            # ************************************************************
            # ***** Abstraction from channels ****************************
            # ***** average abstraction taken from entire waterregion ****
            # ***** limited by available channel water and e-flow minimum*
            # ************************************************************

            AreaTotalDemandedAbstractionFromSurfaceWaterM3 = np.maximum(
                np.take(
                    np.bincount(
                        self.var.WUseRegionC,
                        weights=self.var.TotalAbstractionFromSurfaceWaterM3),
                    self.var.WUseRegionC), 0)

            PixelAvailableWaterFromChannelsM3 = np.maximum(
                self.var.ChanM3Kin - self.var.EFlowThreshold * self.var.DtSec,
                0) * (1 - self.var.WUsePercRemain)
            # respecting e-flow

            AreaTotalAvailableWaterFromChannelsM3 = np.maximum(
                np.take(
                    np.bincount(self.var.WUseRegionC,
                                weights=PixelAvailableWaterFromChannelsM3),
                    self.var.WUseRegionC), 0)
            AreaTotalDemandedWaterFromChannelsM3 = np.minimum(
                AreaTotalAvailableWaterFromChannelsM3,
                AreaTotalDemandedAbstractionFromSurfaceWaterM3)

            self.var.FractionAbstractedFromChannels = np.where(
                AreaTotalAvailableWaterFromChannelsM3 > 0,
                np.minimum(
                    AreaTotalDemandedWaterFromChannelsM3 /
                    AreaTotalAvailableWaterFromChannelsM3, 1), 0)
            # IS THE DEFINITION OF AreaTotalDemandedWaterFromChannelsM3 REDUNDANT WITH np.minimum(...) ABOVE?
            # fraction that is abstracted from channels (should be 0-1)
            self.var.WUseAddM3 = self.var.FractionAbstractedFromChannels * PixelAvailableWaterFromChannelsM3
            # pixel abstracted water in m3

            self.var.WUseAddM3Dt = self.var.WUseAddM3 * self.var.InvNoRoutSteps
            # splitting water use per timestep into water use per sub time step

            self.var.wateruseCum += self.var.WUseAddM3
            # summing up for water balance calculation
            # If report wateruse
            if (option['repwateruseGauges']) or (option['repwateruseSites']):
                self.var.WUseSumM3 = accuflux(
                    self.var.Ldd,
                    decompress(self.var.WUseAddM3) * self.var.InvDtSec)

            # totalAdd = areatotal(decompress(WUseAddM3),self.var.WUseRegion);
            self.var.totalAddM3 = np.take(
                np.bincount(self.var.WUseRegionC, weights=self.var.WUseAddM3),
                self.var.WUseRegionC)

            self.var.WaterUseShortageM3 = self.var.TotalAbstractionFromSurfaceWaterM3 - self.var.WUseAddM3
            # amount of M3 that cannot be extracted from any source, including the channels

            self.var.PotentialSurfaceWaterAvailabilityForIrrigationM3 = np.maximum(
                PixelAvailableWaterFromChannelsM3 -
                self.var.TotalAbstractionFromSurfaceWaterM3 +
                IrrigationAbstractionFromSurfaceWaterM3 +
                self.var.PaddyRiceWaterAbstractionFromSurfaceWaterM3, 0.0)
            # available water excluding the surface water irrigation needs

            # ************************************************************
            # ***** Water Allocation *************************************
            # ***** average abstraction taken from entire waterregion ****
            # ***** limited by available channel water and e-flow minimum*
            # ************************************************************

            # totalAbstr = areatotal(decompress(TotalAbstractionFromSurfaceWaterM3),self.var.WUseRegion)
            self.var.AreaTotalAbstractionFromSurfaceWaterM3 = np.take(
                np.bincount(
                    self.var.WUseRegionC,
                    weights=self.var.TotalAbstractionFromSurfaceWaterM3 -
                    self.var.WUseAddM3), self.var.WUseRegionC)
            self.var.AreaTotalAbstractionFromGroundwaterM3 = np.take(
                np.bincount(
                    self.var.WUseRegionC,
                    weights=self.var.TotalAbstractionFromGroundwaterM3),
                self.var.WUseRegionC)

            # demand
            self.var.AreaTotalDemandM3 = np.take(
                np.bincount(self.var.WUseRegionC,
                            weights=self.var.TotalDemandM3),
                self.var.WUseRegionC)

            # totalEne = areatotal(decompress(self.var.EnergyConsumptiveUseMM*self.var.MMtoM3),self.var.WUseRegion)
            AreatotalIrriM3 = np.take(
                np.bincount(
                    self.var.WUseRegionC,
                    weights=IrrigationAbstractionFromSurfaceWaterM3 +
                    self.var.PaddyRiceWaterAbstractionFromSurfaceWaterM3),
                self.var.WUseRegionC)
            # AreatotalDomM3 = np.take(np.bincount(self.var.WUseRegionC, weights=DomAbstractionFromSurfaceWaterM3),
            #                          self.var.WUseRegionC)
            # AreatotalLiveM3 = np.take(np.bincount(self.var.WUseRegionC, weights=LivestockAbstractionFromSurfaceWaterM3),
            #                           self.var.WUseRegionC)
            # AreatotalIndM3 = np.take(np.bincount(self.var.WUseRegionC, weights=IndustrialAbstractionFromSurfaceWaterM3),
            #                          self.var.WUseRegionC)
            # AreatotalEneM3 = np.take(np.bincount(self.var.WUseRegionC, weights=EnergyAbstractionFromSurfaceWaterM3),
            #                          self.var.WUseRegionC)

            # Allocation rule: Domestic ->  Energy -> Livestock -> Industry -> Irrigation
            self.var.AreatotalIrrigationShortageM3 = np.take(
                np.bincount(self.var.WUseRegionC,
                            weights=self.var.WaterUseShortageM3),
                self.var.WUseRegionC)
            self.var.AreatotalIrrigationUseM3 = np.maximum(
                AreatotalIrriM3 - self.var.AreatotalIrrigationShortageM3, 0.0)

            with np.errstate(all='ignore'):
                fractionIrrigationAvailability = np.where(
                    AreatotalIrriM3 > 0,
                    self.var.AreatotalIrrigationUseM3 / AreatotalIrriM3, 1.0)

                self.var.IrrigationWaterAbstractionM3 = fractionIrrigationAvailability * IrrigationAbstractionFromSurfaceWaterM3 + IrrigationAbstractionFromGroundwaterM3
                # real irrigation is percentage of avail/demand for waterregion * old surface + old groundwater abstraction
                IrrigationWaterDemand = self.var.IrrigationWaterAbstractionM3 * self.var.M3toMM
                IrrigationWaterDemand = np.where(
                    self.var.IrrigationFraction > 0,
                    IrrigationWaterDemand / self.var.IrrigationFraction, 0.0)

            # for mass balance calculate the loss of irrigation water
            # ---------------------------------------------------------
            # updating soil in loop3=irrigation
            # ---------------------------------------------------------

            Wold = self.var.W1[2]
            IrrigationDemandW1b = np.maximum(
                IrrigationWaterDemand - (self.var.WFilla - self.var.W1a[2]), 0)
            self.var.W1a[2] = np.where(
                self.var.W1a[2] >= self.var.WFilla, self.var.W1a[2],
                np.minimum(self.var.WFilla,
                           self.var.W1a[2] + IrrigationWaterDemand))
            self.var.W1b[2] = np.where(
                self.var.W1b[2] >= self.var.WFillb, self.var.W1b[2],
                np.minimum(self.var.WFillb,
                           self.var.W1b[2] + IrrigationDemandW1b))
            self.var.W1[2] = np.add(self.var.W1a[2], self.var.W1b[2])
            # if irrigated soil is less than Pf3 then fill up to Pf3 (if there is water demand)
            # if more than Pf3 the additional water is transpirated
            # there is already no water demand if the soil is frozen
            Wdiff = self.var.W1[2] - Wold
            self.var.Ta[2] = self.var.Ta[2] + IrrigationWaterDemand - Wdiff

            self.var.IrriLossCUM = self.var.IrriLossCUM - self.var.IrrigationWaterAbstractionM3 * self.var.IrrigationEfficiency * self.var.ConveyanceEfficiency - Wdiff * self.var.MMtoM3 * self.var.IrrigationFraction

            # Added to TA but also
            # for mass balance calculate the loss of irrigation water
            # AdR: irrigation demand added to W1 and Ta; so assumption here that soil moisture stays the same
            # we could also abstract more water equivalent to satisfy Ta and bring soil moisture to pF2 or so, for later consideration#
            # self.var.Ta[2] = np.where(self.var.FrostIndex > self.var.FrostIndexThreshold, maskinfo.in_zero(), self.var.Ta[2])
            # transpiration is 0 when soil is frozen

            # ---------------------------------------------------------
            # E-flow
            # ---------------------------------------------------------

            self.var.EFlowIndicator = np.where(
                self.var.ChanQ <= self.var.EFlowThreshold,
                maskinfo.in_zero() + 1.0, maskinfo.in_zero())
            # if ChanQ is less than EflowThreshold, EFlowIndicator becomes 1

            # ************************************************************
            # ***** update state variables                             ***
            # ************************************************************
            # CM Update state variables for changes to W1a[2] and W1b[2]
            self.var.Theta1a[2] = self.var.W1a[2] / self.var.SoilDepth1a[2]
            self.var.Theta1b[2] = self.var.W1b[2] / self.var.SoilDepth1b[2]

            # ************************************************************
            # ***** smooth lower zone with correction                  ***
            # ************************************************************

            if option['groundwaterSmooth']:
                LZPcr = decompress(self.var.LZ)

                Range = self.var.LZSmoothRange * celllength()

                LZTemp1 = ifthen(self.var.GroundwaterBodiesPcr == 1, LZPcr)
                LZTemp2 = ifthen(self.var.GroundwaterBodiesPcr == 1,
                                 windowtotal(LZTemp1, Range))
                LZTemp3 = windowtotal(LZTemp1 * 0 + 1, Range)
                LZSmooth = ifthenelse(LZTemp3 == 0, 0.0,
                                      pcrDiv(LZTemp2, LZTemp3))
                LZPcr = ifthenelse(self.var.GroundwaterBodiesPcr == 0, LZPcr,
                                   0.9 * LZPcr + 0.1 * LZSmooth)

                diffCorr = 0.1 * areaaverage(LZSmooth - LZTemp1,
                                             self.var.groundwaterCatch)
                # error of 0.1  LZSmooth operation (same factor of 0.1 as above)
                LZPcr -= cover(diffCorr, 0)
                # correction of LZ by the average error from smoothing operation

                self.var.LZ = compressArray(LZPcr)