Coverage for calorine/tools/structures.py: 100%
28 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-12-10 08:26 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-12-10 08:26 +0000
1from ase import Atoms
2from ase.filters import FrechetCellFilter
3from ase.optimize import BFGS, LBFGS, FIRE, GPMin
4from ase.optimize.sciopt import SciPyFminBFGS
5from ase.units import GPa
8def relax_structure(structure: Atoms,
9 fmax: float = 0.001,
10 steps: int = 500,
11 minimizer: str = 'bfgs',
12 constant_cell: bool = False,
13 constant_volume: bool = False,
14 scalar_pressure: float = 0.0,
15 **kwargs) -> None:
16 """Relaxes the given structure.
18 Parameters
19 ----------
20 structure
21 Atomic configuration to relax.
22 fmax
23 Stop relaxation if the absolute force for all atoms falls below this value.
24 steps
25 Maximum number of relaxation steps the minimizer is allowed to take.
26 minimizer
27 Minimizer to use; possible values: 'bfgs', 'lbfgs', 'fire', 'gpmin', 'bfgs-scipy'.
28 constant_cell
29 If True do not relax the cell or the volume.
30 constant_volume
31 If True relax the cell shape but keep the volume constant.
32 kwargs
33 Keyword arguments to be handed over to the minimizer; possible arguments can be found
34 in the `ASE documentation <https://wiki.fysik.dtu.dk/ase/ase/optimize.html>`_
35 https://wiki.fysik.dtu.dk/ase/ase/filters.html#the-frechetcellfilter-class.
36 scalar_pressure
37 External pressure in GPa.
38 """
39 if structure.calc is None:
40 raise ValueError('Structure has no attached calculator object')
41 if constant_cell:
42 ucf = structure
43 else:
44 ucf = FrechetCellFilter(
45 structure, constant_volume=constant_volume, scalar_pressure=scalar_pressure * GPa)
46 kwargs['logfile'] = kwargs.get('logfile', None)
47 if minimizer == 'bfgs':
48 dyn = BFGS(ucf, **kwargs)
49 dyn.run(fmax=fmax, steps=steps)
50 elif minimizer == 'lbfgs':
51 dyn = LBFGS(ucf, **kwargs)
52 dyn.run(fmax=fmax, steps=steps)
53 elif minimizer == 'bfgs-scipy':
54 dyn = SciPyFminBFGS(ucf, **kwargs)
55 dyn.run(fmax=fmax, steps=steps)
56 elif minimizer == 'fire':
57 dyn = FIRE(ucf, **kwargs)
58 dyn.run(fmax=fmax, steps=steps)
59 elif minimizer == 'gpmin':
60 dyn = GPMin(ucf, **kwargs)
61 dyn.run(fmax=fmax, steps=steps)
62 else:
63 raise ValueError(f'Unknown minimizer: {minimizer}')