2 from sympy
.combinatorics
import Permutation
, PermutationGroup
3 sympy
.init_printing(perm_cyclic
= True)
5 from cmath
import exp
, pi
8 np
.set_printoptions(linewidth
=200)
12 from .tmatrices
import zflip_tyty
, xflip_tyty
, yflip_tyty
, zrotN_tyty
, WignerD_yy_fromvector
, identity_tyty
, apply_ndmatrix_left
13 from .cyquaternions
import IRot3
14 from .cycommon
import get_mn_y
16 s3long
= np
.sqrt(np
.longdouble(3.))
18 def grouprep_try(tdict
, src
, im
, srcgens
, imgens
, immultop
= None, imcmp
= None):
20 for i
in range(len(srcgens
)):
21 new_src
= src
* srcgens
[i
]
22 new_im
= (im
* imgens
[i
]) if (immultop
is None) else immultop(im
, imgens
[i
])
23 if new_src
not in tdict
.keys():
24 grouprep_try(tdict
, new_src
, new_im
, srcgens
, imgens
, immultop
, imcmp
)
25 elif ((new_im
!= tdict
[new_src
]) if (imcmp
is None) else (not imcmp(new_im
, tdict
[new_src
]))): # check consistency
26 print(src
, ' * ', srcgens
[i
], ' --> ', new_src
)
34 raise ValueError("Homomorphism inconsistency detected")
37 def group_dps_try(elemlist
, elem
, gens
):
38 '''Deterministic group depth-first search'''
40 for i
in range(len(gens
)):
41 newelem
= elem
* gens
[i
]
42 if newelem
not in elemlist
:
43 group_dps_try(elemlist
, newelem
, gens
)
46 class SVWFPointGroupInfo
: # only for point groups, coz in svwf_rep() I use I_tyty, not I_ptypty or something alike
49 permgroupgens
, # permutation group generators
50 irrepgens_dict
, # dictionary with irrep generators,
51 svwf_rep_gen_func
, # function that generates a tuple with svwf representation generators
52 rep3d_gens
= None, # 3d (quaternion) representation generators of a point group: sequence of qpms.irep3 instances
55 self
.permgroupgens
= permgroupgens
56 self
.permgroup
= PermutationGroup(*permgroupgens
)
57 self
.irrepgens_dict
= irrepgens_dict
58 self
.svwf_rep_gen_func
= svwf_rep_gen_func
60 for irrepname
, irrepgens
in irrepgens_dict
.items():
61 is1d
= isinstance(irrepgens
[0], (int,float,complex))
62 irrepdim
= 1 if is1d
else irrepgens
[0].shape
[0]
63 self
.irreps
[irrepname
] = generate_grouprep(self
.permgroup
,
64 1 if is1d
else np
.eye(irrepdim
),
65 permgroupgens
, irrepgens
,
66 immultop
= None if is1d
else np
.dot
,
67 imcmp
= None if is1d
else np
.allclose
69 self
.rep3d_gens
= rep3d_gens
70 self
.rep3d
= None if rep3d_gens
is None else generate_grouprep(
73 permgroupgens
, rep3d_gens
,
74 immultop
= None, imcmp
= (lambda x
, y
: x
.isclose(y
))
77 def deterministic_elemlist(self
):
79 group_dps_try(thelist
, self
.permgroup
.identity
, self
.permgroupgens
)
82 def svwf_rep(self
, lMax
, *rep_gen_func_args
, **rep_gen_func_kwargs
):
84 This method generates full SVWF (reducible) representation of the group.
86 svwfgens
= self
.svwf_rep_gen_func(lMax
, *rep_gen_func_args
, **rep_gen_func_kwargs
)
87 my
, ny
= get_mn_y(lMax
)
89 I_tyty
= np
.moveaxis(np
.eye(2)[:,:,ň
,ň
] * np
.eye(nelem
), 2,1)
90 return generate_grouprep(self
.permgroup
, I_tyty
, self
.permgroupgens
, svwfgens
, immultop
= mmult_tyty
, imcmp
= np
.allclose
)
92 def svwf_irrep_projectors(self
, lMax
, *rep_gen_func_args
, **rep_gen_func_kwargs
):
93 return gen_point_group_svwfrep_projectors(self
.permgroup
, self
.irreps
, self
.svwf_rep(lMax
, *rep_gen_func_args
, **rep_gen_func_kwargs
))
95 # alternative, for comparison and testing; should give the same results
96 def svwf_irrep_projectors2(self
, lMax
, *rep_gen_func_args
, **rep_gen_func_kwargs
):
97 return gen_point_group_svwfrep_projectors2(self
.permgroup
, self
.irreps
, self
.svwf_rep(lMax
, *rep_gen_func_args
, **rep_gen_func_kwargs
))
99 def svwf_irrep_projectors2_w_bases(self
, lMax
, *rep_gen_func_args
, **rep_gen_func_kwargs
):
100 return gen_point_group_svwfrep_projectors2_w_bases(self
.permgroup
, self
.irreps
, self
.svwf_rep(lMax
, *rep_gen_func_args
, **rep_gen_func_kwargs
))
102 def generate_c_source(self
):
104 Generates a string with a chunk of C code with a definition of a qpms_finite_group_t instance.
107 permlist
= self
.deterministic_elemlist()
108 order
= len(permlist
)
109 permindices
= {perm
: i
for i
, perm
in enumerate(permlist
)} # 'invert' permlist
110 identity
= self
.permgroup
.identity
113 s
+= ' "%s", // name\n' % self
.name
115 s
+= ' %d, // order\n' % order
117 s
+= ' %d, // idi\n' % permindices
[identity
]
119 s
+= ' (qpms_gmi_t[]) { // mt\n'
120 for i
in range(order
):
121 ss
= ', '.join([str(permindices
[permlist
[i
]*permlist
[j
]]) for j
in range(order
)])
122 s
+= ' ' + ss
+ ',\n'
125 s
+= ' (qpms_gmi_t[]) { // invi\n'
126 s
+= ' ' + ', '.join([str(permindices
[permlist
[j
]**-1]) for j
in range(order
)])
129 s
+= ' (qpms_gmi_t[]) {' + ', '.join([str(permindices
[g
]) for g
in self
.permgroupgens
]) + '}, // gens\n'
131 s
+= ' %d, // ngens\n' % len(self
.permgroupgens
)
132 # qpms_permutation_t permrep[]
133 s
+= ' (qpms_permutation_t[]){ // permrep\n'
134 for i
in range(order
):
135 s
+= ' "%s",\n' % str(permlist
[i
])
138 s
+= ' NULL, // elemlabels\n'
140 s
+= ' %d, // permrep_nelem\n' % self
.permgroup
.degree
141 # qpms_irot3_t rep3d[]
142 if self
.rep3d
is None:
143 s
+= ' NULL, // rep3d TODO!!!\n'
145 s
+= ' (qpms_irot3_t[]) { // rep3d\n'
146 for i
in range(order
):
147 s
+= ' ' + self
.rep3d
[permlist
[i
]].crepr() + ',\n'
150 s
+= ' %d, // nirreps\n' % len(self
.irreps
)
151 # struct qpms_finite_grep_irrep_t irreps[]
152 s
+= ' (struct qpms_finite_group_irrep_t[]) { // irreps\n'
153 for irname
in sorted(self
.irreps
.keys()):
154 irrep
= self
.irreps
[irname
]
156 is1d
= isinstance(irrep
[identity
], (int, float, complex))
157 dim
= 1 if is1d
else irrep
[identity
].shape
[0]
159 s
+= ' %d, // dim\n' % dim
161 s
+= ' "%s", //name\n' % re
.escape(irname
)
165 s
+= ' (complex double []) {' + ', '.join([str(irrep
[permlist
[i
]]) for i
in range(order
)]) + '} // m\n'
167 s
+= ' (complex double []) {\n'
168 for i
in range(order
):
169 s
+= ' // %s\n' % str(permlist
[i
])
170 for row
in range(dim
):
172 for col
in range(dim
):
173 s
+= '%s, ' % re
.sub('j', '*I', str(irrep
[permlist
[i
]][row
,col
]))
175 mat
= irrep
[permlist
[i
]]
178 #s += ' %d, // dim\n' %
180 s
+= ' } // end of irreps\n'
184 # srcgroup is expected to be PermutationGroup and srcgens of the TODO
185 # imcmp returns True if two elements of the image group are 'equal', otherwise False
186 def generate_grouprep(srcgroup
, im_identity
, srcgens
, imgens
, immultop
= None, imcmp
= None):
190 raise ValueError('All the generators must have the same "size"')
192 grouprep_try(tdict
, Permutation(sz
-1), im_identity
, srcgens
, imgens
, immultop
= immultop
, imcmp
= imcmp
)
193 if(srcgroup
.order() != len(tdict
.keys())): # basic check
194 raise ValueError('The supplied "generators" failed to generate the preimage group: ',
195 srcgroup
.order(), " != ", len(tdict
.keys()))
198 # matrices appearing in 2d representations of common groups as used in Bradley, Cracknell p. 61 (with arabic names instead of greek, because lambda is a keyword)
200 alif
= np
.array(((-1/2,-s3long
/2),(s3long
/2,-1/2)))
201 bih
= np
.array(((-1/2,s3long
/2),(-s3long
/2,-1/2)))
202 kaf
= np
.array(((0,1),(1,0)))
203 lam
= np
.array(((1,0),(0,-1)))
204 ra
= np
.array(((0,-1),(1,0)))
205 mim
= np
.array(((-1/2,-s3long
/2),(-s3long
/2,1/2)))
206 nun
= np
.array(((-1/2,s3long
/2),(s3long
/2,1/2)))
211 def mmult_tyty(a
, b
):
212 return(apply_ndmatrix_left(a
, b
, (-4,-3)))
213 def mmult_ptypty(a
, b
):
214 return(apply_ndmatrix_left(a
, b
, (-6,-5,-4)))
216 def gen_point_group_svwfrep_irreps(permgroup
, matrix_irreps_dict
, sphrep_full
):
218 Gives the projection operators $P_kl('\Gamma')$ from Dresselhaus (4.28)
219 for all irreps $\Gamma$ of D3h.;
220 as an array with indices [k,l,t,y,t,y]
222 Example of creating last argument:
223 sphrep_full = generate_grouprep(D3h_permgroup, I_tyty, D3h_srcgens, [C3_tyty, vfl_tyty, zfl_tyty],
224 immultop = mmult_tyty, imcmp = np.allclose)
226 order
= permgroup
.order()
228 nelem
= sphrep_full
[permgroup
[0]].shape
[-1] # quite ugly hack
229 for repkey
, matrixrep
in matrix_irreps_dict
.items():
230 arepmatrix
= matrixrep
[permgroup
[0]] # just one of the matrices to get the shape etc
231 if isinstance(arepmatrix
, numbers
.Number
):
232 dim
= 1 # repre dimension
233 preprocess
= lambda x
: np
.array([[x
]])
234 elif isinstance(arepmatrix
, np
.ndarray
):
235 if(len(arepmatrix
.shape
)) != 2 or arepmatrix
.shape
[0] != arepmatrix
.shape
[1]:
236 raise ValueError("Arrays representing irrep matrices must be of square shape")
237 dim
= arepmatrix
.shape
[0]
238 preprocess
= lambda x
: x
240 raise ValueError("Irrep is not a square array or number")
241 sphrep
= np
.zeros((dim
,dim
,2,nelem
,2,nelem
), dtype
=complex)
242 for i
in permgroup
.elements
:
243 sphrep
+= preprocess(matrixrep
[i
]).conj().transpose()[:,:,ň
,ň
,ň
,ň
] * sphrep_full
[i
]
244 sphrep
*= dim
/ order
245 # clean the nonexact values here
246 for x
in [0, 0.5, -0.5, 0.5j
, -0.5j
]:
247 sphrep
[np
.isclose(sphrep
,x
)]=x
248 sphreps
[repkey
] = sphrep
252 def gen_point_group_svwfrep_projectors(permgroup
, matrix_irreps_dict
, sphrep_full
):
254 The same as gen_point_group_svwfrep_irreps, but summed over the kl diagonal, so
255 one gets single projector onto each irrep space and the arrays have indices
259 for repi
, W
in gen_point_group_svwfrep_irreps(permgroup
, matrix_irreps_dict
, sphrep_full
).items():
262 mat
= np
.reshape(W
, W
.shape
[-4:])
264 mat
= np
.zeros(W
.shape
[-4:], dtype
=complex) # TODO the result should be real — check!
265 for d
in range(irrepd
):
267 if not np
.allclose(mat
.imag
, 0):
268 raise ValueError("The imaginary part of the resulting projector should be zero, damn!")
270 summedprojs
[repi
] = mat
.real
274 def gen_point_group_svwfrep_projectors2_w_bases(permgroup
, matrix_irreps_dict
, sphrep_full
):
275 return gen_point_group_svwfrep_projectors2(permgroup
, matrix_irreps_dict
, sphrep_full
, do_bases
= True)
277 def gen_point_group_svwfrep_projectors2(permgroup
, matrix_irreps_dict
, sphrep_full
, do_bases
= False):
279 an approach as in gen_hexlattice_Kpoint_svwf_rep_projectors; for comparison and testing
284 for repi
, W
in gen_point_group_svwfrep_irreps(permgroup
, matrix_irreps_dict
, sphrep_full
).items():
285 nelem
= W
.shape
[-1] # however, this should change between iterations
289 for y
in range(nelem
):
290 for ai
in range(W
.shape
[0]):
291 for bi
in range(W
.shape
[1]):
292 v
= np
.zeros((2, nelem
))
294 v1
= np
.tensordot(W
[ai
,bi
], v
, axes
= ([-2,-1],[0,1]))
296 if not np
.allclose(v1
,0):
299 dot
= np
.tensordot(v1
.conjugate(),v2
, axes
=([-2,-1],[0,1]))
300 if not (np
.allclose(dot
,0)):
301 if not np
.allclose(np
.abs(dot
),1):
302 raise ValueError('You have to fix this piece of code.')
307 theprojector
= np
.zeros((2,nelem
, 2, nelem
), dtype
= float)
309 thebasis
= np
.zeros((len(tmplist
), 2, nelem
), dtype
=complex)
310 for i
, v
in enumerate(tmplist
):
312 bases
[repi
] = thebasis
314 theprojector
+= (v
[:,:,ň
,ň
] * v
.conjugate()[ň
,ň
,:,:]).real
315 for x
in [0, 1, -1, sqrt(.5), -sqrt(.5), .5, -.5]:
316 theprojector
[np
.isclose(theprojector
,x
)] = x
317 projectors
[repi
] = theprojector
319 return projectors
, bases
324 # Group D3h; mostly legacy code (kept because of the the honeycomb lattice K-point code, whose generalised version not yet implemented)
325 # Note that the size argument of permutations is necessary, otherwise e.g. c*c and b*b would not be evaluated equal
326 # N.B. the weird elements as Permutation(N) – it means identity permutation of size N+1.
327 rot3_perm
= Permutation(0,1,2, size
=5) # C3 rotation
328 xflip_perm
= Permutation(0,2, size
=5) # vertical mirror
329 zflip_perm
= Permutation(3,4, size
=5) # horizontal mirror
330 D3h_srcgens
= [rot3_perm
,xflip_perm
,zflip_perm
]
331 D3h_permgroup
= PermutationGroup(*D3h_srcgens
) # D3h
334 # Bradley, Cracknell p. 61
335 "E'" : generate_grouprep(D3h_permgroup
, epsilon
, D3h_srcgens
, [alif
, lam
, epsilon
], immultop
= np
.dot
, imcmp
= np
.allclose
),
336 "E''" : generate_grouprep(D3h_permgroup
, epsilon
, D3h_srcgens
, [alif
, lam
, -epsilon
], immultop
= np
.dot
, imcmp
= np
.allclose
),
337 # Bradley, Cracknell p. 59, or Dresselhaus, Table A.14 (p. 482)
338 "A1'" : generate_grouprep(D3h_permgroup
, 1, D3h_srcgens
, [1,1,1]),
339 "A2'" : generate_grouprep(D3h_permgroup
, 1, D3h_srcgens
, [1,-1,1]),
340 "A1''" : generate_grouprep(D3h_permgroup
, 1, D3h_srcgens
, [1,-1,-1]),
341 "A2''" : generate_grouprep(D3h_permgroup
, 1, D3h_srcgens
, [1,1,-1]),
344 #TODO lepší název fce; legacy, use group_info['D3h'].generate_grouprep() instead
345 def gen_point_D3h_svwf_rep(lMax
, vflip
= 'x'):
347 Gives the projection operators $P_kl('\Gamma')$ from Dresselhaus (4.28)
348 for all irreps $\Gamma$ of D3h.;
349 as an array with indices [k,l,t,y,t,y]
352 my
, ny
= get_mn_y(lMax
)
354 C3_yy
= WignerD_yy_fromvector(lMax
, np
.array([0,0,2*pi
/3]))
355 C3_tyty
= np
.moveaxis(np
.eye(2)[:,:,ň
,ň
] * C3_yy
, 2,1)
356 zfl_tyty
= zflip_tyty(lMax
)
357 #yfl_tyty = yflip_tyty(lMax)
358 #xfl_tyty = xflip_tyty(lMax)
359 vfl_tyty
= yflip_tyty(lMax
) if vflip
== 'y' else xflip_tyty(lMax
)
360 I_tyty
= np
.moveaxis(np
.eye(2)[:,:,ň
,ň
] * np
.eye(nelem
), 2,1)
361 order
= D3h_permgroup
.order()
362 sphrep_full
= generate_grouprep(D3h_permgroup
, I_tyty
, D3h_srcgens
, [C3_tyty
, vfl_tyty
, zfl_tyty
],
363 immultop
= mmult_tyty
, imcmp
= np
.allclose
)
365 for repkey
, matrixrep
in D3h_irreps
.items():
366 arepmatrix
= matrixrep
[rot3_perm
] # just one of the matrices to get the shape etc
367 if isinstance(arepmatrix
, numbers
.Number
):
368 dim
= 1 # repre dimension
369 preprocess
= lambda x
: np
.array([[x
]])
370 elif isinstance(arepmatrix
, np
.ndarray
):
371 if(len(arepmatrix
.shape
)) != 2 or arepmatrix
.shape
[0] != arepmatrix
.shape
[1]:
372 raise ValueError("Arrays representing irrep matrices must be of square shape")
373 dim
= arepmatrix
.shape
[0]
374 preprocess
= lambda x
: x
376 raise ValueError("Irrep is not a square array or number")
377 sphrep
= np
.zeros((dim
,dim
,2,nelem
,2,nelem
), dtype
=complex)
378 for i
in D3h_permgroup
.elements
:
379 sphrep
+= preprocess(matrixrep
[i
]).conj().transpose()[:,:,ň
,ň
,ň
,ň
] * sphrep_full
[i
]
380 sphrep
*= dim
/ order
381 # clean the nonexact values here
382 for x
in [0, 0.5, -0.5, 0.5j
, -0.5j
]:
383 sphrep
[np
.isclose(sphrep
,x
)]=x
384 sphreps
[repkey
] = sphrep
387 def gen_hexlattice_Kpoint_svwf_rep(lMax
, psi
, vflip
= 'x'):
388 my
, ny
= get_mn_y(lMax
)
390 C3_yy
= WignerD_yy_fromvector(lMax
, np
.array([0,0,2*pi
/3]))
391 C3_tyty
= np
.moveaxis(np
.eye(2)[:,:,ň
,ň
] * C3_yy
, 2,1)
392 zfl_tyty
= zflip_tyty(lMax
)
393 #yfl_tyty = yflip_tyty(lMax)
394 #xfl_tyty = xflip_tyty(lMax)
395 vfl_tyty
= yflip_tyty(lMax
) if vflip
== 'y' else xflip_tyty(lMax
)
396 I_tyty
= np
.moveaxis(np
.eye(2)[:,:,ň
,ň
] * np
.eye(nelem
), 2,1)
397 hex_C3_K_ptypty
= np
.diag([exp(-psi
*1j
*2*pi
/3),exp(+psi
*1j
*2*pi
/3)])[:,ň
,ň
,:,ň
,ň
] * C3_tyty
[ň
,:,:,ň
,:,:]
398 hex_zfl_ptypty
= np
.eye(2)[:,ň
,ň
,:,ň
,ň
] * zfl_tyty
[ň
,:,:,ň
,:,:]
399 #hex_xfl_ptypty = np.array([[0,1],[1,0]])[:,ň,ň,:,ň,ň] * xfl_tyty[ň,:,:,ň,:,:]
400 hex_vfl_ptypty
= np
.array([[0,1],[1,0]])[:,ň
,ň
,:,ň
,ň
] * vfl_tyty
[ň
,:,:,ň
,:,:]
401 hex_I_ptypty
= np
.eye((2*2*nelem
)).reshape((2,2,nelem
,2,2,nelem
))
402 order
= D3h_permgroup
.order()
403 hex_K_sphrep_full
= generate_grouprep(D3h_permgroup
, hex_I_ptypty
, D3h_srcgens
, [hex_C3_K_ptypty
, hex_vfl_ptypty
, hex_zfl_ptypty
],
404 immultop
= mmult_ptypty
, imcmp
= np
.allclose
)
405 hex_K_sphreps
= dict()
406 for repkey
, matrixrep
in D3h_irreps
.items():
407 arepmatrix
= matrixrep
[rot3_perm
] # just one of the matrices to get the shape etc
408 if isinstance(arepmatrix
, numbers
.Number
):
409 dim
= 1 # repre dimension
410 preprocess
= lambda x
: np
.array([[x
]])
411 elif isinstance(arepmatrix
, np
.ndarray
):
412 if(len(arepmatrix
.shape
)) != 2 or arepmatrix
.shape
[0] != arepmatrix
.shape
[1]:
413 raise ValueError("Arrays representing irrep matrices must be of square shape")
414 dim
= arepmatrix
.shape
[0]
415 preprocess
= lambda x
: x
417 raise ValueError("Irrep is not a square array or number")
418 sphrep
= np
.zeros((dim
,dim
,2,2,nelem
,2,2,nelem
), dtype
=complex)
419 for i
in D3h_permgroup
.elements
:
420 sphrep
+= preprocess(matrixrep
[i
]).conj().transpose()[:,:,ň
,ň
,ň
,ň
,ň
,ň
] * hex_K_sphrep_full
[i
]
421 sphrep
*= dim
/ order
422 # clean the nonexact values here
423 for x
in [0, 0.5, -0.5, 0.5j
, -0.5j
]:
424 sphrep
[np
.isclose(sphrep
,x
)]=x
425 hex_K_sphreps
[repkey
] = sphrep
429 norm
= np
.linalg
.norm(v
.reshape((np
.prod(v
.shape
),)), ord=2)
434 def gen_hexlattice_Kpoint_svwf_rep_projectors(lMax
, psi
, vflip
='x', do_bases
=False):
435 nelem
= lMax
* (lMax
+2)
439 for repi
, W
in gen_hexlattice_Kpoint_svwf_rep(lMax
,psi
,vflip
=vflip
).items():
444 for y
in range(nelem
):
445 for ai
in range(W
.shape
[0]):
446 for bi
in range(W
.shape
[1]):
447 v
= np
.zeros((2,2,nelem
))
449 #v = np.ones((2,2,nelem))
450 v1
= np
.tensordot(W
[ai
,bi
],v
, axes
= ([-3,-2,-1],[0,1,2]))
453 if not np
.allclose(v1
,0):
456 dot
= np
.tensordot(v1
.conjugate(),v2
,axes
= ([-3,-2,-1],[0,1,2]))
457 if not np
.allclose(dot
,0):
458 if not np
.allclose(np
.abs(dot
),1):
459 raise ValueError('You have to fix this piece of code.')# TODO maybe I should make sure that the absolute value is around 1
464 #for index, x in np.ndenumerate(v1):
468 theprojector
= np
.zeros((2,2,nelem
,2,2,nelem
), dtype
= float)
470 thebasis
= np
.zeros((len(tmplist
), 2,2,nelem
), dtype
=complex)
471 for i
, v
in enumerate(tmplist
):
473 bases
[repi
] = thebasis
475 theprojector
+= (v
[:,:,:,ň
,ň
,ň
] * v
.conjugate()[ň
,ň
,ň
,:,:,:]).real
# TODO check is it possible to have imaginary elements?
476 for x
in [0, 1, -1,sqrt(0.5),-sqrt(0.5),0.5,-0.5]:
477 theprojector
[np
.isclose(theprojector
,x
)]=x
478 projectors
[repi
] = theprojector
480 return projectors
, bases
486 point_group_info
= { # representation info of some useful point groups
487 # TODO real trivial without generators
488 'trivial_g' : SVWFPointGroupInfo('trivial_g',
489 # permutation group generators
490 ( # I put here the at least the identity for now (it is reduntant, but some functions are not robust enough to have an empty set of generators
493 # dictionary with irrep generators
497 # function that generates a tuple with svwf representation generators
498 lambda lMax
: (identity_tyty(lMax
),),
499 # quaternion rep generators
504 'C2' : SVWFPointGroupInfo('C2',
505 # permutation group generators
506 (Permutation(0,1), # 180 deg rotation around z axis
508 # dictionary with irrep generators
510 # Bradley, Cracknell p. 57;
514 # function that generates a tuple with svwf representation generators
515 lambda lMax
: (zrotN_tyty(2, lMax
),),
516 # quaternion rep generators
522 'C2v' : SVWFPointGroupInfo('C2v',
523 # permutation group generators
524 (Permutation(0,1, size
=4)(2,3), # x -> - x mirror operation (i.e. yz mirror plane)
525 Permutation(0,3, size
=4)(1,2), # y -> - y mirror operation (i.e. xz mirror plane)
527 # dictionary with irrep generators
529 # Bradley, Cracknell p. 58; not sure about the labels / axes here
535 # function that generates a tuple with svwf representation generators
536 lambda lMax
: (xflip_tyty(lMax
), yflip_tyty(lMax
)),
537 # quaternion rep generators
544 'D2h' : SVWFPointGroupInfo('D2h',
545 # permutation group generators
546 (Permutation(0,1, size
=6)(2,3), # x -> - x mirror operation (i.e. yz mirror plane)
547 Permutation(0,3, size
=6)(1,2), # y -> - y mirror operation (i.e. xz mirror plane)
548 # ^^^ btw, I guess that Permutation(0,1, size=6) and Permutation(2,3, size=6) would
549 # do exactly the same job (they should; CHECK)
550 Permutation(4,5, size
=6) # z -> - z mirror operation (i.e. xy mirror plane)
552 # dictionary with irrep generators
554 # Product of C2v and zflip; not sure about the labels / axes here
564 # function that generates a tuple with svwf representation generators
565 lambda lMax
: (xflip_tyty(lMax
), yflip_tyty(lMax
), zflip_tyty(lMax
)),
566 # quaternion rep generators
573 'C4' : SVWFPointGroupInfo('C4',
574 # permutation group generators
575 (Permutation(0,1,2,3, size
=4),), #C4 rotation
576 # dictionary with irrep generators
578 # Bradley, Cracknell p. 58
584 # function that generates a tuple with svwf representation generators
585 lambda lMax
: (zrotN_tyty(4, lMax
), ),
586 # quaternion rep generators
591 'C4v' : SVWFPointGroupInfo('C4v',
592 # permutation group generators
593 (Permutation(0,1,2,3, size
=4), #C4 rotation
594 Permutation(0,1, size
=4)(2,3)), # x -> - x mirror operation (i.e. yz mirror plane)
595 # dictionary with irrep generators
597 # Bradley, Cracknell p. 62
599 # Bradley, Cracknell p. 59, or Dresselhaus, Table A.18
605 # function that generates a tuple with svwf representation generators
606 lambda lMax
: (zrotN_tyty(4, lMax
), xflip_tyty(lMax
)),
607 # quaternion rep generators
613 'D4h' : SVWFPointGroupInfo('D4h',
614 # permutation group generators
615 (Permutation(0,1,2,3, size
=6), # C4 rotation
616 Permutation(0,1, size
=6)(2,3), # x -> - x mirror operation (i.e. yz mirror plane)
617 Permutation(4,5, size
=6), # horizontal mirror operation z -> -z (i.e. xy mirror plane)
619 # dictionary with irrep generators
620 { # product of C4v and zflip
621 "E'": (ra
, -lam
, epsilon
),
622 "E''":(ra
, -lam
, -epsilon
),
632 # function that generates a tuple with svwf representation generators
633 lambda lMax
: (zrotN_tyty(4, lMax
), xflip_tyty(lMax
), zflip_tyty(lMax
)),
634 # quaternion rep generators
641 'D3h' : SVWFPointGroupInfo('D3h',
642 # permutation group generators
643 ( Permutation(0,1,2, size
=5), # C3 rotation
644 Permutation(0,2, size
=5), # vertical mirror
645 Permutation(3,4, size
=5), # horizontal mirror z -> -z (i.e. xy mirror plane)
647 # dictionary with irrep generators
648 { # Bradley, Cracknell p. 61
649 "E'" : (alif
, lam
, epsilon
),
650 "E''" : (alif
, lam
, -epsilon
),
651 # Bradley, Cracknell p. 59, or Dresselhaus, Table A.14 (p. 482)
657 # function that generates a tuple with svwf representation generators
658 lambda lMax
, vflip
: (zrotN_tyty(3, lMax
), yflip_tyty(lMax
) if vflip
== 'y' else xflip_tyty(lMax
), zflip_tyty(lMax
)),
659 # quaternion rep generators
662 IRot3
.xflip(), # if vflip == 'y' else IRot3.xflip(), # FIXME enable to choose
666 'x_and_z_flip': SVWFPointGroupInfo(
669 Permutation(0,1, size
=4), # x -> -x mirror op
670 Permutation(2,3, size
=4), # z -> -z mirror op
678 lambda lMax
: (xflip_tyty(lMax
), zflip_tyty(lMax
)),
685 'y_and_z_flip': SVWFPointGroupInfo(
688 Permutation(0,1, size
=4), # y -> -y mirror op
689 Permutation(2,3, size
=4), # z -> -z mirror op
697 lambda lMax
: (yflip_tyty(lMax
), zflip_tyty(lMax
)),