Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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()
Esempio n. 5
0
    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)