Statistiques
| Révision :

root / ase / io / cfg.py @ 1

Historique | Voir | Annoter | Télécharger (6,56 ko)

1
import numpy as np
2

    
3
import ase
4

    
5
from ase.parallel import paropen
6

    
7

    
8
cfg_default_fields = np.array( [ 'positions', 'momenta', 'numbers', 'magmoms' ] )
9

    
10
def write_cfg(f, a):
11
    """Write atomic configuration to a CFG-file (native AtomEye format).
12
       See: http://mt.seas.upenn.edu/Archive/Graphics/A/
13
    """
14
    if isinstance(f, str):
15
        f = paropen(f, 'w')
16

    
17
    f.write('Number of particles = %i\n' % len(a))
18
    f.write('A = 1.0 Angstrom\n')
19
    cell = a.get_cell()
20
    for i in range(3):
21
        for j in range(3):
22
            f.write('H0(%1.1i,%1.1i) = %f A\n' % ( i + 1, j + 1, cell[i, j] ))
23

    
24
    entry_count  = 3
25
    for x in a.arrays.keys():
26
        if not x in cfg_default_fields:
27
            if len(a.get_array(x).shape) == 1:
28
                entry_count += 1
29
            else:
30
                entry_count += a.get_array(x).shape[1]
31

    
32
    vels = a.get_velocities()
33
    if type(vels) == np.ndarray:
34
        entry_count += 3
35
    else:
36
        f.write('.NO_VELOCITY.\n')
37

    
38
    f.write('entry_count = %i\n' % entry_count)
39

    
40
    i = 0
41
    for name, aux in a.arrays.iteritems():
42
        if not name in cfg_default_fields:
43
            if len(aux.shape) == 1:
44
                f.write('auxiliary[%i] = %s [a.u.]\n' % ( i, name ))
45
                i += 1
46
            else:
47
                for j in range(aux.shape[1]):
48
                    f.write('auxiliary[%i] = %s_%1.1i [a.u.]\n' % ( i, name, j ))
49
                    i += 1
50

    
51
    # Distinct elements
52
    spos = a.get_scaled_positions()
53
    for i in a:
54
        el  = i.get_symbol()
55

    
56
        f.write('%f\n' % ase.data.atomic_masses[ase.data.chemical_symbols.index(el)])
57
        f.write('%s\n' % el)
58

    
59
        x, y, z = spos[i.index, :]
60
        s =  '%e %e %e ' % ( x, y, z )
61

    
62
        if type(vels) == np.ndarray:
63
            vx, vy, vz  = vels[i.index, :]
64
            s  = s + ' %e %e %e ' % ( vx, vy, vz )
65

    
66
        for name, aux in a.arrays.iteritems():
67
            if not name in cfg_default_fields:
68
                if len(aux.shape) == 1:
69
                    s += ' %e' % aux[i.index]
70
                else:
71
                    s += ( aux.shape[1]*' %e' ) % tuple(aux[i.index].tolist())
72
                         
73
        f.write('%s\n' % s)
74

    
75

    
76
default_color = {
77
    'H': [ 0.800, 0.800, 0.800 ],
78
    'C': [ 0.350, 0.350, 0.350 ],
79
    'O': [ 0.800, 0.200, 0.200 ]
80
    }
81

    
82
default_radius = {
83
    'H': 0.435,
84
    'C': 0.655,
85
    'O': 0.730
86
    }
87
       
88

    
89

    
90
def write_clr(f, atoms):
91
    """Write extra color and radius code to a CLR-file (for use with AtomEye).
92
       Hit F12 in AtomEye to use.
93
       See: http://mt.seas.upenn.edu/Archive/Graphics/A/
94
    """
95
    color   = None
96
    radius  = None
97
    if atoms.has('color'):
98
        color  = atoms.get_array('color')
99
    if atoms.has('radius'):
100
        radius  = atoms.get_array('radius')
101

    
102
    if color is None:
103
        color  = np.zeros([len(atoms),3], dtype=float)
104
        for a in atoms:
105
            color[a.index, :]  = default_color[a.get_symbol()]
106

    
107
    if radius is None:
108
        radius  = np.zeros(len(atoms), dtype=float)
109
        for a in atoms:
110
            radius[a.index]  = default_radius[a.get_symbol()]
111

    
112
    radius.shape = (-1, 1)
113

    
114
    if isinstance(f, str):
115
        f = paropen(f, 'w')   
116
    for c1, c2, c3, r in np.append(color, radius, axis=1):
