Statistiques
| Révision :

root / ase / utils / adsorb.py @ 19

Historique | Voir | Annoter | Télécharger (4,51 ko)

1 1 tkerber
#!/usr/bin/env python
2 1 tkerber
3 1 tkerber
# Copyright 2010 CAMd
4 1 tkerber
# (see accompanying license files for details).
5 1 tkerber
6 1 tkerber
from optparse import OptionParser
7 1 tkerber
8 1 tkerber
import numpy as np
9 1 tkerber
10 1 tkerber
from ase.lattice.surface import fcc111, hcp0001, bcc110, add_adsorbate
11 1 tkerber
from ase.structure import estimate_lattice_constant
12 1 tkerber
from ase.data import reference_states, atomic_numbers, covalent_radii
13 1 tkerber
from ase.io import write
14 1 tkerber
from ase.visualize import view
15 1 tkerber
from ase.atoms import Atoms, string2symbols
16 1 tkerber
from ase.data.molecules import molecule
17 1 tkerber
18 1 tkerber
def build():
19 1 tkerber
    p = OptionParser(usage='%prog  [options] [ads@]surf [output file]',
20 1 tkerber
                     version='%prog 0.1',
21 1 tkerber
                     description='Example ads/surf: CO@2x2Ru0001')
22 1 tkerber
    p.add_option('-l', '--layers', type='int',
23 1 tkerber
                 default=4,
24 1 tkerber
                 help='Number of layers.')
25 1 tkerber
    p.add_option('-v', '--vacuum', type='float',
26 1 tkerber
                 default=5.0,
27 1 tkerber
                 help='Vacuum.')
28 1 tkerber
    p.add_option('-x', '--crystal-structure',
29 1 tkerber
                 help='Crystal structure.',
30 1 tkerber
                 choices=['sc', 'fcc', 'bcc', 'hcp'])
31 1 tkerber
    p.add_option('-a', '--lattice-constant', type='float',
32 1 tkerber
                 help='Lattice constant in Angstrom.')
33 1 tkerber
    p.add_option('--c-over-a', type='float',
34 1 tkerber
                 help='c/a ratio.')
35 1 tkerber
    p.add_option('--height', type='float',
36 1 tkerber
                 help='Height of adsorbate over surface.')
37 1 tkerber
    p.add_option('--distance', type='float',
38 1 tkerber
                 help='Distance between adsorbate and nearest surface atoms.')
39 1 tkerber
    p.add_option('--site',
40 1 tkerber
                 help='Adsorption site.',
41 1 tkerber
                 choices=['fcc', 'hcc', 'hollow', 'bridge'])
42 1 tkerber
    p.add_option('-M', '--magnetic-moment', type='float', default=0.0,
43 1 tkerber
                 help='Magnetic moment.')
44 1 tkerber
    p.add_option('-G', '--gui', action='store_true',
45 1 tkerber
                 help="Pop up ASE's GUI.")
46 1 tkerber
47 1 tkerber
    opt, args = p.parse_args()
48 1 tkerber
49 1 tkerber
    if not 1 <= len(args) <= 2:
50 1 tkerber
        p.error("incorrect number of arguments")
51 1 tkerber
52 1 tkerber
    if '@' in args[0]:
53 1 tkerber
        ads, surf = args[0].split('@')
54 1 tkerber
    else:
55 1 tkerber
        ads = None
56 1 tkerber
        surf = args[0]
57 1 tkerber
58 1 tkerber
    if surf[0].isdigit():
59 1 tkerber
        i1 = surf.index('x')
60 1 tkerber
        n = int(surf[:i1])
61 1 tkerber
        i2 = i1 + 1
62 1 tkerber
        while surf[i2].isdigit():
63 1 tkerber
            i2 += 1
64 1 tkerber
        m = int(surf[i1 + 1:i2])
65 1 tkerber
        surf = surf[i2:]
66 1 tkerber
    else:
67 1 tkerber
        n = 1
68 1 tkerber
        m = 1
69 1 tkerber
70 1 tkerber
    if surf[-1].isdigit():
71 1 tkerber
        if surf[1].isdigit():
72 1 tkerber
            face = surf[1:]
73 1 tkerber
            surf = surf[0]
74 1 tkerber
        else:
75 1 tkerber
            face = surf[2:]
