root / ase / lattice / cubic.py @ 5
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() |