Exemplo n.º 1
0
def graphene(n1,n2,R,height=5.0):
    """
    Construct graphene lattice, multiply the primitive cell
    n1 x n2 times in corresponding directions.
        
         .-----.
        /     /
       /   X / a2  
      /     /
     X----->        
      a1            
    """
    from hotbit import Atoms
    
    if not isinstance(R,float): R=R[0]
    a1=vec([R*np.cos(pi/6)*2,0.,0.])
    a2=0.5*a1 + vec([0.,1.5*R,0.])
    #assert n2%2==0
        
    r=[]
    for i1 in range(n1):
        for i2 in range(n2):
            corner = i1*a1+i2*a2
            r.append(corner)
            r.append(corner+a1+vec([0.0,R,0.0]))
                
    cell=[[n1*a1[0], 0, 0],[n2*a2[0],n2*a2[1],0],[0,0,10]]                
    atoms=Atoms('C'*len(r),positions=r,cell=cell)
    atoms.center(vacuum=height/2,axis=2)
    atoms.set_pbc((True,True,False))
    return atoms
Exemplo n.º 2
0
 def compare_trajectory(self, i_traj, calc, tables, i_par):
     """
     Calculate the energies for the frames in the trajectory
     and plot them.
     """
     frames = []
     energies = []
     trajectory = PickleTrajectory(self.trajectories[i_traj])
     for i, image in enumerate(trajectory):
         e_tb = None
         try:
             atoms = Atoms(image)
             c = copy(calc)
             c.tables = tables
             atoms.set_calculator(c)
             e_tb = atoms.get_potential_energy()
         except Exception as ex:
             print(ex, file=self.txt)
         if e_tb != None:
             energies.append(e_tb)
             frames.append(i)
     delta_E = self.norm_to_isolated_atoms(trajectory[0])
     for i in range(len(energies)):
         energies[i] += delta_E
     self.plot(frames, energies, i_traj, tables, i_par)
Exemplo n.º 3
0
    def append_dimer(self,
                     weight,
                     calc,
                     R,
                     comment=None,
                     label='dimer',
                     color=None):
        """
        Use dimer bond length in fitting.

        parameters:
        ===========
        weight:    fitting weight
        calc:      Hotbit calculator used in calculation
                   (remember Gamma-point and charge)
        R:         dimer bond length (Angstroms)
        comment:   fitting comment for par-file (replaced by label if None)
        label:     plotting label (replaced by comment if None)
        color:     plotting color
        """
        if comment == None: comment = label
        self.r_dimer = R
        atoms = Atoms([self.sym1, self.sym2], [(0, 0, 0), (R, 0, 0)],
                      pbc=False)
        atoms.center(vacuum=5)
        color = self._get_color(color)
        self.append_scalable_system(weight,
                                    calc,
                                    atoms,
                                    comment=comment,
                                    label=label,
                                    color=color)
Exemplo n.º 4
0
def chiral_nanotube(n, m, R=1.42, element='C'):
    """
    Construct a nanotube with a chiral container.
    
    parameters:
    ===========
    n,m:     chiral indices
    R:       bond length
    element: element type 
    """
    from hotbit import Atoms
    a = np.sqrt(3) * R
    a1 = np.array([a, 0, 0])
    a2 = np.array([0.5 * a, -1.5 * R, 0])

    rl = []
    shift = (a / 2, -0.5 * R, 0)
    for i in range(n):
        origin = i * a1
        rl.append(origin)
        rl.append(origin + shift)

    for j in range(m):
        origin = (n - 1) * a1 + (j + 1) * a1
        rl.append(origin)
        rl.append(origin + shift)

    atoms = Atoms()
    C = n * a1 + m * a2
    Cn = np.linalg.norm(C)
    T = np.array([C[1], -C[0], 0])
    t = T / np.linalg.norm(T)
    radius = Cn / (2 * pi)

    atoms = Atoms()
    for r in rl:
        phi = np.dot(r, C) / Cn**2 * 2 * pi
        atoms += Atom(
            element,
            (radius * np.cos(phi), radius * np.sin(phi), np.dot(r, t)))

    atoms = Atoms(atoms, container='Chiral')
    height = np.abs(np.dot(a1 - a2, t))
    angle = -np.dot(a1 - a2, C) / Cn**2 * 2 * pi
    atoms.set_container(angle=angle, height=height)

    data = nanotube_data(n, m, R)
    T, Ntot = data['T'], 2 * data['hexagons_per_cell']
    data['height'] = height
    data['twist'] = angle
    atoms.data = data
    return atoms
