예제 #1
0
def elfcarBondAnalysis(elfcarFile,elfcarNeighbsFile,verbose=True):
    #Loads up an ELFCAR, generates a starting neighbor list from voronoi tesselation
    #Initial neighbors are dropped if bondlength is greater than maxBondLength
    #Generates a bunch of points on a cylinder
    #Maps the cylinder points across each neighbor pair
    #If the average ELF is always above minELF accross this cylinder, atoms are bonded.

    ELFlevel=0.5

    #Parse ELFCAR
    elfcar=open(elfcarFile,"r").readlines()
    (basis,atypes,atoms,header),elf = elfcarIO.read(elfcar)
    lengths=array([basis[0][0],basis[1][1],basis[2][2]])

    #Neighbors
    elfcarNeighbs=open(elfcarNeighbsFile,"r").readlines()
    neighbors=[map(int,line.split()) for line in elfcarNeighbs[1:]]
    halfNeighbs=full2half(neighbors)

    a=elf.shape
    AvgElf=sum([sum([sum(line) for line in plane]) for plane in elf])/a[0]/a[1]/a[2]
    if verbose:
        print elfcarFile
        print "Average ELF value:",AvgElf

    #Evaluate the ELF between each nieghbor pair
    #creates a bunch of points on a circle in the x-y plane
    def circlePoints(center,radius):
        N=11
        ps=[float(p)/N*radius for p in range(-N,N+1)]
        r2=radius*radius
        points=list()
        for x in ps:
            for y in ps:
                if (x**2+y**2)<=r2:
                    points.append(asarray([x,y]))
        return asarray(points)

    atoms=asarray([lengths[i]-v for i,v in enumerate(atoms.T)]).T

    #Flip the ELF because its off, thanks a lot VASP.
    elf=elf[::-1,::-1,::-1]

    #Loop over atom pairs
    cylRadius = 2.0
    cirPoints = circlePoints(a,cylRadius).T
    cirPoints = vstack([cirPoints,zeros(cirPoints.shape[1])]) 
    coordination=zeros(len(atoms))
    gridx,gridy=np.mgrid[0:1:20j,0:1:20j]*4.2-2.1
    cirPoints2=array(cirPoints)
    cirPoints2=cirPoints2[:2].T
    f,ax  =plt.subplots(1,1)
    rs=[list() for i in halfNeighbs]
    rsFlat=list()
    for i,ineighbs in enumerate(halfNeighbs):
        a=atoms[i]
        for j in ineighbs:
            #copy the cylinder points so you can play with them...
            localCir=array(cirPoints)

            #Find the minimum image atom
            b=minImageAtom(a,atoms[j],basis)
            l=minImageDist(a,b,basis)

            #How to map your cylinder onto the local atom
            R=rotmatx([0,0,l],b-a)

            #Loop over each cylinder slice
            sliceParam=list()
            localCir[2]=l/2.
            cir=asarray([dot(R,p)+a for p in localCir.T]).T
                
            #cir2 is circle with periodic boundary conditions applied and mapped to index space
            cir2=asarray([((c/lengths[ind]*elf.shape[ind])%(elf.shape[ind]-1)) for ind,c in enumerate(cir)])            

            #Interpolation across cylinder
            z=ndimage.map_coordinates(elf,cir2)

            #Generate a grid and find the desired contour on the bond crosssection
            gridz=interpolate.griddata(cirPoints2,z,(gridx,gridy),fill_value=0)
            ac=ax.contour(gridx,gridy,gridz,levels=[ELFlevel],linewidths=5,colors="black")

            #take the longest list (this is the bond)
            m=0
            if len(ac.collections[0].get_paths()):
                m=np.asarray([len(v.vertices) for v in ac.collections[0].get_paths()]).argmax()     
            midCircle= ac.collections[0].get_paths()[m].vertices.T
            n=midCircle.shape[1]

            #Find the center of the bond and calculate the radius
            com=[midCircle[0].sum()/n,midCircle[1].sum()/n]
            midCircle[0]-=com[0]
            midCircle[1]-=com[1]
            r=0
            for m in midCircle.T:
                r+=(m[0]**2+m[1]**2)**(0.5)
            r/=n
            rs[i].append(r)
            rs[j].append(r)
            rsFlat.append(r)

#                pl.contour(gridx,gridy,gridz,levels=[0.5],linewidths=5,colors="black")
#                pl.show()
            #avgCircle+=jCircle
    #avgCircle/=sum(map(len,neighbors))/2.
    
    #pl.show()
    return rs,rsFlat,atoms,neighbors,basis
