def waterBalanceCheck(fluxesIn,fluxesOut,preStorages,endStorages,processName,PrintOnlyErrors,dateStr,threshold=1e-5,landmask=None): """ Returns the water balance for a list of input, output, and storage map files """ # modified by Edwin (22 Apr 2013) inMap = pcr.spatial(pcr.scalar(0.0)) outMap = pcr.spatial(pcr.scalar(0.0)) dsMap = pcr.spatial(pcr.scalar(0.0)) for fluxIn in fluxesIn: inMap += fluxIn for fluxOut in fluxesOut: outMap += fluxOut for preStorage in preStorages: dsMap += preStorage for endStorage in endStorages: dsMap -= endStorage a,b,c = getMinMaxMean(inMap + dsMap- outMap) if abs(a) > threshold or abs(b) > threshold: if PrintOnlyErrors: msg = "\n" msg += "\n" msg = "\n" msg += "\n" msg += "##############################################################################################################################################\n" msg += "WARNING !!!!!!!! Water Balance Error %s Min %f Max %f Mean %f" %(processName,a,b,c) msg += "\n" msg += "##############################################################################################################################################\n" msg += "\n" msg += "\n" msg += "\n" logger.error(msg)
def lattometres(lat): """" Determines the length of one degree lat/long at a given latitude (in meter). Code taken from http:www.nga.mil/MSISiteContent/StaticFiles/Calculators/degree.html Input: map with lattitude values for each cell Returns: length of a cell lat, length of a cell long """ # radlat = pcr.spatial(lat * ((2.0 * math.pi)/360.0)) # radlat = lat * (2.0 * math.pi)/360.0 pcr.setglobaloption("degrees") radlat = pcr.spatial(lat) # pcraster cos/sin work in degrees! m1 = 111132.92 # latitude calculation term 1 m2 = -559.82 # latitude calculation term 2 m3 = 1.175 # latitude calculation term 3 m4 = -0.0023 # latitude calculation term 4 p1 = 111412.84 # longitude calculation term 1 p2 = -93.5 # longitude calculation term 2 p3 = 0.118 # longitude calculation term 3 # # Calculate the length of a degree of latitude and longitude in meters latlen = ( m1 + (m2 * pcr.cos(2.0 * radlat)) + (m3 * pcr.cos(4.0 * radlat)) + (m4 * pcr.cos(6.0 * radlat)) ) longlen = ( (p1 * pcr.cos(radlat)) + (p2 * pcr.cos(3.0 * radlat)) + (p3 * pcr.cos(5.0 * radlat)) ) return latlen, longlen
def find_outlet(ldd): """ Tries to find the outlet of the largest catchment in the Ldd Input: - Ldd Output: - outlet map (single point in the map) """ largest = pcr.mapmaximum(pcr.catchmenttotal(pcr.spatial(pcr.scalar(1.0)), ldd)) outlet = pcr.ifthen( pcr.catchmenttotal(1.0, ldd) == largest, pcr.spatial(pcr.scalar(1.0)) ) return outlet
def sample(self, expression): """ Sampling the current values of 'expression' at the given locations for the current timestep """ arrayRowPos = self._userModel.currentTimeStep() - self._userModel.firstTimeStep() #if isinstance(expression, float): # expression = pcraster.scalar(expression) try: # store the data type for tss file header if self._spatialDatatype == None: self._spatialDatatype = str(expression.dataType()) except AttributeError as e: datatype, sep, tail = str(e).partition(" ") msg = "Argument must be a PCRaster map, type %s given. If necessary use data conversion functions like scalar()" % (datatype) raise AttributeError(msg) if self._spatialIdGiven: if expression.dataType() == pcraster.Scalar or expression.dataType() == pcraster.Directional: tmp = pcraster.areaaverage(pcraster.spatial(expression), pcraster.spatial(self._spatialId)) else: tmp = pcraster.areamajority(pcraster.spatial(expression), pcraster.spatial(self._spatialId)) col = 0 for cellIndex in self._sampleAddresses: value, valid = pcraster.cellvalue(tmp, cellIndex) if not valid: value = Decimal("NaN") self._sampleValues[arrayRowPos][col] = value col += 1 else: if expression.dataType() == pcraster.Scalar or expression.dataType() == pcraster.Directional: tmp = pcraster.maptotal(pcraster.spatial(expression))\ / pcraster.maptotal(pcraster.scalar(pcraster.defined(pcraster.spatial(expression)))) else: tmp = pcraster.mapmaximum(pcraster.maptotal(pcraster.areamajority(pcraster.spatial(expression),\ pcraster.spatial(pcraster.nominal(1))))) value, valid = pcraster.cellvalue(tmp, 1) if not valid: value = Decimal("NaN") self._sampleValues[arrayRowPos] = value if self._userModel.currentTimeStep() == self._userModel.nrTimeSteps(): self._writeTssFile()
def waterBalanceCheck(fluxesIn,fluxesOut,preStorages,endStorages,processName,PrintOnlyErrors,dateStr,threshold=1e-5,landmask=None): """ Returns the water balance for a list of input, output, and storage map files """ # modified by Edwin (22 Apr 2013) inMap = pcr.spatial(pcr.scalar(0.0)) outMap = pcr.spatial(pcr.scalar(0.0)) dsMap = pcr.spatial(pcr.scalar(0.0)) for fluxIn in fluxesIn: inMap += fluxIn for fluxOut in fluxesOut: outMap += fluxOut for preStorage in preStorages: dsMap += preStorage for endStorage in endStorages: dsMap -= endStorage a,b,c = getMinMaxMean(inMap + dsMap- outMap) if abs(a) > threshold or abs(b) > threshold: if PrintOnlyErrors: print "WBError %s Min %f Max %f Mean %f" %(processName,a,b,c) print "" wb = inMap + dsMap - outMap maxWBError = pcr.cellvalue(pcr.mapmaximum(pcr.abs(wb)), 1, 1)[0]
def arbitraryMapEquals(self, firstMap, secondMap): import math def floatEquals(float1, float2): threshold = 1e-6 return math.fabs(float1 - float2) <= threshold if((firstMap.dataType() == _pcraster.Scalar) | \ (firstMap.dataType() == _pcraster.Directional)): result = _pcraster._closeAtTolerance(firstMap, secondMap) else: result = pcraster.pcreq(firstMap, secondMap) minMap = pcraster.mapminimum(pcraster.spatial(pcraster.scalar(result))) value, isValid = pcraster.cellvalue(minMap, 1) assert isValid return floatEquals(value, 1.0)
def test_003(self): """ pcr2numpy should not run out of memory """ nrRows, nrCols, cellSize = 200, 200, 1.0 west, north = 0.0, 0.0 pcraster.setclone(nrRows, nrCols, cellSize, west, north) raster = pcraster.uniform(1) process = psutil.Process(os.getpid()) mem = process.memory_info() init_mem = mem.rss / 2**10 nr_iterations = 50 mem_increase = False # small memory increase can occur at runtime # allow for, but less than iterations * size(raster) max_diff = 400 for it in range(0, nr_iterations): pcraster.pcr2numpy(raster, numpy.nan) mem = process.memory_info() curr_mem = mem.rss / 2**10 if curr_mem - init_mem > max_diff: mem_increase = True raster = pcraster.spatial(pcraster.boolean(1)) for it in range(0, nr_iterations): pcraster.pcr2numpy(raster, numpy.nan) mem = process.memory_info() curr_mem = mem.rss / 2**10 if curr_mem - init_mem > max_diff: mem_increase = True raster = pcraster.nominal(pcraster.uniform(1) * 10) for it in range(0, nr_iterations): pcraster.pcr2numpy(raster, numpy.nan) mem = process.memory_info() curr_mem = mem.rss / 2**10 if curr_mem - init_mem > max_diff: mem_increase = True self.assertEqual(mem_increase, False)
def dayLength(doy, lat): """ daylength fraction of day """ lat = lat * pcr.scalar(math.pi) / 180.0 M_PI_2 = pcr.spatial(pcr.scalar(math.pi / 2.0)) dec = pcr.sin((6.224111 + 0.017202 * doy) * 180 / math.pi) dec = pcr.scalar(0.39785 * pcr.sin( (4.868961 + .017203 * doy + 0.033446 * pcr.sin(dec * 180 / math.pi)) * 180 / math.pi)) dec = pcr.scalar(pcr.asin(dec)) lat = pcr.ifthenelse( pcr.abs(lat) > M_PI_2, (M_PI_2 - pcr.scalar(0.01)) * pcr.ifthenelse(lat > 0, pcr.scalar(1.0), pcr.scalar(-1.0)), lat) arg = pcr.tan(dec) * pcr.tan(lat * 180.0 / math.pi) * -1 h = pcr.scalar(pcr.acos(arg)) h = h / 180 * math.pi h = pcr.ifthenelse(arg > 1.0, 0.0, h) # /* sun stays below horizon */ h = pcr.ifthenelse(arg < -1.0, math.pi, h) # /* sun stays above horizon */ return (h / math.pi)
def areastat(Var, Area): """ Calculate several statistics of *Var* for each unique id in *Area* Input: - Var - Area Output: - Standard_Deviation,Average,Max,Min """ Avg = pcr.areaaverage(Var, Area) Sq = (Var - Avg) ** 2 N = pcr.areatotal(pcr.spatial(pcr.cellarea()), Area) / pcr.cellarea() Sd = (pcr.areatotal(Sq, Area) / N) ** 0.5 Max = pcr.areamaximum(Var, Area) Min = pcr.areaminimum(Var, Area) return Sd, Avg, Max, Min
def main(): # output folder (and tmp folder) clean_out_folder = True if os.path.exists(out_folder): if clean_out_folder: shutil.rmtree(out_folder) os.makedirs(out_folder) else: os.makedirs(out_folder) os.chdir(out_folder) os.system("pwd") # set the clone map print("set the clone") pcr.setclone(global_ldd_30min_inp_file) # define the landmask print("define the landmask") # - based on the 30min input landmask_30min = define_landmask(input_file = global_landmask_30min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_30min_only.map") # - based on the 05min input landmask_05min = define_landmask(input_file = global_landmask_05min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_05min_only.map") # - based on the 06min input landmask_06min = define_landmask(input_file = global_landmask_06min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_06min_only.map") # - based on the 30sec input landmask_30sec = define_landmask(input_file = global_landmask_30sec_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_30sec_only.map") # - based on the 30sec input landmask_03sec = define_landmask(input_file = global_landmask_03sec_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_03sec_only.map") # # - merge all landmasks landmask = pcr.cover(landmask_30min, landmask_05min, landmask_06min, landmask_30sec, landmask_03sec) pcr.report(landmask, "global_landmask_extended_30min.map") # ~ pcr.aguila(landmask) # extend ldd print("extend/define the ldd") ldd_map = pcr.readmap(global_ldd_30min_inp_file) ldd_map = pcr.ifthen(landmask, pcr.cover(ldd_map, pcr.ldd(5))) pcr.report(ldd_map, "global_ldd_extended_30min.map") # ~ pcr.aguila(ldd_map) # catchment map and size catchment_map = pcr.catchment(ldd_map, pcr.pit(ldd_map)) catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) # ~ pcr.aguila(catchment_size) # identify small islands print("identify small islands") # - maps of islands smaller than 15000 cells (at half arc degree resolution) island_map = pcr.ifthen(landmask, pcr.clump(pcr.defined(ldd_map))) island_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), island_map) island_map = pcr.ifthen(island_size < 15000., island_map) # ~ # - use catchments (instead of islands) # ~ island_map = catchment_map # ~ island_size = catchment_size # ~ island_map = pcr.ifthen(island_size < 10000., island_map) # - sort from the largest island # -- take one cell per island as a representative island_map_rep_size = pcr.ifthen( pcr.areaorder(island_size, island_map) == 1.0, island_size) # -- sort from the largest island island_map_rep_ids = pcr.areaorder( island_map_rep_size * -1.00, pcr.ifthen(pcr.defined(island_map_rep_size), pcr.nominal(1.0))) # -- map of smaller islands, sorted from the largest one island_map = pcr.areamajority(pcr.nominal(island_map_rep_ids), island_map) # identify the biggest island for every group of small islands within a certain window (arcdeg cells) print("the biggest island for every group of small islands") large_island_map = pcr.ifthen( pcr.scalar(island_map) == pcr.windowminimum(pcr.scalar(island_map), 15.), island_map) # ~ pcr.aguila(large_island_map) # identify big catchments print("identify large catchments") catchment_map = pcr.catchment(ldd_map, pcr.pit(ldd_map)) catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) # ~ # - identify all large catchments with size >= 50 cells (at the resolution of 30 arcmin) = 50 x (50^2) km2 = 125000 km2 # ~ large_catchment_map = pcr.ifthen(catchment_size >= 50, catchment_map) # ~ # - identify all large catchments with size >= 10 cells (at the resolution of 30 arcmin) # ~ large_catchment_map = pcr.ifthen(catchment_size >= 10, catchment_map) # ~ # - identify all large catchments with size >= 5 cells (at the resolution of 30 arcmin) # ~ large_catchment_map = pcr.ifthen(catchment_size >= 5, catchment_map) # ~ # - identify all large catchments with size >= 20 cells (at the resolution of 30 arcmin) # ~ large_catchment_map = pcr.ifthen(catchment_size >= 20, catchment_map) # - identify all large catchments with size >= 25 cells (at the resolution of 30 arcmin) large_catchment_map = pcr.ifthen(catchment_size >= 25, catchment_map) # - give the codes that are different than islands large_catchment_map = pcr.nominal( pcr.scalar(large_catchment_map) + 10. * vos.getMinMaxMean(pcr.scalar(large_island_map))[1]) # merge biggest islands and big catchments print("merge large catchments and islands") large_catchment_and_island_map = pcr.cover(large_catchment_map, large_island_map) # ~ large_catchment_and_island_map = pcr.cover(large_island_map, large_catchment_map) large_catchment_and_island_map_size = pcr.areatotal( pcr.spatial(pcr.scalar(1.0)), large_catchment_and_island_map) # - sort from the largest one # -- take one cell per island as a representative large_catchment_and_island_map_rep_size = pcr.ifthen( pcr.areaorder(large_catchment_and_island_map_size, large_catchment_and_island_map) == 1.0, large_catchment_and_island_map_size) # -- sort from the largest large_catchment_and_island_map_rep_ids = pcr.areaorder( large_catchment_and_island_map_rep_size * -1.00, pcr.ifthen(pcr.defined(large_catchment_and_island_map_rep_size), pcr.nominal(1.0))) # -- map of largest catchments and islands, sorted from the largest one large_catchment_and_island_map = pcr.areamajority( pcr.nominal(large_catchment_and_island_map_rep_ids), large_catchment_and_island_map) # ~ pcr.report(large_catchment_and_island_map, "large_catchments_and_islands.map") # ~ # perform cdo fillmiss2 in order to merge the small catchments to the nearest large catchments # ~ print("spatial interpolation/extrapolation using cdo fillmiss2 to get initial subdomains") # ~ cmd = "gdal_translate -of NETCDF large_catchments_and_islands.map large_catchments_and_islands.nc" # ~ print(cmd); os.system(cmd) # ~ cmd = "cdo fillmiss2 large_catchments_and_islands.nc large_catchments_and_islands_filled.nc" # ~ print(cmd); os.system(cmd) # ~ cmd = "gdal_translate -of PCRaster large_catchments_and_islands_filled.nc large_catchments_and_islands_filled.map" # ~ print(cmd); os.system(cmd) # ~ cmd = "mapattr -c " + global_ldd_30min_inp_file + " " + "large_catchments_and_islands_filled.map" # ~ print(cmd); os.system(cmd) # ~ # - initial subdomains # ~ subdomains_initial = pcr.nominal(pcr.readmap("large_catchments_and_islands_filled.map")) # ~ subdomains_initial = pcr.areamajority(subdomains_initial, catchment_map) # ~ pcr.aguila(subdomains_initial) # spatial interpolation/extrapolation in order to merge the small catchments to the nearest large catchments print("spatial interpolation/extrapolation to get initial subdomains") field = large_catchment_and_island_map cellID = pcr.nominal(pcr.uniqueid(pcr.defined(field))) zoneID = pcr.spreadzone(cellID, 0, 1) field = pcr.areamajority(field, zoneID) subdomains_initial = field subdomains_initial = pcr.areamajority(subdomains_initial, catchment_map) pcr.aguila(subdomains_initial) pcr.report(subdomains_initial, "global_subdomains_30min_initial.map") print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[0]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[1]))) # ~ print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial_clump))[0]))) # ~ print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial_clump))[1]))) print("Checking all subdomains, avoid too large subdomains") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[1]) # clone code that will be assigned assigned_number = 0 subdomains_final = pcr.ifthen( pcr.scalar(subdomains_initial) < -7777, pcr.nominal(0)) for nr in range(1, num_of_masks + 1, 1): msg = "Processing the landmask %s" % (str(nr)) print(msg) mask_selected_boolean = pcr.ifthen(subdomains_initial == nr, pcr.boolean(1.0)) # ~ if nr == 1: pcr.aguila(mask_selected_boolean) xmin, ymin, xmax, ymax = boundingBox(mask_selected_boolean) area_in_degree2 = (xmax - xmin) * (ymax - ymin) # ~ print(str(area_in_degree2)) # check whether the size of bounding box is ok # - initial check value check_ok = True reference_area_in_degree2 = 2500. if area_in_degree2 > 1.50 * reference_area_in_degree2: check_ok = False if (xmax - xmin) > 10 * (ymax - ymin): check_ok = False if check_ok == True: msg = "Clump is not needed." msg = "\n\n" + str(msg) + "\n\n" print(msg) # assign the clone code assigned_number = assigned_number + 1 # update global landmask for river and land mask_selected_nominal = pcr.ifthen(mask_selected_boolean, pcr.nominal(assigned_number)) subdomains_final = pcr.cover(subdomains_final, mask_selected_nominal) if check_ok == False: msg = "Clump is needed." msg = "\n\n" + str(msg) + "\n\n" print(msg) # make clump clump_ids = pcr.nominal(pcr.clump(mask_selected_boolean)) # merge clumps that are close together clump_ids_window_majority = pcr.windowmajority(clump_ids, 10.0) clump_ids = pcr.areamajority(clump_ids_window_majority, clump_ids) # ~ pcr.aguila(clump_ids) # minimimum and maximum values min_clump_id = int( pcr.cellvalue(pcr.mapminimum(pcr.scalar(clump_ids)), 1)[0]) max_clump_id = int( pcr.cellvalue(pcr.mapmaximum(pcr.scalar(clump_ids)), 1)[0]) for clump_id in range(min_clump_id, max_clump_id + 1, 1): msg = "Processing the clump %s of %s from the landmask %s" % ( str(clump_id), str(max_clump_id), str(nr)) msg = "\n\n" + str(msg) + "\n\n" print(msg) # identify mask based on the clump mask_selected_boolean_from_clump = pcr.ifthen( clump_ids == pcr.nominal(clump_id), mask_selected_boolean) mask_selected_boolean_from_clump = pcr.ifthen( mask_selected_boolean_from_clump, mask_selected_boolean_from_clump) # check whether the clump is empty check_mask_selected_boolean_from_clump = pcr.ifthen( mask_selected_boolean, mask_selected_boolean_from_clump) check_if_empty = float( pcr.cellvalue( pcr.mapmaximum( pcr.scalar( pcr.defined( check_mask_selected_boolean_from_clump))), 1)[0]) if check_if_empty == 0.0: msg = "Map is empty !" msg = "\n\n" + str(msg) + "\n\n" print(msg) else: msg = "Map is NOT empty !" msg = "\n\n" + str(msg) + "\n\n" print(msg) # assign the clone code assigned_number = assigned_number + 1 # update global landmask for river and land mask_selected_nominal = pcr.ifthen( mask_selected_boolean_from_clump, pcr.nominal(assigned_number)) subdomains_final = pcr.cover(subdomains_final, mask_selected_nominal) # ~ # kill all aguila processes if exist # ~ os.system('killall aguila') pcr.aguila(subdomains_final) print("") print("") print("") print("The subdomain map is READY.") pcr.report(subdomains_final, "global_subdomains_30min_final.map") num_of_masks = int(vos.getMinMaxMean(pcr.scalar(subdomains_final))[1]) print(num_of_masks) print("") print("") print("") for nr in range(1, num_of_masks + 1, 1): mask_selected_boolean = pcr.ifthen(subdomains_final == nr, pcr.boolean(1.0)) xmin, ymin, xmax, ymax = boundingBox(mask_selected_boolean) area_in_degree2 = (xmax - xmin) * (ymax - ymin) print( str(nr) + " ; " + str(area_in_degree2) + " ; " + str((xmax - xmin)) + " ; " + str((ymax - ymin))) print("") print("") print("") print("Number of subdomains: " + str(num_of_masks)) print("") print("") print("") # spatial extrapolation in order to cover the entire map print("spatial interpolation/extrapolation to cover the entire map") field = subdomains_final cellID = pcr.nominal(pcr.uniqueid(pcr.defined(field))) zoneID = pcr.spreadzone(cellID, 0, 1) field = pcr.areamajority(field, zoneID) subdomains_final_filled = field pcr.aguila(subdomains_final_filled) pcr.report(subdomains_final_filled, "global_subdomains_30min_final_filled.map")
edwin_code_pcrglobwb_catchment_area_km2) # make correction if required abs_diff_value = pcr.cellvalue(pcr.mapmaximum(abs_diff), 1)[0] usgs_drain_area_km2 = pcr.cellvalue(pcr.mapmaximum(usgs_drain_area_km2), 1)[0] if (usgs_drain_area_km2 > 1000.0) and \ (abs_diff_value > 0.10 * usgs_drain_area_km2): # class within 0.1 arc degree windows edwin_code = pcr.windowmajority(edwin_code, 0.1) # find the most accurate cell: areaorder = pcr.areaorder( pcr.windowmaximum(pcr.spatial(pcr.scalar(usgs_drain_area_km2)), 0.1) - pcrglobwb_catchment_area_km2, edwin_code) # select pixel edwin_code = pcr.ifthen(areaorder == 1., edwin_code) # pcrglobwb catchment area edwin_code_pcrglobwb_catchment_area_km2 = pcr.ifthen( areaorder == 1., pcrglobwb_catchment_area_km2) # save using map2col pcr.report(edwin_code, "edwin_code.map") pcr.report(edwin_code_pcrglobwb_catchment_area_km2, "edwin_code_pcrglobwb_catchment_area_km2.map") cmd = "map2col edwin_code.map edwin_code_pcrglobwb_catchment_area_km2.map edwin_code_pcrglobwb_catchment_area_km2.tmp" print(cmd)
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",['version']) 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 if o == "--version": import wflow print("wflow version: ", wflow.__version__) sys.exit(0) 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 X = np.fromstring(gauges_x, sep=',') Y = np.fromstring(gauges_y, sep=',') tr.Verbose = 1 # make the directories to save results in if not os.path.isdir(step1dir + "/"): os.makedirs(step1dir) if not os.path.isdir(step2dir): os.makedirs(step2dir) if initialscale > 1: print("Initial scaling of DEM...") os.system( "resample -r " + str(initialscale) + " " + masterdem + " " + step1dir + "/dem_scaled.map" ) print("Reading dem...") dem = pcr.readmap(step1dir + "/dem_scaled.map") ldddem = dem else: print ("Reading dem...") dem = pcr.readmap(masterdem) ldddem = dem 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) rivshpattr = os.path.splitext(os.path.basename(rivshp))[0] 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 # 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, dem - 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 = tr.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 = tr.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" )
yMin= -35.0 yMax= 37.5 sampleResolution= 0.5 resampleRatio= 1. #-class to clip map during read clippedRead= pcrPartialRead(xMin,xMax,yMin,yMax,sampleResolution,resampleRatio,clone) cellAreaMap= os.path.join(mapsDir,'cellarea30.map') cellArea= clippedRead.get(cellAreaMap,'scalar') #-channel and floodplain characteristics LDDMap= os.path.join(mapsDir,'lddsound_30min.map') LDD= pcr.lddrepair(clippedRead.get(LDDMap,'ldd')) channelGradient= clippedRead.get(os.path.join(mapsDir,'globalgradchannel.map')) channelWidth= clippedRead.get(os.path.join(mapsDir,'channel_width.map')) channelLength= clippedRead.get(os.path.join(mapsDir,'channel_length.map')) channelDepth= clippedRead.get(os.path.join(mapsDir,'channel_depth.map')) floodplainMask= pcr.spatial(pcr.boolean(1)) # NOTE: set to zero for static, to one for dynamic floodplains channelManN= 0.04 floodplainManN= 0.10 #-flood plain parameterization #-root of file name with maps of relative elvation above floodplain # and associated fractions relZFileName= 'elev%04d.map' areaFractions=[0.0,0.01,0.05,0.10,0.20,0.30,0.40,\ 0.50,0.60,0.70,0.80,0.90,1.00] # reduction parameter of smoothing interval and error threshold reductionKK= 0.5 criterionKK= 40. #-modelSignature if pcr.cellvalue(pcr.mapmaximum(pcr.scalar(floodplainMask)),1)[0] == 1: modelSignature= forcingDataSet+'_dynamic-routing' else:
# finding the month that give the maximum discharge (from the climatology time series) msg = "Identifying the month with peak discharge (from climatology time series):" logger.info(msg) # - read the maximum monthly discharge for every basin maximum_discharge = vos.netcdf2PCRobjClone(input_files['maximumClimatologyDischargeMonthAvg'], \ "discharge", 1,\ useDoy = "Yes", cloneMapFileName = clone_map_file,\ LatitudeLongitude = True,\ specificFillValue = None) maximum_discharge = pcr.areamaximum(\ pcr.cover(maximum_discharge, 0.0), basin_map) # - find the month with maximum discharge maximum_month = pcr.spatial(pcr.scalar(1.0)) for i_month in range(1, 12 + 1): # read the climatology discharge time series discharge_for_this_month = vos.netcdf2PCRobjClone(input_files['climatologyDischargeMonthAvg'], \ "discharge", i_month,\ useDoy = "Yes", cloneMapFileName = clone_map_file,\ LatitudeLongitude = True,\ specificFillValue = None) # upscale it to the basin scale discharge_for_this_month = pcr.areamaximum(discharge_for_this_month, basin_map) maximum_month = pcr.ifthenelse(discharge_for_this_month == maximum_discharge, pcr.scalar(i_month), maximum_month) pcr.report(maximum_month, "maximum_month.map") # defining the hydrological year type msg = "Defining the type of hydrological year:"
def report_summary(self, landWaterStoresAtBeginning, landWaterStoresAtEnd,\ surfaceWaterStoresAtBeginning, surfaceWaterStoresAtEnd): # set total to 0 on first day of the year if self._modelTime.doy == 1 or self._modelTime.isFirstTimestep(): # set all accumulated variables to zero self.precipitationAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) for var in self.landSurface.fluxVars: vars(self)[var+'Acc'] = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) self.baseflowAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) self.surfaceWaterInfAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) self.runoffAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) self.unmetDemandAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) self.waterBalanceAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) self.absWaterBalanceAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) # non irrigation water use (unit: m) self.nonIrrigationWaterUseAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) # non irrigation return flow to water body and water body evaporation (unit: m) self.nonIrrReturnFlowAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) self.waterBodyEvaporationAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) # surface water input/loss volume (m3) and outgoing volume (m3) at pits self.surfaceWaterInputAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) self.dischargeAtPitAcc = pcr.ifthen(self.landmask, pcr.spatial(pcr.scalar(0.0))) # also save the storages at the first day of the year (or the first time step) # - land surface storage (unit: m) self.storageAtFirstDay = pcr.ifthen(self.landmask, landWaterStoresAtBeginning) # - channel storages (unit: m3) self.channelVolumeAtFirstDay = pcr.ifthen(self.landmask, surfaceWaterStoresAtBeginning) # accumulating until the last day of the year: self.precipitationAcc += self.meteo.precipitation for var in self.landSurface.fluxVars: vars(self)[var+'Acc'] += vars(self.landSurface)[var] self.baseflowAcc += self.groundwater.baseflow self.surfaceWaterInfAcc += self.groundwater.surfaceWaterInf self.runoffAcc += self.routing.runoff self.unmetDemandAcc += self.groundwater.unmetDemand self.waterBalance = \ (landWaterStoresAtBeginning - landWaterStoresAtEnd +\ self.meteo.precipitation + self.landSurface.irrGrossDemand + self.groundwater.surfaceWaterInf -\ self.landSurface.actualET - self.routing.runoff - self.groundwater.nonFossilGroundwaterAbs) self.waterBalanceAcc += self.waterBalance self.absWaterBalanceAcc += pcr.abs(self.waterBalance) # consumptive water use for non irrigation demand (m) self.nonIrrigationWaterUseAcc += self.routing.nonIrrWaterConsumption self.waterBodyEvaporationAcc += self.routing.waterBodyEvaporation self.surfaceWaterInputAcc += self.routing.local_input_to_surface_water # unit: m3 self.dischargeAtPitAcc += self.routing.outgoing_volume_at_pits # unit: m3 if self._modelTime.isLastDayOfYear() or self._modelTime.isLastTimeStep(): logger.info("") msg = 'The following summary values do not include storages in surface water bodies (lake, reservoir and channel storages).' logger.info(msg) # TODO: Improve these water balance checks. totalCellArea = vos.getMapTotal(pcr.ifthen(self.landmask, self.routing.cellArea)) msg = 'Total area = %e km2'\ % (totalCellArea/1e6) logger.info(msg) deltaStorageOneYear = vos.getMapVolume( \ pcr.ifthen(self.landmask,landWaterStoresAtBeginning) - \ pcr.ifthen(self.landmask,self.storageAtFirstDay), self.routing.cellArea) msg = 'Delta total storage days 1 to %i in %i = %e km3 = %e mm'\ % ( int(self._modelTime.doy),\ int(self._modelTime.year),\ deltaStorageOneYear/1e9,\ deltaStorageOneYear*1000/totalCellArea) logger.info(msg) variableList = ['precipitation', 'baseflow', 'surfaceWaterInf', 'runoff', 'unmetDemand'] variableList += self.landSurface.fluxVars variableList += ['waterBalance','absWaterBalance','irrigationEvaporationWaterUse','nonIrrigationWaterUse'] # consumptive water use for irrigation (unit: m) self.irrigationEvaporationWaterUseAcc = vos.getValDivZero(self.irrGrossDemandAcc,\ self.precipitationAcc + self.irrGrossDemandAcc) * self.actualETAcc for var in variableList: volume = vos.getMapVolume(\ self.__getattribute__(var + 'Acc'),\ self.routing.cellArea) #~ # an eperiment: To test an improved version of map total - still need to be tested #~ if var == "actSurfaceWaterAbstract" or var == "allocSurfaceWaterAbstract": #~ volume = vos.getMapTotalHighPrecisionButOnlyForPositiveValues(self.__getattribute__(var + 'Acc') * self.routing.cellArea) msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\ % (var,int(self._modelTime.doy),\ int(self._modelTime.year),volume/1e9,volume*1000/totalCellArea) # TODO: Calculation does not always start from day 1. logger.info(msg) logger.info("") msg = 'The following summary is for surface water bodies.' logger.info(msg) deltaChannelStorageOneYear = vos.getMapTotal( \ pcr.ifthen(self.landmask,surfaceWaterStoresAtEnd) - \ pcr.ifthen(self.landmask,self.channelVolumeAtFirstDay)) msg = 'Delta surface water storage days 1 to %i in %i = %e km3 = %e mm'\ % ( int(self._modelTime.doy),\ int(self._modelTime.year),\ deltaChannelStorageOneYear/1e9,\ deltaChannelStorageOneYear*1000/totalCellArea) logger.info(msg) variableList = ['waterBodyEvaporation'] for var in variableList: volume = vos.getMapVolume(\ self.__getattribute__(var + 'Acc'),\ self.routing.cellArea) msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\ % (var,int(self._modelTime.doy),\ int(self._modelTime.year),volume/1e9,volume*1000/totalCellArea) logger.info(msg) # surface water balance check surfaceWaterInputTotal = vos.getMapTotal(self.surfaceWaterInputAcc) msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\ % ("surfaceWaterInput",int(self._modelTime.doy),\ int(self._modelTime.year),surfaceWaterInputTotal/1e9,surfaceWaterInputTotal*1000/totalCellArea) logger.info(msg) dischargeAtPitTotal = vos.getMapTotal(self.dischargeAtPitAcc) msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\ % ("dischargeAtPitTotal",int(self._modelTime.doy),\ int(self._modelTime.year),dischargeAtPitTotal/1e9, dischargeAtPitTotal*1000/totalCellArea) logger.info(msg) surfaceWaterBalance = deltaChannelStorageOneYear - surfaceWaterInputTotal + dischargeAtPitTotal msg = 'Accumulated %s days 1 to %i in %i = %e km3 = %e mm'\ % ("surfaceWaterBalance",int(self._modelTime.doy),\ int(self._modelTime.year),surfaceWaterBalance/1e9, surfaceWaterBalance*1000/totalCellArea) logger.info(msg)
def waterBalance( fluxesIn, fluxesOut, deltaStorages, processName, PrintOnlyErrors, dateStr,threshold=1e-5): """ Returns the water balance for a list of input, output, and storage map files and """ inMap = pcr.spatial(pcr.scalar(0.0)) dsMap = pcr.spatial(pcr.scalar(0.0)) outMap = pcr.spatial(pcr.scalar(0.0)) inflow = 0 outflow = 0 deltaS = 0 for fluxIn in fluxesIn: inflow += getMapTotal(fluxIn) inMap += fluxIn for fluxOut in fluxesOut: outflow += getMapTotal(fluxOut) outMap += fluxOut for deltaStorage in deltaStorages: deltaS += getMapTotal(deltaStorage) dsMap += deltaStorage #if PrintOnlyErrors: a,b,c = getMinMaxMean(inMap + dsMap- outMap) # if abs(a) > 1e-5 or abs(b) > 1e-5: # if abs(a) > 1e-4 or abs(b) > 1e-4: if abs(a) > threshold or abs(b) > threshold: print "WBError %s Min %f Max %f Mean %f" %(processName,a,b,c) # if abs(inflow + deltaS - outflow) > 1e-5: # print "Water balance Error for %s on %s: in = %f\tout=%f\tdeltaS=%f\tBalance=%f" \ # %(processName,dateStr,inflow,outflow,deltaS,inflow + deltaS - outflow) #else: # print "Water balance for %s: on %s in = %f\tout=%f\tdeltaS=%f\tBalance=%f" \ # %(processName,dateStr,inflow,outflow,deltaS,inflow + deltaS - outflow) wb = inMap + dsMap - outMap maxWBError = pcr.cellvalue(pcr.mapmaximum(pcr.abs(wb)), 1, 1)[0] #if maxWBError > 0.001 / 1000: #row = 0 #col = 0 #cellID = 1 #troubleCell = 0 #print "Water balance for %s on %s: %f mm !!! " %(processName,dateStr,maxWBError * 1000) #pcr.report(wb,"%s-WaterBalanceError-%s" %(processName,dateStr)) #npWBMError = pcr2numpy(wb, -9999) #(nr, nc) = np.shape(npWBMError) #for r in range(0, nr): #for c in range(0, nc): ## print r,c #if npWBMError[r, c] != -9999.0: #val = npWBMError[r, c] #if math.fabs(val) > 0.0001 / 1000: ## print npWBMError[r,c] #row = r #col = c #troubleCell = cellID #cellID += 1 #print 'Water balance for %s on %s: %f mm row %i col %i cellID %i!!! ' % ( #processName, #dateStr, #maxWBError * 1000, #row, #col, #troubleCell, #) return inMap + dsMap - outMap
def modflow_simulation(self,\ simulation_type,\ initial_head,\ currTimeStep = None,\ PERLEN = 1.0, NSTP = 1, \ HCLOSE = 1.0,\ RCLOSE = 10.* 400.*400.,\ MXITER = 50,\ ITERI = 30,\ NPCOND = 1,\ RELAX = 1.00,\ NBPOL = 2,\ DAMP = 1,\ ITMUNI = 4, LENUNI = 2, TSMULT = 1.0): # initiate pcraster modflow object if modflow is not called yet: if self.modflow_has_been_called == False or self.modflow_converged == False: self.initiate_modflow() self.modflow_has_been_called = True if simulation_type == "transient": logger.info("Preparing MODFLOW input for a transient simulation.") SSTR = 0 if simulation_type == "steady-state": logger.info("Preparing MODFLOW input for a steady-state simulation.") SSTR = 1 # waterBody class to define the extent of lakes and reservoirs # if simulation_type == "steady-state": self.WaterBodies = waterBodies.WaterBodies(self.iniItems,\ self.landmask,\ self.onlyNaturalWaterBodies) self.WaterBodies.getParameterFiles(date_given = self.iniItems.globalOptions['startTime'],\ cellArea = self.cellAreaMap, \ ldd = self.lddMap) # if simulation_type == "transient": if currTimeStep.timeStepPCR == 1: self.WaterBodies = waterBodies.WaterBodies(self.iniItems,\ self.landmask,\ self.onlyNaturalWaterBodies) if currTimeStep.timeStepPCR == 1 or currTimeStep.doy == 1: self.WaterBodies.getParameterFiles(date_given = str(currTimeStep.fulldate),\ cellArea = self.cellAreaMap, \ ldd = self.lddMap) print "here" # using dem_average as the initial groundwater head value self.pcr_modflow.setInitialHead(initial_head, 1) # set parameter values for the DIS package and PCG solver self.pcr_modflow.setDISParameter(ITMUNI, LENUNI, PERLEN, NSTP, TSMULT, SSTR) self.pcr_modflow.setPCG(MXITER, ITERI, NPCOND, HCLOSE, RCLOSE, RELAX, NBPOL, DAMP) # # Some notes about the values # # ITMUNI = 4 # indicates the time unit (0: undefined, 1: seconds, 2: minutes, 3: hours, 4: days, 5: years) # LENUNI = 2 # indicates the length unit (0: undefined, 1: feet, 2: meters, 3: centimeters) # PERLEN = 1.0 # duration of a stress period # NSTP = 1 # number of time steps in a stress period # TSMULT = 1.0 # multiplier for the length of the successive iterations # SSTR = 1 # 0 - transient, 1 - steady state # # MXITER = 50 # maximum number of outer iterations # Deltares use 50 # ITERI = 30 # number of inner iterations # Deltares use 30 # NPCOND = 1 # 1 - Modified Incomplete Cholesky, 2 - Polynomial matrix conditioning method; # HCLOSE = 0.01 # HCLOSE (unit: m) # RCLOSE = 10.* 400.*400. # RCLOSE (unit: m3) # RELAX = 1.00 # relaxation parameter used with NPCOND = 1 # NBPOL = 2 # indicates whether the estimate of the upper bound on the maximum eigenvalue is 2.0 (but we don ot use it, since NPCOND = 1) # DAMP = 1 # no damping (DAMP introduced in MODFLOW 2000) # read input files (for the steady-state condition, we use pcraster maps): if simulation_type == "steady-state": # - discharge (m3/s) from PCR-GLOBWB discharge = vos.readPCRmapClone(self.iniItems.modflowSteadyStateInputOptions['avgDischargeInputMap'],\ self.cloneMap, self.tmpDir, self.inputDir) # - recharge/capillary rise (unit: m/day) from PCR-GLOBWB gwRecharge = vos.readPCRmapClone(self.iniItems.modflowSteadyStateInputOptions['avgGroundwaterRechargeInputMap'],\ self.cloneMap, self.tmpDir, self.inputDir) if self.ignoreCapRise: gwRecharge = pcr.max(0.0, gwRecharge) gwAbstraction = pcr.spatial(pcr.scalar(0.0)) # read input files (for the transient, input files are given in netcdf files): if simulation_type == "transient": # - discharge (m3/s) from PCR-GLOBWB discharge = vos.netcdf2PCRobjClone(self.iniItems.modflowTransientInputOptions['dischargeInputNC'], "discharge",str(currTimeStep.fulldate),None,self.cloneMap) # - recharge/capillary rise (unit: m/day) from PCR-GLOBWB gwRecharge = vos.netcdf2PCRobjClone(self.iniItems.modflowTransientInputOptions['groundwaterRechargeInputNC'],\ "groundwater_recharge",str(currTimeStep.fulldate),None,self.cloneMap) if self.ignoreCapRise: gwRecharge = pcr.max(0.0, gwRecharge) # - groundwater abstraction (unit: m/day) from PCR-GLOBWB gwAbstraction = vos.netcdf2PCRobjClone(self.iniItems.modflowTransientInputOptions['groundwaterAbstractionInputNC'],\ "total_groundwater_abstraction",str(currTimeStep.fulldate),None,self.cloneMap) # set recharge, river, well and drain packages self.set_river_package(discharge, currTimeStep) self.set_recharge_package(gwRecharge) self.set_well_package(gwAbstraction) self.set_drain_package() # execute MODFLOW logger.info("Executing MODFLOW.") self.pcr_modflow.run() logger.info("Check if the model whether a run has converged or not") self.modflow_converged = self.check_modflow_convergence() if self.modflow_converged == False: msg = "MODFLOW FAILED TO CONVERGE with HCLOSE = "+str(HCLOSE)+" and RCLOSE = "+str(RCLOSE) logger.info(msg) # iteration index for the RCLOSE self.iteration_RCLOSE += 1 # reset if the index has reached the length of available criteria if self.iteration_RCLOSE > (len(self.criteria_RCLOSE)-1): self.iteration_RCLOSE = 0 # iteration index for the HCLOSE if self.iteration_RCLOSE == 0: self.iteration_HCLOSE += 1 # we have to reset modflow as we want to change the PCG setup self.modflow_has_been_called = False # for the steady state simulation, we still save the calculated head as the initial estimate for the next iteration if simulation_type == "steady-state": self.groundwaterHead = self.pcr_modflow.getHeads(1) # NOTE: We cannot implement this principle for transient simulation else: msg = "HURRAY!!! MODFLOW CONVERGED with HCLOSE = "+str(HCLOSE)+" and RCLOSE = "+str(RCLOSE) logger.info(msg) # reset the iteration because modflow has converged self.iteration_HCLOSE = 0 self.iteration_RCLOSE = 0 self.modflow_has_been_called = True # obtaining the results from modflow simulation self.groundwaterHead = None self.groundwaterHead = self.pcr_modflow.getHeads(1) # calculate groundwater depth only in the landmask region self.groundwaterDepth = pcr.ifthen(self.landmask, self.dem_average - self.groundwaterHead)
def main(): # output folder (and tmp folder) clean_out_folder = True if os.path.exists(out_folder): if clean_out_folder: shutil.rmtree(out_folder) os.makedirs(out_folder) else: os.makedirs(out_folder) os.chdir(out_folder) os.system("pwd") # set the clone map print("set the clone") pcr.setclone(global_ldd_30min_inp_file) # define the landmask print("define the landmask") # - based on the 30min input landmask_30min = define_landmask(input_file = global_landmask_30min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_30min_only") # - based on the 05min input landmask_05min = define_landmask(input_file = global_landmask_05min_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_05min_only") # - based on the 30sec input landmask_30sec = define_landmask(input_file = global_landmask_30sec_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_30sec_only") # - based on the 30sec input landmask_03sec = define_landmask(input_file = global_landmask_03sec_file,\ clone_map_file = global_ldd_30min_inp_file,\ output_map_file = "landmask_03sec_only") # # - merge all landmasks landmask = pcr.cover(landmask_30min, landmask_05min, landmask_30sec, landmask_03sec) pcr.report(landmask, "global_landmask_30min_final.map") # ~ pcr.aguila(landmask) # extend ldd print("extend/define the ldd") ldd_map = pcr.readmap(global_ldd_30min_inp_file) ldd_map = pcr.ifthen(landmask, pcr.cover(ldd_map, pcr.ldd(5))) pcr.report(ldd_map, "global_ldd_final.map") # ~ pcr.aguila(ldd_map) # identify small islands print("identify small islands") # - maps of islands smaller than 10000 cells (at half arc degree resolution) island_map = pcr.ifthen(landmask, pcr.clump(pcr.defined(ldd_map))) island_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), island_map) island_map = pcr.ifthen(island_size < 10000., island_map) UNTIL_THIS # identify the biggest island for every group of small islands within the windows 10x10 arcdeg cells # - sort from the largest catchment catchment_pits_boolean = pcr.ifthen( pcr.scalar(pcr.pit(ldd_map)) > 0.0, pcr.boolean(1.0)) catchment_pits_boolean = pcr.ifthen(catchment_pits_boolean, catchment_pits_boolean) pcr.aguila(catchment_pits_boolean) catchment_map = pcr.nominal( pcr.areaorder(catchment_size * -1.0, pcr.nominal(catchment_pits_boolean))) island_map = pcr.ifthen(island_size == pcr.windowmaximum(island_size, 10.), island_map) pcr.aguila(island_map) # identify big catchments # merge biggest islands and big catchments # make catchment and island map print("make catchment and island map") # - catchment map catchment_map = pcr.catchment(ldd_map, pcr.pit(ldd_map)) pcr.report(catchment_map, "global_catchment_not_sorted.map") os.system("mapattr -p global_catchment_not_sorted.map") num_of_catchments = int(vos.getMinMaxMean(pcr.scalar(catchment_map))[1]) # - maps of islands smaller than 10000 cells island_map = pcr.ifthen(landmask, pcr.clump(pcr.defined(ldd_map))) island_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), island_map) island_map = pcr.ifthen(island_size < 10000., island_map) island_map = pcr.nominal( pcr.scalar(pcr.ifthen(landmask, pcr.clump(island_map))) + pcr.scalar(num_of_catchments) * 100.) pcr.aguila(island_map) island_size = pcr.ifthen(pcr.defined(island_map), island_size) island_map = pcr.ifthen(island_size == pcr.windowmaximum(island_size, 10.), island_map) pcr.aguila(island_map) catchment_map = pcr.cover(island_map, catchment_map) catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) # - calculate the size catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) # - sort from the largest catchment catchment_pits_boolean = pcr.ifthen( pcr.scalar(pcr.pit(ldd_map)) > 0.0, pcr.boolean(1.0)) catchment_pits_boolean = pcr.ifthen(catchment_pits_boolean, catchment_pits_boolean) pcr.aguila(catchment_pits_boolean) catchment_map = pcr.nominal( pcr.areaorder(catchment_size * -1.0, pcr.nominal(catchment_pits_boolean))) catchment_map = pcr.catchment(ldd_map, catchment_map) pcr.report(catchment_map, "global_catchment_final.map") os.system("mapattr -p global_catchment_final.map") # - calculate the size catchment_size = pcr.areatotal(pcr.spatial(pcr.scalar(1.0)), catchment_map) pcr.report(catchment_size, "global_catchment_size_in_number_of_cells.map") # number of catchments num_of_catchments = int(vos.getMinMaxMean(pcr.scalar(catchment_map))[1]) # size of the largest catchment catchment_size_max = vos.getMinMaxMean(catchment_size)[1] print("") print(str(float(catchment_size_max))) print("") # identify all large catchments with size >= 50 cells (at the resolution of 30 arcmin) = 50 x (50^2) km2 = 125000 km2 print("identify catchments with the minimum size of 50 cells") catchment_map_ge_50 = pcr.ifthen(catchment_size >= 50, catchment_map) pcr.report(catchment_map_ge_50, "global_catchment_ge_50_cells.map") # include the island catchment_map_ge_50 = pcr.cover(island_map, catchment_map_ge_50) # perform cdo fillmiss2 in order to merge the small catchments to the nearest large catchments cmd = "gdal_translate -of NETCDF global_catchment_ge_50_cells.map global_catchment_ge_50_cells.nc" print(cmd) os.system(cmd) cmd = "cdo fillmiss2 global_catchment_ge_50_cells.nc global_catchment_ge_50_cells_filled.nc" print(cmd) os.system(cmd) cmd = "cdo fillmiss2 global_catchment_ge_50_cells_filled.nc global_catchment_ge_50_cells_filled.nc" print(cmd) os.system(cmd) cmd = "gdal_translate -of PCRaster global_catchment_ge_50_cells_filled.nc global_catchment_ge_50_cells_filled.map" print(cmd) os.system(cmd) cmd = "mapattr -c " + global_ldd_30min_inp_file + " " + "global_catchment_ge_50_cells_filled.map" print(cmd) os.system(cmd) # - initial subdomains subdomains_initial = pcr.nominal( pcr.readmap("global_catchment_ge_50_cells_filled.map")) subdomains_initial = pcr.areamajority(subdomains_initial, catchment_map) pcr.aguila(subdomains_initial) # - initial subdomains clump subdomains_initial_clump = pcr.clump(subdomains_initial) pcr.aguila(subdomains_initial_clump) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[0]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial))[1]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial_clump))[0]))) print(str(int(vos.getMinMaxMean(pcr.scalar(subdomains_initial_clump))[1]))) # - remove temporay files (not used) cmd = "rm global_catchment_ge_50_cells_filled*" print(cmd) os.system(cmd) # clone code that will be assigned assigned_number = 0
def dynamic(self): ##################### # * dynamic section # ##################### #-evaluation of the current date: return current month and the time step used #-reading in fluxes over land and water area for current time step [m/d] # and read in reservoir demand and surface water extraction [m3] try: self.landSurfaceQ= clippedRead.get(pcrm.generateNameT(landSurfaceQFileName,self.currentTimeStep())) except: pass try: self.potWaterSurfaceQ= clippedRead.get(pcrm.generateNameT(waterSurfaceQFileName,self.currentTimeStep())) except: pass #-surface water extraction and reservoir demand currently set to zero, should # be computed automatically and updated to reservoirs self.potSurfaceWaterExtraction= pcr.spatial(pcr.scalar(0.)) #self.waterBodies.demand= #self.reservoirDemandTSS.assignID(self.waterBodies.ID,self.currentTimeStep(),0.)*self.timeSec #-initialization of cumulative values of actual water extractions self.actWaterSurfaceQ= pcr.spatial(pcr.scalar(0.)) self.actSurfaceWaterExtraction= pcr.spatial(pcr.scalar(0.)) #-definition of sub-loop for routing scheme - explicit scheme has to satisfy Courant condition timeLimit= pcr.cellvalue(pcr.mapminimum((pcr.cover(pcr.ifthen(self.waterBodies.distribution == 0,\ self.channelLength/self.flowVelocity),\ self.timeSec/self.nrIterDefault)*self.timeSec/self.nrIterDefault)**0.5),1)[0] nrIter= int(self.timeSec/timeLimit) nrIter= min(nrIter,int(self.timeSec/300.)) while float(self.timeSec/nrIter) % 1 <> 0: nrIter+= 1 deltaTime= self.timeSec/nrIter #-sub-loop for current time step if self.currentDate.day == 1 or nrIter >= 24: print '\n*\tprocessing %s, currently using %d substeps of %d seconds\n' % \ (self.currentDate.date(),nrIter,deltaTime) #-update discharge and storage for nrICur in range(nrIter): #-initializing discharge for the current sub-timestep and fill in values # for channels and at outlets of waterbodies # * channels * estQ= pcr.ifthenelse((self.actualStorage > 0.) & (self.waterBodies.distribution == 0) ,\ (self.wettedArea/self.alphaQ)**(1./self.betaQ),0.) #estQ= pcr.ifthenelse((self.actualStorage > 0.) & (self.waterBodies.distribution == 0) ,\ #0.5*(self.Q+(self.wettedArea/self.alphaQ)**(1./self.betaQ)),0.) #estQ= pcr.min(estQ,self.actualStorage/deltaTime) self.report(estQ,'results/qest') self.Q= pcr.spatial(pcr.scalar(0.)) self.Q= pcr.ifthenelse(self.waterBodies.distribution == 0,\ pcr.kinematic(self.channelLDD,estQ,0.,self.alphaQ,\ self.betaQ,1,deltaTime,self.channelLength),self.Q) # * water bodies * self.waterBodies.dischargeUpdate() self.Q= self.waterBodies.returnMapValue(self.Q,self.waterBodies.actualQ) #-fluxes and resulting change in storage: first the local fluxes are evaluated # and aggregated over the water bodies where applicable; this includes the specific runoff [m/day/m2] # from input and the estimated extraction from surface water as volume per day [m3/day]; # specific runoff from the land surface is always positive whereas the fluxes over the water surface # are potential, including discharge, and are adjusted to match the availabe storage; to this end, # surface water storage and fluxes over water bodies are totalized and assigned to the outlet; # discharge is updated in a separate step, after vertical fluxes are compared to the actual storage deltaActualStorage= ((self.landFraction*self.landSurfaceQ+\ self.waterFraction*self.potWaterSurfaceQ)*self.cellArea-\ self.potSurfaceWaterExtraction)*float(self.duration)/nrIter deltaActualStorage= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(deltaActualStorage,self.waterBodies.distribution),0),\ deltaActualStorage) adjustmentRatio= pcr.ifthenelse(deltaActualStorage < 0.,\ pcr.min(1.,-self.actualStorage/deltaActualStorage),1.) self.actWaterSurfaceQ+= adjustmentRatio*self.potWaterSurfaceQ self.actSurfaceWaterExtraction+= adjustmentRatio*self.actSurfaceWaterExtraction deltaActualStorage*= adjustmentRatio #-local water balance check if testLocalWaterBalance: differenceActualStorage= self.actualStorage differenceActualStorage+= deltaActualStorage #-overall water balance check: net input self.cumulativeDeltaStorage+= pcr.catchmenttotal(deltaActualStorage,self.LDD) #-update storage first with local changes, then balance discharge with storage and update storage # with lateral flow and return value to water bodies self.actualStorage+= deltaActualStorage self.actualStorage= pcr.max(0.,self.actualStorage) self.Q= pcr.min(self.Q,self.actualStorage/deltaTime) deltaActualStorage= (-self.Q+pcr.upstream(self.LDD,self.Q))*deltaTime deltaActualStorage= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(deltaActualStorage,self.waterBodies.distribution),0),\ deltaActualStorage) self.actualStorage+= deltaActualStorage self.actualStorage= pcr.max(0.,self.actualStorage) self.waterBodies.actualStorage= self.waterBodies.retrieveMapValue(self.actualStorage) #-flooded fraction returned floodedFraction,floodedDepth,\ self.wettedArea,self.alphaQ= self.kinAlphaComposite(self.actualStorage,self.floodplainMask) self.wettedArea= self.waterBodies.returnMapValue(self.wettedArea,\ self.waterBodies.channelWidth+2.*self.waterBodies.updateWaterHeight()) self.waterFraction= pcr.ifthenelse(self.waterBodies.distribution == 0,\ pcr.max(self.waterFractionMask,floodedFraction),self.waterFractionMask) self.landFraction= pcr.max(0.,1.-self.waterFraction) self.flowVelocity= pcr.ifthenelse(self.wettedArea > 0,self.Q/self.wettedArea,0.) #-local water balance check if testLocalWaterBalance: differenceActualStorage+= deltaActualStorage differenceActualStorage-= self.actualStorage totalDifference= pcr.cellvalue(pcr.maptotal(differenceActualStorage),1)[0] minimumDifference= pcr.cellvalue(pcr.mapminimum(differenceActualStorage),1)[0] maximumDifference= pcr.cellvalue(pcr.mapmaximum(differenceActualStorage),1)[0] if abs(totalDifference) > 1.e-3: print 'water balance error: total %e; min %e; max %e' %\ (totalDifference,minimumDifference,maximumDifference) if reportLocalWaterBalance: pcr.report(differenceActualStorage,'mbe_%s.map' % self.currentDate.date()) #-overall water balance check: updating cumulative discharge and total storage [m3] self.totalDischarge+= self.Q*deltaTime self.totalStorage= pcr.catchmenttotal(self.actualStorage,self.LDD) #-check on occurrence of last day and report mass balance if self.currentDate == self.endDate: #-report initial maps pcr.report(self.Q,self.QIniMap) pcr.report(self.actualStorage,self.actualStorageIniMap) #-return relative and absolute water balance error per cell and # as total at basin outlets self.totalDischarge= pcr.ifthen((self.waterBodies.distribution == 0) | \ (self.waterBodies.location != 0),self.totalDischarge) self.cumulativeDeltaStorage= pcr.ifthen((self.waterBodies.distribution == 0) | \ (self.waterBodies.location != 0),self.cumulativeDeltaStorage) massBalanceError= self.totalStorage+self.totalDischarge-\ self.cumulativeDeltaStorage relMassBalanceError= 1.+pcr.ifthenelse(self.cumulativeDeltaStorage <> 0., massBalanceError/self.cumulativeDeltaStorage,0.) totalMassBalanceError= pcr.cellvalue(pcr.maptotal(pcr.ifthen(self.basinOutlet,\ massBalanceError)),1)[0] totalCumulativeDeltaStorage= pcr.cellvalue(pcr.maptotal(pcr.ifthen(self.basinOutlet,\ self.cumulativeDeltaStorage)),1)[0] if totalCumulativeDeltaStorage > 0: totalRelativeMassBalanceError= 1.+totalMassBalanceError/totalCumulativeDeltaStorage else: totalRelativeMassBalanceError= 1. #-report maps and echo value pcr.report(massBalanceError,mbeFileName) pcr.report(relMassBalanceError,mbrFileName) print '\n*\ttotal global mass balance error [m3]: %8.3g' % totalMassBalanceError print '\n*\trelative global mass balance error [-]: %5.3f' % totalRelativeMassBalanceError #-echo to screen: total mass balance error and completion of run print '\trun completed' #-end of day: return states and fluxes #-get surface water attributes? if getSurfaceWaterAttributes: #-compute the following secondary variables: # surface water area [m2]: area given dynamic surface water fraction # residence time [days]: volume over discharge, assigned -1 in case discharge is zero # surface water depth [m], weighed by channel and floodplain volume surfaceWaterArea= self.waterFraction*self.cellArea surfaceWaterArea= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(surfaceWaterArea,self.waterBodies.distribution),0),\ surfaceWaterArea) surfaceWaterResidenceTime= pcr.ifthenelse(self.Q > 0.,self.actualStorage/(self.Q*self.timeSec),-1) surfaceWaterDepth= pcr.ifthenelse(self.actualStorage > 0.,\ pcr.max(0.,self.actualStorage-self.channelStorageCapacity)**2/\ (self.actualStorage*surfaceWaterArea),0.) surfaceWaterDepth+= pcr.ifthenelse(self.actualStorage > 0.,\ pcr.min(self.channelStorageCapacity,self.actualStorage)**2/(self.waterFractionMask*\ self.cellArea*self.actualStorage),0.) #-reports: values at outlet of lakes or reservoirs are assigned to their full extent self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterArea,self.waterBodies.distribution),surfaceWaterArea),\ surfaceWaterAreaFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterResidenceTime,self.waterBodies.distribution),surfaceWaterResidenceTime),\ surfaceWaterResidenceTimeFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterDepth,self.waterBodies.distribution),surfaceWaterDepth),\ surfaceWaterDepthFileName) #-reports on standard output: values at outlet of lakes or reservoirs are assigned to their full extent self.report(pcr.ifthenelse(self.waterBodies.distribution != 0, pcr.areamaximum(self.flowVelocity,self.waterBodies.distribution),self.flowVelocity),flowVelocityFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution != 0, pcr.areamaximum(self.Q,self.waterBodies.distribution),self.Q),QFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution == 0,\ floodedFraction,0.),floodedFractionFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution == 0,\ floodedDepth,0.),floodedDepthFileName) self.report(self.actualStorage,actualStorageFileName) #-update date for time step and report relevant daily output self.currentDate= self.currentDate+datetime.timedelta(self.duration)
mldd = pcraster.mldd.initialise(pcraster.clone()) mldd.setStream( # TODO Create overload which takes strings, or handle internally. pcraster.readmap(os.path.join(dataPath, "ELddF000.out")), pcraster.readmap(os.path.join(dataPath, "NELddF00.out")), pcraster.readmap(os.path.join(dataPath, "NLddF000.out")), pcraster.readmap(os.path.join(dataPath, "NWLddF00.out")), pcraster.readmap(os.path.join(dataPath, "SELddF00.out")), pcraster.readmap(os.path.join(dataPath, "SLddF000.out")), pcraster.readmap(os.path.join(dataPath, "SWLddF00.out")), pcraster.readmap(os.path.join(dataPath, "WLddF000.out"))) mldd.addStream( pcraster.readmap(os.path.join(dataPath, "ELddF000.out"))) mldd.setDem(pcraster.spatial(pcraster.scalar(1))) upstream = mldd.upstream(pcraster.spatial(pcraster.scalar(1))) pcraster.report(upstream, "upstream.map") accuflux = mldd.accuflux(pcraster.ifthen(pcraster.defined(upstream), pcraster.spatial(pcraster.scalar(1)))) pcraster.report(accuflux, "accuflux.map") dem = mldd.getDem() pcraster.report(dem, "dem.map") streamN, streamNE, streamE, streamSE, streamS, streamSW, streamW, streamNW = \ mldd.getStream()
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 getParameterFiles(self,currTimeStep,cellArea,ldd,\ initial_condition_dictionary = None,\ currTimeStepInDateTimeFormat = False): # parameters for Water Bodies: fracWat # waterBodyIds # waterBodyOut # waterBodyArea # waterBodyTyp # waterBodyCap # cell surface area (m2) and ldd self.cellArea = cellArea ldd = pcr.ifthen(self.landmask, ldd) # date used for accessing/extracting water body information if currTimeStepInDateTimeFormat: date_used = currTimeStep year_used = currTimeStep.year else: date_used = currTimeStep.fulldate year_used = currTimeStep.year if self.onlyNaturalWaterBodies == True: date_used = self.dateForNaturalCondition year_used = self.dateForNaturalCondition[0:4] # fracWat = fraction of surface water bodies (dimensionless) self.fracWat = pcr.spatial(pcr.scalar(0.0)) if self.useNetCDF: self.fracWat = vos.netcdf2PCRobjClone(self.ncFileInp,'fracWaterInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.fracWat = vos.readPCRmapClone(\ self.fracWaterInp+str(year_used)+".map", self.cloneMap,self.tmpDir,self.inputDir) self.fracWat = pcr.cover(self.fracWat, pcr.spatial(pcr.scalar(0.0))) self.fracWat = pcr.max(0.0, self.fracWat) self.fracWat = pcr.min(1.0, self.fracWat) self.waterBodyIds = pcr.spatial(pcr.nominal(0)) # waterBody ids self.waterBodyOut = pcr.spatial(pcr.boolean(0)) # waterBody outlets self.waterBodyArea = pcr.spatial( pcr.scalar(0.)) # waterBody surface areas # water body ids if self.useNetCDF: self.waterBodyIds = vos.netcdf2PCRobjClone(self.ncFileInp,'waterBodyIds', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.waterBodyIds = vos.readPCRmapClone(\ self.waterBodyIdsInp+str(year_used)+".map",\ self.cloneMap,self.tmpDir,self.inputDir,False,None,True) # self.waterBodyIds = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ pcr.nominal(self.waterBodyIds)) # water body outlets (correcting outlet positions) wbCatchment = pcr.catchmenttotal(pcr.scalar(1), ldd) self.waterBodyOut = pcr.ifthen(wbCatchment ==\ pcr.areamaximum(wbCatchment, \ self.waterBodyIds),\ self.waterBodyIds) # = outlet ids # This may give more than two outlets, particularly if there are more than one cells that have largest upstream areas # - make sure that there is only one outlet for each water body self.waterBodyOut = pcr.ifthen(\ pcr.areaorder(pcr.scalar(self.waterBodyOut), \ self.waterBodyOut) == 1., self.waterBodyOut) self.waterBodyOut = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ self.waterBodyOut) # TODO: Please also consider endorheic lakes! # correcting water body ids self.waterBodyIds = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0.,\ pcr.subcatchment(ldd,self.waterBodyOut)) # boolean map for water body outlets: self.waterBodyOut = pcr.ifthen(\ pcr.scalar(self.waterBodyOut) > 0.,\ pcr.spatial(pcr.boolean(1))) # reservoir surface area (m2): if self.useNetCDF: resSfArea = 1000. * 1000. * \ vos.netcdf2PCRobjClone(self.ncFileInp,'resSfAreaInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: resSfArea = 1000. * 1000. * vos.readPCRmapClone( self.resSfAreaInp+str(year_used)+".map",\ self.cloneMap,self.tmpDir,self.inputDir) resSfArea = pcr.areaaverage(resSfArea, self.waterBodyIds) resSfArea = pcr.cover(resSfArea, 0.) # water body surface area (m2): (lakes and reservoirs) self.waterBodyArea = pcr.max(pcr.areatotal(\ pcr.cover(\ self.fracWat*self.cellArea, 0.0), self.waterBodyIds), pcr.areaaverage(\ pcr.cover(resSfArea, 0.0) , self.waterBodyIds)) self.waterBodyArea = pcr.ifthen(self.waterBodyArea > 0.,\ self.waterBodyArea) # correcting water body ids and outlets (exclude all water bodies with surfaceArea = 0) self.waterBodyIds = pcr.ifthen(self.waterBodyArea > 0., self.waterBodyIds) self.waterBodyOut = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyOut) # water body types: # - 2 = reservoirs (regulated discharge) # - 1 = lakes (weirFormula) # - 0 = non lakes or reservoirs (e.g. wetland) self.waterBodyTyp = pcr.nominal(0) if self.useNetCDF: self.waterBodyTyp = vos.netcdf2PCRobjClone(self.ncFileInp,'waterBodyTyp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.waterBodyTyp = vos.readPCRmapClone( self.waterBodyTypInp+str(year_used)+".map",\ self.cloneMap,self.tmpDir,self.inputDir,False,None,True) # excluding wetlands (waterBodyTyp = 0) in all functions related to lakes/reservoirs # self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyTyp) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyIds) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.areamajority(self.waterBodyTyp,\ self.waterBodyIds) # choose only one type: either lake or reservoir self.waterBodyTyp = pcr.ifthen(\ pcr.scalar(self.waterBodyTyp) > 0,\ pcr.nominal(self.waterBodyTyp)) self.waterBodyTyp = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyTyp) # correcting lakes and reservoirs ids and outlets self.waterBodyIds = pcr.ifthen( pcr.scalar(self.waterBodyTyp) > 0, self.waterBodyIds) self.waterBodyOut = pcr.ifthen( pcr.scalar(self.waterBodyIds) > 0, self.waterBodyOut) # reservoir maximum capacity (m3): self.resMaxCap = pcr.scalar(0.0) self.waterBodyCap = pcr.scalar(0.0) if self.useNetCDF: self.resMaxCap = 1000. * 1000. * \ vos.netcdf2PCRobjClone(self.ncFileInp,'resMaxCapInp', \ date_used, useDoy = 'yearly',\ cloneMapFileName = self.cloneMap) else: self.resMaxCap = 1000. * 1000. * vos.readPCRmapClone(\ self.resMaxCapInp+str(year_used)+".map", \ self.cloneMap,self.tmpDir,self.inputDir) self.resMaxCap = pcr.ifthen(self.resMaxCap > 0,\ self.resMaxCap) self.resMaxCap = pcr.areaaverage(self.resMaxCap,\ self.waterBodyIds) # water body capacity (m3): (lakes and reservoirs) self.waterBodyCap = pcr.cover( self.resMaxCap, 0.0) # Note: Most of lakes have capacities > 0. self.waterBodyCap = pcr.ifthen(pcr.boolean(self.waterBodyIds), self.waterBodyCap) # correcting water body types: # Reservoirs that have zero capacities will be assumed as lakes. self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyTyp) self.waterBodyTyp = pcr.ifthenelse(self.waterBodyCap > 0.,\ self.waterBodyTyp,\ pcr.ifthenelse(pcr.scalar(self.waterBodyTyp) == 2,\ pcr.nominal(1),\ self.waterBodyTyp)) # final corrections: self.waterBodyTyp = pcr.ifthen(self.waterBodyArea > 0.,\ self.waterBodyTyp) # make sure that all lakes and/or reservoirs have surface areas self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyTyp) # make sure that only types 1 and 2 will be considered in lake/reservoir functions self.waterBodyIds = pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ self.waterBodyIds) # make sure that all lakes and/or reservoirs have ids self.waterBodyOut = pcr.ifthen(pcr.scalar(self.waterBodyIds) > 0.,\ self.waterBodyOut) # make sure that all lakes and/or reservoirs have outlets # for a natural run (self.onlyNaturalWaterBodies == True) # which uses only the year 1900, assume all reservoirs are lakes if self.onlyNaturalWaterBodies == True and date_used == self.dateForNaturalCondition: logger.info( "Using only natural water bodies identified in the year 1900. All reservoirs in 1900 are assumed as lakes." ) self.waterBodyTyp = \ pcr.ifthen(pcr.scalar(self.waterBodyTyp) > 0.,\ pcr.nominal(1)) # check that all lakes and/or reservoirs have types, ids, surface areas and outlets: test = pcr.defined(self.waterBodyTyp) & pcr.defined(self.waterBodyArea) &\ pcr.defined(self.waterBodyIds) & pcr.boolean(pcr.areamaximum(pcr.scalar(self.waterBodyOut), self.waterBodyIds)) a, b, c = vos.getMinMaxMean( pcr.cover(pcr.scalar(test), 1.0) - pcr.scalar(1.0)) threshold = 1e-3 if abs(a) > threshold or abs(b) > threshold: logger.warning( "Missing information in some lakes and/or reservoirs.") # at the beginning of simulation period (timeStepPCR = 1) # - we have to define/get the initial conditions # if initial_condition_dictionary != None and currTimeStep.timeStepPCR == 1: self.getICs(initial_condition_dictionary) # For each new reservoir (introduced at the beginning of the year) # initiating storage, average inflow and outflow # PS: THIS IS NOT NEEDED FOR OFFLINE MODFLOW RUN! # try: self.waterBodyStorage = pcr.cover(self.waterBodyStorage, 0.0) self.avgInflow = pcr.cover(self.avgInflow, 0.0) self.avgOutflow = pcr.cover(self.avgOutflow, 0.0) self.waterBodyStorage = pcr.ifthen(self.landmask, self.waterBodyStorage) self.avgInflow = pcr.ifthen(self.landmask, self.avgInflow) self.avgOutflow = pcr.ifthen(self.landmask, self.avgOutflow) except: # PS: FOR OFFLINE MODFLOW RUN! pass # TODO: Remove try and except # cropping only in the landmask region: self.fracWat = pcr.ifthen(self.landmask, self.fracWat) self.waterBodyIds = pcr.ifthen(self.landmask, self.waterBodyIds) self.waterBodyOut = pcr.ifthen(self.landmask, self.waterBodyOut) self.waterBodyArea = pcr.ifthen(self.landmask, self.waterBodyArea) self.waterBodyTyp = pcr.ifthen(self.landmask, self.waterBodyTyp) self.waterBodyCap = pcr.ifthen(self.landmask, self.waterBodyCap)
#~ pcr.aguila(basin_area) # finding the month that give the maximum discharge (from the climatology time series) msg = "Identifying the month with peak discharge (from climatology time series):" logger.info(msg) # - read the maximum monthly discharge for every basin maximum_discharge = vos.netcdf2PCRobjClone(input_files['maximumClimatologyDischargeMonthAvg'], \ "discharge", 1,\ useDoy = "Yes", cloneMapFileName = clone_map_file,\ LatitudeLongitude = True,\ specificFillValue = None) maximum_discharge = pcr.areamaximum(\ pcr.cover(maximum_discharge, 0.0), basin_map) # - find the month with maximum discharge maximum_month = pcr.spatial(pcr.scalar(1.0)) for i_month in range(1, 12 + 1): # read the climatology discharge time series discharge_for_this_month = vos.netcdf2PCRobjClone(input_files['climatologyDischargeMonthAvg'], \ "discharge", i_month,\ useDoy = "Yes", cloneMapFileName = clone_map_file,\ LatitudeLongitude = True,\ specificFillValue = None) # upscale it to the basin scale discharge_for_this_month = pcr.areamaximum(discharge_for_this_month, basin_map) maximum_month = pcr.ifthenelse( discharge_for_this_month == maximum_discharge, pcr.scalar(i_month), maximum_month) pcr.report(maximum_month, "maximum_month.map")
pcraster.setclone(os.path.join(dataPath, "ELddF000.out")) mldd = pcraster.mldd.initialise(pcraster.clone()) mldd.setStream( # TODO Create overload which takes strings, or handle internally. pcraster.readmap(os.path.join(dataPath, "ELddF000.out")), pcraster.readmap(os.path.join(dataPath, "NELddF00.out")), pcraster.readmap(os.path.join(dataPath, "NLddF000.out")), pcraster.readmap(os.path.join(dataPath, "NWLddF00.out")), pcraster.readmap(os.path.join(dataPath, "SELddF00.out")), pcraster.readmap(os.path.join(dataPath, "SLddF000.out")), pcraster.readmap(os.path.join(dataPath, "SWLddF00.out")), pcraster.readmap(os.path.join(dataPath, "WLddF000.out"))) mldd.addStream(pcraster.readmap(os.path.join(dataPath, "ELddF000.out"))) mldd.setDem(pcraster.spatial(pcraster.scalar(1))) upstream = mldd.upstream(pcraster.spatial(pcraster.scalar(1))) pcraster.report(upstream, "upstream.map") accuflux = mldd.accuflux( pcraster.ifthen(pcraster.defined(upstream), pcraster.spatial(pcraster.scalar(1)))) pcraster.report(accuflux, "accuflux.map") dem = mldd.getDem() pcraster.report(dem, "dem.map") streamN, streamNE, streamE, streamSE, streamS, streamSW, streamW, streamNW = \ mldd.getStream()
def dynamic(self): ##################### # * dynamic section # ##################### #-evaluation of the current date: return current month and the time step used #-reading in fluxes over land and water area for current time step [m/d] # and read in reservoir demand and surface water extraction [m3] try: self.landSurfaceQ = clippedRead.get( pcrm.generateNameT(landSurfaceQFileName, self.currentTimeStep())) except: pass try: self.potWaterSurfaceQ = clippedRead.get( pcrm.generateNameT(waterSurfaceQFileName, self.currentTimeStep())) except: pass #-surface water extraction and reservoir demand currently set to zero, should # be computed automatically and updated to reservoirs self.potSurfaceWaterExtraction = pcr.spatial(pcr.scalar(0.)) #self.waterBodies.demand= #self.reservoirDemandTSS.assignID(self.waterBodies.ID,self.currentTimeStep(),0.)*self.timeSec #-initialization of cumulative values of actual water extractions self.actWaterSurfaceQ = pcr.spatial(pcr.scalar(0.)) self.actSurfaceWaterExtraction = pcr.spatial(pcr.scalar(0.)) #-definition of sub-loop for routing scheme - explicit scheme has to satisfy Courant condition timeLimit= pcr.cellvalue(pcr.mapminimum((pcr.cover(pcr.ifthen(self.waterBodies.distribution == 0,\ self.channelLength/self.flowVelocity),\ self.timeSec/self.nrIterDefault)*self.timeSec/self.nrIterDefault)**0.5),1)[0] nrIter = int(self.timeSec / timeLimit) nrIter = min(nrIter, int(self.timeSec / 300.)) while float(self.timeSec / nrIter) % 1 <> 0: nrIter += 1 deltaTime = self.timeSec / nrIter #-sub-loop for current time step if self.currentDate.day == 1 or nrIter >= 24: print '\n*\tprocessing %s, currently using %d substeps of %d seconds\n' % \ (self.currentDate.date(),nrIter,deltaTime) #-update discharge and storage for nrICur in range(nrIter): #-initializing discharge for the current sub-timestep and fill in values # for channels and at outlets of waterbodies # * channels * estQ= pcr.ifthenelse((self.actualStorage > 0.) & (self.waterBodies.distribution == 0) ,\ (self.wettedArea/self.alphaQ)**(1./self.betaQ),0.) #estQ= pcr.ifthenelse((self.actualStorage > 0.) & (self.waterBodies.distribution == 0) ,\ #0.5*(self.Q+(self.wettedArea/self.alphaQ)**(1./self.betaQ)),0.) #estQ= pcr.min(estQ,self.actualStorage/deltaTime) self.report(estQ, 'results/qest') self.Q = pcr.spatial(pcr.scalar(0.)) self.Q= pcr.ifthenelse(self.waterBodies.distribution == 0,\ pcr.kinematic(self.channelLDD,estQ,0.,self.alphaQ,\ self.betaQ,1,deltaTime,self.channelLength),self.Q) # * water bodies * self.waterBodies.dischargeUpdate() self.Q = self.waterBodies.returnMapValue(self.Q, self.waterBodies.actualQ) #-fluxes and resulting change in storage: first the local fluxes are evaluated # and aggregated over the water bodies where applicable; this includes the specific runoff [m/day/m2] # from input and the estimated extraction from surface water as volume per day [m3/day]; # specific runoff from the land surface is always positive whereas the fluxes over the water surface # are potential, including discharge, and are adjusted to match the availabe storage; to this end, # surface water storage and fluxes over water bodies are totalized and assigned to the outlet; # discharge is updated in a separate step, after vertical fluxes are compared to the actual storage deltaActualStorage= ((self.landFraction*self.landSurfaceQ+\ self.waterFraction*self.potWaterSurfaceQ)*self.cellArea-\ self.potSurfaceWaterExtraction)*float(self.duration)/nrIter deltaActualStorage= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(deltaActualStorage,self.waterBodies.distribution),0),\ deltaActualStorage) adjustmentRatio= pcr.ifthenelse(deltaActualStorage < 0.,\ pcr.min(1.,-self.actualStorage/deltaActualStorage),1.) self.actWaterSurfaceQ += adjustmentRatio * self.potWaterSurfaceQ self.actSurfaceWaterExtraction += adjustmentRatio * self.actSurfaceWaterExtraction deltaActualStorage *= adjustmentRatio #-local water balance check if testLocalWaterBalance: differenceActualStorage = self.actualStorage differenceActualStorage += deltaActualStorage #-overall water balance check: net input self.cumulativeDeltaStorage += pcr.catchmenttotal( deltaActualStorage, self.LDD) #-update storage first with local changes, then balance discharge with storage and update storage # with lateral flow and return value to water bodies self.actualStorage += deltaActualStorage self.actualStorage = pcr.max(0., self.actualStorage) self.Q = pcr.min(self.Q, self.actualStorage / deltaTime) deltaActualStorage = (-self.Q + pcr.upstream(self.LDD, self.Q)) * deltaTime deltaActualStorage= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(deltaActualStorage,self.waterBodies.distribution),0),\ deltaActualStorage) self.actualStorage += deltaActualStorage self.actualStorage = pcr.max(0., self.actualStorage) self.waterBodies.actualStorage = self.waterBodies.retrieveMapValue( self.actualStorage) #-flooded fraction returned floodedFraction,floodedDepth,\ self.wettedArea,self.alphaQ= self.kinAlphaComposite(self.actualStorage,self.floodplainMask) self.wettedArea= self.waterBodies.returnMapValue(self.wettedArea,\ self.waterBodies.channelWidth+2.*self.waterBodies.updateWaterHeight()) self.waterFraction= pcr.ifthenelse(self.waterBodies.distribution == 0,\ pcr.max(self.waterFractionMask,floodedFraction),self.waterFractionMask) self.landFraction = pcr.max(0., 1. - self.waterFraction) self.flowVelocity = pcr.ifthenelse(self.wettedArea > 0, self.Q / self.wettedArea, 0.) #-local water balance check if testLocalWaterBalance: differenceActualStorage += deltaActualStorage differenceActualStorage -= self.actualStorage totalDifference = pcr.cellvalue( pcr.maptotal(differenceActualStorage), 1)[0] minimumDifference = pcr.cellvalue( pcr.mapminimum(differenceActualStorage), 1)[0] maximumDifference = pcr.cellvalue( pcr.mapmaximum(differenceActualStorage), 1)[0] if abs(totalDifference) > 1.e-3: print 'water balance error: total %e; min %e; max %e' %\ (totalDifference,minimumDifference,maximumDifference) if reportLocalWaterBalance: pcr.report(differenceActualStorage, 'mbe_%s.map' % self.currentDate.date()) #-overall water balance check: updating cumulative discharge and total storage [m3] self.totalDischarge += self.Q * deltaTime self.totalStorage = pcr.catchmenttotal(self.actualStorage, self.LDD) #-check on occurrence of last day and report mass balance if self.currentDate == self.endDate: #-report initial maps pcr.report(self.Q, self.QIniMap) pcr.report(self.actualStorage, self.actualStorageIniMap) #-return relative and absolute water balance error per cell and # as total at basin outlets self.totalDischarge= pcr.ifthen((self.waterBodies.distribution == 0) | \ (self.waterBodies.location != 0),self.totalDischarge) self.cumulativeDeltaStorage= pcr.ifthen((self.waterBodies.distribution == 0) | \ (self.waterBodies.location != 0),self.cumulativeDeltaStorage) massBalanceError= self.totalStorage+self.totalDischarge-\ self.cumulativeDeltaStorage relMassBalanceError = 1. + pcr.ifthenelse( self.cumulativeDeltaStorage <> 0., massBalanceError / self.cumulativeDeltaStorage, 0.) totalMassBalanceError= pcr.cellvalue(pcr.maptotal(pcr.ifthen(self.basinOutlet,\ massBalanceError)),1)[0] totalCumulativeDeltaStorage= pcr.cellvalue(pcr.maptotal(pcr.ifthen(self.basinOutlet,\ self.cumulativeDeltaStorage)),1)[0] if totalCumulativeDeltaStorage > 0: totalRelativeMassBalanceError = 1. + totalMassBalanceError / totalCumulativeDeltaStorage else: totalRelativeMassBalanceError = 1. #-report maps and echo value pcr.report(massBalanceError, mbeFileName) pcr.report(relMassBalanceError, mbrFileName) print '\n*\ttotal global mass balance error [m3]: %8.3g' % totalMassBalanceError print '\n*\trelative global mass balance error [-]: %5.3f' % totalRelativeMassBalanceError #-echo to screen: total mass balance error and completion of run print '\trun completed' #-end of day: return states and fluxes #-get surface water attributes? if getSurfaceWaterAttributes: #-compute the following secondary variables: # surface water area [m2]: area given dynamic surface water fraction # residence time [days]: volume over discharge, assigned -1 in case discharge is zero # surface water depth [m], weighed by channel and floodplain volume surfaceWaterArea = self.waterFraction * self.cellArea surfaceWaterArea= pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.ifthenelse(self.waterBodies.location != 0,\ pcr.areatotal(surfaceWaterArea,self.waterBodies.distribution),0),\ surfaceWaterArea) surfaceWaterResidenceTime = pcr.ifthenelse( self.Q > 0., self.actualStorage / (self.Q * self.timeSec), -1) surfaceWaterDepth= pcr.ifthenelse(self.actualStorage > 0.,\ pcr.max(0.,self.actualStorage-self.channelStorageCapacity)**2/\ (self.actualStorage*surfaceWaterArea),0.) surfaceWaterDepth+= pcr.ifthenelse(self.actualStorage > 0.,\ pcr.min(self.channelStorageCapacity,self.actualStorage)**2/(self.waterFractionMask*\ self.cellArea*self.actualStorage),0.) #-reports: values at outlet of lakes or reservoirs are assigned to their full extent self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterArea,self.waterBodies.distribution),surfaceWaterArea),\ surfaceWaterAreaFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterResidenceTime,self.waterBodies.distribution),surfaceWaterResidenceTime),\ surfaceWaterResidenceTimeFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution != 0,\ pcr.areamaximum(surfaceWaterDepth,self.waterBodies.distribution),surfaceWaterDepth),\ surfaceWaterDepthFileName) #-reports on standard output: values at outlet of lakes or reservoirs are assigned to their full extent self.report( pcr.ifthenelse( self.waterBodies.distribution != 0, pcr.areamaximum(self.flowVelocity, self.waterBodies.distribution), self.flowVelocity), flowVelocityFileName) self.report( pcr.ifthenelse( self.waterBodies.distribution != 0, pcr.areamaximum(self.Q, self.waterBodies.distribution), self.Q), QFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution == 0,\ floodedFraction,0.),floodedFractionFileName) self.report(pcr.ifthenelse(self.waterBodies.distribution == 0,\ floodedDepth,0.),floodedDepthFileName) self.report(self.actualStorage, actualStorageFileName) #-update date for time step and report relevant daily output self.currentDate = self.currentDate + datetime.timedelta(self.duration)
class TimeoutputTimeseries(object): """ Class to create pcrcalc timeoutput style timeseries """ def __init__(self, tssFilename, model, idMap=None, noHeader=False): """ """ if not isinstance(tssFilename, str): raise Exception( "timeseries output filename must be of type string") self._outputFilename = tssFilename self._maxId = 1 self._spatialId = None self._spatialDatatype = None self._spatialIdGiven = False self._userModel = model self._writeHeader = not noHeader # array to store the timestep values self._sampleValues = None _idMap = False if isinstance(idMap, str) or isinstance(idMap, pcraster._pcraster.Field): _idMap = True nrRows = self._userModel.nrTimeSteps() - self._userModel.firstTimeStep( ) + 1 if _idMap: self._spatialId = idMap if isinstance(idMap, str): self._spatialId = pcraster.readmap(idMap) _allowdDataTypes = [ pcraster.Nominal, pcraster.Ordinal, pcraster.Boolean ] if self._spatialId.dataType() not in _allowdDataTypes: raise Exception( "idMap must be of type Nominal, Ordinal or Boolean") if self._spatialId.isSpatial(): self._maxId, valid = pcraster.cellvalue( pcraster.mapmaximum(pcraster.ordinal(self._spatialId)), 1) else: self._maxId = 1 # cell indices of the sample locations self._sampleAddresses = [] for cellId in range(1, self._maxId + 1): self._sampleAddresses.append(self._getIndex(cellId)) self._spatialIdGiven = True nrCols = self._maxId self._sampleValues = [[Decimal("NaN")] * nrCols for _ in [0] * nrRows] else: self._sampleValues = [[Decimal("NaN")] * 1 for _ in [0] * nrRows] def _getIndex(self, cellId): """ returns the cell index of a sample location """ nrCells = pcraster.clone().nrRows() * pcraster.clone().nrCols() found = False cell = 1 index = 0 while found == False: if pcraster.cellvalue(self._spatialId, cell)[1] == True and pcraster.cellvalue( self._spatialId, cell)[0] == cellId: index = cell found = True cell += 1 if cell > nrCells: raise RuntimeError( "could not find a cell with the index number %d" % (cellId)) return index def sample(self, expression): """ Sampling the current values of 'expression' at the given locations for the current timestep """ arrayRowPos = self._userModel.currentTimeStep( ) - self._userModel.firstTimeStep() #if isinstance(expression, float): # expression = pcraster.scalar(expression) try: # store the data type for tss file header if self._spatialDatatype == None: self._spatialDatatype = str(expression.dataType()) except AttributeError, e: datatype, sep, tail = str(e).partition(" ") msg = "Argument must be a PCRaster map, type %s given. If necessary use data conversion functions like scalar()" % ( datatype) raise AttributeError(msg) if self._spatialIdGiven: if expression.dataType() == pcraster.Scalar or expression.dataType( ) == pcraster.Directional: tmp = pcraster.areaaverage(pcraster.spatial(expression), pcraster.spatial(self._spatialId)) else: tmp = pcraster.areamajority(pcraster.spatial(expression), pcraster.spatial(self._spatialId)) col = 0 for cellIndex in self._sampleAddresses: value, valid = pcraster.cellvalue(tmp, cellIndex) if not valid: value = Decimal("NaN") self._sampleValues[arrayRowPos][col] = value col += 1 else: if expression.dataType() == pcraster.Scalar or expression.dataType( ) == pcraster.Directional: tmp = pcraster.maptotal(pcraster.spatial(expression))\ / pcraster.maptotal(pcraster.scalar(pcraster.defined(pcraster.spatial(expression)))) else: tmp = pcraster.mapmaximum(pcraster.maptotal(pcraster.areamajority(pcraster.spatial(expression),\ pcraster.spatial(pcraster.nominal(1))))) value, valid = pcraster.cellvalue(tmp, 1) if not valid: value = Decimal("NaN") self._sampleValues[arrayRowPos] = value if self._userModel.currentTimeStep() == self._userModel.nrTimeSteps(): self._writeTssFile()
mldd = pcraster.mldd.initialise(pcraster.clone()) mldd.setStream( # TODO Create overload which takes strings, or handle internally. pcraster.readmap(os.path.join(dataPath, "ELddF000.out")), pcraster.readmap(os.path.join(dataPath, "NELddF00.out")), pcraster.readmap(os.path.join(dataPath, "NLddF000.out")), pcraster.readmap(os.path.join(dataPath, "NWLddF00.out")), pcraster.readmap(os.path.join(dataPath, "SELddF00.out")), pcraster.readmap(os.path.join(dataPath, "SLddF000.out")), pcraster.readmap(os.path.join(dataPath, "SWLddF00.out")), pcraster.readmap(os.path.join(dataPath, "WLddF000.out")), ) mldd.addStream(pcraster.readmap(os.path.join(dataPath, "ELddF000.out"))) mldd.setDem(pcraster.spatial(pcraster.scalar(1))) upstream = mldd.upstream(pcraster.spatial(pcraster.scalar(1))) pcraster.report(upstream, "upstream.map") accuflux = mldd.accuflux(pcraster.ifthen(pcraster.defined(upstream), pcraster.spatial(pcraster.scalar(1)))) pcraster.report(accuflux, "accuflux.map") dem = mldd.getDem() pcraster.report(dem, "dem.map") streamN, streamNE, streamE, streamSE, streamS, streamSW, streamW, streamNW = mldd.getStream() pcraster.report(streamN, "streamN.map") pcraster.report(streamNE, "streamNE.map")
def modflow_simulation(self,\ simulation_type,\ initial_head_layer_1, initial_head_layer_2,\ currTimeStep = None,\ NSTP = 1, \ HCLOSE = 0.5,\ RCLOSE = 100.* 400.*400.,\ MXITER = 300,\ ITERI = 100,\ NPCOND = 1,\ RELAX = 1.00,\ NBPOL = 2,\ DAMP = 1,\ ITMUNI = 4, LENUNI = 2, PERLEN = 1.0, TSMULT = 1.0): # initiate pcraster modflow object self.initiate_modflow() if simulation_type == "transient": logger.info("Preparing MODFLOW input for a transient simulation.") SSTR = 0 if simulation_type == "steady-state": logger.info( "Preparing MODFLOW input for a steady-state simulation.") SSTR = 1 # waterBody class to define the extent of lakes and reservoirs # if simulation_type == "steady-state": self.WaterBodies = waterBodies.WaterBodies(self.iniItems,\ self.landmask,\ self.onlyNaturalWaterBodies) self.WaterBodies.getParameterFiles(date_given = self.iniItems.globalOptions['startTime'],\ cellArea = self.cellAreaMap, \ ldd = self.lddMap) # if simulation_type == "transient": if currTimeStep.timeStepPCR == 1: self.WaterBodies = waterBodies.WaterBodies(self.iniItems,\ self.landmask,\ self.onlyNaturalWaterBodies) if currTimeStep.timeStepPCR == 1 or currTimeStep.doy == 1: self.WaterBodies.getParameterFiles(date_given = str(currTimeStep.fulldate),\ cellArea = self.cellAreaMap, \ ldd = self.lddMap) # using dem_average as the initial groundwater head value self.pcr_modflow.setInitialHead(initial_head_layer_1, 1) self.pcr_modflow.setInitialHead(initial_head_layer_2, 2) # set parameter values for the DIS package and PCG solver self.pcr_modflow.setDISParameter(ITMUNI, LENUNI, PERLEN, NSTP, TSMULT, SSTR) self.pcr_modflow.setPCG(MXITER, ITERI, NPCOND, HCLOSE, RCLOSE, RELAX, NBPOL, DAMP) # # Some notes about the values # # ITMUNI = 4 # indicates the time unit (0: undefined, 1: seconds, 2: minutes, 3: hours, 4: days, 5: years) # LENUNI = 2 # indicates the length unit (0: undefined, 1: feet, 2: meters, 3: centimeters) # PERLEN = 1.0 # duration of a stress period # NSTP = 1 # number of time steps in a stress period # TSMULT = 1.0 # multiplier for the length of the successive iterations # SSTR = 1 # 0 - transient, 1 - steady state # # MXITER = 100 # maximum number of outer iterations # ITERI = 30 # number of inner iterations # NPCOND = 1 # 1 - Modified Incomplete Cholesky, 2 - Polynomial matrix conditioning method; # HCLOSE = 0.01 # HCLOSE (unit: m) # 0.05 is working # RCLOSE = 10.* 400.*400. # RCLOSE (unit: m3) ; Deltares people uses 100 m3 for their 25 m resolution modflow model # RELAX = 1.00 # relaxation parameter used with NPCOND = 1 # NBPOL = 2 # indicates whether the estimate of the upper bound on the maximum eigenvalue is 2.0 (but we don ot use it, since NPCOND = 1) # DAMP = 1 # no damping (DAMP introduced in MODFLOW 2000) # read input files (for the steady-state condition, we use pcraster maps): if simulation_type == "steady-state": # - discharge (m3/s) from PCR-GLOBWB discharge = vos.readPCRmapClone(self.iniItems.modflowSteadyStateInputOptions['avgDischargeInputMap'],\ self.cloneMap, self.tmpDir, self.inputDir) # - recharge/capillary rise (unit: m/day) from PCR-GLOBWB gwRecharge = vos.readPCRmapClone(self.iniItems.modflowSteadyStateInputOptions['avgGroundwaterRechargeInputMap'],\ self.cloneMap, self.tmpDir, self.inputDir) if self.ignoreCapRise: gwRecharge = pcr.max(0.0, gwRecharge) gwAbstraction = pcr.spatial(pcr.scalar(0.0)) # read input files (for the transient, input files are given in netcdf files): if simulation_type == "transient": # - discharge (m3/s) from PCR-GLOBWB discharge = vos.netcdf2PCRobjClone( self.iniItems.modflowTransientInputOptions['dischargeInputNC'], "discharge", str(currTimeStep.fulldate), None, self.cloneMap) # - recharge/capillary rise (unit: m/day) from PCR-GLOBWB gwRecharge = vos.netcdf2PCRobjClone(self.iniItems.modflowTransientInputOptions['groundwaterRechargeInputNC'],\ "groundwater_recharge",str(currTimeStep.fulldate),None,self.cloneMap) if self.ignoreCapRise: gwRecharge = pcr.max(0.0, gwRecharge) # - groundwater abstraction (unit: m/day) from PCR-GLOBWB gwAbstraction = vos.netcdf2PCRobjClone(self.iniItems.modflowTransientInputOptions['groundwaterAbstractionInputNC'],\ "total_groundwater_abstraction",str(currTimeStep.fulldate),None,self.cloneMap) # set recharge and river packages self.set_river_package(discharge) self.set_recharge_package(gwRecharge) self.set_well_package(gwAbstraction) # execute MODFLOW logger.info("Executing MODFLOW.") self.pcr_modflow.run() # TODO: Add the mechanism to check whether a run has converged or not. # obtaining the results from modflow simulation self.groundwaterHeadLayer2 = None self.groundwaterHeadLayer2 = self.pcr_modflow.getHeads(2) self.groundwaterHeadLayer1 = None self.groundwaterHeadLayer1 = self.pcr_modflow.getHeads(1) # calculate groundwater depth only in the landmask region self.groundwaterDepth = pcr.ifthen( self.landmask, self.dem_average - self.groundwaterHeadLayer2)
def read_forcings(self, currTimeStep): # reading precipitation: if self.precipitation_set_per_year: #~ print currTimeStep.year nc_file_per_year = self.preFileNC % (float( currTimeStep.year), float(currTimeStep.year)) self.precipitation = vos.netcdf2PCRobjClone(\ nc_file_per_year, 'precipitation',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) else: #self.precipitation = vos.netcdf2PCRobjClone(\ # self.preFileNC, 'precipitation',\ # str(currTimeStep.fulldate), # useDoy = None, # cloneMapFileName = self.cloneMap,\ # LatitudeLongitude = True) # reading precip when ISI-MIP is used precipitation = vos.netcdf2PCRobjClone(\ self.preFileNC, 'pr',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) # unit original km m-2 s-1 to m d-1 # soortelijk gewicht water = 998 km/m3 self.precipitation = (precipitation / 998.0) * (60. * 60. * 24) precipitationCorrectionFactor = pcr.scalar( 1.0 ) # Since 19 Feb 2014, Edwin removed the support for correcting precipitation. self.precipitation = pcr.max(0.,self.precipitation*\ precipitationCorrectionFactor) self.precipitation = pcr.cover(self.precipitation, 0.0) # ignore very small values of precipitation (less than 0.00001 m/day or less than 0.01 kg.m-2.day-1 ) if self.usingDailyTimeStepForcingData: self.precipitation = pcr.rounddown( self.precipitation * 100000.) / 100000. # reading temperature if self.temperature_set_per_year: nc_file_per_year = self.tmpFileNC % (int( currTimeStep.year), int(currTimeStep.year)) self.temperature = vos.netcdf2PCRobjClone(\ nc_file_per_year, 'temperature',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) else: # updated to temp when using ISI-MIP projection temperature = vos.netcdf2PCRobjClone(\ self.tmpFileNC,'tas',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName=self.cloneMap,\ LatitudeLongitude = True) # unit K to C self.temperature = temperature - 273.15 # Downscaling precipitation and temperature if self.downscalePrecipitationOption: self.downscalePrecipitation(currTimeStep) if self.downscaleTemperatureOption: self.downscaleTemperature(currTimeStep) # calculate or obtain referencePotET if self.refETPotMethod == 'Hamon': self.referencePotET = \ refPotET.HamonPotET(self.temperature,\ currTimeStep.doy,\ self.latitudes) if self.refETPotMethod == 'Input': if self.refETPotFileNC_set_per_year: nc_file_per_year = self.etpFileNC % (int( currTimeStep.year), int(currTimeStep.year)) self.referencePotET = vos.netcdf2PCRobjClone(\ nc_file_per_year, 'evapotranspiration',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName = self.cloneMap,\ LatitudeLongitude = True) else: self.referencePotET = vos.netcdf2PCRobjClone(\ self.etpFileNC,'evapotranspiration',\ str(currTimeStep.fulldate), useDoy = None, cloneMapFileName=self.cloneMap,\ LatitudeLongitude = True) # Downscaling referenceETPot (based on temperature) if self.downscaleReferenceETPotOption: self.downscaleReferenceETPot() # smoothing: if self.forcingSmoothing == True: logger.debug("Forcing data are smoothed.") self.precipitation = pcr.windowaverage(self.precipitation, self.smoothingWindowsLength) self.temperature = pcr.windowaverage(self.temperature, self.smoothingWindowsLength) self.referencePotET = pcr.windowaverage( self.referencePotET, self.smoothingWindowsLength) # make sure precipitation is always positive: self.precipitation = pcr.max(0.0, self.precipitation) # rounding temperature values to minimize numerical errors (note only to minimize, not remove) self.temperature = pcr.roundoff(self.temperature * 1000.) / 1000. # ignore snow by setting temperature to 25 deg C if self.ignore_snow: self.temperature = pcr.spatial(pcr.scalar(25.)) # define precipitation, temperature and referencePotET ONLY at landmask area (for reporting): self.precipitation = pcr.ifthen(self.landmask, self.precipitation) self.temperature = pcr.ifthen(self.landmask, self.temperature) self.referencePotET = pcr.ifthen(self.landmask, self.referencePotET) if self.report == True: timeStamp = datetime.datetime(currTimeStep.year,\ currTimeStep.month,\ currTimeStep.day,\ 0) # writing daily output to netcdf files timestepPCR = currTimeStep.timeStepPCR if self.outDailyTotNC[0] != "None": for var in self.outDailyTotNC: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_dailyTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,timestepPCR-1) # writing monthly output to netcdf files # -cummulative if self.outMonthTotNC[0] != "None": for var in self.outMonthTotNC: # introduce variables at the beginning of simulation or # reset variables at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.day == 1: \ vars(self)[var+'MonthTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'MonthTot'] += vars(self)[var] # reporting at the end of the month: if currTimeStep.endMonth == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'MonthTot'),\ vos.MV),timeStamp,currTimeStep.monthIdx-1) # -average if self.outMonthAvgNC[0] != "None": for var in self.outMonthAvgNC: # only if a accumulator variable has not been defined: if var not in self.outMonthTotNC: # introduce accumulator at the beginning of simulation or # reset accumulator at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.day == 1: \ vars(self)[var+'MonthTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'MonthTot'] += vars(self)[var] # calculating average & reporting at the end of the month: if currTimeStep.endMonth == True: vars(self)[var+'MonthAvg'] = vars(self)[var+'MonthTot']/\ currTimeStep.day self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthAvg.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'MonthAvg'),\ vos.MV),timeStamp,currTimeStep.monthIdx-1) # # -last day of the month if self.outMonthEndNC[0] != "None": for var in self.outMonthEndNC: # reporting at the end of the month: if currTimeStep.endMonth == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_monthEnd.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,currTimeStep.monthIdx-1) # writing yearly output to netcdf files # -cummulative if self.outAnnuaTotNC[0] != "None": for var in self.outAnnuaTotNC: # introduce variables at the beginning of simulation or # reset variables at the beginning of the month if currTimeStep.timeStepPCR == 1 or \ currTimeStep.doy == 1: \ vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'AnnuaTot'] += vars(self)[var] # reporting at the end of the year: if currTimeStep.endYear == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaTot.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'AnnuaTot'),\ vos.MV),timeStamp,currTimeStep.annuaIdx-1) # -average if self.outAnnuaAvgNC[0] != "None": for var in self.outAnnuaAvgNC: # only if a accumulator variable has not been defined: if var not in self.outAnnuaTotNC: # introduce accumulator at the beginning of simulation or # reset accumulator at the beginning of the year if currTimeStep.timeStepPCR == 1 or \ currTimeStep.doy == 1: \ vars(self)[var+'AnnuaTot'] = pcr.scalar(0.0) # accumulating vars(self)[var + 'AnnuaTot'] += vars(self)[var] # # calculating average & reporting at the end of the year: if currTimeStep.endYear == True: vars(self)[var+'AnnuaAvg'] = vars(self)[var+'AnnuaTot']/\ currTimeStep.doy self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaAvg.nc",\ var,\ pcr2numpy(self.__getattribute__(var+'AnnuaAvg'),\ vos.MV),timeStamp,currTimeStep.annuaIdx-1) # # -last day of the year if self.outAnnuaEndNC[0] != "None": for var in self.outAnnuaEndNC: # reporting at the end of the year: if currTimeStep.endYear == True: self.netcdfObj.data2NetCDF(str(self.outNCDir)+"/"+ \ str(var)+"_annuaEnd.nc",\ var,\ pcr2numpy(self.__getattribute__(var),vos.MV),\ timeStamp,currTimeStep.annuaIdx-1)
def 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 initial(self): # make sure that you start from the script directory os.chdir(self.script_directory) # In this part (premcloop), we initiate parameters/variables/objects that are changing throughout all monte carlo samples. msg = "\n" msg += "Sample number: " + str(self.currentSampleNumber()) msg += "\n" print(msg) # conductivities for the BCF package, see: http://pcraster.geo.uu.nl/pcraster/4.1.0/doc/modflow/bcf.html inp_soil_conductivity = self.model_setup['soil_conductivity'][ int(str(self.currentSampleNumber())) - 1] self.soil_conductivity = pcr.spatial(pcr.scalar(inp_soil_conductivity)) # # - horizontal and vertical conductivity self.hConductivity = self.soil_conductivity self.vConductivity = self.hConductivity # - for one layer model, vConductivity is just dummy and never used # - layer type, we use LAYTYPE = 0 (harmonic mean) and LAYCON = 0 (confined, constant transmissivities and storage coefficients) # storage coefficients for the BCF package, see: http://pcraster.geo.uu.nl/pcraster/4.1.0/doc/modflow/bcf.html # - sand porosity (m3.m-3) # TODO: Find the value from Sebastian paper. self.sand_porosity = pcr.spatial(pcr.scalar(0.25)) # # - primary and secondary storage coefficients self.primary_storage_coefficient = self.sand_porosity self.secondary_storage_coefficient = self.primary_storage_coefficient # - for LAYCON = 0 (and 1), secondary_storage_coefficient is just dummy and never used # The following are CURRENTLY just the same for all samples. ############################################################################ # defining the layer (one layer model), thickness (m), top and bottom elevations self.thickness = 15.0 # - thickness value is suggested by Kim Cohen (put reference here) self.top_elevation = self.input_dem self.bottom_elevation = self.top_elevation - self.thickness # DIS parameters, see http://pcraster.geo.uu.nl/pcraster/4.1.0/doc/modflow/dis.html # - time and spatial units self.ITMUNI = 4 # indicating that the time unit is "days" self.LENUNI = 2 # indicating that the spatial unit is "meters" # - PERLEN: duration of stress period (days) # -- 10 minute stress period = 600 seconds stress period self.length_of_stress_period = 600. / (24. * 60. * 60.) self.PERLEN = self.length_of_stress_period # - NSTP: number of sub time steps within the PERLEN self.NSTP = 1 # - TSMULT # always 1 by default self.TSMULT = 1 # - SSTR: transient (0) or steady state (1) self.SSTR = 0 # values for the IBOND of the BAS package, see: http://pcraster.geo.uu.nl/pcraster/4.1.0/doc/modflow/bas.html # - Alternative 1: all cells are active self.ibound = pcr.spatial(pcr.nominal(1.)) #~ # - Alternative 2: in the ocean region (x < -75 m), assume the heads will follow the tides #~ self.ibound = pcr.ifthenelse(pcr.xcoordinate(clone_map) < -75., pcr.nominal(-1.), pcr.nominal(1.)) #~ pcr.aguila(self.ibound) # ibound with regional groundwater head values if self.model_setup['regional_groundwater_head']['activation']: self.ibound = pcr.ifthenelse( pcr.xcoordinate(pcr.boolean(1.0)) >= self.model_setup['regional_groundwater_head']['starting_x'], pcr.nominal(-1.), self.ibound) # parameter values for the SOLVER package self.MXITER = 50 # maximum number of outer iterations # Deltares use 50 self.ITERI = 30 # number of inner iterations # Deltares use 30 self.NPCOND = 1 # 1 - Modified Incomplete Cholesky, 2 - Polynomial matrix conditioning method self.HCLOSE = 0.001 # HCLOSE (unit: m) self.RCLOSE = 0.001 # RCLOSE (unit: m3) self.RELAX = 1.00 # relaxation parameter used with NPCOND = 1 self.NBPOL = 2 # indicates whether the estimate of the upper bound on the maximum eigenvalue is 2.0 (but we don ot use it, since NPCOND = 1) self.DAMP = 1 # no damping (DAMP introduced in MODFLOW 2000) # the initial head for the BAS package, see: http://pcraster.geo.uu.nl/pcraster/4.1.0/doc/modflow/bas.html # - Gerben recommends to start using 0.8 m self.initial_head = pcr.spatial(pcr.scalar(0.8)) # regional groundwater head if self.model_setup['regional_groundwater_head']['activation']: self.initial_head = pcr.ifthenelse( pcr.xcoordinate(pcr.boolean(1.0)) >= self.model_setup['regional_groundwater_head']['starting_x'], self.model_setup['regional_groundwater_head']['value'], self.initial_head) # initialise timeoutput object for reporting time series in txt files # - groundwater head self.head_obs_point = pcr.readmap( "input_files/groundwater_well_coordinates.map") self.reportGwHeadTss = TimeoutputTimeseries("groundwater_head", self, self.head_obs_point, noHeader=False) # Save model parameter values (and other information) to a txt file. # - output directory (that will contain result) output_directory = self.output_folder + "/" + str( self.currentSampleNumber()) try: os.makedirs(output_directory) except: pass # - file name for this information information_file = output_directory + "/" + "info.txt" file_info = open(information_file, 'w') write_line = "" # - DEM write_line += "DEM (m): " + str(self.model_setup['dem_file_name']) write_line += "\n" # - tide write_line += "Tide input file name: " + str( self.model_setup['tide_file_name']) write_line += "\n" # - starting date write_line += "Starting date and time: " + str( self.model_setup['start_datetime']) write_line += "\n" # - soil conductivity write_line += "Soil conductivity (m.day-1): " + str( inp_soil_conductivity) write_line += "\n" # - regional groundwater head (optional): if self.model_setup['regional_groundwater_head']['activation']: write_line += "Regional groundwater head is fixed to : " + str( self.model_setup['regional_groundwater_head']['value']) write_line += "\n" write_line += "for all cells in with x coordinate >=: " + str( self.model_setup['regional_groundwater_head']['starting_x']) write_line += "\n" else: write_line += "NO regional groundwater head. " write_line += "\n" # - sample number write_line += "PCRaster sample number: " + str( self.currentSampleNumber()) write_line += "\n" file_info.write(write_line) # - close the file file_info.close() # initiate netcdf files for groundwater head netcdf_variable_name = "groundwater_head" self.netcdf_file_name = self.output_folder + "/" + str( self.currentSampleNumber()) + "/" + netcdf_variable_name + ".nc" self.model_setup['netcdf_attributes']['notes'] = write_line self.netcdf_writer.create_netcdf_file( self.netcdf_file_name, self.model_setup['netcdf_attributes']) # - create variable netcdf_variable_unit = "m" self.netcdf_writer.create_variable(self.netcdf_file_name, netcdf_variable_name, netcdf_variable_unit)