root / ase / lattice / cubic.py @ 1
Historique | Voir | Annoter | Télécharger (4,36 ko)
1 | 1 | tkerber | """Function-like objects creating cubic lattices (SC, FCC, BCC and Diamond).
|
---|---|---|---|
2 | 1 | tkerber |
|
3 | 1 | tkerber | The following lattice creators are defined:
|
4 | 1 | tkerber | SimpleCubic
|
5 | 1 | tkerber | FaceCenteredCubic
|
6 | 1 | tkerber | BodyCenteredCubic
|
7 | 1 | tkerber | Diamond
|
8 | 1 | tkerber | """
|
9 | 1 | tkerber | |
10 | 1 | tkerber | from ase.lattice.bravais import Bravais |
11 | 1 | tkerber | import numpy as np |
12 | 1 | tkerber | from ase.data import reference_states as _refstate |
13 | 1 | tkerber | |
14 | 1 | tkerber | class SimpleCubicFactory(Bravais): |
15 | 1 | tkerber | "A factory for creating simple cubic lattices."
|
16 | 1 | tkerber | |
17 | 1 | tkerber | # The name of the crystal structure in ChemicalElements
|
18 | 1 | tkerber | xtal_name = "sc"
|
19 | 1 | tkerber | |
20 | 1 | tkerber | # The natural basis vectors of the crystal structure
|
21 | 1 | tkerber | int_basis = np.array([[1, 0, 0], |
22 | 1 | tkerber | [0, 1, 0], |
23 | 1 | tkerber | [0, 0, 1]]) |
24 | 1 | tkerber | basis_factor = 1.0
|
25 | 1 | tkerber | |
26 | 1 | tkerber | # Converts the natural basis back to the crystallographic basis
|
27 | 1 | tkerber | inverse_basis = np.array([[1, 0, 0], |
28 | 1 | tkerber | [0, 1, 0], |
29 | 1 | tkerber | [0, 0, 1]]) |
30 | 1 | tkerber | inverse_basis_factor = 1.0
|
31 | 1 | tkerber | |
32 | 1 | tkerber | # For checking the basis volume
|
33 | 1 | tkerber | atoms_in_unit_cell = 1
|
34 | 1 | tkerber | |
35 | 1 | tkerber | def get_lattice_constant(self): |
36 | 1 | tkerber | "Get the lattice constant of an element with cubic crystal structure."
|
37 | 1 | tkerber | if _refstate[self.atomicnumber]['symmetry'].lower() != self.xtal_name: |
38 | 1 | tkerber | raise ValueError, (("Cannot guess the %s lattice constant of" |
39 | 1 | tkerber | + " an element with crystal structure %s.")
|
40 | 1 | tkerber | % (self.xtal_name,
|
41 | 1 | tkerber | _refstate[self.atomicnumber]['symmetry'])) |
42 | 1 | tkerber | return _refstate[self.atomicnumber]['a'] |
43 | 1 | tkerber | |
44 | 1 | tkerber | def make_crystal_basis(self): |
45 | 1 | tkerber | "Make the basis matrix for the crystal unit cell and the system unit cell."
|
46 | 1 | tkerber | self.crystal_basis = (self.latticeconstant * self.basis_factor |
47 | 1 | tkerber | * self.int_basis)
|
48 | 1 | tkerber | self.miller_basis = self.latticeconstant * np.identity(3) |
49 | 1 | tkerber | self.basis = np.dot(self.directions, self.crystal_basis) |
50 | 1 | tkerber | self.check_basis_volume()
|
51 | 1 | tkerber | |
52 | 1 | tkerber | def check_basis_volume(self): |
53 | 1 | tkerber | "Check the volume of the unit cell."
|
54 | 1 | tkerber | vol1 = abs(np.linalg.det(self.basis)) |
55 | 1 | tkerber | cellsize = self.atoms_in_unit_cell
|
56 | 1 | tkerber | if self.bravais_basis is not None: |
57 | 1 | tkerber | cellsize *= len(self.bravais_basis) |
58 | 1 | tkerber | vol2 = (self.calc_num_atoms() * self.latticeconstant**3 / cellsize) |
59 | 1 | tkerber | assert abs(vol1-vol2) < 1e-5 |
60 | 1 | tkerber | |
61 | 1 | tkerber | def find_directions(self, directions, miller): |
62 | 1 | tkerber | "Find missing directions and miller indices from the specified ones."
|
63 | 1 | tkerber | directions = list(directions)
|
64 | 1 | tkerber | miller = list(miller)
|
65 | 1 | tkerber | # Process keyword "orthogonal"
|
66 | 1 | tkerber | self.find_ortho(directions)
|
67 | 1 | tkerber | self.find_ortho(miller)
|
68 | 1 | tkerber | Bravais.find_directions(self, directions, miller)
|
69 | 1 | tkerber | |
70 | 1 | tkerber | def find_ortho(self, idx): |
71 | 1 | tkerber | "Replace keyword 'ortho' or 'orthogonal' with a direction."
|
72 | 1 | tkerber | for i in range(3): |
73 | 1 | tkerber | if isinstance(idx[i], str) and (idx[i].lower() == "ortho" or |
74 | 1 | tkerber | idx[i].lower() == "orthogonal"):
|
75 | 1 | tkerber | if self.debug: |
76 | 1 | tkerber | print "Calculating orthogonal direction", i |
77 | 1 | tkerber | print idx[i-2], "X", idx[i-1], |
78 | 1 | tkerber | idx[i] = reduceindex(cross(idx[i-2], idx[i-1])) |
79 | 1 | tkerber | if self.debug: |
80 | 1 | tkerber | print "=", idx[i] |
81 | 1 | tkerber | |
82 | 1 | tkerber | |
83 | 1 | tkerber | SimpleCubic = SimpleCubicFactory() |
84 | 1 | tkerber | |
85 | 1 | tkerber | class FaceCenteredCubicFactory(SimpleCubicFactory): |
86 | 1 | tkerber | "A factory for creating face-centered cubic lattices."
|
87 | 1 | tkerber | |
88 | 1 | tkerber | xtal_name = "fcc"
|
89 | 1 | tkerber | int_basis = np.array([[0, 1, 1], |
90 | 1 | tkerber | [1, 0, 1], |
91 | 1 | tkerber | [1, 1, 0]]) |
92 | 1 | tkerber | basis_factor = 0.5
|
93 | 1 | tkerber | inverse_basis = np.array([[-1, 1, 1], |
94 | 1 | tkerber | [1, -1, 1], |
95 | 1 | tkerber | [1, 1, -1]]) |
96 | 1 | tkerber | inverse_basis_factor = 1.0
|
97 | 1 | tkerber | |
98 | 1 | tkerber | atoms_in_unit_cell = 4
|
99 | 1 | tkerber | |
100 | 1 | tkerber | FaceCenteredCubic = FaceCenteredCubicFactory() |
101 | 1 | tkerber | |
102 | 1 | tkerber | class BodyCenteredCubicFactory(SimpleCubicFactory): |
103 | 1 | tkerber | "A factory for creating body-centered cubic lattices."
|
104 | 1 | tkerber | |
105 | 1 | tkerber | xtal_name = "bcc"
|
106 | 1 | tkerber | int_basis = np.array([[-1, 1, 1], |
107 | 1 | tkerber | [1, -1, 1], |
108 | 1 | tkerber | [1, 1, -1]]) |
109 | 1 | tkerber | basis_factor = 0.5
|
110 | 1 | tkerber | inverse_basis = np.array([[0, 1, 1], |
111 | 1 | tkerber | [1, 0, 1], |
112 | 1 | tkerber | [1, 1, 0]]) |
113 | 1 | tkerber | inverse_basis_factor = 1.0
|
114 | 1 | tkerber | |
115 | 1 | tkerber | atoms_in_unit_cell = 2
|
116 | 1 | tkerber | |
117 | 1 | tkerber | BodyCenteredCubic = BodyCenteredCubicFactory() |
118 | 1 | tkerber | |
119 | 1 | tkerber | class DiamondFactory(FaceCenteredCubicFactory): |
120 | 1 | tkerber | "A factory for creating diamond lattices."
|
121 | 1 | tkerber | xtal_name = "diamond"
|
122 | 1 | tkerber | bravais_basis = [[0,0,0], [0.25, 0.25, 0.25]] |
123 | 1 | tkerber | |
124 | 1 | tkerber | Diamond = DiamondFactory() |