File: cubic.py

package info (click to toggle)
python-ase 3.24.0-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 15,448 kB
  • sloc: python: 144,945; xml: 2,728; makefile: 113; javascript: 47
file content (134 lines) | stat: -rw-r--r-- 4,459 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
"""Function-like objects creating cubic lattices (SC, FCC, BCC and Diamond).

The following lattice creators are defined:
    SimpleCubic
    FaceCenteredCubic
    BodyCenteredCubic
    Diamond
"""

import numpy as np

from ase.data import reference_states as _refstate
from ase.lattice.bravais import Bravais, reduceindex


class SimpleCubicFactory(Bravais):
    "A factory for creating simple cubic lattices."

    # The name of the crystal structure in ChemicalElements
    xtal_name = "sc"

    # The natural basis vectors of the crystal structure
    int_basis = np.array([[1, 0, 0],
                          [0, 1, 0],
                          [0, 0, 1]])
    basis_factor = 1.0

    # Converts the natural basis back to the crystallographic basis
    inverse_basis = np.array([[1, 0, 0],
                              [0, 1, 0],
                              [0, 0, 1]])
    inverse_basis_factor = 1.0

    # For checking the basis volume
    atoms_in_unit_cell = 1

    def get_lattice_constant(self):
        "Get the lattice constant of an element with cubic crystal structure."
        if _refstate[self.atomicnumber]['symmetry'] != self.xtal_name:
            raise ValueError(("Cannot guess the %s lattice constant of"
                              + " an element with crystal structure %s.")
                             % (self.xtal_name,
                                _refstate[self.atomicnumber]['symmetry']))
        return _refstate[self.atomicnumber]['a']

    def make_crystal_basis(self):
        """Make the basis matrix for the crystal unit cell and the
        system unit cell."""
        self.crystal_basis = (self.latticeconstant * self.basis_factor
                              * self.int_basis)
        self.miller_basis = self.latticeconstant * np.identity(3)
        self.basis = np.dot(self.directions, self.crystal_basis)
        self.check_basis_volume()

    def check_basis_volume(self):
        "Check the volume of the unit cell."
        vol1 = abs(np.linalg.det(self.basis))
        cellsize = self.atoms_in_unit_cell
        if self.bravais_basis is not None:
            cellsize *= len(self.bravais_basis)
        vol2 = (self.calc_num_atoms() * self.latticeconstant**3 / cellsize)
        assert abs(vol1 - vol2) < 1e-5

    def find_directions(self, directions, miller):
        "Find missing directions and miller indices from the specified ones."
        directions = list(directions)
        miller = list(miller)
        # Process keyword "orthogonal"
        self.find_ortho(directions)
        self.find_ortho(miller)
        Bravais.find_directions(self, directions, miller)

    def find_ortho(self, idx):
        "Replace keyword 'ortho' or 'orthogonal' with a direction."
        for i in range(3):
            if (isinstance(idx[i], str)
                and (idx[i].lower() == "ortho" or
                     idx[i].lower() == "orthogonal")):
                if self.debug:
                    print("Calculating orthogonal direction", i)
                    print(idx[i - 2], "X", idx[i - 1], end=' ')
                idx[i] = reduceindex(np.cross(idx[i - 2], idx[i - 1]))
                if self.debug:
                    print("=", idx[i])


SimpleCubic = SimpleCubicFactory()


class FaceCenteredCubicFactory(SimpleCubicFactory):
    "A factory for creating face-centered cubic lattices."

    xtal_name = "fcc"
    int_basis = np.array([[0, 1, 1],
                          [1, 0, 1],
                          [1, 1, 0]])
    basis_factor = 0.5
    inverse_basis = np.array([[-1, 1, 1],
                              [1, -1, 1],
                              [1, 1, -1]])
    inverse_basis_factor = 1.0

    atoms_in_unit_cell = 4


FaceCenteredCubic = FaceCenteredCubicFactory()


class BodyCenteredCubicFactory(SimpleCubicFactory):
    "A factory for creating body-centered cubic lattices."

    xtal_name = "bcc"
    int_basis = np.array([[-1, 1, 1],
                          [1, -1, 1],
                          [1, 1, -1]])
    basis_factor = 0.5
    inverse_basis = np.array([[0, 1, 1],
                              [1, 0, 1],
                              [1, 1, 0]])
    inverse_basis_factor = 1.0

    atoms_in_unit_cell = 2


BodyCenteredCubic = BodyCenteredCubicFactory()


class DiamondFactory(FaceCenteredCubicFactory):
    "A factory for creating diamond lattices."
    xtal_name = "diamond"
    bravais_basis = [[0, 0, 0], [0.25, 0.25, 0.25]]


Diamond = DiamondFactory()