Statistiques
| Révision :

root / ase / io / xsf.py @ 19

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]