Statistiques
| Révision :

root / ase / gui / images.py @ 20

Historique | Voir | Annoter | Télécharger (12,65 ko)

1 1 tkerber
from math import sqrt
2 1 tkerber
3 1 tkerber
import numpy as np
4 1 tkerber
5 1 tkerber
from ase.data import covalent_radii
6 1 tkerber
from ase.atoms import Atoms
7 1 tkerber
from ase.calculators.singlepoint import SinglePointCalculator
8 1 tkerber
from ase.io import read, write, string2index
9 1 tkerber
from ase.constraints import FixAtoms
10 1 tkerber
11 1 tkerber
12 1 tkerber
class Images:
13 1 tkerber
    def __init__(self, images=None):
14 1 tkerber
15 1 tkerber
        if images is not None:
16 1 tkerber
            self.initialize(images)
17 1 tkerber
18 1 tkerber
    def initialize(self, images, filenames=None, init_magmom=False):
19 1 tkerber
20 1 tkerber
        self.natoms = len(images[0])
21 1 tkerber
22 1 tkerber
        self.nimages = len(images)
23 1 tkerber
        if filenames is None:
24 1 tkerber
            filenames = [None] * self.nimages
25 1 tkerber
        self.filenames = filenames
26 1 tkerber
        self.P = np.empty((self.nimages, self.natoms, 3))
27 1 tkerber
        self.E = np.empty(self.nimages)
28 1 tkerber
        self.K = np.empty(self.nimages)
29 1 tkerber
        self.F = np.empty((self.nimages, self.natoms, 3))
30 1 tkerber
        self.M = np.empty((self.nimages, self.natoms))
31 1 tkerber
        self.T = np.empty((self.natoms))
32 1 tkerber
        self.A = np.empty((self.nimages, 3, 3))
33 1 tkerber
        self.Z = images[0].get_atomic_numbers()
34 1 tkerber
        self.pbc = images[0].get_pbc()
35 1 tkerber
        warning = False
36 1 tkerber
        for i, atoms in enumerate(images):
37 1 tkerber
            natomsi = len(atoms)
38 1 tkerber
            if (natomsi != self.natoms or
39 1 tkerber
                (atoms.get_atomic_numbers() != self.Z).any()):
40 1 tkerber
                raise RuntimeError('Can not handle different images with ' +
41 1 tkerber
                                   'different numbers of atoms or different ' +
42 1 tkerber
                                   'kinds of atoms!')
43 1 tkerber
            self.P[i] = atoms.get_positions()
44 1 tkerber
            self.A[i] = atoms.get_cell()
45 1 tkerber
            if (atoms.get_pbc() != self.pbc).any():
46 1 tkerber
                warning = True
47 1 tkerber
            try:
48 1 tkerber
                self.E[i] = atoms.get_potential_energy()
49 1 tkerber
            except RuntimeError:
50 1 tkerber
                self.E[i] = np.nan
51 1 tkerber
            self.K[i] = atoms.get_kinetic_energy()
52 1 tkerber
            try:
53 1 tkerber
                self.F[i] = atoms.get_forces(apply_constraint=False)
54 1 tkerber
            except RuntimeError:
55 1 tkerber
                self.F[i] = np.nan
56 1 tkerber
            try:
57 1 tkerber
                if init_magmom:
58 1 tkerber
                    self.M[i] = atoms.get_initial_magnetic_moments()
59 1 tkerber
                else:
60 1 tkerber
                  self.M[i] = atoms.get_magnetic_moments()
61 1 tkerber
            except (RuntimeError, AttributeError):
62 1 tkerber
                self.M[i] = 0.0
63 1 tkerber
64 1 tkerber
            # added support for tags
65 1 tkerber
            try:
66 1 tkerber
                self.T = atoms.get_tags()
67 1 tkerber
            except RuntimeError:
68 1 tkerber
                self.T = np.nan
69 1 tkerber
70 1 tkerber
71 1 tkerber
        if warning:
72 1 tkerber
            print('WARNING: Not all images have the same bondary conditions!')
73 1 tkerber
74 1 tkerber
        self.selected = np.zeros(self.natoms, bool)
75 1 tkerber
        self.selected_ordered  = []
76 1 tkerber
        self.atoms_to_rotate_0 = np.zeros(self.natoms, bool)
