Example #1
0
def create_gmsh_geo(shpfile, scalefile, geofile,
    startpoly=0, ndmin=8, scalefac=1.0,\
    r=1.08, lcmax=2000.0, sigmoid=0,\
    linetype='BSpline'):
    """
    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.
        - sigmoid [default=0]
        - linetype - 'BSpline' or 'Line'
    """
    # 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

            if linetype == 'Line' and ip > 1:
                fgeo.write("Line(IL + %i) = {IP + %i , IP + %i};\n" % \
                        (il, ip-2, ip-1))
                il = il + 1
                lines.append(il - 1)

        if linetype == 'BSpline':
            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("%s(IL + %i) = {IP + %i : IP + %i};\n" %
                       (linetpye, 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("%s(IL + %i) = {IP + %i : IP + %i};\n" %
                       (linetype, 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)
Example #2
0
File: gmsh.py Project: mrayson/soda
def create_gmsh_geo(shpfile, scalefile, geofile, 
    startpoly=0, ndmin=8, scalefac=1.0,\
    r=1.08, lcmax=2000.0, sigmoid=0,\
    linetype='BSpline'):
    """
    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.
        - sigmoid [default=0]
        - linetype - 'BSpline' or 'Line'
    """
    # 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

            if linetype == 'Line' and ip > 1:
                fgeo.write("Line(IL + %i) = {IP + %i , IP + %i};\n" % \
                        (il, ip-2, ip-1))
                il = il + 1
                lines.append(il-1)

                
        
        if linetype =='BSpline':
            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("%s(IL + %i) = {IP + %i : IP + %i};\n" % (linetpye,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("%s(IL + %i) = {IP + %i : IP + %i};\n" % (linetype,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
Example #3
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
    import pandas as pd

    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))

    # Vectorize operations using pandas
    geo_points = pd.DataFrame({'single_column':xy.tolist()}).single_column.\
        apply(lambda x: geometry.Point(x[0],x[1])).values

    geo_lines = pd.DataFrame({'single_column':xyscale}).single_column.\
        apply(lambda x: geometry.LineString(x)).values

    def distance(a_point, a_line):
        return a_point.distance(a_line)

    distance_vec = np.vectorize(distance)

    dist_all = distance_vec(geo_points[..., np.newaxis], geo_lines)

    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))
        dist = dist_all[:, n].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 is 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()
Example #4
0
File: gmsh.py Project: mrayson/soda
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
    import pandas as pd

    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))

    # Vectorize operations using pandas
    geo_points = pd.DataFrame({'single_column':xy.tolist()}).single_column.\
        apply(lambda x: geometry.Point(x[0],x[1])).values

    geo_lines = pd.DataFrame({'single_column':xyscale}).single_column.\
        apply(lambda x: geometry.LineString(x)).values

    def distance(a_point, a_line):
        return a_point.distance(a_line)

    distance_vec = np.vectorize(distance)

    dist_all = distance_vec(geo_points[...,np.newaxis], geo_lines)

    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))
        dist = dist_all[:,n].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 is 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()