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