Coverage for /builds/kinetik161/ase/ase/ga/relax_attaches.py: 22.22%
36 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
1""" An object which can be associated with a local relaxation in order
2to make the relaxations run more smoothly."""
3from math import sqrt
5import numpy as np
8class VariansBreak:
10 """ Helper class which can be attached to a structure optimization,
11 in order to terminale stalling calculations.
13 Parameters:
15 atoms: Atoms object being optimized
16 dyn: The relaxation object being used
17 min_stdev: The limiting std. deviation in forces to terminate at
18 N: The number of steps used to calculate the st. dev.
19 """
21 def __init__(self, atoms, dyn, min_stdev=0.005, N=15):
22 self.atoms = atoms
23 self.dyn = dyn
24 self.N = N
25 self.forces = []
26 self.min_stdev = min_stdev
28 def write(self):
29 """ The method called by the optimizer in each step. """
30 if len(self.forces) >= self.N:
31 self.forces.pop(0)
32 fmax = (self.atoms.get_forces()**2).sum(axis=1).max()**0.5
33 self.forces.append(fmax)
35 m = sum(self.forces) / float(len(self.forces))
37 stdev = sqrt(sum([(c - m)**2 for c in self.forces]) /
38 float(len(self.forces)))
40 if len(self.forces) >= self.N and stdev < self.min_stdev:
41 self.dyn.converged = lambda x: True
44class DivergenceBreak:
46 """ Helper class which can be attached to a structure optimization,
47 in order to terminate diverging calculations.
49 Parameters:
51 atoms: Atoms object being optimized
52 dyn: The relaxation object being used
53 N: The maximum number of recent steps to be included in the
54 evaluation of the slope
55 Nmin: The minimal amount of steps required before evaluating
56 the slope
57 """
59 def __init__(self, atoms, dyn, N=15, Nmin=5):
60 self.atoms = atoms
61 self.dyn = dyn
62 self.N = N
63 self.Nmin = 5
64 self.energies = []
66 def write(self):
67 """ The method called by the optimizer in each step. """
69 if len(self.energies) >= self.N:
70 self.energies.pop(0)
71 self.energies.append(self.atoms.get_potential_energy())
73 if len(self.energies) > self.Nmin:
74 x = np.array(range(len(self.energies)))
75 y = np.array(self.energies)
76 A = np.vstack([x, np.ones(len(x))]).T
77 slope, intersect = np.linalg.lstsq(A, y)[0]
79 if len(self.energies) >= self.N and slope > 0:
80 self.dyn.converged = lambda x: True