예제 #2
0
def fieldNeighbors3D(atoms,atypes,basis,field,fieldSize,halfNeighbors=None,Ninterps=[7,7,15],cutoffs=None,loc=None):
    #loc=["center","bond","half"]

    [v1,v2,v3]=basis
    latoms=array(atoms)

    if loc==None:
        loc="bond"

    #Ensure simulation box is orthorhombic
    if sum(map(fabs,v1))-fabs(v1[0]) > 1e-10 or \
       sum(map(fabs,v2))-fabs(v2[1]) > 1e-10 or \
       sum(map(fabs,v3))-fabs(v3[2]) > 1e-10:
        print "Error: simulation axes are not sufficiently orthogonal.  Use script poscarRectify.py and regenerate doscar"
        exit(0)
    
    cutFlag=True
    if cutoffs==None:
        cutFlag=False
    else: #ensure cutoffs is a list and not just a float
        cutoffs=list(cutoffs)

    bounds=[[0.,v1[0]],[0.,v2[1]],[0.,v3[2]]]
    simSize=asarray([v1[0],v2[1],v3[2]])

    if halfNeighbors==None:
        halfNeighbors=voronoiNeighbors(atoms=latoms,basis=basis,atypes=atypes,style='half')

    #Interpolation and summation properties
    grids=list()
    if cutFlag:
        avgGrids=[zeros(Ninterps) for i in range(len(cutoffs))]
        bondcnts=zeros(len(cutoffs))
    else:
        avgGrid=zeros(Ninterps)
        bondcnt=0

    nlines=float(sum(map(len,halfNeighbors)))
    delx=2.0/Ninterps[0]
    dely=2.0/Ninterps[1]

    #Local Grid size
    delGrids=simSize/fieldSize
    lGridSize=fieldSize
    nlGridPoints=reduce(operator.mul,lGridSize)
    for iNeighb,jNeighbors in enumerate(halfNeighbors):
        if len(jNeighbors)==0:
            continue

        atomi=latoms[iNeighb]
        for i,ai in enumerate(atomi):
            if ai < 0.0:
                atomi[i]+=simSize[i]
            if ai > simSize[i]:
                atomi[i]-=simSize[i]
        
        #Make the local grid about the central atom
        lGridCenter = map(int,atomi/simSize*fieldSize)
        lGridBounds = [[lGridCenter[i]-lGridSize[i]/2,lGridCenter[i]+lGridSize[i]/2] for i in range(3)]
        lGridBoundPoints = array([[lGridBounds[i][0]*delGrids[i],lGridBounds[i][1]*delGrids[i]] for i in range(3)])
        lGridPoints = array( [ \
                map(lambda x: x*delGrids[i],range(lGridCenter[i]-lGridSize[i]/2,lGridCenter[i]+lGridSize[i]/2)) \
                    for i in range(3) ] )
        bnds=list()
        lbnds=list()
        bnds.append(list(lGridBounds))
        lbnds.append(map(list,zip([0,0,0],lGridSize)))
        while outOfBounds(bnds,fieldSize):
            a=whichBounds(bnds,fieldSize)
            bnds.append(map(list,bnds[a]))
            lbnds.append(map(list,lbnds[a]))
            for i in range(3):
                if bnds[-1][i][1] > fieldSize[i]:
                    lbnds[a][i][1] = lGridSize[i]-(bnds[-1][i][1]-fieldSize[i])
                    lbnds[-1][i][0] = lGridSize[i]-(bnds[-1][i][1]-fieldSize[i])
                    lbnds[-1][i][1] = lbnds[-1][i][0]+(bnds[-1][i][1]-fieldSize[i])

                    bnds[-1][i][0]  = 0
                    bnds[-1][i][1] -= fieldSize[i]
                    bnds[a][i][1]   = fieldSize[i]
                    break

                elif bnds[-1][i][0] < 0:
                    lbnds[-1][i][0] = 0
                    lbnds[-1][i][1] = -bnds[-1][i][0]
                    lbnds[a][i][0] = -bnds[-1][i][0]

                    bnds[-1][i][1]  = fieldSize[i]
                    bnds[-1][i][0] += fieldSize[i]
                    bnds[a][i][0]   = 0
                    break

        #Now make the field
        lfield=zeros(lGridSize)
        for lbnd,bnd in zip(lbnds,bnds):
            [[lxa,lxb],[lya,lyb],[lza,lzb]]=lbnd
            [[xa,xb],[ya,yb],[za,zb]]=bnd
            lfield[lxa:lxb, lya:lyb, lza:lzb]=field[xa:xb, ya:yb, za:zb]

        #Loop over Neighboring atoms within the local grid
        for jNeighb in jNeighbors:
            atomj=latoms[jNeighb]
            for i,aj in enumerate(atomj):
                if aj < lGridPoints[i][0]:
                    atomj[i]+=simSize[i]
                if aj > lGridPoints[i][-1]:
                    atomj[i]-=simSize[i]
            d=dist(atomj,atomi)
            
            #If this bond is longer than all the cutoffs than don't bother with it
            if cutFlag and len([1 for i in cutoffs if d<=i])==0:
                continue

            #Change the location as requested
            if loc=="bond":
                delz=mag(atomj-atomi)/Ninterps[2]
                Tran=(atomj-atomi)/2.+atomi
            if loc=="half":
                delz=mag(atomj-atomi)/(Ninterps[2]*2.)
                Tran=(atomj-atomi)/4.+atomi
            if loc=="center":
                delz=dely
                Tran=atomi

            #Change of coordinate systems into atomj-atomi basis.
            Rota=rotmatx(array([0.,0.,1.]),atomj-atomi) 

            xps=array([(i-Ninterps[0]/2)*delx for i in range(Ninterps[0])]*Ninterps[1]*Ninterps[2]).ravel()
            yps=array([[(i-Ninterps[1]/2)*dely]*Ninterps[0] for i in range(Ninterps[1])]*Ninterps[2]).ravel()
            zps=array([[(i-Ninterps[2]/2)*delz]*Ninterps[0]*Ninterps[1] for i in range(Ninterps[2])]).ravel()
            ipnts=array([dot(Rota,array(pnt))+Tran for pnt in zip(xps,yps,zps)])

            #Do the interpolation
            if cutFlag:
                for j,cut in enumerate(cutoffs):
                    if d <= cut: 
                        bondcnts[j]+=1
                        if Ninterps[0]!=1:
                            grid=array([interp3d(ipnts[i],lGridBoundPoints,lGridPoints,lfield) for i in range(len(ipnts))]).reshape(Ninterps)
                        else:
                            grid=array([interp3d(ipnts[i],lGridBoundPoints,lGridPoints,lfield) for i in range(len(ipnts))]).reshape(Ninterps[1:])
                        grids.append(grid)
                        avgGrids[j]+=grid
            else:    
                grid=array([interp3d(ipnts[i],lGridBoundPoints,lGridPoints,lfield) for i in range(len(ipnts))]).reshape(Ninterps)
                grids.append(grid)
                avgGrid+=grid
                bondcnt+=1
    if cutFlag:
        for i,v in enumerate(bondcnts):
            if v==0:
                bondcnts[i]=1
        return [avgGrid/bc for bc,avgGrid in zip(bondcnts,avgGrids)],grids,bondcnts
    return avgGrid/bondcnt,grids,bondcnt
