Hide keyboard shortcuts

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

1""" 

2This module defines abstract helper classes with the objective of reducing 

3boilerplace method definitions (i.e. duplication) in calculators. 

4""" 

5 

6from abc import ABC, abstractmethod 

7from typing import Mapping, Any 

8 

9 

10class GetPropertiesMixin(ABC): 

11 """Mixin class which provides get_forces(), get_stress() and so on. 

12 

13 Inheriting class must implement get_property().""" 

14 

15 @abstractmethod 

16 def get_property(self, name, atoms=None, allow_calculation=True): 

17 """Get the named property.""" 

18 

19 def get_potential_energies(self, atoms=None): 

20 return self.get_property('energies', atoms) 

21 

22 def get_forces(self, atoms=None): 

23 return self.get_property('forces', atoms) 

24 

25 def get_stress(self, atoms=None): 

26 return self.get_property('stress', atoms) 

27 

28 def get_stresses(self, atoms=None): 

29 """the calculator should return intensive stresses, i.e., such that 

30 stresses.sum(axis=0) == stress 

31 """ 

32 return self.get_property('stresses', atoms) 

33 

34 def get_dipole_moment(self, atoms=None): 

35 return self.get_property('dipole', atoms) 

36 

37 def get_charges(self, atoms=None): 

38 return self.get_property('charges', atoms) 

39 

40 def get_magnetic_moment(self, atoms=None): 

41 return self.get_property('magmom', atoms) 

42 

43 def get_magnetic_moments(self, atoms=None): 

44 """Calculate magnetic moments projected onto atoms.""" 

45 return self.get_property('magmoms', atoms) 

46 

47 

48class GetOutputsMixin(ABC): 

49 """Mixin class for providing get_fermi_level() and others. 

50 

51 Effectively this class expresses data in calc.results as 

52 methods such as get_fermi_level(). 

53 

54 Inheriting class must implement _outputmixin_get_results(), 

55 typically returning self.results, which must be a mapping 

56 using the naming defined in ase.outputs.Properties. 

57 """ 

58 @abstractmethod 

59 def _outputmixin_get_results(self) -> Mapping[str, Any]: 

60 """Return Mapping of names to result value. 

61 

62 This may be called many times and should hence not be 

63 expensive (except possibly the first time).""" 

64 

65 def _get(self, name): 

66 # Cyclic import, should restructure. 

67 from ase.calculators.calculator import PropertyNotPresent 

68 dct = self._outputmixin_get_results() 

69 try: 

70 return dct[name] 

71 except KeyError: 

72 raise PropertyNotPresent(name) 

73 

74 def get_fermi_level(self): 

75 return self._get('fermi_level') 

76 

77 def get_ibz_k_points(self): 

78 return self._get('ibz_kpoints') 

79 

80 def get_k_point_weights(self): 

81 return self._get('kpoint_weights') 

82 

83 def get_eigenvalues(self, kpt=0, spin=0): 

84 eigs = self._get('eigenvalues') 

85 return eigs[kpt, spin] 

86 

87 def _eigshape(self): 

88 # We don't need this if we already have a Properties object. 

89 return self._get('eigenvalues').shape 

90 

91 def get_occupation_numbers(self, kpt=0, spin=0): 

92 occs = self._get('occupations') 

93 return occs[kpt, spin] 

94 

95 def get_number_of_bands(self): 

96 return self._eigshape()[2] 

97 

98 def get_number_of_spins(self): 

99 nspins = self._eigshape()[0] 

100 assert nspins in [1, 2] 

101 return nspins 

102 

103 def get_spin_polarized(self): 

104 return self.get_number_of_spins() == 2