def __init__(self,suntanspath,**kwargs): self.__dict__.update(kwargs) Grid.__init__(self,suntanspath) # Initialise the trisearch object self.tsearch = GridSearch(self.xp,self.yp,self.cells)
def __init__(self,suntanspath,timestep): self.suntanspath = suntanspath Grid.__init__(self,suntanspath) # Get the time timestep self.time = datetime.strptime(timestep,'%Y%m%d.%H%M%S') # Initialise the output array self.initArrays()
def writeNC(self,outfile,dv=None): """ Export the results to a netcdf file """ from suntans_ugrid import ugrid from netCDF4 import Dataset # Fill in the depths with zero #if not self.__dict__.has_key('dv'): if dv==None: self.dv = np.zeros((self.Nc,)) else: self.dv = dv if not self.__dict__.has_key('Nk'): self.Nk = self.Nkmax*np.ones((self.Nc,)) Grid.writeNC(self,outfile) # write the time variable t= othertime.SecondsSince(self.time) self.create_nc_var(outfile,'time', ugrid['time']['dimensions'], ugrid['time']['attributes']) # Create the other variables self.create_nc_var(outfile,'eta',('time','Nc'),{'long_name':'Sea surface elevation','units':'metres','coordinates':'time yv xv'}) self.create_nc_var(outfile,'uc',('time','Nk','Nc'),{'long_name':'Eastward water velocity component','units':'metre second-1','coordinates':'time z_r yv xv'}) self.create_nc_var(outfile,'vc',('time','Nk','Nc'),{'long_name':'Northward water velocity component','units':'metre second-1','coordinates':'time z_r yv xv'}) self.create_nc_var(outfile,'salt',('time','Nk','Nc'),{'long_name':'Salinity','units':'ppt','coordinates':'time z_r yv xv'}) self.create_nc_var(outfile,'temp',('time','Nk','Nc'),{'long_name':'Water temperature','units':'degrees C','coordinates':'time z_r yv xv'}) self.create_nc_var(outfile,'agec',('time','Nk','Nc'),{'long_name':'Age concentration','units':''}) self.create_nc_var(outfile,'agealpha',('time','Nk','Nc'),{'long_name':'Age alpha parameter','units':'seconds','coordinates':'time z_r yv xv'}) self.create_nc_var(outfile,'agesource',('Nk','Nc'),\ {'long_name':'Age source grid cell (>0 = source)',\ 'units':'','coordinates':'z_r yv xv'}) # now write the variables... nc = Dataset(outfile,'a') nc.variables['time'][:]=t nc.variables['eta'][:]=self.h nc.variables['uc'][:]=self.uc nc.variables['vc'][:]=self.vc nc.variables['salt'][:]=self.S nc.variables['temp'][:]=self.T nc.variables['agec'][:]=self.agec nc.variables['agealpha'][:]=self.agealpha nc.variables['agesource'][:]=self.agesource nc.close() print 'Initial condition file written to: %s'%outfile
def __init__(self,suntanspath,basename,numprocs,outvars=None): tic=time.clock() print '########################################################' print ' Initializing python SUNTANS NetCDF joining script...' print '########################################################' # Step 1) Read the main grid #print 'Loading suntans grid points...' Grid.__init__(self,suntanspath) self.numprocs = numprocs self.suntanspath=suntanspath self.basename=basename # Step 2) Build a dictionary of the variable names, attributes and dimensions in the first ncfile proc=0 self.ncfile='%s/%s.%d'%(suntanspath,basename,proc) self.variables, self.dims, self.globalatts = nc_info(self.ncfile) # If outvars have been set only write those variables and the grid variables if not outvars==None: self.outvars=gridvars+outvars self.outvars=outvars newvariables = [vv for vv in self.variables if vv['Name'] in self.outvars] self.variables = newvariables # Step 3) Set the dimension sizes based on the original grid self.dims['Nc']=self.Nc self.dims['Np']=self.xp.shape[0] self.dims['Ne']=self.edges.shape[0] self.dims['time']=None # Sets to unlimited # Open each input file and load the cell and edge pointers that go from # the "localgrid" to the "maingrid" self.ncin=[] self.cptr=[] # cell pointer self.eptr=[] # edge pointer for n in range(numprocs): ncfile='%s/%s.%d'%(suntanspath,basename,n) # Open all of the input files and get some info self.ncin.append(Dataset(ncfile,'r')) ncvars= self.ncin[n].variables self.nt = len(ncvars['time'][:]) self.cptr.append(ncvars['mnptr'][:]) self.eptr.append(ncvars['eptr'][:])
def on_load_grid(self, event): dlg = wx.DirDialog( self, message="Open SUNTANS grid from folder...", defaultPath=os.getcwd(), style= wx.DD_DEFAULT_STYLE) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() # Initialise the class self.flash_status_message("Opening SUNTANS grid from folder: %s" % path) Grid.__init__(self,path) # Plot the Grid self.axes,self.collection = self.plotmesh(ax=self.axes,edgecolors='y') # redraw the figure self.canvas.draw()
def __init__(self,x,y,z,cells,nfaces,mask,method='nearest',grdfile=None): self.method=method # Initialise the trisearch array GridSearch.__init__(self,x,y,cells,nfaces=nfaces,force_inside=True) if self.method == 'linear': Grid.__init__(self,grdfile) self.datatmp = np.zeros(mask.shape,dtype=np.double) self.z = np.sort(z) self.z[-1]=10.0 # Set the surface layer to large self.Nkmax = z.size-1 self.mask3d = mask self.maskindex = -1*np.ones(self.mask3d.shape,dtype=np.int32) rr=0 for ii in range(self.mask3d.shape[0]): for jj in range(self.mask3d.shape[1]): if self.mask3d[ii,jj]: self.maskindex[ii,jj]=rr rr+=1
#### Nkmax = 1 # number of layers r = 1.30 # vertical stretching parameter ### # Free surface function ### def calc_fs(xv): a = 0.0 Lx = 10000. return -xv*a/Lx ################################# # Load the model grid and bathymetry into the object 'grd' and initialise the vertical spacing ################################## grd = Grid(suntanspath) ########## # Modify the boundary markers and create the boundary condition file ########## # This changes the edge types based on the polygons in the shapefile #modifyBCmarker(suntanspath,bcpolygonfile) # Modify the left and right edges and convert to type 2 hgrd = grd.convert2hybrid() grd.mark[grd.mark>0]=1 # reset all edges to land # convert edges +/- half a grid cell from the edge dx = hgrd.dg.max()
""" Plots a hybrid grid """ from sunpy import Grid import matplotlib.pyplot as plt ### # #ncfile = 'rundata/Plume.nc.0' ncfile = 'grids/hybrid' sun = Grid(ncfile) plt.figure() #sun.plot() sun.plotmesh(facecolors='none') plt.show()
r = 1.30 # vertical stretching parameter ### # Free surface function ### def calc_fs(xv): a = 0.0 Lx = 10000. return -xv * a / Lx ################################# # Load the model grid and bathymetry into the object 'grd' and initialise the vertical spacing ################################## grd = Grid(suntanspath) ########## # Modify the boundary markers and create the boundary condition file ########## # This changes the edge types based on the polygons in the shapefile #modifyBCmarker(suntanspath,bcpolygonfile) # Modify the left and right edges and convert to type 2 hgrd = grd.convert2hybrid() grd.mark[grd.mark > 0] = 1 # reset all edges to land # convert edges +/- half a grid cell from the edge dx = hgrd.dg.max() xmin = hgrd.xe.min() + dx / 4.0
p_lcc[:,1] = yp np.savetxt(base + pname, p_lcc) else: p_lcc = np.loadtxt(base + pname) cname = 'cells.dat' if not os.path.exists(base + pname): c_utm = np.loadtxt(base + 'cells_utm.dat') c_lcc = c_utm.copy() lonp, latp = p(c_utm[:,0], c_utm[:,1], inverse=True) xp, yp = basemap_gulf(lonp, latp) c_lcc[:,0] = xp c_lcc[:,1] = yp np.savetxt(base + cname, c_lcc) else: c_lcc = np.loadtxt(base + cname) grd = Grid(base) if doshelf: xr_shelf, yr_shelf = basemap_gulf(g_shelf.variables['lon_rho'][:], g_shelf.variables['lat_rho'][:]) maskr = g_shelf.variables['mask_rho'][:] xr2_shelf = np.ma.masked_where(maskr==0,xr_shelf) yr2_shelf = np.ma.masked_where(maskr==0,yr_shelf) if dogulf: g_gulf = netCDF.Dataset('http://barataria.tamu.edu:8080/thredds/dodsC/fmrc/roms/out/ROMS_Output_Feature_Collection_Aggregation_best.ncd') xr_gulf2 = np.ma.masked_where(maskr_gulf==0,xr_gulf) yr_gulf2 = np.ma.masked_where(maskr_gulf==0,yr_gulf) ### Gulf
class sundriver(object): """ Driver class for generating SUNTANS input files """ # Switches to generate bathymetry, boundary, meteorology and initial condition input files makebathy=False makebnd=False makewinds=False makeinitial=False ### # General options ### # Grid projection variables convert2utm=False CS='NAD83' utmzone=51 isnorth=False vdatum = 'MSL' # Verical grid options Nkmax = 1 # number of layers r = 1.01 # vertical stretching parameter setconstantdepth=False # Option to set constant depth H0 = 10.0 # Constant depth ### # Bathymetry interpolation options ### depthfile = None depthmax=0.1 interpmethod='idw' # Interpolation method: 'nn', 'idw', 'kriging', 'griddata' plottype='mpl' # Type of plot: 'mpl', 'vtk2' or 'vtk3' shapefieldname='contour' # name of shapefile attribute with contour data scalefac = 1.0 # Interpolation options NNear=3 # Interpolate to nodes then take maximum depth for cell interpnodes=False # IF interpmethod = 'idw' p = 1.0 # power for inverse distance weighting # IF interpmethod = 'kriging' varmodel = 'spherical' nugget = 0.1 sill = 0.8 vrange = 250.0 # Smoothing options smooth=True smoothmethod='kriging' # USe kriging or idw for smoothing smoothnear=4 # No. of points to use for smoothing # Option to adjust channel depths using a shapefile adjust_depths=False channel_shpfile='channel.shp' #### # Open boundary options #### opt_bcseg = 'constant' # Segment boundary condition option: 'constant' or 'file' opt_bctype2 = 'constant' # Type 2 boundary condition option: 'constant' or 'file' opt_bctype3 = 'constant' # Type 3 boundary condition option: 'constant', ,'file','OTIS', 'ROMS', 'ROMSOTIS','ROMSFILE', 'OTISFILE', 'ROMSOTISFILE' modifyedges = False # Option to modify the boundary edges bcpolygonfile = None # Shape file with fields 'marker' and 'edge_id' bcfile = 'SUNTANS_BC.nc' # Input boundary condition file # IF opt_bcseg = 'consant Q0 = 100.0 # m3/s # IF opt_bctype2/opt_bctype3 = 'constant' T0 = 0 # Open boundary background temperature S0 = 0 # Open boundary background salinity # IF opt_bctype3 = 'file' or 'ROMSFILE' waterlevelstationID = None # IF opt_bctype3 = 'harmonic' amp = 0.25 omega = 2*PI/(24.0*3600.0) # IF opt_bctype2 = 'file' TairstatationID = None # Filter type (waterlevel) filttype='low' cutoff=3600.0 # Air temp cuttoff (bctype2 = file) tairfilttype = 'low' taircutoff = 14.0*24.0*3600.0 #### # Atmospheric input options #### opt_met = 'constant' # Met file creation options: 'constant' metfile = 'SUNTANS_MetForcing.nc' # IF opt_met = 'consant' Uwind = 0.0 Vwind = 5.0 RH = 50.0 Tair = 30.0 Pair = 1010.0 rain = 0.0 cloud = 0.0 #### # Initial condition options #### opt_ic = 'constant', 'depth_profile', 'ROMS' , 'SUNTANS' icfile = 'SUNTANS_IC.nc' icfilterdx = 0.0 # Filtering length scale # Age source term polygon agesourcepoly = None # Initial condition temperature and salinity T0ic = 0 S0ic = 0 ### # Input file names ### romsfile = None suntansicfile = None otisfile = None dbasefile = None # Use ROMS u,v and eta useROMSuv=False useROMSeta=False # Use OTIS u & v useOTISuv=False ############################ def __init__(self,**kwargs): self.__dict__.update(kwargs) def __call__(self,suntanspath,starttime,endtime,dt): self.suntanspath = suntanspath self.starttime = starttime self.endtime = endtime self.dt = dt # Step through and perform each step self._makebathy() if self.makebnd: self._makebnd() if self.makeinitial: self._makeinitial() if self.makewinds: self._makewinds() print '###########\n Completed generating input files. Check text for errors!!!!\n##########' def _makebathy(self): """ Loads the grid object and interpolates the depths """ # Interpolate the depths onto the grid if self.makebathy: if self.depthfile == None: raise Exception, 'need to set "depthfile" parameter' else: print 'Interpolation depths onto grid from file:\n%s'%self.depthfile D = DepthDriver(self.depthfile,interpmethod=self.interpmethod,\ plottype=self.plottype,NNear=self.NNear,\ p=self.p,varmodel=self.varmodel,nugget=self.nugget,sill=self.sill,vrange=self.vrange,\ convert2utm=self.convert2utm,utmzone=self.utmzone,isnorth=self.isnorth,vdatum=self.vdatum,\ shapefieldname=self.shapefieldname,\ smooth=self.smooth,smoothmethod=self.smoothmethod,smoothnear=self.smoothnear) D(self.suntanspath,depthmax=self.depthmax,interpnodes=self.interpnodes,\ scalefac=self.scalefac) self.grd = D.grd # Now go through and adjust the channel depths from a shapefile if self.adjust_depths: self.grd = adjust_channel_depth(self.grd,self.channel_shpfile) # Write the depths to file print 'Writing depths.dat (again)...' self.grd.saveBathy(self.suntanspath+'/depths.dat-voro') print 'Data (re-)saved to %s.'%self.suntanspath+'/depths.dat-voro' print 'SUNTANS depths saved to: %s'%(self.suntanspath+'/depths.dat-voro') elif self.setconstantdepth: print 'Using constant depth (%6.2f m)...'%self.H0 self.grd = Grid(self.suntanspath) self.grd.dv = np.zeros_like(self.grd.xv) self.grd.dv[:] = self.H0 else: print 'Loading grid from folder:\n%s'%self.suntanspath # Load the grid self.grd = Grid(self.suntanspath) # Load the depth data into the grid object self.grd.loadBathy(self.suntanspath+'/depths.dat-voro') zmax = np.abs(self.grd.dv.max()) print 'Calculating vertical grid spacing for Nk = %d, r = %1.3f, %6.3f...'%(self.Nkmax,self.r,zmax) # Set up the vertical coordinates dz = self.grd.calcVertSpace(self.Nkmax,self.r,zmax) self.grd.setDepth(dz) # Save vertspace.dat self.grd.saveVertspace(self.suntanspath+'/vertspace.dat') # Write cells.dat and edges.dat to ensure they are in the right format print 'Overwriting cells.dat and edges.dat to ensure format consistency.' self.grd.saveCells(self.suntanspath+'/cells.dat') self.grd.saveEdges(self.suntanspath+'/edges.dat') def _makebnd(self): """ Generate boundary condition files """ if self.modifyedges: modifyBCmarker(self.suntanspath,self.bcpolygonfile) #Load the boundary object from the grid bnd = Boundary(self.suntanspath,(self.starttime,self.endtime,self.dt)) ### # Segment (flux) boundaries ### if self.opt_bcseg == 'constant': print 'Setting %d boundary segments to discharge of %6.3f m3/s'%(bnd.Nseg,self.Q0) bnd.boundary_Q[:]=self.Q0 elif self.opt_bcseg == 'file': print 'Loading river segment data from file...\n' for ii, ID in enumerate(bnd.segp): print 'Loading discahrge data for boundary segment (%d) StationID: %d...'%(ii,ID) ts = timeseries.loadDBstation(self.dbasefile,ID,'discharge',timeinfo=(self.starttime,self.endtime,self.dt),\ filttype=self.filttype,cutoff=self.cutoff) bnd.boundary_Q[:,ii]=ts.y.copy() else: print 'Unknown option: opt_bcseg = %s. Not setting boundary segment data.'%self.opt_bcseg ### # Type-3 boundaries ### self.useROMS = False self.useOTIS = False self.useFILE = False self.useOTISFILE = False if self.opt_bctype3=='constant': print 'Setting constant type-3 boundary conditions...' print 'Setting salinity = %f, temperature = %f'%(self.S0,self.T0) bnd.S[:]=self.S0 bnd.T[:]=self.T0 elif self.opt_bctype3=='depth_profile': print 'Setting type-3 boundary T/S from profile...' self.loadTSprofile() for ii in range(0,bnd.N3): bnd.T[0,:,ii] = self.Tz bnd.S[0,:,ii] = self.Sz elif self.opt_bctype3 in ('ROMS'): self.useROMS = True elif self.opt_bctype3 in ('OTIS'): self.useOTIS = True elif self.opt_bctype3 in ('file'): self.useFILE = True elif self.opt_bctype3 in ('ROMSOTIS'): self.useROMS = True self.useOTIS = True elif self.opt_bctype3 in ('ROMSFILE'): self.useROMS = True self.useFILE = True elif self.opt_bctype3 in ('OTISFILE'): self.useOTISFILE = True elif self.opt_bctype3 in ('ROMSOTISFILE'): self.useOTISFILE = True self.useROMS = True else: print 'Unknown option: opt_bctype3 = %s. Not setting type-3 boundaries.'%self.opt_bctype3 if self.useROMS: bnd.roms2boundary(self.romsfile,setUV=self.useROMSuv,seth=self.useROMSeta) if self.useOTIS: bnd.otis2boundary(self.otisfile,setUV=self.useOTISuv) if self.useOTISFILE: bnd.otisfile2boundary(self.otisfile,self.dbasefile,self.waterlevelstationID,setUV=self.useOTISuv) if self.useFILE: ID = self.waterlevelstationID print 'Loading waterlevel onto all type-3 points from stationID: %d...'%(ID) ts = timeseries.loadDBstation(self.dbasefile,ID,'waterlevel',timeinfo=(self.starttime,self.endtime,self.dt),\ filttype=self.filttype,cutoff=self.cutoff) for ii in range(bnd.N3): bnd.h[:,ii] += ts.y.copy() ### # Type-2 boundaries ### self.useFILE2 = False if self.opt_bctype2 == 'constant': print 'Setting constant type-2 boundary conditions...' print 'Setting salinity = %f, temperature = %f'%(self.S0,self.T0) bnd.boundary_S[:]=self.S0 bnd.boundary_T[:]=self.T0 elif self.opt_bctype2 == 'file': print 'Using file for type-2 boundary condition (temperature only)' print 'Setting salinity = %f'%(self.S0) bnd.boundary_S[:]=self.S0 self.useFILE2 = True else: print 'Unknown option: opt_bctype2 = %s. Not setting type-2 boundaries.'%self.opt_bctype3 if self.useFILE2: ID = self.TairstationID print 'Loading air temperature onto all type-2 points from stationID: %s...'%(ID) ts = timeseries.loadDBstation(self.dbasefile,ID,'Tair',timeinfo=(self.starttime,self.endtime,self.dt),\ filttype=self.tairfilttype,cutoff=self.taircutoff) for ii in range(bnd.N2): for kk in range(bnd.Nk): bnd.boundary_T[:,kk,ii] += ts.y.copy() # Write to netcdf bnd.write2NC(self.suntanspath+'/'+self.bcfile) def _makeinitial(self): """ Generate initial conditions """ # Initialise the class IC = InitialCond(self.suntanspath,self.starttime) if self.opt_ic=='constant': print 'Setting constant initial conditions...' print 'Setting salinity = %f, temperature = %f'%(self.S0ic,self.T0ic) IC.T[:]=self.T0ic IC.S[:]=self.S0ic elif self.opt_ic=='depth_profile': print 'Setting depth-varying initial conditions...' self.loadTSprofile() for ii in range(0,IC.Nc): IC.T[0,:,ii] = self.Tz IC.S[0,:,ii] = self.Sz elif self.opt_ic=='ROMS': print 'Setting initial conditions from ROMS model output...' IC.roms2ic(self.romsfile,setUV=self.useROMSuv,seth=self.useROMSeta,interpmethod='idw',NNear=5,p=2) #interpmethod=self.interpmethod,NNear=self.NNear,p=self.p,\ #varmodel=self.varmodel,nugget=self.nugget,sill=self.sill,\ #vrange=self.vrange) elif self.opt_ic=='SUNTANS': IC.suntans2ic(self.suntansicfile,setUV=self.useROMSuv,seth=self.useROMSeta) else: print 'Unknown option: opt_ic = %s. Not setting initial conditions.'%self.opt_ic # Filter the variables in space if self.icfilterdx>0: IC.filteric(self.icfilterdx) # Set the age source term from a polygon if not self.agesourcepoly==None: print 'Setting age source term with shapefile: %s...'%self.agesourcepoly IC.setAgeSource(self.agesourcepoly) # Write the initial condition file IC.writeNC(self.suntanspath+'/'+self.icfile,dv=self.grd.dv) def _makewinds(self): """ Generate a metfile """ if self.opt_met=='constant': print 'Setting constant met forcing with: Uwind = %6.2f\nVwind = %6.2f\nTair = %6.2f\nPair = %6.2f\nRH = %6.2f\nrain = %6.2f\ncloud = %6.2f\n'\ %(self.Uwind,self.Vwind,self.Tair,self.Pair,self.RH,self.cloud,self.rain) xpt = self.grd.xv.mean() ypt = self.grd.yv.mean() zpt = 10.0 # Load the met object met = SunMet(xpt,ypt,zpt,(self.starttime,self.endtime,self.dt)) # Fill the arrays met.Uwind.data[:] = self.Uwind met.Vwind.data[:] = self.Vwind met.Tair.data[:] = self.Tair met.Pair.data[:] = self.Pair met.RH.data[:] = self.RH met.cloud.data[:] = self.cloud met.rain.data[:] = self.rain met.write2NC(self.suntanspath+'/'+self.metfile) else: print 'Unknown option: opt_met=%s. Failed to generate a metfile'%self.opt_met def loadTSprofile(self): """ Loads a temperature salinity profile from a matfile and interpolates onto the grid depths """ try: data=io.loadmat(self.TSprofilefile) z = data['depth'].ravel() temp = data['temp_profile'].ravel() salt = data['salt_profile'].ravel() FT = interp1d(z,temp,kind=3) self.Tz=FT(self.grd.z_r) FS = interp1d(z,salt,kind=3) self.Sz=FS(self.grd.z_r) except: print 'Warning could not find variables: "depth", "temp_profile" or "salt_profile" in file:\n%s'%self.TSprofilefile self.Tz = self.T0 self.Sz = self.S0
""" Calculates the dual of a grid """ from sunpy import Grid import matplotlib.pyplot as plt import numpy as np from hybridgrid import HybridGrid ### ncfile = 'grid' outpath = 'grid/hex' sun = Grid(ncfile) sun.neigh = sun.neigh.astype(int) # Load the data into a hybrid grid class grd = HybridGrid(sun.xp, sun.yp, sun.cells, nfaces=sun.nfaces) grd.create_dual_grid(minfaces=5, outpath=outpath) sun = Grid(outpath) plt.figure() sun.plotmesh(facecolors='none', linewidths=0.2) plt.plot(sun.xv, sun.yv, 'm.') plt.figure() sun.plothist()
""" Example of how to plot the grid and open boundaries in python """ from sunpy import Grid import matplotlib.pyplot as plt from maptools import Polygon2GIS grdfolder = 'rundata/' kmlfile = 'gis/sfbay_suntans_grid.kml' shpfile = 'gis/sfbay_suntans_grid.shp' utmzone = 10 # Load the grid into a sunpy object sun = Grid(grdfolder) # save the grid to a google earth file #Polygon2GIS(sun.xy,kmlfile,utmzone) # the grid polygons are stored in the 'xy' attribute # save the grid to a gis shapefile #Polygon2GIS(sun.xy,shpfile,utmzone) # Plot the mesh plt.figure() sun.plotmesh() # Plot the boundary conditions sun.plotBC() plt.show()
Calculates the dual of a grid """ from sunpy import Grid import matplotlib.pyplot as plt import numpy as np from hybridgrid import HybridGrid ### ncfile = 'grids/tri' outpath='grids/hex' sun = Grid(ncfile) sun.neigh = sun.neigh.astype(int) # Load the data into a hybrid grid class grd = HybridGrid(sun.xp,sun.yp,sun.cells,nfaces=sun.nfaces) grd.create_dual_grid(minfaces=5,outpath=outpath) sun = Grid(outpath) #plt.figure() #sun.plotmesh(facecolors='none',linewidths=0.2) #plt.plot(sun.xv,sun.yv,'m.') # #
###################################################################### # End of input variables - do not change anything below here. ###################################################################### # Interpolate the depths onto the grid if makebathy: D = DepthDriver(depthfile,interpmethod=interpmethod,plottype=plottype,NNear=NNear,\ p=p,varmodel=varmodel,nugget=nugget,sill=sill,vrange=vrange,convert2utm=convert2utm,\ utmzone=utmzone,isnorth=isnorth,vdatum=vdatum,smooth=smooth,smoothmethod=smoothmethod,\ smoothnear=smoothnear) D(suntanspath, depthmax=depthmax) # Load the model grid and bathymetry into the object 'grd' and initialise the vertical spacing grd = Grid(suntanspath) # Load the depth data into the grid object grd.loadBathy(suntanspath + '/depths.dat-voro') zmax = np.abs(grd.dv.min()) # Set up the vertical coordinates dz = grd.calcVertSpace(Nkmax, r, zmax) grd.setDepth(dz) # Save vertspace.dat grd.saveVertspace(suntanspath + '/vertspace.dat') # Modify the boundary markers and create the boundary condition file if makebnd: # This changes the edge types based on the polygons in the shapefile
def _makebathy(self): """ Loads the grid object and interpolates the depths """ # Interpolate the depths onto the grid if self.makebathy: if self.depthfile == None: raise Exception, 'need to set "depthfile" parameter' else: print 'Interpolation depths onto grid from file:\n%s' % self.depthfile D = DepthDriver(self.depthfile,interpmethod=self.interpmethod,\ plottype=self.plottype,NNear=self.NNear,\ p=self.p,varmodel=self.varmodel,nugget=self.nugget,sill=self.sill,vrange=self.vrange,\ convert2utm=self.convert2utm,utmzone=self.utmzone,isnorth=self.isnorth,vdatum=self.vdatum,\ shapefieldname=self.shapefieldname,\ smooth=self.smooth,smoothmethod=self.smoothmethod,smoothnear=self.smoothnear) D(self.suntanspath,depthmax=self.depthmax,interpnodes=self.interpnodes,\ scalefac=self.scalefac) self.grd = D.grd # Now go through and adjust the channel depths from a shapefile if self.adjust_depths: self.grd = adjust_channel_depth(self.grd, self.channel_shpfile) # Write the depths to file print 'Writing depths.dat (again)...' self.grd.saveBathy(self.suntanspath + '/depths.dat-voro') print 'Data (re-)saved to %s.' % self.suntanspath + '/depths.dat-voro' print 'SUNTANS depths saved to: %s' % (self.suntanspath + '/depths.dat-voro') elif self.setconstantdepth: print 'Using constant depth (%6.2f m)...' % self.H0 self.grd = Grid(self.suntanspath) self.grd.dv = np.zeros_like(self.grd.xv) self.grd.dv[:] = self.H0 else: print 'Loading grid from folder:\n%s' % self.suntanspath # Load the grid self.grd = Grid(self.suntanspath) # Load the depth data into the grid object self.grd.loadBathy(self.suntanspath + '/depths.dat-voro') zmax = np.abs(self.grd.dv.max()) print 'Calculating vertical grid spacing for Nk = %d, r = %1.3f, %6.3f...' % ( self.Nkmax, self.r, zmax) # Set up the vertical coordinates dz = self.grd.calcVertSpace(self.Nkmax, self.r, zmax) self.grd.setDepth(dz) # Save vertspace.dat self.grd.saveVertspace(self.suntanspath + '/vertspace.dat') # Write cells.dat and edges.dat to ensure they are in the right format print 'Overwriting cells.dat and edges.dat to ensure format consistency.' self.grd.saveCells(self.suntanspath + '/cells.dat') self.grd.saveEdges(self.suntanspath + '/edges.dat')
def GridParticles(grdfile,dx,dy,nz,xypoly=None,splitvec=1): """ Returns the locations of particles on a regular grid inside of suntans grid Inputs: grdfile - netcdf filename containing the suntans grid dx,dy - resolution in x and y component respectively. nz - number of particles in the vertical. Particles are arranged in sigma layers. xypoly - [optional] coordinates of an additional bounding polygon [Nx2 array] """ # Load the suntans grid sun = Grid(grdfile) # Load a trisearch object tri = GridSearch(sun.xp,sun.yp,sun.cells,nfaces=sun.nfaces,verbose=False) if xypoly == None: xlims = [sun.xlims[0],sun.xlims[1]] ylims = [sun.ylims[0],sun.ylims[1]] else: xlims = [xypoly[:,0].min(),xypoly[:,0].max()] ylims = [xypoly[:,1].min(),xypoly[:,1].max()] # Construct a 2D mesh of particles x = np.arange(xlims[0],xlims[1],dx) y = np.arange(ylims[0],ylims[1],dy) X,Y = np.meshgrid(x,y) X=X.ravel() Y=Y.ravel() # Check which particles are inside the grid cellind = tri(X,Y) mask = cellind!=-1 # Check which particles are also inside of the polygon if not xypoly == None: inpoly = inpolygon(np.vstack((X,Y)).T,xypoly) mask = operator.and_(mask,inpoly) xout = X[mask] yout = Y[mask] nx = xout.shape[0] # Construct the 3D mesh xout = np.repeat(xout.reshape((nx,1)),nz,axis=1) yout = np.repeat(yout.reshape((nx,1)),nz,axis=1) zout = np.linspace(0.05,0.95,nz) zout = np.repeat(zout.reshape((nz,1)),nx,axis=1) zout *= -sun.dv[cellind[mask]] zout = zout.T xout = xout.ravel() yout = yout.ravel() zout = zout.ravel() # Rearrange the vectors to avoid clustering (this helps even the MPI workload) #xout_split=[] #yout_split=[] #zout_split=[] #for start in range(splitvec): # xout_split.append(xout[start::splitvec]) # yout_split.append(yout[start::splitvec]) # zout_split.append(zout[start::splitvec]) #xout = np.hstack(xout_split) #yout = np.hstack(yout_split) #zout = np.hstack(zout_split) return xout, yout, zout
""" Calculates the dual of a grid """ from sunpy import Grid import matplotlib.pyplot as plt import numpy as np from hybridgrid import HybridGrid ### ncfile = 'grids/tri' outpath = 'grids/hex' sun = Grid(ncfile) sun.neigh = sun.neigh.astype(int) # Load the data into a hybrid grid class grd = HybridGrid(sun.xp, sun.yp, sun.cells, nfaces=sun.nfaces) grd.create_dual_grid(minfaces=5, outpath=outpath) sun = Grid(outpath) #plt.figure() #sun.plotmesh(facecolors='none',linewidths=0.2) #plt.plot(sun.xv,sun.yv,'m.') # # #plt.figure() #sun.plothist()
def __init__(self, ncfile): self.ncfile = ncfile Grid.__init__(self, ncfile, gridvars=untrim_gridvars, griddims=untrim_griddims)
###################################################################### # End of input variables - do not change anything below here. ###################################################################### # Interpolate the depths onto the grid if makebathy: D = DepthDriver(depthfile,interpmethod=interpmethod,plottype=plottype,NNear=NNear,\ p=p,varmodel=varmodel,nugget=nugget,sill=sill,vrange=vrange,convert2utm=convert2utm,\ utmzone=utmzone,isnorth=isnorth,vdatum=vdatum,smooth=smooth,smoothmethod=smoothmethod,\ smoothnear=smoothnear) D(suntanspath,depthmax=depthmax) # Load the model grid and bathymetry into the object 'grd' and initialise the vertical spacing grd = Grid(suntanspath) # Load the depth data into the grid object grd.loadBathy(suntanspath+'/depths.dat-voro') zmax = np.abs(grd.dv.min()) # Set up the vertical coordinates dz = grd.calcVertSpace(Nkmax,r,zmax) grd.setDepth(dz) # Save vertspace.dat grd.saveVertspace(suntanspath+'/vertspace.dat') # Modify the boundary markers and create the boundary condition file
def _makebathy(self): """ Loads the grid object and interpolates the depths """ # Interpolate the depths onto the grid if self.makebathy: if self.depthfile == None: raise Exception, 'need to set "depthfile" parameter' else: print 'Interpolation depths onto grid from file:\n%s'%self.depthfile D = DepthDriver(self.depthfile,interpmethod=self.interpmethod,\ plottype=self.plottype,NNear=self.NNear,\ p=self.p,varmodel=self.varmodel,nugget=self.nugget,sill=self.sill,vrange=self.vrange,\ convert2utm=self.convert2utm,utmzone=self.utmzone,isnorth=self.isnorth,vdatum=self.vdatum,\ shapefieldname=self.shapefieldname,\ smooth=self.smooth,smoothmethod=self.smoothmethod,smoothnear=self.smoothnear) D(self.suntanspath,depthmax=self.depthmax,interpnodes=self.interpnodes,\ scalefac=self.scalefac) self.grd = D.grd # Now go through and adjust the channel depths from a shapefile if self.adjust_depths: self.grd = adjust_channel_depth(self.grd,self.channel_shpfile) # Write the depths to file print 'Writing depths.dat (again)...' self.grd.saveBathy(self.suntanspath+'/depths.dat-voro') print 'Data (re-)saved to %s.'%self.suntanspath+'/depths.dat-voro' print 'SUNTANS depths saved to: %s'%(self.suntanspath+'/depths.dat-voro') elif self.setconstantdepth: print 'Using constant depth (%6.2f m)...'%self.H0 self.grd = Grid(self.suntanspath) self.grd.dv = np.zeros_like(self.grd.xv) self.grd.dv[:] = self.H0 else: print 'Loading grid from folder:\n%s'%self.suntanspath # Load the grid self.grd = Grid(self.suntanspath) # Load the depth data into the grid object self.grd.loadBathy(self.suntanspath+'/depths.dat-voro') zmax = np.abs(self.grd.dv.max()) print 'Calculating vertical grid spacing for Nk = %d, r = %1.3f, %6.3f...'%(self.Nkmax,self.r,zmax) # Set up the vertical coordinates dz = self.grd.calcVertSpace(self.Nkmax,self.r,zmax) self.grd.setDepth(dz) # Save vertspace.dat self.grd.saveVertspace(self.suntanspath+'/vertspace.dat') # Write cells.dat and edges.dat to ensure they are in the right format print 'Overwriting cells.dat and edges.dat to ensure format consistency.' self.grd.saveCells(self.suntanspath+'/cells.dat') self.grd.saveEdges(self.suntanspath+'/edges.dat')
""" Updates suntans grid text files to the quad format Edges.dat has an extra column for the 'edge_id' variable """ from sunpy import Grid import os # grdfolder = 'grids/quad/' outfolder = 'rundata/' maxfaces = 4 grd = Grid(grdfolder, MAXFACES=maxfaces) try: os.mkdir(outfolder) except: pass os.system('cp %s/*.dat %s' % (grdfolder, outfolder)) grd.saveEdges(outfolder + '/edges.dat') grd.saveCells(outfolder + '/cells.dat') print 'Saved new grid in: %s' % outfolder
def run(): # Location of TXLA model output loc = 'http://barataria.tamu.edu:8080/thredds/dodsC/NcML/txla_nesting6.nc' # Matt's d = netCDF.MFDataset('tracks/matt/2010-05-*.nc', aggdim='ntrac') p = pyproj.Proj(proj='utm', zone='15') lonm,latm = p(d.variables['xp'][:], d.variables['yp'][:], inverse=True) # want one simulation to have a single set of the starting points d1 = netCDF.MFDataset('tracks/matt/2010-05-23T00.nc', aggdim='ntrac') lonmstart, latmstart = p(d1.variables['xp'][:,0], d1.variables['yp'][:,0], inverse=True) # Kristen's db = netCDF.MFDataset('tracks/galv_b/2010-05-*.nc',aggdim='ntrac') lonb = np.fliplr(db.variables['lonp'][:]) # flip to be forward in time latb = np.fliplr(db.variables['latp'][:]) # flip to be forward in time df = netCDF.MFDataset('tracks/galv_f/2010-05-*.nc',aggdim='ntrac') lonf = df.variables['lonp'][:] latf = df.variables['latp'][:] # Combined lonk = np.concatenate((lonb,lonf),axis=1) latk = np.concatenate((latb,latf),axis=1) grid = tracpy.inout.readgrid(loc) ## Shelf tracks ## # Eliminate drifters in the bay and outside Matt's domain # lonvert = np.array([-94.44896376, -94.38868859, -94.38625664, -94.35380894, # -94.35357294, -94.32114683, -94.32099761, -94.2839534 , # -94.28371841, -94.32073196, -94.32015033, -94.35247582, # -94.35185901, -94.38873039, -94.3886522 , -94.41861373, # -94.41854639, -94.45541454, -94.45530469, -94.52433946, # -94.52422355, -94.59322436, -94.59308138, -94.65976418, # -94.65956549, -94.76770875, -94.76763167, -94.96778311, # -94.96789969, -95.07604071, -95.07642981, -95.17770396, # -95.17810623, -95.2795571 , -95.2798657 , -95.31901876, # -95.3199739 , -95.14404646, -95.14434603, -95.0427632 , # -95.04318363, -95.00854345, -95.00884843, -94.9349127 , # -94.935271 , -94.90060651, -94.90089718, -94.83385365, # -94.83415664, -94.76476871, -94.76501578, -94.72799532, # -94.7285101 , -94.69609675, -94.69634997, -94.62918694, # -94.62940326, -94.59001667, -94.59019564, -94.45345669, -94.44896376]) # latvert = np.array([ 29.51080435, 29.51099607, 29.48073304, 29.48082425, # 29.41424186, 29.41432502, 29.3679228 , 29.36800802, # 29.28529434, 29.28520919, 29.10363677, 29.10355388, # 28.92804192, 28.92793764, 28.90776056, 28.90766817, # 28.89152842, 28.89140532, 28.86720038, 28.85483934, # 28.8326488 , 28.81822849, 28.7940243 , 28.78361653, # 28.75336181, 28.75277136, 28.74268359, 28.74135471, # 28.75345628, 28.75261073, 28.78892442, 28.78805142, # 28.82234232, 28.83349224, 28.85769558, 28.85730671, # 28.92992664, 29.06675435, 29.0929739 , 29.09382103, # 29.13417612, 29.134447 , 29.16470469, 29.16525227, # 29.20358522, 29.20382761, 29.23610029, 29.23654313, # 29.27286272, 29.273285 , 29.30556746, 29.30577777, # 29.37638645, 29.37656202, 29.41287395, 29.41321234, # 29.44751927, 29.44770176, 29.47796222, 29.47850429, 29.51080435]) # # xvert, yvert = grid['basemap'](lonvert, latvert) # # These are the x,y locations for the normal projection, but want to save in lon/lat # # xvert = np.array([422614, 428447, 428671, 431812, 431812, 434953, 434953, 438543, # # 438543, 434953, 434953, 431812, 431812, 428223, 428223, 425306, # # 425306, 421716, 421716, 414986, 414986, 408255, 408255, 401749, # # 401749, 391204, 391204, 371685, 371685, 361140, 361140, 351268, # # 351268, 341397, 341397, 337583, 337583, 354858, 354858, 364730, # # 364730, 368095, 368095, 375275, 375275, 378640, 378640, 385146, # # 385146, 391877, 391877, 395467, 395467, 398608, 398608, 405114, # # 405114, 408928, 408928, 422165, 422614]) # # yvert = np.array([772846, 772846, 769480, 769480, 762076, 762076, 756916, 756916, # # 747718, 747718, 727526, 727526, 708007, 708007, 705763, 705763, # # 703968, 703968, 701276, 699930, 697462, 695891, 693199, 692077, # # 688712, 688712, 687590, 687590, 688936, 688936, 692975, 692975, # # 696789, 698135, 700827, 700827, 708904, 723936, 726852, 726852, # # 731340, 731340, 734705, 734705, 738968, 738968, 742557, 742557, # # 746596, 746596, 750186, 750186, 758038, 758038, 762076, 762076, # # 765891, 765891, 769256, 769256, 772846]) # # xyverts = np.vstack((xvert,yvert)) # verts = np.vstack((lonvert,latvert)) # # Form path # path = Path(verts.T) # # Loop through the drifters as represented by their initial location for lonf,latf # # Establish a set of indices of the drifters that are outside the desired domain # ind = np.zeros(lonf.shape[0]) # for i in xrange(lonf.shape[0]): # if path.contains_point(np.vstack((lonf[i,0],latf[i,0]))): # ind[i] = 1 # # These only contain tracks that go through the starting points of Matt's runs # lonknew = lonk[ind.astype(bool),:] # latknew = latk[ind.astype(bool),:] # Do plot # Find initial points (since this is a backward run) to plot as starting points # moving forward lonki = [] latki = [] for idrift in xrange(lonk.shape[0]): # pdb.set_trace() # print idrift # Find last non-nan and make sure it is in the desired month start time ind3 = ~np.isnan(lonk[idrift,:]) #pdb.set_trace() # only plot if last non-nan (back in time) is in 1 month period # in order to plot the tracks that "started" in the plotted month if np.sum(ind3) > 1: # don't want tracks that start on land # This is for if we care when the drifter stopped # if t[find(ind3)[-1]] >= datetime(year,startMonth,startDay,0) and \ # t[find(ind3)[-1]] <= datetime(year,startMonth+1,startDay,0): # ind2 = ~np.isnan(lonk[idrift,:]) if np.sum(np.isnan(lonk[idrift,:])) > 0 and np.sum(np.isnan(lonk[idrift,:])) < lonk.shape[1]: # if there is a nan # ax.plot(lonk[idrift,find(ind2)[-1]].T,latk[idrift,find(ind2)[-1]].T,'o',color='orange',liidth=.5,label='_nolegend_') lonki.append(lonk[idrift,find(ind3)[0]]) latki.append(latk[idrift,find(ind3)[0]]) else: # ax.plot(lonk[idrift,0].T,latk[idrift,0].T,'o',color='orange',liidth=.5,label='_nolegend_') lonki.append(lonk[idrift,find(ind3)[0]]) latki.append(latk[idrift,find(ind3)[0]]) xki, yki = grid['basemap'](lonki,latki) # Overall shelf tracks # Backward to forward tracpy.plotting.tracks(lonk, latk, 'matt/shelf', grid=grid) plot(xki,yki,'go',alpha=.4) savefig('figures/matt/shelftracks.png',bbox_inches='tight') # Backward to Bay opening only tracpy.plotting.tracks(lonb, latb, 'matt/shelf_backonly', grid=grid) plot(xki,yki,'go',alpha=.4) savefig('figures/matt/shelf_backonlytracks.png',bbox_inches='tight') # Bay forward only tracpy.plotting.tracks(lonf, latf, 'matt/shelf_forwardonly', grid=grid) plot(lonf[:,0],latf[:,0],'go',alpha=.4) savefig('figures/matt/shelf_forwardonlytracks.png',bbox_inches='tight') ## Galveston histograms ## # Smaller basemap parameters. llcrnrlon=-95.6; llcrnrlat=28.4; urcrnrlon=-93.8; urcrnrlat=29.8; loc = 'http://barataria.tamu.edu:8080/thredds/dodsC/NcML/txla_nesting6.nc' smallgrid = tracpy.inout.readgrid(loc, llcrnrlon=llcrnrlon, llcrnrlat=llcrnrlat, urcrnrlat=urcrnrlat, urcrnrlon=urcrnrlon) # Matt histogram tracpy.plotting.hist(lonm, latm, 'matt/matt', grid=smallgrid, which='hexbin', bins=(160,160)) xmstart, ymstart = smallgrid['basemap'](lonmstart,latmstart) f = gcf() ax = f.axes[0] # last axis was for colorbar so grab inital one ax.plot(xmstart,ymstart,'go',alpha=.3) # add grid from sunpy import Grid # suntans code p_utm = np.loadtxt('projects/suntans/points_utm.dat') lonp, latp = p(p_utm[:,0], p_utm[:,1], inverse=True) xp, yp = smallgrid['basemap'](lonp, latp) p_lcc = np.zeros(p_utm.shape) p_lcc[:,0] = xp p_lcc[:,1] = yp np.savetxt('projects/suntans/points.dat', p_lcc) c_utm = np.loadtxt('projects/suntans/cells_utm.dat') c_lcc = c_utm.copy() lonp, latp = p(c_utm[:,0], c_utm[:,1], inverse=True) xp, yp = smallgrid['basemap'](lonp, latp) c_lcc[:,0] = xp c_lcc[:,1] = yp np.savetxt('projects/suntans/cells.dat', c_lcc) grd = Grid('projects/suntans') grd.plotmesh(ax=ax, edgecolors=('lightgrey',), facecolors=('None',), zorder=0) # plt.show() # triang = Triangulation(xp,yp) # f.axes[0].triplot(triang) savefig('figures/matt/matthisthexbin.png',bbox_inches='tight') # Matt tracks tracpy.plotting.tracks(lonm, latm, 'matt/matt', grid=smallgrid) # Shelf: # Need to stop drifters as his domain boundary BUT not from going into the Bay # x and y verts on smallgrid projection, but this projection might change over time # xvertbig = np.array([ 113263.66720431, 119096.66652423, 119320.66686604, # 122461.66678215, 122461.66685854, 125602.66643451, # 125602.66642388, 129192.66658589, 129192.66626941, # 125602.66643373, 125602.66631186, 122461.66719913, # 122461.66712714, 118872.66642492, 118872.66647544, # 115955.66697976, 115955.6668092 , 112365.66628673, # 112365.66670544, 105635.66662346, 105635.66692937, # 98904.66691465, 98904.66683249, 92398.66693207, # 92398.66669606, 81853.66708999, 81853.66694612, # 62334.66648085, 62334.66659896, 51789.66706805, # 51789.66695047, 41917.66679772, 41917.66677504, # 32046.66715647, 32046.66652647, 28232.66691345, # 28232.66655248, 28232.66655248, 97180. , # 113263.66720431]) # yvertbig = np.array([ 133653.2476132 , 133653.24740824, 130287.24684561, # 130287.24661835, 122883.24689633, 122883.24719082, # 117723.24701227, 117723.247473 , 108525.24747157, # 108525.24679182, 88333.24664775, 88333.24703864, # 68814.24678444, 68814.2469479 , 66570.24736787, # 66570.24692043, 64775.24764515, 64775.2469847 , # 62083.24742793, 60737.24763316, 58269.24688878, # 56698.24684586, 54006.24684154, 52884.24719558, # 49519.24754775, 49519.24728893, 48397.24693971, # 48397.24676136, 49743.24761656, 49743.24760865, # 53782.24766385, 53782.24756101, 57596.24732823, # 58942.24741941, 61634.24691447, 61634.24696074, # 69711.24711498, 136328. , 169068. , # 133653.2476132 ]) # lonvertbig, latvertbig = smallgrid['basemap'](xvertbig, yvertbig, inverse=True) lonvertbig = np.array([-94.44896376, -94.38868859, -94.38625664, -94.35380894, -94.35357294, -94.32114683, -94.32099761, -94.2839534 , -94.28371841, -94.32073196, -94.32015033, -94.35247582, -94.35185901, -94.38873039, -94.3886522 , -94.41861373, -94.41854639, -94.45541454, -94.45530469, -94.52433946, -94.52422355, -94.59322436, -94.59308138, -94.65976418, -94.65956549, -94.76770875, -94.76763167, -94.96778311, -94.96789969, -95.07604071, -95.07642981, -95.17770396, -95.17810623, -95.2795571 , -95.2798657 , -95.31901876, -95.3199739 , -95.32790465, -94.61713345, -94.44896376]) latvertbig = np.array([ 29.51080435, 29.51099607, 29.48073304, 29.48082425, 29.41424186, 29.41432502, 29.3679228 , 29.36800802, 29.28529434, 29.28520919, 29.10363677, 29.10355388, 28.92804192, 28.92793764, 28.90776056, 28.90766817, 28.89152842, 28.89140532, 28.86720038, 28.85483934, 28.8326488 , 28.81822849, 28.7940243 , 28.78361653, 28.75336181, 28.75277136, 28.74268359, 28.74135471, 28.75345628, 28.75261073, 28.78892442, 28.78805142, 28.82234232, 28.83349224, 28.85769558, 28.85730671, 28.92992664, 29.52892904, 29.82861514, 29.51080435]) vertsbig = np.vstack((lonvertbig,latvertbig)) # Form path pathbig = Path(vertsbig.T) # # Only use drifters starting where Matt started them # lonfnew = lonf[ind.astype(bool),:] # latfnew = latf[ind.astype(bool),:] # update lonfnew to stop drifters that exit matt's domain (but they can enter bay) for i in xrange(lonf.shape[0]): for t in xrange(lonf.shape[1]): if not pathbig.contains_point(np.vstack((lonf[i,t],latf[i,t]))): lonf[i,t:] = np.nan latf[i,t:] = np.nan break # Shelf histogram tracpy.plotting.hist(lonf, latf, 'matt/kristen', grid=smallgrid, which='hexbin', bins=(160,160)) xf, yf = smallgrid['basemap'](lonf,latf) f = gcf() # plot grid xr = np.ma.masked_where(smallgrid['mask']==0,smallgrid['xr']) yr = np.ma.masked_where(smallgrid['mask']==0,smallgrid['yr']) f.axes[0].plot(xr,yr,xr.T,yr.T,color='lightgrey',zorder=0) # last axis was for colorbar so grab inital one f.axes[0].plot(xf[0:384,0],yf[0:384,0],'go',alpha=.3) # just plot them once savefig('figures/matt/kristenhisthexbin.png',bbox_inches='tight') # Shelf tracks tracpy.plotting.tracks(lonf, latf, 'matt/kristen', grid=smallgrid)
def __init__(self,ncfile): self.ncfile=ncfile Grid.__init__(self,ncfile,gridvars=untrim_gridvars,griddims=untrim_griddims)
def suntans2untrim(ncfile, outfile, tstart, tend, grdfile=None): """ Converts a suntans averages netcdf file into untrim format for use in particle tracking """ #### # Step 1: Load the suntans data object #### sun = Spatial(ncfile, klayer=[-99]) # Calculate some other variables sun.de = sun.get_edgevar(sun.dv, method='min') sun.mark[sun.mark == 5] = 0 sun.mark[sun.mark == 3] = 2 sun.facemark = np.zeros((sun.Nc, ), dtype=np.int) # Update the grad variable from the ascii grid file if supplied if not grdfile == None: print('Updating grid with ascii values...') grd = Grid(grdfile) sun.grad = grd.grad[:, ::-1] ### # Step 2: Write the grid variables to a netcdf file ### nc = Dataset(outfile, 'w', format='NETCDF4_CLASSIC') # Global variable nc.Description = 'UnTRIM history file converted from SUNTANS output' # Write the dimensions for dd in list(untrim_griddims.keys()): if dd == 'time': nc.createDimension(untrim_griddims[dd], 0) elif dd == 'numsides': nc.createDimension(untrim_griddims[dd], sun.maxfaces) else: nc.createDimension(untrim_griddims[dd], sun[dd]) for dd in other_dims: nc.createDimension(dd, other_dims[dd]) ### # Step 3: Initialize all of the grid variables ### def create_nc_var(name, dimensions, attdict,data=None, \ dtype='f8',zlib=False,complevel=0,fill_value=999999.0): tmp=nc.createVariable(name, dtype, dimensions,\ zlib=zlib,complevel=complevel,fill_value=fill_value) for aa in list(attdict.keys()): tmp.setncattr(aa, attdict[aa]) if not data == None: nc.variables[name][:] = data # Make sure the masked cells have a value of -1 mask = sun['cells'].mask.copy() sun['cells'][mask] = FILLVALUE sun['face'][mask] = FILLVALUE for vv in list(untrim_gridvars.keys()): vname = untrim_gridvars[vv] print('Writing grid variable %s (%s)...' % (vname, vv)) if vv == 'time': continue # add dz_min attribute to z_r variable if vv == 'z_r': ugrid[vname]['attributes'].update({'dz_min': 1e-5}) #sun[vv][:]=sun[vv][::-1] sun[vv][:] = sun['z_w'][0:-1][::-1] # Reverse the order of grad(???) if vv == 'grad': sun[vv][:] = sun[vv][:, ::-1] ## Fix one-based indexing #if vv in ['cells','edges','grad']: # mask = sun[vv][:]==-1 # tmp = sun[vv][:]+1 # tmp[mask]=-1 # #sun[vv][:]=sun[vv][:]+1 # create_nc_var(vname,ugrid[vname]['dimensions'],ugrid[vname]['attributes'],\ # data=tmp,dtype=ugrid[vname]['dtype']) create_nc_var(vname,ugrid[vname]['dimensions'],ugrid[vname]['attributes'],\ data=sun[vv],dtype=ugrid[vname]['dtype']) # Initialize the two time variables vname = untrim_gridvars['time'] create_nc_var(vname,ugrid[vname]['dimensions'],ugrid[vname]['attributes'],\ dtype=ugrid[vname]['dtype']) vname = 'Mesh2_data_time_string' create_nc_var(vname,ugrid[vname]['dimensions'],ugrid[vname]['attributes'],\ dtype=ugrid[vname]['dtype']) ### # Step 4: Initialize all of the time-varying variables (but don't write) ### for vname in varnames: print('Creating variable %s...' % (vname)) create_nc_var(vname,ugrid[vname]['dimensions'],ugrid[vname]['attributes'],\ dtype=ugrid[vname]['dtype'],zlib=True,complevel=1,fill_value=999999.) ### # Step 5: Loop through all of the time steps and write the variables ### tsteps = sun.getTstep(tstart, tend) tdays = othertime.DaysSince(sun.time, basetime=datetime(1899, 12, 31)) for ii, tt in enumerate(tsteps): # Convert the time to the untrim formats timestr = datetime.strftime(sun.time[tt], '%Y-%m-%d %H:%M:%S') print('Writing data at time %s (%d of %d)...' % (timestr, tt, tsteps[-1])) #Write the time variables nc.variables['Mesh2_data_time'][ii] = tdays[ii] nc.variables['Mesh2_data_time_string'][:, ii] = timestr # Load each variable or calculate it and convert it to the untrim format sun.tstep = [tt] ### # Compute a few terms first eta = sun.loadData(variable='eta') U = sun.loadData(variable='U_F') dzz = sun.getdzz(eta) dzf = sun.getdzf(eta) vname = 'Mesh2_sea_surface_elevation' #print '\tVariable: %s...'%vname nc.variables[vname][:, ii] = eta vname = 'Mesh2_salinity_3d' #print '\tVariable: %s...'%vname tmp3d = sun.loadData(variable='salt') nc.variables[vname][:, :, ii] = tmp3d.swapaxes(0, 1)[:, ::-1] vname = 'Mesh2_vertical_diffusivity_3d' #print '\tVariable: %s...'%vname tmp3d = sun.loadData(variable='nu_v') nc.variables[vname][:, :, ii] = tmp3d.swapaxes(0, 1)[:, ::-1] vname = 'h_flow_avg' #print '\tVariable: %s...'%vname nc.variables[vname][:, :, ii] = U.swapaxes(0, 1)[:, ::-1] vname = 'v_flow_avg' #print '\tVariable: %s...'%vname tmp3d = sun.loadData(variable='w') * sun.Ac # m^3/s nc.variables[vname][:, :, ii] = tmp3d.swapaxes(0, 1)[:, ::-1] # Need to calculate a few terms for the other variables vname = 'Mesh2_edge_wet_area' #print '\tVariable: %s...'%vname #dzf = sun.loadData(variable='dzf') tmp3d = dzf * sun.df nc.variables[vname][:, :, ii] = tmp3d.swapaxes(0, 1)[:, ::-1] vname = 'Mesh2_face_water_volume' #print '\tVariable: %s...'%vname #dzz = sun.loadData(variable='dzz') tmp3d = dzz * sun.Ac nc.variables[vname][:, :, ii] = tmp3d.swapaxes(0, 1)[:, ::-1] vname = 'Mesh2_face_wet_area' #print '\tVariable: %s...'%vname tmp3d = np.repeat(sun.Ac[np.newaxis, ...], sun.Nkmax, axis=0) nc.variables[vname][:, :, ii] = tmp3d.swapaxes(0, 1)[:, ::-1] # UnTRIM references from bottom to top i.e. # k = 0 @ bed ; k = Nkmax-1 @ top vname = 'Mesh2_edge_bottom_layer' #print '\tVariable: %s...'%vname #tmp2d = sun.Nkmax-sun.Nke # zero based tmp2d = sun.Nkmax - sun.Nke + 1 # one based nc.variables[vname][:, ii] = tmp2d vname = 'Mesh2_edge_top_layer' #print '\tVariable: %s...'%vname etop = sun.loadData(variable='etop') #tmp2d = sun.Nkmax-etop-1 # zero based tmp2d = sun.Nkmax - etop # one based nc.variables[vname][:, ii] = tmp2d vname = 'Mesh2_face_bottom_layer' #print '\tVariable: %s...'%vname #tmp2d = sun.Nkmax-sun.Nk + 1 # zero based tmp2d = sun.Nkmax - sun.Nk # one based nc.variables[vname][:, ii] = tmp2d vname = 'Mesh2_face_top_layer' #print '\tVariable: %s...'%vname ctop = sun.loadData(variable='ctop') #tmp2d = sun.Nkmax-ctop-1 # zero based tmp2d = sun.Nkmax - ctop # one based nc.variables[vname][:, ii] = tmp2d print(72 * '#') print('\t Finished SUNTANS->UnTRIM conversion') print(72 * '#') # close the file nc.close()
class sundriver(object): """ Driver class for generating SUNTANS input files """ # Switches to generate bathymetry, boundary, meteorology and initial condition input files makebathy = False makebnd = False makewinds = False makeinitial = False ### # General options ### # Grid projection variables convert2utm = False CS = 'NAD83' utmzone = 51 isnorth = False vdatum = 'MSL' # Verical grid options Nkmax = 1 # number of layers r = 1.01 # vertical stretching parameter setconstantdepth = False # Option to set constant depth H0 = 10.0 # Constant depth ### # Bathymetry interpolation options ### depthfile = None depthmax = 0.1 interpmethod = 'idw' # Interpolation method: 'nn', 'idw', 'kriging', 'griddata' plottype = 'mpl' # Type of plot: 'mpl', 'vtk2' or 'vtk3' shapefieldname = 'contour' # name of shapefile attribute with contour data scalefac = 1.0 # Interpolation options NNear = 3 # Interpolate to nodes then take maximum depth for cell interpnodes = False # IF interpmethod = 'idw' p = 1.0 # power for inverse distance weighting # IF interpmethod = 'kriging' varmodel = 'spherical' nugget = 0.1 sill = 0.8 vrange = 250.0 # Smoothing options smooth = True smoothmethod = 'kriging' # USe kriging or idw for smoothing smoothnear = 4 # No. of points to use for smoothing # Option to adjust channel depths using a shapefile adjust_depths = False channel_shpfile = 'channel.shp' #### # Open boundary options #### opt_bcseg = 'constant' # Segment boundary condition option: 'constant' or 'file' opt_bctype2 = 'constant' # Type 2 boundary condition option: 'constant' or 'file' opt_bctype3 = 'constant' # Type 3 boundary condition option: 'constant', ,'file','OTIS', 'ROMS', 'ROMSOTIS','ROMSFILE', 'OTISFILE', 'ROMSOTISFILE' modifyedges = False # Option to modify the boundary edges bcpolygonfile = None # Shape file with fields 'marker' and 'edge_id' bcfile = 'SUNTANS_BC.nc' # Input boundary condition file # IF opt_bcseg = 'consant Q0 = 100.0 # m3/s # IF opt_bctype2/opt_bctype3 = 'constant' T0 = 0 # Open boundary background temperature S0 = 0 # Open boundary background salinity # IF opt_bctype3 = 'file' or 'ROMSFILE' waterlevelstationID = None # IF opt_bctype3 = 'harmonic' amp = 0.25 omega = 2 * PI / (24.0 * 3600.0) # IF opt_bctype2 = 'file' TairstatationID = None # Filter type (waterlevel) filttype = 'low' cutoff = 3600.0 # Air temp cuttoff (bctype2 = file) tairfilttype = 'low' taircutoff = 14.0 * 24.0 * 3600.0 #### # Atmospheric input options #### opt_met = 'constant' # Met file creation options: 'constant' metfile = 'SUNTANS_MetForcing.nc' # IF opt_met = 'consant' Uwind = 0.0 Vwind = 5.0 RH = 50.0 Tair = 30.0 Pair = 1010.0 rain = 0.0 cloud = 0.0 #### # Initial condition options #### opt_ic = 'constant', 'depth_profile', 'ROMS', 'SUNTANS' icfile = 'SUNTANS_IC.nc' icfilterdx = 0.0 # Filtering length scale # Age source term polygon agesourcepoly = None # Initial condition temperature and salinity T0ic = 0 S0ic = 0 ### # Input file names ### romsfile = None suntansicfile = None otisfile = None dbasefile = None # Use ROMS u,v and eta useROMSuv = False useROMSeta = False # Use OTIS u & v useOTISuv = False ############################ def __init__(self, **kwargs): self.__dict__.update(kwargs) def __call__(self, suntanspath, starttime, endtime, dt): self.suntanspath = suntanspath self.starttime = starttime self.endtime = endtime self.dt = dt # Step through and perform each step self._makebathy() if self.makebnd: self._makebnd() if self.makeinitial: self._makeinitial() if self.makewinds: self._makewinds() print '###########\n Completed generating input files. Check text for errors!!!!\n##########' def _makebathy(self): """ Loads the grid object and interpolates the depths """ # Interpolate the depths onto the grid if self.makebathy: if self.depthfile == None: raise Exception, 'need to set "depthfile" parameter' else: print 'Interpolation depths onto grid from file:\n%s' % self.depthfile D = DepthDriver(self.depthfile,interpmethod=self.interpmethod,\ plottype=self.plottype,NNear=self.NNear,\ p=self.p,varmodel=self.varmodel,nugget=self.nugget,sill=self.sill,vrange=self.vrange,\ convert2utm=self.convert2utm,utmzone=self.utmzone,isnorth=self.isnorth,vdatum=self.vdatum,\ shapefieldname=self.shapefieldname,\ smooth=self.smooth,smoothmethod=self.smoothmethod,smoothnear=self.smoothnear) D(self.suntanspath,depthmax=self.depthmax,interpnodes=self.interpnodes,\ scalefac=self.scalefac) self.grd = D.grd # Now go through and adjust the channel depths from a shapefile if self.adjust_depths: self.grd = adjust_channel_depth(self.grd, self.channel_shpfile) # Write the depths to file print 'Writing depths.dat (again)...' self.grd.saveBathy(self.suntanspath + '/depths.dat-voro') print 'Data (re-)saved to %s.' % self.suntanspath + '/depths.dat-voro' print 'SUNTANS depths saved to: %s' % (self.suntanspath + '/depths.dat-voro') elif self.setconstantdepth: print 'Using constant depth (%6.2f m)...' % self.H0 self.grd = Grid(self.suntanspath) self.grd.dv = np.zeros_like(self.grd.xv) self.grd.dv[:] = self.H0 else: print 'Loading grid from folder:\n%s' % self.suntanspath # Load the grid self.grd = Grid(self.suntanspath) # Load the depth data into the grid object self.grd.loadBathy(self.suntanspath + '/depths.dat-voro') zmax = np.abs(self.grd.dv.max()) print 'Calculating vertical grid spacing for Nk = %d, r = %1.3f, %6.3f...' % ( self.Nkmax, self.r, zmax) # Set up the vertical coordinates dz = self.grd.calcVertSpace(self.Nkmax, self.r, zmax) self.grd.setDepth(dz) # Save vertspace.dat self.grd.saveVertspace(self.suntanspath + '/vertspace.dat') # Write cells.dat and edges.dat to ensure they are in the right format print 'Overwriting cells.dat and edges.dat to ensure format consistency.' self.grd.saveCells(self.suntanspath + '/cells.dat') self.grd.saveEdges(self.suntanspath + '/edges.dat') def _makebnd(self): """ Generate boundary condition files """ if self.modifyedges: modifyBCmarker(self.suntanspath, self.bcpolygonfile) #Load the boundary object from the grid bnd = Boundary(self.suntanspath, (self.starttime, self.endtime, self.dt)) ### # Segment (flux) boundaries ### if self.opt_bcseg == 'constant': print 'Setting %d boundary segments to discharge of %6.3f m3/s' % ( bnd.Nseg, self.Q0) bnd.boundary_Q[:] = self.Q0 elif self.opt_bcseg == 'file': print 'Loading river segment data from file...\n' for ii, ID in enumerate(bnd.segp): print 'Loading discahrge data for boundary segment (%d) StationID: %d...' % ( ii, ID) ts = timeseries.loadDBstation(self.dbasefile,ID,'discharge',timeinfo=(self.starttime,self.endtime,self.dt),\ filttype=self.filttype,cutoff=self.cutoff) bnd.boundary_Q[:, ii] = ts.y.copy() else: print 'Unknown option: opt_bcseg = %s. Not setting boundary segment data.' % self.opt_bcseg ### # Type-3 boundaries ### self.useROMS = False self.useOTIS = False self.useFILE = False self.useOTISFILE = False if self.opt_bctype3 == 'constant': print 'Setting constant type-3 boundary conditions...' print 'Setting salinity = %f, temperature = %f' % (self.S0, self.T0) bnd.S[:] = self.S0 bnd.T[:] = self.T0 elif self.opt_bctype3 == 'depth_profile': print 'Setting type-3 boundary T/S from profile...' self.loadTSprofile() for ii in range(0, bnd.N3): bnd.T[0, :, ii] = self.Tz bnd.S[0, :, ii] = self.Sz elif self.opt_bctype3 in ('ROMS'): self.useROMS = True elif self.opt_bctype3 in ('OTIS'): self.useOTIS = True elif self.opt_bctype3 in ('file'): self.useFILE = True elif self.opt_bctype3 in ('ROMSOTIS'): self.useROMS = True self.useOTIS = True elif self.opt_bctype3 in ('ROMSFILE'): self.useROMS = True self.useFILE = True elif self.opt_bctype3 in ('OTISFILE'): self.useOTISFILE = True elif self.opt_bctype3 in ('ROMSOTISFILE'): self.useOTISFILE = True self.useROMS = True else: print 'Unknown option: opt_bctype3 = %s. Not setting type-3 boundaries.' % self.opt_bctype3 if self.useROMS: bnd.roms2boundary(self.romsfile, setUV=self.useROMSuv, seth=self.useROMSeta) if self.useOTIS: bnd.otis2boundary(self.otisfile, setUV=self.useOTISuv) if self.useOTISFILE: bnd.otisfile2boundary(self.otisfile, self.dbasefile, self.waterlevelstationID, setUV=self.useOTISuv) if self.useFILE: ID = self.waterlevelstationID print 'Loading waterlevel onto all type-3 points from stationID: %d...' % ( ID) ts = timeseries.loadDBstation(self.dbasefile,ID,'waterlevel',timeinfo=(self.starttime,self.endtime,self.dt),\ filttype=self.filttype,cutoff=self.cutoff) for ii in range(bnd.N3): bnd.h[:, ii] += ts.y.copy() ### # Type-2 boundaries ### self.useFILE2 = False if self.opt_bctype2 == 'constant': print 'Setting constant type-2 boundary conditions...' print 'Setting salinity = %f, temperature = %f' % (self.S0, self.T0) bnd.boundary_S[:] = self.S0 bnd.boundary_T[:] = self.T0 elif self.opt_bctype2 == 'file': print 'Using file for type-2 boundary condition (temperature only)' print 'Setting salinity = %f' % (self.S0) bnd.boundary_S[:] = self.S0 self.useFILE2 = True else: print 'Unknown option: opt_bctype2 = %s. Not setting type-2 boundaries.' % self.opt_bctype3 if self.useFILE2: ID = self.TairstationID print 'Loading air temperature onto all type-2 points from stationID: %s...' % ( ID) ts = timeseries.loadDBstation(self.dbasefile,ID,'Tair',timeinfo=(self.starttime,self.endtime,self.dt),\ filttype=self.tairfilttype,cutoff=self.taircutoff) for ii in range(bnd.N2): for kk in range(bnd.Nk): bnd.boundary_T[:, kk, ii] += ts.y.copy() # Write to netcdf bnd.write2NC(self.suntanspath + '/' + self.bcfile) def _makeinitial(self): """ Generate initial conditions """ # Initialise the class IC = InitialCond(self.suntanspath, self.starttime) if self.opt_ic == 'constant': print 'Setting constant initial conditions...' print 'Setting salinity = %f, temperature = %f' % (self.S0ic, self.T0ic) IC.T[:] = self.T0ic IC.S[:] = self.S0ic elif self.opt_ic == 'depth_profile': print 'Setting depth-varying initial conditions...' self.loadTSprofile() for ii in range(0, IC.Nc): IC.T[0, :, ii] = self.Tz IC.S[0, :, ii] = self.Sz elif self.opt_ic == 'ROMS': print 'Setting initial conditions from ROMS model output...' IC.roms2ic(self.romsfile, setUV=self.useROMSuv, seth=self.useROMSeta, interpmethod='idw', NNear=5, p=2) #interpmethod=self.interpmethod,NNear=self.NNear,p=self.p,\ #varmodel=self.varmodel,nugget=self.nugget,sill=self.sill,\ #vrange=self.vrange) elif self.opt_ic == 'SUNTANS': IC.suntans2ic(self.suntansicfile, setUV=self.useROMSuv, seth=self.useROMSeta) else: print 'Unknown option: opt_ic = %s. Not setting initial conditions.' % self.opt_ic # Filter the variables in space if self.icfilterdx > 0: IC.filteric(self.icfilterdx) # Set the age source term from a polygon if not self.agesourcepoly == None: print 'Setting age source term with shapefile: %s...' % self.agesourcepoly IC.setAgeSource(self.agesourcepoly) # Write the initial condition file IC.writeNC(self.suntanspath + '/' + self.icfile, dv=self.grd.dv) def _makewinds(self): """ Generate a metfile """ if self.opt_met == 'constant': print 'Setting constant met forcing with: Uwind = %6.2f\nVwind = %6.2f\nTair = %6.2f\nPair = %6.2f\nRH = %6.2f\nrain = %6.2f\ncloud = %6.2f\n'\ %(self.Uwind,self.Vwind,self.Tair,self.Pair,self.RH,self.cloud,self.rain) xpt = self.grd.xv.mean() ypt = self.grd.yv.mean() zpt = 10.0 # Load the met object met = SunMet(xpt, ypt, zpt, (self.starttime, self.endtime, self.dt)) # Fill the arrays met.Uwind.data[:] = self.Uwind met.Vwind.data[:] = self.Vwind met.Tair.data[:] = self.Tair met.Pair.data[:] = self.Pair met.RH.data[:] = self.RH met.cloud.data[:] = self.cloud met.rain.data[:] = self.rain met.write2NC(self.suntanspath + '/' + self.metfile) else: print 'Unknown option: opt_met=%s. Failed to generate a metfile' % self.opt_met def loadTSprofile(self): """ Loads a temperature salinity profile from a matfile and interpolates onto the grid depths """ try: data = io.loadmat(self.TSprofilefile) z = data['depth'].ravel() temp = data['temp_profile'].ravel() salt = data['salt_profile'].ravel() FT = interp1d(z, temp, kind=3) self.Tz = FT(self.grd.z_r) FS = interp1d(z, salt, kind=3) self.Sz = FS(self.grd.z_r) except: print 'Warning could not find variables: "depth", "temp_profile" or "salt_profile" in file:\n%s' % self.TSprofilefile self.Tz = self.T0 self.Sz = self.S0
smoothnear=4 # No. of points to use for smoothing ### # End options ### D = DepthDriver(depthfile,interpmethod=interpmethod,plottype=plottype,NNear=NNear,\ p=p,varmodel=varmodel,nugget=nugget,sill=sill,vrange=vrange,convert2utm=convert2utm,\ utmzone=utmzone,isnorth=isnorth,vdatum=vdatum,smooth=smooth,smoothmethod=smoothmethod,\ smoothnear=smoothnear) D(suntanspath,depthmax=depthmax) ################################# # Load the model grid and bathymetry into the object 'grd' and initialise the vertical spacing ################################## grd = Grid(suntanspath) # Load the depth data into the grid object grd.loadBathy(suntanspath+'/depth.dat-voro') zmax = np.abs(grd.dv.max()) print zmax # Set up the vertical coordinates dz = grd.calcVertSpace(Nkmax,r,zmax) # Default version #def calcvertspace(Nkmax,r,depth): # ktop=15 # dztop=2.0 grd.setDepth(dz)