Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import numpy as np 

2 

3from ase import Atoms 

4from ase.cluster.util import get_element_info 

5 

6 

7def Icosahedron(symbol, noshells, latticeconstant=None): 

8 """ 

9 Returns a cluster with the icosahedra symmetry. 

10 

11 Parameters 

12 ---------- 

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

14 

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

16 

17 latticeconstant (optional): The lattice constant. If not given, 

18 then it is extracted form ase.data. 

19 """ 

20 

21 symbol, atomic_number, latticeconstant = get_element_info( 

22 symbol, latticeconstant) 

23 

24 # Interpret noshells 

25 if noshells < 1: 

26 raise ValueError( 

27 "The number of shells must be equal to or greater than one.") 

28 

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

30 

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

32 [t, 0., -1.], 

33 [-t, 0., 1.], 

34 [-t, 0., -1.], 

35 [1., t, 0.], 

36 [-1., t, 0.], 

37 [1., -t, 0.], 

38 [-1., -t, 0.], 

39 [0., 1., t], 

40 [0., -1., t], 

41 [0., 1., -t], 

42 [0., -1., -t]]) 

43 

44 positions = [] 

45 tags = [] 

46 positions.append(np.zeros(3)) 

47 tags.append(1) 

48 

49 for n in range(1, noshells): 

50 # Construct square edges (6) 

51 for k in range(0, 12, 2): 

52 v1 = verticies[k] 

53 v2 = verticies[k + 1] 

54 for i in range(n + 1): 

55 pos = i * v1 + (n - i) * v2 

56 positions.append(pos) 

57 tags.append(n + 1) 

58 

59 # Construct triangle planes (12) 

60 if n > 1: 

61 map = {0: (8, 9), 1: (10, 11), 

62 2: (8, 9), 3: (10, 11), 

63 4: (0, 1), 5: (2, 3), 

64 6: (0, 1), 7: (2, 3), 

65 8: (4, 5), 9: (6, 7), 

66 10: (4, 5), 11: (6, 7)} 

67 

68 for k in range(0, 12): 

69 v0 = n * verticies[k] 

70 v1 = (verticies[map[k][0]] - verticies[k]) 

71 v2 = (verticies[map[k][1]] - verticies[k]) 

72 for i in range(n): 

73 for j in range(n - i): 

74 if i == 0 and j == 0: 

75 continue 

76 pos = v0 + i * v1 + j * v2 

77 positions.append(pos) 

78 tags.append(n + 1) 

79 

80 # Fill missing triangle planes (8) 

81 if n > 2: 

82 map = {0: (9, 6, 8, 4,), 

83 1: (11, 6, 10, 4), 

84 2: (9, 7, 8, 5,), 

85 3: (11, 7, 10, 5)} 

86 

87 for k in range(0, 4): 

88 v0 = n * verticies[k] 

89 v1 = (verticies[map[k][0]] - verticies[k]) 

90 v2 = (verticies[map[k][1]] - verticies[k]) 

91 v3 = (verticies[map[k][2]] - verticies[k]) 

92 v4 = (verticies[map[k][3]] - verticies[k]) 

93 for i in range(1, n): 

94 for j in range(1, n - i): 

95 pos = v0 + i * v1 + j * v2 

96 positions.append(pos) 

97 tags.append(n + 1) 

98 pos = v0 + i * v3 + j * v4 

99 positions.append(pos) 

100 tags.append(n + 1) 

101 

102 # Scale the positions 

103 scaling_factor = latticeconstant / np.sqrt(2 * (1 + t**2)) 

104 positions = np.array(positions) * scaling_factor 

105 

106 symbols = [atomic_number] * len(positions) 

107 atoms = Atoms(symbols=symbols, positions=positions, tags=tags) 

108 atoms.center(about=(0, 0, 0)) 

109 atoms.cell[:] = 0 

110 return atoms