Coverage for /builds/ase/ase/ase/lattice/cubic.py: 88.71%

62 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 cubic lattices (SC, FCC, BCC and Diamond). 

4 

5The following lattice creators are defined: 

6 SimpleCubic 

7 FaceCenteredCubic 

8 BodyCenteredCubic 

9 Diamond 

10""" 

11 

12import numpy as np 

13 

14from ase.data import reference_states as _refstate 

15from ase.lattice.bravais import Bravais, reduceindex 

16 

17 

18class SimpleCubicFactory(Bravais): 

19 "A factory for creating simple cubic lattices." 

20 

21 # The name of the crystal structure in ChemicalElements 

22 xtal_name = "sc" 

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 # For checking the basis volume 

37 atoms_in_unit_cell = 1 

38 

39 def get_lattice_constant(self): 

40 "Get the lattice constant of an element with cubic crystal structure." 

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

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

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

44 % (self.xtal_name, 

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

46 return _refstate[self.atomicnumber]['a'] 

47 

48 def make_crystal_basis(self): 

49 """Make the basis matrix for the crystal unit cell and the 

50 system unit cell.""" 

51 self.crystal_basis = (self.latticeconstant * self.basis_factor 

52 * self.int_basis) 

53 self.miller_basis = self.latticeconstant * np.identity(3) 

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

55 self.check_basis_volume() 

56 

57 def check_basis_volume(self): 

58 "Check the volume of the unit cell." 

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

60 cellsize = self.atoms_in_unit_cell 

61 if self.bravais_basis is not None: 

62 cellsize *= len(self.bravais_basis) 

63 vol2 = (self.calc_num_atoms() * self.latticeconstant**3 / cellsize) 

64 assert abs(vol1 - vol2) < 1e-5 

65 

66 def find_directions(self, directions, miller): 

67 "Find missing directions and miller indices from the specified ones." 

68 directions = list(directions) 

69 miller = list(miller) 

70 # Process keyword "orthogonal" 

71 self.find_ortho(directions) 

72 self.find_ortho(miller) 

73 Bravais.find_directions(self, directions, miller) 

74 

75 def find_ortho(self, idx): 

76 "Replace keyword 'ortho' or 'orthogonal' with a direction." 

77 for i in range(3): 

78 if (isinstance(idx[i], str) 

79 and (idx[i].lower() == "ortho" or 

80 idx[i].lower() == "orthogonal")): 

81 if self.debug: 

82 print("Calculating orthogonal direction", i) 

83 print(idx[i - 2], "X", idx[i - 1], end=' ') 

84 idx[i] = reduceindex(np.cross(idx[i - 2], idx[i - 1])) 

85 if self.debug: 

86 print("=", idx[i]) 

87 

88 

89SimpleCubic = SimpleCubicFactory() 

90 

91 

92class FaceCenteredCubicFactory(SimpleCubicFactory): 

93 "A factory for creating face-centered cubic lattices." 

94 

95 xtal_name = "fcc" 

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

97 [1, 0, 1], 

98 [1, 1, 0]]) 

99 basis_factor = 0.5 

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

101 [1, -1, 1], 

102 [1, 1, -1]]) 

103 inverse_basis_factor = 1.0 

104 

105 atoms_in_unit_cell = 4 

106 

107 

108FaceCenteredCubic = FaceCenteredCubicFactory() 

109 

110 

111class BodyCenteredCubicFactory(SimpleCubicFactory): 

112 "A factory for creating body-centered cubic lattices." 

113 

114 xtal_name = "bcc" 

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

116 [1, -1, 1], 

117 [1, 1, -1]]) 

118 basis_factor = 0.5 

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

120 [1, 0, 1], 

121 [1, 1, 0]]) 

122 inverse_basis_factor = 1.0 

123 

124 atoms_in_unit_cell = 2 

125 

126 

127BodyCenteredCubic = BodyCenteredCubicFactory() 

128 

129 

130class DiamondFactory(FaceCenteredCubicFactory): 

131 "A factory for creating diamond lattices." 

132 xtal_name = "diamond" 

133 bravais_basis = [[0, 0, 0], [0.25, 0.25, 0.25]] 

134 

135 

136Diamond = DiamondFactory()