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
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
1# fmt: off
3"""Function-like objects creating cubic lattices (SC, FCC, BCC and Diamond).
5The following lattice creators are defined:
6 SimpleCubic
7 FaceCenteredCubic
8 BodyCenteredCubic
9 Diamond
10"""
12import numpy as np
14from ase.data import reference_states as _refstate
15from ase.lattice.bravais import Bravais, reduceindex
18class SimpleCubicFactory(Bravais):
19 "A factory for creating simple cubic lattices."
21 # The name of the crystal structure in ChemicalElements
22 xtal_name = "sc"
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
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
36 # For checking the basis volume
37 atoms_in_unit_cell = 1
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']
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()
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
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)
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])
89SimpleCubic = SimpleCubicFactory()
92class FaceCenteredCubicFactory(SimpleCubicFactory):
93 "A factory for creating face-centered cubic lattices."
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
105 atoms_in_unit_cell = 4
108FaceCenteredCubic = FaceCenteredCubicFactory()
111class BodyCenteredCubicFactory(SimpleCubicFactory):
112 "A factory for creating body-centered cubic lattices."
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
124 atoms_in_unit_cell = 2
127BodyCenteredCubic = BodyCenteredCubicFactory()
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]]
136Diamond = DiamondFactory()