Coverage for gpaw/point_groups/groups.py: 91%

798 statements  

« prev     ^ index     » next       coverage.py v7.7.1, created at 2025-07-20 00:19 +0000

1from math import pi 

2import numpy as np 

3from scipy.spatial.transform import Rotation 

4""" 

5The point groups are written as classes that inherit the class 

6Pointgroup and contain the information about 

7- the character table in irreducible form 

8- representations that correspond to translations in x, y and z 

9- whether the point group contains complex representations 

10 

11About complex point groups: 

12The classes of complex groups (such as Th) are tagged 

13as that they contain the attribute `complex`. For those groups, 

14only the real character table is given which is used as such 

15in the reduction formula. For the representations of these 

16character tables, the regular orthogonality rules between the 

17rows and columns do not apply due to the lost information about 

18the imaginary parts. 

19 

20""" 

21 

22 

23def rotation(vec): 

24 rot = Rotation.from_rotvec(vec) 

25 try: 

26 return rot.as_matrix() # new in scipy-1.4.0 

27 except AttributeError: 

28 return rot.as_dcm() # will be removed in scipy-1.6.0 

29 

30 

31class Pointgroup: 

32 def unit(self, data): 

33 return np.eye(3) 

34 

35 def rotate_mainaxis(self, angle, data=None): 

36 return rotation([0, 0, angle / 180 * pi]) 

37 

38 def rotate(self, angle, data=None, axis='z'): 

39 """ 

40 Parameters 

41 ---------- 

42 data : array_like 

43 3D data (a wave function) 

44 angle : float 

45 Rotational angle in degrees 

46 axis : string, optional 

47 The Rotational axis ('x', 'y' or 'z') 

48 """ 

49 vec = [0, 0, 0] 

50 vec['xyz'.index(axis)] = angle / 180 * pi 

51 return rotation(vec).dot(data) 

52 

53 def C2prime(self, data, angle): 

54 """180 degree rotation around the secondary axis""" 

55 newdata = self.rotate(angle=angle, data=data, axis='z') 

56 newdata2 = self.rotate(angle=180., data=newdata, axis='x') 

57 return self.rotate(angle=-angle, data=newdata2, 

58 axis='z') # rotate back 

59 

60 def S(self, angle, data): 

61 """ 

62 Rotate and mirror 

63 """ 

64 rotated = self.rotate(angle=angle, data=data, axis='z') 

65 return self.mirror_xy(rotated) 

66 

67 def invert(self, data): 

68 return self.mirror_xy(self.mirror_yz(self.mirror_xz(data))) 

69 

70 def mirror_xy(self, data): 

71 return np.array([[1, 0, 0], [0, 1, 0], [0, 0, -1.0]]).dot(data) 

72 

73 def mirror_xz(self, data): 

74 return np.array([[1, 0, 0], [0, -1.0, 0], [0, 0, 1]]).dot(data) 

75 

76 def mirror_yz(self, data): 

77 return np.array([[-1.0, 0, 0], [0, 1, 0], [0, 0, 1]]).dot(data) 

78 

79 

80class D5(Pointgroup): 

81 # main axis should be the z-axis! 

82 def __init__(self): 

83 self.operations = [('E', self.unit), 

84 ('1C5', self.rotate_mainaxis(angle=72.)), 

85 ('4C5', self.rotate_mainaxis(angle=-72.)), 

86 ('2C5', self.rotate_mainaxis(angle=2 * 72.)), 

87 ('3C5', self.rotate_mainaxis(angle=-2 * 72.)), 

88 ('C2_0', self.C2(angle=0 * 72.)), 

89 ('C2_1', self.C2(angle=1 * 72.)), 

90 ('C2_2', self.C2(angle=2 * 72.)), 

91 ('C2_3', self.C2(angle=3 * 72.)), 

92 ('C2_4', self.C2(angle=4 * 72.))] 

93 self.operation_names = [pair[0] for pair in self.operations] 

94 self.symmetries = ['A1', 'A2', 'E1', 'E2'] 

95 self.character_table = [ 

96 [1., 1., 1., 1.], [1., 1., 1., -1.], 

97 [2., 2 * np.cos(2 * np.pi / 5.), 2 * np.cos(4 * np.pi / 5.), 0.], 

98 [2., 2 * np.cos(4 * np.pi / 5.), 2 * np.cos(2 * np.pi / 5.), 0.] 

99 ] 

100 self.nof_operations = [1, 2, 2, 5] 

101 self.Tx_i = 2 # row index for representation of translation vector x 

102 self.Ty_i = 2 

103 self.Tz_i = 1 

104 

105 def __str__(self): 

106 return 'D5' 

107 

108 def C2(self, angle, data=None): 

109 angle = angle 

110 

111 def do_it(data): 

112 return self.C2prime(data, angle) 

113 

114 if data is None: 

115 return do_it 

116 return do_it(data) 

117 

118 

119class D5h(Pointgroup): 

120 # main axis should be the z-axis! 

121 def __init__(self): 

122 self.operations = [('E', self.unit), 

123 ('1C5', self.rotate_mainaxis(angle=72.)), 

124 ('4C5', self.rotate_mainaxis(angle=-72.)), 

125 ('2C5', self.rotate_mainaxis(angle=2 * 72.)), 

126 ('3C5', self.rotate_mainaxis(angle=-2 * 72.)), 

127 ('C2_0', self.C2(angle=0 * 72.)), 

128 ('C2_1', self.C2(angle=1 * 72.)), 

129 ('C2_2', self.C2(angle=2 * 72.)), 

130 ('C2_3', self.C2(angle=3 * 72.)), 

131 ('C2_4', self.C2(angle=4 * 72.)), 

132 ('sigma_h', self.sigma_h), 

133 ('S5_1', self.S5(angle=72.)), 

134 ('S5_2', self.S5(angle=-72.)), 

135 ('S53_1', self.S53(angle=72.)), 

136 ('S53_2', self.S53(angle=-72.)), 

137 ('sigma_v0', self.sigma_v(angle=0.)), 

138 ('sigma_v1', self.sigma_v(angle=72.)), 

139 ('sigma_v4', self.sigma_v(angle=-72.)), 

140 ('sigma_v2', self.sigma_v(angle=2 * 72.)), 

141 ('sigma_v3', self.sigma_v(angle=-2 * 72.))] 

142 self.operation_names = [pair[0] for pair in self.operations] 

143 self.symmetries = [ 

144 'A\'1', 'A\'2', 'E\'1', 'E\'2', 'A\'\'1', 'A\'\'2', 'E\'\'1', 

145 'E\'\'2' 

146 ] 

147 self.character_table = [ 

148 [1., 1., 1., 1., 1., 1., 1., 1.], 

149 [1., 1., 1., -1., 1., 1., 1., -1.], 

150 [2., 2 * np.cos(2 * np.pi / 5.), 

151 2 * np.cos(4 * np.pi / 5.), 0., 2., 

152 2 * np.cos(2 * np.pi / 5.), 

153 2 * np.cos(4 * np.pi / 5.), 0.], 

154 [2., 

155 2 * np.cos(4 * np.pi / 5.), 

156 2 * np.cos(2 * np.pi / 5.), 

157 0., 

158 2., 

159 2 * np.cos(4 * np.pi / 5.), 

160 2 * np.cos(2 * np.pi / 5.), 

161 0.], 

162 [1., 1., 1., 1., -1., -1., -1., -1.], 

163 [1., 1., 1., -1., -1., -1., -1., 1.], 

164 [2., 2 * np.cos(2 * np.pi / 5.), 

165 2 * np.cos(4 * np.pi / 5.), 0., -2., 

166 -2 * np.cos(2 * np.pi / 5.), 

167 -2 * np.cos(4 * np.pi / 5.), 0.], 

168 [2., 

169 2 * np.cos(4 * np.pi / 5.), 

170 2 * np.cos(2 * np.pi / 5.), 

171 0., 

172 -2., 

173 -2 * np.cos(4 * np.pi / 5.), 

174 -2 * np.cos(2 * np.pi / 5.), 

175 0.]] 

176 self.nof_operations = [1, 2, 2, 5, 1, 2, 2, 5] 

177 self.Tx_i = 2 

178 self.Ty_i = 2 

179 self.Tz_i = 5 

180 

181 def __str__(self): 

182 return 'D5h' 

183 

184 def C2(self, angle, data=None): 

185 angle = angle 

186 

187 def do_it(data): 

188 return self.C2prime(data, angle) 

189 

190 if data is None: 

191 return do_it 

192 return do_it(data) 

193 

194 def sigma_h(self, data=None): 

195 return self.mirror_xy(data) 

196 

197 def S5(self, angle, data=None): 

198 angle = angle 

199 

200 def do_it(data): 

201 return self.S(angle=angle, data=data) 

202 

203 if data is None: 

204 return do_it 

205 return do_it(data) 

206 

207 def S53(self, angle, data=None): 

208 angle = angle 

209 

210 def do_it(data): 

211 data = self.S(angle=angle, data=data) 

212 data = self.S(angle=angle, data=data) 

213 data = self.S(angle=angle, data=data) 

214 return data 

215 

216 if data is None: 

217 return do_it 

218 return do_it(data) 

219 

220 def sigma_v(self, angle, data=None): 

221 # first rotate so that the plane is xz plane, flip, and rotate back 

222 angle = angle 

223 

224 def do_it(data): 

