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