Exemplo n.º 5
0
def setup_bending(atoms, angle, radius, rotation=0.0, physical=True):
    """
    Prepare a bending setup for a tube or slab.
    
    Tube should be originally periodic in z-direction with
    the correct cell, and optionally periodic in y-direction.
    
    Then atoms are set up for bending with hotbit.Wedge class
    with bending wrt. z-axis, and optionally periodic along
    z-axis.
    
    Atoms are first rotated pi/2 around -x-axis, then
    rotated an angle 'rotation' around y-axis, then
    transformed the distance 'radius' towards x-axis.
    The atoms are further adjusted for the wedge angle 'angle'.
    'physical' tells if the angle should be 2*pi/integer.
    """
    a = atoms.copy()
    a.rotate('-x', np.pi / 2)
    L = a.get_cell().diagonal()
    if abs(L.prod() - a.get_volume()) > 1E-10:
        raise AssertionError('Cell should be orthorhombic.')
    pbc = a.get_pbc()
    if not pbc[2] or pbc[0]:
        raise AssertionError(
            'Should be periodic in z-direction and not periodic in x-direction'
        )
    r = a.get_positions()
    if np.any(r[:, 1] < 0):  # index 1 is correct here
        raise AssertionError('For bending, all atoms should be above xy-plane')

    # move and adjust
    a.rotate('y', rotation)
    for i in range(len(a)):
        x, y = r[i, 0:2]
        R = x + radius
        phi = y * angle / L[2]
        r[i, 0] = R * np.cos(phi)
        r[i, 1] = R * np.sin(phi)
    a.set_positions(r)
    a = Atoms(a, container='Wedge')
    a.set_container(angle=angle, height=L[1], pbcz=pbc[1], physical=physical)
    return a
Exemplo n.º 6
0
    def append_dimer(self,weight,calc,R,comment=None,label='dimer',color=None):
        """
        Use dimer bond length in fitting.

        parameters:
        ===========
        weight:    fitting weight
        calc:      Hotbit calculator used in calculation
                   (remember Gamma-point and charge)
        R:         dimer bond length (Angstroms)
        comment:   fitting comment for par-file (replaced by label if None)
        label:     plotting label (replaced by comment if None)
        color:     plotting color
        """
        if comment==None: comment=label
        self.r_dimer = R
        atoms = Atoms([self.sym1,self.sym2],[(0,0,0),(R,0,0)],pbc=False)
        atoms.center(vacuum=5)
        color = self._get_color(color)
        self.append_scalable_system(weight,calc,atoms,comment=comment,label=label,color=color)