예제 #3
0
def elfcarNeighborAnalysis(elfcarfile,
                           verbose=False,
                           minELF=0.5,
                           maxBondLength=4.0):
    #Loads up an ELFCAR, generates a starting neighbor list from voronoi tesselation
    #Initial neighbors are dropped if bondlength is greater than maxBondLength
    #Generates a bunch of points on a cylinder
    #Maps the cylinder points across each neighbor pair
    #If the average ELF is always above minELF accross this cylinder, atoms are bonded.

    #Parse ELFCAR
    elfcar = open(elfcarfile, "r").readlines()
    (basis, atypes, atoms, header), elf = elfcarIO.read(elfcar)
    lengths = array([basis[0][0], basis[1][1], basis[2][2]])

    #Neighbors
    bounds = [[0, basis[0][0]], [0, basis[1][1]], [0, basis[2][2]]]
    halfNeighbs = voronoiNeighbors(atoms, basis, style="half")

    a = elf.shape
    AvgElf = sum([sum([sum(line) for line in plane])
                  for plane in elf]) / a[0] / a[1] / a[2]
    if verbose:
        print elfcarfile
        print "Average ELF value:", AvgElf

    #Evaluate the ELF between each nieghbor pair
    #creates a bunch of points on a circle in the x-y plane
    def circlePoints(center, radius):
        N = 4
        ps = [float(p) / N * radius for p in range(-N, N + 1)]
        r2 = radius * radius
        points = list()
        for x in ps:
            for y in ps:
                if (x**2 + y**2) <= r2:
                    points.append(asarray([x, y]))
        return asarray(points)

    atoms = asarray([lengths[i] - v for i, v in enumerate(atoms.T)]).T

    #Flip the ELF because its off, thanks a lot VASP.
    elf = elf[::-1, ::-1, ::-1]

    #Loop over atom pairs, generate cylinders
    cylSlices = 10
    cylRadius = 0.7
    cirPoints = circlePoints(a, cylRadius).T
    cylPoints = [
        vstack([cirPoints, zeros(cirPoints.shape[1]) + float(z)])
        for z in range(cylSlices + 1)
    ]
    coordination = zeros(len(atoms))
    neighborsELF = [list() for i in range(len(atoms))]

    for i, ineighbs in enumerate(halfNeighbs):
        a = atoms[i]

        for j in ineighbs:
            #copy the cylinder points so you can play with them...
            localCyl = array(cylPoints)

            #Find the minimum image atom
            b = minImageAtom(a, atoms[j], basis)
            l = minImageDist(a, b, basis)

            if l > maxBondLength or l == 0.0: continue

            #How to map your cylinder onto the local atom
            R = rotmatx([0, 0, l], b - a)

            #Loop over each cylinder slice
            sliceParam = list()
            for cir in localCyl:
                #cir is stretched and rotated cylinder
                cir[2] /= cylSlices / l
                cir = asarray([dot(R, p) + a for p in cir.T]).T

                #cir2 is cir with periodic boundary conditions applied and mapped to index space
                cir2 = asarray([((c / lengths[ind] * elf.shape[ind]) %
                                 (elf.shape[ind] - 1))
                                for ind, c in enumerate(cir)])

                #Interpolation across cylinder
                z = ndimage.map_coordinates(elf, cir2)

                #Average ELF value across each slice.
                sliceParam.append(sum(z) / len(z))

            if min(sliceParam) > minELF:
                #neighbor pair is bonded, count it!
                neighborsELF[i].append(j)
                neighborsELF[j].append(i)

    return neighborsELF
