File: orthorhombic.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 (156 lines) | stat: -rw-r--r-- 5,487 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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"""Function-like objects creating orthorhombic lattices.

The following lattice creators are defined:
    SimleOrthorhombic
    BaseCenteredOrthorhombic
    BodyCenteredOrthorhombic
    FaceCenteredOrthorhombic
"""

import numpy as np

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


class SimpleOrthorhombicFactory(Bravais):
    "A factory for creating simple orthorhombic lattices."

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

    # 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

    def get_lattice_constant(self):
        """Get the lattice constant of an element with orhtorhombic
        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].copy()

    def make_crystal_basis(self):
        """Make the basis matrix for the crystal unit cell and the system unit
        cell."""

        lattice = self.latticeconstant
        if isinstance(lattice, type({})):
            a = lattice['a']
            try:
                b = lattice['b']
            except KeyError:
                b = a * lattice['b/a']
            try:
                c = lattice['c']
            except KeyError:
                c = a * lattice['c/a']
        else:
            if len(lattice) == 3:
                (a, b, c) = lattice
            else:
                raise ValueError(
                    "Improper lattice constants for orthorhombic crystal.")

        lattice = np.array([[a, 0, 0], [0, b, 0], [0, 0, c]])
        self.latticeconstant = lattice
        self.miller_basis = lattice
        self.crystal_basis = (self.basis_factor *
                              np.dot(self.int_basis, lattice))
        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))
        vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant)
        if self.bravais_basis is not None:
            vol2 /= len(self.bravais_basis)
        if abs(vol1 - vol2) > 1e-5:
            print(f"WARNING: Got volume {vol1:f}, expected {vol2:f}")


SimpleOrthorhombic = SimpleOrthorhombicFactory()


class BaseCenteredOrthorhombicFactory(SimpleOrthorhombicFactory):
    "A factory for creating base-centered orthorhombic lattices."

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

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

    def check_basis_volume(self):
        "Check the volume of the unit cell."
        vol1 = abs(np.linalg.det(self.basis))
        vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 2.0
        if abs(vol1 - vol2) > 1e-5:
            print(f"WARNING: Got volume {vol1:f}, expected {vol2:f}")


BaseCenteredOrthorhombic = BaseCenteredOrthorhombicFactory()


class BodyCenteredOrthorhombicFactory(SimpleOrthorhombicFactory):
    "A factory for creating body-centered orthorhombic lattices."

    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

    def check_basis_volume(self):
        "Check the volume of the unit cell."
        vol1 = abs(np.linalg.det(self.basis))
        vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 2.0
        if abs(vol1 - vol2) > 1e-5:
            print(f"WARNING: Got volume {vol1:f}, expected {vol2:f}")


BodyCenteredOrthorhombic = BodyCenteredOrthorhombicFactory()


class FaceCenteredOrthorhombicFactory(SimpleOrthorhombicFactory):
    "A factory for creating face-centered orthorhombic lattices."

    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

    def check_basis_volume(self):
        "Check the volume of the unit cell."
        vol1 = abs(np.linalg.det(self.basis))
        vol2 = self.calc_num_atoms() * np.linalg.det(self.latticeconstant) / 4.0
        if abs(vol1 - vol2) > 1e-5:
            print(f"WARNING: Got volume {vol1:f}, expected {vol2:f}")


FaceCenteredOrthorhombic = FaceCenteredOrthorhombicFactory()