Exemplo n.º 7
0
def setup_bending(atoms,angle,radius,rotation=0.0,physical=True):
    """
    Prepare a bending setup for a tube or slab.
    
    Tube should be originally periodic in z-direction with
    the correct cell, and optionally periodic in y-direction.
    
    Then atoms are set up for bending with hotbit.Wedge class
    with bending wrt. z-axis, and optionally periodic along
    z-axis.
    
    Atoms are first rotated pi/2 around -x-axis, then
    rotated an angle 'rotation' around y-axis, then
    transformed the distance 'radius' towards x-axis.
    The atoms are further adjusted for the wedge angle 'angle'.
    'physical' tells if the angle should be 2*pi/integer.
    """
    a = atoms.copy()
    a.rotate('-x',np.pi/2)
    L = a.get_cell().diagonal()
    if abs(L.prod()-a.get_volume())>1E-10:
        raise AssertionError('Cell should be orthorhombic.')
    pbc = a.get_pbc()
    if not pbc[2] or pbc[0]:
        raise AssertionError('Should be periodic in z-direction and not periodic in x-direction')
    r = a.get_positions()    
    if np.any( r[:,1]<0 ): # index 1 is correct here 
        raise AssertionError('For bending, all atoms should be above xy-plane')
    
    # move and adjust
    a.rotate('y',rotation)
    for i in range(len(a)):
        x,y = r[i,0:2]
        R = x + radius
        phi = y*angle/L[2]
        r[i,0] = R*np.cos(phi)
        r[i,1] = R*np.sin(phi)
    a.set_positions(r)
    a = Atoms(a,container='Wedge')
    a.set_container(angle=angle,height=L[1],pbcz=pbc[1],physical=physical)
    return a
Exemplo n.º 8
0
 def compare_trajectory(self, i_traj, calc, tables, i_par):
     """
     Calculate the energies for the frames in the trajectory
     and plot them.
     """
     frames = []
     energies = []
     trajectory = PickleTrajectory(self.trajectories[i_traj])
     for i, image in enumerate(trajectory):
         e_tb = None
         try:
             atoms = Atoms(image)
             c = copy(calc)
             c.tables = tables
             atoms.set_calculator(c)
             e_tb = atoms.get_potential_energy()
         except Exception, ex:
             print>>self.txt, ex
         if e_tb != None:
             energies.append(e_tb)
             frames.append(i)
Exemplo n.º 9
0
 def compare_trajectory(self, i_traj, calc, tables, i_par):
     """
     Calculate the energies for the frames in the trajectory
     and plot them.
     """
     frames = []
     energies = []
     trajectory = PickleTrajectory(self.trajectories[i_traj])
     for i, image in enumerate(trajectory):
         e_tb = None
         try:
             atoms = Atoms(image)
             c = copy(calc)
             c.tables = tables
             atoms.set_calculator(c)
             e_tb = atoms.get_potential_energy()
         except Exception, ex:
             print >> self.txt, ex
         if e_tb != None:
             energies.append(e_tb)
             frames.append(i)
Exemplo n.º 10
0
def graphene(n1, n2, R, height=5.0):
    """
    Construct graphene lattice, multiply the primitive cell
    n1 x n2 times in corresponding directions.
        
         .-----.
        /     /
       /   X / a2  
      /     /
     X----->        
      a1            
    """
    from hotbit import Atoms

    if not isinstance(R, float): R = R[0]
    a1 = vec([R * np.cos(pi / 6) * 2, 0., 0.])
    a2 = 0.5 * a1 + vec([0., 1.5 * R, 0.])
    #assert n2%2==0

    r = []
    for i1 in range(n1):
        for i2 in range(n2):
            corner = i1 * a1 + i2 * a2
            r.append(corner)
            r.append(corner + a1 + vec([0.0, R, 0.0]))

    cell = [[n1 * a1[0], 0, 0], [n2 * a2[0], n2 * a2[1], 0], [0, 0, 10]]
    atoms = Atoms('C' * len(r), positions=r, cell=cell)
    atoms.center(vacuum=height / 2, axis=2)
    atoms.set_pbc((True, True, False))
    return atoms