225 first = self.rotate(data=data, angle=angle) 

226 second = self.mirror_xz(first) 

227 third = self.rotate(data=second, angle=-angle) 

228 return third 

229 

230 if data is None: 

231 return do_it 

232 return do_it(data) 

233 

234 

235class Ih(Pointgroup): 

236 # main axis should be the z-axis! 

237 def __init__(self): 

238 # some geometric math: 

239 a = 1. 

240 r_cap = np.sin(2 * np.pi / 5) * a 

241 r_side = np.sqrt(3) * (3 + np.sqrt(5)) / 12. * a 

242 r_edge = np.cos(np.pi / 5) * a 

243 r_captoside = 1 / np.sqrt(3) * a 

244 r_captoedge = 0.5 * a 

245 r_height = np.sqrt(3) / 2. * a 

246 self.angle_captocap = np.arccos(((r_cap**2 + r_cap**2) - a**2) / 

247 (2 * r_cap * r_cap)) * 180. / np.pi 

248 self.angle_captoside = np.arccos( 

249 ((r_side**2 + r_cap**2) - r_captoside**2) / 

250 (2 * r_side * r_cap)) * 180. / np.pi 

251 self.angle_captoedge = np.arccos( 

252 ((r_edge**2 + r_cap**2) - r_captoedge**2) / 

253 (2 * r_edge * r_cap)) * 180. / np.pi 

254 self.angle_captoedge2 = np.arccos( 

255 ((r_edge**2 + r_cap**2) - r_height**2) / 

256 (2 * r_edge * r_cap)) * 180. / np.pi 

257 self.angle_sidetoside = 180. - (2 * self.angle_captoside + 

258 self.angle_captocap) 

259 

260 self.operations = [ 

261 ('E', self.unit), ('01C5', self.rotate_mainaxis(angle=72.)), 

262 ('02C5', self.rotate_mainaxis(angle=-72.)), 

263 ('03C5', self.rotate_othermainaxis(numberofcap=0, angle=72.)), 

264 ('04C5', self.rotate_othermainaxis(numberofcap=0, angle=-72.)), 

265 ('05C5', self.rotate_othermainaxis(numberofcap=1, angle=72.)), 

266 ('06C5', self.rotate_othermainaxis(numberofcap=1, angle=-72.)), 

267 ('07C5', self.rotate_othermainaxis(numberofcap=2, angle=72.)), 

268 ('08C5', self.rotate_othermainaxis(numberofcap=2, angle=-72.)), 

269 ('09C5', self.rotate_othermainaxis(numberofcap=3, angle=72.)), 

270 ('10C5', self.rotate_othermainaxis(numberofcap=3, angle=-72.)), 

271 ('11C5', self.rotate_othermainaxis(numberofcap=4, angle=72.)), 

272 ('12C5', self.rotate_othermainaxis(numberofcap=4, angle=-72.)), 

273 ('01C52', self.rotate_mainaxis(angle=2 * 72.)), 

274 ('02C52', self.rotate_mainaxis(angle=-2 * 72.)), 

275 ('03C52', self.rotate_othermainaxis(numberofcap=0, angle=2 * 72.)), 

276 ('04C52', self.rotate_othermainaxis(numberofcap=0, 

277 angle=-2 * 72.)), 

278 ('05C52', self.rotate_othermainaxis(numberofcap=1, angle=2 * 72.)), 

279 ('06C52', self.rotate_othermainaxis(numberofcap=1, 

280 angle=-2 * 72.)), 

281 ('07C52', self.rotate_othermainaxis(numberofcap=2, angle=2 * 72.)), 

282 ('08C52', self.rotate_othermainaxis(numberofcap=2, 

283 angle=-2 * 72.)), 

284 ('09C52', self.rotate_othermainaxis(numberofcap=3, angle=2 * 72.)), 

285 ('10C52', self.rotate_othermainaxis(numberofcap=3, 

286 angle=-2 * 72.)), 

287 ('11C52', self.rotate_othermainaxis(numberofcap=4, angle=2 * 72.)), 

288 ('12C52', self.rotate_othermainaxis(numberofcap=4, 

289 angle=-2 * 72.)), 

290 ('01C3', self.rotate_C3(numberofside=0, angle=120.)), 

291 ('02C3', self.rotate_C3(numberofside=0, angle=-120.)), 

292 ('03C3', self.rotate_C3(numberofside=1, angle=120.)), 

293 ('04C3', self.rotate_C3(numberofside=1, angle=-120.)), 

294 ('05C3', self.rotate_C3(numberofside=2, angle=120.)), 

295 ('06C3', self.rotate_C3(numberofside=2, angle=-120.)), 

296 ('07C3', self.rotate_C3(numberofside=3, angle=120.)), 

297 ('08C3', self.rotate_C3(numberofside=3, angle=-120.)), 

298 ('09C3', self.rotate_C3(numberofside=4, angle=120.)), 

299 ('10C3', self.rotate_C3(numberofside=4, angle=-120.)), 

300 ('11C3', self.rotate_C3(numberofside=5, angle=120.)), 

301 ('12C3', self.rotate_C3(numberofside=5, angle=-120.)), 

302 ('13C3', self.rotate_C3(numberofside=6, angle=120.)), 

303 ('14C3', self.rotate_C3(numberofside=6, angle=-120.)), 

304 ('15C3', self.rotate_C3(numberofside=7, angle=120.)), 

305 ('16C3', self.rotate_C3(numberofside=7, angle=-120.)), 

306 ('17C3', self.rotate_C3(numberofside=8, angle=120.)), 

307 ('18C3', self.rotate_C3(numberofside=8, angle=-120.)), 

308 ('19C3', self.rotate_C3(numberofside=9, angle=120.)), 

309 ('20C3', self.rotate_C3(numberofside=9, angle=-120.)), 

310 ('01C2', self.C2(numberofedge=0)), ('02C2', 

311 self.C2(numberofedge=1)), 

312 ('03C2', self.C2(numberofedge=2)), ('04C2', 

313 self.C2(numberofedge=3)), 

314 ('05C2', self.C2(numberofedge=4)), ('06C2', 

315 self.C2(numberofedge=5)), 

316 ('07C2', self.C2(numberofedge=6)), ('08C2', 

317 self.C2(numberofedge=7)), 

318 ('09C2', self.C2(numberofedge=8)), 

319 ('10C2', self.C2(numberofedge=9)), 

320 ('11C2', self.C2(numberofedge=10)), 

321 ('12C2', self.C2(numberofedge=11)), 

322 ('13C2', self.C2(numberofedge=12)), 

323 ('14C2', self.C2(numberofedge=13)), 

324 ('15C2', self.C2(numberofedge=14)), ('i', self.inversion), 

325 ('01S10', self.S10(angle=36.)), ('02S10', self.S10(angle=-36.)), 

326 ('03S10', self.S10_othercap(numberofcap=0, angle=36.)), 

327 ('04S10', self.S10_othercap(numberofcap=0, angle=-36.)), 

328 ('05S10', self.S10_othercap(numberofcap=1, angle=36.)), 

329 ('06S10', self.S10_othercap(numberofcap=1, angle=-36.)), 

330 ('07S10', self.S10_othercap(numberofcap=2, angle=36.)), 

331 ('08S10', self.S10_othercap(numberofcap=2, angle=-36.)), 

332 ('09S10', self.S10_othercap(numberofcap=3, angle=36.)), 

333 ('10S10', self.S10_othercap(numberofcap=3, angle=-36.)), 

334 ('11S10', self.S10_othercap(numberofcap=4, angle=36.)), 

335 ('12S10', self.S10_othercap(numberofcap=4, angle=-36.)), 

336 ('01S10_3', self.S10_3(angle=36.)), 

337 ('02S10_3', self.S10_3(angle=-36.)), 

338 ('03S10_3', self.S10_3_othercap(numberofcap=0, angle=36.)), 

339 ('04S10_3', self.S10_3_othercap(numberofcap=0, angle=-36.)), 

340 ('05S10_3', self.S10_3_othercap(numberofcap=1, angle=36.)), 

341 ('06S10_3', self.S10_3_othercap(numberofcap=1, angle=-36.)), 

342 ('07S10_3', self.S10_3_othercap(numberofcap=2, angle=36.)), 

343 ('08S10_3', self.S10_3_othercap(numberofcap=2, angle=-36.)), 

344 ('09S10_3', self.S10_3_othercap(numberofcap=3, angle=36.)), 

345 ('10S10_3', self.S10_3_othercap(numberofcap=3, angle=-36.)), 

346 ('11S10_3', self.S10_3_othercap(numberofcap=4, angle=36.)), 

347 ('12S10_3', self.S10_3_othercap(numberofcap=4, angle=-36.)), 

348 ('01S6', self.S6(numberofside=0, angle=60.)), 

349 ('02S6', self.S6(numberofside=0, angle=-60.)), 

350 ('03S6', self.S6(numberofside=1, angle=60.)), 

351 ('04S6', self.S6(numberofside=1, angle=-60.)), 

352 ('05S6', self.S6(numberofside=2, angle=60.)), 

353 ('06S6', self.S6(numberofside=2, angle=-60.)), 

354 ('07S6', self.S6(numberofside=3, angle=60.)), 

355 ('08S6', self.S6(numberofside=3, angle=-60.)), 

356 ('09S6', self.S6(numberofside=4, angle=60.)), 

357 ('10S6', self.S6(numberofside=4, angle=-60.)), 

358 ('11S6', self.S6(numberofside=5, angle=60.)), 

359 ('12S6', self.S6(numberofside=5, angle=-60.)), 

360 ('13S6', self.S6(numberofside=6, angle=60.)), 

361 ('14S6', self.S6(numberofside=6, angle=-60.)), 

362 ('15S6', self.S6(numberofside=7, angle=60.)), 

363 ('16S6', self.S6(numberofside=7, angle=-60.)), 

364 ('17S6', self.S6(numberofside=8, angle=60.)), 

365 ('18S6', self.S6(numberofside=8, angle=-60.)), 

366 ('19S6', self.S6(numberofside=9, angle=60.)), 

367 ('20S6', self.S6(numberofside=9, angle=-60.)), 

368 ('01sigma', self.sigma(numberofedge=0)), 

369 ('02sigma', self.sigma(numberofedge=1)), 

370 ('03sigma', self.sigma(numberofedge=2)), 

371 ('04sigma', self.sigma(numberofedge=3)), 

372 ('05sigma', self.sigma(numberofedge=4)), 

373 ('06sigma', self.sigma(numberofedge=5)), 

374 ('07sigma', self.sigma(numberofedge=6)), 

375 ('08sigma', self.sigma(numberofedge=7)), 

376 ('09sigma', self.sigma(numberofedge=8)), 

377 ('10sigma', self.sigma(numberofedge=9)), 

378 ('11sigma', self.sigma(numberofedge=10)), 

379 ('12sigma', self.sigma(numberofedge=11)), 

380 ('13sigma', self.sigma(numberofedge=12)), 

381 ('14sigma', self.sigma(numberofedge=13)), 

382 ('15sigma', self.sigma(numberofedge=14)) 

383 ] 

