Coverage for /builds/ase/ase/ase/lattice/triclinic.py: 95.92%
49 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 object creating triclinic lattices.
5The following lattice creator is defined:
6 Triclinic
7"""
9import numpy as np
11from ase.data import reference_states as _refstate
12from ase.lattice.bravais import Bravais
15class TriclinicFactory(Bravais):
16 "A factory for creating triclinic lattices."
18 # The name of the crystal structure in ChemicalElements
19 xtal_name = "triclinic"
21 # The natural basis vectors of the crystal structure
22 int_basis = np.array([[1, 0, 0],
23 [0, 1, 0],
24 [0, 0, 1]])
25 basis_factor = 1.0
27 # Converts the natural basis back to the crystallographic basis
28 inverse_basis = np.array([[1, 0, 0],
29 [0, 1, 0],
30 [0, 0, 1]])
31 inverse_basis_factor = 1.0
33 def get_lattice_constant(self):
34 """Get the lattice constant of an element with triclinic
35 crystal structure."""
36 if _refstate[self.atomicnumber]['symmetry'] != self.xtal_name:
37 raise ValueError(('Cannot guess the %s lattice constant of'
38 + ' an element with crystal structure %s.')
39 % (self.xtal_name,
40 _refstate[self.atomicnumber]['symmetry']))
41 return _refstate[self.atomicnumber].copy()
43 def make_crystal_basis(self):
44 """Make the basis matrix for the crystal unit cell and the system
45 unit cell."""
46 lattice = self.latticeconstant
47 if isinstance(lattice, type({})):
48 a = lattice['a']
49 try:
50 b = lattice['b']
51 except KeyError:
52 b = a * lattice['b/a']
53 try:
54 c = lattice['c']
55 except KeyError:
56 c = a * lattice['c/a']
57 alpha = lattice['alpha']
58 beta = lattice['beta']
59 gamma = lattice['gamma']
60 else:
61 if len(lattice) == 6:
62 (a, b, c, alpha, beta, gamma) = lattice
63 else:
64 raise ValueError(
65 "Improper lattice constants for triclinic crystal.")
67 degree = np.pi / 180.0
68 cosa = np.cos(alpha * degree)
69 cosb = np.cos(beta * degree)
70 sinb = np.sin(beta * degree)
71 cosg = np.cos(gamma * degree)
72 sing = np.sin(gamma * degree)
73 lattice = np.array(
74 [[a, 0, 0],
75 [b * cosg, b * sing, 0],
76 [c * cosb, c * (cosa - cosb * cosg) / sing,
77 c * np.sqrt(sinb**2 - ((cosa - cosb * cosg) / sing)**2)]])
78 self.latticeconstant = lattice
79 self.miller_basis = lattice
80 self.crystal_basis = (self.basis_factor *
81 np.dot(self.int_basis, lattice))
82 self.basis = np.dot(self.directions, self.crystal_basis)
83 assert abs(np.dot(lattice[0], lattice[1]) - a * b * cosg) < 1e-5
84 assert abs(np.dot(lattice[0], lattice[2]) - a * c * cosb) < 1e-5
85 assert abs(np.dot(lattice[1], lattice[2]) - b * c * cosa) < 1e-5
86 assert abs(np.dot(lattice[0], lattice[0]) - a * a) < 1e-5
87 assert abs(np.dot(lattice[1], lattice[1]) - b * b) < 1e-5
88 assert abs(np.dot(lattice[2], lattice[2]) - c * c) < 1e-5
91Triclinic = TriclinicFactory()