77 1 tkerber
        self.visible = np.ones(self.natoms, bool)
78 1 tkerber
        self.nselected = 0
79 1 tkerber
        self.set_dynamic(constraints = images[0].constraints)
80 1 tkerber
        self.repeat = np.ones(3, int)
81 1 tkerber
        self.set_radii(0.89)
82 1 tkerber
83 1 tkerber
    def prepare_new_atoms(self):
84 1 tkerber
        "Marks that the next call to append_atoms should clear the images."
85 1 tkerber
        self.next_append_clears = True
86 1 tkerber
87 1 tkerber
    def append_atoms(self, atoms, filename=None):
88 1 tkerber
        "Append an atoms object to the images already stored."
89 1 tkerber
        assert len(atoms) == self.natoms
90 1 tkerber
        if self.next_append_clears:
91 1 tkerber
            i = 0
92 1 tkerber
        else:
93 1 tkerber
            i = self.nimages
94 1 tkerber
        for name in ('P', 'E', 'K', 'F', 'M', 'A'):
95 1 tkerber
            a = getattr(self, name)
96 1 tkerber
            newa = np.empty( (i+1,) + a.shape[1:] )
97 1 tkerber
            if not self.next_append_clears:
98 1 tkerber
                newa[:-1] = a
99 1 tkerber
            setattr(self, name, newa)
100 1 tkerber
        self.next_append_clears = False
101 1 tkerber
        self.P[i] = atoms.get_positions()
102 1 tkerber
        self.A[i] = atoms.get_cell()
103 1 tkerber
        try:
104 1 tkerber
            self.E[i] = atoms.get_potential_energy()
105 1 tkerber
        except RuntimeError:
106 1 tkerber
            self.E[i] = np.nan
107 1 tkerber
        self.K[i] = atoms.get_kinetic_energy()
108 1 tkerber
        try:
109 1 tkerber
            self.F[i] = atoms.get_forces(apply_constraint=False)
110 1 tkerber
        except RuntimeError:
111 1 tkerber
            self.F[i] = np.nan
112 1 tkerber
        try:
113 1 tkerber
            self.M[i] = atoms.get_magnetic_moments()
114 1 tkerber
        except (RuntimeError, AttributeError):
115 1 tkerber
            self.M[i] = np.nan
116 1 tkerber
        self.nimages = i + 1
117 1 tkerber
        self.filenames.append(filename)
118 1 tkerber
        self.set_dynamic()
119 1 tkerber
        return self.nimages
120 1 tkerber
121 1 tkerber
    def set_radii(self, scale):
122 1 tkerber
        self.r = covalent_radii[self.Z] * scale
123 1 tkerber
124 1 tkerber
    def read(self, filenames, index=-1):
125 1 tkerber
        images = []
126 1 tkerber
        names = []
127 1 tkerber
        for filename in filenames:
128 1 tkerber
            i = read(filename, index)
129 1 tkerber
130 1 tkerber
            if not isinstance(i, list):
131 1 tkerber
                i = [i]
132 1 tkerber
            images.extend(i)
133 1 tkerber
            names.extend([filename] * len(i))
134 1 tkerber
135 1 tkerber
        self.initialize(images, names)
136 1 tkerber
137 1 tkerber
    def import_atoms(self, filename, cur_frame):
138 1 tkerber
        if filename:
139 1 tkerber
            filename = filename[0]
140 1 tkerber
            old_a = self.get_atoms(cur_frame)
141 1 tkerber
            imp_a = read(filename, -1)
142 1 tkerber
            new_a = old_a + imp_a
143 1 tkerber
            self.initialize([new_a], [filename])
144 1 tkerber
145 1 tkerber
    def repeat_images(self, repeat):
146 1 tkerber
        n = self.repeat.prod()
147 1 tkerber
        repeat = np.array(repeat)
148 1 tkerber
        self.repeat = repeat
149 1 tkerber
        N = repeat.prod()
150 1 tkerber
        natoms = self.natoms // n
151 1 tkerber
        P = np.empty((self.nimages, natoms * N, 3))
152 1 tkerber
        M = np.empty((self.nimages, natoms * N))
153 1 tkerber
        T = np.empty(natoms * N, int)
154 1 tkerber
        F = np.empty((self.nimages, natoms * N, 3))
