File: icosahedron.py

package info (click to toggle)
python-ase 3.21.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 13,936 kB
  • sloc: python: 122,428; xml: 946; makefile: 111; javascript: 47
file content (110 lines) | stat: -rw-r--r-- 3,653 bytes parent folder | download | duplicates (2)
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
import numpy as np

from ase import Atoms
from ase.cluster.util import get_element_info


def Icosahedron(symbol, noshells, latticeconstant=None):
    """
    Returns a cluster with the icosahedra symmetry.

    Parameters
    ----------
    symbol: The chemical symbol (or atomic number) of the element.

    noshells: The number of shells (>= 1).

    latticeconstant (optional): The lattice constant. If not given,
    then it is extracted form ase.data.
    """

    symbol, atomic_number, latticeconstant = get_element_info(
        symbol, latticeconstant)

    # Interpret noshells
    if noshells < 1:
        raise ValueError(
            "The number of shells must be equal to or greater than one.")

    t = 0.5 + np.sqrt(5) / 2.0

    verticies = np.array([[t, 0., 1.],
                          [t, 0., -1.],
                          [-t, 0., 1.],
                          [-t, 0., -1.],
                          [1., t, 0.],
                          [-1., t, 0.],
                          [1., -t, 0.],
                          [-1., -t, 0.],
                          [0., 1., t],
                          [0., -1., t],
                          [0., 1., -t],
                          [0., -1., -t]])

    positions = []
    tags = []
    positions.append(np.zeros(3))
    tags.append(1)

    for n in range(1, noshells):
        # Construct square edges (6)
        for k in range(0, 12, 2):
            v1 = verticies[k]
            v2 = verticies[k + 1]
            for i in range(n + 1):
                pos = i * v1 + (n - i) * v2
                positions.append(pos)
                tags.append(n + 1)

        # Construct triangle planes (12)
        if n > 1:
            map = {0: (8, 9), 1: (10, 11),
                   2: (8, 9), 3: (10, 11),
                   4: (0, 1), 5: (2, 3),
                   6: (0, 1), 7: (2, 3),
                   8: (4, 5), 9: (6, 7),
                   10: (4, 5), 11: (6, 7)}

            for k in range(0, 12):
                v0 = n * verticies[k]
                v1 = (verticies[map[k][0]] - verticies[k])
                v2 = (verticies[map[k][1]] - verticies[k])
                for i in range(n):
                    for j in range(n - i):
                        if i == 0 and j == 0:
                            continue
                        pos = v0 + i * v1 + j * v2
                        positions.append(pos)
                        tags.append(n + 1)

        # Fill missing triangle planes (8)
        if n > 2:
            map = {0: (9, 6, 8, 4,),
                   1: (11, 6, 10, 4),
                   2: (9, 7, 8, 5,),
                   3: (11, 7, 10, 5)}

            for k in range(0, 4):
                v0 = n * verticies[k]
                v1 = (verticies[map[k][0]] - verticies[k])
                v2 = (verticies[map[k][1]] - verticies[k])
                v3 = (verticies[map[k][2]] - verticies[k])
                v4 = (verticies[map[k][3]] - verticies[k])
                for i in range(1, n):
                    for j in range(1, n - i):
                        pos = v0 + i * v1 + j * v2
                        positions.append(pos)
                        tags.append(n + 1)
                        pos = v0 + i * v3 + j * v4
                        positions.append(pos)
                        tags.append(n + 1)

    # Scale the positions
    scaling_factor = latticeconstant / np.sqrt(2 * (1 + t**2))
    positions = np.array(positions) * scaling_factor

    symbols = [atomic_number] * len(positions)
    atoms = Atoms(symbols=symbols, positions=positions, tags=tags)
    atoms.center(about=(0, 0, 0))
    atoms.cell[:] = 0
    return atoms