예제 #4
0
def elfcarNeighborAnalysis(elfcarfile,verbose=False,minELF=0.5,maxBondLength=4.0):
    #Loads up an ELFCAR, generates a starting neighbor list from voronoi tesselation
    #Initial neighbors are dropped if bondlength is greater than maxBondLength
    #Generates a bunch of points on a cylinder
    #Maps the cylinder points across each neighbor pair
    #If the average ELF is always above minELF accross this cylinder, atoms are bonded.

    #Parse ELFCAR
    elfcar=open(elfcarfile,"r").readlines()
    (basis,atypes,atoms,header),elf = elfcarIO.read(elfcar)
    lengths=array([basis[0][0],basis[1][1],basis[2][2]])

    #Neighbors
    bounds=[[0,basis[0][0]],[0,basis[1][1]],[0,basis[2][2]]]
    halfNeighbs = voronoiNeighbors(atoms,basis,style="half")

    a=elf.shape
    AvgElf=sum([sum([sum(line) for line in plane]) for plane in elf])/a[0]/a[1]/a[2]
    if verbose:
        print elfcarfile
        print "Average ELF value:",AvgElf

    #Evaluate the ELF between each nieghbor pair
    #creates a bunch of points on a circle in the x-y plane
    def circlePoints(center,radius):
        N=4
        ps=[float(p)/N*radius for p in range(-N,N+1)]
        r2=radius*radius
        points=list()
        for x in ps:
            for y in ps:
                if (x**2+y**2)<=r2:
                    points.append(asarray([x,y]))
        return asarray(points)

    atoms=asarray([lengths[i]-v for i,v in enumerate(atoms.T)]).T

    #Flip the ELF because its off, thanks a lot VASP.
    elf=elf[::-1,::-1,::-1]

    #Loop over atom pairs, generate cylinders
    cylSlices = 10   
    cylRadius = 0.7
    cirPoints = circlePoints(a,cylRadius).T
    cylPoints = [vstack([cirPoints,zeros(cirPoints.shape[1])+float(z)]) for z in range(cylSlices+1)]
    coordination=zeros(len(atoms))
    neighborsELF=[list() for i in range(len(atoms))]

    for i,ineighbs in enumerate(halfNeighbs):
        a=atoms[i]

        for j in ineighbs:
            #copy the cylinder points so you can play with them...
            localCyl=array(cylPoints)

            #Find the minimum image atom
            b=minImageAtom(a,atoms[j],basis)
            l=minImageDist(a,b,basis)

            if l>maxBondLength or l==0.0: continue

            #How to map your cylinder onto the local atom
            R=rotmatx([0,0,l],b-a)

            #Loop over each cylinder slice
            sliceParam=list()
            for cir in localCyl:
                #cir is stretched and rotated cylinder
                cir[2]/=cylSlices/l
                cir=asarray([dot(R,p)+a for p in cir.T]).T
                
                #cir2 is cir with periodic boundary conditions applied and mapped to index space
                cir2=asarray([((c/lengths[ind]*elf.shape[ind])%(elf.shape[ind]-1)) for ind,c in enumerate(cir)])            

                #Interpolation across cylinder
                z=ndimage.map_coordinates(elf,cir2)

                #Average ELF value across each slice.
                sliceParam.append(sum(z)/len(z))

            if min(sliceParam)>minELF:
                #neighbor pair is bonded, count it!
                neighborsELF[i].append(j)
                neighborsELF[j].append(i)

    return neighborsELF