Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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)
Exemplo n.º 4
0
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    
Exemplo n.º 5
0
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)  
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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()
Exemplo n.º 8
0
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'    
Exemplo n.º 9
0
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()
Exemplo n.º 10
0
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'
Exemplo n.º 11
0
    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)
Exemplo n.º 12
0
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
Exemplo n.º 13
0
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