Statistiques
| Révision :

root / ase / optimize / basin.py @ 3

Historique | Voir | Annoter | Télécharger (3,84 ko)

1 1 tkerber
import numpy as np
2 1 tkerber
3 1 tkerber
from ase.optimize.optimize import Dynamics
4 1 tkerber
from ase.optimize.fire import FIRE
5 1 tkerber
from ase.units import kB
6 1 tkerber
from ase.parallel import world
7 1 tkerber
from ase.io.trajectory import PickleTrajectory
8 1 tkerber
9 1 tkerber
class BasinHopping(Dynamics):
10 1 tkerber
    """Basin hopping algorythm.
11 1 tkerber

12 1 tkerber
    After Wales and Doye, J. Phys. Chem. A, vol 101 (1997) 5111-5116"""
13 1 tkerber
14 1 tkerber
    def __init__(self, atoms,
15 1 tkerber
                 temperature=100 * kB,
16 1 tkerber
                 optimizer=FIRE,
17 1 tkerber
                 fmax=0.1,
18 1 tkerber
                 dr=.1,
19 1 tkerber
                 logfile='-',
20 1 tkerber
                 trajectory='lowest.traj',
21 1 tkerber
                 optimizer_logfile='-',
22 1 tkerber
                 local_minima_trajectory='local_minima.traj',
23 1 tkerber
                 adjust_cm=True):
24 1 tkerber
        Dynamics.__init__(self, atoms, logfile, trajectory)
25 1 tkerber
        self.kT = temperature
26 1 tkerber
        self.optimizer = optimizer
27 1 tkerber
        self.fmax = fmax
28 1 tkerber
        self.dr = dr
29 1 tkerber
        if adjust_cm:
30 1 tkerber
            self.cm = atoms.get_center_of_mass()
31 1 tkerber
        else:
32 1 tkerber
            self.cm = None
33 1 tkerber
34 1 tkerber
        self.optimizer_logfile = optimizer_logfile
35 1 tkerber
        self.lm_trajectory = local_minima_trajectory
36 1 tkerber
        if isinstance(local_minima_trajectory, str):
37 1 tkerber
            self.lm_trajectory = PickleTrajectory(local_minima_trajectory,
38 1 tkerber
                                                  'w', atoms)
39 1 tkerber
40 1 tkerber
        self.initialize()
41 1 tkerber
42 1 tkerber
    def initialize(self):
43 1 tkerber
        self.positions = 0. * self.atoms.get_positions()
44 1 tkerber
        self.Emin = self.get_energy(self.atoms.get_positions())
45 1 tkerber
        self.rmin = self.atoms.get_positions()
46 1 tkerber
        self.positions = self.atoms.get_positions()
47 1 tkerber
        self.call_observers()
48 1 tkerber
        self.log(-1, self.Emin, self.Emin)
49 1 tkerber
50 1 tkerber
    def run(self, steps):
51 1 tkerber
        """Hop the basins for defined number of steps."""
52 1 tkerber
53 1 tkerber
        ro = self.positions
54 1 tkerber
        Eo = self.get_energy(ro)
55 1 tkerber
56 1 tkerber
        for step in range(steps):
57 1 tkerber
            rn = self.move(ro)
58 1 tkerber
            En = self.get_energy(rn)
59 1 tkerber
60 1 tkerber
            if En < self.Emin:
61 1 tkerber
                # new minimum found
62 1 tkerber
                self.Emin = En
63 1 tkerber
                self.rmin = self.atoms.get_positions()
64 1 tkerber
                self.call_observers()
65 1 tkerber
                rn = self.rmin
66 1 tkerber
            self.log(step, En, self.Emin)
67 1 tkerber
68 1 tkerber
            accept = np.exp((Eo - En) / self.kT) > np.random.uniform()
69 1 tkerber
            if accept:
70 1 tkerber
                ro = rn
71 1 tkerber
                Eo = En
72 1 tkerber
73 1 tkerber
    def log(self, step, En, Emin):
74 1 tkerber
        if self.logfile is None:
75 1 tkerber
            return
76 1 tkerber
        name = self.__class__.__name__
77 1 tkerber
        self.logfile.write('%s: step %d, energy %15.6f, emin %15.6f\n'
78 1 tkerber
                           % (name, step, En, self.Emin))
79 1 tkerber
        self.logfile.flush()
80 1 tkerber
81 1 tkerber
    def move(self, ro):
82 1 tkerber
        atoms = self.atoms
83 1 tkerber
        # displace coordinates
84 1 tkerber
        disp = np.random.uniform(-1., 1., (len(atoms), 3))
85 1 tkerber
        rn = ro + self.dr * disp
86 1 tkerber
        atoms.set_positions(rn)
87 1 tkerber
        if self.cm is not None:
88 1 tkerber
            cm = atoms.get_center_of_mass()
89 1 tkerber
            atoms.translate(self.cm - cm)
90 1 tkerber
        rn = atoms.get_positions()
91 1 tkerber
        if world is not None:
92 1 tkerber
            world.broadcast(rn, 0)
93 1 tkerber
        atoms.set_positions(rn)
94 1 tkerber
        return atoms.get_positions()
95 1 tkerber
96 1 tkerber
    def get_minimum(self):
97 1 tkerber
        atoms = self.atoms.copy()
98 1 tkerber
        atoms.set_positions(self.rmin)
99 1 tkerber
        return self.Emin, atoms
100 1 tkerber
101 1 tkerber
    def get_energy(self, positions):
102 1 tkerber
        """Return the energy of the nearest local minimum."""
103 1 tkerber
        if np.sometrue(self.positions != positions):
104 1 tkerber
            self.positions = positions
105 1 tkerber
            self.atoms.set_positions(positions)
106 1 tkerber
107 1 tkerber
            try:
108 1 tkerber
                opt = self.optimizer(self.atoms, logfile=self.optimizer_logfile)
109 1 tkerber
                opt.run(fmax=self.fmax)
110 1 tkerber
                if self.lm_trajectory is not None:
111 1 tkerber
                    self.lm_trajectory.write(self.atoms)
112 1 tkerber
113 1 tkerber
                self.energy = self.atoms.get_potential_energy()
114 1 tkerber
            except:
115 1 tkerber
                # the atoms are probably to near to each other
116 1 tkerber
                self.energy = 1.e32
117 1 tkerber
118 1 tkerber
        return self.energy