def get_coordinate_arrays(settings, ncols, nrows): # Fill variables try: int_lons = settings.binding['internal.lons'] int_lats = settings.binding['internal.lats'] # x1 = Decimal(__DECIMAL_FORMAT.format(int_lons[0])) # x2 = Decimal(__DECIMAL_FORMAT.format(int_lons[1])) # y1 = Decimal(__DECIMAL_FORMAT.format(int_lats[0])) # y2 = Decimal(__DECIMAL_FORMAT.format(int_lats[1])) # cellSizeX = abs(x2 - x1) # cellSizeY = abs(y2 - y1) lats = coordinates_range_from_array(int_lats) lons = coordinates_range_from_array(int_lons) except: cellSize = Decimal(__DECIMAL_FORMAT.format( pcraster.clone().cellSize())) half_cell = cellSize * Decimal(0.5) xl = Decimal(__DECIMAL_FORMAT.format( pcraster.clone().west())) + half_cell # xr = xl + ncols * cellSize - half_cell yu = Decimal(__DECIMAL_FORMAT.format( pcraster.clone().north())) - half_cell # yd = yu - nrows * cellSize + half_cell lats = coordinates_range(yu, nrows, -cellSize) lons = coordinates_range(xl, ncols, cellSize) return lats, lons
def testSetCloneUsingFile(self): pcraster.setclone(os.path.join("validated", "ordinal_Result.map")) self.assertEqual(pcraster.clone().nrRows(), 3) self.assertEqual(pcraster.clone().nrCols(), 3) self.assertEqual(pcraster.clone().cellSize(), 1.0) self.assertEqual(pcraster.clone().west(), 0.0) self.assertEqual(pcraster.clone().north(), 0.0)
def __init__(self, input_netcdf,\ output_netcdf,\ modelTime,\ tmpDir = "/dev/shm/"): DynamicModel.__init__(self) self.input_netcdf = input_netcdf self.output_netcdf = output_netcdf self.tmpDir = tmpDir self.modelTime = modelTime # set clone self.clone_map_file = self.input_netcdf['cell_area'] pcr.setclone(self.clone_map_file) self.clone = {} self.clone['cellsize'] = pcr.clone().cellSize() ; print self.clone['cellsize'] self.clone['rows'] = int(pcr.clone().nrRows()) self.clone['cols'] = int(pcr.clone().nrCols()) self.clone['xUL'] = round(pcr.clone().west(), 2) self.clone['yUL'] = round(pcr.clone().north(), 2) # cell area (unit: m2) self.cell_area = pcr.readmap(self.input_netcdf['cell_area']) # an object for netcdf reporting self.output = OutputNetcdf(self.clone, self.output_netcdf) # preparing the netcdf file and make variable: self.output.createNetCDF(self.output_netcdf['file_name'], self.output_netcdf['gross_variable_name'], self.output_netcdf['variable_unit']) self.output.addNewVariable(self.output_netcdf['file_name'], self.output_netcdf['netto_variable_name'], self.output_netcdf['variable_unit'])
def updateTrachytopes(inFile, outFile, roughCodeMap): """ input: inFile: path to ascii trachytope file with columns x, y, 0, code, fraction outFile: path to outfile with ascii trachytopes roughCodeMap: pcraster map with roughness codes output: new trachytope file """ #-read the trachtope data into a DataFrame columns = ['x', 'y', 'z', 'code', 'frac'] trachytopes = pd.DataFrame(data=np.loadtxt(inFile), columns=columns) nrCols = pcr.clone().nrCols() nrRows = pcr.clone().nrRows() #-get cell value for each line in trachytope DataFrame for cnt in xrange(len(trachytopes)): xcoord = trachytopes.loc[cnt, 'x'] ycoord = trachytopes.loc[cnt, 'y'] row, col = pcr_coord(xcoord, ycoord) if col > nrCols: roughCode, validCell = 102, False elif row <= 0: roughCode, validCell = 102, False else: roughCode, validCell = pcr.cellvalue(roughCodeMap, row, col) if validCell == True: trachytopes.loc[cnt, 'code'] = roughCode groupedCodes = trachytopes.groupby(by=['x', 'y', 'z', 'code']).sum() groupedCodes.reset_index(inplace=True) np.savetxt(outFile, groupedCodes.values, fmt='%.4f %.4f %.0f %.0f %.4f') return groupedCodes
def set_latlon_based_on_cloneMapFileName( self, cloneMapFileName, netcdf_y_orientation_from_top_bottom=True): # cloneMap cloneMap = pcr.boolean(pcr.readmap(cloneMapFileName)) cloneMap = pcr.boolean(pcr.scalar(1.0)) # properties of the clone maps # - numbers of rows and colums rows = pcr.clone().nrRows() cols = pcr.clone().nrCols() # - cell size in arc minutes rounded to one value behind the decimal cellSizeInArcMin = round(pcr.clone().cellSize() * 60.0, 1) # - cell sizes in ar degrees for longitude and langitude direction deltaLon = cellSizeInArcMin / 60. deltaLat = deltaLon # - coordinates of the upper left corner - rounded to two values behind the decimal in order to avoid rounding errors during (future) resampling process x_min = round(pcr.clone().west(), 2) y_max = round(pcr.clone().north(), 2) # - coordinates of the lower right corner - rounded to two values behind the decimal in order to avoid rounding errors during (future) resampling process x_max = round(x_min + cols * deltaLon, 2) y_min = round(y_max - rows * deltaLat, 2) # cell centres coordinates longitudes = np.arange(x_min + deltaLon / 2., x_max, deltaLon) latitudes = np.arange(y_max - deltaLat / 2., y_min, -deltaLat) if netcdf_y_orientation_from_top_bottom == False: latitudes = latitudes[::-1] return longitudes, latitudes, cellSizeInArcMin
def set_latlon_based_on_cloneMapFileName(self, cloneMapFileName): # cloneMap cloneMap = pcr.boolean(pcr.readmap(cloneMapFileName)) cloneMap = pcr.boolean(pcr.scalar(1.0)) # properties of the clone maps # - numbers of rows and colums rows = pcr.clone().nrRows() cols = pcr.clone().nrCols() # - cell size in arc minutes rounded to one value behind the decimal cellSizeInArcMin = round(pcr.clone().cellSize() * 60.0, 1) # - cell sizes in ar degrees for longitude and langitude direction deltaLon = cellSizeInArcMin / 60. deltaLat = deltaLon # - coordinates of the upper left corner - rounded to two values behind the decimal in order to avoid rounding errors during (future) resampling process x_min = round(pcr.clone().west(), 2) y_max = round(pcr.clone().north(), 2) # - coordinates of the lower right corner - rounded to two values behind the decimal in order to avoid rounding errors during (future) resampling process x_max = round(x_min + cols*deltaLon, 2) y_min = round(y_max - rows*deltaLat, 2) # cell centres coordinates longitudes = np.arange(x_min + deltaLon/2., x_max, deltaLon) latitudes = np.arange(y_max - deltaLat/2., y_min,-deltaLat) #~ # cell centres coordinates #~ longitudes = np.linspace(x_min + deltaLon/2., x_max - deltaLon/2., cols) #~ latitudes = np.linspace(y_max - deltaLat/2., y_min + deltaLat/2., rows) #~ # cell centres coordinates (latitudes and longitudes, directly from the clone maps) #~ longitudes = np.unique(pcr.pcr2numpy(pcr.xcoordinate(cloneMap), vos.MV)) #~ latitudes = np.unique(pcr.pcr2numpy(pcr.ycoordinate(cloneMap), vos.MV))[::-1] return longitudes, latitudes, cellSizeInArcMin
def set_latlon_based_on_cloneMapFileName(self, cloneMapFileName): # cloneMap cloneMap = pcr.boolean(pcr.readmap(cloneMapFileName)) cloneMap = pcr.boolean(pcr.scalar(1.0)) # properties of the clone maps # - numbers of rows and colums rows = pcr.clone().nrRows() cols = pcr.clone().nrCols() # - cell size in arc minutes rounded to one value behind the decimal cellSizeInArcMin = round(pcr.clone().cellSize() * 60.0, 1) # - cell sizes in ar degrees for longitude and langitude direction deltaLon = cellSizeInArcMin / 60.0 deltaLat = deltaLon # - coordinates of the upper left corner - rounded to two values behind the decimal in order to avoid rounding errors during (future) resampling process x_min = round(pcr.clone().west(), 2) y_max = round(pcr.clone().north(), 2) # - coordinates of the lower right corner - rounded to two values behind the decimal in order to avoid rounding errors during (future) resampling process x_max = round(x_min + cols * deltaLon, 2) y_min = round(y_max - rows * deltaLat, 2) # cell centres coordinates longitudes = np.arange(x_min + deltaLon / 2.0, x_max, deltaLon) latitudes = np.arange(y_max - deltaLat / 2.0, y_min, -deltaLat) # ~ # cell centres coordinates # ~ longitudes = np.linspace(x_min + deltaLon/2., x_max - deltaLon/2., cols) # ~ latitudes = np.linspace(y_max - deltaLat/2., y_min + deltaLat/2., rows) # ~ # cell centres coordinates (latitudes and longitudes, directly from the clone maps) # ~ longitudes = np.unique(pcr.pcr2numpy(pcr.xcoordinate(cloneMap), vos.MV)) # ~ latitudes = np.unique(pcr.pcr2numpy(pcr.ycoordinate(cloneMap), vos.MV))[::-1] return longitudes, latitudes, cellSizeInArcMin
def __init__(self, maskname): self.name = maskname self._attrs = { 'x': pcraster.clone().west(), 'y': pcraster.clone().north(), 'col': pcraster.clone().nrCols(), 'row': pcraster.clone().nrRows(), 'cell': pcraster.clone().cellSize(), }
def get_grid_origin(self, long_var_name): north = pcr.clone().north() cellSize = pcr.clone().cellSize() nrRows = pcr.clone().nrRows() south = north - (cellSize * nrRows) west = pcr.clone().west() return np.array([south, west])
def testSetCloneUsingValues(self): nrRows = 4 nrCols = 5 cellSize = 6.0 west = 7.0 north = 8.0 pcraster.setclone(nrRows, nrCols, cellSize, west, north) self.assertEqual(pcraster.clone().nrRows(), nrRows) self.assertEqual(pcraster.clone().nrCols(), nrCols) self.assertEqual(pcraster.clone().cellSize(), cellSize) self.assertEqual(pcraster.clone().west(), west) self.assertEqual(pcraster.clone().north(), north)
def pcr_coord(xcoord, ycoord): """ Get the row and column number for the clone map at xcoord, ycoord. Clone map should be defined explicitly, or through a previous command. """ west = pcr.clone().west() north = pcr.clone().north() cell_size = pcr.clone().cellSize() xCol = (xcoord - west) / cell_size yRow = (north - ycoord) / cell_size col = 1 + int(math.floor(xCol)) row = 1 + int(math.floor(yRow)) return row, col
def valuecell(coordx, coordstr): """ to put a value into a pcraster map -> invert of cellvalue pcraster map is converted into a numpy array first """ coord = [] for xy in coordx: try: coord.append(float(xy)) except ValueError: msg = 'Gauges: {} in {} is not a coordinate'.format(xy, coordstr) raise LisfloodError(msg) null = np.zeros((pcraster.clone().nrRows(), pcraster.clone().nrCols())) null[null == 0] = -9999 for i in range(int(len(coord) / 2)): col = int((coord[i * 2] - pcraster.clone().west()) / pcraster.clone().cellSize()) row = int((pcraster.clone().north() - coord[i * 2 + 1]) / pcraster.clone().cellSize()) if 0 <= col < pcraster.clone().nrCols() and 0 <= row < pcraster.clone().nrRows(): null[row, col] = i + 1 else: msg = 'Coordinates: {}, {} to put value in is outside mask map - col,row: {}, {}'.format(coord[i * 2], coord[i * 2 + 1], col, row) raise LisfloodError(msg) return numpy_operations.numpy2pcr(Nominal, null, -9999)
def valuecell(mask, coordx, coordstr): """ to put a value into a pcraster map -> invert of cellvalue pcraster map is converted into a numpy array first """ coord = [] for xy in coordx: try: coord.append(float(xy)) except: msg = "Gauges: " + xy + " in " + coordstr + " is not a coordinate" raise LisfloodError(msg) null = np.zeros((pcraster.clone().nrRows(), pcraster.clone().nrCols())) null[null == 0] = -9999 for i in range(int(len(coord) / 2)): col = int((coord[i * 2] - pcraster.clone().west()) / pcraster.clone().cellSize()) row = int((pcraster.clone().north() - coord[i * 2 + 1]) / pcraster.clone().cellSize()) #if col >= 0 and row >= 0 and col < pcraster.clone().nrCols() and row < pcraster.clone().nrRows(): if col >= 0 and row >= 0 and col < pcraster.clone().nrCols( ) and row < pcraster.clone().nrRows(): null[row, col] = i + 1 else: msg = "Coordinates: " + str(coord[i * 2]) + ',' + str(coord[ i * 2 + 1]) + " to put value in is outside mask map - col,row: " + str( col) + ',' + str(row) raise LisfloodError(msg) map = numpy2pcr(Nominal, null, -9999) return map
def clone_attributes(): """ Get the map attributes from the PCRaster clone map. Returns a list with: xmin, xmax, ymin, ymax, nr_rows, nr_cols, cell_size. """ nr_rows = pcr.clone().nrRows() nr_cols = pcr.clone().nrCols() cell_size = pcr.clone().cellSize() ymax = pcr.clone().north() xmin = pcr.clone().west() ymin = ymax - nr_rows * cell_size xmax = xmin + nr_cols * cell_size return xmin, xmax, ymin, ymax, nr_rows, nr_cols, cell_size
def __init__(self,cloneMapFileName,netcdf_attribute_description): # cloneMap cloneMap = pcr.boolean(pcr.readmap(cloneMapFileName)) cloneMap = pcr.boolean(pcr.scalar(1.0)) # properties of the clone maps # - numbers of rows and colums rows = pcr.clone().nrRows() cols = pcr.clone().nrCols() # - cell size in arc minutes rounded to one value behind the decimal cellSizeInArcMin = round(pcr.clone().cellSize() * 60.0, 1) # - cell sizes in ar degrees for longitude and langitude direction deltaLon = cellSizeInArcMin / 60. deltaLat = deltaLon # - coordinates of the upper left corner - rounded to two values behind the decimal in order to avoid rounding errors during (future) resampling process x_min = round(pcr.clone().west(), 2) y_max = round(pcr.clone().north(), 2) # - coordinates of the lower right corner - rounded to two values behind the decimal in order to avoid rounding errors during (future) resampling process x_max = round(x_min + cols*deltaLon, 2) y_min = round(y_max - rows*deltaLat, 2) # cell centres coordinates self.longitudes = np.arange(x_min + deltaLon/2., x_max, deltaLon) self.latitudes = np.arange(y_max - deltaLat/2., y_min,-deltaLat) #~ # cell centres coordinates #~ self.longitudes = np.linspace(x_min + deltaLon/2., x_max - deltaLon/2., cols) #~ self.latitudes = np.linspace(y_max - deltaLat/2., y_min + deltaLat/2., rows) #~ # cell centres coordinates (latitudes and longitudes, directly from the clone maps) #~ self.latitudes = np.unique(pcr.pcr2numpy(pcr.ycoordinate(cloneMap), vos.MV))[::-1] #~ self.longitudes = np.unique(pcr.pcr2numpy(pcr.xcoordinate(cloneMap), vos.MV)) # netCDF format and attributes: important_information = "The dataset was resampled to "+str(cellSizeInArcMin)+" arc minute resolution. " self.format = 'NETCDF3_CLASSIC' self.attributeDictionary = {} self.attributeDictionary['institution'] = "European Commission - JRC and Department of Physical Geography, Utrecht University" self.attributeDictionary['title' ] = "EFAS-Meteo 5km for Rhine-Meuse - resampled to "+str(cellSizeInArcMin)+" arc minute resolution. " self.attributeDictionary['source' ] = "5km Gridded Meteo Database (C) European Commission - JRDC, 2014" self.attributeDictionary['history' ] = "The data were provided by Ad de Roo ([email protected]) on 19 November 2014 and then converted by Edwin H. Sutanudjaja ([email protected]) to netcdf. " self.attributeDictionary['history' ] += important_information self.attributeDictionary['references' ] = "Ntegeka et al., 2013. EFAS-Meteo: A European daily high-resolution gridded meteorological data set. JRC Technical Reports. doi: 10.2788/51262" self.attributeDictionary['comment' ] = "Please use this dataset only for Hyper-Hydro test bed experiments. " self.attributeDictionary['comment' ] += "For using it and publishing it, please acknowledge its source: 5km Gridded Meteo Database (C) European Commission - JRDC, 2014 and its reference: Ntegeka et al., 2013 (doi: 10.2788/51262). " self.attributeDictionary['comment' ] += "The original data provided by JRC are in European ETRS projection, 5km grid; http://en.wikipedia.org/wiki/European_grid. " self.attributeDictionary['comment' ] += important_information self.attributeDictionary['description'] = netcdf_attribute_description
def premcloop(self): # In this part (premcloop), we initiate parameters/variables/objects that are the same (constant) values throughout all monte carlo (MC) samples. # - Note that you can also write this part in "__init__" (see above). # get the map properties of the clone map (length and width, in meter) self.cell_length = pcr.clone().cellSize() self.cell_width = pcr.clone().cellSize() # - cell area (m2) self.cell_area = self.cell_length * self.cell_width # digital elevation model (m) self.input_dem = pcr.readmap(self.model_setup['dem_file_name']) # before entering the initial part, save the current working direcory self.script_directory = os.getcwd()
def estimate_bottom_of_bank_storage(self): # influence zone depth (m) influence_zone_depth = 0.50 # bottom_elevation > flood_plain elevation - influence zone bottom_of_bank_storage = self.dem_floodplain - influence_zone_depth #~ # bottom_elevation > river bed #~ bottom_of_bank_storage = pcr.max(self.dem_riverbed, bottom_of_bank_storage) # bottom_elevation > its downstream value bottom_of_bank_storage = pcr.max(bottom_of_bank_storage, \ pcr.cover(pcr.downstream(self.lddMap, bottom_of_bank_storage), bottom_of_bank_storage)) # bottom_elevation >= 0.0 (must be higher than sea level) bottom_of_bank_storage = pcr.max(0.0, bottom_of_bank_storage) # reducing noise bottom_of_bank_storage = pcr.max(bottom_of_bank_storage,\ pcr.windowaverage(bottom_of_bank_storage, 3.0 * pcr.clone().cellSize())) # bottom_elevation < dem_average bottom_of_bank_storage = pcr.min(bottom_of_bank_storage, self.dem_average) bottom_of_bank_storage = pcr.cover(bottom_of_bank_storage, self.dem_average) # TODO: Check again this concept. # TODO: We may want to improve this concept - by incorporating the following # - smooth bottom_elevation # - upstream areas in the mountainous regions and above perrenial stream starting points may also be drained (otherwise water will accumulate) # - bottom_elevation > minimum elevation that is estimated from the maximum of S3 from the PCR-GLOBWB simulation return bottom_of_bank_storage
def estimate_bottom_of_bank_storage(self): # influence zone depth (m) # TODO: Define this one as part of influence_zone_depth = 5.0 # bottom_elevation > flood_plain elevation - influence zone bottom_of_bank_storage = self.dem_floodplain - influence_zone_depth # reducing noise (so we will not introduce unrealistic sinks) # TODO: Define the window size as part of the configuration/ini file bottom_of_bank_storage = pcr.max(bottom_of_bank_storage,\ pcr.windowaverage(bottom_of_bank_storage, 3.0 * pcr.clone().cellSize())) # bottom_elevation > river bed bottom_of_bank_storage = pcr.max(self.dem_riverbed, bottom_of_bank_storage) # reducing noise by comparing to its downstream value (so we will not introduce unrealistic sinks) bottom_of_bank_storage = pcr.max(bottom_of_bank_storage, \ (bottom_of_bank_storage + pcr.cover(pcr.downstream(self.lddMap, bottom_of_bank_storage), bottom_of_bank_storage))/2.) # bottom_elevation >= 0.0 (must be higher than sea level) bottom_of_bank_storage = pcr.max(0.0, bottom_of_bank_storage) # bottom_elevation < dem_average (this is to drain overland flow) bottom_of_bank_storage = pcr.min(bottom_of_bank_storage, self.dem_average) bottom_of_bank_storage = pcr.cover(bottom_of_bank_storage, self.dem_average) # TODO: Check again this concept. # TODO: We may want to improve this concept - by incorporating the following # - smooth bottom_elevation # - upstream areas in the mountainous regions and above perrenial stream starting points may also be drained (otherwise water will accumulate) # - bottom_elevation > minimum elevation that is estimated from the maximum of S3 from the PCR-GLOBWB simulation return bottom_of_bank_storage
def _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 _getIndex(self, cellId): """ returns the cell index of a sample location """ nrCells = pcraster.clone().nrRows() * pcraster.clone().nrCols() found = False cell = 1 while found == False: if cell > nrCells: raise RuntimeError("Could not find a cell with the index number {}".format(cellId)) value = pcraster.cellvalue(self._spatialId, cell) if value[0] == cellId and value[1] == True: break cell += 1 return cell
def set_recharge_package(self, \ gwRecharge, gwAbstraction, gwAbstractionReturnFlow = 0.0): # Note: We ignored the latter as MODFLOW should capture this part as well. logger.info("Set the recharge package based on the given recharge, abstraction and abstraction return flow fields.") # specify the recharge package # + recharge/capillary rise (unit: m/day) from PCR-GLOBWB # - groundwater abstraction (unit: m/day) from PCR-GLOBWB # + return flow of groundwater abstraction (unit: m/day) from PCR-GLOBWB net_recharge = gwRecharge - gwAbstraction + \ gwAbstractionReturnFlow # - correcting values (considering MODFLOW lat/lon cell properties) # and pass them to the RCH package net_RCH = pcr.cover(net_recharge * self.cellAreaMap/(pcr.clone().cellSize()*pcr.clone().cellSize()), 0.0) net_RCH = pcr.cover(pcr.ifthenelse(pcr.abs(net_RCH) < 1e-20, 0.0, net_RCH), 0.0) self.pcr_modflow.setRecharge(net_RCH, 1)
def _getIndex(self, cellId): """ returns the cell index of a sample location """ nrCells = pcraster.clone().nrRows() * pcraster.clone().nrCols() found = False cell = 1 while found == False: if cell > nrCells: raise RuntimeError( "Could not find a cell with the index number {}".format( cellId)) value = pcraster.cellvalue(self._spatialId, cell) if value[0] == cellId and value[1] == True: break cell += 1 return cell
def initiate_modflow(self): logger.info("Initializing pcraster modflow.") # initialise self.pcr_modflow = None self.pcr_modflow = pcr.initialise(pcr.clone()) # grid specification - one layer model top = self.dem_average bottom = top - self.totalGroundwaterThickness self.pcr_modflow.createBottomLayer(bottom, top) # specification for the boundary condition (IBOUND, BAS package) # - active cells only in landmask # - constant head for outside the landmask ibound = pcr.ifthen(self.landmask, pcr.nominal(1)) ibound = pcr.cover(ibound, pcr.nominal(-1)) self.pcr_modflow.setBoundary(ibound, 1) # specification for conductivities (BCF package) horizontal_conductivity = self.kSatAquifer # unit: m/day # set the minimum value for transmissivity; (Deltares's default value: 10 m2/day) minimimumTransmissivity = 10. horizontal_conductivity = pcr.max(minimimumTransmissivity, \ horizontal_conductivity * self.totalGroundwaterThickness) / self.totalGroundwaterThickness vertical_conductivity = horizontal_conductivity # dummy values, as one layer model is used self.pcr_modflow.setConductivity(00, horizontal_conductivity, \ vertical_conductivity, 1) # specification for storage coefficient # - correction due to the usage of lat/lon coordinates primary = pcr.cover(self.specificYield * self.cellAreaMap/(pcr.clone().cellSize()*pcr.clone().cellSize()), 0.0) primary = pcr.max(1e-20, primary) secondary = primary # dummy values as we used layer type 00 self.pcr_modflow.setStorage(primary, secondary, 1) # set drain package self.set_drain_package()
def __init__(self,cloneMapFile,attribute=None,cellSizeInArcMinutes=None): # cloneMap # - the cloneMap must be at 5 arc min resolution cloneMap = pcr.readmap(cloneMapFile) cloneMap = pcr.boolean(1.0) # properties of the clone map # - number of rows and columns self.nrRows = np.round(pcr.clone().nrRows()) self.nrCols = np.round(pcr.clone().nrCols()) # - upper right coordinate, unit: arc degree ; must be integer (without decimals) self.minLongitude = np.round(pcr.clone().west() , 0) self.maxLatitude = np.round(pcr.clone().north(), 0) # - cell resolution, unit: arc degree self.cellSize = pcr.clone().cellSize() if cellSizeInArcMinutes != None: self.cellSize = cellSizeInArcMinutes / 60.0 # - lower right coordinate, unit: arc degree ; must be integer (without decimals) self.maxLongitude = np.round(self.minLongitude + self.cellSize*self.nrCols, 0) self.minLatitude = np.round(self.maxLatitude - self.cellSize*self.nrRows, 0) # latitudes and longitudes for netcdf files latMin = self.minLatitude + self.cellSize / 2 latMax = self.maxLatitude - self.cellSize / 2 lonMin = self.minLongitude + self.cellSize / 2 lonMax = self.maxLongitude - self.cellSize / 2 self.longitudes = np.arange(lonMin,lonMax+self.cellSize, self.cellSize) self.latitudes= np.arange(latMax,latMin-self.cellSize,-self.cellSize) # netCDF format and attributes: self.format = 'NETCDF4' self.attributeDictionary = {} if attribute == None: self.attributeDictionary['institution'] = "None" self.attributeDictionary['title' ] = "None" self.attributeDictionary['description'] = "None" else: self.attributeDictionary = attribute
def updateNetNC(ncFile, dem): """Updates the Netnode_z variable in a fm '_net.nc' netCDF file Input: ncFile : *_net.nc file that describes the netnodes of the computational grid dem : pcraster object with new terrain heights at the location of the measures """ ds = netCDF4.Dataset(ncFile, 'a') xcoords = ds.variables['NetNode_x'][:] ycoords = ds.variables['NetNode_y'][:] zcoords = ds.variables['NetNode_z'][:] #-update the z-values and sync with netCDF file on disk newZ = [] nrCols = pcr.clone().nrCols() nrRows = pcr.clone().nrRows() for cnt in xrange(len(xcoords)): x, y, z = xcoords[cnt], ycoords[cnt], zcoords[cnt] row, col = pcr_coord(x, y) if col > nrCols: zMeasure, validCell = z, False elif row <= 0: zMeasure, validCell = z, False else: zMeasure, validCell = pcr.cellvalue(dem, row, col) if validCell == True: newZ.append(zMeasure) else: newZ.append(z) ds.variables['NetNode_z'][:] = np.array(newZ) ds.sync ds.close() del ds return newZ
def relocation(self, reloc_area): """Sum up the cost and st.dev of dike relocation.""" reloc_area = pcr.cover(pcr.boolean(reloc_area), pcr.boolean(0)) buffer_m = 1.5 * pcr.clone().cellSize( ) # buffer 1 cell in 8 directions reloc_buffered = pcr.spreadmaxzone(reloc_area, 0, 1, buffer_m) reloc_length = pcr.ifthen(reloc_buffered, self.dike_length) cost_spatial = 0.001 * reloc_length * self.dike_reloc_distr.mean std_spatial = 0.001 * reloc_length * self.dike_reloc_distr.stddev area = pcr.ifthen(reloc_area, pcr.boolean(1)) cost = area_total_value(cost_spatial, area) std = area_total_value(std_spatial, area) return cost, std
def __init__(self, model_setup): # In this part ("__init__"), we initiate pcraster frameworks and set the clone map. # initiate pcraster dynamic and monte carlo frameworks DynamicModel.__init__(self) MonteCarloModel.__init__(self) # make model_setup available for the entire method self.model_setup = model_setup # set the clone map based on DEM self.clone_map = self.model_setup['dem_file_name'] pcr.setclone(self.clone_map) # - landmask - needed if we want to mask out some areas/cells self.landmask = pcr.defined(pcr.readmap(self.clone_map)) # output folder self.output_folder = self.model_setup['output_folder'] # initiate a netcdf writer self.netcdf_writer = output_netcdf_writer.OutputNetCDF(pcr.clone())
def plot(raster, title='', hover=None): #geoviews.extension('bokeh') # casting should not be necessary... np_raster = _get_raster(pcraster.scalar(raster)) minx = pcraster.clone().west() maxy = pcraster.clone().north() maxx = minx + pcraster.clone().nrCols() * pcraster.clone().cellSize() miny = maxy - pcraster.clone().nrRows() * pcraster.clone().cellSize() extent = (minx, maxx, miny, maxy) img = hv.Image(np_raster, bounds=extent) if hover is None: hover = ['hover'] else: hover = [hover] s = pcraster.clone().nrCols() / pcraster.clone().nrRows() width = 770 if raster.dataType() == pcraster.Scalar: return img.options(cmap='viridis', tools=hover, aspect=s, colorbar=True, frame_width=width, toolbar="above").relabel(title) else: return img.options(cmap='flag', tools=hover, aspect=s, frame_width=width, toolbar="above").relabel(title)
def __init__(self, iniItems, landmask): object.__init__(self) # cloneMap, temporary directory, absolute path for input directory, landmask self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask # configuration from the ini file self.iniItems = iniItems # topography properties: read several variables from the netcdf file for var in ['dem_minimum','dem_maximum','dem_average','dem_standard_deviation',\ 'slopeLength','orographyBeta','tanslope',\ 'dzRel0000','dzRel0001','dzRel0005',\ 'dzRel0010','dzRel0020','dzRel0030','dzRel0040','dzRel0050',\ 'dzRel0060','dzRel0070','dzRel0080','dzRel0090','dzRel0100']: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['topographyNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # channel properties: read several variables from the netcdf file for var in [ 'lddMap', 'cellAreaMap', 'gradient', 'bankfull_width', 'bankfull_depth', 'dem_floodplain', 'dem_riverbed' ]: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['channelNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # minimum channel width minimum_channel_width = 0.1 self.bankfull_width = pcr.max(minimum_channel_width, self.bankfull_width) #~ # cell fraction if channel water reaching the flood plan # NOT USED #~ self.flood_plain_fraction = self.return_innundation_fraction(pcr.max(0.0, self.dem_floodplain - self.dem_minimum)) # coefficient of Manning self.manningsN = vos.readPCRmapClone(self.iniItems.modflowParameterOptions['manningsN'],\ self.cloneMap,self.tmpDir,self.inputDir) # minimum channel gradient minGradient = 0.00005 self.gradient = pcr.max(minGradient, pcr.cover(self.gradient, minGradient)) # correcting lddMap self.lddMap = pcr.ifthen(pcr.scalar(self.lddMap) > 0.0, self.lddMap) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) # channelLength = approximation of channel length (unit: m) # This is approximated by cell diagonal. cellSizeInArcMin = np.round(pcr.clone().cellSize() * 60.) verticalSizeInMeter = cellSizeInArcMin * 1852. self.channelLength = ((self.cellAreaMap/verticalSizeInMeter)**(2)+\ (verticalSizeInMeter)**(2))**(0.5) # option for lakes and reservoir self.onlyNaturalWaterBodies = False if self.iniItems.modflowParameterOptions[ 'onlyNaturalWaterBodies'] == "True": self.onlyNaturalWaterBodies = True # groundwater linear recession coefficient (day-1) ; the linear reservoir concept is still being used to represent fast response flow # particularly from karstic aquifer in mountainous regions self.recessionCoeff = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'recessionCoeff', self.cloneMap) self.recessionCoeff = pcr.cover(self.recessionCoeff, 0.00) self.recessionCoeff = pcr.min(1.0000, self.recessionCoeff) # if 'minRecessionCoeff' in iniItems.modflowParameterOptions.keys(): minRecessionCoeff = float( iniItems.modflowParameterOptions['minRecessionCoeff']) else: minRecessionCoeff = 1.0e-4 # This is the minimum value used in Van Beek et al. (2011). self.recessionCoeff = pcr.max(minRecessionCoeff, self.recessionCoeff) # aquifer saturated conductivity (m/day) self.kSatAquifer = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'kSatAquifer', self.cloneMap) self.kSatAquifer = pcr.cover(self.kSatAquifer, pcr.mapmaximum(self.kSatAquifer)) self.kSatAquifer = pcr.max(0.010, self.kSatAquifer) self.kSatAquifer *= 0.001 # aquifer specific yield (dimensionless) self.specificYield = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'specificYield', self.cloneMap) self.specificYield = pcr.cover(self.specificYield, pcr.mapmaximum(self.specificYield)) self.specificYield = pcr.max( 0.010, self.specificYield ) # TODO: TO BE CHECKED: The resample process of specificYield self.specificYield = pcr.min(1.000, self.specificYield) # estimate of thickness (unit: m) of accesible groundwater totalGroundwaterThickness = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['estimateOfTotalGroundwaterThicknessNC'],\ 'thickness', self.cloneMap) # extrapolation totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, 0.0) # # set minimum thickness minimumThickness = pcr.scalar(float(\ self.iniItems.modflowParameterOptions['minimumTotalGroundwaterThickness'])) totalGroundwaterThickness = pcr.max(minimumThickness, totalGroundwaterThickness) # # set maximum thickness: 250 m. maximumThickness = 250. self.totalGroundwaterThickness = pcr.min(maximumThickness, totalGroundwaterThickness) # river bed resistance (unit: day) self.bed_resistance = 1.0 # option to ignore capillary rise self.ignoreCapRise = True if self.iniItems.modflowParameterOptions['ignoreCapRise'] == "False": self.ignoreCapRise = False # initiate old style reporting # TODO: remove this! self.initiate_old_style_groundwater_reporting(iniItems)
def initiate_modflow(self): logger.info("Initializing pcraster modflow.") # initialise self.pcr_modflow = None self.pcr_modflow = pcr.initialise(pcr.clone()) # grid specification - two layer model top_layer_2 = self.dem_average # - thickness of layer 1 is at least 10% of totalGroundwaterThickness # TODO: Change this using Inge's thickness of confining layer. bottom_layer_2 = self.dem_average - 0.10 * self.totalGroundwaterThickness # - thickness of layer 1 should be until 5 m below the river bed bottom_layer_2 = pcr.min(self.dem_riverbed - 5.0, bottom_layer_2) # - make sure that the minimum thickness of layer 2 is at least 5.0 m thickness_of_layer_2 = pcr.max(5.0, top_layer_2 - bottom_layer_2) bottom_layer_2 = top_layer_2 - thickness_of_layer_2 # - thickness of layer 1 is at least 5.0 m thickness_of_layer_1 = pcr.max( 5.0, self.totalGroundwaterThickness - thickness_of_layer_2) bottom_layer_1 = bottom_layer_2 - thickness_of_layer_1 self.pcr_modflow.createBottomLayer(bottom_layer_1, bottom_layer_2) self.pcr_modflow.addLayer(top_layer_2) # specification for the boundary condition (IBOUND, BAS package) # - active cells only in landmask # - constant head for outside the landmask ibound = pcr.ifthen(self.landmask, pcr.nominal(1)) ibound = pcr.cover(ibound, pcr.nominal(-1)) self.pcr_modflow.setBoundary(ibound, 1) # upper layer self.pcr_modflow.setBoundary(ibound, 2) # lower layer # specification for conductivities (BCF package) horizontal_conductivity = self.kSatAquifer # unit: m/day # set the minimum value for transmissivity; (Deltares's default value: 10 m2/day) minimimumTransmissivity = 10. # - layer 2 (upper layer) horizontal_conductivity_layer_2 = pcr.max(minimimumTransmissivity, \ horizontal_conductivity * thickness_of_layer_2) / thickness_of_layer_2 vertical_conductivity_layer_2 = pcr.min(self.kSatAquifer, 0.00000000000000005) * self.cellAreaMap/\ (pcr.clone().cellSize()*pcr.clone().cellSize()) self.pcr_modflow.setConductivity(00, horizontal_conductivity_layer_2, \ vertical_conductivity_layer_2, 2) # - layer 1 (lower layer) horizontal_conductivity_layer_1 = pcr.max(minimimumTransmissivity, \ horizontal_conductivity * thickness_of_layer_1) / thickness_of_layer_1 vertical_conductivity_layer_1 = vertical_conductivity_layer_2 # dummy values self.pcr_modflow.setConductivity(00, horizontal_conductivity_layer_1, \ vertical_conductivity_layer_1, 1) # specification for storage coefficient # - correction due to the usage of lat/lon coordinates primary = pcr.cover( self.specificYield * self.cellAreaMap / (pcr.clone().cellSize() * pcr.clone().cellSize()), 0.0) primary = pcr.max(1e-20, primary) secondary = primary # dummy values as we used layer type 00 self.pcr_modflow.setStorage(primary, secondary, 1) self.pcr_modflow.setStorage(primary, secondary, 2) # set drain package self.set_drain_package()
import pcraster import pcraster.moc dataPath = "../../Mldd/demo" pcraster.setclone(os.path.join(dataPath, "DemIn")) timeIncrement = 10 nrParticles = 5 raster = pcraster.readmap(os.path.join(dataPath, "DemIn")) initialConcentration = (raster / raster) + 2.5 effectivePorosity = raster storageCoefficient = raster moc = pcraster.moc.initialise( pcraster.clone(), timeIncrement, nrParticles, initialConcentration, effectivePorosity, storageCoefficient ) flux = raster flowX = raster flowY = raster longitudinalDispersionCoefficient = raster transverseDispersionCoefficient = raster hydraulicHead = raster saturatedThickness = raster concentration, particlesPerCell = moc.transport( flux, flowX, flowY, longitudinalDispersionCoefficient,
import pcraster import pcraster.moc dataPath = "../../Mldd/demo" pcraster.setclone(os.path.join(dataPath, "DemIn")) timeIncrement = 10 nrParticles = 5 raster = pcraster.readmap(os.path.join(dataPath, "DemIn")) initialConcentration = (raster / raster) + 2.5 effectivePorosity = raster storageCoefficient = raster moc = pcraster.moc.initialise(pcraster.clone(), timeIncrement, nrParticles, initialConcentration, effectivePorosity, storageCoefficient) flux = raster flowX = raster flowY = raster longitudinalDispersionCoefficient = raster transverseDispersionCoefficient = raster hydraulicHead = raster saturatedThickness = raster concentration, particlesPerCell = moc.transport(flux, flowX, flowY, longitudinalDispersionCoefficient, transverseDispersionCoefficient, hydraulicHead, saturatedThickness) changeInConcentration = (raster / raster) + 1.5
def __init__( self, netcdffile, logger, starttime, timesteps, EPSG="EPSG:4326", timestepsecs=86400, metadata={}, zlib=True, Format="NETCDF4", maxbuf=25, least_significant_digit=None, ): """ Under construction """ self.EPSG = EPSG self.zlib = zlib self.Format = Format self.least_significant_digit = least_significant_digit def date_range(start, end, timestepsecs): r = int( (end + dt.timedelta(seconds=timestepsecs) - start).total_seconds() / timestepsecs ) return [start + dt.timedelta(seconds=(timestepsecs * i)) for i in range(r)] self.logger = logger # Do not allow a max buffer larger than the number of timesteps self.maxbuf = maxbuf if timesteps >= maxbuf else timesteps self.ncfile = netcdffile self.timesteps = timesteps rows = pcr.clone().nrRows() cols = pcr.clone().nrCols() cellsize = pcr.clone().cellSize() yupper = pcr.clone().north() xupper = pcr.clone().west() x = pcr.pcr2numpy(pcr.xcoordinate(pcr.boolean(pcr.cover(1.0))), np.nan)[0, :] y = pcr.pcr2numpy(pcr.ycoordinate(pcr.boolean(pcr.cover(1.0))), np.nan)[:, 0] # Shift one timestep as we output at the end # starttime = starttime + dt.timedelta(seconds=timestepsecs) end = starttime + dt.timedelta(seconds=timestepsecs * (self.timesteps - 1)) timeList = date_range(starttime, end, timestepsecs) self.timestepbuffer = np.zeros((self.maxbuf, len(y), len(x))) self.bufflst = {} self.buffdirty = False globmetadata.update(metadata) prepare_nc( self.ncfile, timeList, x, y, globmetadata, logger, Format=self.Format, EPSG=EPSG, zlib=self.zlib, least_significant_digit=self.least_significant_digit, )
pcr.report(river_length_low_resolution, "resampled_low_resolution_channel_length.map") # - river width river_width_file_name = "/projects/0/dfguu/users/edwin/data/data_for_glofris_downscaling/input_data/maps_05min/bankfull_width.map" river_width_low_resolution = vos.readPCRmapClone(river_width_file_name, \ clone_map_file, \ tmp_folder, \ None, False, None, False) river_width_low_resolution = pcr.ifthen(landmask, river_width_low_resolution) river_width_low_resolution = pcr.cover(river_width_low_resolution, 0.0) pcr.report(river_width_low_resolution, "resampled_low_resolution_bankfull_width.map") # clone at high resolution (e.g. 30 arc-seconds) msg = "Set the clone map at high resolution." logger.info(msg) num_of_rows = np.round(pcr.clone().nrRows() * 10 , 2) num_of_cols = np.round(pcr.clone().nrCols() * 10 , 2) x_min = np.round(pcr.clone().west() , 2) y_max = np.round(pcr.clone().north() , 2) cell_length = pcr.clone().cellSize() / 10. # set the cell length manually cell_length = '0.00833333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333' # # - make the map using 'mapattr' command cmd = 'mapattr -s -R ' + str(num_of_rows) + \ ' -C ' + str(num_of_cols) + \ ' -B -P yb2t ' + \ ' -x ' + str(x_min) + \ ' -y ' + str(y_max) + \ ' -l ' + str(cell_length) + \ ' clone_high_resolution.map'
# Test script to check everything works. import os import sys sys.path.append(os.environ["PCRTREE2"] + "/bin") import pcraster import pcraster.mldd dataPath = "../demo" 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)))
# upscaling to 30 arc-min: for i_file in range(0, len(file_names)): # read extreme value map file_name = file_names[i_file] extreme_value_05min_map = pcr.readmap(file_name) # upscale it to 30 arcmin resolution: extreme_value_30min_map_at_5min_resolution = pcr.areatotal(extreme_value_05min_map, cell_ids_30min) # convert it to 30 arcmin numpy array and store it in a dictionary extreme_value_30min_at_5min_resolution = pcr.pcr2numpy(extreme_value_30min_map_at_5min_resolution, vos.MV) resampling_factor = np.int(30. / (5.)) extreme_value_30min[file_name] = vos.regridToCoarse(extreme_value_30min_at_5min_resolution, resampling_factor, "max", vos.MV) # save numpy arrays to 30 arcmin maps # # - set the clone map to 30 arcmin resolution num_of_rows = np.round(pcr.clone().nrRows() / resampling_factor , 2) num_of_cols = np.round(pcr.clone().nrCols() / resampling_factor , 2) x_min = np.round(pcr.clone().west() , 2) y_max = np.round(pcr.clone().north() , 2) cell_length = pcr.clone().cellSize() * resampling_factor # set the cell length manually cell_length = '0.5' # # - make the map using 'mapattr' command cmd = 'mapattr -s -R ' + str(num_of_rows) + \ ' -C ' + str(num_of_cols) + \ ' -B -P yb2t ' + \ ' -x ' + str(x_min) + \ ' -y ' + str(y_max) + \ ' -l ' + str(cell_length) + \ ' clone_low_resolution_30min.map'
import pcraster import pcraster.moc dataPath = "../../Mldd/demo" pcraster.setclone(os.path.join(dataPath, "DemIn")) timeIncrement = 10 nrParticles = 5 raster = pcraster.readmap(os.path.join(dataPath, "DemIn")) initialConcentration = (raster / raster) + 2.5 effectivePorosity = raster storageCoefficient = raster moc = pcraster.moc.initialise(pcraster.clone(), timeIncrement, nrParticles, initialConcentration, effectivePorosity, storageCoefficient) flux = raster flowX = raster flowY = raster longitudinalDispersionCoefficient = raster transverseDispersionCoefficient = raster hydraulicHead = raster saturatedThickness = raster concentration, particlesPerCell = moc.transport( flux, flowX, flowY, longitudinalDispersionCoefficient, transverseDispersionCoefficient, hydraulicHead, saturatedThickness)
def writenet(flag, inputmap, netfile, timestep, value_standard_name, value_long_name, value_unit, fillval, startdate, flag_time=True): """ write a netcdf stack flag: integer. If 0 it means write a NEW file (!) FIXME omg inputmap: a PCRaster 2D array netfile: output netcdf filename timestep: """ p = Path(netfile) netfile = Path(p.parent) / Path( '{}.nc'.format(p.name) if not p.name.endswith('.nc') else p.name) prefix = os.path.splitext(netfile.name)[0] cutmap = CutMap.instance() row = np.abs(cutmap.cuts[3] - cutmap.cuts[2]) col = np.abs(cutmap.cuts[1] - cutmap.cuts[0]) if flag == 0: nf1 = Dataset(netfile, 'w', format='NETCDF4_CLASSIC') # general Attributes nf1.history = 'Created ' + xtime.ctime(xtime.time()) nf1.Conventions = 'CF-1.4' nf1.Source_Software = 'Lisvap' nf1.source = 'Lisvap output maps' metadata_ncdf = NetcdfMetadata.instance() # Dimension spatial_dims = tuple( [c for c in ('y', 'lat', 'x', 'lon') if c in metadata_ncdf]) for dim_name, dim_size in zip(spatial_dims, [row, col]): nf1.createDimension(dim_name, dim_size) coord = nf1.createVariable(dim_name, 'f8', (dim_name, )) for i in metadata_ncdf[dim_name]: if i != '_FillValue': # to avoid AttributeError ("_FillValue attribute must be set when variable is created") when writing output nc attributes setattr(coord, i, metadata_ncdf[dim_name][i]) if flag_time: nf1.createDimension('time', None) time = nf1.createVariable('time', 'f8', ('time', )) time.standard_name = 'time' time.units = 'days since %s' % startdate.strftime( '%Y-%m-%d %H:%M:%S.0') time.calendar = 'gregorian' value = nf1.createVariable(prefix, fillval, ('time', ) + spatial_dims, zlib=True) else: value = nf1.createVariable(prefix, fillval, spatial_dims, zlib=True) value.standard_name = value_standard_name value.long_name = value_long_name value.units = value_unit # value.esri_pe_string='PROJCS["ETRS_1989_LAEA",GEOGCS["GCS_ETRS_1989",DATUM["D_ETRS_1989",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Azimuthal_Equal_Area"],PARAMETER["false_easting",4321000.0],PARAMETER["false_northing",3210000.0],PARAMETER["central_meridian",10.0],PARAMETER["latitude_of_origin",52.0],UNIT["Meter",1.0]]' # projection if 'laea' in metadata_ncdf: proj = nf1.createVariable('laea', 'i4') proj.grid_mapping_name = 'lambert_azimuthal_equal_area' # FIXME magic numbers proj.false_easting = 4321000.0 proj.false_northing = 3210000.0 proj.longitude_of_projection_origin = 10.0 proj.latitude_of_projection_origin = 52.0 proj.semi_major_axis = 6378137.0 proj.inverse_flattening = 298.257223563 proj.proj4_params = "+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs" proj.EPSG_code = "EPSG:3035" if 'lambert_azimuthal_equal_area' in metadata_ncdf: proj = nf1.createVariable('laea', 'i4') for i in metadata_ncdf['lambert_azimuthal_equal_area']: setattr(proj, i, metadata_ncdf['lambert_azimuthal_equal_area'][i]) """ EUROPE proj.grid_mapping_name='lambert_azimuthal_equal_area' proj.false_easting=4321000.0 proj.false_northing=3210000.0 proj.longitude_of_projection_origin = 10.0 proj.latitude_of_projection_origin = 52.0 proj.semi_major_axis = 6378137.0 proj.inverse_flattening = 298.257223563 proj.proj4_params = "+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs" proj.EPSG_code = "EPSG:3035" """ # Fill variables cell = pcraster.clone().cellSize() xl = pcraster.clone().west() + cell / 2 xr = xl + col * cell yu = pcraster.clone().north() - cell / 2 yd = yu - row * cell lats = np.arange(yu, yd, -cell) lons = np.arange(xl, xr, cell) nf1.variables[spatial_dims[0]][:] = lats nf1.variables[spatial_dims[1]][:] = lons if 'pr' in metadata_ncdf and 'esri_pe_string' in metadata_ncdf['pr']: value.esri_pe_string = metadata_ncdf['pr']['esri_pe_string'] else: nf1 = Dataset(netfile, 'a') mapnp = numpy_operations.pcr2numpy(inputmap, np.nan) if flag_time: nf1.variables['time'][flag] = timestep - 1 nf1.variables[prefix][flag, :, :] = mapnp else: nf1.variables[prefix][:, :] = mapnp nf1.close()
def __init__(self, iniItems, landmask): object.__init__(self) # cloneMap, temporary directory for the resample process, temporary directory for the modflow process, absolute path for input directory, landmask self.cloneMap = iniItems.cloneMap self.tmpDir = iniItems.tmpDir self.tmp_modflow_dir = iniItems.tmp_modflow_dir self.inputDir = iniItems.globalOptions['inputDir'] self.landmask = landmask # configuration from the ini file self.iniItems = iniItems # topography properties: read several variables from the netcdf file for var in ['dem_minimum','dem_maximum','dem_average','dem_standard_deviation',\ 'slopeLength','orographyBeta','tanslope',\ 'dzRel0000','dzRel0001','dzRel0005',\ 'dzRel0010','dzRel0020','dzRel0030','dzRel0040','dzRel0050',\ 'dzRel0060','dzRel0070','dzRel0080','dzRel0090','dzRel0100']: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['topographyNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # channel properties: read several variables from the netcdf file for var in ['lddMap','cellAreaMap','gradient','bankfull_width', 'bankfull_depth','dem_floodplain','dem_riverbed']: vars(self)[var] = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['channelNC'], \ var, self.cloneMap) vars(self)[var] = pcr.cover(vars(self)[var], 0.0) # minimum channel width minimum_channel_width = 0.5 # TODO: Define this one in the configuration file self.bankfull_width = pcr.max(minimum_channel_width, self.bankfull_width) #~ # cell fraction if channel water reaching the flood plan # NOT USED YET #~ self.flood_plain_fraction = self.return_innundation_fraction(pcr.max(0.0, self.dem_floodplain - self.dem_minimum)) # coefficient of Manning self.manningsN = vos.readPCRmapClone(self.iniItems.modflowParameterOptions['manningsN'],\ self.cloneMap,self.tmpDir,self.inputDir) # minimum channel gradient minGradient = 0.00005 # TODO: Define this one in the configuration file self.gradient = pcr.max(minGradient, pcr.cover(self.gradient, minGradient)) # correcting lddMap self.lddMap = pcr.ifthen(pcr.scalar(self.lddMap) > 0.0, self.lddMap) self.lddMap = pcr.lddrepair(pcr.ldd(self.lddMap)) # channelLength = approximation of channel length (unit: m) # This is approximated by cell diagonal. cellSizeInArcMin = np.round(pcr.clone().cellSize()*60.) # FIXME: This one will not work if you use the resolution: 0.5, 1.5, 2.5 arc-min verticalSizeInMeter = cellSizeInArcMin*1852. horizontalSizeInMeter = self.cellAreaMap/verticalSizeInMeter self.channelLength = ((horizontalSizeInMeter)**(2)+\ (verticalSizeInMeter)**(2))**(0.5) # option for lakes and reservoir self.onlyNaturalWaterBodies = False if self.iniItems.modflowParameterOptions['onlyNaturalWaterBodies'] == "True": self.onlyNaturalWaterBodies = True # groundwater linear recession coefficient (day-1) ; the linear reservoir concept is still being used to represent fast response flow # particularly from karstic aquifer in mountainous regions self.recessionCoeff = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'recessionCoeff', self.cloneMap) self.recessionCoeff = pcr.cover(self.recessionCoeff,0.00) self.recessionCoeff = pcr.min(1.0000,self.recessionCoeff) # if 'minRecessionCoeff' in iniItems.modflowParameterOptions.keys(): minRecessionCoeff = float(iniItems.modflowParameterOptions['minRecessionCoeff']) else: minRecessionCoeff = 1.0e-4 # This is the minimum value used in Van Beek et al. (2011). self.recessionCoeff = pcr.max(minRecessionCoeff,self.recessionCoeff) # aquifer saturated conductivity (m/day) self.kSatAquifer = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'kSatAquifer', self.cloneMap) self.kSatAquifer = pcr.cover(self.kSatAquifer,pcr.mapmaximum(self.kSatAquifer)) self.kSatAquifer = pcr.max(0.001,self.kSatAquifer) # TODO: Define the minimum value as part of the configuration file # aquifer specific yield (dimensionless) self.specificYield = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['groundwaterPropertiesNC'],\ 'specificYield', self.cloneMap) self.specificYield = pcr.cover(self.specificYield,pcr.mapmaximum(self.specificYield)) self.specificYield = pcr.max(0.010,self.specificYield) # TODO: TO BE CHECKED: The resample process of specificYield self.specificYield = pcr.min(1.000,self.specificYield) # TODO: Define the minimum value as part of the configuration file # estimate of thickness (unit: m) of accesible groundwater totalGroundwaterThickness = vos.netcdf2PCRobjCloneWithoutTime(self.iniItems.modflowParameterOptions['estimateOfTotalGroundwaterThicknessNC'],\ 'thickness', self.cloneMap) # extrapolation totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.0)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness,\ pcr.windowaverage(totalGroundwaterThickness, 1.5)) totalGroundwaterThickness = pcr.cover(totalGroundwaterThickness, 0.0) # # set minimum thickness minimumThickness = pcr.scalar(float(\ self.iniItems.modflowParameterOptions['minimumTotalGroundwaterThickness'])) totalGroundwaterThickness = pcr.max(minimumThickness, totalGroundwaterThickness) # # set maximum thickness: 250 m. # TODO: Define this one as part of the ini file maximumThickness = 250. self.totalGroundwaterThickness = pcr.min(maximumThickness, totalGroundwaterThickness) # TODO: Define the maximum value as part of the configuration file # surface water bed thickness (unit: m) bed_thickness = 0.1 # TODO: Define this as part of the configuration file # surface water bed resistance (unit: day) bed_resistance = bed_thickness / (self.kSatAquifer) minimum_bed_resistance = 1.0 # TODO: Define this as part of the configuration file self.bed_resistance = pcr.max(minimum_bed_resistance,\ bed_resistance,) # option to ignore capillary rise self.ignoreCapRise = True if self.iniItems.modflowParameterOptions['ignoreCapRise'] == "False": self.ignoreCapRise = False # a variable to indicate if the modflow has been called or not self.modflow_has_been_called = False # list of the convergence criteria for HCLOSE (unit: m) # - Deltares default's value is 0.001 m # check this value with Jarno self.criteria_HCLOSE = [0.001, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] self.criteria_HCLOSE = sorted(self.criteria_HCLOSE) # list of the convergence criteria for RCLOSE (unit: m3) # - Deltares default's value for their 25 and 250 m resolution models is 10 m3 # check this value with Jarno cell_area_assumption = verticalSizeInMeter * float(pcr.cellvalue(pcr.mapmaximum(horizontalSizeInMeter),1)[0]) self.criteria_RCLOSE = [10., 10.* cell_area_assumption/(250.*250.), 10.* cell_area_assumption/(25.*25.)] self.criteria_RCLOSE = sorted(self.criteria_RCLOSE) # initiate the index for HCLOSE and RCLOSE self.iteration_HCLOSE = 0 self.iteration_RCLOSE = 0 # initiate old style reporting # TODO: remove this! self.initiate_old_style_groundwater_reporting(iniItems)
def get_initial_heads(self): if self.iniItems.modflowTransientInputOptions['groundwaterHeadIni'] != "None": # using a pre-defined groundwater head described in the ini/configuration file self.groundwaterHead = vos.readPCRmapClone(self.modflowTransientInputOptions['groundwaterHeadIni'],\ self.cloneMap, self.tmpDir, self.inputDir) else: # using the digital elevation model as the initial head self.groundwaterHead = self.dem_average # calculate/simulate a steady state condition (until the modflow converge) self.modflow_converged = False while self.modflow_converged == False: self.modflow_simulation("steady-state", self.groundwaterHead, None,1,1,self.criteria_HCLOSE[self.iteration_HCLOSE],\ self.criteria_RCLOSE[self.iteration_RCLOSE]) # extrapolating the calculated heads for areas/cells outside the landmask (to remove isolated cells) # TODO: Using Deltares's trick to remove isolated cells. # # - the calculate groundwater head within the landmask region self.groundwaterHead = pcr.ifthen(self.landmask, self.groundwaterHead) # - keep the ocean values (dem <= 0.0) - this is in order to maintain the 'behaviors' of sub marine groundwater discharge self.groundwaterHead = pcr.cover(self.groundwaterHead, pcr.ifthen(self.dem_average <= 0.0, self.dem_average)) # - extrapolation # self.groundwaterHead = pcr.cover(self.groundwaterHead, pcr.windowaverage(self.groundwaterHead, 3.*pcr.clone().cellSize())) self.groundwaterHead = pcr.cover(self.groundwaterHead, pcr.windowaverage(self.groundwaterHead, 5.*pcr.clone().cellSize())) self.groundwaterHead = pcr.cover(self.groundwaterHead, self.dem_average) # TODO: Define the window sizes as part of the configuration file. # after having the initial head, set the following variable to True to indicate the first month of the model simulation self.firstMonthOfSimulation = True