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

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 

6 

7 

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. 

17 

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}')