def adjust_channel_depth(grd,shpfile,lcmax=500.): """ Adjusts the depths of a suntans grid object using a line shapefile. The shapefile must have an attribute called "contour" """ from shapely import geometry, speedups from maptools import readShpPointLine if speedups.available: speedups.enable() print('Adjusting depths in channel regions with a shapefile...') # Load the shapefile xyline,contour = readShpPointLine(shpfile,FIELDNAME='contour') # Load all of the points into shapely type geometry # Distance method won't work with numpy array #P = geometry.asPoint(xy) P = [geometry.Point(grd.xv[i],grd.yv[i]) for i in range(grd.Nc)] L=[] for ll in xyline: L.append(geometry.asLineString(ll)) nlines = len(L) weight_all = np.zeros((grd.Nc,nlines)) for n in range(nlines): print('Calculating distance from line %d...'%n) dist = [L[n].distance(P[i]) for i in range(grd.Nc)] dist = np.array(dist) # Calculate the weight from the distance weight = -dist/lcmax+1. weight[dist>=lcmax]=0. weight_all[:,n] = weight # Now go through and re-calculate the depths dv = grd.dv*(1-weight_all.sum(axis=-1)) for n in range(nlines): dv += weight_all[:,n]*contour[n] grd.dv=dv return grd
def adjust_channel_depth(grd,shpfile,lcmax=500.): """ Adjusts the depths of a suntans grid object using a line shapefile. The shapefile must have an attribute called "contour" """ from shapely import geometry, speedups from maptools import readShpPointLine if speedups.available: speedups.enable() print 'Adjusting depths in channel regions with a shapefile...' # Load the shapefile xyline,contour = readShpPointLine(shpfile,FIELDNAME='contour') # Load all of the points into shapely type geometry # Distance method won't work with numpy array #P = geometry.asPoint(xy) P = [geometry.Point(grd.xv[i],grd.yv[i]) for i in range(grd.Nc)] L=[] for ll in xyline: L.append(geometry.asLineString(ll)) nlines = len(L) weight_all = np.zeros((grd.Nc,nlines)) for n in range(nlines): print 'Calculating distance from line %d...'%n dist = [L[n].distance(P[i]) for i in range(grd.Nc)] dist = np.array(dist) # Calculate the weight from the distance weight = -dist/lcmax+1. weight[dist>=lcmax]=0. weight_all[:,n] = weight # Now go through and re-calculate the depths dv = grd.dv*(1-weight_all.sum(axis=-1)) for n in range(nlines): dv += weight_all[:,n]*contour[n] grd.dv=dv return grd
def create_gmsh_geo(shpfile,scalefile,geofile,startpoly=0,ndmin=8,scalefac=1.0,\ r=1.08,lcmax=2000.0,sigmoid=0): """ Generate a gmsh *.geo file using a boundary from a shpfile Inputs: --- - shpfile : a polygon shapefile with the domain boundaries. Make sure that the first polygon is the outer ring. If not change 'startpoly' parameter. - scalefile : a line shapefile with field 'scale' specifying the target grid resolution for that region. - geofile: output geo ascii file. *Optional* - startpoly [default=0] - the index of the outer polygon in the shapefile. - ndmin [default=8] - the minimum range of the scale = ndmin*scale - r : expansion factor - lcmax [default=2000] - the maximum grid cell size. """ # Load the polygon shape file xy,field = readShpPoly(shpfile,FIELDNAME='FID') # Load the scale shape file xyscale,scale = readShpPointLine(scalefile,FIELDNAME='scale') # Load the 'embed' flag to see if the scale layer should be embedded #try: # exyscale,embed = readShpPointLine(scalefile,FIELDNAME='embed') #except: # print 'Warning - could not find "embed" field in shapefile. Setting embed = 0.' # embed = [ss*0 for ss in scale] exyscale,embed = readShpPointLine(scalefile,FIELDNAME='embed') if embed == []: embed = [ss*0 for ss in scale] ## output geo and svg file fgeo = open(geofile,'w') fgeo.write("""IP = newp; IL = newl; IS = news; IF = newf; """ ) ip = 0 # Point counter il = 0 # Line counter rp = 0 lines=[] for loop in xy: firstp = ip for p in range(loop.shape[0]): rp = rp + 1 fgeo.write("Point(IP + %i) = {%.16e, %.16e, %.16e}; // %i\n" % (ip, loop[p,0], loop[p,1], 0., rp -1)) ip = ip + 1 fgeo.write("BSpline(IL + %i) = {IP + %i : IP + %i, IP + %i};\n" % (il, firstp, ip - 1, firstp)) il = il + 1 lines.append(il-1) # Create the surface polygon fgeo.write('\n//%s\n//Surface Polygon Definition\n//%s\n\n'%(72*'#',72*'#')) surfstart=il fgeo.write("Line Loop(IL + %i) = {IL + %s};\n" % (il,startpoly) ) il += 1 for ll in lines: if ll != startpoly: fgeo.write("Line Loop(IL + %i) = {IL + %s};\n" % (il,ll) ) il += 1 surfend = il - 1 fgeo.write("Plane Surface(IL + %i) = {IL + %i : IL + %i};\n"%(il,surfstart,surfend)) fgeo.write('Physical Surface("Ocean") = {IL + %i};\n'%il) surface_id = il # Keep this to embed lines into il += 1 # Create the grid scale lines and fields fgeo.write('\n//%s\n//Grid Scale Definition\n//%s\n\n'%(72*'#',72*'#')) slines=[] # Reference to scale lines for loop,ss,ee in zip(xyscale,scale,embed): firstp = ip ss *= scalefac # Applies scale factor for p in range(loop.shape[0]): rp = rp + 1 #fgeo.write("Point(IP + %i) = {%.16e, %.16e, %.16e}; // %i\n" % (ip, loop[p,0], loop[p,1], 0., rp -1)) fgeo.write("Point(IP + %i) = {%.16e, %.16e, %.16e,%.16e}; // %i\n" % (ip, loop[p,0], loop[p,1], 0., rp -1,float(ss))) ip = ip + 1 if ee: #fgeo.write("BSpline(IL + %i) = {IP + %i : IP + %i};\n" % (il, firstp, ip - 1)) fgeo.write("Spline(IL + %i) = {IP + %i : IP + %i};\n" % (il, firstp, ip - 1)) # Embed this line in the main surface so that cells are aligned fgeo.write("Line{IL + %i} In Surface{IL + %i};\n"%(il,surface_id)) else: # Don't embed (can set as BSpline) fgeo.write("BSpline(IL + %i) = {IP + %i : IP + %i};\n" % (il, firstp, ip - 1)) slines.append(il) il = il + 1 ifield = 0 # Field counter fids = [] ii=0 for ss,line in zip(scale,slines): fgeo.write("Field[IF + %i] = Attractor;\n"%ifield) fgeo.write("Field[IF + %i].EdgesList = {IL + %i};\n"%(ifield,line)) nodesperedge = get_nnodes_from_line(xyscale[ii],2.0*float(ss)) fgeo.write("Field[IF + %i].NNodesByEdge = %i;\n"%(ifield,nodesperedge)) ifield+=1 fgeo.write("Field[IF + %i] = Threshold;\n"%ifield) # Find the maximum distance Nk = np.log(lcmax/ss)/np.log(r) print ss,Nk lmin = float(ndmin)*float(ss) lmax = lmin + Nk * ss fgeo.write("Field[IF + %i].DistMax = %6.2f;\n"%(ifield,lmax)) fgeo.write("Field[IF + %i].DistMin = %6.2f;\n"%(ifield,lmin)) fgeo.write("Field[IF + %i].IField = IF + %i;\n"%(ifield,ifield-1)) fgeo.write("Field[IF + %i].LcMax = %6.2f;\n"%(ifield,lcmax)) fgeo.write("Field[IF + %i].LcMin = %6.2f;\n"%(ifield,float(ss))) fgeo.write("Field[IF + %i].Sigmoid = %d;\n"%(ifield,sigmoid)) fids.append(ifield) ifield+=1 ii+=1 fieldlist = '{' for ff in fids: fieldlist += 'IF + %d, '%ff fieldlist = fieldlist[:-2]+'}' fgeo.write("Field[IF + %i] = Min;\n"%ifield) fgeo.write("Field[IF + %i].FieldsList = %s;\n"%(ifield,fieldlist)) fgeo.write("Background Field = IF + %i;\n"%ifield) # Set Quad options by default fgeo.write("Mesh.CharacteristicLengthMax=%.16e;//Max cell size\n"%lcmax) fgeo.write("Mesh.RecombineAll=0;//recombine all defined surfaces\n") fgeo.write("Mesh.Algorithm=6;//front\n") fgeo.write("Mesh.Smoothing=10;//10 smoothing steps\n") fgeo.write("Mesh.Remove4Triangles = 1;\n") fgeo.close() print 'Complete. GMSH geo file written to:\n\t %s'%geofile
def create_pos_file(posfile,scalefile, xlims,ylims,dx,\ geofile=None,ndmin=5, lcmax=2000.,r=1.05, scalefac=1.0): """ Generates a gmsh background scale file (*.pos) If a geofile is specified the mesh is embedded """ from shapely import geometry, speedups if speedups.available: speedups.enable() X,Y = np.meshgrid(np.arange(xlims[0],xlims[1],dx),np.arange(ylims[0],ylims[1],dx)) xy = np.vstack((X.ravel(),Y.ravel())).T Np = xy.shape[0] nj,ni=X.shape # Load the scalefile xyscale,gridscale = readShpPointLine(scalefile,FIELDNAME='scale') # Load all of the points into shapely type geometry # Distance method won't work with numpy array #P = geometry.asPoint(xy) P = [geometry.Point(xy[i,0],xy[i,1]) for i in range(Np)] L=[] for ll in xyscale: L.append(geometry.asLineString(ll)) nlines = len(L) scale_all = np.zeros((nj,ni,nlines)) for n in range(nlines): print 'Calculating distance from line %d...'%n ss = gridscale[n] * scalefac lmin = ndmin * ss # Find the maximum distance Nk = np.log(lcmax/ss)/np.log(r) print ss,Nk lmax = lmin + Nk * ss dist = [L[n].distance(P[i]) for i in range(Np)] dist = np.array(dist).reshape((nj,ni)) # Calculate the scale N = (dist-lmin)/ss scale = ss*r**N ind = dist<=lmin if ind.any(): scale[ind] = ss ind = scale>lcmax if ind.any(): scale[ind] = lcmax scale_all[:,:,n] = scale scale_min = scale_all.min(axis=-1) write_pos_file(posfile,X,Y,scale_min) if not geofile == None: fgeo = open(geofile,'a') fgeo.write("// Merge a post-processing view containing the target mesh sizes\n") fgeo.write('Merge "%s";'%posfile) fgeo.write("// Apply the view as the current background mesh\n") fgeo.write("Background Mesh View[0];\n") fgeo.close()
def __init__(self, outfile, t, lat, lon, air_u, air_v, tair, cloud, rh, pair, rain, **kwargs): from maptools import readShpPointLine self.__dict__.update(kwargs) self.outfile = outfile self.t = t self.lat = lat self.lon = lon self.air_u = air_u self.air_v = air_v self.tair = tair self.cloud = cloud self.rh = rh self.pair = pair self.rain = rain ##SUNTANS wind coordinates shp_file = '../../../coarse_gis/wind_stations_LM.shp' XY, field0 = readShpPointLine(shp_file) lon_new = [] lat_new = [] for i in range(len(XY)): lon_new.append(XY[i][0]) lat_new.append(XY[i][1]) ## Test predefined locations import matplotlib.pyplot as plt from mpl_toolkits.basemap import Basemap #west = -97.458207; east = -96.72 #south = 27.368078; north = 28.291049 #25.883046, -97.966679 #27.658327, -96.824101 west = -97.966679 east = -96.824101 south = 25.883046 north = 27.658327 fig = plt.figure(figsize=(10, 10)) basemap = Basemap(projection='merc',llcrnrlat=south,urcrnrlat=north,\ llcrnrlon=west,urcrnrlon=east, resolution='h') basemap.drawcoastlines() basemap.fillcontinents(color='coral', lake_color='aqua') basemap.drawcountries() basemap.drawstates() llons, llats = basemap(lon_new, lat_new) basemap.plot(llons, llats, 'ob', markersize=8.5) plt.show() self.xsun = np.zeros([len(lat_new)]) self.ysun = np.zeros([len(lon_new)]) for i in range(len(lon_new)): (self.xsun[i], self.ysun[i]) = utm.from_latlon(lat_new[i], lon_new[i])[0:2] #pdb.set_trace() ## Step One: interpolate wind data self.interp() self.writeNC(self.outfile, self.t, self.xsun, self.ysun, self.air_u_new, \ self.air_v_new, self.tair_new, self.cloud_new, self.rh_new, \ self.pair_new, self.rain_new)