def __init__(self, configuration, currTimeStep, initialState = None): self._configuration = configuration self._modelTime = currTimeStep pcr.setclone(configuration.cloneMap) # Read the ldd map. self.lddMap = vos.readPCRmapClone(\ configuration.routingOptions['lddMap'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir'],True) #ensure ldd map is correct, and actually of type "ldd" self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) if configuration.globalOptions['landmask'] != "None": self.landmask = vos.readPCRmapClone(\ configuration.globalOptions['landmask'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir']) else: self.landmask = pcr.defined(self.lddMap) # ADDED: variables necessary for 2-way coupling functions # ---------------------------------------------------------------------------------------------------------------- # variable to control activation of 2-way coupling functions (can be changed through BMI) self.ActivateCoupling = self._configuration.globalOptions['ActivateCoupling'] # ---------------------------------------------------------------------------------------------------------------- # defining catchment areas self.catchment_class = 1.0 # number of upperSoilLayers: self.numberOfSoilLayers = int(configuration.landSurfaceOptions['numberOfUpperSoilLayers']) self.createSubmodels(initialState)
def __init__(self, configuration, currTimeStep, initialState = None): self._configuration = configuration self._modelTime = currTimeStep pcr.setclone(configuration.cloneMap) # Read the ldd map. self.lddMap = vos.readPCRmapClone(\ configuration.routingOptions['lddMap'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir'],True) #ensure ldd map is correct, and actually of type "ldd" self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) if configuration.globalOptions['landmask'] != "None": self.landmask = vos.readPCRmapClone(\ configuration.globalOptions['landmask'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir']) else: self.landmask = pcr.defined(self.lddMap) # defining catchment areas self.catchment_class = 1.0 # number of upperSoilLayers: self.numberOfSoilLayers = int(configuration.landSurfaceOptions['numberOfUpperSoilLayers']) self.createSubmodels(initialState)
def getICs(self, iniItems, iniConditions=None): #print iniItems.groundwaterOptions['storGroundwaterFossilIni'] # initial condition for storGroundwater (unit: m) if iniConditions == None: # when the model just start self.storGroundwater = vos.readPCRmapClone(\ iniItems.groundwaterOptions['storGroundwaterIni'], self.cloneMap,self.tmpDir,self.inputDir) self.avgAbstraction = vos.readPCRmapClone(\ iniItems.groundwaterOptions['avgTotalGroundwaterAbstractionIni'], self.cloneMap,self.tmpDir,self.inputDir) else: # during/after spinUp self.storGroundwater = iniConditions['groundwater'][ 'storGroundwater'] self.avgAbstraction = iniConditions['groundwater'][ 'avgTotalGroundwaterAbstractionIni'] # initial condition for storGroundwaterFossil (unit: m) # # Note that storGroundwaterFossil should not be depleted during the spin-up. # if iniItems.groundwaterOptions['storGroundwaterFossilIni'] != "Maximum": #logger.info("Using a pre-defined initial condition for fossil groundwater storage.") self.storGroundwaterFossil = vos.readPCRmapClone(\ iniItems.groundwaterOptions['storGroundwaterFossilIni'], self.cloneMap,self.tmpDir,self.inputDir) # if self.limitFossilGroundwaterAbstraction and iniItems.groundwaterOptions[ 'storGroundwaterFossilIni'] != "Maximum": #logger.info("The pre-defined initial condition for fossil groundwater is limited by fossilWaterCap (full capacity).") self.storGroundwaterFossil = pcr.min(self.storGroundwaterFossil, self.fossilWaterCap) # if self.limitFossilGroundwaterAbstraction and iniItems.groundwaterOptions[ 'storGroundwaterFossilIni'] == "Maximum": #logger.info("Assuming 'full' fossilWaterCap as the initial condition for fossil groundwater storage.") self.storGroundwaterFossil = self.fossilWaterCap # make sure that active storGroundwater and avgAbstraction cannot be negative # self.storGroundwater = pcr.cover(self.storGroundwater, 0.0) self.storGroundwater = pcr.max(0., self.storGroundwater) self.storGroundwater = pcr.ifthen(self.landmask,\ self.storGroundwater) # self.avgAbstraction = pcr.cover(self.avgAbstraction, 0.0) self.avgAbstraction = pcr.max(0., self.avgAbstraction) self.avgAbstraction = pcr.ifthen(self.landmask,\ self.avgAbstraction) # storGroundwaterFossil can be negative (particularly if limitFossilGroundwaterAbstraction == False) self.storGroundwaterFossil = pcr.ifthen(self.landmask,\ self.storGroundwaterFossil)
def readTopo(self, iniItems): # maps of elevation attributes: topoParams = ['tanslope', 'slopeLength', 'orographyBeta'] if iniItems.landSurfaceOptions['topographyNC'] == str(None): for var in topoParams: input = iniItems.landSurfaceOptions[str(var)] vars(self)[var] = pcr.scalar(0.0) vars(self)[var] = vos.readPCRmapClone(input, self.cloneMap, self.tmpDir, self.inputDir) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) else: topoPropertiesNC = vos.getFullPath(\ iniItems.landSurfaceOptions[\ 'topographyNC'], self.inputDir) for var in topoParams: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(\ topoPropertiesNC,var, \ cloneMapFileName = self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) self.tanslope = pcr.max(self.tanslope, 0.00001) # maps of relative elevation above flood plains dzRel = [ 'dzRel0001', 'dzRel0005', 'dzRel0010', 'dzRel0020', 'dzRel0030', 'dzRel0040', 'dzRel0050', 'dzRel0060', 'dzRel0070', 'dzRel0080', 'dzRel0090', 'dzRel0100' ] if iniItems.landSurfaceOptions['topographyNC'] == str(None): for i in range(0, len(dzRel)): var = dzRel[i] input = iniItems.landSurfaceOptions[str(var)] vars(self)[var] = vos.readPCRmapClone(input, self.cloneMap, self.tmpDir, self.inputDir) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) if i > 0: vars(self)[var] = pcr.max( vars(self)[var], vars(self)[dzRel[i - 1]]) else: for i in range(0, len(dzRel)): var = dzRel[i] vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(\ topoPropertiesNC,var, \ cloneMapFileName = self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) if i > 0: vars(self)[var] = pcr.max( vars(self)[var], vars(self)[dzRel[i - 1]])
def readTopo(self, iniItems, optionDict): # a dictionary/section of options that will be used if optionDict == None: optionDict = iniItems._sections["landSurfaceOptions"] # maps of elevation attributes: topoParams = ['tanslope','slopeLength','orographyBeta'] if optionDict['topographyNC'] == str(None): for var in topoParams: input = configget(iniItems,"landSurfaceOptions",str(var),"None") vars(self)[var] = vos.readPCRmapClone(input,self.cloneMap, self.tmpDir,self.inputDir) if var != "slopeLength": vars(self)[var] = pcr.cover(vars(self)[var], 0.0) else: topoPropertiesNC = vos.getFullPath(\ optionDict['topographyNC'], self.inputDir) for var in topoParams: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(\ topoPropertiesNC,var, \ cloneMapFileName = self.cloneMap) if var != "slopeLength": vars(self)[var] = pcr.cover(vars(self)[var], 0.0) #~ self.tanslope = pcr.max(self.tanslope, 0.00001) # In principle, tanslope can be zero. Zero tanslope will provide zero TCL (no interflow) # covering slopeLength with its maximum value self.slopeLength = pcr.cover(self.slopeLength, pcr.mapmaximum(self.slopeLength)) # maps of relative elevation above flood plains dzRel = ['dzRel0001','dzRel0005', 'dzRel0010','dzRel0020','dzRel0030','dzRel0040','dzRel0050', 'dzRel0060','dzRel0070','dzRel0080','dzRel0090','dzRel0100'] if optionDict['topographyNC'] == str(None): for i in range(0, len(dzRel)): var = dzRel[i] input = optionDict[str(var)] vars(self)[var] = vos.readPCRmapClone(input,self.cloneMap, self.tmpDir,self.inputDir) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) if i > 0: vars(self)[var] = pcr.max(vars(self)[var], vars(self)[dzRel[i-1]]) else: for i in range(0, len(dzRel)): var = dzRel[i] vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(\ topoPropertiesNC,var, \ cloneMapFileName = self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) if i > 0: vars(self)[var] = pcr.max(vars(self)[var], vars(self)[dzRel[i-1]])
def get_initial_heads(self): if self.iniItems.modflowTransientInputOptions['groundwaterHeadIni'] != "None": # using a pre-defined groundwater head described in the ini/configuration file self.groundwaterHead = vos.readPCRmapClone(self.modflowTransientInputOptions['groundwaterHeadIni'],\ self.cloneMap, self.tmpDir, self.inputDir) else: # using the digital elevation model as the initial head self.groundwaterHead = self.dem_average # calculate/simulate a steady state condition (until the modflow converge) self.modflow_converged = False while self.modflow_converged == False: self.modflow_simulation("steady-state", self.groundwaterHead, None,1,1,self.criteria_HCLOSE[self.iteration_HCLOSE],\ self.criteria_RCLOSE[self.iteration_RCLOSE]) # extrapolating the calculated heads for areas/cells outside the landmask (to remove isolated cells) # TODO: Using Deltares's trick to remove isolated cells. # # - the calculate groundwater head within the landmask region self.groundwaterHead = pcr.ifthen(self.landmask, self.groundwaterHead) # - keep the ocean values (dem <= 0.0) - this is in order to maintain the 'behaviors' of sub marine groundwater discharge self.groundwaterHead = pcr.cover(self.groundwaterHead, pcr.ifthen(self.dem_average <= 0.0, self.dem_average)) # - extrapolation # self.groundwaterHead = pcr.cover(self.groundwaterHead, pcr.windowaverage(self.groundwaterHead, 3.*pcr.clone().cellSize())) self.groundwaterHead = pcr.cover(self.groundwaterHead, pcr.windowaverage(self.groundwaterHead, 5.*pcr.clone().cellSize())) self.groundwaterHead = pcr.cover(self.groundwaterHead, self.dem_average) # TODO: Define the window sizes as part of the configuration file. # after having the initial head, set the following variable to True to indicate the first month of the model simulation self.firstMonthOfSimulation = True
def __init__(self, iniItems, landmask, Dir, cloneMap, tmpDir): object.__init__(self) # clone map file names, temporary directory and global/absolute path of input directory self.cloneMap = cloneMap #iniItems.cloneMap self.tmpDir = tmpDir #iniItems.tmpDir self.inputDir = Dir #iniItems.globalOptions['inputDir'] self.landmask = landmask # local drainage direction: self.lddMap = vos.readPCRmapClone( iniItems.get("routingOptions", "lddMap"), self.cloneMap, self.tmpDir, self.inputDir, True) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) self.lddMap = pcr.lddrepair(self.lddMap) # option to activate water balance check self.debugWaterBalance = True if configget(iniItems, "routingOptions", "debugWaterBalance", "True") == "False": self.debugWaterBalance = False # option to perform a run with only natural lakes (without reservoirs) self.onlyNaturalWaterBodies = False if "onlyNaturalWaterBodies" in iniItems._sections[ 'routingOptions'] and configget(iniItems, "routingOptions", "onlyNaturalWaterBodies", "False") == "True": logger.info( "Using only natural water bodies identified in the year 1900. All reservoirs in 1900 are assumed as lakes." ) self.onlyNaturalWaterBodies = True self.dateForNaturalCondition = "1900-01-01" # The run for a natural condition should access only this date. # names of files containing water bodies parameters if configget(iniItems, "routingOptions", "waterBodyInputNC", "None") == str(None): self.useNetCDF = False self.fracWaterInp = iniItems.get("routingOptions", "fracWaterInp") self.waterBodyIdsInp = iniItems.get("routingOptions", "waterBodyIds") self.waterBodyTypInp = iniItems.get("routingOptions", "waterBodyTyp") self.resMaxCapInp = iniItems.get("routingOptions", "resMaxCapInp") self.resSfAreaInp = iniItems.get("routingOptions", "resSfAreaInp") else: self.useNetCDF = True self.ncFileInp = vos.getFullPath(\ iniItems.get("routingOptions","waterBodyInputNC"),\ self.inputDir) # minimum width (m) used in the weir formula # TODO: define minWeirWidth based on the GLWD, GRanD database and/or bankfull discharge formula self.minWeirWidth = 10. # lower and upper limits at which reservoir release is terminated and # at which reservoir release is equal to long-term average outflow self.minResvrFrac = 0.10 self.maxResvrFrac = 0.75
def dynamic(self): # re-calculate current model time using current pcraster timestep value self.modelTime.update(self.currentTimeStep()) # perform the operation only at the last day of the month (as the input netcdf file has a monthly resolution with the last date of the month as its time stamp) if self.modelTime.isLastDayOfMonth(): self.i_month = self.i_month + 1 # reading a netcdf file (global extent, 5 arcmin resolution): pcr.setclone(self.globeCloneMapFileName) global_pcraster_map = vos.netcdf2PCRobjClone(ncFile = self.netcdf_input['file_name'], \ varName = self.netcdf_input['variable_name'], \ dateInput = self.modelTime.fulldate) # save it to pcraster maps (still at a global extent and 5 arcmin resolution); # there will be two files as follows: # - Format 1: example file names: htop0000.001 (for the 1st time step), htop0000.002, htop0000.003, etc. ... pcraster_file_name = self.pcraster_output[ 'output_folder'] + "/global/" + self.pcraster_output[ 'file_name'] pcraster_file_name = pcr.framework.frameworkBase.generateNameT( pcraster_file_name, self.i_month) pcr.report(global_pcraster_map, pcraster_file_name) # - Format 2: example file names: htop_2000_01.map, htop_2000_02.map, etc. pcraster_file_name = self.pcraster_output[ 'output_folder'] + "/global/" + self.pcraster_output[ 'file_name'] + "_" + self.modelTime.fulldate[0:7].replace( "-", "_") + ".map" pcr.report(global_pcraster_map, pcraster_file_name) # reproject and resample it to a local coordinate system pcr.setclone(self.localCloneMapFileName) local_pcraster_map = vos.readPCRmapClone(v = pcraster_file_name, \ cloneMapFileName = self.localCloneMapFileName, \ tmpDir = self.pcraster_output['output_folder'] + "/tmp/", \ absolutePath = None,\ isLddMap = False, \ cover = None, \ isNomMap = False, \ inputEPSG = self.inputEPSG, outputEPSG = self.outputEPSG, method = "near") # save it to pcraster maps (now already at the extent, the resolution and the coordinate system of the local model) # there will be two files as follows: # - Format 1: example file names: htop0000.001 (for the 1st time step), htop0000.002, htop0000.003, etc. ... pcraster_file_name = self.pcraster_output[ 'output_folder'] + "/regional/" + self.pcraster_output[ 'file_name'] pcraster_file_name = pcr.framework.frameworkBase.generateNameT( pcraster_file_name, self.i_month) pcr.report(local_pcraster_map, pcraster_file_name) # - Format 2: example file names: htop_2000_01.map, htop_2000_02.map, etc. pcraster_file_name = self.pcraster_output[ 'output_folder'] + "/regional/" + self.pcraster_output[ 'file_name'] + "_" + self.modelTime.fulldate[0:7].replace( "-", "_") + ".map" pcr.report(local_pcraster_map, pcraster_file_name)
def __init__(self, configuration, currTimeStep, initialState=None): self._configuration = configuration self._modelTime = currTimeStep pcr.setclone(configuration.cloneMap) # Read the ldd map. self.lddMap = vos.readPCRmapClone(\ configuration.routingOptions['lddMap'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir'],True) #ensure ldd map is correct, and actually of type "ldd" self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) if configuration.globalOptions['landmask'] != "None": self.landmask = vos.readPCRmapClone(\ configuration.globalOptions['landmask'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir']) else: self.landmask = pcr.defined(self.lddMap) # defining catchment areas self.catchment_class = 1.0 # number of upperSoilLayers: self.numberOfSoilLayers = int( configuration.landSurfaceOptions['numberOfUpperSoilLayers']) # preparing sub-modules self.createSubmodels(initialState) # option for debugging to PCR-GLOBWB version 1.0 self.debug_to_version_one = False if configuration.debug_to_version_one: self.debug_to_version_one = True if self.debug_to_version_one: # preparing initial folder directory self.directory_for_initial_maps = vos.getFullPath( "initials/", self.configuration.mapsDir) if os.path.exists(self.directory_for_initial_maps): shutil.rmtree(self.directory_for_initial_maps) os.makedirs(self.directory_for_initial_maps) # dump the initial state self.dumpState(self.directory_for_initial_maps, "initial")
def __init__(self, input_files,\ output_files,\ modelTime,\ tmpDir = "/dev/shm/"): DynamicModel.__init__(self) # self.input_files = input_files self.output_files = output_files self.tmpDir = tmpDir self.modelTime = modelTime pcr.setclone(self.input_files["model_cell_area"]) clone_map = pcr.boolean(1) # cell area (m2) self.cell_area = vos.readPCRmapClone(\ self.input_files["model_cell_area"],\ self.input_files["model_cell_area"],\ self.tmpDir) # resampling factor: ratio between target (coarse) and original (fine) resolution self.resample_factor = round( vos.getMapAttributes(self.input_files["one_degree_id"],'cellsize')/\ vos.getMapAttributes(self.input_files["model_cell_area"],'cellsize')) # unique ids for upscaling to one degree resolution (grace resolution) self.one_degree_id = pcr.nominal(\ vos.readPCRmapClone(\ self.input_files["one_degree_id"],\ self.input_files["model_cell_area"],\ self.tmpDir)) # object for reporting at coarse resolution (i.e. one arc degree - grace resolution) self.output = OutputNetcdf(self.input_files["one_degree_id"], self.input_files["model_cell_area"]) # preparing the netcdf file at coarse resolution: self.output.createNetCDF(self.output_files['one_degree_tws']['model'], "pcrglobwb_tws","m") # # edit some attributes: attributeDictionary = {} attributeDictionary['description'] = "One degree resolution total water storage (tws), upscaled from PCR-GLOBWB result. " self.output.changeAtrribute(self.output_files['one_degree_tws']['model'],\ attributeDictionary)
def get_initial_heads(self): if self.iniItems.modflowTransientInputOptions['groundwaterHeadIni'] != "None": # using a pre-defined groundwater head described in the ini/configuration file self.groundwaterHead = vos.readPCRmapClone(self.modflowTransientInputOptions['groundwaterHeadIni'],\ self.cloneMap, self.tmpDir, self.inputDir) else: # calculate/simulate a steady state condition and obtain its calculated head values self.modflow_simulation("steady-state", self.dem_average, None)
def read_meteo_conversion_factors(self, meteoOptions): if 'precipitationConstant' in meteoOptions: self.preConst = pcr.cover( vos.readPCRmapClone(meteoOptions['precipitationConstant'], self.cloneMap, self.tmpDir, self.inputDir), 0.0) if 'precipitationFactor' in meteoOptions: self.preFactor = pcr.cover( vos.readPCRmapClone(meteoOptions['precipitationFactor'], self.cloneMap, self.tmpDir, self.inputDir), 1.0) if 'temperatureConstant' in meteoOptions: self.tmpConst = pcr.cover( vos.readPCRmapClone(meteoOptions['temperatureConstant'], self.cloneMap, self.tmpDir, self.inputDir), 0.0) if 'temperatureFactor' in meteoOptions: self.tmpFactor = pcr.cover( vos.readPCRmapClone(meteoOptions['temperatureFactor'], self.cloneMap, self.tmpDir, self.inputDir), 1.0) if 'referenceEPotConstant' in meteoOptions: self.refETPotConst = pcr.cover( vos.readPCRmapClone(meteoOptions['referenceEPotConstant'], self.cloneMap, self.tmpDir, self.inputDir), 0.0) if 'referenceEPotFactor' in meteoOptions: self.refETPotFactor = pcr.cover( vos.readPCRmapClone(meteoOptions['referenceEPotFactor'], self.cloneMap, self.tmpDir, self.inputDir), 1.0)
def __init__(self, configuration, currTimeStep): self._configuration = configuration self._modelTime = currTimeStep pcr.setclone(configuration.cloneMap) # read the ldd map self.lddMap = vos.netcdf2PCRobjCloneWithoutTime(configuration.modflowParameterOptions['channelNC'],'lddMap',\ configuration.cloneMap) # ensure ldd map is correct, and actually of type "ldd" self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) # defining the landmask map if configuration.globalOptions['landmask'] != "None": self.landmask = vos.readPCRmapClone(\ configuration.globalOptions['landmask'], configuration.cloneMap,configuration.tmpDir,configuration.globalOptions['inputDir']) else: self.landmask = pcr.defined(self.lddMap) # preparing the sub-model(s) - Currently, there is only one sub-model. self.createSubmodels()
def main(): # output folder clean_out_folder = True if os.path.exists(out_folder): if clean_out_folder: shutil.rmtree(out_folder) os.makedirs(out_folder) else: os.makedirs(out_folder) os.chdir(out_folder) os.system("pwd") # tmp folder tmp_folder = out_folder + "/tmp/" if os.path.exists(tmp_folder): shutil.rmtree(tmp_folder) os.makedirs(tmp_folder) # set the clone map print("set the clone map") pcr.setclone(global_clone_map_file) # read ldd map print("define the ldd") # ~ ldd_map = pcr.readmap(global_ldd_inp_file) ldd_map = pcr.lddrepair(pcr.lddrepair(pcr.ldd(vos.readPCRmapClone(v = global_ldd_inp_file, \ cloneMapFileName = global_clone_map_file, \ tmpDir = tmp_folder, \ absolutePath = None, \ isLddMap = True, \ cover = None, \ isNomMap = False)))) # define the landmask if landmask_map_file == None: print("define the landmask based on the ldd input") # ~ landmask = pcr.defined(pcr.readmap(global_ldd_inp_file)) landmask = pcr.defined(ldd_map) landmask = pcr.ifthen(landmask, landmask) else: print("define the landmask based on the input landmask_map_file") landmask = pcr.readmap(landmask_map_file) ldd_map = pcr.ifthen(landmask, pcr.cover(ldd_map, pcr.ldd(5))) ldd_map = pcr.lddrepair(pcr.lddrepair(pcr.ldd(ldd_map))) landmask = pcr.defined(ldd_map) landmask = pcr.ifthen(landmask, landmask) # save ldd files used # - global ldd cmd = "cp " + str(global_ldd_inp_file) + " ." print(cmd) os.system(cmd) # - ldd map that is used pcr.report(ldd_map, "lddmap_used.map") # make catchment map print("make catchment map") catchment_map = pcr.catchment(ldd_map, pcr.pit(ldd_map)) # read global subdomain file print("read global subdomain file") global_subdomain_map = vos.readPCRmapClone( v=global_subdomain_file, cloneMapFileName=global_clone_map_file, tmpDir=tmp_folder, absolutePath=None, isLddMap=False, cover=None, isNomMap=True) # set initial subdomain print("assign subdomains to all catchments") subdomains_initial = pcr.areamajority(global_subdomain_map, catchment_map) subdomains_initial = pcr.ifthen(landmask, subdomains_initial) pcr.aguila(subdomains_initial) pcr.report(subdomains_initial, "global_subdomains_initial.map") print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[0]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[1]))) print("Checking all subdomains, avoid too large subdomains") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[1]) # clone code that will be assigned assigned_number = 0 subdomains_final = pcr.ifthen( pcr.scalar(subdomains_initial) < -7777, pcr.nominal(0)) for nr in range(1, num_of_masks + 1, 1): msg = "Processing the landmask %s" % (str(nr)) print(msg) mask_selected_boolean = pcr.ifthen(subdomains_initial == nr, pcr.boolean(1.0)) process_this_clone = False if pcr.cellvalue(pcr.mapmaximum(pcr.scalar(mask_selected_boolean)), 1, 1)[0] > 0: process_this_clone = True # ~ if nr == 1: pcr.aguila(mask_selected_boolean) # - initial check value check_ok = True if process_this_clone: xmin, ymin, xmax, ymax = boundingBox(mask_selected_boolean) area_in_degree2 = (xmax - xmin) * (ymax - ymin) # ~ print(str(area_in_degree2)) # check whether the size of bounding box is ok reference_area_in_degree2 = 2500. if area_in_degree2 > 1.50 * reference_area_in_degree2: check_ok = False if (xmax - xmin) > 10 * (ymax - ymin): check_ok = False # ~ # ignore checking # ~ check_ok = True if check_ok == True and process_this_clone == True: msg = "Clump is not needed." msg = "\n\n" + str(msg) + "\n\n" print(msg) # assign the clone code assigned_number = assigned_number + 1 # update global landmask for river and land mask_selected_nominal = pcr.ifthen(mask_selected_boolean, pcr.nominal(assigned_number)) subdomains_final = pcr.cover(subdomains_final, mask_selected_nominal) if check_ok == False and process_this_clone == True: msg = "Clump is needed." msg = "\n\n" + str(msg) + "\n\n" print(msg) # make clump clump_ids = pcr.nominal(pcr.clump(mask_selected_boolean)) # merge clumps that are close together clump_ids_window_majority = pcr.windowmajority(clump_ids, 10.0) clump_ids = pcr.areamajority(clump_ids_window_majority, clump_ids) # ~ pcr.aguila(clump_ids) # minimimum and maximum values min_clump_id = int( pcr.cellvalue(pcr.mapminimum(pcr.scalar(clump_ids)), 1)[0]) max_clump_id = int( pcr.cellvalue(pcr.mapmaximum(pcr.scalar(clump_ids)), 1)[0]) for clump_id in range(min_clump_id, max_clump_id + 1, 1): msg = "Processing the clump %s of %s from the landmask %s" % ( str(clump_id), str(max_clump_id), str(nr)) msg = "\n\n" + str(msg) + "\n\n" print(msg) # identify mask based on the clump mask_selected_boolean_from_clump = pcr.ifthen( clump_ids == pcr.nominal(clump_id), mask_selected_boolean) mask_selected_boolean_from_clump = pcr.ifthen( mask_selected_boolean_from_clump, mask_selected_boolean_from_clump) # check whether the clump is empty check_mask_selected_boolean_from_clump = pcr.ifthen( mask_selected_boolean, mask_selected_boolean_from_clump) check_if_empty = float( pcr.cellvalue( pcr.mapmaximum( pcr.scalar( pcr.defined( check_mask_selected_boolean_from_clump))), 1)[0]) if check_if_empty == 0.0: msg = "Map is empty !" msg = "\n\n" + str(msg) + "\n\n" print(msg) else: msg = "Map is NOT empty !" msg = "\n\n" + str(msg) + "\n\n" print(msg) # assign the clone code assigned_number = assigned_number + 1 # update global landmask for river and land mask_selected_nominal = pcr.ifthen( mask_selected_boolean_from_clump, pcr.nominal(assigned_number)) subdomains_final = pcr.cover(subdomains_final, mask_selected_nominal) # ~ # kill all aguila processes if exist # ~ os.system('killall aguila') pcr.aguila(subdomains_final) print("") print("") print("") print("The subdomain map is READY.") pcr.report(subdomains_final, "global_subdomains_final.map") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_final))[1]) print(num_of_masks) print("") print("") print("") print("Making the clone and landmask maps for all subdomains") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_final))[1]) # clone and mask folders clone_folder = out_folder + "/clone/" if os.path.exists(clone_folder): shutil.rmtree(clone_folder) os.makedirs(clone_folder) mask_folder = out_folder + "/mask/" if os.path.exists(mask_folder): shutil.rmtree(mask_folder) os.makedirs(mask_folder) print("") print("") for nr in range(1, num_of_masks + 1, 1): msg = "Processing the subdomain %s" % (str(nr)) print(msg) # set the global clone pcr.setclone(global_clone_map_file) mask_selected_boolean = pcr.ifthen(subdomains_final == nr, pcr.boolean(1.0)) mask_selected_nominal = pcr.ifthen(subdomains_final == nr, pcr.nominal(nr)) mask_file = "mask/mask_%s.map" % (str(nr)) pcr.report(mask_selected_nominal, mask_file) xmin, ymin, xmax, ymax = boundingBox(mask_selected_boolean) area_in_degree2 = (xmax - xmin) * (ymax - ymin) print( str(nr) + " ; " + str(area_in_degree2) + " ; " + str((xmax - xmin)) + " ; " + str((ymax - ymin))) # cellsize in arcdegree cellsize = cellsize_in_arcmin / 60. # number of rows and cols num_rows = int(round(ymax - ymin) / cellsize) num_cols = int(round(xmax - xmin) / cellsize) # make the clone map using mapattr clonemap_mask_file = "clone/clonemap_mask_%s.map" % (str(nr)) cmd = "mapattr -s -R %s -C %s -B -P yb2t -x %s -y %s -l %s %s" % ( str(num_rows), str(num_cols), str(xmin), str(ymax), str(cellsize), clonemap_mask_file) print(cmd) os.system(cmd) # set the local landmask for the clump pcr.setclone(clonemap_mask_file) local_mask = vos.readPCRmapClone(v = mask_file, \ cloneMapFileName = clonemap_mask_file, tmpDir = tmp_folder, \ absolutePath = None, isLddMap = False, cover = None, isNomMap = True) local_mask_boolean = pcr.defined(local_mask) local_mask_boolean = pcr.ifthen(local_mask_boolean, local_mask_boolean) pcr.report(local_mask_boolean, mask_file) print("") print("") print("") print(num_of_masks)
except: pass # initiate the netcd file and object: tssNetCDF = ConvertMapsToNetCDF4(cloneMapFile = cloneMapFileName, attribute = attributeDictionary) tssNetCDF.createNetCDF(ncFileName,varNames,varUnits) index = 0 # for posCnt # set clone and define land mask region pcr.setclone(landmaskFile) landmask = pcr.defined(pcr.readmap(landmaskFile)) landmask = pcr.ifthen(landmask, landmask) # cell area (m2) cellArea = vos.readPCRmapClone(cellAreaFile, cloneMapFileName,tmp_directory) cellArea = pcr.ifthen(landmask,cellArea) for iYear in range(staYear,endYear+1): # time stamp timeStamp = datetime.datetime(int(iYear),int(1),int(1),int(0)) fulldate = '%4i-%02i-%02i' %(int(iYear),int(1),int(1)) print fulldate # index for time object in the netcdf file: index = index + 1 # reading values from the input netcdf files (30min) abstraction_volume_30min = pcr.roundup( vos.netcdf2PCRobjClone(inputDirectory+inputFiles,\
# class map file name: #~ class_map_file_name = "/home/sutan101/data/aqueduct_gis_layers/aqueduct_shp_from_marta/Aqueduct_States.map" #~ class_map_file_name = "/home/sutan101/data/aqueduct_gis_layers/aqueduct_shp_from_marta/Aqueduct_GDBD.map" #~ class_map_file_name = "/home/sutan101/data/processing_whymap/version_19september2014/major_aquifer_30min.extended.map" #~ class_map_file_name = "/home/sutan101/data/processing_whymap/version_19september2014/major_aquifer_30min.map" class_map_file_name = str(sys.argv[2]) class_map_default_folder = "/home/sutan101/data/aqueduct_gis_layers/aqueduct_shp_from_marta/" if class_map_file_name == "state": class_map_file_name = class_map_default_folder + "/Aqueduct_States.map" if class_map_file_name == "drainage_unit": class_map_file_name = class_map_default_folder + "/Aqueduct_GDBD.map" if class_map_file_name == "aquifer": class_map_file_name = class_map_default_folder + "/why_wgs1984_BUENO.map" if class_map_file_name == "country": class_map_file_name = "/home/sutan101/data/country_shp_from_tianyi/World_Polys_High.map" # reading the class map class_map = pcr.nominal(pcr.uniqueid(landmask)) if class_map_file_name != "pixel": class_map = vos.readPCRmapClone(class_map_file_name, clone_map, tmp_directory, None, False, None, True, False) class_map = pcr.ifthen(pcr.scalar(class_map) > 0.0, pcr.nominal(class_map)) # time selection start_year = int(sys.argv[3]) end_year = int(sys.argv[4]) # cell_area (unit: m2) cell_area = pcr.readmap("/data/hydroworld/PCRGLOBWB20/input5min/routing/cellsize05min.correct.map") segment_cell_area = pcr.areatotal(cell_area, class_map) # extent of aquifer/sedimentary basins: sedimentary_basin = pcr.cover(pcr.scalar(pcr.readmap("/home/sutan101/data/sed_extent/sed_extent.map")), 0.0) cell_area = sedimentary_basin * cell_area #~ cell_area = pcr.ifthenelse(pcr.areatotal(cell_area, class_map) > 0.25 * segment_cell_area, cell_area, 0.0)
out_file = inp_file + "_climatology_average.nc" cmd = "cdo -L -f nc4 -z zip -timavg " + inp_file + " " + out_file print("") print(cmd) os.system(cmd) print("") input_files['averageClimatologyDischargeMonthAvg'] = out_file # set the pcraster clone, ldd, landmask, and cell area map msg = "Setting the clone, ldd, landmask, and cell area maps" + ":" logger.info(msg) # - clone clone_map_file = input_files['clone_map_05min'] pcr.setclone(clone_map_file) # - ldd ldd = vos.readPCRmapClone(input_files['ldd_map_05min'], clone_map_file, output_files['tmp_folder'], None, True) ldd = pcr.lddrepair(pcr.ldd(ldd)) ldd = pcr.lddrepair(ldd) # - landmask landmask = pcr.ifthen(pcr.defined(ldd), pcr.boolean(1.0)) # - cell area cell_area = vos.readPCRmapClone(input_files['cell_area_05min'], clone_map_file, output_files['tmp_folder']) # set the basin map msg = "Setting the basin map" + ":" logger.info(msg) basin_map = pcr.nominal(\ vos.readPCRmapClone(input_files['basin_map_05min'], input_files['clone_map_05min'], output_files['tmp_folder'],
def __init__(self, iniItems, landmask, spinUp): object.__init__(self) self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.inputDir = iniItems.globalOptions['inputDir'] # landmask/area of interest self.landmask = landmask if iniItems.globalOptions['landmask'] != "None": self.landmask = vos.readPCRmapClone(\ iniItems.globalOptions['landmask'], self.cloneMap,self.tmpDir,self.inputDir) # option to ignore snow (temperature will be set to 25 deg C if this option is activated) self.ignore_snow = False if 'ignoreSnow' in list(iniItems.meteoOptions.keys( )) and iniItems.meteoOptions['ignoreSnow'] == "True": self.ignore_snow = True self.preFileNC = iniItems.meteoOptions[ 'precipitationNC'] # starting from 19 Feb 2014, we only support netcdf input files self.tmpFileNC = iniItems.meteoOptions['temperatureNC'] self.refETPotMethod = iniItems.meteoOptions['referenceETPotMethod'] if self.refETPotMethod == 'Hamon': self.latitudes = \ pcr.ycoordinate(self.cloneMap) # needed to calculate 'referenceETPot' if self.refETPotMethod == 'Input': self.etpFileNC = \ iniItems.meteoOptions['refETPotFileNC'] #----------------------------------------------------------------------- # NOTE: RvB 13/07/2016 Added correction constant and factor and variable name # to allow for easier use of netCDF climate inpute files # EHS 20/08/2016 modified for more flexibilities. # - meteo conversion factors self.preConst = 0.0 self.preFactor = 1.0 self.tmpConst = 0.0 self.tmpFactor = 1.0 self.refETPotConst = 0.0 self.refETPotFactor = 1.0 self.read_meteo_conversion_factors(iniItems.meteoOptions) # - variable names self.preVarName = 'precipitation' self.tmpVarName = 'temperature' self.refETPotVarName = 'evapotranspiration' self.read_meteo_variable_names(iniItems.meteoOptions) # daily time step self.usingDailyTimeStepForcingData = False if iniItems.timeStep == 1.0 and iniItems.timeStepUnit == "day": self.usingDailyTimeStepForcingData = True # forcing downscaling options: self.forcingDownscalingOptions(iniItems) # option to use netcdf files that are defined per year (one file for each year) self.precipitation_set_per_year = iniItems.meteoOptions[ 'precipitation_set_per_year'] == "True" self.temperature_set_per_year = iniItems.meteoOptions[ 'temperature_set_per_year'] == "True" self.refETPotFileNC_set_per_year = iniItems.meteoOptions[ 'refETPotFileNC_set_per_year'] == "True" # make the iniItems available for the other modules: self.iniItems = iniItems self.report = True try: self.outDailyTotNC = iniItems.meteoOptions['outDailyTotNC'].split( ",") self.outMonthTotNC = iniItems.meteoOptions['outMonthTotNC'].split( ",") self.outMonthAvgNC = iniItems.meteoOptions['outMonthAvgNC'].split( ",") self.outMonthEndNC = iniItems.meteoOptions['outMonthEndNC'].split( ",") self.outAnnuaTotNC = iniItems.meteoOptions['outAnnuaTotNC'].split( ",") self.outAnnuaAvgNC = iniItems.meteoOptions['outAnnuaAvgNC'].split( ",") self.outAnnuaEndNC = iniItems.meteoOptions['outAnnuaEndNC'].split( ",") except: self.report = False if self.report == True: # daily output in netCDF files: self.outNCDir = iniItems.outNCDir self.netcdfObj = PCR2netCDF(iniItems) # if self.outDailyTotNC[0] != "None": for var in self.outDailyTotNC: # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_dailyTot.nc",\ var,"undefined") # MONTHly output in netCDF files: # - cummulative if self.outMonthTotNC[0] != "None": for var in self.outMonthTotNC: # initiating monthlyVarTot (accumulator variable): vars(self)[var + 'MonthTot'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthTot.nc",\ var,"undefined") # - average if self.outMonthAvgNC[0] != "None": for var in self.outMonthAvgNC: # initiating monthlyTotAvg (accumulator variable) vars(self)[var + 'MonthTot'] = None # initiating monthlyVarAvg: vars(self)[var + 'MonthAvg'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthAvg.nc",\ var,"undefined") # - last day of the month if self.outMonthEndNC[0] != "None": for var in self.outMonthEndNC: # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthEnd.nc",\ var,"undefined") # YEARly output in netCDF files: # - cummulative if self.outAnnuaTotNC[0] != "None": for var in self.outAnnuaTotNC: # initiating yearly accumulator variable: vars(self)[var + 'AnnuaTot'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaTot.nc",\ var,"undefined") # - average if self.outAnnuaAvgNC[0] != "None": for var in self.outAnnuaAvgNC: # initiating annualyVarAvg: vars(self)[var + 'AnnuaAvg'] = None # initiating annualyTotAvg (accumulator variable) vars(self)[var + 'AnnuaTot'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaAvg.nc",\ var,"undefined") # - last day of the year if self.outAnnuaEndNC[0] != "None": for var in self.outAnnuaEndNC: # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaEnd.nc",\ var,"undefined")
def dynamic(self): # re-calculate current model time using current pcraster timestep value self.modelTime.update(self.currentTimeStep()) # for variables other than temperature and maximum temperature, just read them directly if self.output['variable_name'] != "temperature" and self.output['variable_name'] != "maximum_temperature": pcraster_map_file_name = pcr.framework.frameworkBase.generateNameT(self.pcraster_file_name,\ self.modelTime.timeStepPCR) pcr_map_values = vos.readPCRmapClone(v = pcraster_map_file_name,\ cloneMapFileName = self.cloneMapFileName,\ tmpDir = self.tmpDir,\ absolutePath = None, isLddMap = False,\ cover = None,\ isNomMap = False,\ inputEPSG = self.inputEPSG,\ outputEPSG = self.outputEPSG,\ method = self.resample_method) # for temperature and maximum temperature, we have to make sure that maximum temperature is higher than minimum temperature if self.output['variable_name'] == "temperature" or self.output['variable_name'] == "maximum_temperature": min_map_file_name = pcr.framework.frameworkBase.generateNameT(self.pcraster_files['directory']+"/tn", self.modelTime.timeStepPCR) max_map_file_name = pcr.framework.frameworkBase.generateNameT(self.pcraster_files['directory']+"/tx", self.modelTime.timeStepPCR) min_map_values = vos.readPCRmapClone(v = min_map_file_name,\ cloneMapFileName = self.cloneMapFileName,\ tmpDir = self.tmpDir,\ absolutePath = None, isLddMap = False,\ cover = None,\ isNomMap = False,\ inputEPSG = self.inputEPSG,\ outputEPSG = self.outputEPSG,\ method = self.resample_method) max_map_values = vos.readPCRmapClone(v = max_map_file_name,\ cloneMapFileName = self.cloneMapFileName,\ tmpDir = self.tmpDir,\ absolutePath = None, isLddMap = False,\ cover = None,\ isNomMap = False,\ inputEPSG = self.inputEPSG,\ outputEPSG = self.outputEPSG,\ method = self.resample_method) # make sure that maximum values are higher than minimum values max_map_values = pcr.max(min_map_values, max_map_values) if self.output['variable_name'] == "temperature": pcr_map_values = 0.50*(min_map_values + \ max_map_values) if self.output['variable_name'] == "maximum_temperature": pcr_map_values = pcr.max(min_map_values, max_map_values) # for precipitation, converting the unit from mm.day-1 to m.day-1 if self.output['variable_name'] == "precipitation": pcr_map_values *= 0.001 # reporting timeStamp = datetime.datetime(self.modelTime.year,\ self.modelTime.month,\ self.modelTime.day,0) self.netcdf_report.data2NetCDF(self.output['file_name'],\ self.output['variable_name'],\ pcr.pcr2numpy(pcr_map_values,vos.MV),\ timeStamp)
except: pass # initiate the netcd file and object: tssNetCDF = ConvertMapsToNetCDF4(cloneMapFile = cloneMapFileName, attribute = attributeDictionary, cellSizeInArcMinutes = cellSizeInArcMinutes) tssNetCDF.createNetCDF(ncFileName,varNames,varUnits) index = 0 # for posCnt # set clone and define land mask region pcr.setclone(landmask05minFile) landmask = pcr.defined(pcr.readmap(landmask05minFile)) landmask = pcr.ifthen(landmask, landmask) # cell area at 5 arc min resolution cellArea = vos.readPCRmapClone(cellArea05minFile, cloneMapFileName,tmp_directory) cellArea = pcr.ifthen(landmask,cellArea) # ids for every 30 arc min grid: uniqueIDs30min = vos.readPCRmapClone(uniqueIDs30minFile, cloneMapFileName,tmp_directory) uniqueIDs30min = pcr.nominal(pcr.ifthen(landmask, uniqueIDs30min)) for iYear in range(staYear,endYear+1): for iMonth in range(1,12+1): timeStamp = datetime.datetime(int(iYear),int(iMonth),int(1),int(0)) fulldate = '%4i-%02i-%02i' %(int(iYear),int(iMonth),int(1)) print fulldate monthRange = float(calendar.monthrange(int(iYear), int(iMonth))[1])
def __init__(self, iniItems,landmask,spinUp): object.__init__(self) self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask # option to activate water balance check self.debugWaterBalance = True if iniItems.routingOptions['debugWaterBalance'] == "False": self.debugWaterBalance = False if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign the recession coefficient parameter(s) self.recessionCoeff = vos.readPCRmapClone(\ iniItems.groundwaterOptions['recessionCoeff'], self.cloneMap,self.tmpDir,self.inputDir) else: groundwaterPropertiesNC = vos.getFullPath(\ iniItems.groundwaterOptions[\ 'groundwaterPropertiesNC'], self.inputDir) self.recessionCoeff = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'recessionCoeff',\ cloneMapFileName = self.cloneMap) # groundwater recession coefficient (day-1_ self.recessionCoeff = pcr.cover(self.recessionCoeff,0.00) self.recessionCoeff = pcr.min(1.0000,self.recessionCoeff) # if 'minRecessionCoeff' in iniItems.groundwaterOptions.keys(): minRecessionCoeff = float(iniItems.groundwaterOptions['minRecessionCoeff']) else: minRecessionCoeff = 1.0e-4 # This is the minimum value used in Van Beek et al. (2011). self.recessionCoeff = pcr.max(minRecessionCoeff,self.recessionCoeff) if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign aquifer specific yield self.specificYield = vos.readPCRmapClone(\ iniItems.groundwaterOptions['specificYield'], self.cloneMap,self.tmpDir,self.inputDir) else: self.specificYield = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'specificYield',\ cloneMapFileName = self.cloneMap) self.specificYield = pcr.cover(self.specificYield,0.0) self.specificYield = pcr.max(0.010,self.specificYield) # TODO: TO BE CHECKED: The resample process of specificYield self.specificYield = pcr.min(1.000,self.specificYield) if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign aquifer saturated conductivity self.kSatAquifer = vos.readPCRmapClone(\ iniItems.groundwaterOptions['kSatAquifer'], self.cloneMap,self.tmpDir,self.inputDir) else: self.kSatAquifer = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'kSatAquifer',\ cloneMapFileName = self.cloneMap) self.kSatAquifer = pcr.cover(self.kSatAquifer,0.0) self.kSatAquifer = pcr.max(0.010,self.kSatAquifer) # limitAbstraction options self.limitAbstraction = False if iniItems.landSurfaceOptions['limitAbstraction'] == "True": self.limitAbstraction = True # option for limitting fossil groundwater abstractions - This option is only defined for IWMI project self.limitFossilGroundwaterAbstraction = False if self.limitAbstraction == False and\ "extraOptionsforProjectWithIWMI" in iniItems.allSections and\ iniItems.extraOptionsforProjectWithIWMI['limitFossilGroundWaterAbstraction'] == "True": logger.info('Fossil groundwater abstraction limit is used (IWMI project).') self.limitFossilGroundwaterAbstraction = True # estimate of thickness (unit: mm) of aceesible groundwater: shallow and deep totalGroundwaterThickness = vos.readPCRmapClone(\ iniItems.extraOptionsforProjectWithIWMI['estimateOfTotalGroundwaterThickness'], self.cloneMap,self.tmpDir,self.inputDir) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 1.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 1.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 2.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 5.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 7.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.mapmaximum(totalGroundwaterThickness)) # set minimum thickness to 50 m: totalGroundwaterThickness = pcr.max(50.0, totalGroundwaterThickness) # estimate of capacity (unit: m) of renewable groundwater (shallow) storGroundwaterCap = pcr.cover( vos.readPCRmapClone(\ iniItems.extraOptionsforProjectWithIWMI['estimateOfRenewableGroundwaterCapacity'], self.cloneMap,self.tmpDir,self.inputDir),\ 0.0) # fossil groundwater capacity (unit: m) self.fossilWaterCap = pcr.max(0.0,\ totalGroundwaterThickness*self.specificYield - storGroundwaterCap) # option for limitting regional groundwater abstractions - This option is only defined self.limitRegionalAnnualGroundwaterAbstraction = False if "extraOptionsforProjectWithIWMI" in iniItems.allSections and\ iniItems.extraOptionsforProjectWithIWMI['limitRegionalAnnualGroundwaterAbstraction'] == "True": logger.info('Limit for regional groundwater abstraction is used (IWMI project).') self.limitRegionalAnnualGroundwaterAbstraction = True region_ids = vos.readPCRmapClone(\ iniItems.extraOptionsforProjectWithIWMI['regionIds'], self.cloneMap,self.tmpDir,self.inputDir) self.region_ids = pcr.nominal(region_ids) self.region_ids = pcr.ifthen(self.landmask, self.region_ids) self.regionalAnnualGroundwaterAbstractionLimit = vos.readPCRmapClone(\ iniItems.extraOptionsforProjectWithIWMI['pumpingCapacity'], self.cloneMap,self.tmpDir,self.inputDir) self.regionalAnnualGroundwaterAbstractionLimit = pcr.roundup(self.regionalAnnualGroundwaterAbstractionLimit*1000.)/1000. self.regionalAnnualGroundwaterAbstractionLimit = pcr.cover(self.regionalAnnualGroundwaterAbstractionLimit, 0.0) self.regionalAnnualGroundwaterAbstractionLimit *= 1000. * 1000. * 1000. # unit: m3/year self.regionalAnnualGroundwaterAbstractionLimit = pcr.ifthen(self.landmask,\ self.regionalAnnualGroundwaterAbstractionLimit) # zones at which water allocation (surface and groundwater allocation) is determined self.usingAllocSegments = False if iniItems.landSurfaceOptions['allocationSegmentsForGroundSurfaceWater'] != "None": self.usingAllocSegments = True # incorporating groundwater distribution network: if self.usingAllocSegments and self.limitAbstraction == False: self.allocSegments = vos.readPCRmapClone(\ iniItems.landSurfaceOptions['allocationSegmentsForGroundSurfaceWater'], self.cloneMap,self.tmpDir,self.inputDir,isLddMap=False,cover=None,isNomMap=True) self.allocSegments = pcr.ifthen(self.landmask, self.allocSegments) cellArea = vos.readPCRmapClone(\ iniItems.routingOptions['cellAreaMap'], self.cloneMap,self.tmpDir,self.inputDir) cellArea = pcr.ifthen(self.landmask, cellArea) # TODO: integrate this one with the one coming from the routing module self.segmentArea = pcr.areatotal(pcr.cover(cellArea, 0.0), self.allocSegments) self.segmentArea = pcr.ifthen(self.landmask, self.segmentArea) self.report = True try: self.outDailyTotNC = iniItems.groundwaterOptions['outDailyTotNC'].split(",") self.outMonthTotNC = iniItems.groundwaterOptions['outMonthTotNC'].split(",") self.outMonthAvgNC = iniItems.groundwaterOptions['outMonthAvgNC'].split(",") self.outMonthEndNC = iniItems.groundwaterOptions['outMonthEndNC'].split(",") self.outAnnuaTotNC = iniItems.groundwaterOptions['outAnnuaTotNC'].split(",") self.outAnnuaAvgNC = iniItems.groundwaterOptions['outAnnuaAvgNC'].split(",") self.outAnnuaEndNC = iniItems.groundwaterOptions['outAnnuaEndNC'].split(",") except: self.report = False if self.report == True: self.outNCDir = iniItems.outNCDir self.netcdfObj = PCR2netCDF(iniItems) # # daily output in netCDF files: if self.outDailyTotNC[0] != "None": for var in self.outDailyTotNC: # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_dailyTot.nc",\ var,"undefined") # MONTHly output in netCDF files: # - cummulative if self.outMonthTotNC[0] != "None": for var in self.outMonthTotNC: # initiating monthlyVarTot (accumulator variable): vars(self)[var+'MonthTot'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthTot.nc",\ var,"undefined") # - average if self.outMonthAvgNC[0] != "None": for var in self.outMonthAvgNC: # initiating monthlyTotAvg (accumulator variable) vars(self)[var+'MonthTot'] = None # initiating monthlyVarAvg: vars(self)[var+'MonthAvg'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthAvg.nc",\ var,"undefined") # - last day of the month if self.outMonthEndNC[0] != "None": for var in self.outMonthEndNC: # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthEnd.nc",\ var,"undefined") # YEARly output in netCDF files: # - cummulative if self.outAnnuaTotNC[0] != "None": for var in self.outAnnuaTotNC: # initiating yearly accumulator variable: vars(self)[var+'AnnuaTot'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaTot.nc",\ var,"undefined") # - average if self.outAnnuaAvgNC[0] != "None": for var in self.outAnnuaAvgNC: # initiating annualyVarAvg: vars(self)[var+'AnnuaAvg'] = None # initiating annualyTotAvg (accumulator variable) vars(self)[var+'AnnuaTot'] = None # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaAvg.nc",\ var,"undefined") # - last day of the year if self.outAnnuaEndNC[0] != "None": for var in self.outAnnuaEndNC: # creating the netCDF files: self.netcdfObj.createNetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaEnd.nc",\ var,"undefined") #get initial conditions self.getICs(iniItems,spinUp)
attributeDictionary['comment' ] = "None" # additional attribute defined in PCR-GLOBWB attributeDictionary['description'] = "prepared by Edwin H. Sutanudjaja" # initiate the netcd object: tssNetCDF = MakingNetCDF(cloneMapFile = cloneMapFileName, \ attribute = attributeDictionary, \ cellSizeInArcMinutes = cellSizeInArcMinutes) # making netcdf files: for var in variable_names: tssNetCDF.createNetCDF(output[var]['file_name'], var, output[var]['unit']) # class (country) ids uniqueIDsFile = "/projects/0/dfguu/users/edwin/data/country_shp_from_tianyi/World_Polys_High.map" uniqueIDs = pcr.nominal(\ vos.readPCRmapClone(uniqueIDsFile, cloneMapFileName, tmp_directory, None, False, None, True)) uniqueIDs = pcr.readmap(uniqueIDsFile) uniqueIDs = pcr.ifthen(pcr.scalar(uniqueIDs) >= 0.0, uniqueIDs) # landmask landmask = pcr.defined(pcr.readmap(landmask05minFile)) landmask = pcr.ifthen(landmask, landmask) # - extending landmask with uniqueIDs landmask = pcr.cover(landmask, pcr.defined(uniqueIDs)) # extending class (country) ids max_step = 5 for i in range(1, max_step+1, 1): cmd = "Extending class: step "+str(i)+" from " + str(max_step) print(cmd) uniqueIDs = pcr.cover(uniqueIDs, pcr.windowmajority(uniqueIDs, 0.5))
def readSoilMapOfFAO(self, iniItems, optionDict = None): # a dictionary/section of options that will be used if optionDict == None: optionDict = iniItems._sections["landSurfaceOptions"] #iniItems.landSurfaceOptions # soil variable names given either in the ini or netCDF file: soilParameters = ['airEntryValue1','airEntryValue2', 'poreSizeBeta1','poreSizeBeta2', 'resVolWC1','resVolWC2', 'satVolWC1','satVolWC2', 'KSat1','KSat2', 'percolationImp'] if optionDict['soilPropertiesNC'] == str(None): for var in soilParameters: input = optionDict[str(var)] vars(self)[var] = \ vos.readPCRmapClone(input,self.cloneMap,\ self.tmpDir,self.inputDir) vars(self)[var] = pcr.scalar(vars(self)[var]) if input == "percolationImp": vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # extrapolation # - TODO: Make a general extrapolation option as a function in the virtualOS.py vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 0.75)) vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 1.00)) vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 1.00)) vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 1.00)) vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 1.00)) vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 1.00)) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) else: soilPropertiesNC = vos.getFullPath(\ optionDict['soilPropertiesNC'], self.inputDir) for var in soilParameters: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(\ soilPropertiesNC,var, \ cloneMapFileName = self.cloneMap) if var == "percolationImp": vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # extrapolation # - TODO: Make a general extrapolation option as a function in the virtualOS.py vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 0.75)) vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 1.00)) vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 1.00)) vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 1.00)) vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 1.00)) vars(self)[var] = pcr.cover(vars(self)[var], pcr.windowaverage(vars(self)[var], 1.00)) vars(self)[var] = pcr.cover(vars(self)[var], 0.01) # make sure that resVolWC1 <= satVolWC1 self.resVolWC1 = pcr.min(self.resVolWC1, self.satVolWC1) self.resVolWC2 = pcr.min(self.resVolWC2, self.satVolWC2) if self.numberOfLayers == 2: self.satVolMoistContUpp = self.satVolWC1 # saturated volumetric moisture content (m3.m-3) self.satVolMoistContLow = self.satVolWC2 self.resVolMoistContUpp = self.resVolWC1 # residual volumetric moisture content (m3.m-3) self.resVolMoistContLow = self.resVolWC2 self.airEntryValueUpp = self.airEntryValue1 # air entry value (m) according to soil water retention curve of Clapp & Hornberger (1978) self.airEntryValueLow = self.airEntryValue2 self.poreSizeBetaUpp = self.poreSizeBeta1 # pore size distribution parameter according to Clapp & Hornberger (1978) self.poreSizeBetaLow = self.poreSizeBeta2 self.kSatUpp = self.KSat1 # saturated hydraulic conductivity (m.day-1) self.kSatLow = self.KSat2 if self.numberOfLayers == 3: self.satVolMoistContUpp000005 = self.satVolWC1 self.satVolMoistContUpp005030 = self.satVolWC1 self.satVolMoistContLow030150 = self.satVolWC2 self.resVolMoistContUpp000005 = self.resVolWC1 self.resVolMoistContUpp005030 = self.resVolWC1 self.resVolMoistContLow030150 = self.resVolWC2 self.airEntryValueUpp000005 = self.airEntryValue1 self.airEntryValueUpp005030 = self.airEntryValue1 self.airEntryValueLow030150 = self.airEntryValue2 self.poreSizeBetaUpp000005 = self.poreSizeBeta1 self.poreSizeBetaUpp005030 = self.poreSizeBeta1 self.poreSizeBetaLow030150 = self.poreSizeBeta2 self.kSatUpp000005 = self.KSat1 self.kSatUpp005030 = self.KSat1 self.kSatLow030150 = self.KSat2 self.percolationImp = pcr.cover(self.percolationImp, 0.0) # fractional area where percolation to groundwater store is impeded (dimensionless) # soil thickness and storage variable names # as given either in the ini or netCDF file: soilStorages = ['firstStorDepth', 'secondStorDepth', 'soilWaterStorageCap1','soilWaterStorageCap2'] if optionDict['soilPropertiesNC'] == str(None): for var in soilStorages: input = optionDict[str(var)] temp = str(var)+'Inp' vars(self)[temp] = vos.readPCRmapClone(input,\ self.cloneMap, self.tmpDir,self.inputDir) # extrapolation # - TODO: Make a general extrapolation option as a function in the virtualOS.py vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 0.75)) vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 1.05)) vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 1.05)) vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 1.05)) vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 1.05)) vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 1.05)) vars(self)[temp] = pcr.cover(vars(self)[temp], 0.0) else: soilPropertiesNC = vos.getFullPath(\ optionDict['soilPropertiesNC'], self.inputDir) for var in soilStorages: temp = str(var)+'Inp' vars(self)[temp] = vos.netcdf2PCRobjCloneWithoutTime(\ soilPropertiesNC,var, \ cloneMapFileName = self.cloneMap) # extrapolation # - TODO: Make a general extrapolation option as a function in the virtualOS.py vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 0.75)) vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 1.05)) vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 1.05)) vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 1.05)) vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 1.05)) vars(self)[temp] = pcr.cover(vars(self)[temp], pcr.windowaverage(vars(self)[temp], 1.05)) vars(self)[temp] = pcr.cover(vars(self)[temp], 0.0) # layer thickness if self.numberOfLayers == 2: self.thickUpp = (0.30/0.30)*self.firstStorDepthInp self.thickLow = (1.20/1.20)*self.secondStorDepthInp if self.numberOfLayers == 3: self.thickUpp000005 = (0.05/0.30)*self.firstStorDepthInp self.thickUpp005030 = (0.25/0.30)*self.firstStorDepthInp self.thickLow030150 = (1.20/1.20)*self.secondStorDepthInp # soil storage if self.numberOfLayers == 2: #~ self.storCapUpp = (0.30/0.30)*self.soilWaterStorageCap1Inp #~ self.storCapLow = (1.20/1.20)*self.soilWaterStorageCap2Inp # 22 Feb 2014: We can calculate this based on thickness and porosity. self.storCapUpp = self.thickUpp * \ (self.satVolMoistContUpp - self.resVolMoistContUpp) self.storCapLow = self.thickLow * \ (self.satVolMoistContLow - self.resVolMoistContLow) self.rootZoneWaterStorageCap = self.storCapUpp + \ self.storCapLow # This is called as WMAX in the original pcrcalc script. if self.numberOfLayers == 3: self.storCapUpp000005 = self.thickUpp000005 * \ (self.satVolMoistContUpp000005 - self.resVolMoistContUpp000005) self.storCapUpp005030 = self.thickUpp005030 * \ (self.satVolMoistContUpp005030 - self.resVolMoistContUpp005030) self.storCapLow030150 = self.thickLow030150 * \ (self.satVolMoistContLow030150 - self.resVolMoistContLow030150) self.rootZoneWaterStorageCap = self.storCapUpp000005 + \ self.storCapUpp005030 + \ self.storCapLow030150
#~ end_year = 2099 # - based on the system arguments: str_year = int(sys.argv[3]) end_year = int(sys.argv[4]) # set the pcraster clone, ldd and landmask maps msg = "Setting the clone, ldd and landmask maps" + ":" logger.info(msg) # - clone clone_map_file = input_files['clone_map_05min'] pcr.setclone(clone_map_file) # - ldd ldd = vos.readPCRmapClone(input_files['ldd_map_05min'], clone_map_file, output_files['tmp_folder'], None, True) ldd = pcr.lddrepair(pcr.ldd(ldd)) ldd = pcr.lddrepair(ldd) # - landmask landmask = pcr.ifthen(pcr.defined(ldd), pcr.boolean(1.0)) # set the cell areas for 5 arc-min and half arc-degree cells msg = "Setting the cell areas for 5 arc-min and half arc-degree cells" + ":" logger.info(msg) # - 5 arc-min cell_area = vos.readPCRmapClone(input_files['cell_area_05min'], clone_map_file, output_files['tmp_folder']) cell_area = pcr.ifthen(landmask, cell_area)
def modflow_simulation(self,\ simulation_type,\ initial_head,\ currTimeStep = None,\ PERLEN = 1.0, NSTP = 1, \ HCLOSE = 1.0,\ RCLOSE = 10.* 400.*400.,\ MXITER = 50,\ ITERI = 30,\ NPCOND = 1,\ RELAX = 1.00,\ NBPOL = 2,\ DAMP = 1,\ ITMUNI = 4, LENUNI = 2, TSMULT = 1.0): # initiate pcraster modflow object if modflow is not called yet: if self.modflow_has_been_called == False or self.modflow_converged == False: self.initiate_modflow() self.modflow_has_been_called = True if simulation_type == "transient": logger.info("Preparing MODFLOW input for a transient simulation.") SSTR = 0 if simulation_type == "steady-state": logger.info("Preparing MODFLOW input for a steady-state simulation.") SSTR = 1 # waterBody class to define the extent of lakes and reservoirs # if simulation_type == "steady-state": self.WaterBodies = waterBodies.WaterBodies(self.iniItems,\ self.landmask,\ self.onlyNaturalWaterBodies) self.WaterBodies.getParameterFiles(date_given = self.iniItems.globalOptions['startTime'],\ cellArea = self.cellAreaMap, \ ldd = self.lddMap) # if simulation_type == "transient": if currTimeStep.timeStepPCR == 1: self.WaterBodies = waterBodies.WaterBodies(self.iniItems,\ self.landmask,\ self.onlyNaturalWaterBodies) if currTimeStep.timeStepPCR == 1 or currTimeStep.doy == 1: self.WaterBodies.getParameterFiles(date_given = str(currTimeStep.fulldate),\ cellArea = self.cellAreaMap, \ ldd = self.lddMap) print "here" # using dem_average as the initial groundwater head value self.pcr_modflow.setInitialHead(initial_head, 1) # set parameter values for the DIS package and PCG solver self.pcr_modflow.setDISParameter(ITMUNI, LENUNI, PERLEN, NSTP, TSMULT, SSTR) self.pcr_modflow.setPCG(MXITER, ITERI, NPCOND, HCLOSE, RCLOSE, RELAX, NBPOL, DAMP) # # Some notes about the values # # ITMUNI = 4 # indicates the time unit (0: undefined, 1: seconds, 2: minutes, 3: hours, 4: days, 5: years) # LENUNI = 2 # indicates the length unit (0: undefined, 1: feet, 2: meters, 3: centimeters) # PERLEN = 1.0 # duration of a stress period # NSTP = 1 # number of time steps in a stress period # TSMULT = 1.0 # multiplier for the length of the successive iterations # SSTR = 1 # 0 - transient, 1 - steady state # # MXITER = 50 # maximum number of outer iterations # Deltares use 50 # ITERI = 30 # number of inner iterations # Deltares use 30 # NPCOND = 1 # 1 - Modified Incomplete Cholesky, 2 - Polynomial matrix conditioning method; # HCLOSE = 0.01 # HCLOSE (unit: m) # RCLOSE = 10.* 400.*400. # RCLOSE (unit: m3) # RELAX = 1.00 # relaxation parameter used with NPCOND = 1 # NBPOL = 2 # indicates whether the estimate of the upper bound on the maximum eigenvalue is 2.0 (but we don ot use it, since NPCOND = 1) # DAMP = 1 # no damping (DAMP introduced in MODFLOW 2000) # read input files (for the steady-state condition, we use pcraster maps): if simulation_type == "steady-state": # - discharge (m3/s) from PCR-GLOBWB discharge = vos.readPCRmapClone(self.iniItems.modflowSteadyStateInputOptions['avgDischargeInputMap'],\ self.cloneMap, self.tmpDir, self.inputDir) # - recharge/capillary rise (unit: m/day) from PCR-GLOBWB gwRecharge = vos.readPCRmapClone(self.iniItems.modflowSteadyStateInputOptions['avgGroundwaterRechargeInputMap'],\ self.cloneMap, self.tmpDir, self.inputDir) if self.ignoreCapRise: gwRecharge = pcr.max(0.0, gwRecharge) gwAbstraction = pcr.spatial(pcr.scalar(0.0)) # read input files (for the transient, input files are given in netcdf files): if simulation_type == "transient": # - discharge (m3/s) from PCR-GLOBWB discharge = vos.netcdf2PCRobjClone(self.iniItems.modflowTransientInputOptions['dischargeInputNC'], "discharge",str(currTimeStep.fulldate),None,self.cloneMap) # - recharge/capillary rise (unit: m/day) from PCR-GLOBWB gwRecharge = vos.netcdf2PCRobjClone(self.iniItems.modflowTransientInputOptions['groundwaterRechargeInputNC'],\ "groundwater_recharge",str(currTimeStep.fulldate),None,self.cloneMap) if self.ignoreCapRise: gwRecharge = pcr.max(0.0, gwRecharge) # - groundwater abstraction (unit: m/day) from PCR-GLOBWB gwAbstraction = vos.netcdf2PCRobjClone(self.iniItems.modflowTransientInputOptions['groundwaterAbstractionInputNC'],\ "total_groundwater_abstraction",str(currTimeStep.fulldate),None,self.cloneMap) # set recharge, river, well and drain packages self.set_river_package(discharge, currTimeStep) self.set_recharge_package(gwRecharge) self.set_well_package(gwAbstraction) self.set_drain_package() # execute MODFLOW logger.info("Executing MODFLOW.") self.pcr_modflow.run() logger.info("Check if the model whether a run has converged or not") self.modflow_converged = self.check_modflow_convergence() if self.modflow_converged == False: msg = "MODFLOW FAILED TO CONVERGE with HCLOSE = "+str(HCLOSE)+" and RCLOSE = "+str(RCLOSE) logger.info(msg) # iteration index for the RCLOSE self.iteration_RCLOSE += 1 # reset if the index has reached the length of available criteria if self.iteration_RCLOSE > (len(self.criteria_RCLOSE)-1): self.iteration_RCLOSE = 0 # iteration index for the HCLOSE if self.iteration_RCLOSE == 0: self.iteration_HCLOSE += 1 # we have to reset modflow as we want to change the PCG setup self.modflow_has_been_called = False # for the steady state simulation, we still save the calculated head as the initial estimate for the next iteration if simulation_type == "steady-state": self.groundwaterHead = self.pcr_modflow.getHeads(1) # NOTE: We cannot implement this principle for transient simulation else: msg = "HURRAY!!! MODFLOW CONVERGED with HCLOSE = "+str(HCLOSE)+" and RCLOSE = "+str(RCLOSE) logger.info(msg) # reset the iteration because modflow has converged self.iteration_HCLOSE = 0 self.iteration_RCLOSE = 0 self.modflow_has_been_called = True # obtaining the results from modflow simulation self.groundwaterHead = None self.groundwaterHead = self.pcr_modflow.getHeads(1) # calculate groundwater depth only in the landmask region self.groundwaterDepth = pcr.ifthen(self.landmask, self.dem_average - self.groundwaterHead)
def __init__(self, iniItems, landmask): object.__init__(self) # cloneMap, temporary directory for the resample process, temporary directory for the modflow process, absolute path for input directory, landmask self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.tmp_modflow_dir = iniItems.tmp_modflow_dir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask # configuration from the ini file self.iniItems = iniItems # topography properties: read several variables from the netcdf file for var in ['dem_minimum','dem_maximum','dem_average','dem_standard_deviation',\ 'slopeLength','orographyBeta','tanslope',\ 'dzRel0000','dzRel0001','dzRel0005',\ 'dzRel0010','dzRel0020','dzRel0030','dzRel0040','dzRel0050',\ 'dzRel0060','dzRel0070','dzRel0080','dzRel0090','dzRel0100']: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['topographyNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # channel properties: read several variables from the netcdf file for var in ['lddMap','cellAreaMap','gradient','bankfull_width', 'bankfull_depth','dem_floodplain','dem_riverbed']: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['channelNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # minimum channel width minimum_channel_width = 0.5 # TODO: Define this one in the configuration file self.bankfull_width = pcr.max(minimum_channel_width, self.bankfull_width) #~ # cell fraction if channel water reaching the flood plan # NOT USED YET #~ self.flood_plain_fraction = self.return_innundation_fraction(pcr.max(0.0, self.dem_floodplain - self.dem_minimum)) # coefficient of Manning self.manningsN = vos.readPCRmapClone(self.iniItems.modflowParameterOptions['manningsN'],\ self.cloneMap,self.tmpDir,self.inputDir) # minimum channel gradient minGradient = 0.00005 # TODO: Define this one in the configuration file self.gradient = pcr.max(minGradient, pcr.cover(self.gradient, minGradient)) # correcting lddMap self.lddMap = pcr.ifthen(pcr.scalar(self.lddMap) > 0.0, self.lddMap) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) # channelLength = approximation of channel length (unit: m) # This is approximated by cell diagonal. cellSizeInArcMin = np.round(pcr.clone().cellSize()*60.) # FIXME: This one will not work if you use the resolution: 0.5, 1.5, 2.5 arc-min verticalSizeInMeter = cellSizeInArcMin*1852. horizontalSizeInMeter = self.cellAreaMap/verticalSizeInMeter self.channelLength = ((horizontalSizeInMeter)**(2)+\ (verticalSizeInMeter)**(2))**(0.5) # option for lakes and reservoir self.onlyNaturalWaterBodies = False if self.iniItems.modflowParameterOptions['onlyNaturalWaterBodies'] == "True": self.onlyNaturalWaterBodies = True # groundwater linear recession coefficient (day-1) ; the linear reservoir concept is still being used to represent fast response flow # particularly from karstic aquifer in mountainous regions self.recessionCoeff = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'recessionCoeff', self.cloneMap) self.recessionCoeff = pcr.cover(self.recessionCoeff,0.00) self.recessionCoeff = pcr.min(1.0000,self.recessionCoeff) # if 'minRecessionCoeff' in iniItems.modflowParameterOptions.keys(): minRecessionCoeff = float(iniItems.modflowParameterOptions['minRecessionCoeff']) else: minRecessionCoeff = 1.0e-4 # This is the minimum value used in Van Beek et al. (2011). self.recessionCoeff = pcr.max(minRecessionCoeff,self.recessionCoeff) # aquifer saturated conductivity (m/day) self.kSatAquifer = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'kSatAquifer', self.cloneMap) self.kSatAquifer = pcr.cover(self.kSatAquifer,pcr.mapmaximum(self.kSatAquifer)) self.kSatAquifer = pcr.max(0.001,self.kSatAquifer) # TODO: Define the minimum value as part of the configuration file # aquifer specific yield (dimensionless) self.specificYield = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'specificYield', self.cloneMap) self.specificYield = pcr.cover(self.specificYield,pcr.mapmaximum(self.specificYield)) self.specificYield = pcr.max(0.010,self.specificYield) # TODO: TO BE CHECKED: The resample process of specificYield self.specificYield = pcr.min(1.000,self.specificYield) # TODO: Define the minimum value as part of the configuration file # estimate of thickness (unit: m) of accesible groundwater totalGroundwaterThickness = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['estimateOfTotalGroundwaterThicknessNC'],\ 'thickness', self.cloneMap) # extrapolation totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, 0.0) # # set minimum thickness minimumThickness = pcr.scalar(float(\ self.iniItems.modflowParameterOptions['minimumTotalGroundwaterThickness'])) totalGroundwaterThickness = pcr.max(minimumThickness, totalGroundwaterThickness) # # set maximum thickness: 250 m. # TODO: Define this one as part of the ini file maximumThickness = 250. self.totalGroundwaterThickness = pcr.min(maximumThickness, totalGroundwaterThickness) # TODO: Define the maximum value as part of the configuration file # surface water bed thickness (unit: m) bed_thickness = 0.1 # TODO: Define this as part of the configuration file # surface water bed resistance (unit: day) bed_resistance = bed_thickness / (self.kSatAquifer) minimum_bed_resistance = 1.0 # TODO: Define this as part of the configuration file self.bed_resistance = pcr.max(minimum_bed_resistance,\ bed_resistance,) # option to ignore capillary rise self.ignoreCapRise = True if self.iniItems.modflowParameterOptions['ignoreCapRise'] == "False": self.ignoreCapRise = False # a variable to indicate if the modflow has been called or not self.modflow_has_been_called = False # list of the convergence criteria for HCLOSE (unit: m) # - Deltares default's value is 0.001 m # check this value with Jarno self.criteria_HCLOSE = [0.001, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] self.criteria_HCLOSE = sorted(self.criteria_HCLOSE) # list of the convergence criteria for RCLOSE (unit: m3) # - Deltares default's value for their 25 and 250 m resolution models is 10 m3 # check this value with Jarno cell_area_assumption = verticalSizeInMeter * float(pcr.cellvalue(pcr.mapmaximum(horizontalSizeInMeter),1)[0]) self.criteria_RCLOSE = [10., 10.* cell_area_assumption/(250.*250.), 10.* cell_area_assumption/(25.*25.)] self.criteria_RCLOSE = sorted(self.criteria_RCLOSE) # initiate the index for HCLOSE and RCLOSE self.iteration_HCLOSE = 0 self.iteration_RCLOSE = 0 # initiate old style reporting # TODO: remove this! self.initiate_old_style_groundwater_reporting(iniItems)
def __init__(self, iniItems, landmask, onlyNaturalWaterBodies=False, lddMap=None): object.__init__(self) # clone map file names, temporary directory and global/absolute path of input directory self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask self.iniItems = iniItems # local drainage direction: if lddMap is None: self.lddMap = vos.readPCRmapClone( iniItems.routingOptions['lddMap'], self.cloneMap, self.tmpDir, self.inputDir, True) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) self.lddMap = pcr.lddrepair(self.lddMap) else: self.lddMap = lddMap # the following is needed for a modflowOfflineCoupling run if 'modflowOfflineCoupling' in list(iniItems.globalOptions.keys( )) and iniItems.globalOptions[ 'modflowOfflineCoupling'] == "True" and 'routingOptions' not in iniItems.allSections: logger.info( "The 'routingOptions' are not defined in the configuration ini file. We will adopt them from the 'modflowParameterOptions'." ) iniItems.routingOptions = iniItems.modflowParameterOptions # option to activate water balance check self.debugWaterBalance = True if 'debugWaterBalance' in list(iniItems.routingOptions.keys( )) and iniItems.routingOptions['debugWaterBalance'] == "False": self.debugWaterBalance = False # option to perform a run with only natural lakes (without reservoirs) self.onlyNaturalWaterBodies = onlyNaturalWaterBodies if "onlyNaturalWaterBodies" in list(iniItems.routingOptions.keys( )) and iniItems.routingOptions['onlyNaturalWaterBodies'] == "True": logger.info( "Using only natural water bodies identified in the year 1900. All reservoirs in 1900 are assumed as lakes." ) self.onlyNaturalWaterBodies = True self.dateForNaturalCondition = "1900-01-01" # The run for a natural condition should access only this date. # names of files containing water bodies parameters if iniItems.routingOptions['waterBodyInputNC'] == str(None): self.useNetCDF = False self.fracWaterInp = iniItems.routingOptions['fracWaterInp'] self.waterBodyIdsInp = iniItems.routingOptions['waterBodyIds'] self.waterBodyTypInp = iniItems.routingOptions['waterBodyTyp'] self.resMaxCapInp = iniItems.routingOptions['resMaxCapInp'] self.resSfAreaInp = iniItems.routingOptions['resSfAreaInp'] else: self.useNetCDF = True self.ncFileInp = vos.getFullPath(\ iniItems.routingOptions['waterBodyInputNC'],\ self.inputDir) # minimum width (m) used in the weir formula # TODO: define minWeirWidth based on the GLWD, GRanD database and/or bankfull discharge formula self.minWeirWidth = 10. # lower and upper limits at which reservoir release is terminated and # at which reservoir release is equal to long-term average outflow # - default values self.minResvrFrac = 0.10 self.maxResvrFrac = 0.75 # - from the ini file if "minResvrFrac" in list(iniItems.routingOptions.keys()): minResvrFrac = iniItems.routingOptions['minResvrFrac'] self.minResvrFrac = vos.readPCRmapClone(minResvrFrac, self.cloneMap, self.tmpDir, self.inputDir) if "maxResvrFrac" in list(iniItems.routingOptions.keys()): maxResvrFrac = iniItems.routingOptions['maxResvrFrac'] self.maxResvrFrac = vos.readPCRmapClone(maxResvrFrac, self.cloneMap, self.tmpDir, self.inputDir)
def getParameterFiles(self,currTimeStep,cellArea,ldd,\ initial_condition_dictionary = None,\ currTimeStepInDateTimeFormat = False): # parameters for Water Bodies: fracWat # waterBodyIds # waterBodyOut # waterBodyArea # waterBodyTyp # waterBodyCap # cell surface area (m2) and ldd self.cellArea = cellArea ldd = pcr.ifthen(self.landmask, ldd) # date used for accessing/extracting water body information if currTimeStepInDateTimeFormat: date_used = currTimeStep year_used = currTimeStep.year else: date_used = currTimeStep.fulldate year_used = currTimeStep.year if self.onlyNaturalWaterBodies == True: date_used = self.dateForNaturalCondition year_used = self.dateForNaturalCondition[0:4] # fracWat = fraction of surface water bodies (dimensionless) self.fracWat = pcr.scalar(0.0) if self.useNetCDF: self.fracWat = vos.netcdf2PCRobjClone(self.ncFileInp,'fracWaterInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.fracWat = vos.readPCRmapClone(\ self.fracWaterInp+str(year_used)+".map", self.cloneMap,self.tmpDir,self.inputDir) self.fracWat = pcr.cover(self.fracWat, 0.0) self.fracWat = pcr.max(0.0, self.fracWat) self.fracWat = pcr.min(1.0, self.fracWat) self.waterBodyIds = pcr.nominal(0) # waterBody ids self.waterBodyOut = pcr.boolean(0) # waterBody outlets self.waterBodyArea = pcr.scalar(0.) # waterBody surface areas # water body ids if self.useNetCDF: self.waterBodyIds = vos.netcdf2PCRobjClone(self.ncFileInp,'waterBodyIds', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.waterBodyIds = vos.readPCRmapClone(\ self.waterBodyIdsInp+str(year_used)+".map",\ self.cloneMap,self.tmpDir,self.inputDir,False,None,True) # self.waterBodyIds = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ pcr.nominal(self.waterBodyIds)) # water body outlets (correcting outlet positions) wbCatchment = pcr.catchmenttotal(pcr.scalar(1), ldd) self.waterBodyOut = pcr.ifthen(wbCatchment ==\ pcr.areamaximum(wbCatchment, \ self.waterBodyIds),\ self.waterBodyIds) # = outlet ids # This may give more than two outlets, particularly if there are more than one cells that have largest upstream areas # - make sure that there is only one outlet for each water body self.waterBodyOut = pcr.ifthen(\ pcr.areaorder(pcr.scalar(self.waterBodyOut), \ self.waterBodyOut) == 1., self.waterBodyOut) self.waterBodyOut = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ self.waterBodyOut) # TODO: Please also consider endorheic lakes! # correcting water body ids self.waterBodyIds = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ pcr.subcatchment(ldd,self.waterBodyOut)) # boolean map for water body outlets: self.waterBodyOut = pcr.ifthen(\ pcr.scalar(self.waterBodyOut) > 0.,\ pcr.boolean(1)) # reservoir surface area (m2): if self.useNetCDF: resSfArea = 1000. * 1000. * \ vos.netcdf2PCRobjClone(self.ncFileInp,'resSfAreaInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: resSfArea = 1000. * 1000. * vos.readPCRmapClone( self.resSfAreaInp+str(year_used)+".map",\ self.cloneMap,self.tmpDir,self.inputDir) resSfArea = pcr.areaaverage(resSfArea, self.waterBodyIds) resSfArea = pcr.cover(resSfArea, 0.) # water body surface area (m2): (lakes and reservoirs) self.waterBodyArea = pcr.max(pcr.areatotal(\ pcr.cover(\ self.fracWat*self.cellArea, 0.0), self.waterBodyIds), pcr.areaaverage(\ pcr.cover(resSfArea, 0.0) , self.waterBodyIds)) self.waterBodyArea = pcr.ifthen(self.waterBodyArea > 0.,\ self.waterBodyArea) # correcting water body ids and outlets (exclude all water bodies with surfaceArea = 0) self.waterBodyIds = pcr.ifthen(self.waterBodyArea > 0., self.waterBodyIds) self.waterBodyOut = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyOut) # water body types: # - 2 = reservoirs (regulated discharge) # - 1 = lakes (weirFormula) # - 0 = non lakes or reservoirs (e.g. wetland) self.waterBodyTyp = pcr.nominal(0) if self.useNetCDF: self.waterBodyTyp = vos.netcdf2PCRobjClone(self.ncFileInp,'waterBodyTyp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.waterBodyTyp = vos.readPCRmapClone( self.waterBodyTypInp+str(year_used)+".map",\ self.cloneMap,self.tmpDir,self.inputDir,False,None,True) # excluding wetlands (waterBodyTyp = 0) in all functions related to lakes/reservoirs # self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyTyp) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.areamajority(self.waterBodyTyp,\ self.waterBodyIds) # choose only one type: either lake or reservoir self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyTyp) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyTyp) # correcting lakes and reservoirs ids and outlets self.waterBodyIds = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0, self.waterBodyIds) self.waterBodyOut = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0, self.waterBodyOut) # reservoir maximum capacity (m3): self.resMaxCap = pcr.scalar(0.0) self.waterBodyCap = pcr.scalar(0.0) if self.useNetCDF: self.resMaxCap = 1000. * 1000. * \ vos.netcdf2PCRobjClone(self.ncFileInp,'resMaxCapInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.resMaxCap = 1000. * 1000. * vos.readPCRmapClone(\ self.resMaxCapInp+str(year_used)+".map", \ self.cloneMap,self.tmpDir,self.inputDir) self.resMaxCap = pcr.ifthen(self.resMaxCap > 0,\ self.resMaxCap) self.resMaxCap = pcr.areaaverage(self.resMaxCap,\ self.waterBodyIds) # water body capacity (m3): (lakes and reservoirs) self.waterBodyCap = pcr.cover( self.resMaxCap, 0.0) # Note: Most of lakes have capacities > 0. self.waterBodyCap = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyCap) # correcting water body types: # Reservoirs that have zero capacities will be assumed as lakes. self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyTyp) self.waterBodyTyp = pcr.ifthenelse(self.waterBodyCap > 0.,\ self.waterBodyTyp,\ pcr.ifthenelse(pcr.scalar(self.waterBodyTyp) == 2,\ pcr.nominal(1),\ self.waterBodyTyp)) # final corrections: self.waterBodyTyp = pcr.ifthen(self.waterBodyArea > 0.,\ self.waterBodyTyp) # make sure that all lakes and/or reservoirs have surface areas self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyTyp) # make sure that only types 1 and 2 will be considered in lake/reservoir functions self.waterBodyIds = pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyIds) # make sure that all lakes and/or reservoirs have ids self.waterBodyOut = pcr.ifthen(pcr.scalar(self.waterBodyIds) > 0.,\ self.waterBodyOut) # make sure that all lakes and/or reservoirs have outlets # for a natural run (self.onlyNaturalWaterBodies == True) # which uses only the year 1900, assume all reservoirs are lakes if self.onlyNaturalWaterBodies == True and date_used == self.dateForNaturalCondition: logger.info( "Using only natural water bodies identified in the year 1900. All reservoirs in 1900 are assumed as lakes." ) self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ pcr.nominal(1)) # check that all lakes and/or reservoirs have types, ids, surface areas and outlets: test = pcr.defined(self.waterBodyTyp) & pcr.defined(self.waterBodyArea) &\ pcr.defined(self.waterBodyIds) & pcr.boolean(pcr.areamaximum(pcr.scalar(self.waterBodyOut), self.waterBodyIds)) a, b, c = vos.getMinMaxMean( pcr.cover(pcr.scalar(test), 1.0) - pcr.scalar(1.0)) threshold = 1e-3 if abs(a) > threshold or abs(b) > threshold: logger.warning( "Missing information in some lakes and/or reservoirs.") # at the beginning of simulation period (timeStepPCR = 1) # - we have to define/get the initial conditions # if initial_condition_dictionary != None and currTimeStep.timeStepPCR == 1: self.getICs(initial_condition_dictionary) # For each new reservoir (introduced at the beginning of the year) # initiating storage, average inflow and outflow # PS: THIS IS NOT NEEDED FOR OFFLINE MODFLOW RUN! # try: self.waterBodyStorage = pcr.cover(self.waterBodyStorage, 0.0) self.avgInflow = pcr.cover(self.avgInflow, 0.0) self.avgOutflow = pcr.cover(self.avgOutflow, 0.0) self.waterBodyStorage = pcr.ifthen(self.landmask, self.waterBodyStorage) self.avgInflow = pcr.ifthen(self.landmask, self.avgInflow) self.avgOutflow = pcr.ifthen(self.landmask, self.avgOutflow) except: # PS: FOR OFFLINE MODFLOW RUN! pass # TODO: Remove try and except # cropping only in the landmask region: self.fracWat = pcr.ifthen(self.landmask, self.fracWat) self.waterBodyIds = pcr.ifthen(self.landmask, self.waterBodyIds) self.waterBodyOut = pcr.ifthen(self.landmask, self.waterBodyOut) self.waterBodyArea = pcr.ifthen(self.landmask, self.waterBodyArea) self.waterBodyTyp = pcr.ifthen(self.landmask, self.waterBodyTyp) self.waterBodyCap = pcr.ifthen(self.landmask, self.waterBodyCap)
def readSoil(self, iniItems, optionDict = None): # a dictionary/section of options that will be used if optionDict == None: optionDict = iniItems._sections["landSurfaceOptions"] #iniItems.landSurfaceOptions # default values of soil parameters that are constant/uniform for the entire domain: self.clappAddCoeff = pcr.scalar(3.0) # dimensionless self.matricSuctionFC = pcr.scalar(1.0) # unit: m #~ self.matricSuction50 = pcr.scalar(10./3.) # unit: m self.matricSuction50 = pcr.scalar(3.33) # unit: m self.matricSuctionWP = pcr.scalar(156.0) # unit: m self.maxGWCapRise = pcr.scalar(5.0) # unit: m # # values defined in the ini/configuration file: soilParameterConstants = ['clappAddCoeff', 'matricSuctionFC', 'matricSuction50', 'matricSuctionWP', 'maxGWCapRise'] for var in soilParameterConstants: if var in configsection(iniItems,"landSurfaceOptions"): input = configget(iniItems,"landSurfaceOptions",str(var),"None") vars(self)[var] = vos.readPCRmapClone(input,self.cloneMap,\ self.tmpDir,self.inputDir) # read soil parameter based on the FAO soil map: self.readSoilMapOfFAO(iniItems, optionDict) # assign Campbell's (1974) beta coefficient, as well as degree # of saturation at field capacity and corresponding unsaturated hydraulic conductivity # if self.numberOfLayers == 2: self.campbellBetaUpp = self.poreSizeBetaUpp*2.0 + \ self.clappAddCoeff # Campbell's (1974) coefficient ; Rens's line: BCB = 2*BCH + BCH_ADD self.campbellBetaLow = self.poreSizeBetaLow*2.0 + \ self.clappAddCoeff self.effSatAtFieldCapUpp = \ (self.matricSuctionFC / self.airEntryValueUpp)**\ (-1.0/ self.poreSizeBetaUpp ) # saturation degree at field capacity : THEFF_FC = (PSI_FC/PSI_A)**(-1/BCH) self.effSatAtFieldCapUpp = pcr.cover(self.effSatAtFieldCapUpp, 1.0) self.effSatAtFieldCapLow = \ (self.matricSuctionFC / self.airEntryValueLow)**\ (-1.0/ self.poreSizeBetaLow ) self.effSatAtFieldCapLow = pcr.cover(self.effSatAtFieldCapLow, 1.0) self.kUnsatAtFieldCapUpp = pcr.max(0., \ (self.effSatAtFieldCapUpp ** self.campbellBetaUpp) * self.kSatUpp) # unsaturated conductivity at field capacity: KTHEFF_FC = max(0,THEFF_FC[TYPE]**BCB*KS1) self.kUnsatAtFieldCapLow = pcr.max(0., \ (self.effSatAtFieldCapLow ** self.campbellBetaLow) * self.kSatLow) # if self.numberOfLayers == 3: self.campbellBetaUpp000005 = self.poreSizeBetaUpp000005*2.0 + \ self.clappAddCoeff self.campbellBetaUpp005030 = self.poreSizeBetaUpp005030*2.0 + \ self.clappAddCoeff self.campbellBetaLow030150 = self.poreSizeBetaLow030150*2.0 + \ self.clappAddCoeff self.effSatAtFieldCapUpp000005 = \ (self.matricSuctionFC / self.airEntryValueUpp000005)**\ (-1.0/ self.poreSizeBetaUpp000005) self.effSatAtFieldCapUpp005030 = \ (self.matricSuctionFC / self.airEntryValueUpp005030)**\ (-1.0/ self.poreSizeBetaUpp005030) self.effSatAtFieldCapLow030150 = \ (self.matricSuctionFC / self.airEntryValueLow030150)**\ (-1.0/ self.poreSizeBetaLow030150) self.kUnsatAtFieldCapUpp000005 = pcr.max(0., \ (self.effSatAtFieldCapUpp000005 ** self.campbellBetaUpp000005) * self.kSatUpp000005) self.kUnsatAtFieldCapUpp005030 = pcr.max(0., \ (self.effSatAtFieldCapUpp005030 ** self.campbellBetaUpp005030) * self.kSatUpp005030) self.kUnsatAtFieldCapLow030150 = pcr.max(0., \ (self.effSatAtFieldCapLow030150 ** self.campbellBetaLow030150) * self.kSatLow030150) # calculate degree of saturation at which transpiration is halved (50) # and at wilting point # if self.numberOfLayers == 2: self.effSatAt50Upp = (self.matricSuction50/self.airEntryValueUpp)**\ (-1.0/self.poreSizeBetaUpp) self.effSatAt50Upp = pcr.cover(self.effSatAt50Upp, 1.0) self.effSatAt50Low = (self.matricSuction50/self.airEntryValueLow)**\ (-1.0/self.poreSizeBetaLow) self.effSatAt50Low = pcr.cover(self.effSatAt50Low, 1.0) self.effSatAtWiltPointUpp = pcr.cover(\ (self.matricSuctionWP/self.airEntryValueUpp)**\ (-1.0/self.poreSizeBetaUpp), 1.0) self.effSatAtWiltPointLow = pcr.cover(\ (self.matricSuctionWP/self.airEntryValueLow)**\ (-1.0/self.poreSizeBetaLow), 1.0) if self.numberOfLayers == 3: self.effSatAt50Upp000005 = (self.matricSuction50/self.airEntryValueUpp000005)**\ (-1.0/self.poreSizeBetaUpp000005) self.effSatAt50Upp005030 = (self.matricSuction50/self.airEntryValueUpp005030)**\ (-1.0/self.poreSizeBetaUpp005030) self.effSatAt50Low030150 = (self.matricSuction50/self.airEntryValueLow030150)**\ (-1.0/self.poreSizeBetaLow030150) self.effSatAtWiltPointUpp000005 = \ (self.matricSuctionWP/self.airEntryValueUpp000005)**\ (-1.0/self.poreSizeBetaUpp000005) self.effSatAtWiltPointUpp005030 = \ (self.matricSuctionWP/self.airEntryValueUpp005030)**\ (-1.0/self.poreSizeBetaUpp005030) self.effSatAtWiltPointLow030150 = \ (self.matricSuctionWP/self.airEntryValueLow030150)**\ (-1.0/self.poreSizeBetaLow030150) # calculate interflow parameter (TCL): # if self.numberOfLayers == 2: self.interflowConcTime = (self.kSatLow * self.tanslope*2.0) / \ (self.slopeLength * (1.- self.effSatAtFieldCapLow) * \ (self.satVolMoistContLow - self.resVolMoistContLow)) # TCL = Duration*(2*KS2*TANSLOPE)/(LSLOPE*(1-THEFF2_FC)*(THETASAT2-THETARES2)) # if self.numberOfLayers == 3: self.interflowConcTime = (self.kSatLow030150 * self.tanslope*2.0) / \ (self.slopeLength * (1.-self.effSatAtFieldCapLow030150) * \ (self.satVolMoistContLow030150 - self.resVolMoistContLow030150)) self.interflowConcTime = pcr.max(0.0, pcr.cover(self.interflowConcTime, 0.0))
def modflow_simulation(self,\ simulation_type,\ initial_head_layer_1, initial_head_layer_2,\ currTimeStep = None,\ NSTP = 1, \ HCLOSE = 0.5,\ RCLOSE = 100.* 400.*400.,\ MXITER = 300,\ ITERI = 100,\ NPCOND = 1,\ RELAX = 1.00,\ NBPOL = 2,\ DAMP = 1,\ ITMUNI = 4, LENUNI = 2, PERLEN = 1.0, TSMULT = 1.0): # initiate pcraster modflow object self.initiate_modflow() if simulation_type == "transient": logger.info("Preparing MODFLOW input for a transient simulation.") SSTR = 0 if simulation_type == "steady-state": logger.info( "Preparing MODFLOW input for a steady-state simulation.") SSTR = 1 # waterBody class to define the extent of lakes and reservoirs # if simulation_type == "steady-state": self.WaterBodies = waterBodies.WaterBodies(self.iniItems,\ self.landmask,\ self.onlyNaturalWaterBodies) self.WaterBodies.getParameterFiles(date_given = self.iniItems.globalOptions['startTime'],\ cellArea = self.cellAreaMap, \ ldd = self.lddMap) # if simulation_type == "transient": if currTimeStep.timeStepPCR == 1: self.WaterBodies = waterBodies.WaterBodies(self.iniItems,\ self.landmask,\ self.onlyNaturalWaterBodies) if currTimeStep.timeStepPCR == 1 or currTimeStep.doy == 1: self.WaterBodies.getParameterFiles(date_given = str(currTimeStep.fulldate),\ cellArea = self.cellAreaMap, \ ldd = self.lddMap) # using dem_average as the initial groundwater head value self.pcr_modflow.setInitialHead(initial_head_layer_1, 1) self.pcr_modflow.setInitialHead(initial_head_layer_2, 2) # set parameter values for the DIS package and PCG solver self.pcr_modflow.setDISParameter(ITMUNI, LENUNI, PERLEN, NSTP, TSMULT, SSTR) self.pcr_modflow.setPCG(MXITER, ITERI, NPCOND, HCLOSE, RCLOSE, RELAX, NBPOL, DAMP) # # Some notes about the values # # ITMUNI = 4 # indicates the time unit (0: undefined, 1: seconds, 2: minutes, 3: hours, 4: days, 5: years) # LENUNI = 2 # indicates the length unit (0: undefined, 1: feet, 2: meters, 3: centimeters) # PERLEN = 1.0 # duration of a stress period # NSTP = 1 # number of time steps in a stress period # TSMULT = 1.0 # multiplier for the length of the successive iterations # SSTR = 1 # 0 - transient, 1 - steady state # # MXITER = 100 # maximum number of outer iterations # ITERI = 30 # number of inner iterations # NPCOND = 1 # 1 - Modified Incomplete Cholesky, 2 - Polynomial matrix conditioning method; # HCLOSE = 0.01 # HCLOSE (unit: m) # 0.05 is working # RCLOSE = 10.* 400.*400. # RCLOSE (unit: m3) ; Deltares people uses 100 m3 for their 25 m resolution modflow model # RELAX = 1.00 # relaxation parameter used with NPCOND = 1 # NBPOL = 2 # indicates whether the estimate of the upper bound on the maximum eigenvalue is 2.0 (but we don ot use it, since NPCOND = 1) # DAMP = 1 # no damping (DAMP introduced in MODFLOW 2000) # read input files (for the steady-state condition, we use pcraster maps): if simulation_type == "steady-state": # - discharge (m3/s) from PCR-GLOBWB discharge = vos.readPCRmapClone(self.iniItems.modflowSteadyStateInputOptions['avgDischargeInputMap'],\ self.cloneMap, self.tmpDir, self.inputDir) # - recharge/capillary rise (unit: m/day) from PCR-GLOBWB gwRecharge = vos.readPCRmapClone(self.iniItems.modflowSteadyStateInputOptions['avgGroundwaterRechargeInputMap'],\ self.cloneMap, self.tmpDir, self.inputDir) if self.ignoreCapRise: gwRecharge = pcr.max(0.0, gwRecharge) gwAbstraction = pcr.spatial(pcr.scalar(0.0)) # read input files (for the transient, input files are given in netcdf files): if simulation_type == "transient": # - discharge (m3/s) from PCR-GLOBWB discharge = vos.netcdf2PCRobjClone( self.iniItems.modflowTransientInputOptions['dischargeInputNC'], "discharge", str(currTimeStep.fulldate), None, self.cloneMap) # - recharge/capillary rise (unit: m/day) from PCR-GLOBWB gwRecharge = vos.netcdf2PCRobjClone(self.iniItems.modflowTransientInputOptions['groundwaterRechargeInputNC'],\ "groundwater_recharge",str(currTimeStep.fulldate),None,self.cloneMap) if self.ignoreCapRise: gwRecharge = pcr.max(0.0, gwRecharge) # - groundwater abstraction (unit: m/day) from PCR-GLOBWB gwAbstraction = vos.netcdf2PCRobjClone(self.iniItems.modflowTransientInputOptions['groundwaterAbstractionInputNC'],\ "total_groundwater_abstraction",str(currTimeStep.fulldate),None,self.cloneMap) # set recharge and river packages self.set_river_package(discharge) self.set_recharge_package(gwRecharge) self.set_well_package(gwAbstraction) # execute MODFLOW logger.info("Executing MODFLOW.") self.pcr_modflow.run() # TODO: Add the mechanism to check whether a run has converged or not. # obtaining the results from modflow simulation self.groundwaterHeadLayer2 = None self.groundwaterHeadLayer2 = self.pcr_modflow.getHeads(2) self.groundwaterHeadLayer1 = None self.groundwaterHeadLayer1 = self.pcr_modflow.getHeads(1) # calculate groundwater depth only in the landmask region self.groundwaterDepth = pcr.ifthen( self.landmask, self.dem_average - self.groundwaterHeadLayer2)
def main(): # global map of subdomain masks global_clone_map = "/scratch/mo/nest/ulysses/data/edwin/clone_maps/version_2020-08-04/clone_all_maps/clone_ulysses_06min_global.map" # number of subdomain masks num_of_masks = 54 # list of subdomain mask files for land (all in nc files) subdomain_land_nc = "/scratch/mo/nest/ulysses/data/subdomain_masks/subdomain_land_%s.nc" # lisk of subdomain maks files for touring (all in nc files) subdomain_river_nc = "/scratch/mo/nest/ulysses/data/subdomain_river_masks/subdomain_river_%s.nc" # output folder (and tmp folder) out_folder = "/scratch/mo/nest/ulysses/data/edwin/clone_maps/version_2020-08-04/pcraster_maps/" clean_out_folder = True if os.path.exists(out_folder): if clean_out_folder: shutil.rmtree(out_folder) os.makedirs(out_folder) else: os.makedirs(out_folder) os.chdir(out_folder) os.system("pwd") # make tmp folder tmp_folder = os.path.join(out_folder, "tmp_clone_uly") + "/" if os.path.exists(tmp_folder): shutil.rmtree(tmp_folder) os.makedirs(tmp_folder) # make initial landmask maps at the global extent # - set to the global clone map pcr.setclone(global_clone_map) # - for land landmask_land_all = pcr.ifthen( pcr.scalar(global_clone_map) > 10, pcr.nominal(0)) # - for river landmask_river_and_land_all = pcr.ifthen( pcr.scalar(global_clone_map) > 10, pcr.nominal(0)) for nr in range(1, num_of_masks + 1, 1): msg = "Processing the landmask %s" % (str(nr)) msg = "\n\n" + str(msg) + "\n\n" print(msg) # set to the global clone map pcr.setclone(global_clone_map) # read land nc file (and convert it to pcraster) subdomain_land_nc_file = subdomain_land_nc % (str(nr)) mask_land_selected = vos.netcdf2PCRobjCloneWithoutTime(ncFile = subdomain_land_nc_file, \ varName = "mask",\ cloneMapFileName = global_clone_map,\ LatitudeLongitude = True,\ specificFillValue = "NaN",\ absolutePath = None) mask_land_selected_boolean = pcr.ifthen( pcr.scalar(mask_land_selected) > 0.0, pcr.boolean(1.0)) mask_land_selected_boolean = pcr.ifthen(mask_land_selected_boolean, mask_land_selected_boolean) # update global landmask for land mask_land_selected_nominal = pcr.ifthen(mask_land_selected_boolean, pcr.nominal(nr)) landmask_land_all = pcr.cover(landmask_land_all, mask_land_selected_nominal) # ~ pcr.aguila(landmask_land_all) # read river nc file (and convert it to pcraster) subdomain_river_nc_file = subdomain_river_nc % (str(nr)) mask_river_selected = vos.netcdf2PCRobjCloneWithoutTime(ncFile = subdomain_river_nc_file, \ varName = "mask",\ cloneMapFileName = global_clone_map,\ LatitudeLongitude = True,\ specificFillValue = "NaN",\ absolutePath = None) mask_river_selected_boolean = pcr.ifthen( pcr.scalar(mask_river_selected) > 0.0, pcr.boolean(1.0)) mask_river_selected_boolean = pcr.ifthen(mask_river_selected_boolean, mask_river_selected_boolean) # merge land and river landmask mask_selected_boolean = pcr.cover(mask_land_selected_boolean, mask_river_selected_boolean) mask_selected_nominal = pcr.ifthen(mask_selected_boolean, pcr.nominal(nr)) # ~ pcr.aguila(mask_selected_nominal) filename_for_land_river_mask_at_global_extent = "global_landmask_river_and_land_mask_%s.map" % ( str(nr)) filename_for_land_river_mask_at_global_extent = os.path.join( out_folder, filename_for_land_river_mask_at_global_extent) pcr.report(mask_selected_nominal, filename_for_land_river_mask_at_global_extent) # update global landmask for land and river landmask_river_and_land_all = pcr.cover(landmask_river_and_land_all, mask_selected_nominal) # ~ pcr.aguila(landmask_river_and_land_all) # get the bounding box based on the landmask file xmin, ymin, xmax, ymax = boundingBox(mask_selected_boolean) # cellsize cellsize = vos.getMapAttributes(global_clone_map, "cellsize") num_rows = int(round(ymax - ymin) / cellsize) num_cols = int(round(xmax - xmin) / cellsize) # make the clone map using mapattr clonemap_mask_file = "clonemap_mask_%s.map" % (str(nr)) # - example: mapattr -s -R 19 -C 68 -B -P yb2t -x 12 -y -14.02 -l 0.8 mask2.map cmd = "mapattr -s -R %s -C %s -B -P yb2t -x %s -y %s -l %s %s" % ( str(num_rows), str(num_cols), str(xmin), str(ymax), str(cellsize), clonemap_mask_file) print(cmd) os.system(cmd) # set the landmask for land pcr.setclone(clonemap_mask_file) landmask_land = vos.netcdf2PCRobjCloneWithoutTime(ncFile = subdomain_land_nc_file, \ varName = "mask",\ cloneMapFileName = clonemap_mask_file,\ LatitudeLongitude = True,\ specificFillValue = "NaN",\ absolutePath = None) landmask_land_boolean = pcr.ifthen( pcr.scalar(landmask_land) > 0.0, pcr.boolean(1.0)) landmask_land_boolean = pcr.ifthen(landmask_land_boolean, landmask_land_boolean) # - save the landmask for land (used for PCR-GLOBWB reporting) landmask_land_file = "landmask_land_mask_%s.map" % (str(nr)) pcr.report(landmask_land_boolean, landmask_land_file) # set the landmask for river and land landmask_river_and_land = vos.readPCRmapClone(v = filename_for_land_river_mask_at_global_extent, \ cloneMapFileName = clonemap_mask_file, tmpDir = tmp_folder, \ absolutePath = None, isLddMap = False, cover = None, isNomMap = True) landmask_river_and_land_boolean = pcr.ifthen( pcr.scalar(landmask_river_and_land) > 0.0, pcr.boolean(1.0)) landmask_river_and_land_boolean = pcr.ifthen( landmask_river_and_land_boolean, landmask_river_and_land_boolean) landmask_river_and_land_file = "landmask_river_and_land_mask_%s.map" % ( str(nr)) pcr.report(landmask_river_and_land_boolean, landmask_river_and_land_file) # kill all aguila processes if exist os.system('killall aguila') # report a global nominal map for land pcr.setclone(global_clone_map) filename_for_nominal_land_mask_at_global_extent = "global_landmask_land_mask_all.map" pcr.report(landmask_land_all, filename_for_nominal_land_mask_at_global_extent) pcr.aguila(landmask_land_all) # report a global nominal map for river and and land pcr.setclone(global_clone_map) filename_for_nominal_land_river_mask_at_global_extent = "global_landmask_river_and_land_mask_all.map" pcr.report(landmask_river_and_land_all, filename_for_nominal_land_river_mask_at_global_extent) pcr.aguila(landmask_river_and_land_all) print("\n\n Done \n\n")
# - number of rows and clones nrRows = int((latMax-latMin)/deltaLat) nrCols = int((lonMax-lonMin)/deltaLon) # - make and set the clone map tempCloneMap = outputDir+'/temp_clone.map' command = 'mapattr -s -R %d -C %d -P "yb2t" -B -x %f -y %f -l %f %s' %\ (nrRows,nrCols,lonMin,latMax,deltaLat,tempCloneMap) vos.cmd_line(command, using_subprocess = False) # - set the clone map pcr.setclone(tempCloneMap) clone_map_file = tempCloneMap # set the landmask landmask_05_min = pcr.defined( vos.readPCRmapClone("extended_landmask_5min.map", \ clone_map_file, \ tmp_folder, \ None, True, None, False)) landmask_used = pcr.ifthen(landmask_05_min, landmask_05_min) landmask_30_sec_file = "/projects/0/dfguu/users/edwinhs/data/HydroSHEDS/hydro_basin_without_lakes/integrating_ldd/version_9_december_2016/merged_ldd.map" landmask_30_sec = pcr.defined(pcr.readmap(landmask_30_sec_file)) landmask_used = pcr.ifthen(landmask_05_min, landmask_30_sec) #~ pcr.aguila(landmask_used) #~ print areas #~ print areas[0] # get a list of input files that will be merged msg = "Get the list of input files that will be merged." logger.info(msg) inputDir = inputDirRoot + "/" + areas[0] + "/output_folder/" files = getFileList(inputDir, '/*/*-year*.map')
def __init__(self, modelTime, input_file, output_file, variable_name, variable_unit): DynamicModel.__init__(self) self.modelTime = modelTime # netcdf input file - based on PCR-GLOBWB output self.input_file = "/projects/0/dfguu/users/edwin/pcr-globwb-aqueduct/historical/1951-2005/gfdl-esm2m/temperature_annuaAvg_output_%s-12-31_to_%s-12-31.nc" self.input_file = input_file # output file - in netcdf format self.output_file = output_folder + "/mekong/basin_temperature_annuaAvg_output.nc" self.output_file = output_file # output variable name and unit self.variable_name = variable_name self.variable_unit = variable_unit # preparing temporary directory self.temporary_directory = output_folder + "/tmp/" os.makedirs(self.temporary_directory) # clone and landmask maps logger.info("Set the clone and landmask maps.") self.clonemap_file_name = "/projects/0/dfguu/users/edwinhs/data/mekong_etc_clone/version_2018-10-22/final/clone_mekong.map" pcr.setclone(self.clonemap_file_name) landmask_file_name = "/projects/0/dfguu/users/edwinhs/data/mekong_etc_clone/version_2018-10-22/final/mask_mekong.map" self.landmask = vos.readPCRmapClone(landmask_file_name, \ self.clonemap_file_name, \ self.temporary_directory, \ None, False, None, True) # pcraster input files # - river network map and sub-catchment map ldd_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/lddsound_05min.map" # - cell area (unit: m2) cell_area_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/cellsize05min.correct.map" # loading pcraster input maps self.ldd_network = vos.readPCRmapClone(ldd_file_name, \ self.clonemap_file_name, \ self.temporary_directory, \ None, \ True) self.ldd_network = pcr.lddrepair(pcr.ldd(self.ldd_network)) self.ldd_network = pcr.lddrepair(self.ldd_network) self.cell_area = vos.readPCRmapClone(cell_area_file_name, \ self.clonemap_file_name, \ self.temporary_directory, \ None) # set/limit all input maps to the defined landmask self.ldd_network = pcr.ifthen(self.landmask, self.ldd_network) self.cell_area = pcr.ifthen(self.landmask, self.cell_area) # calculate basin/catchment area self.basin_area = pcr.catchmenttotal(self.cell_area, self.ldd_network) self.basin_area = pcr.ifthen(self.landmask, self.basin_area) # preparing an object for reporting netcdf files: self.netcdf_report = netcdf_writer.PCR2netCDF(self.clonemap_file_name) # preparing netcdf output files: self.netcdf_report.createNetCDF(self.output_file, \ self.variable_name, \ self.variable_unit)
def forcingDownscalingOptions(self, iniItems): self.downscalePrecipitationOption = False self.downscaleTemperatureOption = False self.downscaleReferenceETPotOption = False if 'meteoDownscalingOptions' in iniItems.allSections: # downscaling options if iniItems.meteoDownscalingOptions[ 'downscalePrecipitation'] == "True": self.downscalePrecipitationOption = True logger.info( "Precipitation forcing will be downscaled to the cloneMap resolution." ) if iniItems.meteoDownscalingOptions[ 'downscaleTemperature'] == "True": self.downscaleTemperatureOption = True logger.info( "Temperature forcing will be downscaled to the cloneMap resolution." ) if iniItems.meteoDownscalingOptions[ 'downscaleReferenceETPot'] == "True" and self.refETPotMethod != 'Hamon': self.downscaleReferenceETPotOption = True logger.info( "Reference potential evaporation will be downscaled to the cloneMap resolution." ) # Note that for the Hamon method: referencePotET will be calculated based on temperature, # therefore, we do not have to downscale it (particularly if temperature is already provided at high resolution). if self.downscalePrecipitationOption or\ self.downscaleTemperatureOption or\ self.downscaleReferenceETPotOption: # creating anomaly DEM highResolutionDEM = vos.readPCRmapClone(\ iniItems.meteoDownscalingOptions['highResolutionDEM'], self.cloneMap,self.tmpDir,self.inputDir) highResolutionDEM = pcr.cover(highResolutionDEM, 0.0) highResolutionDEM = pcr.max(highResolutionDEM, 0.0) self.meteoDownscaleIds = vos.readPCRmapClone(\ iniItems.meteoDownscalingOptions['meteoDownscaleIds'], self.cloneMap,self.tmpDir,self.inputDir,isLddMap=False,cover=None,isNomMap=True) self.cellArea = vos.readPCRmapClone(\ iniItems.routingOptions['cellAreaMap'], self.cloneMap,self.tmpDir,self.inputDir) loweResolutionDEM = pcr.areatotal(pcr.cover(highResolutionDEM*self.cellArea, 0.0),\ self.meteoDownscaleIds)/\ pcr.areatotal(pcr.cover(self.cellArea, 0.0),\ self.meteoDownscaleIds) self.anomalyDEM = highResolutionDEM - loweResolutionDEM # unit: meter # temperature lapse rate (netCDF) file self.temperLapseRateNC = vos.getFullPath(iniItems.meteoDownscalingOptions[\ 'temperLapseRateNC'],self.inputDir) self.temperatCorrelNC = vos.getFullPath(iniItems.meteoDownscalingOptions[\ 'temperatCorrelNC'],self.inputDir) # TODO: Remove this criteria. # precipitation lapse rate (netCDF) file self.precipLapseRateNC = vos.getFullPath(iniItems.meteoDownscalingOptions[\ 'precipLapseRateNC'],self.inputDir) self.precipitCorrelNC = vos.getFullPath(iniItems.meteoDownscalingOptions[\ 'precipitCorrelNC'],self.inputDir) # TODO: Remove this criteria. else: logger.info("No forcing downscaling is implemented.") # forcing smoothing options: - THIS is still experimental. PS: MUST BE TESTED. self.forcingSmoothing = False if 'meteoDownscalingOptions' in iniItems.allSections and \ 'smoothingWindowsLength' in list(iniItems.meteoDownscalingOptions.keys()): if float(iniItems.meteoDownscalingOptions['smoothingWindowsLength'] ) > 0.0: self.forcingSmoothing = True self.smoothingWindowsLength = vos.readPCRmapClone(\ iniItems.meteoDownscalingOptions['smoothingWindowsLength'], self.cloneMap,self.tmpDir,self.inputDir) msg = "Forcing data will be smoothed with 'windowaverage' using the window length:" + str( iniItems.meteoDownscalingOptions['smoothingWindowsLength']) logger.info(msg)
def evaluateAllModelResults(self,\ globalCloneMapFileName,\ catchmentClassFileName,\ lddMapFileName,\ cellAreaMapFileName,\ pcrglobwb_output,\ analysisOutputDir = "",\ tmpDir = None): # temporary directory if tmpDir == None: tmpDir = self.tmpDir+"/edwin_grdc_" # output directory for all analyses for all stations analysisOutputDir = str(analysisOutputDir) self.chartOutputDir = analysisOutputDir+"/chart/" self.tableOutputDir = analysisOutputDir+"/table/" # if analysisOutputDir == "": self.chartOutputDir = "chart/" if analysisOutputDir == "": self.tableOutputDir = "table/" # # make the chart and table directories: os.system('rm -r '+self.chartOutputDir+"*") os.system('rm -r '+self.tableOutputDir+"*") os.makedirs(self.chartOutputDir) os.makedirs(self.tableOutputDir) # cloneMap for all pcraster operations pcr.setclone(globalCloneMapFileName) cloneMap = pcr.boolean(1) self.cell_size_in_arc_degree = vos.getMapAttributesALL(globalCloneMapFileName)['cellsize'] # ldd map lddMap = vos.readPCRmapClone(lddMapFileName, \ globalCloneMapFileName, \ tmpDir, None, \ True, None, False) lddMap = pcr.lddrepair(lddMap) # cell area map cellArea = vos.readPCRmapClone(cellAreaMapFileName, \ globalCloneMapFileName, \ tmpDir) cellArea = pcr.scalar(cellArea) # The landMaskClass map contains the nominal classes for all landmask regions. landMaskClass = pcr.nominal(cloneMap) # default: if catchmentClassFileName is not given if catchmentClassFileName != None: landMaskClass = vos.readPCRmapClone(catchmentClassFileName, \ globalCloneMapFileName, \ tmpDir, None, \ False, None, True) landMaskClass = pcr.nominal(landMaskClass) # model catchment areas and cordinates catchmentAreaAll = pcr.catchmenttotal(cellArea, lddMap) / (1000*1000) # unit: km2 xCoordinate = pcr.xcoordinate(cloneMap) yCoordinate = pcr.ycoordinate(cloneMap) for id in self.list_of_grdc_ids: logger.info("Evaluating simulated discharge to the grdc observation at "+str(self.attributeGRDC["id_from_grdc"][str(id)])+".") # identify model pixel self.identifyModelPixel(tmpDir, catchmentAreaAll, landMaskClass, xCoordinate, yCoordinate,str(id)) # evaluate model results to GRDC data self.evaluateModelResultsToGRDC(str(id),pcrglobwb_output,catchmentClassFileName,tmpDir) # write the summary to a table summary_file = analysisOutputDir+"summary.txt" # logger.info("Writing the summary for all stations to the file: "+str(summary_file)+".") # # prepare the file: summary_file_handle = open(summary_file,"w") # # write the header summary_file_handle.write( ";".join(self.grdc_dict_keys)+"\n") # # write the content for id in self.list_of_grdc_ids: rowLine = "" for key in self.grdc_dict_keys: rowLine += str(self.attributeGRDC[key][str(id)]) + ";" rowLine = rowLine[0:-1] + "\n" summary_file_handle.write(rowLine) summary_file_handle.close()
clone_map_file = "/projects/0/dfguu/data/hydroworld/others/05ArcMinCloneMaps/new_masks_from_top/clone_" + str(mask_code) + ".map" msg = "Set the pcraster clone map to : " + str(clone_map_file) logger.info(msg) pcr.setclone(clone_map_file) # - set the landmask landmask_map_file = "/projects/0/dfguu/data/hydroworld/others/05ArcMinCloneMaps/new_masks_from_top/mask_" + str(mask_code) + ".map" msg = "Set the landmask to : " + str(landmask_map_file) logger.info(msg) landmask = pcr.readmap(landmask_map_file) # resampling low resolution ldd map msg = "Resample the low resolution ldd map." logger.info(msg) ldd_map_low_resolution_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/lddsound_05min.map" ldd_map_low_resolution = vos.readPCRmapClone(ldd_map_low_resolution_file_name, \ clone_map_file, \ tmp_folder, \ None, True, None, False) ldd_map_low_resolution = pcr.ifthen(landmask, ldd_map_low_resolution) # NOTE THAT YOU MAY NOT HAVE TO MASK-OUT THE LDD. ldd_map_low_resolution = pcr.lddrepair(pcr.ldd(ldd_map_low_resolution)) ldd_map_low_resolution = pcr.lddrepair(ldd_map_low_resolution) pcr.report(ldd_map_low_resolution, "resampled_low_resolution_ldd.map") # permanent water bodies files (at 5 arc-minute resolution) reservoir_capacity_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/reservoirs/waterBodiesFinal_version15Sept2013/maps/reservoircapacity_2010.map" fracwat_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/reservoirs/waterBodiesFinal_version15Sept2013/maps/fracwat_2010.map" water_body_id_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/reservoirs/waterBodiesFinal_version15Sept2013/maps/waterbodyid_2010.map" # cell_area_file cell_area_file = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/cellsize05min.correct.map"
def __init__(self, iniItems, landmask): object.__init__(self) # cloneMap, temporary directory, absolute path for input directory, landmask self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask # configuration from the ini file self.iniItems = iniItems # topography properties: read several variables from the netcdf file for var in ['dem_minimum','dem_maximum','dem_average','dem_standard_deviation',\ 'slopeLength','orographyBeta','tanslope',\ 'dzRel0000','dzRel0001','dzRel0005',\ 'dzRel0010','dzRel0020','dzRel0030','dzRel0040','dzRel0050',\ 'dzRel0060','dzRel0070','dzRel0080','dzRel0090','dzRel0100']: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['topographyNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # channel properties: read several variables from the netcdf file for var in [ 'lddMap', 'cellAreaMap', 'gradient', 'bankfull_width', 'bankfull_depth', 'dem_floodplain', 'dem_riverbed' ]: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['channelNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # minimum channel width minimum_channel_width = 0.1 self.bankfull_width = pcr.max(minimum_channel_width, self.bankfull_width) #~ # cell fraction if channel water reaching the flood plan # NOT USED #~ self.flood_plain_fraction = self.return_innundation_fraction(pcr.max(0.0, self.dem_floodplain - self.dem_minimum)) # coefficient of Manning self.manningsN = vos.readPCRmapClone(self.iniItems.modflowParameterOptions['manningsN'],\ self.cloneMap,self.tmpDir,self.inputDir) # minimum channel gradient minGradient = 0.00005 self.gradient = pcr.max(minGradient, pcr.cover(self.gradient, minGradient)) # correcting lddMap self.lddMap = pcr.ifthen(pcr.scalar(self.lddMap) > 0.0, self.lddMap) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) # channelLength = approximation of channel length (unit: m) # This is approximated by cell diagonal. cellSizeInArcMin = np.round(pcr.clone().cellSize() * 60.) verticalSizeInMeter = cellSizeInArcMin * 1852. self.channelLength = ((self.cellAreaMap/verticalSizeInMeter)**(2)+\ (verticalSizeInMeter)**(2))**(0.5) # option for lakes and reservoir self.onlyNaturalWaterBodies = False if self.iniItems.modflowParameterOptions[ 'onlyNaturalWaterBodies'] == "True": self.onlyNaturalWaterBodies = True # groundwater linear recession coefficient (day-1) ; the linear reservoir concept is still being used to represent fast response flow # particularly from karstic aquifer in mountainous regions self.recessionCoeff = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'recessionCoeff', self.cloneMap) self.recessionCoeff = pcr.cover(self.recessionCoeff, 0.00) self.recessionCoeff = pcr.min(1.0000, self.recessionCoeff) # if 'minRecessionCoeff' in iniItems.modflowParameterOptions.keys(): minRecessionCoeff = float( iniItems.modflowParameterOptions['minRecessionCoeff']) else: minRecessionCoeff = 1.0e-4 # This is the minimum value used in Van Beek et al. (2011). self.recessionCoeff = pcr.max(minRecessionCoeff, self.recessionCoeff) # aquifer saturated conductivity (m/day) self.kSatAquifer = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'kSatAquifer', self.cloneMap) self.kSatAquifer = pcr.cover(self.kSatAquifer, pcr.mapmaximum(self.kSatAquifer)) self.kSatAquifer = pcr.max(0.010, self.kSatAquifer) self.kSatAquifer *= 0.001 # aquifer specific yield (dimensionless) self.specificYield = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'specificYield', self.cloneMap) self.specificYield = pcr.cover(self.specificYield, pcr.mapmaximum(self.specificYield)) self.specificYield = pcr.max( 0.010, self.specificYield ) # TODO: TO BE CHECKED: The resample process of specificYield self.specificYield = pcr.min(1.000, self.specificYield) # estimate of thickness (unit: m) of accesible groundwater totalGroundwaterThickness = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['estimateOfTotalGroundwaterThicknessNC'],\ 'thickness', self.cloneMap) # extrapolation totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, 0.0) # # set minimum thickness minimumThickness = pcr.scalar(float(\ self.iniItems.modflowParameterOptions['minimumTotalGroundwaterThickness'])) totalGroundwaterThickness = pcr.max(minimumThickness, totalGroundwaterThickness) # # set maximum thickness: 250 m. maximumThickness = 250. self.totalGroundwaterThickness = pcr.min(maximumThickness, totalGroundwaterThickness) # river bed resistance (unit: day) self.bed_resistance = 1.0 # option to ignore capillary rise self.ignoreCapRise = True if self.iniItems.modflowParameterOptions['ignoreCapRise'] == "False": self.ignoreCapRise = False # initiate old style reporting # TODO: remove this! self.initiate_old_style_groundwater_reporting(iniItems)
def readSoilMapOfFAO(self, iniItems): # soil variable names given either in the ini or netCDF file: soilParameters = [ 'airEntryValue1', 'airEntryValue2', 'poreSizeBeta1', 'poreSizeBeta2', 'resVolWC1', 'resVolWC2', 'satVolWC1', 'satVolWC2', 'KSat1', 'KSat2', 'percolationImp' ] if iniItems.landSurfaceOptions['soilPropertiesNC'] == str(None): for var in soilParameters: input = iniItems.landSurfaceOptions[str(var)] vars(self)[var] = \ vos.readPCRmapClone(input,self.cloneMap,\ self.tmpDir,self.inputDir) vars(self)[var] = pcr.scalar(vars(self)[var]) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) else: soilPropertiesNC = vos.getFullPath(\ iniItems.landSurfaceOptions[\ 'soilPropertiesNC'], self.inputDir) for var in soilParameters: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(\ soilPropertiesNC,var, \ cloneMapFileName = self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) if self.numberOfLayers == 2: self.satVolMoistContUpp = self.satVolWC1 # saturated volumetric moisture content (m3.m-3) self.satVolMoistContLow = self.satVolWC2 self.resVolMoistContUpp = self.resVolWC1 # residual volumetric moisture content (m3.m-3) self.resVolMoistContLow = self.resVolWC2 self.airEntryValueUpp = self.airEntryValue1 # air entry value (m) according to soil water retention curve of Clapp & Hornberger (1978) self.airEntryValueLow = self.airEntryValue2 self.poreSizeBetaUpp = self.poreSizeBeta1 # pore size distribution parameter according to Clapp & Hornberger (1978) self.poreSizeBetaLow = self.poreSizeBeta2 self.kSatUpp = self.KSat1 # saturated hydraulic conductivity (m.day-1) self.kSatLow = self.KSat2 if self.numberOfLayers == 3: self.satVolMoistContUpp000005 = self.satVolWC1 self.satVolMoistContUpp005030 = self.satVolWC1 self.satVolMoistContLow030150 = self.satVolWC2 self.resVolMoistContUpp000005 = self.resVolWC1 self.resVolMoistContUpp005030 = self.resVolWC1 self.resVolMoistContLow030150 = self.resVolWC2 self.airEntryValueUpp000005 = self.airEntryValue1 self.airEntryValueUpp005030 = self.airEntryValue1 self.airEntryValueLow030150 = self.airEntryValue2 self.poreSizeBetaUpp000005 = self.poreSizeBeta1 self.poreSizeBetaUpp005030 = self.poreSizeBeta1 self.poreSizeBetaLow030150 = self.poreSizeBeta2 self.kSatUpp000005 = self.KSat1 self.kSatUpp005030 = self.KSat1 self.kSatLow030150 = self.KSat2 self.percolationImp = self.percolationImp # fractional area where percolation to groundwater store is impeded (dimensionless) # soil thickness and storage variable names # as given either in the ini or netCDF file: soilStorages = [ 'firstStorDepth', 'secondStorDepth', 'soilWaterStorageCap1', 'soilWaterStorageCap2' ] if iniItems.landSurfaceOptions['soilPropertiesNC'] == str(None): for var in soilStorages: input = iniItems.landSurfaceOptions[str(var)] temp = str(var) + 'Inp' vars(self)[temp] = vos.readPCRmapClone(input,\ self.cloneMap, self.tmpDir,self.inputDir) vars(self)[temp] = pcr.cover(vars(self)[temp], 0.0) else: soilPropertiesNC = vos.getFullPath(\ iniItems.landSurfaceOptions[\ 'soilPropertiesNC'], self.inputDir) for var in soilStorages: temp = str(var) + 'Inp' vars(self)[temp] = vos.netcdf2PCRobjCloneWithoutTime(\ soilPropertiesNC,var, \ cloneMapFileName = self.cloneMap) vars(self)[temp] = pcr.cover(vars(self)[temp], 0.0) # layer thickness if self.numberOfLayers == 2: self.thickUpp = (0.30 / 0.30) * self.firstStorDepthInp self.thickLow = (1.20 / 1.20) * self.secondStorDepthInp if self.numberOfLayers == 3: self.thickUpp000005 = (0.05 / 0.30) * self.firstStorDepthInp self.thickUpp005030 = (0.25 / 0.30) * self.firstStorDepthInp self.thickLow030150 = (1.20 / 1.20) * self.secondStorDepthInp # soil storage if self.numberOfLayers == 2: #~ self.storCapUpp = (0.30/0.30)*self.soilWaterStorageCap1Inp #~ self.storCapLow = (1.20/1.20)*self.soilWaterStorageCap2Inp # 22 Feb 2014: We can calculate this based on thickness and porosity. self.storCapUpp = self.thickUpp * \ (self.satVolMoistContUpp - self.resVolMoistContUpp) self.storCapLow = self.thickLow * \ (self.satVolMoistContLow - self.resVolMoistContLow) self.rootZoneWaterStorageCap = self.storCapUpp + \ self.storCapLow if self.numberOfLayers == 3: self.storCapUpp000005 = self.thickUpp000005 * \ (self.satVolMoistContUpp000005 - self.resVolMoistContUpp000005) self.storCapUpp005030 = self.thickUpp005030 * \ (self.satVolMoistContUpp005030 - self.resVolMoistContUpp005030) self.storCapLow030150 = self.thickLow030150 * \ (self.satVolMoistContLow030150 - self.resVolMoistContLow030150) self.rootZoneWaterStorageCap = self.storCapUpp000005 + \ self.storCapUpp005030 + \ self.storCapLow030150
for var in variable_names: input_files['file_name'][hydro_year][var] = glob.glob(input_files['folder'] + "/" + str(hydro_year) + "/" + str(var) + "*" + str(str_year) + "_to_" + str(end_year) + "*.nc")[0] msg = input_files['file_name'][hydro_year][var] logger.info(msg) # set the pcraster clone, ldd, landmask, and cell area map msg = "Setting the clone, ldd, landmask, and cell area maps" + ":" logger.info(msg) # - clone clone_map_file = input_files['clone_map_05min'] pcr.setclone(clone_map_file) # - ldd ldd = vos.readPCRmapClone(input_files['ldd_map_05min'], clone_map_file, output_files['tmp_folder'], None, True) ldd = pcr.lddrepair(pcr.ldd(ldd)) ldd = pcr.lddrepair(ldd) # - landmask landmask = pcr.ifthen(pcr.defined(ldd), pcr.boolean(1.0)) # - cell area cell_area = vos.readPCRmapClone(input_files['cell_area_05min'], clone_map_file, output_files['tmp_folder']) # read the hydrological year msg = "Reading the hydrological year types" + ":" logger.info(msg)
def __init__(self, iniItems,landmask,spinUp): object.__init__(self) self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask # option to activate water balance check self.debugWaterBalance = True if iniItems.routingOptions['debugWaterBalance'] == "False": self.debugWaterBalance = False if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign the recession coefficient parameter(s) self.recessionCoeff = vos.readPCRmapClone(\ iniItems.groundwaterOptions['recessionCoeff'], self.cloneMap,self.tmpDir,self.inputDir) else: groundwaterPropertiesNC = vos.getFullPath(\ iniItems.groundwaterOptions[\ 'groundwaterPropertiesNC'], self.inputDir) self.recessionCoeff = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'recessionCoeff',\ cloneMapFileName = self.cloneMap) # groundwater recession coefficient (day-1) self.recessionCoeff = pcr.cover(self.recessionCoeff,0.00) self.recessionCoeff = pcr.min(1.0000,self.recessionCoeff) # if 'minRecessionCoeff' in iniItems.groundwaterOptions.keys(): minRecessionCoeff = float(iniItems.groundwaterOptions['minRecessionCoeff']) else: minRecessionCoeff = 1.0e-4 # This is the minimum value used in Van Beek et al. (2011). self.recessionCoeff = pcr.max(minRecessionCoeff,self.recessionCoeff) if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign aquifer specific yield self.specificYield = vos.readPCRmapClone(\ iniItems.groundwaterOptions['specificYield'], self.cloneMap,self.tmpDir,self.inputDir) else: self.specificYield = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'specificYield',\ cloneMapFileName = self.cloneMap) self.specificYield = pcr.cover(self.specificYield,0.0) self.specificYield = pcr.max(0.010,self.specificYield) # TODO: TO BE CHECKED: The resample process of specificYield self.specificYield = pcr.min(1.000,self.specificYield) if iniItems.groundwaterOptions['groundwaterPropertiesNC'] == str(None): # assign aquifer saturated conductivity self.kSatAquifer = vos.readPCRmapClone(\ iniItems.groundwaterOptions['kSatAquifer'], self.cloneMap,self.tmpDir,self.inputDir) else: self.kSatAquifer = vos.netcdf2PCRobjCloneWithoutTime(\ groundwaterPropertiesNC,'kSatAquifer',\ cloneMapFileName = self.cloneMap) self.kSatAquifer = pcr.cover(self.kSatAquifer,0.0) self.kSatAquifer = pcr.max(0.010,self.kSatAquifer) # limitAbstraction options self.limitAbstraction = False if iniItems.landSurfaceOptions['limitAbstraction'] == "True": self.limitAbstraction = True # option for limitting regional groundwater abstractions if iniItems.groundwaterOptions['pumpingCapacityNC'] != "None": logger.info('Limit for annual regional groundwater abstraction is used.') self.limitRegionalAnnualGroundwaterAbstraction = True self.pumpingCapacityNC = vos.getFullPath(\ iniItems.groundwaterOptions['pumpingCapacityNC'],self.inputDir,False) else: logger.warning('NO LIMIT for regional groundwater (annual) pumping. It may result too high groundwater abstraction.') self.limitRegionalAnnualGroundwaterAbstraction = False # option for limitting fossil groundwater abstractions: self.limitFossilGroundwaterAbstraction = False # # estimate of fossil groundwater capacity: if iniItems.groundwaterOptions['limitFossilGroundWaterAbstraction'] == "True": logger.info('Fossil groundwater abstractions are allowed with LIMIT.') self.limitFossilGroundwaterAbstraction = True # estimate of thickness (unit: m) of accesible groundwater: shallow and deep totalGroundwaterThickness = vos.readPCRmapClone(\ iniItems.groundwaterOptions['estimateOfTotalGroundwaterThickness'], self.cloneMap,self.tmpDir,self.inputDir) # extrapolation totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 1.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 1.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 2.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, pcr.windowaverage(totalGroundwaterThickness, 5.0)) # totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, 0.0) # # set minimum thickness minimumThickness = pcr.scalar(float(\ iniItems.groundwaterOptions['minimumTotalGroundwaterThickness'])) totalGroundwaterThickness = pcr.max(minimumThickness, totalGroundwaterThickness) # # estimate of capacity (unit: m) of renewable groundwater (shallow) storGroundwaterCap = pcr.cover( vos.readPCRmapClone(\ iniItems.groundwaterOptions['estimateOfRenewableGroundwaterCapacity'], self.cloneMap,self.tmpDir,self.inputDir), 0.0) # # fossil groundwater capacity (unit: m) self.fossilWaterCap = pcr.ifthen(self.landmask,\ pcr.max(0.0,\ totalGroundwaterThickness*self.specificYield - storGroundwaterCap)) # zones at which groundwater allocations are determined self.usingAllocSegments = False if iniItems.landSurfaceOptions['allocationSegmentsForGroundSurfaceWater'] != "None": self.usingAllocSegments = True # incorporating groundwater distribution network: if self.usingAllocSegments: self.allocSegments = vos.readPCRmapClone(\ iniItems.landSurfaceOptions['allocationSegmentsForGroundSurfaceWater'], self.cloneMap,self.tmpDir,self.inputDir,isLddMap=False,cover=None,isNomMap=True) self.allocSegments = pcr.ifthen(self.landmask, self.allocSegments) cellArea = vos.readPCRmapClone(\ iniItems.routingOptions['cellAreaMap'], self.cloneMap,self.tmpDir,self.inputDir) cellArea = pcr.ifthen(self.landmask, cellArea) # TODO: integrate this one with the one coming from the routing module self.segmentArea = pcr.areatotal(pcr.cover(cellArea, 0.0), self.allocSegments) self.segmentArea = pcr.ifthen(self.landmask, self.segmentArea) # get initial conditions self.getICs(iniItems,spinUp) # initiate old style reporting # TODO: remove this! self.initiate_old_style_groundwater_reporting(iniItems)