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
« 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
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.
20"""
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
31class Pointgroup:
32 def unit(self, data):
33 return np.eye(3)
35 def rotate_mainaxis(self, angle, data=None):
36 return rotation([0, 0, angle / 180 * pi])
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)
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
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)
67 def invert(self, data):
68 return self.mirror_xy(self.mirror_yz(self.mirror_xz(data)))
70 def mirror_xy(self, data):
71 return np.array([[1, 0, 0], [0, 1, 0], [0, 0, -1.0]]).dot(data)
73 def mirror_xz(self, data):
74 return np.array([[1, 0, 0], [0, -1.0, 0], [0, 0, 1]]).dot(data)
76 def mirror_yz(self, data):
77 return np.array([[-1.0, 0, 0], [0, 1, 0], [0, 0, 1]]).dot(data)
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
105 def __str__(self):
106 return 'D5'
108 def C2(self, angle, data=None):
109 angle = angle
111 def do_it(data):
112 return self.C2prime(data, angle)
114 if data is None:
115 return do_it
116 return do_it(data)
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
181 def __str__(self):
182 return 'D5h'
184 def C2(self, angle, data=None):
185 angle = angle
187 def do_it(data):
188 return self.C2prime(data, angle)
190 if data is None:
191 return do_it
192 return do_it(data)
194 def sigma_h(self, data=None):
195 return self.mirror_xy(data)
197 def S5(self, angle, data=None):
198 angle = angle
200 def do_it(data):
201 return self.S(angle=angle, data=data)
203 if data is None:
204 return do_it
205 return do_it(data)
207 def S53(self, angle, data=None):
208 angle = angle
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
216 if data is None:
217 return do_it
218 return do_it(data)
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
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
230 if data is None:
231 return do_it
232 return do_it(data)
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)
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
419 def __str__(self):
420 return 'Ih'
422 def rotate_othermainaxis(self, numberofcap, angle, data=None):
423 angle = angle
424 numberofcap = numberofcap
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')
431 # do the actual rotation:
432 data = self.rotate(angle=angle, data=data, axis='z')
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
439 if data is None:
440 return do_it
441 return do_it(data)
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
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')
458 # do the actual rotation:
459 data = self.rotate(angle=angle, data=data, axis='z')
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
466 if data is None:
467 return do_it
468 return do_it(data)
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.
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')
491 # do the actual rotation:
492 data = self.rotate(angle=angle, data=data, axis='z')
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
499 if data is None:
500 return do_it
501 return do_it(data)
503 def inversion(self, data=None):
504 return self.invert(data)
506 def S10(self, angle, data=None):
507 angle = angle
509 def do_it(data):
510 return self.S(data=data, angle=angle)
512 if data is None:
513 return do_it
514 return do_it(data)
516 def S10_othercap(self, numberofcap, angle, data=None):
517 angle = angle
518 numberofcap = numberofcap
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')
525 # do the actual S-operation:
526 data = self.S(angle=angle, data=data)
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
533 if data is None:
534 return do_it
535 return do_it(data)
537 def S10_3(self, angle, data=None):
538 angle = angle
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
546 if data is None:
547 return do_it
548 return do_it(data)
550 def S10_3_othercap(self, numberofcap, angle, data=None):
551 angle = angle
552 numberofcap = numberofcap
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')
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)
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
569 if data is None:
570 return do_it
571 return do_it(data)
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
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')
588 # do the actual rotation:
589 data = self.S(angle=angle, data=data)
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
596 if data is None:
597 return do_it
598 return do_it(data)
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
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')
624 # do the actual rotation:
625 data = self.mirror_xz(data)
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
633 if data is None:
634 return do_it
635 return do_it(data)
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)
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
744 def __str__(self):
745 return 'Ico'
747 def rotate_othermainaxis(self, numberofcap, angle, data=None):
748 angle = angle
749 numberofcap = numberofcap
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')
756 # do the actual rotation:
757 data = self.rotate(angle=angle, data=data, axis='z')
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
764 if data is None:
765 return do_it
766 return do_it(data)
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
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')
783 # do the actual rotation:
784 data = self.rotate(angle=angle, data=data, axis='z')
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
791 if data is None:
792 return do_it
793 return do_it(data)
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.
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')
816 # do the actual rotation:
817 data = self.rotate(angle=angle, data=data, axis='z')
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
824 if data is None:
825 return do_it
826 return do_it(data)
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
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
878 def __str__(self):
879 return 'Td'
881 def rotate_othermainaxis(self, numberofcap, angle, data=None):
882 angle = angle
883 numberofcap = numberofcap
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')
890 # do the actual rotation:
891 data = self.rotate(angle=angle, data=data, axis='z')
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
898 if data is None:
899 return do_it
900 return do_it(data)
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
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')
913 # do the actual rotation:
914 data = self.rotate(angle=angle, data=data, axis='z')
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
921 if data is None:
922 return do_it
923 return do_it(data)
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
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')
936 # do the actual rotation:
937 data = self.S(angle=angle, data=data)
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
944 if data is None:
945 return do_it
946 return do_it(data)
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.
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')
960 # do the actual reflection:
961 data = self.mirror_xz(data)
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
969 if data is None:
970 return do_it
971 return do_it(data)
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
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 ]
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
1030 def __str__(self):
1031 return 'Th'
1033 def rotate_othermainaxis(self, numberofcap, angle, data=None):
1034 angle = angle
1035 numberofcap = numberofcap
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')
1042 # do the actual rotation:
1043 data = self.rotate(angle=angle, data=data, axis='z')
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
1050 if data is None:
1051 return do_it
1052 return do_it(data)
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
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')
1065 # do the actual rotation:
1066 data = self.rotate(angle=angle, data=data, axis='z')
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
1073 if data is None:
1074 return do_it
1075 return do_it(data)
1077 def inversion(self, data=None):
1078 return self.invert(data)
1080 def S6(self, angle, data=None):
1081 angle = angle
1083 def do_it(data):
1084 data = self.S(angle=angle, data=data)
1085 return data
1087 if data is None:
1088 return do_it
1089 return do_it(data)
1091 def S6_othercap(self, numberofcap, angle, data=None):
1092 angle = angle
1093 numberofcap = numberofcap
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')
1099 # do the actual rotation:
1100 data = self.S(angle=angle, data=data)
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
1107 if data is None:
1108 return do_it
1109 return do_it(data)
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.
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')
1123 # do the actual reflection:
1124 data = self.mirror_xz(data)
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
1132 if data is None:
1133 return do_it
1134 return do_it(data)
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
1153 def __str__(self):
1154 return 'C2v'
1156 def C2(self, angle, data=None):
1157 angle = angle
1159 def do_it(data):
1160 return self.C2prime(data, angle)
1162 if data is None:
1163 return do_it
1164 return do_it(data)
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
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
1176 if data is None:
1177 return do_it
1178 return do_it(data)
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
1198 def __str__(self):
1199 return 'C3v'
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
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
1211 if data is None:
1212 return do_it
1213 return do_it(data)
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
1246 def __str__(self):
1247 return 'D3h'
1249 def C2(self, angle, data=None):
1250 angle = angle
1252 def do_it(data):
1253 return self.C2prime(data, angle)
1255 if data is None:
1256 return do_it
1257 return do_it(data)
1259 def sigma_h(self, data=None):
1260 return self.mirror_xy(data)
1262 def S3(self, angle, data=None):
1263 angle = angle
1265 def do_it(data):
1266 return self.S(data=data, angle=angle)
1268 if data is None:
1269 return do_it
1270 return do_it(data)
1272 def S53(self, angle, data=None):
1273 angle = angle
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
1281 if data is None:
1282 return do_it
1283 return do_it(data)
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
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
1295 if data is None:
1296 return do_it
1297 return do_it(data)
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
1321 def __str__(self):
1322 return 'D2d'
1324 def S4(self, angle, data=None):
1325 angle = angle
1327 # first, bring an edge center to z-axis:
1329 def do_it(data):
1330 # do the actual rotation:
1331 data = self.S(angle=angle, data=data)
1332 return data
1334 if data is None:
1335 return do_it
1336 return do_it(data)
1338 def C2(self, angle, data=None):
1339 angle = angle
1341 def do_it(data):
1342 return self.rotate(angle=angle, data=data, axis='z')
1344 if data is None:
1345 return do_it
1346 return do_it(data)
1348 def C2p(self, angle=90., data=None):
1349 angle = angle
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')
1355 # do the actual rotation:
1356 data = self.rotate(angle=180., data=data, axis='z')
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
1363 if data is None:
1364 return do_it
1365 return do_it(data)
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
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
1377 if data is None:
1378 return do_it
1379 return do_it(data)
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.]]
1394 self.nof_operations = [1, 1]
1395 self.Tx_i = 1
1396 self.Ty_i = 1
1397 self.Tz_i = 0
1399 def __str__(self):
1400 return 'C2'
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
1463 def __str__(self):
1464 return 'Oh'
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
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')
1477 data = self.rotate(angle=120., data=data, axis='z')
1479 data = self.rotate(angle=-angle2, data=data, axis='x')
1480 data = self.rotate(angle=-angle1, data=data, axis='y')
1481 return data
1483 if data is None:
1484 return do_it
1485 return do_it(data)
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]
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])
1497 data = self.rotate(angle=180., data=data, axis='z')
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
1503 if data is None:
1504 return do_it
1505 return do_it(data)
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.
1513 def do_it(data):
1514 data = self.rotate(angle=90., data=data, axis=axis)
1516 data = self.rotate(angle=angle, data=data, axis='z')
1518 data = self.rotate(angle=-90., data=data, axis=axis)
1519 return data
1521 if data is None:
1522 return do_it
1523 return do_it(data)
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.
1531 def do_it(data):
1532 data = self.rotate(angle=90., data=data, axis=axis)
1534 data = self.rotate(angle=angle, data=data, axis='y')
1536 data = self.rotate(angle=-90., data=data, axis=axis)
1537 return data
1539 if data is None:
1540 return do_it
1541 return do_it(data)
1543 def inversion(self, data=None):
1544 return self.invert(data)
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.
1552 def do_it(data):
1553 data = self.rotate(angle=90., data=data, axis=axis)
1555 data = self.S(angle=angle, data=data)
1557 data = self.rotate(angle=-90., data=data, axis=axis)
1558 return data
1560 if data is None:
1561 return do_it
1562 return do_it(data)
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
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')
1575 data = self.S(angle=60., data=data)
1577 data = self.rotate(angle=-angle2, data=data, axis='x')
1578 data = self.rotate(angle=-angle1, data=data, axis='y')
1579 return data
1581 if data is None:
1582 return do_it
1583 return do_it(data)
1585 def sigma_h(self, face, data=None):
1586 face = face
1587 t1, t2 = divmod(face, 3)
1588 axis = ['x', 'y', 'z'][t2]
1590 def do_it(data):
1591 data = self.rotate(angle=90., data=data, axis=axis)
1593 data = self.mirror_xy(data)
1595 data = self.rotate(angle=-90., data=data, axis=axis)
1596 return data
1598 if data is None:
1599 return do_it
1600 return do_it(data)
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.
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')
1612 data = self.mirror_xz(data)
1614 data = self.rotate(angle=-angle2, data=data, axis='z')
1615 data = self.rotate(angle=-90., data=data, axis=axis)
1616 return data
1618 if data is None:
1619 return do_it
1620 return do_it(data)