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