155 1 tkerber
        Z = np.empty(natoms * N, int)
156 1 tkerber
        r = np.empty(natoms * N)
157 1 tkerber
        dynamic = np.empty(natoms * N, bool)
158 1 tkerber
        a0 = 0
159 1 tkerber
        for i0 in range(repeat[0]):
160 1 tkerber
            for i1 in range(repeat[1]):
161 1 tkerber
                for i2 in range(repeat[2]):
162 1 tkerber
                    a1 = a0 + natoms
163 1 tkerber
                    for i in range(self.nimages):
164 1 tkerber
                        P[i, a0:a1] = (self.P[i, :natoms] +
165 1 tkerber
                                       np.dot((i0, i1, i2), self.A[i]))
166 1 tkerber
                    F[:, a0:a1] = self.F[:, :natoms]
167 1 tkerber
                    M[:, a0:a1] = self.M[:, :natoms]
168 1 tkerber
                    T[a0:a1] = self.T[:natoms]
169 1 tkerber
                    Z[a0:a1] = self.Z[:natoms]
170 1 tkerber
                    r[a0:a1] = self.r[:natoms]
171 1 tkerber
                    dynamic[a0:a1] = self.dynamic[:natoms]
172 1 tkerber
                    a0 = a1
173 1 tkerber
        self.P = P
174 1 tkerber
        self.F = F
175 1 tkerber
        self.Z = Z
176 1 tkerber
        self.T = T
177 1 tkerber
        self.M = M
178 1 tkerber
        self.r = r
179 1 tkerber
        self.dynamic = dynamic
180 1 tkerber
        self.natoms = natoms * N
181 1 tkerber
        self.selected = np.zeros(natoms * N, bool)
182 1 tkerber
        self.atoms_to_rotate_0 = np.zeros(self.natoms, bool)
183 1 tkerber
        self.visible = np.ones(natoms * N, bool)
184 1 tkerber
        self.nselected = 0
185 1 tkerber
186 1 tkerber
    def graph(self, expr):
187 1 tkerber
        import ase.units as units
188 1 tkerber
        code = compile(expr + ',', 'atoms.py', 'eval')
189 1 tkerber
190 1 tkerber
        n = self.nimages
191 1 tkerber
        def d(n1, n2):
192 1 tkerber
            return sqrt(((R[n1] - R[n2])**2).sum())
193 1 tkerber
        def a(n1, n2, n3):
194 1 tkerber
            v1 = R[n1]-R[n2]
195 1 tkerber
            v2 = R[n3]-R[n2]
196 1 tkerber
            arg = np.vdot(v1,v2)/(sqrt((v1**2).sum()*(v2**2).sum()))
197 1 tkerber
            if arg > 1.0: arg = 1.0
198 1 tkerber
            if arg < -1.0: arg = -1.0
199 1 tkerber
            return 180.0*np.arccos(arg)/np.pi
200 1 tkerber
        def dih(n1, n2, n3, n4):
201 1 tkerber
            # vector 0->1, 1->2, 2->3 and their normalized cross products:
202 1 tkerber
            a    = R[n2]-R[n1]
203 1 tkerber
            b    = R[n3]-R[n2]
204 1 tkerber
            c    = R[n4]-R[n3]
205 1 tkerber
            bxa  = np.cross(b,a)
206 1 tkerber
            bxa /= np.sqrt(np.vdot(bxa,bxa))
207 1 tkerber
            cxb  = np.cross(c,b)
208 1 tkerber
            cxb /= np.sqrt(np.vdot(cxb,cxb))
209 1 tkerber
            angle = np.vdot(bxa,cxb)
210 1 tkerber
            # check for numerical trouble due to finite precision:
211 1 tkerber
            if angle < -1: angle = -1
212 1 tkerber
            if angle >  1: angle =  1
213 1 tkerber
            angle = np.arccos(angle)
214 1 tkerber
            if (np.vdot(bxa,c)) > 0: angle = 2*np.pi-angle
215 1 tkerber
            return angle*180.0/np.pi
216 1 tkerber
        # get number of mobile atoms for temperature calculation
217 1 tkerber
        ndynamic = 0
218 1 tkerber
        for dyn in self.dynamic:
219 1 tkerber
            if dyn: ndynamic += 1
