Coverage for /builds/ase/ase/ase/lattice/orthorhombic.py: 45.33%

75 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2025-08-02 00:12 +0000

1# fmt: off 

2 

3"""Function-like objects creating orthorhombic lattices. 

4 

5The following lattice creators are defined: 

6 SimleOrthorhombic 

7 BaseCenteredOrthorhombic 

8 BodyCenteredOrthorhombic 

9 FaceCenteredOrthorhombic 

10""" 

11 

12import numpy as np 

13 

14from ase.data import reference_states as _refstate 

15from ase.lattice.bravais import Bravais 

16 

17 

18class SimpleOrthorhombicFactory(Bravais): 

19 "A factory for creating simple orthorhombic lattices." 

20 

21 # The name of the crystal structure in ChemicalElements 

22 xtal_name = "orthorhombic" 

23 

24 # The natural basis vectors of the crystal structure 

25 int_basis = np.array([[1, 0, 0], 

26 [0, 1, 0], 

27 [0, 0, 1]]) 

28 basis_factor = 1.0 

29 

30 # Converts the natural basis back to the crystallographic basis 

31 inverse_basis = np.array([[1, 0, 0], 

32 [0, 1, 0], 

33 [0, 0, 1]]) 

34 inverse_basis_factor = 1.0 

35 

36 def get_lattice_constant(self): 

37 """Get the lattice constant of an element with orhtorhombic 

38 crystal structure.""" 

39 if _refstate[self.atomicnumber]['symmetry'] != self.xtal_name: 

40 raise ValueError(("Cannot guess the %s lattice constant of" 

41 + " an element with crystal structure %s.") 

42 % (self.xtal_name, 

43 _refstate[self.atomicnumber]['symmetry'])) 

44 return _refstate[self.atomicnumber].copy() 

45 

46 def make_crystal_basis(self): 

47 """Make the basis matrix for the crystal unit cell and the system unit 

48 cell.""" 

49 

50 lattice = self.latticeconstant 

51 if isinstance(lattice, type({})): 

52 a = lattice['a'] 

53 try: 

54 b = lattice['b'] 

55 except KeyError: 

56 b = a * lattice['b/a'] 

57 try: 

58 c = lattice['c'] 

59 except KeyError: 

60 c = a * lattice['c/a'] 

61 else: 

62 if len(lattice) == 3: 

63 (a, b, c) = lattice 

64 else: 

65 raise ValueError( 

66 "Improper lattice constants for orthorhombic crystal.") 

67 

68 lattice = np.array([[a, 0, 0], [0, b, 0], [0, 0, c]]) 

69 self.latticeconstant = lattice 

70 self.miller_basis = lattice 

71 self.crystal_basis = (self.basis_factor * 

72 np.dot(self.int_basis, lattice)) 

73 self.basis = np.dot(self.directions, self.crystal_basis) 

74 self.check_basis_volume() 

75 

76 def check_basis_volume(self): 

77 "Check the volume of the unit cell." 

78 vol1 = abs(np.linalg.det(self.basis)) 

79 vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) 

80 if self.bravais_basis is not None: 

81 vol2 /= len(self.bravais_basis) 

82 if abs(vol1 - vol2) > 1e-5: 

83 print(f"WARNING: Got volume {vol1:f}, expected {vol2:f}") 

84 

85 

86SimpleOrthorhombic = SimpleOrthorhombicFactory() 

87 

88 

89class BaseCenteredOrthorhombicFactory(SimpleOrthorhombicFactory): 

90 "A factory for creating base-centered orthorhombic lattices." 

91 

92 # The natural basis vectors of the crystal structure 

93 int_basis = np.array([[1, -1, 0], 

94 [1, 1, 0], 

95 [0, 0, 2]]) 

96 basis_factor = 0.5 

97 

98 # Converts the natural basis back to the crystallographic basis 

99 inverse_basis = np.array([[1, 1, 0], 

100 [-1, 1, 0], 

101 [0, 0, 1]]) 

102 inverse_basis_factor = 1.0 

103 

104 def check_basis_volume(self): 

105 "Check the volume of the unit cell." 

106 vol1 = abs(np.linalg.det(self.basis)) 

107 vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 2.0 

108 if abs(vol1 - vol2) > 1e-5: 

109 print(f"WARNING: Got volume {vol1:f}, expected {vol2:f}") 

110 

111 

112BaseCenteredOrthorhombic = BaseCenteredOrthorhombicFactory() 

113 

114 

115class BodyCenteredOrthorhombicFactory(SimpleOrthorhombicFactory): 

116 "A factory for creating body-centered orthorhombic lattices." 

117 

118 int_basis = np.array([[-1, 1, 1], 

119 [1, -1, 1], 

120 [1, 1, -1]]) 

121 basis_factor = 0.5 

122 inverse_basis = np.array([[0, 1, 1], 

123 [1, 0, 1], 

124 [1, 1, 0]]) 

125 inverse_basis_factor = 1.0 

126 

127 def check_basis_volume(self): 

128 "Check the volume of the unit cell." 

129 vol1 = abs(np.linalg.det(self.basis)) 

130 vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 2.0 

131 if abs(vol1 - vol2) > 1e-5: 

132 print(f"WARNING: Got volume {vol1:f}, expected {vol2:f}") 

133 

134 

135BodyCenteredOrthorhombic = BodyCenteredOrthorhombicFactory() 

136 

137 

138class FaceCenteredOrthorhombicFactory(SimpleOrthorhombicFactory): 

139 "A factory for creating face-centered orthorhombic lattices." 

140 

141 int_basis = np.array([[0, 1, 1], 

142 [1, 0, 1], 

143 [1, 1, 0]]) 

144 basis_factor = 0.5 

145 inverse_basis = np.array([[-1, 1, 1], 

146 [1, -1, 1], 

147 [1, 1, -1]]) 

148 inverse_basis_factor = 1.0 

149 

150 def check_basis_volume(self): 

151 "Check the volume of the unit cell." 

152 vol1 = abs(np.linalg.det(self.basis)) 

153 vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 4.0 

154 if abs(vol1 - vol2) > 1e-5: 

155 print(f"WARNING: Got volume {vol1:f}, expected {vol2:f}") 

156 

157 

158FaceCenteredOrthorhombic = FaceCenteredOrthorhombicFactory()