示例#1
0
文件: ucell.py 项目: ont/cbox
    def __init__( self, *args, **kargs ):
        if len( args ) == 6:
            a,b,c, alpha, beta, gamma = args
            if kargs.get( 'indeg', False ):
                self.rep = Reper.from_abc( a,b,c, alpha * math.pi / 180.0, beta * math.pi / 180.0, gamma * math.pi / 180.0 )
            else:
                self.rep = Reper.from_abc( a,b,c, alpha, beta, gamma )
        elif len( args ) == 9:
            self.rep = Reper( Vec( *args[0:3] ), Vec( *args[3:6] ), Vec( *args[6:9] ) )
        else:
            assert type( args[ 0 ] ) is Reper
            self.rep = args[ 0 ]

        self.atoms = {}
        self.decart = kargs.get( 'decart', False )  ## by default assume that all coordinates of atoms in fractional coordinates
示例#2
0
def from_abc(klass, a, b, c, alpha, beta, gamma):
    """ Create 3 vectors from six parameters
    """
    sin_gamma = sin(gamma)
    cos_gamma = cos(gamma)
    tan_gamma = tan(gamma)
    cos_beta = cos(beta)
    cos_alpha = cos(alpha)
    v1 = Vec(a, 0, 0)
    v2 = Vec(b * cos_gamma, b * sin_gamma, 0)
    v3 = Vec(
        c * cos_beta, -(c * cos_beta / tan_gamma) + c * cos_alpha / sin_gamma,
        sqrt(c**2 - (c * cos_beta)**2 -
             (-(c * cos_beta / tan_gamma) + c * cos_alpha / sin_gamma)**2))
    return Reper(v1, v2, v3)
示例#3
0
def norm(self):
    """ Reduce & make all zelling args negative.
    """
    vs = [self.v1, self.v2, self.v3, (self.v1 + self.v2 + self.v3) * -1]

    f = True
    while f:
        f = False
        for i, v1 in enumerate(vs):
            for j, v2 in enumerate(vs):
                if i != j and v1 * v2 > 0.0001:
                    for k in xrange(4):
                        if k != i and k != j:
                            vs[k] += v1  ## add v1 to all, except v1 and v2
                    vs[i] *= -1  ## v1 --> -v1
                    v1 *= -1  ## also correct cycle var
                    f = True

    return Reper(vs[0], vs[1], vs[2])
示例#4
0
def minimize(self):
    """ Reduce reper to 3 minimal vector.
    """
    vs = [self.v1, self.v2, self.v3]
    f = True
    while f:
        f = False
        vts = [t for t in vs]
        abc = ( (i,j,k) for i in xrange( -1, 2 )\
                        for j in xrange( -1, 2 )\
                        for k in xrange( -1, 2 ) )
        for a, b, c in abc:
            vnew = a * vs[0] + b * vs[1] + c * vs[2]
            for i, v in enumerate(vts):
                if v.vlen2() > vnew.vlen2():
                    vo, vts[i] = vts[i], vnew
                    if abs(vts[0] * vts[1].vcross(vts[2])) > 0.0001:
                        f = True
                    else:
                        vts[i] = vo
        #print vs, vts, f
        vs = vts

    return Reper(*vs)
示例#5
0
文件: ucell_min.py 项目: ont/cbox
def to_min( self ):
    decart = self.decart

    self.to_decart() ## transform coordinates to decart basis
    rep = self.rep   ## alias
    near = {}

    ext = self * 1   ## extend in all directions by 1

    mps = min( self.atoms.values(), key = lambda l: len( l ) )  ## "minimal points"
                                                                ## this is minimal group of points
    mps = list( mps )  ## convert set() to ordered list()

    #print "minimal points = ", mps

    eqv_dr = set()  ## all possible translations wich translate each point of
                    ## this ucell (self) to extended ucell (ext)

    #print '--[1]-- find eqv_dr'
    ## for each pair from mps...
    for i in xrange( len(mps) ):
        for j in xrange( i+1, len(mps) ):
            dr = mps[i] - mps[j]  ## vec to translate
            uct = self + dr       ## translated ucell

            eqv = True         ## translate equiv or not
            for k,vs in uct:   ## for each groups of atoms...  (k = group name, vs = list of positions)
                if not vs.issubset( ext.atoms[ k ] ):  ## some points not intersected with others
                    eqv = False
                    break
            if eqv:
                eqv_dr.add( dr )

    eqv_dr.update( list( rep ) )  ## add vectors from original reper

    #print "possible translations = ", eqv_dr

    ## sort vectors by its lengs
    eqv_dr = list( eqv_dr )
    eqv_dr.sort( key = lambda v: v.vlen() )

    #DEBUG DRAW
    #for v in eqv_dr:
    #    drawgl( v, style="line", color=(1,0,0) )

    #print '--[2]-- find v1,v2,v3'
    ## take first vector
    for v1 in eqv_dr:
        v2, v3 = None, None

        ## take second shorterst wich is not lie on one line with v1
        v1n = v1.norm()
        for v in eqv_dr:
            if not v1n == v.norm():
                #print v1n, v.norm()
                v2 = v
                break

        ## take third shortest wich is not coplanar with v1 and v2
        vc = v1.vcross( v2 )
        for v in eqv_dr:
            if abs( vc * v ) > 0.05:
                v3 = v
                break

        if v2 and v3: ## good solution founded
            nrep = Reper( v1,v2,v3 ) ## new reper
            break


    #DEBUG DRAW
    #for v in nrep:
    #    drawgl( v, style="line", color=(0,1,0) )
    #print '--[3]-- reduce ucell'

    uc   = UCell( nrep, decart = True )  ## all atoms in decart coordinate system

    ## reduce basis
    for k,vs in self.atoms.iteritems():
        vsn = nrep.dec2frac( vs )
        vsn = map( lambda v: v.z2o(), vsn )
        vsn = set( vsn )
        vsn = nrep.frac2dec( vsn )
        uc.add( k, vsn )


    if not decart:
        self.to_fract()  ## restore state of ucell
        uc.to_fract()    ## convert answer to the same coordinate system

    return uc