220 1 tkerber
        S = self.selected
221 1 tkerber
        D = self.dynamic[:, np.newaxis]
222 1 tkerber
        E = self.E
223 1 tkerber
        s = 0.0
224 1 tkerber
        data = []
225 1 tkerber
        for i in range(n):
226 1 tkerber
            R = self.P[i]
227 1 tkerber
            F = self.F[i]
228 1 tkerber
            A = self.A[i]
229 1 tkerber
            f = ((F * D)**2).sum(1)**.5
230 1 tkerber
            fmax = max(f)
231 1 tkerber
            fave = f.mean()
232 1 tkerber
            epot = E[i]
233 1 tkerber
            ekin = self.K[i]
234 1 tkerber
            e = epot + ekin
235 1 tkerber
            T = 2.0 * ekin / (3.0 * ndynamic * units.kB)
236 1 tkerber
            data = eval(code)
237 1 tkerber
            if i == 0:
238 1 tkerber
                m = len(data)
239 1 tkerber
                xy = np.empty((m, n))
240 1 tkerber
            xy[:, i] = data
241 1 tkerber
            if i + 1 < n:
242 1 tkerber
                s += sqrt(((self.P[i + 1] - R)**2).sum())
243 1 tkerber
        return xy
244 1 tkerber
245 1 tkerber
    def set_dynamic(self, constraints = None):
246 1 tkerber
        if self.nimages == 1:
247 1 tkerber
            self.dynamic = np.ones(self.natoms, bool)
248 1 tkerber
        else:
249 1 tkerber
            self.dynamic = np.zeros(self.natoms, bool)
250 1 tkerber
            R0 = self.P[0]
251 1 tkerber
            for R in self.P[1:]:
252 1 tkerber
                self.dynamic |= (np.abs(R - R0) > 1.0e-10).any(1)
253 1 tkerber
        if constraints is not None:
254 1 tkerber
            for con in constraints:
255 1 tkerber
                if isinstance(con,FixAtoms):
256 1 tkerber
                    self.dynamic[con.index] = False
257 1 tkerber
258 1 tkerber
    def write(self, filename, rotations='', show_unit_cell=False, bbox=None):
259 1 tkerber
        indices = range(self.nimages)
260 1 tkerber
        p = filename.rfind('@')
261 1 tkerber
        if p != -1:
262 1 tkerber
            try:
263 1 tkerber
                slice = string2index(filename[p + 1:])
264 1 tkerber
            except ValueError:
265 1 tkerber
                pass
266 1 tkerber
            else:
267 1 tkerber
                indices = indices[slice]
268 1 tkerber
                filename = filename[:p]
269 1 tkerber
                if isinstance(indices, int):
270 1 tkerber
                    indices = [indices]
271 1 tkerber
272 1 tkerber
        images = [self.get_atoms(i) for i in indices]
273 1 tkerber
        if len(filename) > 4 and filename[-4:] in ['.eps', '.png', '.pov']:
274 1 tkerber
            write(filename, images,
275 1 tkerber
                  rotation=rotations, show_unit_cell=show_unit_cell,
276 1 tkerber
                  bbox=bbox)
277 1 tkerber
        else:
278 1 tkerber
            write(filename, images)
279 1 tkerber
280 1 tkerber
    def get_atoms(self, frame):
281 1 tkerber
        atoms = Atoms(positions=self.P[frame],
282 1 tkerber
                      numbers=self.Z,
283 1 tkerber
                      magmoms=self.M[0],
284 1 tkerber
                      tags=self.T,
285 1 tkerber
                      cell=self.A[frame],
286 1 tkerber
                      pbc=self.pbc)
287 1 tkerber
288 1 tkerber
        # check for constrained atoms and add them accordingly:
289 1 tkerber
        if not self.dynamic.all():
290 1 tkerber
            atoms.set_constraint(FixAtoms(mask=1-self.dynamic))
291 1 tkerber
292 1 tkerber
        atoms.set_calculator(SinglePointCalculator(self.E[frame],
293 1 tkerber
                                                   self.F[frame],
294 1 tkerber
                                                   None, None, atoms))
295 1 tkerber
        return atoms
296 1 tkerber
297 1 tkerber
    def delete(self, i):
298 1 tkerber
        self.nimages -= 1
