def extended_copy(self,n): """ Get copies of atoms for all listed symmetry operations n. @param: n i) list of 3-tuples for transformations explicitly e.g. [(0,0,0),(1,0,0),(0,1,0)] ii) 3-tuple for the number of transformations (for infinite extensions -> start from zero; for finite extensions -> symmetry ops around zero) e.g. (10,10,1) iii) 3-tuple of 2-tuples that give the ranges for symmetry ops e.g. ((-3,3),(-3,3),1) Return normal ase.Atoms -instance. """ r = self.container.get_symmetry_operation_ranges() if isinstance(n,list): n_list = copy(n) elif isinstance(n,tuple): ops = [] for i in range(3): if isinstance(n[i],tuple): ops.append( np.arange(n[i][0],n[i][1]+1) ) elif isinstance(n[i],int): assert n[i]>0 if r[i,0]==-np.Inf: # this symmetry operation has the full range rng = np.arange(0,n[i]) else: # take copies around the 0-operation start = max(r[i,0],-n[i]//2) rng = np.arange(start,start+n[i]) ops.append( rng ) n_list=[] for n1 in ops[0]: for n2 in ops[1]: for n3 in ops[2]: n_list.append( (n1,n2,n3) ) atoms2=None for n in n_list: self._check_symmetry_operation(n) atomsn = ase_Atoms() atomsn += self atomsn.set_positions( np.array([self.transform(r,n) for r in self.get_positions()]) ) try: atoms2 += atomsn except: atoms2 = atomsn atoms2.set_pbc(False) atoms2.set_cell((1,1,1)) return atoms2
def extended_copy(self,n): """ Get copies of atoms for all listed symmetry operations n. @param: n i) list of 3-tuples for transformations explicitly e.g. [(0,0,0),(1,0,0),(0,1,0)] ii) 3-tuple for the number of transformations (for infinite extensions -> start from zero; for finite extensions -> symmetry ops around zero) e.g. (10,10,1) iii) 3-tuple of 2-tuples that give the ranges for symmetry ops e.g. ((-3,3),(-3,3),1) Return normal ase.Atoms -instance. """ r = self.container.get_symmetry_operation_ranges() if isinstance(n,list): n_list = copy(n) elif isinstance(n,tuple): ops = [] for i in range(3): if isinstance(n[i],tuple): ops.append( np.arange(n[i][0],n[i][1]+1) ) elif isinstance(n[i],int): assert n[i]>0 if r[i,0]==-np.Inf: # this symmetry operation has the full range rng = np.arange(0,n[i]) else: # take copies around the 0-operation start = max(r[i,0],-n[i]/2) rng = np.arange(start,start+n[i]) ops.append( rng ) n_list=[] for n1 in ops[0]: for n2 in ops[1]: for n3 in ops[2]: n_list.append( (n1,n2,n3) ) atoms2=None for n in n_list: self._check_symmetry_operation(n) atomsn = ase_Atoms() atomsn += self atomsn.set_positions( np.array([self.transform(r,n) for r in self.get_positions()]) ) try: atoms2 += atomsn except: atoms2 = atomsn atoms2.set_pbc(False) atoms2.set_cell((1,1,1)) return atoms2
def armchair_ribbon(n1, n2, R, pbc='z'): """ Make ribbon out of graphene with armchair edges: n1 armchair periods in x-direction and n2 stacked armchairs. parameters: =========== n1: length (units in periodic direction) n2: width R: bond distance pbc: periodic direction ('z' or 'x') """ from hotbit import Atoms a1 = vec([3 * R, 0, 0]) a2 = vec([0, 2 * R * np.cos(pi / 6), 0]) atoms = ase_Atoms() r = [] for i1 in range(n1): for i2 in range(n2): corner = i1 * a1 + i2 * a2 atoms += Atom('C', corner) atoms += Atom('C', corner + vec([R, 0, 0])) atoms += Atom('C', corner + vec([1.5 * R, R * np.cos(pi / 6), 0])) atoms += Atom('C', corner + vec([2.5 * R, R * np.cos(pi / 6), 0])) if pbc == 'x': atoms.set_cell([n1 * 3 * R, n2 * 2 * R * np.cos(pi / 6), 1]) atoms.center(vacuum=5, axis=2) atoms.center(vacuum=5, axis=1) atoms.set_pbc((True, False, False)) return atoms elif pbc == 'z': atoms.translate(-atoms.get_center_of_mass()) atoms.rotate('z', np.pi / 2) atoms.rotate('x', np.pi / 2) atoms.center(vacuum=5, axis=1) atoms.translate(-atoms.get_center_of_mass()) zmin = atoms.get_positions()[:, 2].min() atoms.translate((0, 0, -zmin)) atoms.set_cell([n2 * 2 * R * np.cos(pi / 6), 1, n1 * 3 * R]) atoms.set_pbc((False, False, True)) return atoms else: raise NotImplementedError('pbc only along x or z')
def armchair_ribbon(n1,n2,R,pbc='z'): """ Make ribbon out of graphene with armchair edges: n1 armchair periods in x-direction and n2 stacked armchairs. parameters: =========== n1: length (units in periodic direction) n2: width R: bond distance pbc: periodic direction ('z' or 'x') """ from hotbit import Atoms a1=vec([3*R,0,0]) a2=vec([0,2*R*np.cos(pi/6),0]) atoms=ase_Atoms() r=[] for i1 in range(n1): for i2 in range(n2): corner=i1*a1+i2*a2 atoms += Atom('C',corner) atoms += Atom('C',corner+vec([R,0,0])) atoms += Atom('C',corner+vec([1.5*R,R*np.cos(pi/6),0])) atoms += Atom('C',corner+vec([2.5*R,R*np.cos(pi/6),0])) if pbc=='x': atoms.set_cell( [n1*3*R,n2*2*R*np.cos(pi/6),1] ) atoms.center(vacuum=5,axis=2) atoms.center(vacuum=5,axis=1) atoms.set_pbc((True,False,False)) return atoms elif pbc=='z': atoms.translate( -atoms.get_center_of_mass() ) atoms.rotate('z',np.pi/2) atoms.rotate('x',np.pi/2) atoms.center(vacuum=5,axis=1) atoms.translate( -atoms.get_center_of_mass() ) zmin = atoms.get_positions()[:,2].min() atoms.translate( (0,0,-zmin) ) atoms.set_cell( [n2*2*R*np.cos(pi/6),1,n1*3*R] ) atoms.set_pbc((False,False,True)) return atoms else: raise NotImplementedError('pbc only along x or z')
def ZGNR(n, units=1, pbc='z', R=1.42): """ Make an n-zigzag graphene nanoribbon. parameters: =========== n: ribbon width (atomic rows) length: ribbon length (unit cells) pbc: periodic direction, 'x' or 'z' R: bond length """ from hotbit import Atoms a0 = R * np.sqrt(3) atoms = ase_Atoms() for i in range(n): x = 1 if np.mod(i, 2) == 1: x = -1 atoms += Atom('C', (0, 3 * R * i / 2 + 3 * R / 4 - x * R / 4, 0)) atoms += Atom('C', (a0 / 2, 3 * R * i / 2 + 3 * R / 4 + x * R / 4, 0)) a = atoms.copy() for i in range(units - 1): b = a.copy() b.translate(((i + 1) * a0, 0, 0)) atoms += b if pbc == 'x': atoms.set_pbc((True, False, False)) atoms.set_cell((units * a0, 1, 1)) atoms.center(vacuum=6, axis=1) atoms.center(vacuum=6, axis=2) elif pbc == 'z': atoms.set_pbc((False, False, True)) atoms.rotate('z', np.pi / 2) atoms.rotate('x', np.pi / 2) atoms.set_cell((n * 3 * R / 2 * 1.2 / 2, 1, units * a0)) atoms.translate(-atoms.get_center_of_mass()) atoms.center(axis=2) return atoms
def ZGNR(n,units=1,pbc='z',R=1.42): """ Make an n-zigzag graphene nanoribbon. parameters: =========== n: ribbon width (atomic rows) length: ribbon length (unit cells) pbc: periodic direction, 'x' or 'z' R: bond length """ from hotbit import Atoms a0 = R*np.sqrt(3) atoms = ase_Atoms() for i in range(n): x = 1 if np.mod(i,2)==1: x=-1 atoms += Atom('C',(0,3*R*i/2+3*R/4-x*R/4,0)) atoms += Atom('C',(a0/2,3*R*i/2+3*R/4+x*R/4,0)) a = atoms.copy() for i in range(units-1): b = a.copy() b.translate(((i+1)*a0,0,0)) atoms += b if pbc=='x': atoms.set_pbc((True,False,False)) atoms.set_cell((units*a0,1,1)) atoms.center(vacuum=6,axis=1) atoms.center(vacuum=6,axis=2) elif pbc=='z': atoms.set_pbc((False,False,True)) atoms.rotate('z',np.pi/2) atoms.rotate('x',np.pi/2) atoms.set_cell((n*3*R/2*1.2/2,1,units*a0)) atoms.translate( -atoms.get_center_of_mass() ) atoms.center(axis=2) return atoms
def AGNR(n, units=1, pbc='z', R=1.42): """ Make an n-armchair graphene nanoribbon. parameters: =========== n: ribbon width (atomic rows) length: ribbon length (unit cells) pbc: periodic direction, 'x' or 'z' R: bond length """ from hotbit import Atoms a = R * np.sqrt(3) atoms = ase_Atoms() for i in range(n): x0 = 0.0 if np.mod(i, 2) == 1: x0 = 1.5 * R atoms += Atom('C', (x0 + 0, i * a / 2, 0)) atoms += Atom('C', (x0 + R, i * a / 2, 0)) a = atoms.copy() for i in range(units - 1): b = a.copy() b.translate(((i + 1) * 3 * R, 0, 0)) atoms += b if pbc == 'x': atoms.set_pbc((True, False, False)) atoms.set_cell((units * 3 * R, 1, 1)) atoms.center(vacuum=6, axis=1) atoms.center(vacuum=6, axis=2) elif pbc == 'z': atoms.set_pbc((False, False, True)) atoms.rotate('z', np.pi / 2) atoms.rotate('x', np.pi / 2) atoms.set_cell((1, 1, units * 3 * R)) atoms.translate(-atoms.get_center_of_mass()) return atoms
def AGNR(n,units=1,pbc='z',R=1.42): """ Make an n-armchair graphene nanoribbon. parameters: =========== n: ribbon width (atomic rows) length: ribbon length (unit cells) pbc: periodic direction, 'x' or 'z' R: bond length """ from hotbit import Atoms a = R*np.sqrt(3) atoms = ase_Atoms() for i in range(n): x0 = 0.0 if np.mod(i,2)==1: x0 = 1.5*R atoms += Atom('C',(x0+0,i*a/2,0)) atoms += Atom('C',(x0+R,i*a/2,0)) a = atoms.copy() for i in range(units-1): b = a.copy() b.translate(((i+1)*3*R,0,0)) atoms += b if pbc=='x': atoms.set_pbc((True,False,False)) atoms.set_cell((units*3*R,1,1)) atoms.center(vacuum=6,axis=1) atoms.center(vacuum=6,axis=2) elif pbc=='z': atoms.set_pbc((False,False,True)) atoms.rotate('z',np.pi/2) atoms.rotate('x',np.pi/2) atoms.set_cell((1,1,units*3*R)) atoms.translate( -atoms.get_center_of_mass() ) return atoms
def zigzag_ribbon(n1, n2, R, pbc='z'): """ Make ribbon out of graphene with zigzag edges. """ from hotbit import Atoms a1 = vec([2 * R * np.cos(pi / 6), 0, 0]) a2 = vec([0, 3 * R, 0]) r = [] for i1 in range(n1): for i2 in range(n2): corner = i1 * a1 + i2 * a2 r.append(corner + vec([R * np.cos(pi / 6), R / 2, 0])) r.append(corner + vec([0, R, 0])) r.append(corner + vec([0, 2 * R, 0])) r.append(corner + vec([R * np.cos(pi / 6), 2.5 * R, 0])) cell = [n1 * 2 * R * np.cos(pi / 6), n2 * 3 * R, 1] elements = ['C'] * len(r) atoms = ase_Atoms(elements, r, cell=cell) if pbc == 'x': atoms.set_cell([2 * R * np.cos(pi / 6), n1 * 3 * R, 1]) atoms.center(vacuum=5, axis=2) atoms.center(vacuum=5, axis=1) atoms.set_pbc((True, False, False)) return atoms elif pbc == 'z': atoms.translate(-atoms.get_center_of_mass()) atoms.rotate('z', np.pi / 2) atoms.rotate('x', np.pi / 2) atoms.center(vacuum=5, axis=1) atoms.translate(-atoms.get_center_of_mass()) zmin = atoms.get_positions()[:, 2].min() atoms.translate((0, 0, -zmin)) atoms.set_cell([n2 * 2 * R * np.cos(pi / 6), 1, n1 * 3 * R]) atoms.set_pbc((False, False, True)) return atoms else: raise NotImplementedError('pbc only along x or z')
def zigzag_ribbon(n1,n2,R,pbc='z'): """ Make ribbon out of graphene with zigzag edges. """ from hotbit import Atoms a1=vec([2*R*np.cos(pi/6),0,0]) a2=vec([0,3*R,0]) r=[] for i1 in range(n1): for i2 in range(n2): corner=i1*a1+i2*a2 r.append(corner+vec([R*np.cos(pi/6),R/2,0])) r.append(corner+vec([0,R,0])) r.append(corner+vec([0,2*R,0])) r.append(corner+vec([R*np.cos(pi/6),2.5*R,0])) cell=[n1*2*R*np.cos(pi/6),n2*3*R,1] elements=['C']*len(r) atoms = ase_Atoms(elements,r,cell=cell) if pbc=='x': atoms.set_cell( [2*R*np.cos(pi/6),n1*3*R,1] ) atoms.center(vacuum=5,axis=2) atoms.center(vacuum=5,axis=1) atoms.set_pbc((True,False,False)) return atoms elif pbc=='z': atoms.translate( -atoms.get_center_of_mass() ) atoms.rotate('z',np.pi/2) atoms.rotate('x',np.pi/2) atoms.center(vacuum=5,axis=1) atoms.translate( -atoms.get_center_of_mass() ) zmin = atoms.get_positions()[:,2].min() atoms.translate( (0,0,-zmin) ) atoms.set_cell( [n2*2*R*np.cos(pi/6),1,n1*3*R] ) atoms.set_pbc((False,False,True)) return atoms else: raise NotImplementedError('pbc only along x or z')
from hotbit.atoms import Atoms from box.md import check_energy_conservation from hotbit.test.misc import default_param # check that C1H1-presentation of C6H6 goes right SCC=True cut=3.0 atoms = Atoms('CH',[(1.42,0,0),(2.0,1.0,0.2)],container='Wedge') atoms.set_container(M=6,height=10) calc = Hotbit(SCC=SCC,txt='tmp.cal',kpts=(6,1,1),gamma_cut=cut,**default_param) atoms.set_calculator(calc) e1 = atoms.get_potential_energy() atoms6 = ase_Atoms(pbc=False) atoms6 += atoms.extended_copy([(i-2,0,0) for i in range(6)]) #view(atoms) calc = Hotbit(SCC=SCC,txt='tmp.cal',gamma_cut=cut,**default_param) atoms6.set_calculator(calc) e6 = atoms6.get_potential_energy() assert abs(6*e1-e6)<1E-5 # # energy conservation # atoms = Atoms('CH',[(1.42,0,0),(2.0,0.5,0.3)],container='Wedge') atoms.set_container(M=6,height=10) calc = Hotbit(SCC=SCC,txt='tmp.cal',kpts=(6,1,1),gamma_cut=cut,**default_param)
# check that C1H1-presentation of C6H6 goes right SCC = True cut = 3.0 atoms = Atoms('CH', [(1.42, 0, 0), (2.0, 1.0, 0.2)], container='Wedge') atoms.set_container(M=6, height=10) calc = Hotbit(SCC=SCC, txt='tmp.cal', kpts=(6, 1, 1), gamma_cut=cut, **default_param) atoms.set_calculator(calc) e1 = atoms.get_potential_energy() atoms6 = ase_Atoms(pbc=False) atoms6 += atoms.extended_copy([(i - 2, 0, 0) for i in range(6)]) #view(atoms) calc = Hotbit(SCC=SCC, txt='tmp.cal', gamma_cut=cut, **default_param) atoms6.set_calculator(calc) e6 = atoms6.get_potential_energy() assert abs(6 * e1 - e6) < 1E-5 # # energy conservation # atoms = Atoms('CH', [(1.42, 0, 0), (2.0, 0.5, 0.3)], container='Wedge') atoms.set_container(M=6, height=10) calc = Hotbit(SCC=SCC, txt='tmp.cal',