root / ase / io / cfg.py
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
|