Exemplo n.º 11
0
def chiral_nanotube(n,m,R=1.42,element='C'):
    """
    Construct a nanotube with a chiral container.
    
    parameters:
    ===========
    n,m:     chiral indices
    R:       bond length
    element: element type 
    """
    from hotbit import Atoms
    a = np.sqrt(3)*R
    a1 = np.array([a,0,0])
    a2 = np.array([0.5*a,-1.5*R,0])
    
    rl = []
    shift = (a/2,-0.5*R,0)
    for i in range(n):
        origin = i*a1
        rl.append( origin )
        rl.append( origin+shift )
          
    for j in range(m):
        origin = (n-1)*a1 + (j+1)*a1
        rl.append( origin )
        rl.append( origin + shift )
        
    atoms = Atoms()
    C = n*a1 + m*a2
    Cn = np.linalg.norm(C)
    T = np.array([C[1],-C[0],0])
    t = T/np.linalg.norm(T)
    radius = Cn/(2*pi)
    
    atoms = Atoms()
    for r in rl:
        phi = np.dot(r,C)/Cn**2 * 2*pi
        atoms += Atom( element,(radius*np.cos(phi),radius*np.sin(phi),np.dot(r,t)) )
    
    atoms = Atoms(atoms,container='Chiral')
    height = np.abs( np.dot(a1-a2,t) )
    angle = -np.dot(a1-a2,C)/Cn**2 * 2*pi
    atoms.set_container(angle=angle,height=height) 
    
    data = nanotube_data(n,m,R)
    T, Ntot = data['T'],2*data['hexagons_per_cell']
    data['height']=height
    data['twist']=angle
    atoms.data = data
    return atoms
Exemplo n.º 12
0
 def get_isolated_energies(self, trajs, par):
     """
     Return the energies of an isolated atoms.
     """
     elements = []
     energies = {}
     for t in trajs:
         traj = PickleTrajectory(t)
         for atom in traj[0]:
             if not atom.symbol in elements:
                 elements.append(atom.symbol)
     el1, el2 = par.split("_")[0:2]
     for el in elements:
         ss = "%s%s" % (el, el)
         if el1 == el2 and el1 == el:
             tables = {ss:par, 'rest':'default'}
             calc = Hotbit(SCC=True, tables=tables)
         else:
             calc = Hotbit(SCC=True)
         atoms = Atoms(ss, ((0,0,0),(200,0,0)))
         atoms.center(vacuum=100)
         atoms.set_calculator(calc)
         energies[el] = atoms.get_potential_energy() / 2
     return energies
Exemplo n.º 13
0
 def get_isolated_energies(self, trajs, par):
     """
     Return the energies of an isolated atoms.
     """
     elements = []
     energies = {}
     for t in trajs:
         traj = PickleTrajectory(t)
         for atom in traj[0]:
             if not atom.symbol in elements:
                 elements.append(atom.symbol)
     el1, el2 = par.split("_")[0:2]
     for el in elements:
         ss = "%s%s" % (el, el)
         if el1 == el2 and el1 == el:
             tables = {ss:par, 'rest':'default'}
             calc = Hotbit(SCC=True, tables=tables)
         else:
             calc = Hotbit(SCC=True)
         atoms = Atoms(ss, ((0,0,0),(200,0,0)))
         atoms.center(vacuum=100)
         atoms.set_calculator(calc)
         energies[el] = atoms.get_potential_energy() / 2
     return energies