117
        f.write('%f %f %f %f\n' % ( c1, c2, c3, r ))
118

    
119

    
120
###
121

    
122
def read_key_val(f):
123
    if isinstance(f, str):
124
        l = f
125
    else:
126
        l = f.readline()
127
    s = l.split('=')
128
    if len(s) != 2:
129
        raise RuntimeError("Line '%s' is not of the form 'key = value'." % l[:-1])
130
    return ( s[0].strip(), s[1].strip() )
131

    
132

    
133
def read_str_key(f, key, key2=None):
134
    in_key, val  = read_key_val(f)
135
    if key2 is None:
136
        if key.upper() != in_key.upper():
137
            raise RuntimeError("Key '%s' expected, '%s' found." % ( key, in_key ))
138
    else:
139
        if key.upper() != in_key.upper() and key2.upper() != in_key.upper():
140
            raise RuntimeError("Key '%s' or '%s' expected, '%s' found." % ( key, key2, in_key ))
141
    return val
142

    
143

    
144
def read_int_key(f, key):
145
    vals  = read_str_key(f, key).split()
146
    # Ignore units
147
    return int(vals[0])
148

    
149

    
150
def read_float_key(f, key):
151
    vals  = read_str_key(f, key).split()
152
    # Ignore units
153
    return float(vals[0])
154

    
155

    
156
###
157

    
158
def read_cfg(f):
159
    """Read atomic configuration from a CFG-file (native AtomEye format).
160
       See: http://mt.seas.upenn.edu/Archive/Graphics/A/
161
    """
162
    if isinstance(f, str):
163
        f  = open(f)
164

    
165
    nat   = read_int_key(f, 'Number of particles')
166
    unit  = read_float_key(f, 'A')
167

    
168
    cell  = np.zeros( [ 3, 3 ] )
169
    for i in range(3):
170
        for j in range(3):
171
            cell[i, j]  = read_float_key(f, 'H0(%1.1i,%1.1i)' % (i + 1, j + 1))
172

    
173
    l     = f.readline()
174
    vels  = None
175
    if l.strip() == '.NO_VELOCITY.':
176
        l     = f.readline()
177
    else:
178
        vels  = np.zeros( [ nat, 3 ] )
179

    
180
    naux      = read_int_key(l, 'entry_count') - 3
181
    if vels is not None:
182
        naux -= 3
183
    aux       = np.zeros( [ nat, naux ] )
184

    
185
    auxstrs   = [ ]
186
    for i in range(naux):
187
        s  = read_str_key(f, 'auxiliary[%1.1i]' % i, 'auxiliary[%2.2i]' % i)
188
        auxstrs += [ s[:s.find('[')].strip() ]
189

    
190
    spos     = np.zeros( [ nat, 3 ] )
191
    masses   = np.zeros( nat )
192
    syms     = [ '' for i in range(nat) ]
193

    
194
    i  = 0
195
    s  = f.readline().split()
196
    while l:
197
        mass   = float(s[0])
198
        sym    = f.readline().strip()
199

    
200
        l      = f.readline()
201
        s      = l.split()
202

    
203
        while l and len(s) > 1:
204
            masses[i]  = mass
205
            syms[i]    = sym
206
            props      = [ float(x) for x in s ]
207

    
208
            spos[i, :] = props[0:3]
209
            off        = 3
210
            if vels is not None:
211
                off         = 6
212
                vels[i, :]  = props[3:6]
213

    
214
            aux[i, :]  = props[off:]
215

    
216
            i  += 1
217

    
218
            l  = f.readline()
219
            if l:
220
                s  = l.split()
221
                
222
    if vels is None:
223
        a = ase.Atoms(
224
            symbols           = syms,
225
            masses            = masses,
226
            scaled_positions  = spos,
227
            cell              = cell,
228
            pbc               = True
229
        )
230
    else:
231
        a = ase.Atoms(
232
            symbols           = syms,
233
            masses            = masses,
234
            scaled_positions  = spos,
235
            momenta           = masses.reshape(-1,1)*vels,
236
            cell              = cell,
237
            pbc               = True
238
        )
239

    
240
    i  = 0
241
    while i < naux:
242
        auxstr  = auxstrs[i]
243

    
244
        if auxstr[-2:] == '_x':
245
            a.set_array(auxstr[:-2], aux[:, i:i+3])
246

    
247
            i  += 3
248
        else:
249
            a.set_array(auxstr, aux[:, i])
250

    
251
            i  += 1
252

    
253
    return a