Coverage for /builds/ase/ase/ase/lattice/hexagonal.py: 74.14%
58 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 hexagonal lattices.
5The following lattice creators are defined:
7* Hexagonal
8* HexagonalClosedPacked
9* Graphite
10* Graphene
12Example for using Graphene to create atoms object gra::
14 from ase.lattice.hexagonal import *
15 import ase.io as io
16 from ase import Atoms, Atom
18 index1=6
19 index2=7
20 mya = 2.45
21 myc = 20.0
23 gra = Graphene(symbol = 'C',latticeconstant={'a':mya,'c':myc},
24 size=(index1,index2,1))
25 io.write('test.xyz', gra, format='xyz')
26"""
28from ase.lattice.triclinic import TriclinicFactory
31class HexagonalFactory(TriclinicFactory):
32 "A factory for creating simple hexagonal lattices."
33 # The name of the crystal structure in ChemicalElements
34 xtal_name = "hexagonal"
36 def make_crystal_basis(self):
37 """Make the basis matrix for the crystal and system unit cells."""
38 # First convert the basis specification to a triclinic one
39 if isinstance(self.latticeconstant, type({})):
40 self.latticeconstant['alpha'] = 90
41 self.latticeconstant['beta'] = 90
42 self.latticeconstant['gamma'] = 120
43 self.latticeconstant['b/a'] = 1.0
44 else:
45 if len(self.latticeconstant) == 2:
46 a, c = self.latticeconstant
47 self.latticeconstant = (a, a, c, 90, 90, 120)
48 else:
49 raise ValueError(
50 "Improper lattice constants for hexagonal crystal.")
51 TriclinicFactory.make_crystal_basis(self)
53 def find_directions(self, directions, miller):
54 """Find missing directions and miller indices from the specified ones.
56 Also handles the conversion of hexagonal-style 4-index notation to
57 the normal 3-index notation.
58 """
59 directions = list(directions)
60 miller = list(miller)
61 if miller != [None, None, None]:
62 raise NotImplementedError(
63 'Specifying Miller indices of surfaces currently '
64 'broken for hexagonal crystals.')
65 for obj in (directions, miller):
66 for i in range(3):
67 if obj[i] is not None:
68 (a, b, c, d) = obj[i]
69 if a + b + c != 0:
70 raise ValueError(
71 ("(%d,%d,%d,%d) is not a valid hexagonal Miller " +
72 "index, as the sum of the first three numbers " +
73 "should be zero.") % (a, b, c, d))
74 x = 4 * a + 2 * b
75 y = 2 * a + 4 * b
76 z = 3 * d
77 obj[i] = (x, y, z)
78 TriclinicFactory.find_directions(self, directions, miller)
80 def print_directions_and_miller(self, txt=""):
81 "Print direction vectors and Miller indices."
82 print(f"Direction vectors of unit cell{txt}:")
83 for i in (0, 1, 2):
84 self.print_four_vector("[]", self.directions[i])
85 print(f"Miller indices of surfaces{txt}:")
86 for i in (0, 1, 2):
87 self.print_four_vector("()", self.miller[i])
89 def print_four_vector(self, bracket, numbers):
90 bra, ket = bracket
91 (x, y, z) = numbers
92 a = 2 * x - y
93 b = -x + 2 * y
94 c = -x - y
95 d = 2 * z
96 print(" %s%d, %d, %d%s ~ %s%d, %d, %d, %d%s" %
97 (bra, x, y, z, ket, bra, a, b, c, d, ket))
100Hexagonal = HexagonalFactory()
103class HexagonalClosedPackedFactory(HexagonalFactory):
104 "A factory for creating HCP lattices."
105 xtal_name = "hcp"
106 bravais_basis = [[0, 0, 0], [1.0 / 3.0, 2.0 / 3.0, 0.5]]
109HexagonalClosedPacked = HexagonalClosedPackedFactory()
112class GraphiteFactory(HexagonalFactory):
113 "A factory for creating graphite lattices."
114 xtal_name = "graphite"
115 bravais_basis = [[0, 0, 0], [1.0 / 3.0, 2.0 / 3.0, 0],
116 [1.0 / 3.0, 2.0 / 3.0, 0.5], [2.0 / 3.0, 1.0 / 3.0, 0.5]]
119Graphite = GraphiteFactory()
122class GrapheneFactory(HexagonalFactory):
123 "A factory for creating graphene lattices."
124 xtal_name = "graphene"
125 bravais_basis = [[0, 0, 0], [1.0 / 3.0, 2.0 / 3.0, 0]]
128Graphene = GrapheneFactory()