299 1 tkerber
        P = np.empty((self.nimages, self.natoms, 3))
300 1 tkerber
        F = np.empty((self.nimages, self.natoms, 3))
301 1 tkerber
        A = np.empty((self.nimages, 3, 3))
302 1 tkerber
        E = np.empty(self.nimages)
303 1 tkerber
        P[:i] = self.P[:i]
304 1 tkerber
        P[i:] = self.P[i + 1:]
305 1 tkerber
        self.P = P
306 1 tkerber
        F[:i] = self.F[:i]
307 1 tkerber
        F[i:] = self.F[i + 1:]
308 1 tkerber
        self.F = F
309 1 tkerber
        A[:i] = self.A[:i]
310 1 tkerber
        A[i:] = self.A[i + 1:]
311 1 tkerber
        self.A = A
312 1 tkerber
        E[:i] = self.E[:i]
313 1 tkerber
        E[i:] = self.E[i + 1:]
314 1 tkerber
        self.E = E
315 1 tkerber
        del self.filenames[i]
316 1 tkerber
317 1 tkerber
    def aneb(self):
318 1 tkerber
        n = self.nimages
319 1 tkerber
        assert n % 5 == 0
320 1 tkerber
        levels = n // 5
321 1 tkerber
        n = self.nimages = 2 * levels + 3
322 1 tkerber
        P = np.empty((self.nimages, self.natoms, 3))
323 1 tkerber
        F = np.empty((self.nimages, self.natoms, 3))
324 1 tkerber
        E = np.empty(self.nimages)
325 1 tkerber
        for L in range(levels):
326 1 tkerber
            P[L] = self.P[L * 5]
327 1 tkerber
            P[n - L - 1] = self.P[L * 5 + 4]
328 1 tkerber
            F[L] = self.F[L * 5]
329 1 tkerber
            F[n - L - 1] = self.F[L * 5 + 4]
330 1 tkerber
            E[L] = self.E[L * 5]
331 1 tkerber
            E[n - L - 1] = self.E[L * 5 + 4]
332 1 tkerber
        for i in range(3):
333 1 tkerber
            P[levels + i] = self.P[levels * 5 - 4 + i]
334 1 tkerber
            F[levels + i] = self.F[levels * 5 - 4 + i]
335 1 tkerber
            E[levels + i] = self.E[levels * 5 - 4 + i]
336 1 tkerber
        self.P = P
337 1 tkerber
        self.F = F
338 1 tkerber
        self.E = E
339 1 tkerber
340 1 tkerber
    def interpolate(self, m):
341 1 tkerber
        assert self.nimages == 2
342 1 tkerber
        self.nimages = 2 + m
343 1 tkerber
        P = np.empty((self.nimages, self.natoms, 3))
344 1 tkerber
        F = np.empty((self.nimages, self.natoms, 3))
345 1 tkerber
        A = np.empty((self.nimages, 3, 3))
346 1 tkerber
        E = np.empty(self.nimages)
347 1 tkerber
        P[0] = self.P[0]
348 1 tkerber
        F[0] = self.F[0]
349 1 tkerber
        A[0] = self.A[0]
350 1 tkerber
        E[0] = self.E[0]
351 1 tkerber
        for i in range(1, m + 1):
352 1 tkerber
            x = i / (m + 1.0)
353 1 tkerber
            y = 1 - x
354 1 tkerber
            P[i] = y * self.P[0] + x * self.P[1]
355 1 tkerber
            F[i] = y * self.F[0] + x * self.F[1]
356 1 tkerber
            A[i] = y * self.A[0] + x * self.A[1]
357 1 tkerber
            E[i] = y * self.E[0] + x * self.E[1]
358 1 tkerber
        P[-1] = self.P[1]
359 1 tkerber
        F[-1] = self.F[1]
360 1 tkerber
        A[-1] = self.A[1]
361 1 tkerber
        E[-1] = self.E[1]
362 1 tkerber
        self.P = P
363 1 tkerber
        self.F = F
364 1 tkerber
        self.A = A
365 1 tkerber
        self.E = E
366 1 tkerber
        self.filenames[1:1] = [None] * m
367 1 tkerber
368 1 tkerber
if __name__ == '__main__':
369 1 tkerber
    import os
370 1 tkerber
    os.system('python gui.py')