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 dynamic(self): logger.info("Step 4: Monte Carlo simulation") # draw a random value (uniform for the entire map) z = pcr.mapnormal() #~ self.report(z,"z") # constraints, in order to make sure that random values are in the table of "lookup_table_average_thickness" z = pcr.max(-5.0, z) z = pcr.min(5.0, z) # assign average thickness (also uniform for the entire map) based on z self.Davg = pcr.lookupscalar(self.lookup_table_average_thickness, z) # self.report(self.Davg, "davg") self.lnDavg = pcr.ln(self.Davg) # sedimentary basin thickness (varying over cells and samples) lnD = self.F * (self.lnCV * self.lnDavg) + self.lnDavg # set the minimum depth (must be bigger than zero) minimum_depth = 0.005 lnD = pcr.max(pcr.ln(minimum_depth), lnD) # extrapolation lnD = pcr.cover(lnD, \ pcr.windowaverage(lnD, 1.50*vos.getMapAttributes(self.clone_map_file,"cellsize"))) lnD = pcr.cover(lnD, \ pcr.windowaverage(pcr.cover(lnD, pcr.ln(minimum_depth)), 3.00*vos.getMapAttributes(self.clone_map_file,"cellsize"))) lnD = pcr.cover(lnD, \ pcr.windowaverage(pcr.cover(lnD, pcr.ln(minimum_depth)), 0.50)) # smoothing per quarter arc degree lnD = pcr.windowaverage(lnD, 0.25) # thickness in meter self.D = pcr.exp(lnD) #~ # smoothing bottom elevation #~ dem_bottom = pcr.windowaverage(self.dem_average - self.D, 0.50) #~ # thickness in meter #~ self.D = pcr.max(0.0, self.dem_average - dem_bottom) #~ # smoothing #~ self.D = pcr.windowaverage(self.D, 1.50*vos.getMapAttributes(self.clone_map_file,"cellsize")) # accuracy until cm only self.D = pcr.rounddown(self.D * 100.) / 100. self.report(self.D, "damc")
def estimate_bottom_of_bank_storage(self): # influence zone depth (m) influence_zone_depth = 0.50 # bottom_elevation > flood_plain elevation - influence zone bottom_of_bank_storage = self.dem_floodplain - influence_zone_depth #~ # bottom_elevation > river bed #~ bottom_of_bank_storage = pcr.max(self.dem_riverbed, bottom_of_bank_storage) # bottom_elevation > its downstream value bottom_of_bank_storage = pcr.max(bottom_of_bank_storage, \ pcr.cover(pcr.downstream(self.lddMap, bottom_of_bank_storage), bottom_of_bank_storage)) # bottom_elevation >= 0.0 (must be higher than sea level) bottom_of_bank_storage = pcr.max(0.0, bottom_of_bank_storage) # reducing noise bottom_of_bank_storage = pcr.max(bottom_of_bank_storage,\ pcr.windowaverage(bottom_of_bank_storage, 3.0 * pcr.clone().cellSize())) # bottom_elevation < dem_average bottom_of_bank_storage = pcr.min(bottom_of_bank_storage, self.dem_average) bottom_of_bank_storage = pcr.cover(bottom_of_bank_storage, self.dem_average) # TODO: Check again this concept. # TODO: We may want to improve this concept - by incorporating the following # - smooth bottom_elevation # - upstream areas in the mountainous regions and above perrenial stream starting points may also be drained (otherwise water will accumulate) # - bottom_elevation > minimum elevation that is estimated from the maximum of S3 from the PCR-GLOBWB simulation return bottom_of_bank_storage
def estimate_bottom_of_bank_storage(self): # influence zone depth (m) # TODO: Define this one as part of influence_zone_depth = 5.0 # bottom_elevation > flood_plain elevation - influence zone bottom_of_bank_storage = self.dem_floodplain - influence_zone_depth # reducing noise (so we will not introduce unrealistic sinks) # TODO: Define the window size as part of the configuration/ini file bottom_of_bank_storage = pcr.max(bottom_of_bank_storage,\ pcr.windowaverage(bottom_of_bank_storage, 3.0 * pcr.clone().cellSize())) # bottom_elevation > river bed bottom_of_bank_storage = pcr.max(self.dem_riverbed, bottom_of_bank_storage) # reducing noise by comparing to its downstream value (so we will not introduce unrealistic sinks) bottom_of_bank_storage = pcr.max(bottom_of_bank_storage, \ (bottom_of_bank_storage + pcr.cover(pcr.downstream(self.lddMap, bottom_of_bank_storage), bottom_of_bank_storage))/2.) # bottom_elevation >= 0.0 (must be higher than sea level) bottom_of_bank_storage = pcr.max(0.0, bottom_of_bank_storage) # bottom_elevation < dem_average (this is to drain overland flow) bottom_of_bank_storage = pcr.min(bottom_of_bank_storage, self.dem_average) bottom_of_bank_storage = pcr.cover(bottom_of_bank_storage, self.dem_average) # TODO: Check again this concept. # TODO: We may want to improve this concept - by incorporating the following # - smooth bottom_elevation # - upstream areas in the mountainous regions and above perrenial stream starting points may also be drained (otherwise water will accumulate) # - bottom_elevation > minimum elevation that is estimated from the maximum of S3 from the PCR-GLOBWB simulation return bottom_of_bank_storage
def dynamic(self): # re-calculate current model time using current pcraster timestep value self.modelTime.update(self.currentTimeStep()) # processing done only at the last day of the month if self.modelTime.isLastDayOfMonth(): logger.info("Reading runoff for time %s", self.modelTime.currTime) self.total_runoff = vos.netcdf2PCRobjClone(self.totat_runoff_input_file, "total_runoff",\ str(self.modelTime.fulldate), useDoy = None, cloneMapFileName = self.clonemap_file_name,\ LatitudeLongitude = True) self.total_runoff = pcr.cover(self.total_runoff, 0.0) logger.info("Calculating total inflow and internal inflow for time %s", self.modelTime.currTime) self.total_flow = pcr.catchmenttotal(self.total_runoff * self.cell_area, self.ldd_network) self.internal_flow = pcr.areatotal(self.total_runoff * self.cell_area, self.sub_catchment) # - convert values to m3/s number_of_days_in_a_month = self.modelTime.day self.total_flow = self.total_flow / (number_of_days_in_a_month * 24. * 3600.) self.internal_flow = self.internal_flow / (number_of_days_in_a_month * 24. * 3600.) # - limit the values to the landmask only self.total_flow = pcr.ifthen(self.landmask, self.total_flow) self.internal_flow = pcr.ifthen(self.landmask, self.internal_flow) logger.info("Extrapolating or time %s", self.modelTime.currTime) # Purpose: To avoid missing value data while being extracted by cdo command self.total_flow = pcr.cover(self.total_flow, pcr.windowmaximum(self.total_flow, 0.125)) self.internal_flow = pcr.cover(self.internal_flow, pcr.windowaverage(self.internal_flow, 0.125)) # reporting # - time stamp for reporting timeStamp = datetime.datetime(self.modelTime.year,\ self.modelTime.month,\ self.modelTime.day,\ 0) logger.info("Reporting for time %s", self.modelTime.currTime) self.netcdf_report.data2NetCDF(self.total_flow_output_file, \ "total_flow", \ pcr.pcr2numpy(self.total_flow, vos.MV), \ timeStamp) self.netcdf_report.data2NetCDF(self.internal_flow_output_file, \ "internal_flow", \ pcr.pcr2numpy(self.internal_flow, vos.MV), \ timeStamp)
def mapFilling(self, map_with_MV, map_without_MV, method = "window_average"): # ----- method 1: inverse distance method (but too slow) if method == "inverse_distance": logger.info('Extrapolation using "inverse distance" in progress!') # # - interpolation mask for cells without values interpolatedMask = pcr.ifthenelse(\ pcr.defined(map_with_MV),\ pcr.boolean(0),\ pcr.boolean(1),) map_with_MV_intrpl = pcr.inversedistance(interpolatedMask, \ map_with_MV, 2, 1.50, 25) # else: # method 2: using window average logger.info('Extrapolation using "modified window average" in progress!') # map_with_MV_intrpl = 0.70 * pcr.windowaverage(map_with_MV, 1.50) + \ 0.25 * pcr.windowaverage(map_with_MV, 2.00) + \ 0.05 * pcr.windowaverage(map_with_MV, 2.50) + \ pcr.scalar(0.0) # # - interpolated values are only introduced in cells with MV map_with_MV_intrpl = pcr.cover(map_with_MV, map_with_MV_intrpl) # # - calculating weight factor: weight_factor = pcr.scalar(pcr.defined(map_with_MV)) weight_factor = pcr.windowaverage(0.70*weight_factor, 1.50) +\ pcr.windowaverage(0.25*weight_factor, 2.00) +\ pcr.windowaverage(0.05*weight_factor, 2.50) weight_factor = pcr.min(1.0, weight_factor) weight_factor = pcr.max(0.0, weight_factor) weight_factor = pcr.cover(weight_factor, 0.0) # # merge with weight factor merged_map = weight_factor * map_with_MV_intrpl + \ (1.0 - weight_factor) * map_without_MV # # retain the original values and make sure that all values are covered filled_map = pcr.cover(map_with_MV, merged_map) filled_map = pcr.cover(filled_map, map_without_MV) logger.info('Extrapolation is done!') return filled_map
def main(): """ :ivar masterdem: digital elevation model :ivar dem: digital elevation model :ivar river: optional river map """ # Default values strRiver = 8 masterdem = "dem.map" step1dir = "step1" step2dir = "step2" workdir = "." inifile = "wflow_prepare.ini" recreate = False snapgaugestoriver = False try: opts, args = getopt.getopt(sys.argv[1:], "W:hI:f") except getopt.error as msg: usage(msg) for o, a in opts: if o == "-W": workdir = a if o == "-I": inifile = a if o == "-h": usage() if o == "-f": recreate = True pcr.setglobaloption("unitcell") os.chdir(workdir) config = OpenConf(workdir + "/" + inifile) masterdem = configget(config, "files", "masterdem", "dem.map") pcr.setclone(masterdem) strRiver = int(configget(config, "settings", "riverorder", "4")) try: gauges_x = config.get("settings", "gauges_x") gauges_y = config.get("settings", "gauges_y") except: print("gauges_x and gauges_y are required entries in the ini file") sys.exit(1) step1dir = configget(config, "directories", "step1dir", "step1") step2dir = configget(config, "directories", "step2dir", "step2") # upscalefactor = float(config.get("settings","upscalefactor")) corevolume = float(configget(config, "settings", "corevolume", "1E35")) catchmentprecipitation = float( configget(config, "settings", "catchmentprecipitation", "1E35")) corearea = float(configget(config, "settings", "corearea", "1E35")) outflowdepth = float( configget(config, "settings", "lddoutflowdepth", "1E35")) initialscale = int(configget(config, "settings", "initialscale", "1")) csize = float(configget(config, "settings", "cellsize", "1")) snapgaugestoriver = bool( int(configget(config, "settings", "snapgaugestoriver", "1"))) lddglobaloption = configget(config, "settings", "lddglobaloption", "lddout") pcr.setglobaloption(lddglobaloption) lu_water = configget(config, "files", "lu_water", "") lu_paved = configget(config, "files", "lu_paved", "") # X/Y coordinates of the gauges the system exec("X=tr.array(" + gauges_x + ")") exec("Y=tr.array(" + gauges_y + ")") tr.Verbose = 1 # make the directories to save results in mkoutputdirs(step1dir, step2dir) ldddem = readdem(initialscale, masterdem, step1dir) dem = ldddem try: catchmask = config.get("files", "catchment_mask") except: print("No catchment mask...") else: print("clipping DEM with mask.....") mask = pcr.readmap(catchmask) ldddem = pcr.ifthen(pcr.boolean(mask), ldddem) dem = pcr.ifthen(pcr.boolean(mask), dem) # See if there is a shape file of the river to burn in try: rivshp = config.get("files", "river") except: print("no river file specified") outletpointX = float( configget(config, "settings", "outflowpointX", "0.0")) outletpointY = float( configget(config, "settings", "outflowpointY", "0.0")) else: print("river file specified.....") try: outletpointX = float( configget(config, "settings", "outflowpointX", "0.0")) outletpointY = float( configget(config, "settings", "outflowpointY", "0.0")) except: print( "Need to specify the river outletpoint (a point at the end of the river within the current map)" ) exit(1) outletpointmap = tr.points_to_map(dem, outletpointX, outletpointY, 0.5) pcr.report(outletpointmap, step1dir + "/outletpoint.map") rivshpattr = config.get("files", "riverattr") pcr.report(dem * 0.0, step1dir + "/nilmap.map") thestr = ("gdal_translate -of GTiff " + step1dir + "/nilmap.map " + step1dir + "/riverburn.tif") os.system(thestr) os.system("gdal_rasterize -burn 1 -l " + rivshpattr + " " + rivshp + " " + step1dir + "/riverburn.tif") thestr = ("gdal_translate -of PCRaster " + step1dir + "/riverburn.tif " + step1dir + "/riverburn.map") os.system(thestr) riverburn = pcr.readmap(step1dir + "/riverburn.map") # Determine regional slope assuming that is the way the river should run pcr.setglobaloption("unitcell") demregional = pcr.windowaverage(dem, 100) ldddem = pcr.ifthenelse(riverburn >= 1.0, demregional - 1000, dem) pcr.setglobaloption("unittrue") upscalefactor = int(csize / pcr.celllength()) print("Creating ldd...") ldd = tr.lddcreate_save( step1dir + "/ldd.map", ldddem, recreate, outflowdepth=outflowdepth, corevolume=corevolume, catchmentprecipitation=catchmentprecipitation, corearea=corearea, ) print("Determining streamorder...") stro = pcr.streamorder(ldd) pcr.report(stro, step1dir + "/streamorder.map") strdir = pcr.ifthen(stro >= strRiver, stro) pcr.report(strdir, step1dir + "/streamorderrive.map") pcr.report(pcr.boolean(pcr.ifthen(stro >= strRiver, stro)), step1dir + "/rivers.map") pcr.setglobaloption("unittrue") # outlet (and other gauges if given) # TODO: check is x/y set if not skip this print("Outlet...") outlmap = tr.points_to_map(dem, X, Y, 0.5) if snapgaugestoriver: print("Snapping gauges to nearest river cells...") pcr.report(outlmap, step1dir + "/orggauges.map") outlmap = tr.snaptomap(outlmap, strdir) # noutletmap = tr.points_to_map(dem,XX,YY,0.5) # pcr.report(noutletmap,'noutlet.map') pcr.report(outlmap, step1dir + "/gauges.map") # check if there is a pre-define catchment map try: catchmask = config.get("files", "catchment_mask") except: print("No catchment mask, finding outlet") # Find catchment (overall) outlet = tr.find_outlet(ldd) sub = pcr.subcatch(ldd, outlet) pcr.report(sub, step1dir + "/catchment_overall.map") else: print("reading and converting catchment mask.....") os.system("resample -r " + str(initialscale) + " " + catchmask + " " + step1dir + "/catchment_overall.map") sub = pcr.readmap(step1dir + "/catchment_overall.map") print("Scatch...") sd = pcr.subcatch(ldd, pcr.ifthen(outlmap > 0, outlmap)) pcr.report(sd, step1dir + "/scatch.map") pcr.setglobaloption("unitcell") print("Upscalefactor: " + str(upscalefactor)) if upscalefactor > 1: gc.collect() print("upscale river length1 (checkerboard map)...") ck = tr.checkerboard(dem, upscalefactor) pcr.report(ck, step1dir + "/ck.map") pcr.report(dem, step1dir + "/demck.map") print("upscale river length2...") fact = tr.area_riverlength_factor(ldd, ck, upscalefactor) pcr.report(fact, step1dir + "/riverlength_fact.map") # print("make dem statistics...") dem_ = pcr.areaaverage(dem, ck) pcr.report(dem_, step1dir + "/demavg.map") print("Create DEM statistics...") dem_ = pcr.areaminimum(dem, ck) pcr.report(dem_, step1dir + "/demmin.map") dem_ = pcr.areamaximum(dem, ck) pcr.report(dem_, step1dir + "/demmax.map") # calculate percentiles order = pcr.areaorder(dem, ck) n = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), ck) #: calculate 25 percentile perc = tr.area_percentile(dem, ck, n, order, 25.0) pcr.report(perc, step1dir + "/dem25.map") perc = tr.area_percentile(dem, ck, n, order, 10.0) pcr.report(perc, step1dir + "/dem10.map") perc = tr.area_percentile(dem, ck, n, order, 50.0) pcr.report(perc, step1dir + "/dem50.map") perc = tr.area_percentile(dem, ck, n, order, 33.0) pcr.report(perc, step1dir + "/dem33.map") perc = tr.area_percentile(dem, ck, n, order, 66.0) pcr.report(perc, step1dir + "/dem66.map") perc = tr.area_percentile(dem, ck, n, order, 75.0) pcr.report(perc, step1dir + "/dem75.map") perc = tr.area_percentile(dem, ck, n, order, 90.0) pcr.report(perc, step1dir + "/dem90.map") else: print("No fancy scaling done. Going strait to step2....") pcr.report(dem, step1dir + "/demavg.map") Xul = float(config.get("settings", "Xul")) Yul = float(config.get("settings", "Yul")) Xlr = float(config.get("settings", "Xlr")) Ylr = float(config.get("settings", "Ylr")) gdalstr = ("gdal_translate -projwin " + str(Xul) + " " + str(Yul) + " " + str(Xlr) + " " + str(Ylr) + " -of PCRaster ") # gdalstr = "gdal_translate -a_ullr " + str(Xul) + " " + str(Yul) + " " +str(Xlr) + " " +str(Ylr) + " -of PCRaster " print(gdalstr) pcr.report(pcr.cover(1.0), step1dir + "/wflow_riverlength_fact.map") # Now us gdat tp convert the maps os.system(gdalstr + step1dir + "/wflow_riverlength_fact.map" + " " + step2dir + "/wflow_riverlength_fact.map") os.system(gdalstr + step1dir + "/demavg.map" + " " + step2dir + "/wflow_dem.map") os.system(gdalstr + step1dir + "/demavg.map" + " " + step2dir + "/wflow_demmin.map") os.system(gdalstr + step1dir + "/demavg.map" + " " + step2dir + "/wflow_demmax.map") os.system(gdalstr + step1dir + "/gauges.map" + " " + step2dir + "/wflow_gauges.map") os.system(gdalstr + step1dir + "/rivers.map" + " " + step2dir + "/wflow_river.map") os.system(gdalstr + step1dir + "/streamorder.map" + " " + step2dir + "/wflow_streamorder.map") os.system(gdalstr + step1dir + "/gauges.map" + " " + step2dir + "/wflow_outlet.map") os.system(gdalstr + step1dir + "/scatch.map" + " " + step2dir + "/wflow_catchment.map") os.system(gdalstr + step1dir + "/ldd.map" + " " + step2dir + "/wflow_ldd.map") os.system(gdalstr + step1dir + "/scatch.map" + " " + step2dir + "/wflow_subcatch.map") if lu_water: os.system(gdalstr + lu_water + " " + step2dir + "/WaterFrac.map") if lu_paved: os.system(gdalstr + lu_paved + " " + step2dir + "/PathFrac.map") try: lumap = config.get("files", "landuse") except: print("no landuse map...creating uniform map") # clone=pcr.readmap(step2dir + "/wflow_dem.map") pcr.setclone(step2dir + "/wflow_dem.map") pcr.report(pcr.nominal(1), step2dir + "/wflow_landuse.map") else: os.system("resample --clone " + step2dir + "/wflow_dem.map " + lumap + " " + step2dir + "/wflow_landuse.map") try: soilmap = config.get("files", "soil") except: print("no soil map..., creating uniform map") pcr.setclone(step2dir + "/wflow_dem.map") pcr.report(pcr.nominal(1), step2dir + "/wflow_soil.map") else: os.system("resample --clone " + step2dir + "/wflow_dem.map " + soilmap + " " + step2dir + "/wflow_soil.map") ################################## # Step 2 starts here ################################## pcr.setclone(step2dir + "/cutout.map") strRiver = int(configget(config, "settings", "riverorder_step2", "4")) corevolume = float(configget(config, "settings", "corevolume", "1E35")) catchmentprecipitation = float( configget(config, "settings", "catchmentprecipitation", "1E35")) corearea = float(configget(config, "settings", "corearea", "1E35")) outflowdepth = float( configget(config, "settings", "lddoutflowdepth", "1E35")) lddmethod = configget(config, "settings", "lddmethod", "dem") lddglobaloption = configget(config, "settings", "lddglobaloption", "lddout") pcr.setglobaloption(lddglobaloption) nrrow = round(abs(Yul - Ylr) / csize) nrcol = round(abs(Xlr - Xul) / csize) mapstr = ("mapattr -s -S -R " + str(nrrow) + " -C " + str(nrcol) + " -l " + str(csize) + " -x " + str(Xul) + " -y " + str(Yul) + " -P yb2t " + step2dir + "/cutout.map") os.system(mapstr) pcr.setclone(step2dir + "/cutout.map") lu_water = configget(config, "files", "lu_water", "") lu_paved = configget(config, "files", "lu_paved", "") if lu_water: os.system("resample --clone " + step2dir + "/cutout.map " + lu_water + " " + step2dir + "/wflow_waterfrac.map") if lu_paved: os.system("resample --clone " + step2dir + "/cutout.map " + lu_paved + " " + step2dir + "/PathFrac.map") # try: lumap = config.get("files", "landuse") except: print("no landuse map...creating uniform map") clone = pcr.readmap(step2dir + "/cutout.map") pcr.report(pcr.nominal(clone), step2dir + "/wflow_landuse.map") else: os.system("resample --clone " + step2dir + "/cutout.map " + lumap + " " + step2dir + "/wflow_landuse.map") try: soilmap = config.get("files", "soil") except: print("no soil map..., creating uniform map") clone = pcr.readmap(step2dir + "/cutout.map") pcr.report(pcr.nominal(clone), step2dir + "/wflow_soil.map") else: os.system("resample --clone " + step2dir + "/cutout.map " + soilmap + " " + step2dir + "/wflow_soil.map") resamplemaps(step1dir, step2dir) dem = pcr.readmap(step2dir + "/wflow_dem.map") demmin = pcr.readmap(step2dir + "/wflow_demmin.map") demmax = pcr.readmap(step2dir + "/wflow_demmax.map") catchcut = pcr.readmap(step2dir + "/catchment_cut.map") # now apply the area of interest (catchcut) to the DEM # dem=pcr.ifthen(catchcut >=1 , dem) # # See if there is a shape file of the river to burn in try: rivshp = config.get("files", "river") except: print("no river file specified") riverburn = pcr.readmap(step2dir + "/wflow_riverburnin.map") else: print("river file speficied.....") rivshpattr = config.get("files", "riverattr") pcr.report(dem * 0.0, step2dir + "/nilmap.map") thestr = ("gdal_translate -of GTiff " + step2dir + "/nilmap.map " + step2dir + "/wflow_riverburnin.tif") os.system(thestr) os.system("gdal_rasterize -burn 1 -l " + rivshpattr + " " + rivshp + " " + step2dir + "/wflow_riverburnin.tif") thestr = ("gdal_translate -of PCRaster " + step2dir + "/wflow_riverburnin.tif " + step2dir + "/wflow_riverburnin.map") os.system(thestr) riverburn = pcr.readmap(step2dir + "/wflow_riverburnin.map") # ldddem = pcr.ifthenelse(riverburn >= 1.0, dem -1000 , dem) # Only burn within the original catchment riverburn = pcr.ifthen(pcr.scalar(catchcut) >= 1, riverburn) # Now setup a very high wall around the catchment that is scale # based on the distance to the catchment so that it slopes away from the # catchment if lddmethod != "river": print("Burning in highres-river ...") disttocatch = pcr.spread(pcr.nominal(catchcut), 0.0, 1.0) demmax = pcr.ifthenelse( pcr.scalar(catchcut) >= 1.0, demmax, demmax + (pcr.celllength() * 100.0) / disttocatch, ) pcr.setglobaloption("unitcell") demregional = pcr.windowaverage(demmin, 100) demburn = pcr.cover( pcr.ifthen(pcr.boolean(riverburn), demregional - 100.0), demmax) else: print("using average dem..") demburn = dem ldd = tr.lddcreate_save( step2dir + "/ldd.map", demburn, True, outflowdepth=outflowdepth, corevolume=corevolume, catchmentprecipitation=catchmentprecipitation, corearea=corearea, ) # Find catchment (overall) outlet = tr.find_outlet(ldd) sub = pcr.subcatch(ldd, outlet) pcr.report(sub, step2dir + "/wflow_catchment.map") pcr.report(outlet, step2dir + "/wflow_outlet.map") # make river map strorder = pcr.streamorder(ldd) pcr.report(strorder, step2dir + "/wflow_streamorder.map") river = pcr.ifthen(pcr.boolean(strorder >= strRiver), strorder) pcr.report(river, step2dir + "/wflow_river.map") # make subcatchments # os.system("col2map --clone " + step2dir + "/cutout.map gauges.col " + step2dir + "/wflow_gauges.map") exec("X=tr.array(" + gauges_x + ")") exec("Y=tr.array(" + gauges_y + ")") pcr.setglobaloption("unittrue") outlmap = tr.points_to_map(dem, X, Y, 0.5) pcr.report(outlmap, step2dir + "/wflow_gauges_.map") if snapgaugestoriver: print("Snapping gauges to river") pcr.report(outlmap, step2dir + "/wflow_orggauges.map") outlmap = tr.snaptomap(outlmap, river) outlmap = pcr.ifthen(outlmap > 0, outlmap) pcr.report(outlmap, step2dir + "/wflow_gauges.map") scatch = pcr.subcatch(ldd, outlmap) pcr.report(scatch, step2dir + "/wflow_subcatch.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 __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)
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
def read_forcings(self, currTimeStep): #----------------------------------------------------------------------- # NOTE: RvB 13/07/2016 hard-coded reference to the variable names # preciptiation, temperature and evapotranspiration have been replaced # by the variable names used in the netCDF and passed from the ini file #----------------------------------------------------------------------- # method for finding time indexes in the precipitation netdf file: # - the default one method_for_time_index = None # - based on the ini/configuration file (if given) if 'time_index_method_for_precipitation_netcdf' in list(self.iniItems.meteoOptions.keys()) and\ self.iniItems.meteoOptions['time_index_method_for_precipitation_netcdf'] != "None": method_for_time_index = self.iniItems.meteoOptions[ 'time_index_method_for_precipitation_netcdf'] # reading precipitation: if self.precipitation_set_per_year: #~ print currTimeStep.year nc_file_per_year = self.preFileNC % (float( currTimeStep.year), float(currTimeStep.year)) self.precipitation = vos.netcdf2PCRobjClone(\ nc_file_per_year, self.preVarName,\ str(currTimeStep.fulldate), useDoy = method_for_time_index, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) else: self.precipitation = vos.netcdf2PCRobjClone(\ self.preFileNC, self.preVarName,\ str(currTimeStep.fulldate), useDoy = method_for_time_index, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) #----------------------------------------------------------------------- # NOTE: RvB 13/07/2016 added to automatically update precipitation self.precipitation = self.preConst + self.preFactor * pcr.ifthen( self.landmask, self.precipitation) #----------------------------------------------------------------------- # make sure that precipitation is always positive self.precipitation = pcr.max(0., self.precipitation) self.precipitation = pcr.cover(self.precipitation, 0.0) # ignore very small values of precipitation (less than 0.00001 m/day or less than 0.01 kg.m-2.day-1 ) if self.usingDailyTimeStepForcingData: self.precipitation = pcr.rounddown( self.precipitation * 100000.) / 100000. # method for finding time index in the temperature netdf file: # - the default one method_for_time_index = None # - based on the ini/configuration file (if given) if 'time_index_method_for_temperature_netcdf' in list(self.iniItems.meteoOptions.keys()) and\ self.iniItems.meteoOptions['time_index_method_for_temperature_netcdf'] != "None": method_for_time_index = self.iniItems.meteoOptions[ 'time_index_method_for_temperature_netcdf'] # reading temperature if self.temperature_set_per_year: nc_file_per_year = self.tmpFileNC % (int( currTimeStep.year), int(currTimeStep.year)) self.temperature = vos.netcdf2PCRobjClone(\ nc_file_per_year, self.tmpVarName,\ str(currTimeStep.fulldate), useDoy = method_for_time_index, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) else: self.temperature = vos.netcdf2PCRobjClone(\ self.tmpFileNC,self.tmpVarName,\ str(currTimeStep.fulldate), useDoy = method_for_time_index, cloneMapFileName=self.cloneMap,\ LatitudeLongitude = True) #----------------------------------------------------------------------- # NOTE: RvB 13/07/2016 added to automatically update temperature self.temperature = self.tmpConst + self.tmpFactor * pcr.ifthen( self.landmask, self.temperature) #----------------------------------------------------------------------- # Downscaling precipitation and temperature if self.downscalePrecipitationOption: self.downscalePrecipitation(currTimeStep) if self.downscaleTemperatureOption: self.downscaleTemperature(currTimeStep) # calculate or obtain referencePotET if self.refETPotMethod == 'Hamon': self.referencePotET = \ refPotET.HamonPotET(self.temperature,\ currTimeStep.doy,\ self.latitudes) if self.refETPotMethod == 'Input': # method for finding time indexes in the precipitation netdf file: # - the default one method_for_time_index = None # - based on the ini/configuration file (if given) if 'time_index_method_for_ref_pot_et_netcdf' in list(self.iniItems.meteoOptions.keys()) and\ self.iniItems.meteoOptions['time_index_method_for_ref_pot_et_netcdf'] != "None": method_for_time_index = self.iniItems.meteoOptions[ 'time_index_method_for_ref_pot_et_netcdf'] if self.refETPotFileNC_set_per_year: nc_file_per_year = self.etpFileNC % (int( currTimeStep.year), int(currTimeStep.year)) self.referencePotET = vos.netcdf2PCRobjClone(\ nc_file_per_year, self.refETPotVarName,\ str(currTimeStep.fulldate), useDoy = method_for_time_index, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) else: self.referencePotET = vos.netcdf2PCRobjClone(\ self.etpFileNC,self.refETPotVarName,\ str(currTimeStep.fulldate), useDoy = method_for_time_index, cloneMapFileName=self.cloneMap,\ LatitudeLongitude = True) #----------------------------------------------------------------------- # NOTE: RvB 13/07/2016 added to automatically update reference potential evapotranspiration self.referencePotET = self.refETPotConst + self.refETPotFactor * pcr.ifthen( self.landmask, self.referencePotET) #----------------------------------------------------------------------- # Downscaling referenceETPot (based on temperature) if self.downscaleReferenceETPotOption: self.downscaleReferenceETPot() # smoothing: if self.forcingSmoothing == True: logger.debug("Forcing data are smoothed.") self.precipitation = pcr.windowaverage(self.precipitation, self.smoothingWindowsLength) self.temperature = pcr.windowaverage(self.temperature, self.smoothingWindowsLength) self.referencePotET = pcr.windowaverage( self.referencePotET, self.smoothingWindowsLength) # rounding temperature values to minimize numerical errors (note only to minimize, not remove) self.temperature = pcr.roundoff(self.temperature * 1000.) / 1000. # ignore snow by setting temperature to 25 deg C if self.ignore_snow: self.temperature = pcr.spatial(pcr.scalar(25.)) # define precipitation, temperature and referencePotET ONLY at landmask area (for reporting): self.precipitation = pcr.ifthen(self.landmask, self.precipitation) self.temperature = pcr.ifthen(self.landmask, self.temperature) self.referencePotET = pcr.ifthen(self.landmask, self.referencePotET) # make sure precipitation and referencePotET are always positive: self.precipitation = pcr.max(0.0, self.precipitation) self.referencePotET = pcr.max(0.0, self.referencePotET) if self.report == True: timeStamp = datetime.datetime(currTimeStep.year,\ currTimeStep.month,\ currTimeStep.day,\ 0) # writing daily output to netcdf files timestepPCR = currTimeStep.timeStepPCR if self.outDailyTotNC[0] != "None": for var in self.outDailyTotNC: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_dailyTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,timestepPCR-1) # writing monthly output to netcdf files # -cummulative if self.outMonthTotNC[0] != "None": for var in self.outMonthTotNC: # introduce variables at the beginning of simulation or # reset variables at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.day == 1: \ vars(self)[var+'MonthTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'MonthTot'] += vars(self)[var] # reporting at the end of the month: if currTimeStep.endMonth == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'MonthTot'),\ vos.MV),timeStamp,currTimeStep.monthIdx-1) # -average if self.outMonthAvgNC[0] != "None": for var in self.outMonthAvgNC: # only if a accumulator variable has not been defined: if var not in self.outMonthTotNC: # introduce accumulator at the beginning of simulation or # reset accumulator at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.day == 1: \ vars(self)[var+'MonthTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'MonthTot'] += vars(self)[var] # calculating average & reporting at the end of the month: if currTimeStep.endMonth == True: vars(self)[var+'MonthAvg'] = vars(self)[var+'MonthTot']/\ currTimeStep.day self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthAvg.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'MonthAvg'),\ vos.MV),timeStamp,currTimeStep.monthIdx-1) # # -last day of the month if self.outMonthEndNC[0] != "None": for var in self.outMonthEndNC: # reporting at the end of the month: if currTimeStep.endMonth == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthEnd.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,currTimeStep.monthIdx-1) # writing yearly output to netcdf files # -cummulative if self.outAnnuaTotNC[0] != "None": for var in self.outAnnuaTotNC: # introduce variables at the beginning of simulation or # reset variables at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.doy == 1: \ vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'AnnuaTot'] += vars(self)[var] # reporting at the end of the year: if currTimeStep.endYear == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'AnnuaTot'),\ vos.MV),timeStamp,currTimeStep.annuaIdx-1) # -average if self.outAnnuaAvgNC[0] != "None": for var in self.outAnnuaAvgNC: # only if a accumulator variable has not been defined: if var not in self.outAnnuaTotNC: # introduce accumulator at the beginning of simulation or # reset accumulator at the beginning of the year if currTimeStep.timeStepPCR == 1 or \ currTimeStep.doy == 1: \ vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'AnnuaTot'] += vars(self)[var] # # calculating average & reporting at the end of the year: if currTimeStep.endYear == True: vars(self)[var+'AnnuaAvg'] = vars(self)[var+'AnnuaTot']/\ currTimeStep.doy self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaAvg.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'AnnuaAvg'),\ vos.MV),timeStamp,currTimeStep.annuaIdx-1) # # -last day of the year if self.outAnnuaEndNC[0] != "None": for var in self.outAnnuaEndNC: # reporting at the end of the year: if currTimeStep.endYear == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaEnd.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,currTimeStep.annuaIdx-1)
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)
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 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 )
def read_forcings(self, currTimeStep): # reading precipitation: self.precipitation = vos.netcdf2PCRobjClone(\ self.preFileNC,'precipitation',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName=self.cloneMap,\ LatitudeLongitude = True) precipitationCorrectionFactor = pcr.scalar( 1.0 ) # Since 19 Feb 2014, Edwin removed the support for correcting precipitation. self.precipitation = pcr.max(0.,self.precipitation*\ precipitationCorrectionFactor) self.precipitation = pcr.cover(self.precipitation, 0.0) # ignore very small values of precipitation (less than 0.00001 m/day or less than 0.01 kg.m-2.day-1 ) if self.usingDailyTimeStepForcingData: self.precipitation = pcr.rounddown( self.precipitation * 100000.) / 100000. # reading temperature self.temperature = vos.netcdf2PCRobjClone(\ self.tmpFileNC,'temperature',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName=self.cloneMap,\ LatitudeLongitude = True) # Downscaling precipitation and temperature if self.downscalePrecipitationOption: self.downscalePrecipitation(currTimeStep) if self.downscaleTemperatureOption: self.downscaleTemperature(currTimeStep) # calculate or obtain referencePotET if self.refETPotMethod == 'Hamon': self.referencePotET = \ refPotET.HamonPotET(self.temperature,\ currTimeStep.doy,\ self.latitudes) if self.refETPotMethod == 'Input': self.referencePotET = vos.netcdf2PCRobjClone(\ self.etpFileNC,'evapotranspiration',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName=self.cloneMap,\ LatitudeLongitude = True) # Downscaling referenceETPot (based on temperature) if self.downscaleReferenceETPotOption: self.downscaleReferenceETPot() # smoothing: if self.forcingSmoothing == True: logger.info("Forcing data are smoothed.") self.precipitation = pcr.windowaverage(self.precipitation, self.smoothingWindowsLength) self.temperature = pcr.windowaverage(self.temperature, self.smoothingWindowsLength) self.referencePotET = pcr.windowaverage( self.referencePotET, self.smoothingWindowsLength) # define precipitation, temperature and referencePotET ONLY at landmask area (for reporting): self.precipitation = pcr.ifthen(self.landmask, self.precipitation) self.temperature = pcr.ifthen(self.landmask, self.temperature) self.referencePotET = pcr.ifthen(self.landmask, self.referencePotET) if self.report == True: timeStamp = datetime.datetime(currTimeStep.year,\ currTimeStep.month,\ currTimeStep.day,\ 0) # writing daily output to netcdf files timestepPCR = currTimeStep.timeStepPCR if self.outDailyTotNC[0] != "None": for var in self.outDailyTotNC: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_dailyTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,timestepPCR-1) # writing monthly output to netcdf files # -cummulative if self.outMonthTotNC[0] != "None": for var in self.outMonthTotNC: # introduce variables at the beginning of simulation or # reset variables at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.day == 1: \ vars(self)[var+'MonthTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'MonthTot'] += vars(self)[var] # reporting at the end of the month: if currTimeStep.endMonth == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'MonthTot'),\ vos.MV),timeStamp,currTimeStep.monthIdx-1) # -average if self.outMonthAvgNC[0] != "None": for var in self.outMonthAvgNC: # only if a accumulator variable has not been defined: if var not in self.outMonthTotNC: # introduce accumulator at the beginning of simulation or # reset accumulator at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.day == 1: \ vars(self)[var+'MonthTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'MonthTot'] += vars(self)[var] # calculating average & reporting at the end of the month: if currTimeStep.endMonth == True: vars(self)[var+'MonthAvg'] = vars(self)[var+'MonthTot']/\ currTimeStep.day self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthAvg.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'MonthAvg'),\ vos.MV),timeStamp,currTimeStep.monthIdx-1) # # -last day of the month if self.outMonthEndNC[0] != "None": for var in self.outMonthEndNC: # reporting at the end of the month: if currTimeStep.endMonth == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthEnd.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,currTimeStep.monthIdx-1) # writing yearly output to netcdf files # -cummulative if self.outAnnuaTotNC[0] != "None": for var in self.outAnnuaTotNC: # introduce variables at the beginning of simulation or # reset variables at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.doy == 1: \ vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'AnnuaTot'] += vars(self)[var] # reporting at the end of the year: if currTimeStep.endYear == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'AnnuaTot'),\ vos.MV),timeStamp,currTimeStep.annuaIdx-1) # -average if self.outAnnuaAvgNC[0] != "None": for var in self.outAnnuaAvgNC: # only if a accumulator variable has not been defined: if var not in self.outAnnuaTotNC: # introduce accumulator at the beginning of simulation or # reset accumulator at the beginning of the year if currTimeStep.timeStepPCR == 1 or \ currTimeStep.doy == 1: \ vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'AnnuaTot'] += vars(self)[var] # # calculating average & reporting at the end of the year: if currTimeStep.endYear == True: vars(self)[var+'AnnuaAvg'] = vars(self)[var+'AnnuaTot']/\ currTimeStep.doy self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaAvg.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'AnnuaAvg'),\ vos.MV),timeStamp,currTimeStep.annuaIdx-1) # # -last day of the year if self.outAnnuaEndNC[0] != "None": for var in self.outAnnuaEndNC: # reporting at the end of the year: if currTimeStep.endYear == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaEnd.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,currTimeStep.annuaIdx-1)
def read_forcings(self, currTimeStep): # reading precipitation: if self.precipitation_set_per_year: #~ print currTimeStep.year nc_file_per_year = self.preFileNC % (float( currTimeStep.year), float(currTimeStep.year)) self.precipitation = vos.netcdf2PCRobjClone(\ nc_file_per_year, 'precipitation',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) else: #self.precipitation = vos.netcdf2PCRobjClone(\ # self.preFileNC, 'precipitation',\ # str(currTimeStep.fulldate), # useDoy = None, # cloneMapFileName = self.cloneMap,\ # LatitudeLongitude = True) # reading precip when ISI-MIP is used precipitation = vos.netcdf2PCRobjClone(\ self.preFileNC, 'pr',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) # unit original km m-2 s-1 to m d-1 # soortelijk gewicht water = 998 km/m3 self.precipitation = (precipitation / 998.0) * (60. * 60. * 24) precipitationCorrectionFactor = pcr.scalar( 1.0 ) # Since 19 Feb 2014, Edwin removed the support for correcting precipitation. self.precipitation = pcr.max(0.,self.precipitation*\ precipitationCorrectionFactor) self.precipitation = pcr.cover(self.precipitation, 0.0) # ignore very small values of precipitation (less than 0.00001 m/day or less than 0.01 kg.m-2.day-1 ) if self.usingDailyTimeStepForcingData: self.precipitation = pcr.rounddown( self.precipitation * 100000.) / 100000. # reading temperature if self.temperature_set_per_year: nc_file_per_year = self.tmpFileNC % (int( currTimeStep.year), int(currTimeStep.year)) self.temperature = vos.netcdf2PCRobjClone(\ nc_file_per_year, 'temperature',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) else: # updated to temp when using ISI-MIP projection temperature = vos.netcdf2PCRobjClone(\ self.tmpFileNC,'tas',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName=self.cloneMap,\ LatitudeLongitude = True) # unit K to C self.temperature = temperature - 273.15 # Downscaling precipitation and temperature if self.downscalePrecipitationOption: self.downscalePrecipitation(currTimeStep) if self.downscaleTemperatureOption: self.downscaleTemperature(currTimeStep) # calculate or obtain referencePotET if self.refETPotMethod == 'Hamon': self.referencePotET = \ refPotET.HamonPotET(self.temperature,\ currTimeStep.doy,\ self.latitudes) if self.refETPotMethod == 'Input': if self.refETPotFileNC_set_per_year: nc_file_per_year = self.etpFileNC % (int( currTimeStep.year), int(currTimeStep.year)) self.referencePotET = vos.netcdf2PCRobjClone(\ nc_file_per_year, 'evapotranspiration',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) else: self.referencePotET = vos.netcdf2PCRobjClone(\ self.etpFileNC,'evapotranspiration',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName=self.cloneMap,\ LatitudeLongitude = True) # Downscaling referenceETPot (based on temperature) if self.downscaleReferenceETPotOption: self.downscaleReferenceETPot() # smoothing: if self.forcingSmoothing == True: logger.debug("Forcing data are smoothed.") self.precipitation = pcr.windowaverage(self.precipitation, self.smoothingWindowsLength) self.temperature = pcr.windowaverage(self.temperature, self.smoothingWindowsLength) self.referencePotET = pcr.windowaverage( self.referencePotET, self.smoothingWindowsLength) # make sure precipitation is always positive: self.precipitation = pcr.max(0.0, self.precipitation) # rounding temperature values to minimize numerical errors (note only to minimize, not remove) self.temperature = pcr.roundoff(self.temperature * 1000.) / 1000. # ignore snow by setting temperature to 25 deg C if self.ignore_snow: self.temperature = pcr.spatial(pcr.scalar(25.)) # define precipitation, temperature and referencePotET ONLY at landmask area (for reporting): self.precipitation = pcr.ifthen(self.landmask, self.precipitation) self.temperature = pcr.ifthen(self.landmask, self.temperature) self.referencePotET = pcr.ifthen(self.landmask, self.referencePotET) if self.report == True: timeStamp = datetime.datetime(currTimeStep.year,\ currTimeStep.month,\ currTimeStep.day,\ 0) # writing daily output to netcdf files timestepPCR = currTimeStep.timeStepPCR if self.outDailyTotNC[0] != "None": for var in self.outDailyTotNC: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_dailyTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,timestepPCR-1) # writing monthly output to netcdf files # -cummulative if self.outMonthTotNC[0] != "None": for var in self.outMonthTotNC: # introduce variables at the beginning of simulation or # reset variables at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.day == 1: \ vars(self)[var+'MonthTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'MonthTot'] += vars(self)[var] # reporting at the end of the month: if currTimeStep.endMonth == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'MonthTot'),\ vos.MV),timeStamp,currTimeStep.monthIdx-1) # -average if self.outMonthAvgNC[0] != "None": for var in self.outMonthAvgNC: # only if a accumulator variable has not been defined: if var not in self.outMonthTotNC: # introduce accumulator at the beginning of simulation or # reset accumulator at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.day == 1: \ vars(self)[var+'MonthTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'MonthTot'] += vars(self)[var] # calculating average & reporting at the end of the month: if currTimeStep.endMonth == True: vars(self)[var+'MonthAvg'] = vars(self)[var+'MonthTot']/\ currTimeStep.day self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthAvg.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'MonthAvg'),\ vos.MV),timeStamp,currTimeStep.monthIdx-1) # # -last day of the month if self.outMonthEndNC[0] != "None": for var in self.outMonthEndNC: # reporting at the end of the month: if currTimeStep.endMonth == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthEnd.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,currTimeStep.monthIdx-1) # writing yearly output to netcdf files # -cummulative if self.outAnnuaTotNC[0] != "None": for var in self.outAnnuaTotNC: # introduce variables at the beginning of simulation or # reset variables at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.doy == 1: \ vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'AnnuaTot'] += vars(self)[var] # reporting at the end of the year: if currTimeStep.endYear == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'AnnuaTot'),\ vos.MV),timeStamp,currTimeStep.annuaIdx-1) # -average if self.outAnnuaAvgNC[0] != "None": for var in self.outAnnuaAvgNC: # only if a accumulator variable has not been defined: if var not in self.outAnnuaTotNC: # introduce accumulator at the beginning of simulation or # reset accumulator at the beginning of the year if currTimeStep.timeStepPCR == 1 or \ currTimeStep.doy == 1: \ vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'AnnuaTot'] += vars(self)[var] # # calculating average & reporting at the end of the year: if currTimeStep.endYear == True: vars(self)[var+'AnnuaAvg'] = vars(self)[var+'AnnuaTot']/\ currTimeStep.doy self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaAvg.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'AnnuaAvg'),\ vos.MV),timeStamp,currTimeStep.annuaIdx-1) # # -last day of the year if self.outAnnuaEndNC[0] != "None": for var in self.outAnnuaEndNC: # reporting at the end of the year: if currTimeStep.endYear == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaEnd.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,currTimeStep.annuaIdx-1)
import pcraster as pcr import netCDF4 as nc # clone map clone_map_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/lddsound_05min.map" pcr.setclone(clone_map_file_name) # aquifer thickness map: aquifer_thickness_file_name = "/projects/0/dfguu/users/edwin/data/aquifer_properties/thickness_05min.map" aquifer_thickness = pcr.readmap(aquifer_thickness_file_name) # extent of confining layer extent_of_confining_layer_file_name = "/home/edwin/data/inge_confining_layer_parameters/conflayers4.map" confining_layer_extent = pcr.boolean(pcr.readmap(extent_of_confining_layer_file_name)) # thickness of confining layer = 10 percent from the first 250 m confining_layer_thickness = pcr.ifthen(confining_layer_extent, pcr.min(250.0, aquifer_thickness)) * 0.10 # extrapolate confining_layer_thickness = pcr.cover(confining_layer_thickness, pcr.windowaverage(pcr.cover(confining_layer_thickness, 0.0), 0.50)) confining_layer_thickness = pcr.cover(confining_layer_thickness, 0.0) confining_layer_thickness_output_filename = "/home/edwin/data/inge_confining_layer_parameters/confining_layer_thickness_edwin.map" pcr.report(confining_layer_thickness, confining_layer_thickness_output_filename) # masking only to the landmask landmask_file_name = "/projects/0/dfguu/data/hydroworld/PCRGLOBWB20/input5min/routing/lddsound_05min.map" landmask = pcr.defined(landmask_file_name) confining_layer_thickness_masked_output_filename = "/home/edwin/data/inge_confining_layer_parameters/confining_layer_thickness_edwin.masked.map" pcr.report(pcr.ifthen(landmask, confining_layer_thickness), confining_layer_thickness_masked_output_filename)
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) # we only use pixels belonging to the sedimentary basin class_map_all = class_map class_map = pcr.ifthen(sedimentary_basin > 0, class_map) # fraction for groundwater recharge to be reserved to meet the environmental flow fraction_reserved_recharge = pcr.readmap("/nfsarchive/edwin-emergency-backup-DO-NOT-DELETE/rapid/edwin/05min_runs_results/2015_04_27/non_natural_2015_04_27/global/analysis/reservedrecharge/fraction_reserved_recharge10.5min.map") # - extrapolation fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \ pcr.windowaverage(fraction_reserved_recharge, 0.5)) fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \ pcr.windowaverage(fraction_reserved_recharge, 0.5)) fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \ pcr.windowaverage(fraction_reserved_recharge, 0.5)) fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \ pcr.windowaverage(fraction_reserved_recharge, 0.5)) fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \ pcr.windowaverage(fraction_reserved_recharge, 0.5)) fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \ pcr.windowaverage(fraction_reserved_recharge, 0.5)) fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, \ pcr.windowaverage(fraction_reserved_recharge, 0.5)) fraction_reserved_recharge = pcr.cover(fraction_reserved_recharge, 0.1) # - set minimum value to 0.10 fraction_reserved_recharge = pcr.max(0.10, fraction_reserved_recharge)