Statistiques
| Révision :

root / ase / optimize / optimize.py @ 1

Historique | Voir | Annoter | Télécharger (5,59 ko)

1 1 tkerber
"""Structure optimization. """
2 1 tkerber
3 1 tkerber
import sys
4 1 tkerber
import pickle
5 1 tkerber
import time
6 1 tkerber
from math import sqrt
7 1 tkerber
from os.path import isfile
8 1 tkerber
9 1 tkerber
import numpy as np
10 1 tkerber
11 1 tkerber
from ase.parallel import rank, barrier
12 1 tkerber
from ase.io.trajectory import PickleTrajectory
13 1 tkerber
14 1 tkerber
15 1 tkerber
class Dynamics:
16 1 tkerber
    """Base-class for all MD and structure optimization classes.
17 1 tkerber

18 1 tkerber
    Dynamics(atoms, logfile)
19 1 tkerber

20 1 tkerber
    atoms: Atoms object
21 1 tkerber
        The Atoms object to operate on
22 1 tkerber
    logfile: file object or str
23 1 tkerber
        If *logfile* is a string, a file with that name will be opened.
24 1 tkerber
        Use '-' for stdout.
25 1 tkerber
    trajectory: Trajectory object or str
26 1 tkerber
        Attach trajectory object.  If *trajectory* is a string a
27 1 tkerber
        PickleTrajectory will be constructed.  Use *None* for no
28 1 tkerber
        trajectory.
29 1 tkerber
    """
30 1 tkerber
    def __init__(self, atoms, logfile, trajectory):
31 1 tkerber
        self.atoms = atoms
32 1 tkerber
33 1 tkerber
        if rank != 0:
34 1 tkerber
            logfile = None
35 1 tkerber
        elif isinstance(logfile, str):
36 1 tkerber
            if logfile == '-':
37 1 tkerber
                logfile = sys.stdout
38 1 tkerber
            else:
39 1 tkerber
                logfile = open(logfile, 'a')
40 1 tkerber
        self.logfile = logfile
41 1 tkerber
42 1 tkerber
        self.observers = []
43 1 tkerber
        self.nsteps = 0
44 1 tkerber
45 1 tkerber
        if trajectory is not None:
46 1 tkerber
            if isinstance(trajectory, str):
47 1 tkerber
                trajectory = PickleTrajectory(trajectory, 'w', atoms)
48 1 tkerber
            self.attach(trajectory)
49 1 tkerber
50 1 tkerber
    def get_number_of_steps(self):
51 1 tkerber
        return self.nsteps
52 1 tkerber
53 1 tkerber
    def insert_observer(self, function, position=0, interval=1,
54 1 tkerber
                        *args, **kwargs):
55 1 tkerber
        """Insert an observer."""
56 1 tkerber
        if not callable(function):
57 1 tkerber
            function = function.write
58 1 tkerber
        self.observers.insert(position, (function, interval, args, kwargs))
59 1 tkerber
60 1 tkerber
    def attach(self, function, interval=1, *args, **kwargs):
61 1 tkerber
        """Attach callback function.
62 1 tkerber

63 1 tkerber
        At every *interval* steps, call *function* with arguments
64 1 tkerber
        *args* and keyword arguments *kwargs*."""
65 1 tkerber
66 1 tkerber
        if not hasattr(function, '__call__'):
67 1 tkerber
            function = function.write
68 1 tkerber
        self.observers.append((function, interval, args, kwargs))
69 1 tkerber
70 1 tkerber
    def call_observers(self):
71 1 tkerber
        for function, interval, args, kwargs in self.observers:
72 1 tkerber
            if self.nsteps % interval == 0:
73 1 tkerber
                function(*args, **kwargs)
74 1 tkerber
75 1 tkerber
76 1 tkerber
class Optimizer(Dynamics):
77 1 tkerber
    """Base-class for all structure optimization classes."""
78 1 tkerber
    def __init__(self, atoms, restart, logfile, trajectory):
79 1 tkerber
        """Structure optimizer object.
80 1 tkerber

81 1 tkerber
        atoms: Atoms object
82 1 tkerber
            The Atoms object to relax.
83 1 tkerber
        restart: str
84 1 tkerber
            Filename for restart file.  Default value is *None*.
85 1 tkerber
        logfile: file object or str
86 1 tkerber
            If *logfile* is a string, a file with that name will be opened.
87 1 tkerber
            Use '-' for stdout.
88 1 tkerber
        trajectory: Trajectory object or str
89 1 tkerber
            Attach trajectory object.  If *trajectory* is a string a
90 1 tkerber
            PickleTrajectory will be constructed.  Use *None* for no
91 1 tkerber
            trajectory.
92 1 tkerber
        """
