Source code for cwatm.hydrological_modules.waterbalance

#-------------------------------------------------------------------------
#Name:        Water Balance module
#Purpose:
#1.) check if water balance per time step is ok ( = 0)
#2.) produce an annual overview - income, outcome storage
#Author:      PB
#
#Created:     22/08/2016
#Copyright:   (c) PB 2016
#-------------------------------------------------------------------------

from cwatm.management_modules.data_handling import *

[docs]class waterbalance(object): """ WATER BALANCE * check if water balance per time step is closed ( = 0) * produce an annual overview - income, outcome storage **Global variables** ===================================== ====================================================================== ===== Variable [self.var] Description Unit ===================================== ====================================================================== ===== lakeReservoirStorage -- snowEvap total evaporation from snow for a snow layers m storGroundwater Groundwater storage (non-fossil). This is primarily used when not usin m prestorGroundwater storGroundwater at the beginning of each step m preSmalllakeStorage -- smallLakedaycorrect -- smallLakeIn -- smallevapWaterBody -- smallLakeout -- EvapWaterBodyM Evaporation from lakes and reservoirs m lakeResInflowM -- lakeResOutflowM -- sum_gwRecharge groundwater recharge m lakeStorage -- resStorage -- totalSto Total soil,snow and vegetation storage for each cell including all lan m pretotalSto Previous totalSto m sum_prefFlow Preferential flow from soil to groundwater (summed up for all land cov m sum_perc3toGW Percolation from 3rd soil layer to groundwater (summed up for all land m sum_actBareSoilEvap -- sum_openWaterEvap -- sum_directRunoff -- sum_interflow -- sum_capRiseFromGW Capillary rise from groundwater to 3rd soil layer (summed up for all l m sum_act_irrConsumption -- cellArea Area of cell m2 DtSec number of seconds per timestep (default = 86400) s Precipitation Precipitation (input for the model) m lddCompress compressed river network (without missing values) -- discharge Channel discharge m3/s prelakeResStorage -- catchmentAll -- sumsideflow -- EvapoChannel Channel evaporation m3 prechannelStorage -- runoff -- gridcell_storage -- baseflow simulated baseflow (= groundwater discharge to river) m nonFossilGroundwaterAbs Non-fossil groundwater abstraction. Used primarily without MODFLOW. m lakeResStorage -- smalllakeStorage -- act_SurfaceWaterAbstract Surface water abstractions m addtoevapotrans Irrigation application loss to evaporation m act_irrWithdrawal Irrigation withdrawals m act_nonIrrConsumption Non-irrigation consumption m returnFlow -- unmetDemand Unmet groundwater demand to determine potential fossil groundwaterwate m act_nonIrrWithdrawal Non-irrigation withdrawals m returnflowIrr -- nonIrrReturnFlowFraction -- unmet_lost Fossil water that disappears instead of becoming return flow m channelStorage Channel water storage m3 act_totalWaterWithdrawal Total water withdrawals m totalET Total evapotranspiration for each cell including all landcover types m sum_actTransTotal -- sum_interceptEvap -- prergridcell -- nonIrrReturnFlow -- localQW -- channelStorageBefore -- sumbalance -- sum_balanceStore -- sum_balanceFlux -- ===================================== ====================================================================== ===== **Functions** """ def __init__(self, model): self.var = model.var self.model = model # -------------------------------------------------------------------------- # --------------------------------------------------------------------------
[docs] def initial(self): """ Initial part of the water balance module """ if checkOption('calcWaterBalance'): self.var.nonIrrReturnFlow = 0 self.var.localQW = 0 self.var.channelStorageBefore = 0 self.var.prergridcell = 0 self.var.catchmentAll = (loadmap('MaskMap',local = True) * 0.).astype(np.int) #self.var.catchmentNo = int(loadmap('CatchmentNo')) self.var.sumbalance = 0 """ store the initial storage volume of snow, soil etc. """ if checkOption('sumWaterBalance'): # variables of storage self.var.sum_balanceStore = ['SnowCover','sum_interceptStor','sum_topWaterLayer'] # variable of fluxes self.var.sum_balanceFlux = ['Precipitation','SnowMelt','IceMelt','Rain','sum_interceptEvap','actualET'] #for variable in self.var.sum_balanceStore: # vars(self.var)["sumup_" + variable] = vars(self.var)[variable] for variable in self.var.sum_balanceFlux: vars(self.var)["sumup_" + variable] = globals.inZero.copy()
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
[docs] def waterBalanceCheck(self, fluxesIn, fluxesOut, preStorages, endStorages, processName, printTrue=False): """ Dynamic part of the water balance module Returns the water balance for a list of input, output, and storage map files :param fluxesIn: income :param fluxesOut: this goes out :param preStorages: this was in before :param endStorages: this was in afterwards :param processName: name of the process :param printTrue: calculate it? :return: - """ if printTrue: minB =0 maxB = 0 maxBB = 0 income = 0 out = 0 store = 0 for fluxIn in fluxesIn: income += fluxIn for fluxOut in fluxesOut: out += fluxOut for preStorage in preStorages: store += preStorage for endStorage in endStorages: store -= endStorage balance = income + store - out #balance = endStorages #if balance is not empty if balance.size: balance[np.isnan(balance)]= 0 minB = np.amin(balance) maxB = np.amax(balance) maxBB = np.maximum(np.abs(minB),np.abs(maxB)) #meanB = np.average(balance, axis=0) #meanB = 0.0 print (" %s %10.8f " % (processName, maxBB),) #if maxBB > 0.00000001: # sys.exit() if maxBB > 0.0000001: #print(" %s %10.8f %10.8f" % (processName, minB,maxB), end=' ') print(" %s %10.8f %10.8f" % (processName, minB, maxB)) sys.exit() #quit() if (minB < -0.00001) or (maxB > 0.00001): i=11111 return maxBB
[docs] def waterBalanceCheckSum(self, fluxesIn, fluxesOut, preStorages, endStorages, processName, printTrue=False): """ Returns the water balance for a list of input, output, and storage map files and sums it up for a catchment :param fluxesIn: income :param fluxesOut: this goes out :param preStorages: this was in before :param endStorages: this was in afterwards :param processName: name of the process :param printTrue: calculate it? :return: Water balance as output on the screen """ if printTrue: minB =0 maxB = 0 maxBB = 0 income = 0 out = 0 store = 0 for fluxIn in fluxesIn: if not(isinstance(fluxIn,np.ndarray)) : fluxIn = globals.inZero income = income + np.bincount(self.var.catchmentAll,weights=fluxIn) for fluxOut in fluxesOut: if not (isinstance(fluxOut, np.ndarray)): fluxOut = globals.inZero out = out + np.bincount(self.var.catchmentAll,weights=fluxOut) for preStorage in preStorages: if not (isinstance(preStorage, np.ndarray)): preStorage = globals.inZero store = store + np.bincount(self.var.catchmentAll,weights=preStorage) for endStorage in endStorages: if not (isinstance(endStorage, np.ndarray)): endStorage = globals.inZero store = store - np.bincount(self.var.catchmentAll,weights=endStorage) balance = income + store - out #balance = endStorages #if balance.size: #minB = np.amin(balance) #maxB = np.amax(balance) #maxBB = np.maximum(np.abs(minB),np.abs(maxB)) #meanB = np.average(balance, axis=0) #meanB = 0.0 #no = self.var.catchmentNo no = 0 #print " %s %10.8f " % (processName, maxBB), #print " %s %10.8f %10.8f" % (processName, minB,maxB), #print " %s %10.8f" % (processName, balance[no]), print(" %s %10.8f" % (processName, balance[no]) ) #avgArea = npareaaverage(self.var.cellArea, self.var.catchmentAll) #dis = balance[no] * avgArea[0] / self.var.DtSec #print " %s %10.8f" % (processName, dis), return balance[no]
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
[docs] def checkWaterSoilGround(self): """ Check water balance of snow, vegetation, soil, groundwater """ if checkOption('calcWaterBalance'): self.model.waterbalance_module.waterBalanceCheck( [self.var.Rain,self.var.Snow, self.var.sum_act_irrConsumption], [self.var.sum_directRunoff, self.var.sum_interflow, self.var.sum_gwRecharge,self.var.totalET], # Out [self.var.pretotalSto], # prev storage [self.var.totalSto], "Soil_all", False) self.model.waterbalance_module.waterBalanceCheck( [self.var.Rain,self.var.Snow, self.var.sum_act_irrConsumption,self.var.sum_capRiseFromGW], [self.var.sum_directRunoff, self.var.sum_perc3toGW, self.var.sum_prefFlow, self.var.totalET], # Out [self.var.pretotalSto], # prev storage [self.var.totalSto], "Soil_all1", False) self.model.waterbalance_module.waterBalanceCheck( [self.var.Rain,self.var.Snow, self.var.sum_act_irrConsumption,self.var.sum_capRiseFromGW], [self.var.sum_directRunoff, self.var.sum_perc3toGW, self.var.sum_prefFlow, self.var.sum_actTransTotal, self.var.sum_actBareSoilEvap, self.var.sum_openWaterEvap, self.var.sum_interceptEvap, self.var.snowEvap, self.var.iceEvap], # Out [self.var.pretotalSto], # prev storage [self.var.totalSto], "Soil_all2", False) self.model.waterbalance_module.waterBalanceCheck( [self.var.Rain,self.var.Snow, self.var.sum_act_irrConsumption], [self.var.sum_directRunoff, self.var.sum_interflow, self.var.nonFossilGroundwaterAbs,self.var.baseflow, self.var.sum_actTransTotal, self.var.sum_actBareSoilEvap, self.var.sum_openWaterEvap, self.var.sum_interceptEvap, self.var.snowEvap, self.var.iceEvap], # Out [self.var.pretotalSto,self.var.prestorGroundwater], # prev storage [self.var.totalSto,self.var.storGroundwater], "Soil+G", False) self.model.waterbalance_module.waterBalanceCheck( [self.var.unmetDemand, self.var.nonFossilGroundwaterAbs, self.var.act_SurfaceWaterAbstract], # In [self.var.act_irrWithdrawal,self.var.act_nonIrrWithdrawal], # Out [globals.inZero], [globals.inZero], "Waterdemand1", False) self.model.waterbalance_module.waterBalanceCheck( [self.var.act_irrWithdrawal], # In [self.var.sum_act_irrConsumption, self.var.returnflowIrr,self.var.addtoevapotrans], # Out [globals.inZero], [globals.inZero], "Waterdemand2", False) self.model.waterbalance_module.waterBalanceCheckSum( [self.var.Rain,self.var.Snow, self.var.act_irrWithdrawal], [self.var.sum_directRunoff, self.var.sum_interflow, self.var.nonFossilGroundwaterAbs,self.var.baseflow, self.var.sum_actTransTotal, self.var.sum_actBareSoilEvap, self.var.sum_openWaterEvap, self.var.sum_interceptEvap, self.var.snowEvap, self.var.iceEvap, self.var.returnflowIrr, self.var.addtoevapotrans], # Out [self.var.pretotalSto,self.var.prestorGroundwater], # prev storage [self.var.totalSto,self.var.storGroundwater], "Soil+G+WD", False) self.model.waterbalance_module.waterBalanceCheck( [self.var.Rain,self.var.Snow, self.var.act_irrWithdrawal], [self.var.sum_directRunoff, self.var.sum_interflow, self.var.baseflow, self.var.sum_actTransTotal, self.var.sum_actBareSoilEvap, self.var.sum_openWaterEvap, self.var.sum_interceptEvap, self.var.snowEvap, self.var.iceEvap, self.var.addtoevapotrans, self.var.nonFossilGroundwaterAbs, self.var.returnflowIrr, ], # Out [self.var.pretotalSto, self.var.prestorGroundwater], # prev storage [self.var.totalSto, self.var.storGroundwater], "Soil+G+WD", True) nonIrrReturn = self.var.nonIrrReturnFlowFraction * self.var.act_irrWithdrawal nonIrruse = self.var.act_irrWithdrawal - nonIrrReturn if checkOption('includeWaterBodies'): if checkOption('calcWaterBalance'): self.model.waterbalance_module.waterBalanceCheck( [self.var.lakeResInflowM], # In [self.var.lakeResOutflowM, self.var.EvapWaterBodyM], # Out self.var.evapWaterBodyC [self.var.prelakeResStorage / self.var.cellArea], # prev storage [self.var.lakeResStorage / self.var.cellArea], "LR1", True) self.model.waterbalance_module.waterBalanceCheck( [self.var.lakeReservoirStorage], # In [self.var.lakeStorage,self.var.resStorage,self.var.smalllakeStorage], # Out self.var.evapWaterBodyC [], # prev storage [], "LR1a", True) if checkOption('calcWaterBalance') and returnBool('useSmallLakes'): self.model.waterbalance_module.waterBalanceCheck( [self.var.smallLakeIn], # In [self.var.smallLakeout, self.var.smallevapWaterBody], # Out [self.var.preSmalllakeStorage / self.var.cellArea], # prev storage [self.var.smalllakeStorage / self.var.cellArea], "LR2", False) if checkOption('calcWaterBalance') and returnBool('useSmallLakes'): self.model.waterbalance_module.waterBalanceCheck( [self.var.Precipitation,self.var.smallLakedaycorrect, self.var.unmetDemand, self.var.act_SurfaceWaterAbstract ], [self.var.totalET, self.var.runoff,self.var.smallevapWaterBody, self.var.act_nonIrrConsumption, self.var.returnFlow, self.var.unmet_lost ], # Out [self.var.pretotalSto, self.var.prestorGroundwater, self.var.prergridcell,self.var.preSmalllakeStorage / self.var.cellArea], # prev storage [self.var.totalSto, self.var.storGroundwater, self.var.gridcell_storage,self.var.smalllakeStorage / self.var.cellArea], "Soil+G+WD+LR3", False) # without waterdemand #### IMPORTANT set Routingstep to 1 to test! if checkOption('calcWaterBalance'): DisOut = self.var.discharge * self.var.DtSec / self.var.cellArea DisOut = np.where(self.var.lddCompress == 5, DisOut, 0.) self.model.waterbalance_module.waterBalanceCheckSum( [self.var.runoff, self.var.returnFlow], # In [self.var.sumsideflow / self.var.cellArea, self.var.EvapoChannel / self.var.cellArea, self.var.act_SurfaceWaterAbstract, ], # Out [], # prev storage [], "rout11", False) self.model.waterbalance_module.waterBalanceCheckSum( [self.var.runoff], # In [DisOut, self.var.EvapoChannel / self.var.cellArea], # Out [self.var.prechannelStorage / self.var.cellArea], # prev storage [self.var.channelStorage / self.var.cellArea], "rout2", False) self.model.waterbalance_module.waterBalanceCheckSum( [self.var.runoff, self.var.returnFlow], # In [DisOut, self.var.EvapoChannel, self.var.act_SurfaceWaterAbstract], # Out [self.var.prechannelStorage / self.var.cellArea], # prev storage [self.var.channelStorage / self.var.cellArea], "rout4", False) #print self.var.channelStorageBefore[10], # print "%10.8f %10.8f %10.8f " % (income[10], out[10], store[10]), # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if checkOption('sumWaterBalance'): self.model.waterbalance_module.waterBalanceCheckSum( [self.var.nonFossilGroundwaterAbs, self.var.unmetDemand, self.var.act_SurfaceWaterAbstract], # In [self.var.act_totalWaterWithdrawal], # Out [globals.inZero], [globals.inZero], "WaterdemandSum", True) """ self.model.waterbalance_module.waterBalanceCheckSum( [self.var.Precipitation, self.var.surfaceWaterInf,self.var.sumIrrDemand,self.var.nonIrrReturnFlow], # In [self.var.totalET, self.var.localQW, self.var.riverbedExchange * self.var.InvCellArea, self.var.nonFossilGroundwaterAbs, self.var.act_SurfaceWaterAbstract], [self.var.pretotalSto,self.var.prestorGroundwater,self.var.prechannelStorage * self.var.InvCellArea], # prev storage [self.var.totalSto,self.var.storGroundwater,self.var.channelStorageBefore * self.var.InvCellArea], "S+G+Rout1Sum", False) """ """ if checkOption('budyko'): # in mm self.var.sumETRef =[] self.var.sumP = [] self.var.sumETA = [] for i in xrange(self.var.noOutpoints): # TODO change this to store in arrays not in maps for each gauge station! area = npareatotal(self.var.cellArea, self.var.evalCatch[i]) self.var.sumETRef.append(1000 * npareatotal(self.var.ETRef * self.var.cellArea, self.var.evalCatch[i]) / area) self.var.sumP.append(1000 * npareatotal(self.var.Precipitation * self.var.cellArea, self.var.evalCatch[i]) / area) self.var.sumETA.append(1000 * npareatotal((self.var.totalET) * self.var.cellArea, self.var.evalCatch[i]) / area) ##self.var.area = npareatotal(self.var.cellArea, self.var.catchment) ##self.var.sumETRef = 1000 * npareatotal(self.var.ETRef * self.var.cellArea, self.var.catchment)/self.var.area ##self.var.sumP = 1000 * npareatotal(self.var.Precipitation * self.var.cellArea, self.var.catchment) / self.var.area #self.var.sumETA = 1000 * npareatotal((self.var.totalET + self.var.localQW) * self.var.cellArea , self.var.catchment)/self.var.area ##self.var.sumETA = 1000 * npareatotal((self.var.totalET) * self.var.cellArea, self.var.catchment) / self.var.area #self.var.sumRunoff = 1000 * npareatotal((self.var.channelStorageBefore - self.var.prechannelStorage), self.var.catchment)/self.var.area #self.var.sumDelta1 = 1000 * npareatotal((self.var.SnowCover + self.var.totalSoil + self.var.storGroundwater) * self.var.cellArea , self.var.catchment)/self.var.area #self.var.sumDelta2 = 1000 * npareatotal((self.var.prevSnowCover + self.var.pretotalSoil + self.var.prestorGroundwater) * self.var.cellArea , self.var.catchment)/self.var.area #self.var.sumAll = self.var.sumDelta1- self.var.sumDelta2 #report(decompress(self.var.sumRunoff), r"C:\work\output3/sumRun.map") """
[docs] def dynamic(self): """ Dynamic part of the water balance module If option **sumWaterBalance** sum water balance for certain variables """ #if checkOption('sumWaterBalance'): # i = 1 # sum up storage variables #for variable in self.var.sum_balanceStore: # vars(self.var)["sumup_" + variable] = vars(self.var)[variable].copy() # sum up fluxes variables for variable in self.var.sum_balanceFlux: vars(self.var)["sumup_" + variable] = vars(self.var)["sumup_" + variable] + vars(self.var)[variable]