def three_perp_eigs(A):
    testvecs = []
    testindices = []
    svecs = zeros((3, 3), dtype=float)
    for k in range(A.nops):
        #        print; print k
        op = array(A.symops[:, :, k])
        [vals, vecs] = eig(op)
        vecs = array(vecs)
        #find operations with nondegenerate real eigenvalues
        #        print k, nonDegen(vals)
        for i in nonDegen(vals):
            if not matchDirection(transpose(vecs[:, i]),
                                  testvecs):  #keep only unique directions
                testvecs.append(real(vecs[:, i]))
                testindices.append([k, i])
    if len(testvecs) >= 3:
        testvecstrials = [list(x) for x in combinations(testvecs, 3)]
        #        print testvecstrials
        for trial in testvecstrials:
            #find superlattice
            for i in range(3):
                #                print; print 'trial u',trial[i]
                svecs[i, :] = lattvec_u(A.vecs, trial[i])


#                print svecs[i,:]
#                print 'lattice m for lattice vector', dot(inv(A.vecs),transpose(svecs[i,:]))
#            print 'cosvecs', cosvecs(svecs[0,:],svecs[1,:]) , cosvecs(svecs[1,:],svecs[2,:]) , cosvecs(svecs[2,:],svecs[0,:])
#            print arenormal(svecs[0,:],svecs[1,:]) , arenormal(svecs[1,:],svecs[2,:]) , arenormal(svecs[2,:],svecs[0,:])
            if arenormal(svecs[0, :], svecs[1, :]) and arenormal(
                    svecs[1, :], svecs[2, :]) and arenormal(
                        svecs[2, :], svecs[0, :]):
                S = transpose(array([svecs[0, :], svecs[1, :], svecs[2, :]]))
                #                print 'found 3 perp'; print unique_anorms(S)
                #                print S; print norm(S[:,0]); print norm(S[:,1]); print norm(S[:,2])
                #                print unique_anorms(S).count(True); print A.lattype
                if A.lattype == 'Cubic' and unique_anorms(S).count(True) == 0:
                    return trimSmall(S)
                if A.lattype == 'Tetragonal' and unique_anorms(S).count(
                        True) <= 1:
                    return trimSmall(S)
                if A.lattype == 'Orthorhombic':  #and unique_anorms(S).count(True) == 3:
                    return trimSmall(S)
    sys.exit('error in three_perp_eigs')
Example #2
0
def three_perp_eigs(A):
    testvecs = []; testindices = []
    svecs = zeros((3,3),dtype = float)
    for k in range(A.nops):
#        print; print k
        op = array(A.symops[:,:,k])
        [vals,vecs]=eig(op); vecs = array(vecs)      
        #find operations with nondegenerate real eigenvalues
#        print k, nonDegen(vals)
        for i in nonDegen(vals):
            if not matchDirection(transpose(vecs[:,i]),testvecs): #keep only unique directions    
                testvecs.append(real(vecs[:,i]))
                testindices.append([k,i])
    if len(testvecs) >= 3:
        testvecstrials = [list(x) for x in combinations(testvecs,3)]
#        print testvecstrials
        for trial in testvecstrials:
            #find superlattice
            for i in range(3):
#                print; print 'trial u',trial[i]
                svecs[i,:] = lattvec_u(A.vecs,trial[i])
#                print svecs[i,:]
#                print 'lattice m for lattice vector', dot(inv(A.vecs),transpose(svecs[i,:]))
#            print 'cosvecs', cosvecs(svecs[0,:],svecs[1,:]) , cosvecs(svecs[1,:],svecs[2,:]) , cosvecs(svecs[2,:],svecs[0,:])
#            print arenormal(svecs[0,:],svecs[1,:]) , arenormal(svecs[1,:],svecs[2,:]) , arenormal(svecs[2,:],svecs[0,:])           
            if arenormal(svecs[0,:],svecs[1,:]) and arenormal(svecs[1,:],svecs[2,:]) and arenormal(svecs[2,:],svecs[0,:]):
                S = transpose(array([svecs[0,:],svecs[1,:],svecs[2,:]]))
#                print 'found 3 perp'; print unique_anorms(S)
#                print S; print norm(S[:,0]); print norm(S[:,1]); print norm(S[:,2])
#                print unique_anorms(S).count(True); print A.lattype
                if A.lattype == 'Cubic' and unique_anorms(S).count(True) == 0:
                    return trimSmall(S) 
                if A.lattype == 'Tetragonal' and unique_anorms(S).count(True) <= 1:
                    return trimSmall(S) 
                if A.lattype == 'Orthorhombic': #and unique_anorms(S).count(True) == 3:
                    return trimSmall(S)
    sys.exit('error in three_perp_eigs')
Example #3
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'    
Example #4
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'
    print trimSmall(op)
    m = trimSmall(dot(dot(inv(A.vecs[:,:]), A.symops[:,:,k]),A.vecs[:,:])  ) 
    [vals,vecs]=eig(m); vecs = array(vecs)
    print 'symop m'; print m

    print 'det(m)', det(m)
    print 'eigen of m',vals
    print vecs
    print 'as rows, scaled to integers'
    print vecs[:,0]/abs(vecs[:,0])[nonzero(vecs[:,0])].min()
    print vecs[:,1]/abs(vecs[:,1])[nonzero(vecs[:,1])].min()
    print vecs[:,2]/abs(vecs[:,2])[nonzero(vecs[:,2])].min()
    
    #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 testindices
MT = zeros((3,3),dtype = int)

if len(testvecs) == 0:
    print 'No eigen directions'
    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')