384 self.operation_names = [pair[0] for pair in self.operations] 

385 self.symmetries = [ 

386 'Ag', 'T1g', 'T2g', 'Gg', 'Hg', 'Au', 'T1u', 'T2u', 'Gu', 'Hu' 

387 ] 

388 self.character_table = [ 

389 [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 

390 [ 

391 3., -2 * np.cos(4 * np.pi / 5.), -2 * np.cos(2 * np.pi / 5.), 

392 0., -1., 3., -2 * np.cos(2 * np.pi / 5.), 

393 -2 * np.cos(4 * np.pi / 5.), 0., -1. 

394 ], 

395 [ 

396 3., -2 * np.cos(2 * np.pi / 5.), -2 * np.cos(4 * np.pi / 5.), 

397 0., -1., 3., -2 * np.cos(4 * np.pi / 5.), 

398 -2 * np.cos(2 * np.pi / 5.), 0., -1. 

399 ], [4., -1., -1., 1., 0., 4., -1., -1., 1., 0.], 

400 [5., 0., 0., -1., 1., 5., 0., 0., -1., 1.], 

401 [1., 1., 1., 1., 1., -1., -1., -1., -1., -1.], 

402 [ 

403 3., -2 * np.cos(4 * np.pi / 5.), -2 * np.cos(2 * np.pi / 5.), 

404 0., -1., -3., 2 * np.cos(2 * np.pi / 5.), 

405 2 * np.cos(4 * np.pi / 5.), 0., 1. 

406 ], 

407 [ 

408 3., -2 * np.cos(2 * np.pi / 5.), -2 * np.cos(4 * np.pi / 5.), 

409 0., -1., -3., 2 * np.cos(4 * np.pi / 5.), 

410 2 * np.cos(2 * np.pi / 5.), 0., 1. 

411 ], [4., -1., -1., 1., 0., -4., 1., 1., -1., 0.], 

412 [5., 0., 0., -1., 1., -5., 0., 0., 1., -1.] 

413 ] 

414 self.nof_operations = [1, 12, 12, 20, 15, 1, 12, 12, 20, 15] 

415 self.Tx_i = 6 

416 self.Ty_i = 6 

417 self.Tz_i = 6 

418 

419 def __str__(self): 

420 return 'Ih' 

421 

422 def rotate_othermainaxis(self, numberofcap, angle, data=None): 

423 angle = angle 

424 numberofcap = numberofcap 

425 

426 def do_it(data): 

427 # first, bring another cap to z-axis: 

428 data = self.rotate(angle=numberofcap * 72., data=data, axis='z') 

429 data = self.rotate(angle=self.angle_captocap, data=data, axis='y') 

430 

431 # do the actual rotation: 

432 data = self.rotate(angle=angle, data=data, axis='z') 

433 

434 # rotate back: 

435 data = self.rotate(angle=-self.angle_captocap, data=data, axis='y') 

436 data = self.rotate(angle=-numberofcap * 72., data=data, axis='z') 

437 return data 

438 

439 if data is None: 

440 return do_it 

441 return do_it(data) 

442 

443 def rotate_C3(self, numberofside, angle, data=None): 

444 angle = angle 

445 numberofside = numberofside 

446 n_is_even = (numberofside % 2 == 0) 

447 # first, bring a face center to z-axis: 

448 angle1 = int((numberofside + 1e-4) / 2.) * 72. 

449 if n_is_even: 

450 angle2 = -(self.angle_captoside + self.angle_sidetoside) 

451 else: 

452 angle2 = -self.angle_captoside 

453 

454 def do_it(data): 

455 data = self.rotate(angle=angle1, data=data, axis='z') 

456 data = self.rotate(angle=angle2, data=data, axis='y') 

457 

458 # do the actual rotation: 

459 data = self.rotate(angle=angle, data=data, axis='z') 

460 

461 # rotate back: 

462 data = self.rotate(angle=-angle2, data=data, axis='y') 

463 data = self.rotate(angle=-angle1, data=data, axis='z') 

464 return data 

465 

466 if data is None: 

467 return do_it 

468 return do_it(data) 

469 

470 def C2(self, numberofedge, angle=180., data=None): 

471 angle = angle 

472 numberofedge = numberofedge 

473 n_is_g1 = (numberofedge % 3 == 0) 

474 n_is_g2 = (numberofedge % 3 == 1) 

475 # first, bring an edge center to z-axis: 

476 angle1 = int((numberofedge + 1e-4) / 3.) * 72. + 36. 

477 if n_is_g1: 

478 angle2 = 0. 

479 angle3 = -self.angle_captoedge 

480 elif n_is_g2: 

481 angle2 = 36. 

482 angle3 = -self.angle_captoedge2 

483 else: 

484 angle2 = 18. 

485 angle3 = -90. 

486 

487 def do_it(data): 

488 data = self.rotate(angle=angle1 + angle2, data=data, axis='z') 

489 data = self.rotate(angle=angle3, data=data, axis='y') 

490 

491 # do the actual rotation: 

492 data = self.rotate(angle=angle, data=data, axis='z') 

493 

494 # rotate back: 

495 data = self.rotate(angle=-angle3, data=data, axis='y') 

496 data = self.rotate(angle=-(angle1 + angle2), data=data, axis='z') 

497 return data 

498 

499 if data is None: 

500 return do_it 

501 return do_it(data) 

502 

503 def inversion(self, data=None): 

504 return self.invert(data) 

505 

506 def S10(self, angle, data=None): 

507 angle = angle 

508 

509 def do_it(data): 

510 return self.S(data=data, angle=angle) 

511 

512 if data is None: 

513 return do_it 

514 return do_it(data) 

515 

516 def S10_othercap(self, numberofcap, angle, data=None): 

517 angle = angle 

518 numberofcap = numberofcap 

519 

520 def do_it(data): 

521 # first, bring another cap to z-axis: 

522 data = self.rotate(angle=numberofcap * 72., data=data, axis='z') 

523 data = self.rotate(angle=self.angle_captocap, data=data, axis='y') 

524 

525 # do the actual S-operation: 

526 data = self.S(angle=angle, data=data) 

527 

528 # rotate back: 

529 data = self.rotate(angle=-self.angle_captocap, data=data, axis='y') 

530 data = self.rotate(angle=-numberofcap * 72., data=data, axis='z') 

531 return data 

532 

533 if data is None: 

534 return do_it 

535 return do_it(data) 

536 

537 def S10_3(self, angle, data=None): 

538 angle = angle 

539 

540 def do_it(data): 

541 first = self.S(data=data, angle=angle) 

542 second = self.S(data=first, angle=angle) 

543 third = self.S(data=second, angle=angle) 

544 return third 

545 

546 if data is None: 

547 return do_it 

548 return do_it(data) 

549 

550 def S10_3_othercap(self, numberofcap, angle, data=None): 

551 angle = angle 

552 numberofcap = numberofcap 

553 

554 def do_it(data): 

555 # first, bring another cap to z-axis: 

556 data = self.rotate(angle=numberofcap * 72., data=data, axis='z') 

557 data = self.rotate(angle=self.angle_captocap, data=data, axis='y') 

558 

559 # do the actual S-operation: 

560 data = self.S(data=data, angle=angle) 

561 data = self.S(data=data, angle=angle) 

562 data = self.S(data=data, angle=angle) 

563 

564 # rotate back: 

565 data = self.rotate(angle=-self.angle_captocap, data=data, axis='y') 

566 data = self.rotate(angle=-numberofcap * 72., data=data, axis='z') 

567 return data 

568 

569 if data is None: 

570 return do_it 

571 return do_it(data) 

572 

573 def S6(self, numberofside, angle, data=None): 

574 angle = angle 

575 numberofside = numberofside 

576 n_is_even = (numberofside % 2 == 0) 

577 # first, bring a face center to z-axis: 

578 angle1 = int((numberofside + 1e-4) / 2.) * 72. 

579 if n_is_even: 

580 angle2 = (self.angle_captoside + self.angle_sidetoside) 

581 else: 

582 angle2 = self.angle_captoside 

583 

584 def do_it(data): 

585 data = self.rotate(angle=angle1, data=data, axis='z') 

586 data = self.rotate(angle=-angle2, data=data, axis='y') 

587 

588 # do the actual rotation: 

589 data = self.S(angle=angle, data=data) 

590 

591 # rotate back: 

592 data = self.rotate(angle=angle2, data=data, axis='y') 

593 data = self.rotate(angle=-angle1, data=data, axis='z') 

594 return data 

595 

596 if data is None: 

597 return do_it 

598 return do_it(data) 

599 

600 def sigma(self, numberofedge, data=None): 

601 numberofedge = numberofedge 

602 n_is_g1 = (numberofedge % 3 == 0) 

603 n_is_g2 = (numberofedge % 3 == 1) 

604 # first, bring an edge center to z-axis: 

605 angle1 = int((numberofedge + 1e-4) / 3.) * 72. + 36. 

606 if n_is_g1: 

607 angle2 = 0. 

608 angle3 = self.angle_captoedge 

609 angle4 = 0. 

610 elif n_is_g2: 

611 angle2 = 36. 

612 angle3 = self.angle_captoedge2 

613 angle4 = 90. 

614 else: 

615 angle2 = 18. 

616 angle3 = 90. 

617 angle4 = self.angle_captoedge 

618 

619 def do_it(data): 

620 data = self.rotate(angle=angle1 + angle2, data=data, axis='z') 

621 data = self.rotate(angle=-angle3, data=data, axis='y') 

622 data = self.rotate(angle=angle4, data=data, axis='z') 

623 

624 # do the actual rotation: 

625 data = self.mirror_xz(data) 

626 

627 # rotate back: 

628 data = self.rotate(angle=-angle4, data=data, axis='z') 

629 data = self.rotate(angle=angle3, data=data, axis='y') 

630 data = self.rotate(angle=-(angle1 + angle2), data=data, axis='z') 

631 return data 

632 

633 if data is None: 

634 return do_it 

635 return do_it(data) 

636 

637 

638class Ico(Pointgroup): 

639 # main axis should be the z-axis! 

640 def __init__(self): 

641 # some geometric math: 

642 a = 1. 

643 r_cap = np.sin(2 * np.pi / 5) * a 

644 r_side = np.sqrt(3) * (3 + np.sqrt(5)) / 12. * a 

645 r_edge = np.cos(np.pi / 5) * a 

646 r_captoside = 1 / np.sqrt(3) * a 

647 r_captoedge = 0.5 * a 

648 r_height = np.sqrt(3) / 2. * a 

649 self.angle_captocap = np.arccos(((r_cap**2 + r_cap**2) - a**2) / 

650 (2 * r_cap * r_cap)) * 180. / np.pi 

651 self.angle_captoside = np.arccos( 

652 ((r_side**2 + r_cap**2) - r_captoside**2) / 

653 (2 * r_side * r_cap)) * 180. / np.pi 

654 self.angle_captoedge = np.arccos( 

655 ((r_edge**2 + r_cap**2) - r_captoedge**2) / 

656 (2 * r_edge * r_cap)) * 180. / np.pi 

657 self.angle_captoedge2 = np.arccos( 

658 ((r_edge**2 + r_cap**2) - r_height**2) / 

659 (2 * r_edge * r_cap)) * 180. / np.pi 

660 self.angle_sidetoside = 180. - (2 * self.angle_captoside + 

661 self.angle_captocap) 

662 

663 self.operations = [ 

664 ('E', self.unit), ('01C5', self.rotate_mainaxis(angle=72.)), 

665 ('02C5', self.rotate_mainaxis(angle=-72.)), 

666 ('03C5', self.rotate_othermainaxis(numberofcap=0, angle=72.)), 

667 ('04C5', self.rotate_othermainaxis(numberofcap=0, angle=-72.)), 

668 ('05C5', self.rotate_othermainaxis(numberofcap=1, angle=72.)), 

669 ('06C5', self.rotate_othermainaxis(numberofcap=1, angle=-72.)), 

670 ('07C5', self.rotate_othermainaxis(numberofcap=2, angle=72.)), 

671 ('08C5', self.rotate_othermainaxis(numberofcap=2, angle=-72.)), 

672 ('09C5', self.rotate_othermainaxis(numberofcap=3, angle=72.)), 

673 ('10C5', self.rotate_othermainaxis(numberofcap=3, angle=-72.)), 

674 ('11C5', self.rotate_othermainaxis(numberofcap=4, angle=72.)), 

675 ('12C5', self.rotate_othermainaxis(numberofcap=4, angle=-72.)), 

676 ('01C52', self.rotate_mainaxis(angle=2 * 72.)), 

677 ('02C52', self.rotate_mainaxis(angle=-2 * 72.)), 

678 ('03C52', self.rotate_othermainaxis(numberofcap=0, angle=2 * 72.)), 

679 ('04C52', self.rotate_othermainaxis(numberofcap=0, 

680 angle=-2 * 72.)), 

681 ('05C52', self.rotate_othermainaxis(numberofcap=1, angle=2 * 72.)), 

682 ('06C52', self.rotate_othermainaxis(numberofcap=1, 

683 angle=-2 * 72.)), 

684 ('07C52', self.rotate_othermainaxis(numberofcap=2, angle=2 * 72.)), 

685 ('08C52', self.rotate_othermainaxis(numberofcap=2, 

686 angle=-2 * 72.)), 

687 ('09C52', self.rotate_othermainaxis(numberofcap=3, angle=2 * 72.)), 

688 ('10C52', self.rotate_othermainaxis(numberofcap=3, 

689 angle=-2 * 72.)), 

690 ('11C52', self.rotate_othermainaxis(numberofcap=4, angle=2 * 72.)), 

691 ('12C52', self.rotate_othermainaxis(numberofcap=4, 

692 angle=-2 * 72.)), 

693 ('01C3', self.rotate_C3(numberofside=0, angle=120.)), 

694 ('02C3', self.rotate_C3(numberofside=0, angle=-120.)), 

695 ('03C3', self.rotate_C3(numberofside=1, angle=120.)), 

696 ('04C3', self.rotate_C3(numberofside=1, angle=-120.)), 

697 ('05C3', self.rotate_C3(numberofside=2, angle=120.)), 

698 ('06C3', self.rotate_C3(numberofside=2, angle=-120.)), 

699 ('07C3', self.rotate_C3(numberofside=3, angle=120.)), 

700 ('08C3', self.rotate_C3(numberofside=3, angle=-120.)), 

701 ('09C3', self.rotate_C3(numberofside=4, angle=120.)), 

702 ('10C3', self.rotate_C3(numberofside=4, angle=-120.)), 

703 ('11C3', self.rotate_C3(numberofside=5, angle=120.)), 

704 ('12C3', self.rotate_C3(numberofside=5, angle=-120.)), 

705 ('13C3', self.rotate_C3(numberofside=6, angle=120.)), 

706 ('14C3', self.rotate_C3(numberofside=6, angle=-120.)), 

707 ('15C3', self.rotate_C3(numberofside=7, angle=120.)), 

708 ('16C3', self.rotate_C3(numberofside=7, angle=-120.)), 

709 ('17C3', self.rotate_C3(numberofside=8, angle=120.)), 

710 ('18C3', self.rotate_C3(numberofside=8, angle=-120.)), 

711 ('19C3', self.rotate_C3(numberofside=9, angle=120.)), 

712 ('20C3', self.rotate_C3(numberofside=9, angle=-120.)), 

713 ('01C2', self.C2(numberofedge=0)), ('02C2', 

714 self.C2(numberofedge=1)), 

715 ('03C2', self.C2(numberofedge=2)), ('04C2', 

716 self.C2(numberofedge=3)), 

717 ('05C2', self.C2(numberofedge=4)), ('06C2', 

718 self.C2(numberofedge=5)), 

719 ('07C2', self.C2(numberofedge=6)), ('08C2', 

720 self.C2(numberofedge=7)), 

721 ('09C2', self.C2(numberofedge=8)), 

722 ('10C2', self.C2(numberofedge=9)), 

723 ('11C2', self.C2(numberofedge=10)), 

724 ('12C2', self.C2(numberofedge=11)), 

725 ('13C2', self.C2(numberofedge=12)), 

726 ('14C2', self.C2(numberofedge=13)), 

727 ('15C2', self.C2(numberofedge=14)) 

728 ] 

729 self.operation_names = [pair[0] for pair in self.operations] 

730 self.symmetries = ['A', 'T1', 'T2', 'G', 'H'] 

731 self.character_table = [ 

732 [1., 1., 1., 1., 1.], 

733 [3., -2 * np.cos(4 * np.pi / 5.), 

734 -2 * np.cos(2 * np.pi / 5.), 0., -1.], 

735 [3., -2 * np.cos(2 * np.pi / 5.), 

736 -2 * np.cos(4 * np.pi / 5.), 0., -1.], 

737 [4., -1., -1., 1., 0.], 

738 [5., 0., 0., -1., 1.]] 

739 self.nof_operations = [1, 12, 12, 20, 15] 

740 self.Tx_i = 1 

741 self.Ty_i = 1 

742 self.Tz_i = 1 

743 

744 def __str__(self): 

745 return 'Ico' 

746 

747 def rotate_othermainaxis(self, numberofcap, angle, data=None): 

748 angle = angle 

749 numberofcap = numberofcap 

750 

751 def do_it(data): 

752 # first, bring another cap to z-axis: 

753 data = self.rotate(angle=numberofcap * 72., data=data, axis='z') 

754 data = self.rotate(angle=self.angle_captocap, data=data, axis='y') 

755 

756 # do the actual rotation: 

757 data = self.rotate(angle=angle, data=data, axis='z') 

758 

759 # rotate back: 

760 data = self.rotate(angle=-self.angle_captocap, data=data, axis='y') 

761 data = self.rotate(angle=-numberofcap * 72., data=data, axis='z') 

762 return data 

763 

764 if data is None: 

765 return do_it 

766 return do_it(data) 

767 

768 def rotate_C3(self, numberofside, angle, data=None): 

769 angle = angle 

770 numberofside = numberofside 

771 n_is_even = (numberofside % 2 == 0) 

772 # first, bring a face center to z-axis: 

773 angle1 = int((numberofside + 1e-4) / 2.) * 72. 

774 if n_is_even: 

775 angle2 = -(self.angle_captoside + self.angle_sidetoside) 

776 else: 

777 angle2 = -self.angle_captoside 

778 

779 def do_it(data): 

780 data = self.rotate(angle=angle1, data=data, axis='z') 

781 data = self.rotate(angle=angle2, data=data, axis='y') 

782 

783 # do the actual rotation: 

784 data = self.rotate(angle=angle, data=data, axis='z') 

785 

786 # rotate back: 

787 data = self.rotate(angle=-angle2, data=data, axis='y') 

788 data = self.rotate(angle=-angle1, data=data, axis='z') 

789 return data 

790 

791 if data is None: 

792 return do_it 

793 return do_it(data) 

794 

795 def C2(self, numberofedge, angle=180., data=None): 

796 angle = angle 

797 numberofedge = numberofedge 

798 n_is_g1 = (numberofedge % 3 == 0) 

799 n_is_g2 = (numberofedge % 3 == 1) 

800 # first, bring an edge center to z-axis: 

801 angle1 = int((numberofedge + 1e-4) / 3.) * 72. + 36. 

802 if n_is_g1: 

803 angle2 = 0. 

804 angle3 = -self.angle_captoedge 

805 elif n_is_g2: 

806 angle2 = 36. 

807 angle3 = -self.angle_captoedge2 

808 else: 

809 angle2 = 18. 

810 angle3 = -90. 

811 

812 def do_it(data): 

813 data = self.rotate(angle=angle1 + angle2, data=data, axis='z') 

814 data = self.rotate(angle=angle3, data=data, axis='y') 

815 

816 # do the actual rotation: 

817 data = self.rotate(angle=angle, data=data, axis='z') 

818 

819 # rotate back: 

820 data = self.rotate(angle=-angle3, data=data, axis='y') 

821 data = self.rotate(angle=-(angle1 + angle2), data=data, axis='z') 

822 return data 

823 

824 if data is None: 

825 return do_it 

826 return do_it(data) 

827 

828 

829class Td(Pointgroup): 

830 # main axis should be the z-axis! 

831 def __init__(self): 

832 # some geometric math: 

833 # a = 1. 

834 # r_cap = np.sqrt(3/8.) * a 

835 # r_face = r_cap/3. 

836 # r_edge = np.sqrt(r_cap * r_face) 

837 # r_captoside = 1/np.sqrt(3) * a 

838 # r_captoedge = 0.5*a 

839 # r_height = np.sqrt(3)/2. * a 

840 self.angle_captoedge = np.arctan(np.sqrt(2)) * 180. / np.pi 

841 self.angle_captocap = 2 * self.angle_captoedge 

842 self.angle_captoface = np.arctan(2. * np.sqrt(2)) * 180. / np.pi 

843 

844 self.operations = [ 

845 ('E', self.unit), ('1C3', self.rotate_mainaxis(angle=120.)), 

846 ('2C3', self.rotate_mainaxis(angle=-120.)), 

847 ('3C3', self.rotate_othermainaxis(numberofcap=0, angle=120.)), 

848 ('4C3', self.rotate_othermainaxis(numberofcap=0, angle=-120.)), 

849 ('5C3', self.rotate_othermainaxis(numberofcap=1, angle=120.)), 

850 ('6C3', self.rotate_othermainaxis(numberofcap=1, angle=-120.)), 

851 ('7C3', self.rotate_othermainaxis(numberofcap=2, angle=120.)), 

852 ('8C3', self.rotate_othermainaxis(numberofcap=2, angle=-120.)), 

853 ('1C2', self.C2(numberofedge=0)), ('2C2', self.C2(numberofedge=1)), 

854 ('3C2', self.C2(numberofedge=2)), 

855 ('1S4', self.S4(numberofside=0, angle=90.)), 

856 ('2S4', self.S4(numberofside=0, angle=-90.)), 

857 ('3S4', self.S4(numberofside=1, angle=90.)), 

858 ('4S4', self.S4(numberofside=1, angle=-90.)), 

859 ('5S4', self.S4(numberofside=2, angle=90.)), 

860 ('6S4', self.S4(numberofside=2, angle=-90.)), 

861 ('1sigma', self.sigma(numberofedge=0)), 

862 ('2sigma', self.sigma(numberofedge=1)), 

863 ('3sigma', self.sigma(numberofedge=2)), 

864 ('4sigma', self.sigma(numberofedge=3)), 

865 ('5sigma', self.sigma(numberofedge=4)), 

866 ('6sigma', self.sigma(numberofedge=5)) 

867 ] 

868 self.operation_names = [pair[0] for pair in self.operations] 

869 self.symmetries = ['A1', 'A2', 'E', 'T1', 'T2'] 

870 self.character_table = [[1., 1., 1., 1., 1.], [1., 1., 1., -1., -1.], 

871 [2., -1., 2., 0., 0.], [3., 0., -1., 1., -1.], 

872 [3., 0., -1., -1., 1.]] 

873 self.nof_operations = [1, 8, 3, 6, 6] 

874 self.Tx_i = 4 

875 self.Ty_i = 4 

876 self.Tz_i = 4 

877 

878 def __str__(self): 

879 return 'Td' 

880 

881 def rotate_othermainaxis(self, numberofcap, angle, data=None): 

882 angle = angle 

883 numberofcap = numberofcap 

884 

885 def do_it(data): 

886 # first, bring another cap to z-axis: 

887 data = self.rotate(angle=numberofcap * 120., data=data, axis='z') 

888 data = self.rotate(angle=self.angle_captocap, data=data, axis='y') 

889 

890 # do the actual rotation: 

891 data = self.rotate(angle=angle, data=data, axis='z') 

892 

893 # rotate back: 

894 data = self.rotate(angle=-self.angle_captocap, data=data, axis='y') 

895 data = self.rotate(angle=-numberofcap * 120., data=data, axis='z') 

896 return data 

897 

898 if data is None: 

899 return do_it 

900 return do_it(data) 

901 

902 def C2(self, numberofedge, angle=180., data=None): 

903 angle = angle 

904 numberofedge = numberofedge 

905 # first, bring an edge center to z-axis: 

906 angle1 = numberofedge * 120. 

907 angle2 = self.angle_captoedge 

908 

909 def do_it(data): 

910 data = self.rotate(angle=angle1, data=data, axis='z') 

911 data = self.rotate(angle=angle2, data=data, axis='y') 

912 

913 # do the actual rotation: 

914 data = self.rotate(angle=angle, data=data, axis='z') 

915 

916 # rotate back: 

917 data = self.rotate(angle=-angle2, data=data, axis='y') 

918 data = self.rotate(angle=-angle1, data=data, axis='z') 

919 return data 

920 

921 if data is None: 

922 return do_it 

923 return do_it(data) 

924 

925 def S4(self, numberofside, angle, data=None): 

926 angle = angle 

927 numberofside = numberofside 

928 # first, bring an edge center to z-axis: 

929 angle1 = numberofside * 120. 

930 angle2 = self.angle_captoedge 

931 

932 def do_it(data): 

933 data = self.rotate(angle=angle1, data=data, axis='z') 

934 data = self.rotate(angle=angle2, data=data, axis='y') 

935 

936 # do the actual rotation: 

937 data = self.S(angle=angle, data=data) 

938 

939 # rotate back: 

940 data = self.rotate(angle=-angle2, data=data, axis='y') 

941 data = self.rotate(angle=-angle1, data=data, axis='z') 

942 return data 

943 

944 if data is None: 

945 return do_it 

946 return do_it(data) 

947 

948 def sigma(self, numberofedge, data=None): 

949 numberofedge = numberofedge 

950 # first, bring an edge center to z-axis: 

951 angle1 = (numberofedge % 3) * 120. 

952 angle2 = self.angle_captoedge 

953 angle3 = (numberofedge % 2) * 90. 

954 

955 def do_it(data): 

956 data = self.rotate(angle=angle1, data=data, axis='z') 

957 data = self.rotate(angle=angle2, data=data, axis='y') 

958 data = self.rotate(angle=angle3, data=data, axis='z') 

959 

960 # do the actual reflection: 

961 data = self.mirror_xz(data) 

962 

963 # rotate back: 

964 data = self.rotate(angle=-angle3, data=data, axis='z') 

965 data = self.rotate(angle=-angle2, data=data, axis='y') 

966 data = self.rotate(angle=-angle1, data=data, axis='z') 

967 return data 

968 

969 if data is None: 

970 return do_it 

971 return do_it(data) 

972 

973 

974class Th(Pointgroup): 

975 # main axis should be the z-axis! 

976 def __init__(self): 

977 # some geometric math: 

978 # a = 1. 

979 # r_cap = np.sqrt(3/8.) * a 

980 # r_face = r_cap/3. 

981 # r_edge = np.sqrt(r_cap * r_face) 

982 # r_captoside = 1/np.sqrt(3) * a 

983 # r_captoedge = 0.5*a 

984 # r_height = np.sqrt(3)/2. * a 

985 self.angle_captoedge = np.arctan(np.sqrt(2)) * 180. / np.pi 

986 self.angle_captocap = 2 * self.angle_captoedge 

987 self.angle_captoface = np.arctan(2. * np.sqrt(2)) * 180. / np.pi 

988 

989 self.operations = [ 

990 ('E', self.unit), ('1C3', self.rotate_mainaxis(angle=120.)), 

991 ('2C3', self.rotate_othermainaxis(numberofcap=0, angle=120.)), 

992 ('3C3', self.rotate_othermainaxis(numberofcap=1, angle=120.)), 

993 ('4C3', self.rotate_othermainaxis(numberofcap=2, angle=120.)), 

994 ('1C3_2', self.rotate_mainaxis(angle=-120.)), 

995 ('2C3_2', self.rotate_othermainaxis(numberofcap=0, angle=-120.)), 

996 ('3C3_2', self.rotate_othermainaxis(numberofcap=1, angle=-120.)), 

997 ('4C3_2', self.rotate_othermainaxis(numberofcap=2, angle=-120.)), 

998 ('1C2', self.C2(numberofedge=0)), ('2C2', self.C2(numberofedge=1)), 

999 ('3C2', self.C2(numberofedge=2)), ('i', self.inversion), 

1000 ('1S6_5', self.S6(angle=-60.)), 

1001 ('2S6_5', self.S6_othercap(numberofcap=0, angle=-60.)), 

1002 ('3S6_5', self.S6_othercap(numberofcap=1, angle=-60.)), 

1003 ('4S6_5', self.S6_othercap(numberofcap=2, angle=-60.)), 

1004 ('5S6', self.S6(angle=60.)), 

1005 ('6S6', self.S6_othercap(numberofcap=0, angle=60.)), 

1006 ('7S6', self.S6_othercap(numberofcap=1, angle=60.)), 

1007 ('8S6', self.S6_othercap(numberofcap=2, angle=60.)), 

1008 ('1sigma', self.sigma(numberofedge=0)), 

1009 ('2sigma', self.sigma(numberofedge=1)), 

1010 ('3sigma', self.sigma(numberofedge=2)) 

1011 ] 

1012 

1013 self.operation_names = [pair[0] for pair in self.operations] 

1014 self.symmetries = ['Ag', 'Eg', 'Tg', 'Au', 'Eu', 'Tu'] 

1015 self.character_table = [ 

1016 [1., 1., 1., 1., 1., 1.], 

1017 [2., 2. * np.cos(2 * np.pi / 3.), 2., 2., 

1018 2. * np.cos(2 * np.pi / 3.), 2.], 

1019 [3., 0., -1., 3., 0., -1.], 

1020 [1., 1., 1., -1., -1., -1.], 

1021 [2., 2. * np.cos(2 * np.pi / 3.), 2., -2., 

1022 -2. * np.cos(2 * np.pi / 3.), -2.], 

1023 [3., 0., -1., -3., 0., 1.]] 

1024 self.nof_operations = [1, 8, 3, 1, 8, 3] 

1025 self.Tx_i = 5 

1026 self.Ty_i = 5 

1027 self.Tz_i = 5 

1028 self.complex = True 

1029 

1030 def __str__(self): 

1031 return 'Th' 

1032 

1033 def rotate_othermainaxis(self, numberofcap, angle, data=None): 

1034 angle = angle 

1035 numberofcap = numberofcap 

1036 

1037 def do_it(data): 

1038 # first, bring another cap to z-axis: 

1039 data = self.rotate(angle=numberofcap * 120., data=data, axis='z') 

1040 data = self.rotate(angle=self.angle_captocap, data=data, axis='y') 

1041 

1042 # do the actual rotation: 

1043 data = self.rotate(angle=angle, data=data, axis='z') 

1044 

1045 # rotate back: 

1046 data = self.rotate(angle=-self.angle_captocap, data=data, axis='y') 

1047 data = self.rotate(angle=-numberofcap * 120., data=data, axis='z') 

1048 return data 

1049 

1050 if data is None: 

1051 return do_it 

1052 return do_it(data) 

1053 

1054 def C2(self, numberofedge, angle=180., data=None): 

1055 angle = angle 

1056 numberofedge = numberofedge 

1057 # first, bring an edge center to z-axis: 

1058 angle1 = numberofedge * 120. 

1059 angle2 = self.angle_captoedge 

1060 

1061 def do_it(data): 

1062 data = self.rotate(angle=angle1, data=data, axis='z') 

1063 data = self.rotate(angle=angle2, data=data, axis='y') 

1064 

1065 # do the actual rotation: 

1066 data = self.rotate(angle=angle, data=data, axis='z') 

1067 

1068 # rotate back: 

1069 data = self.rotate(angle=-angle2, data=data, axis='y') 

1070 data = self.rotate(angle=-angle1, data=data, axis='z') 

1071 return data 

1072 

1073 if data is None: 

1074 return do_it 

1075 return do_it(data) 

1076 

1077 def inversion(self, data=None): 

1078 return self.invert(data) 

1079 

1080 def S6(self, angle, data=None): 

1081 angle = angle 

1082 

1083 def do_it(data): 

1084 data = self.S(angle=angle, data=data) 

1085 return data 

1086 

1087 if data is None: 

1088 return do_it 

1089 return do_it(data) 

1090 

1091 def S6_othercap(self, numberofcap, angle, data=None): 

1092 angle = angle 

1093 numberofcap = numberofcap 

1094 

1095 def do_it(data): 

1096 data = self.rotate(angle=numberofcap * 120., data=data, axis='z') 

1097 data = self.rotate(angle=self.angle_captocap, data=data, axis='y') 

1098 

1099 # do the actual rotation: 

1100 data = self.S(angle=angle, data=data) 

1101 

1102 # rotate back: 

1103 data = self.rotate(angle=-self.angle_captocap, data=data, axis='y') 

1104 data = self.rotate(angle=-numberofcap * 120, data=data, axis='z') 

1105 return data 

1106 

1107 if data is None: 

1108 return do_it 

1109 return do_it(data) 

1110 

1111 def sigma(self, numberofedge, data=None): 

1112 numberofedge = numberofedge 

1113 # first, bring an edge center to z-axis: 

1114 angle1 = (numberofedge % 3) * 120. 

1115 angle2 = self.angle_captoedge 

1116 angle3 = 45. 

1117 

1118 def do_it(data): 

1119 data = self.rotate(angle=angle1, data=data, axis='z') 

1120 data = self.rotate(angle=angle2, data=data, axis='y') 

1121 data = self.rotate(angle=angle3, data=data, axis='z') 

1122 

1123 # do the actual reflection: 

1124 data = self.mirror_xz(data) 

1125 

1126 # rotate back: 

1127 data = self.rotate(angle=-angle3, data=data, axis='z') 

1128 data = self.rotate(angle=-angle2, data=data, axis='y') 

1129 data = self.rotate(angle=-angle1, data=data, axis='z') 

1130 return data 

1131 

1132 if data is None: 

1133 return do_it 

1134 return do_it(data) 

1135 

1136 

1137class C2v(Pointgroup): 

1138 # main axis should be the z-axis! 

1139 def __init__(self): 

1140 self.operations = [('E', self.unit), 

1141 ('C2', self.rotate_mainaxis(angle=180.)), 

1142 ('sigma_v0', self.sigma_v(angle=0.)), 

1143 ('sigma_v1', self.sigma_v(angle=90.))] 

1144 self.operation_names = [pair[0] for pair in self.operations] 

1145 self.symmetries = ['A1', 'A2', 'B1', 'B2'] 

1146 self.character_table = [[1., 1., 1., 1.], [1., 1., -1., -1.], 

1147 [1., -1., 1., -1.], [1., -1., -1., 1.]] 

1148 self.nof_operations = [1, 1, 1, 1] 

1149 self.Tx_i = 2 

1150 self.Ty_i = 3 

1151 self.Tz_i = 0 

1152 

1153 def __str__(self): 

1154 return 'C2v' 

1155 

1156 def C2(self, angle, data=None): 

1157 angle = angle 

1158 

1159 def do_it(data): 

1160 return self.C2prime(data, angle) 

1161 

1162 if data is None: 

1163 return do_it 

1164 return do_it(data) 

1165 

1166 def sigma_v(self, angle, data=None): 

1167 # first rotate so that the plane is xz plane, flip, and rotate back 

1168 angle = angle 

1169 

1170 def do_it(data): 

1171 first = self.rotate(data=data, angle=angle) 

1172 second = self.mirror_xz(first) 

1173 third = self.rotate(data=second, angle=-angle) 

1174 return third 

1175 

1176 if data is None: 

1177 return do_it 

1178 return do_it(data) 

1179 

1180 

1181class C3v(Pointgroup): 

1182 # main axis should be the z-axis! 

1183 def __init__(self): 

1184 self.operations = [('E', self.unit), 

1185 ('1C3', self.rotate_mainaxis(angle=120.)), 

1186 ('2C3', self.rotate_mainaxis(angle=-120.)), 

1187 ('sigma_v0', self.sigma_v(angle=0.)), 

1188 ('sigma_v1', self.sigma_v(angle=120.)), 

1189 ('sigma_v2', self.sigma_v(angle=-120.))] 

1190 self.operation_names = [pair[0] for pair in self.operations] 

1191 self.symmetries = ['A1', 'A2', 'E'] 

1192 self.character_table = [[1., 1., 1.], [1., 1., -1.], [2., -1., 0.]] 

1193 self.nof_operations = [1, 2, 3] 

1194 self.Tx_i = 2 

1195 self.Ty_i = 2 

1196 self.Tz_i = 0 

1197 

1198 def __str__(self): 

1199 return 'C3v' 

1200 

1201 def sigma_v(self, angle, data=None): 

1202 # first rotate so that the plane is xz plane, flip, and rotate back 

1203 angle = angle 

1204 

1205 def do_it(data): 

1206 first = self.rotate(data=data, angle=angle) 

1207 second = self.mirror_xz(first) 

1208 third = self.rotate(data=second, angle=-angle) 

1209 return third 

1210 

1211 if data is None: 

1212 return do_it 

1213 return do_it(data) 

1214 

1215 

1216class D3h(Pointgroup): 

1217 # main axis should be the z-axis! 

1218 def __init__(self): 

1219 self.operations = [('E', self.unit), 

1220 ('1C3', self.rotate_mainaxis(angle=120.)), 

1221 ('2C3', self.rotate_mainaxis(angle=-120.)), 

1222 ('C2_0', self.C2(angle=0 * 120.)), 

1223 ('C2_1', self.C2(angle=1 * 120.)), 

1224 ('C2_2', self.C2(angle=2 * 120.)), 

1225 ('sigma_h', self.sigma_h), 

1226 ('S3_1', self.S3(angle=120.)), 

1227 ('S3_2', self.S3(angle=-120.)), 

1228 ('sigma_v0', self.sigma_v(angle=0.)), 

1229 ('sigma_v1', self.sigma_v(angle=120.)), 

1230 ('sigma_v2', self.sigma_v(angle=-120.))] 

1231 self.operation_names = [pair[0] for pair in self.operations] 

1232 self.symmetries = [ 

1233 'A\'1', 'A\'2', 'E\'1', 'A\'\'1', 'A\'\'2', 'E\'\'1' 

1234 ] 

1235 self.character_table = [[1., 1., 1., 1., 1., 1.], 

1236 [1., 1., -1., 1., 1., -1.], 

1237 [2., -1., 0., 2., -1., 0.], 

1238 [1., 1., 1., -1., -1., -1.], 

1239 [1., 1., -1., -1., -1., 1.], 

1240 [2., -1., 0., -2., 1., 0.]] 

1241 self.nof_operations = [1, 2, 3, 1, 2, 3] 

1242 self.Tx_i = 2 

1243 self.Ty_i = 2 

1244 self.Tz_i = 4 

1245 

1246 def __str__(self): 

1247 return 'D3h' 

1248 

1249 def C2(self, angle, data=None): 

1250 angle = angle 

1251 

1252 def do_it(data): 

1253 return self.C2prime(data, angle) 

1254 

1255 if data is None: 

1256 return do_it 

1257 return do_it(data) 

1258 

1259 def sigma_h(self, data=None): 

1260 return self.mirror_xy(data) 

1261 

1262 def S3(self, angle, data=None): 

1263 angle = angle 

1264 

1265 def do_it(data): 

1266 return self.S(data=data, angle=angle) 

1267 

1268 if data is None: 

1269 return do_it 

1270 return do_it(data) 

1271 

1272 def S53(self, angle, data=None): 

1273 angle = angle 

1274 

1275 def do_it(data): 

1276 first = self.S(data=data, angle=angle) 

1277 second = self.S(data=first, angle=angle) 

1278 third = self.S(data=second, angle=angle) 

1279 return third 

1280 

1281 if data is None: 

1282 return do_it 

1283 return do_it(data) 

1284 

1285 def sigma_v(self, angle, data=None): 

1286 # first rotate so that the plane is xz plane, flip, and rotate back 

1287 angle = angle 

1288 

1289 def do_it(data): 

1290 first = self.rotate(data=data, angle=angle) 

1291 second = self.mirror_xz(first) 

1292 third = self.rotate(data=second, angle=-angle) 

1293 return third 

1294 

1295 if data is None: 

1296 return do_it 

1297 return do_it(data) 

1298 

1299 

1300class D2d(Pointgroup): 

1301 # main axis should be the z-axis! 

1302 def __init__(self): 

1303 self.operations = [('E', self.unit), 

1304 ('S4_1', self.S4(angle=90.)), 

1305 ('S4_2', self.S4(angle=-90.)), 

1306 ('C2_0', self.C2(angle=180.)), 

1307 ("C2'_0", self.C2p(angle=45.)), 

1308 ("C2'_1", self.C2p(angle=-45.)), 

1309 ('sigma_d1', self.sigma_d(angle=0.)), 

1310 ('sigma_d2', self.sigma_d(angle=90.))] 

1311 self.operation_names = [pair[0] for pair in self.operations] 

1312 self.symmetries = ['A\'1', 'A\'2', 'B\'1', 'B\'2', 'E'] 

1313 self.character_table = [[1., 1., 1., 1., 1.], [1., 1., 1., -1., -1.], 

1314 [1., -1., 1., 1., -1.], [1., -1., 1., -1., 1.], 

1315 [2., 0., -2., 0., 0.]] 

1316 self.nof_operations = [1, 2, 1, 2, 2] 

1317 self.Tx_i = 4 

1318 self.Ty_i = 4 

1319 self.Tz_i = 3 

1320 

1321 def __str__(self): 

1322 return 'D2d' 

1323 

1324 def S4(self, angle, data=None): 

1325 angle = angle 

1326 

1327 # first, bring an edge center to z-axis: 

1328 

1329 def do_it(data): 

1330 # do the actual rotation: 

1331 data = self.S(angle=angle, data=data) 

1332 return data 

1333 

1334 if data is None: 

1335 return do_it 

1336 return do_it(data) 

1337 

1338 def C2(self, angle, data=None): 

1339 angle = angle 

1340 

1341 def do_it(data): 

1342 return self.rotate(angle=angle, data=data, axis='z') 

1343 

1344 if data is None: 

1345 return do_it 

1346 return do_it(data) 

1347 

1348 def C2p(self, angle=90., data=None): 

1349 angle = angle 

1350 

1351 def do_it(data): 

1352 data = self.rotate(angle=angle, data=data, axis='z') 

1353 data = self.rotate(angle=90., data=data, axis='x') 

1354 

1355 # do the actual rotation: 

1356 data = self.rotate(angle=180., data=data, axis='z') 

1357 

1358 # rotate back: 

1359 data = self.rotate(angle=-90., data=data, axis='x') 

1360 data = self.rotate(angle=-angle, data=data, axis='z') 

1361 return data 

1362 

1363 if data is None: 

1364 return do_it 

1365 return do_it(data) 

1366 

1367 def sigma_d(self, angle, data=None): 

1368 # first rotate so that the plane is xz plane, flip, and rotate back 

1369 angle = angle 

1370 

1371 def do_it(data): 

1372 first = self.rotate(data=data, angle=angle) 

1373 second = self.mirror_xz(first) 

1374 third = self.rotate(data=second, angle=-angle) 

1375 return third 

1376 

1377 if data is None: 

1378 return do_it 

1379 return do_it(data) 

1380 

1381 

1382class C2(Pointgroup): 

1383 # main axis should be the z-axis! 

1384 def __init__(self): 

1385 self.operations = [('E', self.unit), 

1386 ('C2', self.rotate_mainaxis(angle=180.))] 

1387 self.operation_names = [pair[0] for pair in self.operations] 

1388 self.symmetries = ['A', 'B'] 

1389 self.character_table = [[ 

1390 1., 

1391 1., 

1392 ], [1., -1.]] 

1393 

1394 self.nof_operations = [1, 1] 

1395 self.Tx_i = 1 

1396 self.Ty_i = 1 

1397 self.Tz_i = 0 

1398 

1399 def __str__(self): 

1400 return 'C2' 

1401 

1402 

1403class Oh(Pointgroup): 

1404 # main axis should be the z-axis! 

1405 def __init__(self): 

1406 self.operations = [('E', self.unit), ('1C3', self.C3(corner=0)), 

1407 ('2C3', self.C3(corner=1)), 

1408 ('3C3', self.C3(corner=2)), 

1409 ('4C3', self.C3(corner=3)), 

1410 ('5C3', self.C3(corner=4)), 

1411 ('6C3', self.C3(corner=5)), 

1412 ('7C3', self.C3(corner=6)), 

1413 ('8C3', self.C3(corner=7)), 

1414 ('1C2', self.C2(edge=0)), ('2C2', self.C2(edge=1)), 

1415 ('3C2', self.C2(edge=2)), ('4C2', self.C2(edge=3)), 

1416 ('5C2', self.C2(edge=4)), ('6C2', self.C2(edge=5)), 

1417 ('1C4', self.C4(face=0)), ('2C4', self.C4(face=1)), 

1418 ('3C4', self.C4(face=2)), ('4C4', self.C4(face=3)), 

1419 ('5C4', self.C4(face=4)), ('6C4', self.C4(face=5)), 

1420 ('1faceC2', self.faceC2(face=0)), 

1421 ('2faceC2', self.faceC2(face=1)), 

1422 ('3faceC2', self.faceC2(face=2)), 

1423 ('i', self.inversion), ('1S4', self.S4(face=0)), 

1424 ('2S4', self.S4(face=1)), ('3S4', self.S4(face=2)), 

1425 ('4S4', self.S4(face=3)), ('5S4', self.S4(face=4)), 

1426 ('6S4', self.S4(face=5)), 

1427 ('1S6', self.S6(corner=0)), 

1428 ('2S6', self.S6(corner=1)), 

1429 ('3S6', self.S6(corner=2)), 

1430 ('4S6', self.S6(corner=3)), 

1431 ('5S6', self.S6(corner=4)), 

1432 ('6S6', self.S6(corner=5)), 

1433 ('7S6', self.S6(corner=6)), 

1434 ('8S6', self.S6(corner=7)), 

1435 ('1sigma_h1', self.sigma_h(face=0)), 

1436 ('2sigma_h1', self.sigma_h(face=1)), 

1437 ('3sigma_h1', self.sigma_h(face=2)), 

1438 ('1sigma_d1', self.sigma_d(face=0)), 

1439 ('2sigma_d1', self.sigma_d(face=1)), 

1440 ('3sigma_d1', self.sigma_d(face=2)), 

1441 ('4sigma_d1', self.sigma_d(face=3)), 

1442 ('5sigma_d1', self.sigma_d(face=4)), 

1443 ('6sigma_d1', self.sigma_d(face=5))] 

1444 self.operation_names = [pair[0] for pair in self.operations] 

1445 self.symmetries = [ 

1446 'A1g', 'A2g', 'Eg', 'T1g', 'T2g', 'A1u', 'A2u', 'Eu', 'T1u', 'T2u' 

1447 ] 

1448 self.character_table = [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 

1449 [1., 1., -1., -1., 1., 1., -1., 1., 1., -1.], 

1450 [2., -1., 0., 0., 2., 2., 0., -1., 2., 0.], 

1451 [3., 0., -1., 1., -1., 3., 1., 0., -1., -1.], 

1452 [3., 0., 1., -1., -1., 3., -1., 0., -1., 1.], 

1453 [1., 1., 1., 1., 1., -1., -1., -1., -1., -1.], 

1454 [1., 1., -1., -1., 1., -1., 1., -1., -1., 1.], 

1455 [2., -1., 0., 0., 2., -2., 0., 1., -2., 0.], 

1456 [3., 0., -1., 1., -1., -3., -1., 0., 1., 1.], 

1457 [3., 0., 1., -1., -1., -3., 1., 0., 1., -1.]] 

1458 self.nof_operations = [1, 8, 6, 6, 3, 1, 6, 8, 3, 6] 

1459 self.Tx_i = 8 

1460 self.Ty_i = 8 

1461 self.Tz_i = 8 

1462 

1463 def __str__(self): 

1464 return 'Oh' 

1465 

1466 def C3(self, corner, data=None): 

1467 corner = corner 

1468 t1, t2 = divmod(corner, 4) 

1469 t1 = (-1)**t1 

1470 angle1 = (t2 * 90.) + 45. # y 

1471 angle2 = t1 * (np.arctan(1 / np.sqrt(2.)) * 180. / np.pi) # x 

1472 

1473 def do_it(data): 

1474 data = self.rotate(angle=angle1, data=data, axis='y') 

1475 data = self.rotate(angle=angle2, data=data, axis='x') 

1476 

1477 data = self.rotate(angle=120., data=data, axis='z') 

1478 

1479 data = self.rotate(angle=-angle2, data=data, axis='x') 

1480 data = self.rotate(angle=-angle1, data=data, axis='y') 

1481 return data 

1482 

1483 if data is None: 

1484 return do_it 

1485 return do_it(data) 

1486 

1487 def C2(self, edge, data=None): 

1488 edge = edge 

1489 t1, t2 = divmod(edge, 3) 

1490 angle1 = t1 * 90. 

1491 set2 = [[45., 'x'], [45., 'y'], [-45., 'x']][t2] 

1492 

1493 def do_it(data): 

1494 data = self.rotate(angle=angle1, data=data, axis='y') 

1495 data = self.rotate(angle=set2[0], data=data, axis=set2[1]) 

1496 

1497 data = self.rotate(angle=180., data=data, axis='z') 

1498 

1499 data = self.rotate(angle=-set2[0], data=data, axis=set2[1]) 

1500 data = self.rotate(angle=-angle1, data=data, axis='y') 

1501 return data 

1502 

1503 if data is None: 

1504 return do_it 

1505 return do_it(data) 

1506 

1507 def C4(self, face, data=None): 

1508 face = face 

1509 t1, t2 = divmod(face, 3) 

1510 axis = ['x', 'y', 'z'][t2] 

1511 angle = (-1)**t1 * 90. 

1512 

1513 def do_it(data): 

1514 data = self.rotate(angle=90., data=data, axis=axis) 

1515 

1516 data = self.rotate(angle=angle, data=data, axis='z') 

1517 

1518 data = self.rotate(angle=-90., data=data, axis=axis) 

1519 return data 

1520 

1521 if data is None: 

1522 return do_it 

1523 return do_it(data) 

1524 

1525 def faceC2(self, face, data=None): 

1526 face = face 

1527 t1, t2 = divmod(face, 3) 

1528 axis = ['x', 'y', 'z'][t2] 

1529 angle = 180. 

1530 

1531 def do_it(data): 

1532 data = self.rotate(angle=90., data=data, axis=axis) 

1533 

1534 data = self.rotate(angle=angle, data=data, axis='y') 

1535 

1536 data = self.rotate(angle=-90., data=data, axis=axis) 

1537 return data 

1538 

1539 if data is None: 

1540 return do_it 

1541 return do_it(data) 

1542 

1543 def inversion(self, data=None): 

1544 return self.invert(data) 

1545 

1546 def S4(self, face, data=None): 

1547 face = face 

1548 t1, t2 = divmod(face, 3) 

1549 axis = ['x', 'y', 'z'][t2] 

1550 angle = (-1)**t1 * 90. 

1551 

1552 def do_it(data): 

1553 data = self.rotate(angle=90., data=data, axis=axis) 

1554 

1555 data = self.S(angle=angle, data=data) 

1556 

1557 data = self.rotate(angle=-90., data=data, axis=axis) 

1558 return data 

1559 

1560 if data is None: 

1561 return do_it 

1562 return do_it(data) 

1563 

1564 def S6(self, corner, data=None): 

1565 corner = corner 

1566 t1, t2 = divmod(corner, 4) 

1567 t1 = (-1)**t1 

1568 angle1 = (t2 * 90.) + 45. # y 

1569 angle2 = t1 * (np.arctan(1 / np.sqrt(2.)) * 180. / np.pi) # x 

1570 

1571 def do_it(data): 

1572 data = self.rotate(angle=angle1, data=data, axis='y') 

1573 data = self.rotate(angle=angle2, data=data, axis='x') 

1574 

1575 data = self.S(angle=60., data=data) 

1576 

1577 data = self.rotate(angle=-angle2, data=data, axis='x') 

1578 data = self.rotate(angle=-angle1, data=data, axis='y') 

1579 return data 

1580 

1581 if data is None: 

1582 return do_it 

1583 return do_it(data) 

1584 

1585 def sigma_h(self, face, data=None): 

1586 face = face 

1587 t1, t2 = divmod(face, 3) 

1588 axis = ['x', 'y', 'z'][t2] 

1589 

1590 def do_it(data): 

1591 data = self.rotate(angle=90., data=data, axis=axis) 

1592 

1593 data = self.mirror_xy(data) 

1594 

1595 data = self.rotate(angle=-90., data=data, axis=axis) 

1596 return data 

1597 

1598 if data is None: 

1599 return do_it 

1600 return do_it(data) 

1601 

1602 def sigma_d(self, face, data=None): 

1603 face = face 

1604 t1, t2 = divmod(face, 3) 

1605 axis = ['x', 'y', 'z'][t2] 

1606 angle2 = (-1)**t1 * 45. 

1607 

1608 def do_it(data): 

1609 data = self.rotate(angle=90., data=data, axis=axis) 

1610 data = self.rotate(angle=angle2, data=data, axis='z') 

1611 

1612 data = self.mirror_xz(data) 

1613 

1614 data = self.rotate(angle=-angle2, data=data, axis='z') 

1615 data = self.rotate(angle=-90., data=data, axis=axis) 

1616 return data 

1617 

1618 if data is None: 

1619 return do_it 

1620 return do_it(data)