Coverage for /builds/ase/ase/ase/optimize/berny.py : 95.24%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from ase.optimize.optimize import Optimizer
2from ase.units import Ha, Bohr
5class Berny(Optimizer):
6 def __init__(self, atoms, restart=None, logfile='-', trajectory=None,
7 master=None, dihedral=True):
8 """Berny optimizer.
10 This is a light ASE wrapper around the ``Berny`` optimizer from
11 Pyberny_. It is based on a redundant set of internal coordinates, and as
12 such is best suited for optimizing covalently bonded molecules. It does
13 not support periodic boundary conditions. You can find more information
14 on the Pyberny_ website.
16 This optimizer is experimental, and while it can be quite efficient when
17 it works, it can sometimes fail entirely. These issues are most likely
18 related to almost linear bonding angles. For context, see the
19 discussions `here <https://github.com/jhrmnn/pyberny/issues/23>`__ and
20 `here <https://gitlab.com/ase/ase/-/merge_requests/889>`__.
22 .. _Pyberny: https://github.com/jhrmnn/pyberny
24 Parameters:
26 atoms: Atoms object
27 The Atoms object to relax.
29 restart: string
30 Pickle file used to store internal state. If set, file with
31 such a name will be searched and internal state stored will
32 be used, if the file exists.
34 trajectory: string
35 Pickle file used to store trajectory of atomic movement.
37 logfile: file object or str
38 If *logfile* is a string, a file with that name will be opened.
39 Use '-' for stdout.
41 master: boolean
42 Defaults to None, which causes only rank 0 to save files. If
43 set to true, this rank will save files.
45 dihedral: boolean
46 Defaults to True, which means that dihedral angles will be used.
47 """
48 from berny import Berny as _Berny, Geometry
50 self._restart_data = None # Optimizer.__init__() may overwrite
51 Optimizer.__init__(self, atoms, restart, logfile, trajectory, master)
52 geom = Geometry(atoms.get_chemical_symbols(), atoms.positions)
53 self._berny = _Berny(
54 geom,
55 debug=True,
56 restart=self._restart_data,
57 maxsteps=10000000000, # TODO copied from ase.optimize.Optimizer
58 gradientmax=0.,
59 gradientrms=0.,
60 stepmax=0.,
61 steprms=0.,
62 dihedral=dihedral,
63 )
65 # Berny yields the initial geometry the first time because it is
66 # typically used as a generator, see berny.optimize()
67 next(self._berny)
69 def step(self, forces=None):
70 if forces is None:
71 forces = self.atoms.get_forces()
72 energy = self.atoms.get_potential_energy()
73 gradients = -forces
74 debug = self._berny.send((energy / Ha, gradients / Ha * Bohr))
75 self.dump(debug)
76 geom = next(self._berny)
77 self.atoms.positions[:] = geom.coords
79 def read(self):
80 self._restart_data = self.load()