Coverage for calorine/tools/phonons.py: 100%

22 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2025-05-07 12:55 +0000

1from typing import Any, Dict 

2 

3import numpy as np 

4from ase import Atoms 

5from ase.calculators.singlepoint import SinglePointCalculator 

6 

7try: 

8 from phonopy import Phonopy 

9 from phonopy.structure.atoms import PhonopyAtoms 

10 phonopy_exists = True 

11except ModuleNotFoundError: # pragma: no cover 

12 phonopy_exists = False 

13 Phonopy = None 

14 

15 

16def get_force_constants(structure: Atoms, 

17 calculator: SinglePointCalculator, 

18 supercell_matrix: np.ndarray, 

19 kwargs_phonopy: Dict[str, Any] = {}, 

20 kwargs_generate_displacements: Dict[str, Any] = {}) -> Phonopy: 

21 """ 

22 Calculates the force constants for a given structure using 

23 `phonopy <https://phonopy.github.io/phonopy/>`_, which needs to be cited if this function 

24 is used for generating data for publication. 

25 The function returns a `Phonopy` object that can be used to calculate, e.g., 

26 the phonon dispersion, the phonon density of states as well as related quantities such 

27 as the thermal displacements and the free energy. 

28 

29 Parameters 

30 ---------- 

31 structure 

32 structure for which to compute the phonon dispersion; usually this is a primitive cell 

33 calculator 

34 ASE calculator to use for the calculation of forces 

35 supercell_matrix 

36 specification of supercell size handed over to phonopy; 

37 should be a tuple of three values or a matrix 

38 kwargs_phonopy 

39 *Expert option*: 

40 keyword arguments used when initializing the `Phonopy` object; 

41 this includes, e.g., the tolerance used when determining the symmetry (`symprec`) and 

42 `parameters for the non-analytical corrections 

43 <https://phonopy.github.io/phonopy/phonopy-module.html#non-analytical-term-correction>`_ 

44 (`nac_params`) 

45 kwargs_generate_displacements 

46 *Expert option*: 

47 keyword arguments to be handed over to the `generate_displacements` method; 

48 this includes in particular the `distance` keyword, which specifies the 

49 magnitude of the atomic displacement imposed when calculating the force constant matrix 

50 """ 

51 if not phonopy_exists: 

52 raise ModuleNotFoundError('phonopy (https://pypi.org/project/phonopy/) is ' 

53 'required in order to use the functionality ' 

54 'in the phonons module.') # pragma: no cover 

55 

56 # prepare primitive unit cell for phonopy 

57 structure_ph = PhonopyAtoms(symbols=structure.symbols, 

58 cell=structure.cell, 

59 scaled_positions=structure.get_scaled_positions(), 

60 pbc=structure.pbc) 

61 

62 # make sure we are using the masses intended by the user 

63 structure_ph.masses = structure.get_masses() 

64 

65 # prepare supercells 

66 phonon = Phonopy(structure_ph, supercell_matrix, **kwargs_phonopy) 

67 phonon.generate_displacements(**kwargs_generate_displacements) 

68 

69 # compute force constant matrix 

70 forces = [] 

71 for structure_ph in phonon.supercells_with_displacements: 

72 structure_ase = Atoms(symbols=structure_ph.symbols, 

73 cell=structure_ph.cell, 

74 scaled_positions=structure_ph.scaled_positions, 

75 pbc=structure.pbc) 

76 structure_ase.calc = calculator 

77 forces.append(structure_ase.get_forces().copy()) 

78 

79 phonon.forces = forces 

80 phonon.produce_force_constants() 

81 

82 return phonon