def cost(M, B, run): if areEqual(det(M), 0): return 1000 pftarget = B.pftarget K = lattice() K.vecs = dot(B.vecs, inv(M)) K.det = abs(det(K.vecs)) if run == 'minsv': Nscale = 1 * 1.0 Ncost = Nscale * abs((B.det / K.det) - B.Nmesh) / B.Nmesh # cost = surfvol(K.vecs)*(1+Ncost) cost = surfvol(K.vecs) + Ncost elif run == 'maxpf': # K = lattice() # K.vecs = dot(B.vecs,inv(M));K.det = abs(det(K.vecs)) Nscale = 1 * .5 Ncost = Nscale * abs((B.det / K.det) - B.Nmesh) / B.Nmesh pf = packingFraction(K.vecs) # cost = (1/pf)*(1+Ncost) cost = 1 * abs(pftarget - pf) / pftarget + Ncost elif run == 'minsvsym': Nscale = 1 * .05 #.05; Ncost = Nscale * abs((B.det / K.det) - B.Nmesh) / B.Nmesh pfscale = 1 * 0.5 pfcost = pfscale * surfvol(K.vecs) symerr = symmetryError(K.vecs, B) # print symerr # cost = symerr *(1+Ncost)*(1+shapecost) cost = symerr + Ncost + shapecost elif run == 'maxpfsym': Nscale = 1 * .2 #*.2; Ncost = Nscale * abs((B.det / K.det) - B.Nmesh) / B.Nmesh pf = packingFraction(K.vecs) pfscale = 10 pfcost = pfscale * abs(pftarget - pf) / pftarget symerr = symmetryError(K.vecs, B) # print symerr # cost = symerr *(1+Ncost)*(1+pfcost) cost = symerr + Ncost + pfcost elif run == 'sym': symerr = symmetryError(K.vecs, B) # print symerr cost = symerr elif run == 'sym_sv': symerr = symmetryError(K.vecs, B) shapescale = 1 * 0.5 shapecost = shapescale * surfvol(K.vecs) symerr = symmetryError(K.vecs, B) cost = symerr + shapecost else: sys.exit('Cost type not found in cost function. Stop') return (cost)
def cost(M, B): if areEqual(det(M), 0): return 100 # if areEqual(K.det,0): # return 100 else: K = lattice() K.vecs = dot(B.vecs, inv(M)) K.det = abs(det(K.vecs)) Nscale = 1 * 0.05 Ncost = Nscale * abs((B.det / K.det) - B.Nmesh) / B.Nmesh cost = surfvol(K.vecs) * (1 + Ncost) return cost
def cost(M, B): if areEqual(det(M), 0): return 100 # if areEqual(K.det,0): # return 100 else: K = lattice() K.vecs = dot(B.vecs, inv(M)) K.det = abs(det(K.vecs)) Nscale = 1 * .05 Ncost = Nscale * abs((B.det / K.det) - B.Nmesh) / B.Nmesh cost = surfvol(K.vecs) * (1 + Ncost) return (cost)
def nonDegen(vals): '''Tests whether a vector has one unique element. If so, returns the index''' distinct = [] if isreal(vals[0]) and not areEqual(vals[0],vals[1]) and not areEqual(vals[0],vals[2]): distinct.append(0) if isreal(vals[1]) and not areEqual(vals[1],vals[0]) and not areEqual(vals[1],vals[2]): distinct.append(1) if isreal(vals[2]) and not areEqual(vals[2],vals[0]) and not areEqual(vals[2],vals[1]): distinct.append(2) return distinct
def cost(M,B,run): if areEqual(det(M),0): return 1000 pftarget = B.pftarget K = lattice() K.vecs = dot(B.vecs,inv(M));K.det = abs(det(K.vecs)) if run == 'minsv': Nscale =1*1.0; Ncost = Nscale * abs((B.det/K.det)-B.Nmesh)/B.Nmesh # cost = surfvol(K.vecs)*(1+Ncost) cost = surfvol(K.vecs) + Ncost elif run == 'maxpf': # K = lattice() # K.vecs = dot(B.vecs,inv(M));K.det = abs(det(K.vecs)) Nscale =1*.5; Ncost = Nscale * abs((B.det/K.det)-B.Nmesh)/B.Nmesh pf = packingFraction(K.vecs) # cost = (1/pf)*(1+Ncost) cost = 1 * abs(pftarget - pf)/pftarget + Ncost elif run == 'minsvsym': Nscale =1*.05#.05; Ncost = Nscale * abs((B.det/K.det)-B.Nmesh)/B.Nmesh shapescale = 1 * 0.5; shapecost = shapescale * surfvol(K.vecs) symerr = symmetryError(K.vecs,B) # print symerr # cost = symerr *(1+Ncost)*(1+shapecost) cost = symerr + Ncost + shapecost elif run == 'maxpfsym': Nscale =1*.2; #*.2; Ncost = Nscale * abs((B.det/K.det)-B.Nmesh)/B.Nmesh pf = packingFraction(K.vecs) shapescale = 10 ; shapecost = shapescale * abs(pftarget - pf)/pftarget symerr = symmetryError(K.vecs,B) # print symerr # cost = symerr *(1+Ncost)*(1+shapecost) cost = symerr + Ncost + shapecost elif run == 'sym': symerr = symmetryError(K.vecs,B) # print symerr cost = symerr elif run == 'sym_sv': symerr = symmetryError(K.vecs,B) shapescale = 1 * 0.5; shapecost = shapescale * surfvol(K.vecs) symerr = symmetryError(K.vecs,B) cost = symerr + shapecost else: sys.exit('Cost type not found in cost function. Stop') return(cost)
def nonDegen(vals): '''Tests whether a vector has one unique element. If so, returns the index''' distinct = [] if isreal(vals[0]) and not areEqual(vals[0], vals[1]) and not areEqual( vals[0], vals[2]): distinct.append(0) if isreal(vals[1]) and not areEqual(vals[1], vals[0]) and not areEqual( vals[1], vals[2]): distinct.append(1) if isreal(vals[2]) and not areEqual(vals[2], vals[0]) and not areEqual( vals[2], vals[1]): distinct.append(2) return distinct
def writekpts_vasp_M(path, B, M, K): '''write out kpoints file with IBZKPTS format. This will specify all the kpoints and their weights. No shift is allowed for now''' #Fill a 1st brilloun zone with mesh points. We will choose the 1st BZ to be that given by the parallepiped of (B0, B1, B2) #Since B = KM. The first column of M determines the first column of B (B0) We run trial mesh points over a grid made by the maximum and minimum values of columns of M and the three directions # of K. The first row of M gives the first k direction (first column of K) eps = 1e-4 Kv = K.vecs Bv = B.vecs # nBZpt = 0 # Binv = inv(Bv) # #Dummy set up Monkhorst Pack: # nMP = rint(det(M)**(1/3.0)) # M = array([[nMP,0,0],[0,nMP,0],[0,0,nMP]]); # Kv = dot(Bv,inv(M)) #end dummy print 'M in writekpts_vasp_M' print(M) print 'Kvecs in writekpts_vasp_M' print(Kv) # print 'transpose(Bvecs)in writekpts_vasp_M';print transpose(Bv)*100 print 'det of M', det(M) npts = -1 ktryB = zeros((3, rint(det(M) * 2))) # kpts = zeros((3, rint(det(M) * 2))) #The rows of M determine how each vector (column) of K is used in the sum. #The 1BZ parallelpiped must go from (0,0,0) to each of the other vertices #the close vertices are at B1,B2,B3. So each element of each row must be considered. #The far verictecs are at for these three vectors taken in paris. #To reach the diagonal point of the parallelpiped, #which means that the sums of the rows must be part of the limits. #To reach the three far vertices (not the tip), we have to take the columns of M in pairs:, #which means that we check the limits of the pairs among the elements of each row. #in other words, the limits on the search for each row i of (coefficients of grid basis vector Ki) are the partial sums #of the elements of each row: min(0,a,b,c,a+b,a+c,b+c,a+b+c), max(0,a,b,c,a+b,a+c,b+c,a+b+c) Msums = zeros((3, 8), dtype=int) for i in range(3): a = M[i, 0] b = M[i, 1] c = M[i, 2] Msums[i, 0] = 0 Msums[i, 1] = a Msums[i, 2] = b Msums[i, 3] = c Msums[i, 4] = a + b Msums[i, 5] = a + c Msums[i, 6] = b + c Msums[i, 7] = a + b + c ntry = 0 for i2 in range( amin(Msums[2, :]) - 1, amax(Msums[2, :]) + 1 ): #The rows of M determine how each vector (column) of M is used in the sum for i1 in range(amin(Msums[1, :]) - 1, amax(Msums[1, :]) + 1): for i0 in range(amin(Msums[0, :]) - 1, amax(Msums[0, :]) + 1): ntry += 1 ktry = i0 * Kv[:, 0] + i1 * Kv[:, 1] + i2 * Kv[:, 2] ktryB1 = trimSmall(dot(inv(Bv), transpose(ktry))) #test whether it is in 1st BZ. Transform first to basis of B: #it's in the parallelpiped if its components are all less than one and positive eps = 1e-4 if min(ktryB1) > 0 - eps and max(ktryB1) < 1 - eps: npts += 1 #translate to traditional 1BZ for i in range(3): if ktryB1[i] > 0.5 + eps: ktryB1[i] = ktryB1[i] - 1 if ktryB1[i] < -0.5 + eps: ktryB1[i] = ktryB1[i] + 1 #convert back to cartesian ktry = trimSmall(dot(Bv, transpose(ktryB1))) kpts[:, npts] = ktry npts = npts + 1 #from starting at -1 print 'Grid points tested', ntry print 'Points in 1BZ', npts if not areEqual(npts, rint(det(M))): print det(M) sys.exit( 'Stop. Number of grid points in the 1BZ is not equal to det(M)') #Apply symmetry operations and see which are identical to others. All in Cartesian coords kptssymm = zeros((3, npts)) weights = zeros((npts), dtype=int) #record the first point kptssymm[:, 0] = kpts[:, 0] weights[0] = 1 nksymm = 1 for i in range(1, npts): kB = trimSmall(dot(inv(Bv), transpose(kpts[:, i]))) #rotate found = False for iop in range(B.nops): krot = dot(B.symops[:, :, iop], kpts[:, i]) kB2 = trimSmall(dot(inv(Bv), transpose(krot))) #test whether it matches any we have saved. for iksymm in range(nksymm): if areEqual(krot[0], kptssymm[0, iksymm]) and areEqual( krot[1], kptssymm[1, iksymm]) and areEqual( krot[2], kptssymm[2, iksymm]): # print 'Found equivalent point' weights[iksymm] += 1 found = True # It better be equivalent to only one saved point break if found: break if not found: kptssymm[:, nksymm] = kpts[:, i] weights[nksymm] += 1 nksymm += 1 # print 'symm new point',nksymm print 'Points in reduced 1BZ', nksymm print 'Total weights', sum(weights) print 'Vol BZ/ vol irredBZ', npts / float(nksymm) #convert to basis of B lattice vectors for i in range(nksymm): kptssymm[:, i] = trimSmall(dot(inv(Bv), transpose(kptssymm[:, i]))) # #write POSCAR for vmd: put B vectors in lattice, and kmesh in atomic positions # scale = 10 # poscar = open('POSCARk','w') # poscar.write('Cs I kpoints vs B'+'\n') #different sizes from this label # poscar.write('1.0\n') # for i in [0,1,2]: # poscar.write('%20.15f %20.15f %20.15f \n' % (scale*Bv[0,i], scale*Bv[1,i], scale*Bv[2,i])) # poscar.write('1 %i\n' %npts) # poscar.write('Cartesian\n') # poscar.write('0.0 0.0 0.0\n') # for i in range(npts): # poscar.write('%20.15f %20.15f %20.15f \n' % (scale*kpts[0,i],scale*kpts[1,i],scale*kpts[2,i])) # poscar.close() #write POSCAR with irred BZ. for vmd: put B vectors in lattice, and kmesh in atomic positions scale = 10 poscar = open('POSCARkred', 'w') poscar.write('Cs I kpoints vs B' + '\n') #different sizes from this label poscar.write('1.0\n') for i in [0, 1, 2]: poscar.write('%20.15f %20.15f %20.15f \n' % (scale * Bv[0, i], scale * Bv[1, i], scale * Bv[2, i])) poscar.write('1 %i\n' % nksymm) poscar.write('Cartesian\n') poscar.write('0.0 0.0 0.0\n') for i in range(nksymm): poscar.write('%20.15f %20.15f %20.15f %20.15f \n' % (scale * kptssymm[0, i], scale * kptssymm[1, i], scale * kptssymm[2, i], weights[i])) poscar.close() poscar = open('KPOINTS', 'w') poscar.write('BCH generated via bestmeshiter' + '\n') #different sizes from this label poscar.write('%i\n' % nksymm) poscar.write('Reciprocal lattice units\n') for i in range(nksymm): poscar.write( '%20.15f %20.15f %20.15f %i\n' % (kptssymm[0, i], kptssymm[1, i], kptssymm[2, i], weights[i])) poscar.close()
def bestmeshEigen(Blatt,Nmesh): '''The kmesh can be related to the reciprocal lattice B by B = KM, where M is an integer 3x3 matrix So K = B Inv(M) . Work in the inverse space of this problem, where we can work with M instead of Inv(M). T(InvK) = T(InvB)T(M). Define S = T(InvK), and the real lattice A = T(InvB). So S = A T(M) is a superlattice on the real lattice. Minimization scheme''' ############################################################## ########################## Script ############################ M = zeros((3,3),dtype = int) S = zeros((3,3),dtype = fprec) B = lattice() A = lattice() K = lattice() B.vecs = Blatt/2/pi #Don't use 2pi constants in RL here. #############End BCT lattice eps = 1.0e-6 B.det = det(B.vecs) B.Nmesh = Nmesh print 'B vectors';print B.vecs # #print 'B transpose'; print transpose(B.vecs) print 'Det of B', B.det print 'Orth Defect of B', orthdef(B.vecs) print 'Surf/vol of B', surfvol(B.vecs) [B.symops,B.nops] = getGroup(B.vecs) print 'Number of symmetry operations', B.nops eigendirs = zeros([3,3,B.nops],dtype = int) #print 'symmetry operations of B\n' #for j in range(nopsB): # print j # op = array(symopsB[:,:,j]) # print op #find real lattice A.vecs = transpose(inv(B.vecs)) A.det = det(A.vecs) A.Nmesh = Nmesh print;print 'A vectors';print A.vecs print 'Det of A', A.det print 'Orth Defect of A', orthdef(A.vecs) print 'Surf/vol of A', surfvol(A.vecs) [A.symops,A.nops] = getGroup(A.vecs) if A.nops != B.nops: sys.exit('Number of operations different for A and B; stop') testvecs = [];testindices = [] # print 'symmetry operations R of A\n' for k in range(A.nops): print print k op = array(A.symops[:,:,k]) print'symop R of A'; print trimSmall(op) m = trimSmall(dot(dot(inv(A.vecs), A.symops[:,:,k]),A.vecs)) print'symop m'; print m # print 'det(m)', det(m) 'Take eigenvectors in cartesian space' [vals,vecs]=eig(op) print 'eigen of m',vals print 'eigenvecs are calculated in cartesian space'; print vecs #transform to m space for i in range(3): vecs[:,i] = dot(inv(A.vecs),vecs[:,i]) print 'eigenvecs in m space'; print vecs print 'scaled to integers' for i in range(3): vecs[:,i] = vecs[:,i]/abs(vecs[:,i])[nonzero(vecs[:,i])].min() vecs = rint(vecs) print vecs eigendirs[:,:,k]= vecs #find operations with nondegenerate real eigenvalues print 'nonDegen', nonDegen(vals) for i in nonDegen(vals): if not matchDirection(transpose(vecs[:,i]),testvecs): #keep only unique directions testvecs.append(vecs[:,i].real/abs(vecs[:,i])[nonzero(vecs[:,i])].min()) testindices.append([k,i]) #print; print oplist; print 'testvecs'; print testvecs #print testindices MT = zeros((3,3),dtype = fprec) if len(testvecs) == 0: print 'No eigen directions' [M,K.vecs] = unconstrainedSVsearch(B) if det(K.vecs)==0: sys.exit('Det(K) is zero after unconstrained search! Stop') if not checksymmetry(K.vecs,B): sys.exit('Symmetry missing in mesh! Stop') # MT = unconstrainedmin(B.vecs) if len(testvecs) == 1: print 'Only 1 eigen direction' #Choose this one and the other two in the plane perpendicular to this. MT[:,0] = testvecs[0] # print 'testindices',testindices kop = testindices[0][0] #useful operator ieigen = testindices[0][1] #index of the only eigendirection op = array(A.symops[:,:,kop]) # print trimSmall(op) # find one other direction in the plane perp to the eigendireation; either degenerate eigenvalue will do. otherindices = nonzero(array([0,1,2])-ieigen) print eigendirs[:,:,otherindices[0][0]] MT[:,1] = eigendirs[:,:,kop][:,otherindices[0][0]] #Make 3rd vector perp as possible to the other two ur0 = dot(A.vecs,MT[:,0])/norm(dot(A.vecs,MT[:,0])) #unit vectors in real space ur1 = dot(A.vecs,MT[:,1])/norm(dot(A.vecs,MT[:,1])) ur2 = cross(ur0,ur1) print ur0 print ur1 print ur2 print 'ur2 transformed to m space'; print dot(inv(A.vecs),ur2) mvec = dot(inv(A.vecs),ur2) #transformed to M space, but real mvec = rint(mvec/abs(mvec[nonzero(mvec)]).min()) #Scale so smallest comp is 1 MT[:,2] = mvec print 'MT from single operator';print MT print 'starting superlattice'; print dot(A.vecs,MT) # Q2 = MT2mesh_three_ns(MT,B) Q2 = MT2mesh(MT,B,A) if checksymmetry(Q2,B): SV = surfvol(Q2) # print round(surfvol(Q2),4),round(orthdef(Q2),4),'SV of Q2,','OD' K.vecs = Q2 else: print'Q from single operator fails symmetry' if len(testvecs) == 2: print 'Only 2 eigen directions' MT[:,0] = testvecs[0] MT[:,1] = testvecs[1] #Make 3rd vector perp as possible to the other two ur0 = dot(A.vecs,MT[:,0])/norm(dot(A.vecs,MT[:,0])) #unit vector in real space ur1 = dot(A.vecs,MT[:,1])/norm(dot(A.vecs,MT[:,1])) ur2 = cross(ur0,ur1) MT[:,2] = rint(dot(inv(A.vecs),ur2)) print 'MT from two eigen directions';print MT # Q2 = MT2mesh_three_ns(MT,B) Q2 = MT2mesh(MT,B) if checksymmetry(Q2,B): SV = surfvol(Q2) print round(surfvol(Q2),4),round(orthdef(Q2),4),'SV of Q2,','OD' K.vecs = Q2 else: print'Q fails symmetry' if len(testvecs) >= 3: print 'MT from three eigen directions' testvecstrials = [list(x) for x in combinations(testvecs,3)] print testvecstrials bestindex = -1 bestcost = 1000 for i,vecs in enumerate(testvecstrials): print; print 'trial',i print vecs MT[:,0] = vecs[0] MT[:,1] = vecs[1] MT[:,2] = vecs[2] print 'MT'; print MT print 'det MT', det(MT) if not areEqual(det(MT),0): Q2 = MT2mesh(MT,B) if checksymmetry(Q2,B): Nscale =1*.8; Ncost = Nscale * abs((B.det/det(Q2))-B.Nmesh)/B.Nmesh cost = surfvol(Q2)*(1+Ncost) print cost if cost<bestcost: bestcost = cost; bestindex = i; K.vecs = Q2 print round(surfvol(Q2),4),round(orthdef(Q2),4),'SV of Q2,','OD' else: print'Q from trial %i fails symmetry' % i print '___________ Best mesh ___________' print 'trial', bestindex if checksymmetry(K.vecs,B): print K.vecs K.det = abs(det(K.vecs)) print 'N of mesh', B.det/K.det SV = surfvol(K.vecs) print round(surfvol(K.vecs),4),round(orthdef(K.vecs),4),'SV of Q2,','OD' else: print'K mesh fails symmetry'
def writekpts_vasp_M(path,Bv,M,nops,symmops): '''write out kpoints file with IBZKPTS format. This will specify all the kpoints and their weights. No shift is allowed for now. The symmops are those of B''' #Fill a 1st brilloun zone with mesh points. We will choose the 1st BZ to be that given by the parallepiped of (B0, B1, B2) #Since B = KM. The first column of M determines the first column of B (B0) We run trial mesh points over a grid made by the maximum and minimum values of columns of M and the three directions # of K. The first row of M gives the first k direction (first column of K) eps = 1e-4 M = M * sign(det(M)) # want positive determinants Kv = dot(B,inv(M)) nBZpt = 0 Binv = inv(Bv) print 'M in writekpts_vasp_M';print (M) print 'Kvecs in writekpts_vasp_M';print (Kv) # print 'transpose(Bvecs)in writekpts_vasp_M';print transpose(Bv)*100 print 'det of M', det(M) npts = -1 ktryB = zeros((3,rint(det(M)*2))) kpts = zeros((3,rint(det(M)*2))) #all the kpoints in the entire 1BZ #The rows of M determine how each vector (column) of K is used in the sum. #The 1BZ parallelpiped must go from (0,0,0) to each of the other vertices #the close vertices are at B1,B2,B3. So each element of each row must be considered. #The far vertices are at for these three vectors taken in pairs. #To reach the diagonal point of the parallelpiped, #which means that the sums of the rows must be part of the limits. #To reach the three far vertices (not the tip), we have to take the columns of M in pairs:, #which means that we check the limits of the pairs among the elements of each row. #in other words, the limits on the search for each row i of (coefficients of grid basis vector Ki) are the partial sums #of the elements of each row: min(0,a,b,c,a+b,a+c,b+c,a+b+c), max(0,a,b,c,a+b,a+c,b+c,a+b+c) Msums = zeros((3,8),dtype = int) for i in range(3): a = M[i,0]; b = M[i,1];c = M[i,2]; Msums[i,0]=0; Msums[i,1]=a; Msums[i,2]=b;Msums[i,3]=c; Msums[i,4]=a+b; Msums[i,5]=a+c; Msums[i,6]=b+c; Msums[i,7]=a+b+c ntry =0 for i2 in range(amin(Msums[2,:])-1,amax(Msums[2,:])+1): #The rows of M determine how each vector (column) of M is used in the sum for i1 in range(amin(Msums[1,:])-1,amax(Msums[1,:])+1): for i0 in range(amin(Msums[0,:])-1,amax(Msums[0,:])+1): ntry += 1 ktry = i0*Kv[:,0] + i1*Kv[:,1] + i2*Kv[:,2] ktryB1 = trimSmall(dot(inv(Bv),transpose(ktry))) #test whether it is in 1st BZ. Transform first to basis of B: #it's in the parallelpiped if its components are all less than one and positive eps = 1e-4 if min(ktryB1)>0-eps and max(ktryB1)<1-eps : npts += 1 # print i0,i1,i2, trimSmall(ktryB1) #translate to traditional 1BZ for i in range(3): if ktryB1[i]>0.5+eps: ktryB1[i] = ktryB1[i] - 1 if ktryB1[i]<-0.5+eps: ktryB1[i] = ktryB1[i] + 1 #convert back to cartesian ktry = trimSmall(dot(Bv,transpose(ktryB1))) kpts[:,npts] = ktry npts = npts+1 #from starting at -1 print 'Grid points tested',ntry print 'Points in 1BZ',npts if not areEqual(npts,rint(det(M))): print det(M) sys.exit('Stop. Number of grid points in the 1BZ is not equal to det(M)') #Apply symmetry operations and see which are identical to others. All in Cartesian coords kptssymm = zeros((3,npts)) #the kpoints in irreducible 1BZ weights = zeros((npts),dtype = int) #record the first point print '0'; print kpts[:,0] kptssymm[:,0] = kpts[:,0] weights[0] = 1 nksymm = 1 for i in range(1,npts): #test all print; print i;print kpts[:,i] kB = trimSmall(dot(inv(Bv),transpose(kpts[:,i])))#now in the basis of B vectors print kB, 'in recip cords' # if areEqual(kB[0],0.5) or areEqual(kB[1],0.5) or areEqual(kB[2],0.5) : # print'Boundary point', kB #rotate found = False for iop in range(nops): krot = dot(symops[:,:,iop],kpts[:,i]) kB2 = trimSmall(dot(inv(Bv),transpose(krot))) # if areEqual(kB[0],0.5) or areEqual(kB[1],0.5) or areEqual(kB[2],0.5) : # print kB2 #test whether it matches any we have saved. for iksymm in range(nksymm): if areEqual(krot[0],kptssymm[0,iksymm]) and areEqual(krot[1],kptssymm[1,iksymm]) and areEqual(krot[2],kptssymm[2,iksymm]) : print 'Found equivalent point',iksymm;print kptssymm[:,iksymm] weights[iksymm] += 1 found = True # It better be equivalent to only one point in irreducible 1BZ break if found: break if not found: kptssymm[:,nksymm] = kpts[:,i] weights[nksymm] += 1 nksymm += 1 print 'symm new point',nksymm print 'Points in reduced 1BZ',nksymm print 'Total weights',sum(weights) print 'Vol BZ/ vol irredBZ', npts/float(nksymm) #convert to basis of B lattice vectors for i in range(nksymm): kptssymm[:,i] = trimSmall(dot(inv(Bv),transpose(kptssymm[:,i]))) # #write POSCAR for vmd: put B vectors in lattice, and kmesh in atomic positions # scale = 10 # poscar = open('POSCARk','w') # poscar.write('Cs I kpoints vs B'+'\n') #different sizes from this label # poscar.write('1.0\n') # for i in [0,1,2]: # poscar.write('%20.15f %20.15f %20.15f \n' % (scale*Bv[0,i], scale*Bv[1,i], scale*Bv[2,i])) # poscar.write('1 %i\n' %npts) # poscar.write('Cartesian\n') # poscar.write('0.0 0.0 0.0\n') # for i in range(npts): # poscar.write('%20.15f %20.15f %20.15f \n' % (scale*kpts[0,i],scale*kpts[1,i],scale*kpts[2,i])) # poscar.close() #write POSCAR with irred BZ. for vmd: put B vectors in lattice, and kmesh in atomic positions scale = 10 poscar = open('POSCARkred','w') poscar.write('Kpoints in BZ'+'\n') #different sizes from this label poscar.write('1.0\n') for i in [0,1,2]: poscar.write('%20.15f %20.15f %20.15f \n' % (scale*Bv[0,i], scale*Bv[1,i], scale*Bv[2,i])) poscar.write('1 %i\n' %nksymm) poscar.write('Cartesian\n') poscar.write('0.0 0.0 0.0\n') for i in range(nksymm): poscar.write('%20.15f %20.15f %20.15f %20.15f \n' % (scale*kptssymm[0,i],scale*kptssymm[1,i],scale*kptssymm[2,i], weights[i])) poscar.close() kpoints = open('KPOINTS','w') kpoints.write('BCH generated'+'\n') #different sizes from this label kpoints.write('%i\n' % nksymm) kpoints.write('Reciprocal lattice units\n') for i in range(nksymm): kpoints.write('%20.15f %20.15f %20.15f %i\n' % (kptssymm[0,i],kptssymm[1,i],kptssymm[2,i], weights[i])) kpoints.close()
def bestmeshEigen(Blatt, Nmesh): '''The kmesh can be related to the reciprocal lattice B by B = KM, where M is an integer 3x3 matrix So K = B Inv(M) . Work in the inverse space of this problem, where we can work with M instead of Inv(M). T(InvK) = T(InvB)T(M). Define S = T(InvK), and the real lattice A = T(InvB). So S = A T(M) is a superlattice on the real lattice. Minimization scheme Nothing calls this routine''' ############################################################## ########################## Script ############################ M = zeros((3, 3), dtype=int) S = zeros((3, 3), dtype=fprec) B = lattice() A = lattice() K = lattice() B.vecs = Blatt / 2 / pi #Don't use 2pi constants in RL here. #############End BCT lattice eps = 1.0e-6 B.det = det(B.vecs) B.Nmesh = Nmesh print 'B vectors' print B.vecs # #print 'B transpose'; print transpose(B.vecs) print 'Det of B', B.det print 'Orth Defect of B', orthdef(B.vecs) print 'Surf/vol of B', surfvol(B.vecs) [B.symops, B.nops] = getGroup(B.vecs) print 'Number of symmetry operations', B.nops eigendirs = zeros([3, 3, B.nops], dtype=int) #print 'symmetry operations of B\n' #for j in range(nopsB): # print j # op = array(symopsB[:,:,j]) # print op #find real lattice A.vecs = transpose(inv(B.vecs)) A.det = det(A.vecs) A.Nmesh = Nmesh print print 'A vectors' print A.vecs print 'Det of A', A.det print 'Orth Defect of A', orthdef(A.vecs) print 'Surf/vol of A', surfvol(A.vecs) [A.symops, A.nops] = getGroup(A.vecs) if A.nops != B.nops: sys.exit('Number of operations different for A and B; stop') testvecs = [] testindices = [] # print 'symmetry operations R of A\n' for k in range(A.nops): print print k op = array(A.symops[:, :, k]) print 'symop R of A' print trimSmall(op) m = trimSmall(dot(dot(inv(A.vecs), A.symops[:, :, k]), A.vecs)) print 'symop m' print m # print 'det(m)', det(m) 'Take eigenvectors in cartesian space' [vals, vecs] = eig(op) print 'eigen of m', vals print 'eigenvecs are calculated in cartesian space' print vecs #transform to m space for i in range(3): vecs[:, i] = dot(inv(A.vecs), vecs[:, i]) print 'eigenvecs in m space' print vecs print 'scaled to integers' for i in range(3): vecs[:, i] = vecs[:, i] / abs(vecs[:, i])[nonzero(vecs[:, i])].min() vecs = rint(vecs) print vecs eigendirs[:, :, k] = vecs #find operations with nondegenerate real eigenvalues print 'nonDegen', nonDegen(vals) for i in nonDegen(vals): if not matchDirection(transpose(vecs[:, i]), testvecs): #keep only unique directions testvecs.append(vecs[:, i].real / abs(vecs[:, i])[nonzero(vecs[:, i])].min()) testindices.append([k, i]) #print; print oplist; print 'testvecs' print testvecs #print testindices MT = zeros((3, 3), dtype=fprec) if len(testvecs) == 0: print 'No eigen directions' [M, K.vecs] = unconstrainedSVsearch(B) if det(K.vecs) == 0: sys.exit('Det(K) is zero after unconstrained search! Stop') if not checksymmetry(K.vecs, B): sys.exit('Symmetry missing in mesh! Stop') # MT = unconstrainedmin(B.vecs) if len(testvecs) == 1: print 'Only 1 eigen direction' #Choose this one and the other two in the plane perpendicular to this. MT[:, 0] = testvecs[0] # print 'testindices',testindices kop = testindices[0][0] #useful operator ieigen = testindices[0][1] #index of the only eigendirection op = array(A.symops[:, :, kop]) # print trimSmall(op) # find one other direction in the plane perp to the eigendireation; either degenerate eigenvalue will do. otherindices = nonzero(array([0, 1, 2]) - ieigen) print eigendirs[:, :, otherindices[0][0]] MT[:, 1] = eigendirs[:, :, kop][:, otherindices[0][0]] #Make 3rd vector perp as possible to the other two ur0 = dot(A.vecs, MT[:, 0]) / norm(dot( A.vecs, MT[:, 0])) #unit vectors in real space ur1 = dot(A.vecs, MT[:, 1]) / norm(dot(A.vecs, MT[:, 1])) ur2 = cross(ur0, ur1) print ur0 print ur1 print ur2 print 'ur2 transformed to m space' print dot(inv(A.vecs), ur2) mvec = dot(inv(A.vecs), ur2) #transformed to M space, but real mvec = rint( mvec / abs(mvec[nonzero(mvec)]).min()) #Scale so smallest comp is 1 MT[:, 2] = mvec print 'MT from single operator' print MT print 'starting superlattice' print dot(A.vecs, MT) # Q2 = MT2mesh_three_ns(MT,B) Q2 = MT2mesh(MT, B, A) if checksymmetry(Q2, B): SV = surfvol(Q2) # print round(surfvol(Q2),4),round(orthdef(Q2),4),'SV of Q2,','OD' K.vecs = Q2 else: print 'Q from single operator fails symmetry' if len(testvecs) == 2: print 'Only 2 eigen directions' MT[:, 0] = testvecs[0] MT[:, 1] = testvecs[1] #Make 3rd vector perp as possible to the other two ur0 = dot(A.vecs, MT[:, 0]) / norm(dot( A.vecs, MT[:, 0])) #unit vector in real space ur1 = dot(A.vecs, MT[:, 1]) / norm(dot(A.vecs, MT[:, 1])) ur2 = cross(ur0, ur1) MT[:, 2] = rint(dot(inv(A.vecs), ur2)) print 'MT from two eigen directions' print MT # Q2 = MT2mesh_three_ns(MT,B) Q2 = MT2mesh(MT, B) if checksymmetry(Q2, B): SV = surfvol(Q2) print round(surfvol(Q2), 4), round(orthdef(Q2), 4), 'SV of Q2,', 'OD' K.vecs = Q2 else: print 'Q fails symmetry' if len(testvecs) >= 3: print 'MT from three eigen directions' testvecstrials = [list(x) for x in combinations(testvecs, 3)] print testvecstrials bestindex = -1 bestcost = 1000 for i, vecs in enumerate(testvecstrials): print print 'trial', i print vecs MT[:, 0] = vecs[0] MT[:, 1] = vecs[1] MT[:, 2] = vecs[2] print 'MT' print MT print 'det MT', det(MT) if not areEqual(det(MT), 0): Q2 = MT2mesh(MT, B) if checksymmetry(Q2, B): Nscale = 1 * .8 Ncost = Nscale * abs((B.det / det(Q2)) - B.Nmesh) / B.Nmesh cost = surfvol(Q2) * (1 + Ncost) print cost if cost < bestcost: bestcost = cost bestindex = i K.vecs = Q2 print round(surfvol(Q2), 4), round(orthdef(Q2), 4), 'SV of Q2,', 'OD' else: print 'Q from trial %i fails symmetry' % i print '___________ Best mesh ___________' print 'trial', bestindex if checksymmetry(K.vecs, B): print K.vecs K.det = abs(det(K.vecs)) print 'N of mesh', B.det / K.det SV = surfvol(K.vecs) print round(surfvol(K.vecs), 4), round(orthdef(K.vecs), 4), 'SV of Q2,', 'OD' else: print 'K mesh fails symmetry'
else: print'Q fails symmetry' if len(testvecs) >= 3: testvecstrials = [list(x) for x in combinations(testvecs,3)] # print testvecstrials bestindex = -1 bestcost = 1000 for i,vecs in enumerate(testvecstrials): print; print 'trial',i MT[:,0] = vecs[0] MT[:,1] = vecs[1] MT[:,2] = vecs[2] print 'MT from three eigen directions';print MT # print 'det MT', det(MT) if not areEqual(det(MT),0): Q2 = MT2mesh(MT,B) if checksymmetry(Q2,B): Nscale =1*.8; Ncost = Nscale * abs((B.det/det(Q2))-B.Nmesh)/B.Nmesh cost = surfvol(Q2)*(1+Ncost) if cost<bestcost: bestcost = cost; bestindex = i; K.vecs = Q2 # print round(surfvol(Q2),4),round(orthdef(Q2),4),'SV of Q2,','OD' else: print'Q fails symmetry' print '___________ Best mesh ___________' print 'trial', bestindex if checksymmetry(K.vecs,B): print K.vecs K.det = abs(det(K.vecs)) print 'N of mesh', B.det/K.det SV = surfvol(K.vecs)
def matchDirection(vec,list): '''if vec parallel or antiparallel to any vector in the list, don't include it''' for vec2 in list: if areEqual(abs(cosvecs(vec,vec2)),1.0): return True return False
def matchDirection(vec, list): '''if vec parallel or antiparallel to any vector in the list, don't include it''' for vec2 in list: if areEqual(abs(cosvecs(vec, vec2)), 1.0): return True return False