76 1 tkerber
            surf = surf[:2]
77 1 tkerber
    else:
78 1 tkerber
        face = None
79 1 tkerber
80 1 tkerber
    Z = atomic_numbers[surf]
81 1 tkerber
    state = reference_states[Z]
82 1 tkerber
83 1 tkerber
    if opt.crystal_structure:
84 1 tkerber
        x = opt.crystal_structure
85 1 tkerber
    else:
86 1 tkerber
        x = state['symmetry'].lower()
87 1 tkerber
88 1 tkerber
    if opt.lattice_constant:
89 1 tkerber
        a = opt.lattice_constant
90 1 tkerber
    else:
91 1 tkerber
        a = estimate_lattice_constant(surf, x, opt.c_over_a)
92 1 tkerber
93 1 tkerber
    if x == 'fcc':
94 1 tkerber
        if face is None:
95 1 tkerber
            face = '111'
96 1 tkerber
        slab = fcc111(surf, (n, m, opt.layers), a, opt.vacuum)
97 1 tkerber
        r = a / np.sqrt(2) / 2
98 1 tkerber
    elif x == 'bcc':
99 1 tkerber
        if face is None:
100 1 tkerber
            face = '110'
101 1 tkerber
        slab = bcc110(surf, (n, m, opt.layers), a, opt.vacuum)
102 1 tkerber
        r = a * np.sqrt(3) / 4
103 1 tkerber
    elif x == 'hcp':
104 1 tkerber
        if face is None:
105 1 tkerber
            face = '0001'
106 1 tkerber
        slab = hcp0001(surf, (n, m, opt.layers), a, a * opt.c_over_a,
107 1 tkerber
                       opt.vacuum)
108 1 tkerber
        r = a / 2
109 1 tkerber
    else:
110 1 tkerber
        raise NotImplementedError
111 1 tkerber
112 1 tkerber
    magmom = opt.magnetic_moment
113 1 tkerber
    if magmom is None:
114 1 tkerber
        magmom = {'Ni': 0.6, 'Co': 1.2, 'Fe': 2.3}.get(surf, 0.0)
115 1 tkerber
    slab.set_initial_magnetic_moments([magmom] * len(slab))
116 1 tkerber
117 1 tkerber
    slab.pbc = 1
118 1 tkerber
119 1 tkerber
    name = '%dx%d%s%s' % (n, m, surf, face)
120 1 tkerber
121 1 tkerber
    if ads:
122 1 tkerber
        site = 'ontop'
123 1 tkerber
        if '-' in ads:
124 1 tkerber
            site, ads = ads.split('-')
125 1 tkerber
126 1 tkerber
        name = site + '-' + ads + '@' + name
127 1 tkerber
        symbols = string2symbols(ads)
128 1 tkerber
        nads = len(symbols)
129 1 tkerber
        if nads == 1:
130 1 tkerber
            ads = Atoms(ads)
131 1 tkerber
        else:
132 1 tkerber
            ads = molecule(ads)
133 1 tkerber
134 1 tkerber
        add_adsorbate(slab, ads, 0.0, site)
135 1 tkerber
136 1 tkerber
        d = opt.distance
137 1 tkerber
        if d is None:
138 1 tkerber
            d = r + covalent_radii[ads[0].number] / 2
139 1 tkerber
140 1 tkerber
        h = opt.height
141 1 tkerber
        if h is None:
142 1 tkerber
            R = slab.positions
143 1 tkerber
            y = ((R[:-nads] - R[-nads])**2).sum(1).min()**0.5
144 1 tkerber
            print y
145 1 tkerber
            h = (d**2 - y**2)**0.5
146 1 tkerber
            print h
147 1 tkerber
        else:
148 1 tkerber
            assert opt.distance is None
149 1 tkerber
150 1 tkerber
        slab.positions[-nads:, 2] += h
151 1 tkerber
152 1 tkerber
    if len(args) == 2:
153 1 tkerber
        write(args[1], slab)
154 1 tkerber
    elif not opt.gui:
155 1 tkerber
        write(name + '.traj', slab)
156 1 tkerber
157 1 tkerber
    if opt.gui:
158 1 tkerber
        view(slab)
159 1 tkerber
160 1 tkerber
161 1 tkerber
if __name__ == '__main__':
162 1 tkerber
    build()