Exemplo n.º 14
0
def nanotube(n, m, R=1.42, length=1, element='C'):
    '''
    Create a nanotube around z-axis.
    
    parameters:
    -----------
    n,m:    chiral indices
    R:      nearest neighbor distance
    length: number of unit cells
    element: element symbol
    '''
    from hotbit import Atoms
    at = Atoms(pbc=(False, False, True))

    sq3 = sqrt(3.0)
    a0 = R
    gcn = gcd(n, m)

    a1 = np.array([sq3 / 2, 0.5]) * a0 * sq3
    a2 = np.array([sq3 / 2, -0.5]) * a0 * sq3

    h = float(float(n) - float(m)) / float(3 * gcn)

    if h - int(h) == 0.0:
        RR = 3
    else:
        RR = 1

    c = n * a1 + m * a2
    abs_c = sqrt(dot(c, c))

    a = (-(2 * m + n) * a1 + (2 * n + m) * a2) / (gcn * RR)
    abs_a = sqrt(dot(a, a))

    eps = 0.01
    b = [[1. / 3 - eps, 1. / 3 - eps], [2. / 3 - eps, 2. / 3 - eps]]

    nxy = max(n, m) + 100
    eps = 0.00001

    for x in xrange(-nxy, nxy):
        for y in xrange(-nxy, nxy):
            for b1, b2 in b:
                p = (x + b1) * a1 + (y + b2) * a2
                abs_p = sqrt(dot(p, p))

                sa = dot(p, a) / (abs_a**2)
                sc = dot(p, c) / (abs_c**2)

                if sa >= 0 and sa < 1 - eps and sc >= 0 and sc < 1 - eps:
                    r = (cos(2 * pi * sc) * abs_c / (2 * pi),
                         sin(2 * pi * sc) * abs_c / (2 * pi), sa * abs_a)
                    at += Atom(element, r)
    at.set_cell((2 * abs_c / (2 * pi), 2 * abs_c / (2 * pi), length * abs_a))
    b = at.copy()

    for i in range(length - 1):
        b.translate((0.0, 0.0, abs_a))
        for j in b:
            at += j
    at.center(axis=2)
    rcm = at.get_center_of_mass()
    at.translate((-rcm[0], -rcm[1], 0))
    at.set_pbc((False, False, True))
    at.data = nanotube_data(n, m)
    return at
Exemplo n.º 15
0
def nanotube(n,m,R=1.42,length=1,element='C'):
    '''
    Create a nanotube around z-axis.
    
    parameters:
    -----------
    n,m:    chiral indices
    R:      nearest neighbor distance
    length: number of unit cells
    element: element symbol
    '''
    from hotbit import Atoms
    at = Atoms( pbc = ( False, False, True ) )

    sq3 = sqrt(3.0)
    a0 = R
    gcn = gcd(n, m)
    
    a1 = np.array( [ sq3/2,  0.5 ] ) * a0 * sq3
    a2 = np.array( [ sq3/2, -0.5 ] ) * a0 * sq3

    h = float(float(n)-float(m))/float(3*gcn)

    if h-int(h) == 0.0:
        RR = 3
    else:
        RR = 1

    c = n*a1 + m*a2
    abs_c = sqrt(dot(c, c))

    a = ( -(2*m+n)*a1 + (2*n+m)*a2 )/(gcn*RR)
    abs_a = sqrt(dot(a, a))

    eps = 0.01
    b = [ [ 1./3-eps, 1./3-eps ], [ 2./3-eps, 2./3-eps ] ]

    nxy = max(n, m)+100
    eps = 0.00001
    
    for x in xrange(-nxy, nxy):
        for y in xrange(-nxy, nxy):
            for b1, b2 in b:
                p = (x+b1)*a1 + (y+b2)*a2
                abs_p = sqrt(dot(p, p))

                sa = dot(p, a)/(abs_a**2)
                sc = dot(p, c)/(abs_c**2)

                if sa >= 0 and sa < 1-eps and sc >= 0 and sc < 1-eps:
                    r = ( cos(2*pi*sc)*abs_c/(2*pi), sin(2*pi*sc)*abs_c/(2*pi), sa*abs_a )
                    at += Atom( element, r ) 
    at.set_cell( ( 2*abs_c/(2*pi), 2*abs_c/(2*pi), length*abs_a ) )
    b = at.copy()

    for i in range(length-1):
        b.translate( ( 0.0, 0.0, abs_a ) )
        for j in b:
            at += j
    at.center(axis=2)
    rcm = at.get_center_of_mass()
    at.translate( (-rcm[0],-rcm[1],0) )
    at.set_pbc((False,False,True))
    at.data = nanotube_data(n,m)
    return at