r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from math import sqrt, gcd

3import numpy as np

5from ase.atoms import Atoms

8def nanotube(n, m, length=1, bond=1.42, symbol='C', verbose=False,

9 vacuum=None):

10 """Create an atomic structure.

12 Creates a single-walled nanotube whose structure is specified using the

13 standardized (n, m) notation.

15 Parameters

16 ----------

17 n : int

18 n in the (n, m) notation.

19 m : int

20 m in the (n, m) notation.

21 length : int, optional

22 Length (axial repetitions) of the nanotube.

23 bond : float, optional

24 Bond length between neighboring atoms.

25 symbol : str, optional

26 Chemical element to construct the nanotube from.

27 verbose : bool, optional

28 If True, will display key geometric parameters.

30 Returns

31 -------

32 ase.atoms.Atoms

33 An ASE Atoms object corresponding to the specified molecule.

35 Examples

36 --------

37 >>> from ase.build import nanotube

38 >>> atoms1 = nanotube(6, 0, length=4)

39 >>> atoms2 = nanotube(3, 3, length=6, bond=1.4, symbol='Si')

40 """

41 if n < m:

42 m, n = n, m

43 sign = -1

44 else:

45 sign = 1

47 nk = 6000

48 sq3 = sqrt(3.0)

49 a = sq3 * bond

50 l2 = n * n + m * m + n * m

51 l1 = sqrt(l2)

53 nd = gcd(n, m)

54 if (n - m) % (3 * nd) == 0:

55 ndr = 3 * nd

56 else:

57 ndr = nd

59 nr = (2 * m + n) // ndr

60 ns = -(2 * n + m) // ndr

61 nn = 2 * l2 // ndr

63 ichk = 0

64 if nr == 0:

65 n60 = 1

66 else:

67 n60 = nr * 4

69 absn = abs(n60)

70 nnp = []

71 nnq = []

72 for i in range(-absn, absn + 1):

73 for j in range(-absn, absn + 1):

74 j2 = nr * j - ns * i

75 if j2 == 1:

76 j1 = m * i - n * j

77 if j1 > 0 and j1 < nn:

78 ichk += 1

79 nnp.append(i)

80 nnq.append(j)

82 if ichk == 0:

84 if ichk >= 2:

85 raise RuntimeError('more than 1 pair p, q strange!!')

87 nnnp = nnp[0]

88 nnnq = nnq[0]

90 if verbose:

91 print('the symmetry vector is', nnnp, nnnq)

93 lp = nnnp * nnnp + nnnq * nnnq + nnnp * nnnq

94 r = a * sqrt(lp)

95 c = a * l1

96 t = sq3 * c / ndr

98 if 2 * nn > nk:

99 raise RuntimeError('parameter nk is too small!')

101 rs = c / (2.0 * np.pi)

103 if verbose:

106 q1 = np.arctan((sq3 * m) / (2 * n + m))

107 q2 = np.arctan((sq3 * nnnq) / (2 * nnnp + nnnq))

108 q3 = q1 - q2

110 q4 = 2.0 * np.pi / nn

111 q5 = bond * np.cos((np.pi / 6.0) - q1) / c * 2.0 * np.pi

113 h1 = abs(t) / abs(np.sin(q3))

114 h2 = bond * np.sin((np.pi / 6.0) - q1)

116 ii = 0

117 x, y, z = [], [], []

118 for i in range(nn):

119 x1, y1, z1 = 0, 0, 0

121 k = np.floor(i * abs(r) / h1)

122 x1 = rs * np.cos(i * q4)

123 y1 = rs * np.sin(i * q4)

124 z1 = (i * abs(r) - k * h1) * np.sin(q3)

125 kk2 = abs(np.floor((z1 + 0.0001) / t))

126 if z1 >= t - 0.0001:

127 z1 -= t * kk2

128 elif z1 < 0:

129 z1 += t * kk2

130 ii += 1

132 x.append(x1)

133 y.append(y1)

134 z.append(z1)

135 z3 = (i * abs(r) - k * h1) * np.sin(q3) - h2

136 ii += 1

138 if z3 >= 0 and z3 < t:

139 x2 = rs * np.cos(i * q4 + q5)

140 y2 = rs * np.sin(i * q4 + q5)

141 z2 = (i * abs(r) - k * h1) * np.sin(q3) - h2

142 x.append(x2)

143 y.append(y2)

144 z.append(z2)

145 else:

146 x2 = rs * np.cos(i * q4 + q5)

147 y2 = rs * np.sin(i * q4 + q5)

148 z2 = (i * abs(r) - (k + 1) * h1) * np.sin(q3) - h2

149 kk = abs(np.floor(z2 / t))

150 if z2 >= t - 0.0001:

151 z2 -= t * kk

152 elif z2 < 0:

153 z2 += t * kk

154 x.append(x2)

155 y.append(y2)

156 z.append(z2)

158 ntotal = 2 * nn

159 X = []

160 for i in range(ntotal):

161 X.append([x[i], y[i], sign * z[i]])

163 if length > 1:

164 xx = X[:]

165 for mnp in range(2, length + 1):

166 for i in range(len(xx)):

167 X.append(xx[i][:2] + [xx[i][2] + (mnp - 1) * t])

169 transvec = t

170 numatom = ntotal * length

171 diameter = rs * 2

172 chiralangle = np.arctan((sq3 * n) / (2 * m + n)) / np.pi * 180

174 cell = [[0, 0, 0], [0, 0, 0], [0, 0, length * t]]

175 atoms = Atoms(symbol + str(numatom),

176 positions=X,

177 cell=cell,

178 pbc=[False, False, True])

179 if vacuum:

180 atoms.center(vacuum, axis=(0, 1))

181 if verbose:

182 print('translation vector =', transvec)

183 print('diameter = ', diameter)

184 print('chiral angle = ', chiralangle)

185 return atoms