示例#6
0
文件: ucell.py 项目: ont/cbox
class UCell( object ):
    def __init__( self, *args, **kargs ):
        if len( args ) == 6:
            a,b,c, alpha, beta, gamma = args
            if kargs.get( 'indeg', False ):
                self.rep = Reper.from_abc( a,b,c, alpha * math.pi / 180.0, beta * math.pi / 180.0, gamma * math.pi / 180.0 )
            else:
                self.rep = Reper.from_abc( a,b,c, alpha, beta, gamma )
        elif len( args ) == 9:
            self.rep = Reper( Vec( *args[0:3] ), Vec( *args[3:6] ), Vec( *args[6:9] ) )
        else:
            assert type( args[ 0 ] ) is Reper
            self.rep = args[ 0 ]

        self.atoms = {}
        self.decart = kargs.get( 'decart', False )  ## by default assume that all coordinates of atoms in fractional coordinates

    def add( self, name, x ):
        """ Add a group of named points (atoms)
            to unit cell.
            Points mus be in decart (not fractional) coordinate system.
        """
        if name not in self.atoms:
            self.atoms[ name ] = set()

        if type( x ) in ( list, set, tuple ):
            self.atoms[ name ].update( set( x ) )
        elif type( x ) is Vec:
            self.atoms[ name ].add( x )
        else:
            raise Exception, "type of argument must be list,set,tuple, or single Vec"

    def __getitem__( self, n ):
        if n in self.atoms:
            return self.atoms[ n ]
        else:
            res = []
            self.atoms[ n ] = res
            return res

    def __setitem__( self, n, v ):
        self.atoms[ n ] = v

    def __iter__( self ):
        return self.atoms.iteritems()


    def to_fract( self ):
        """ convert all coordinates: decart --> fractional
        """
        if self.decart:
            for n, vs in self:
                self[ n ] = self.rep.dec2frac( vs )
            self.decart = False

    def to_decart( self ):
        """ convert all coordinates: fractional --> decart
        """
        if not self.decart:
            for n, vs in self:
                self[ n ] = self.rep.frac2dec( vs )
            self.decart = True

    def __mul__( self, o ):
        """ Multiply ucell with number and space group
        """
        if type( o ) is int:
            decart = self.decart
            self.to_decart()
            ns = [ (i,j,k) for i in xrange( -o, o+1 )\
                           for j in xrange( -o, o+1 )\
                           for k in xrange( -o, o+1 ) ]
            uc = UCell( self.rep, decart = True )

            for k,vs in self.atoms.iteritems():
                toadd = set()
                for t in ns:
                    vt = self.rep * t
                    for v in vs:              ## for each vector with name "k"
                        toadd.add( v + vt )   ## translate v by reper in each directions
                uc.add( k, toadd )            ## add extended points with name "k"

            if not decart:
                uc.to_fract()
            return uc

        elif type( o ) == SpGrp:
            uc = UCell( self.rep )
            for n, ats in self:
                tmp = set()
                for a in ats:
                    for v in o * a:        ## multiply each atom position with space group
                        tmp.add( v )       ## ... and then add it
                uc[ n ] = list( tmp )      ## transform to list and save
            return uc


    def __add__( self, obj ):
        """ Translate ucell by obj
        """
        if type( obj ) is Vec:
            nc = UCell( self.rep )
            for k,vs in self.atoms.iteritems():
                vs = map( lambda v: v + obj, vs )  ## translate vectors
                nc.add( k, vs )
            return nc
        elif type( obj ) is UCell:
            nc = UCell( self.rep )
            nc.atoms = dict( self.atoms ) ## make copy of self atoms

            for k,v in obj.atoms.iteritems():
                nc.atoms[ k ] = nc.atoms.get( k, [] ) + v ## add extended set of atoms

            return nc


    def __repr__( self ):
        rep = self.rep
        a,b,c = rep[0].vlen(), rep[1].vlen(), rep[2].vlen()
        gam = math.acos( rep[0].norm() * rep[1].norm() ) * 180 / math.pi
        bet = math.acos( rep[0].norm() * rep[2].norm() ) * 180 / math.pi
        alf = math.acos( rep[1].norm() * rep[2].norm() ) * 180 / math.pi

        return "UCell( a,b,c = (%s, %s, %s)  angles = (%s, %s, %s)  atoms = '%s' )" % ( a,b,c, alf, bet, gam, map( lambda t: "%s(%s)" % (t[0], len( t[1] )), self ) )