root / ase / io / xsf.py @ 12
Historique | Voir | Annoter | Télécharger (4,27 ko)
1 |
import numpy as np |
---|---|
2 |
|
3 |
from ase.atoms import Atoms |
4 |
from ase.units import Hartree |
5 |
from ase.parallel import paropen |
6 |
from ase.calculators.singlepoint import SinglePointCalculator |
7 |
|
8 |
|
9 |
def write_xsf(fileobj, images, data=None): |
10 |
if isinstance(fileobj, str): |
11 |
fileobj = paropen(fileobj, 'w')
|
12 |
|
13 |
if not isinstance(images, (list, tuple)): |
14 |
images = [images] |
15 |
|
16 |
fileobj.write('ANIMSTEPS %d\n' % len(images)) |
17 |
|
18 |
numbers = images[0].get_atomic_numbers()
|
19 |
|
20 |
pbc = images[0].get_pbc()
|
21 |
if pbc[2]: |
22 |
fileobj.write('CRYSTAL\n')
|
23 |
elif pbc[1]: |
24 |
fileobj.write('SLAB\n')
|
25 |
elif pbc[0]: |
26 |
fileobj.write('POLYMER\n')
|
27 |
else:
|
28 |
fileobj.write('MOLECULE\n')
|
29 |
|
30 |
for n, atoms in enumerate(images): |
31 |
if pbc.any():
|
32 |
fileobj.write('PRIMVEC %d\n' % (n + 1)) |
33 |
cell = atoms.get_cell() |
34 |
for i in range(3): |
35 |
fileobj.write(' %.14f %.14f %.14f\n' % tuple(cell[i])) |
36 |
|
37 |
fileobj.write('PRIMCOORD %d\n' % (n + 1)) |
38 |
|
39 |
# Get the forces if it's not too expensive:
|
40 |
calc = atoms.get_calculator() |
41 |
if (calc is not None and |
42 |
(hasattr(calc, 'calculation_required') and |
43 |
not calc.calculation_required(atoms,
|
44 |
['energy', 'forces', 'stress']))): |
45 |
forces = atoms.get_forces() |
46 |
else:
|
47 |
forces = None
|
48 |
|
49 |
pos = atoms.get_positions() |
50 |
|
51 |
fileobj.write(' %d 1\n' % len(pos)) |
52 |
for a in range(len(pos)): |
53 |
fileobj.write(' %2d' % numbers[a])
|
54 |
fileobj.write(' %20.14f %20.14f %20.14f' % tuple(pos[a])) |
55 |
if forces is None: |
56 |
fileobj.write('\n')
|
57 |
else:
|
58 |
fileobj.write(' %20.14f %20.14f %20.14f\n' % tuple(forces[a])) |
59 |
|
60 |
if data is None: |
61 |
return
|
62 |
|
63 |
fileobj.write('BEGIN_BLOCK_DATAGRID_3D\n')
|
64 |
fileobj.write(' data\n')
|
65 |
fileobj.write(' BEGIN_DATAGRID_3Dgrid#1\n')
|
66 |
|
67 |
data = np.asarray(data) |
68 |
if data.dtype == complex: |
69 |
data = np.abs(data) |
70 |
|
71 |
shape = data.shape |
72 |
fileobj.write(' %d %d %d\n' % shape)
|
73 |
|
74 |
cell = atoms.get_cell() |
75 |
origin = np.zeros(3)
|
76 |
for i in range(3): |
77 |
if not pbc[i]: |
78 |
origin += cell[i] / shape[i] |
79 |
fileobj.write(' %f %f %f\n' % tuple(origin)) |
80 |
|
81 |
for i in range(3): |
82 |
fileobj.write(' %f %f %f\n' %
|
83 |
tuple(cell[i] * (shape[i] + 1) / shape[i])) |
84 |
|
85 |
for x in range(shape[2]): |
86 |
for y in range(shape[1]): |
87 |
fileobj.write(' ')
|
88 |
fileobj.write(' '.join(['%f' % d for d in data[x, y]])) |
89 |
fileobj.write('\n')
|
90 |
fileobj.write('\n')
|
91 |
|
92 |
fileobj.write(' END_DATAGRID_3D\n')
|
93 |
fileobj.write('END_BLOCK_DATAGRID_3D\n')
|
94 |
|
95 |
|
96 |
def read_xsf(fileobj, index=-1): |
97 |
if isinstance(fileobj, str): |
98 |
fileobj = open(fileobj)
|
99 |
|
100 |
readline = fileobj.readline |
101 |
line = readline() |
102 |
|
103 |
if line.startswith('ANIMSTEPS'): |
104 |
nimages = int(line.split()[1]) |
105 |
line = readline() |
106 |
else:
|
107 |
nimages = 1
|
108 |
|
109 |
if line.startswith('CRYSTAL'): |
110 |
pbc = True
|
111 |
elif line.startswith('SLAB'): |
112 |
pbc = (True, True, Flase) |
113 |
elif line.startswith('POLYMER'): |
114 |
pbc = (True, False, Flase) |
115 |
else:
|
116 |
pbc = False
|
117 |
|
118 |
images = [] |
119 |
for n in range(nimages): |
120 |
cell = None
|
121 |
if pbc:
|
122 |
line = readline() |
123 |
assert line.startswith('PRIMVEC') |
124 |
cell = [] |
125 |
for i in range(3): |
126 |
cell.append([float(x) for x in readline().split()]) |
127 |
|
128 |
line = readline() |
129 |
assert line.startswith('PRIMCOORD') |
130 |
|
131 |
natoms = int(readline().split()[0]) |
132 |
numbers = [] |
133 |
positions = [] |
134 |
for a in range(natoms): |
135 |
line = readline().split() |
136 |
numbers.append(int(line[0])) |
137 |
positions.append([float(x) for x in line[1:]]) |
138 |
|
139 |
positions = np.array(positions) |
140 |
if len(positions[0]) == 3: |
141 |
forces = None
|
142 |
else:
|
143 |
positions = positions[:, :3]
|
144 |
forces = positions[:, 3:] * Hartree
|
145 |
|
146 |
image = Atoms(numbers, positions, cell=cell, pbc=pbc) |
147 |
|
148 |
if forces is not None: |
149 |
image.set_calculator(SinglePointCalculator(None, forces, None, |
150 |
None, image))
|
151 |
images.append(image) |
152 |
|
153 |
return images[index]
|