Coverage for /builds/kinetik161/ase/ase/cluster/icosahedron.py: 98.25%
57 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
1import numpy as np
3from ase import Atoms
4from ase.cluster.util import get_element_info
7def Icosahedron(symbol, noshells, latticeconstant=None):
8 """
9 Returns a cluster with the icosahedra symmetry.
11 Parameters
12 ----------
13 symbol : str or int
14 The chemical symbol (or atomic number) of the element.
16 noshells : int
17 The number of shells (>= 1).
19 latticeconstant : float, optional
20 The lattice constant. If not given, then it is extracted from
21 `ase.data`.
22 """
24 symbol, atomic_number, latticeconstant = get_element_info(
25 symbol, latticeconstant)
27 # Interpret noshells
28 if noshells < 1:
29 raise ValueError(
30 "The number of shells must be equal to or greater than one.")
32 t = 0.5 + np.sqrt(5) / 2.0
34 verticies = np.array([[t, 0., 1.],
35 [t, 0., -1.],
36 [-t, 0., 1.],
37 [-t, 0., -1.],
38 [1., t, 0.],
39 [-1., t, 0.],
40 [1., -t, 0.],
41 [-1., -t, 0.],
42 [0., 1., t],
43 [0., -1., t],
44 [0., 1., -t],
45 [0., -1., -t]])
47 positions = []
48 tags = []
49 positions.append(np.zeros(3))
50 tags.append(1)
52 for n in range(1, noshells):
53 # Construct square edges (6)
54 for k in range(0, 12, 2):
55 v1 = verticies[k]
56 v2 = verticies[k + 1]
57 for i in range(n + 1):
58 pos = i * v1 + (n - i) * v2
59 positions.append(pos)
60 tags.append(n + 1)
62 # Construct triangle planes (12)
63 if n > 1:
64 map = {0: (8, 9), 1: (10, 11),
65 2: (8, 9), 3: (10, 11),
66 4: (0, 1), 5: (2, 3),
67 6: (0, 1), 7: (2, 3),
68 8: (4, 5), 9: (6, 7),
69 10: (4, 5), 11: (6, 7)}
71 for k in range(0, 12):
72 v0 = n * verticies[k]
73 v1 = (verticies[map[k][0]] - verticies[k])
74 v2 = (verticies[map[k][1]] - verticies[k])
75 for i in range(n):
76 for j in range(n - i):
77 if i == 0 and j == 0:
78 continue
79 pos = v0 + i * v1 + j * v2
80 positions.append(pos)
81 tags.append(n + 1)
83 # Fill missing triangle planes (8)
84 if n > 2:
85 map = {0: (9, 6, 8, 4,),
86 1: (11, 6, 10, 4),
87 2: (9, 7, 8, 5,),
88 3: (11, 7, 10, 5)}
90 for k in range(0, 4):
91 v0 = n * verticies[k]
92 v1 = (verticies[map[k][0]] - verticies[k])
93 v2 = (verticies[map[k][1]] - verticies[k])
94 v3 = (verticies[map[k][2]] - verticies[k])
95 v4 = (verticies[map[k][3]] - verticies[k])
96 for i in range(1, n):
97 for j in range(1, n - i):
98 pos = v0 + i * v1 + j * v2
99 positions.append(pos)
100 tags.append(n + 1)
101 pos = v0 + i * v3 + j * v4
102 positions.append(pos)
103 tags.append(n + 1)
105 # Scale the positions
106 scaling_factor = latticeconstant / np.sqrt(2 * (1 + t**2))
107 positions = np.array(positions) * scaling_factor
109 symbols = [atomic_number] * len(positions)
110 atoms = Atoms(symbols=symbols, positions=positions, tags=tags)
111 atoms.center(about=(0, 0, 0))
112 atoms.cell[:] = 0
113 return atoms