93 1 tkerber
        Dynamics.__init__(self, atoms, logfile, trajectory)
94 1 tkerber
        self.restart = restart
95 1 tkerber
96 1 tkerber
        if restart is None or not isfile(restart):
97 1 tkerber
            self.initialize()
98 1 tkerber
        else:
99 1 tkerber
            self.read()
100 1 tkerber
            barrier()
101 1 tkerber
    def initialize(self):
102 1 tkerber
        pass
103 1 tkerber
104 1 tkerber
    def run(self, fmax=0.05, steps=100000000):
105 1 tkerber
        """Run structure optimization algorithm.
106 1 tkerber

107 1 tkerber
        This method will return when the forces on all individual
108 1 tkerber
        atoms are less than *fmax* or when the number of steps exceeds
109 1 tkerber
        *steps*."""
110 1 tkerber
111 1 tkerber
        self.fmax = fmax
112 1 tkerber
        step = 0
113 1 tkerber
        while step < steps:
114 1 tkerber
            f = self.atoms.get_forces()
115 1 tkerber
            self.log(f)
116 1 tkerber
            self.call_observers()
117 1 tkerber
            if self.converged(f):
118 1 tkerber
                return
119 1 tkerber
            self.step(f)
120 1 tkerber
            self.nsteps += 1
121 1 tkerber
            step += 1
122 1 tkerber
123 1 tkerber
    def converged(self, forces=None):
124 1 tkerber
        """Did the optimization converge?"""
125 1 tkerber
        if forces is None:
126 1 tkerber
            forces = self.atoms.get_forces()
127 1 tkerber
        return (forces**2).sum(axis=1).max() < self.fmax**2
128 1 tkerber
129 1 tkerber
    def log(self, forces):
130 1 tkerber
        fmax = sqrt((forces**2).sum(axis=1).max())
131 1 tkerber
        e = self.atoms.get_potential_energy()
132 1 tkerber
        T = time.localtime()
133 1 tkerber
        if self.logfile is not None:
134 1 tkerber
            name = self.__class__.__name__
135 1 tkerber
            self.logfile.write('%s: %3d  %02d:%02d:%02d %15.6f %12.4f\n' %
136 1 tkerber
                               (name, self.nsteps, T[3], T[4], T[5], e, fmax))
137 1 tkerber
            self.logfile.flush()
138 1 tkerber
139 1 tkerber
    def dump(self, data):
140 1 tkerber
        if rank == 0 and self.restart is not None:
141 1 tkerber
            pickle.dump(data, open(self.restart, 'wb'), protocol=2)
142 1 tkerber
143 1 tkerber
    def load(self):
144 1 tkerber
        return pickle.load(open(self.restart))
145 1 tkerber
146 1 tkerber
147 1 tkerber
class NDPoly:
148 1 tkerber
    def __init__(self, ndims=1, order=3):
149 1 tkerber
        """Multivariate polynomium.
150 1 tkerber

151 1 tkerber
        ndims: int
152 1 tkerber
            Number of dimensions.
153 1 tkerber
        order: int
154 1 tkerber
            Order of polynomium."""
155 1 tkerber
156 1 tkerber
        if ndims == 0:
157 1 tkerber
            exponents = [()]
158 1 tkerber
        else:
159 1 tkerber
            exponents = []
160 1 tkerber
            for i in range(order + 1):
161 1 tkerber
                E = NDPoly(ndims - 1, order - i).exponents
162 1 tkerber
                exponents += [(i,) + tuple(e) for e in E]
163 1 tkerber
        self.exponents = np.array(exponents)
164 1 tkerber
        self.c = None
165 1 tkerber
166 1 tkerber
    def __call__(self, *x):
167 1 tkerber
        """Evaluate polynomial at x."""
168 1 tkerber
        return np.dot(self.c, (x**self.exponents).prod(1))
169 1 tkerber
170 1 tkerber
    def fit(self, x, y):
171 1 tkerber
        """Fit polynomium at points in x to values in y."""
172 1 tkerber
        A = (x**self.exponents[:, np.newaxis]).prod(2)
173 1 tkerber
        self.c = np.linalg.solve(np.inner(A, A), np.dot(A, y))
174 1 tkerber
175 1 tkerber
176 1 tkerber
def polyfit(x, y, order=3):
177 1 tkerber
    """Fit polynomium at points in x to values in y.
178 1 tkerber

179 1 tkerber
    With D dimensions and N points, x must have shape (N, D) and y
180 1 tkerber
    must have length N."""
181 1 tkerber
182 1 tkerber
    p = NDPoly(len(x[0]), order)
183 1 tkerber
    p.fit(x, y)
184 1 tkerber
    return p