sign convention in double group representations
My question here is if there's a way to keep track weather the symmetry element is a barred or unbarred symmetry operation of the double group. It seems that you have been working on a similar topic within the pg_representations branch. So, this might be related.
One possible approach is to add an extra property to point group objects labeling if they are barred or unbarred operations and keep track of this at each multiplication in generate_group
. Ideally, it would be interesting if generate_group
could return only the unbarred operations. For instance, a mirror operation could be defined as
U = np.kron(-expm(-1j*np.pi*sy/2), -sy)
My = qsymm.mirror([0,1], U=U, barred=False)
Ebar = My * My # should return the barred identity
Why it is important?
(important for me, at least)
For the theory of invariants this sign issue is irrelevant, since all operations involve U
twice, as in U @ H @ U.T = H
, and the overall sign of U
sign cancels. But the basis transformation proposed in Mozrzymas, J. Phys. A: Math. Theor. 47, 505203 (2014) requires a product of the representations in the original and desired basis (see their Eqs. 3.15 and 3.16). So, it seems important to avoid ambiguities that might mix a barred representation in one basis and a unbarred in another basis, which would make the sum in the coefficient r_ab wrong.
Details
I'm using qsymm generate_group
to build the group elements from its generators, and I've notice that there's no control if the symmetry element represent a barred or unbarred double group operation. For instance, the following code gives True for A == B
, even though their matrices have different signs.
import qsymm
A = qsymm.identity(2, 4)
B = qsymm.identity(2, 4)
B.U = -B.U
print('A == B?', A == B)
print('A:', A.U)
print('B:', B.U)
This becomes an issue when I use the generate_group
routine. In the following example for graphene, G1
is built from the generators (C3, My)
, while G2
is built manually for all 6 unbarred symmetry operations (Um, C3, My, C3b, Mya, Myb)
. I would expect G1
to be the same as G2
, but while G2
has only unbarred operators, G1
has a mixture of barred and unbarred operators. Particularly, the identity differs as illustrated above.
import numpy as np
import qsymm
from scipy.linalg import expm
# Pauli matrices (auxiliar)
s0 = np.array([[1, 0],[0, 1]])
sx = np.array([[0, 1],[1, 0]])
sy = np.array([[0, -1j],[1j, 0]])
sz = np.array([[1, 0],[0, -1]])
phi = 2*np.pi/3
U = np.kron(expm(-1j*phi*sz/2), s0*np.cos(+phi)-1j*sz*np.sin(+phi))
C3 = qsymm.rotation(1/3, U=U)
U = np.kron(expm(+1j*phi*sz/2), s0*np.cos(-phi)-1j*sz*np.sin(-phi))
C3b = qsymm.rotation(-1/3, U=U)
U = np.kron(-expm(-1j*np.pi*sy/2), -sy)
My = qsymm.mirror([0,1], U=U)
s = -np.sin(phi)*sx - np.cos(phi)*sy
U = np.array([[0, 1j*np.exp(-1j*phi)], [-1j*np.exp(1j*phi), 0]])
U = np.kron(-expm(-1j*np.pi*s/2), U)
Mya = qsymm.mirror([-np.sin(phi), -np.cos(phi)], U=U)
s = -np.sin(phi)*sx + np.cos(phi)*sy
U = np.array([[0, 1j*np.exp(1j*phi)], [-1j*np.exp(-1j*phi), 0]])
U = np.kron(-expm(-1j*np.pi*s/2), U)
Myb = qsymm.mirror([-np.sin(phi), +np.cos(phi)], U=U)
Um = qsymm.identity(2, 4)
G1 = list(qsymm.groups.generate_group([C3, My]))
G2 = list(qsymm.groups.generate_group([Um, C3, My, C3b, Mya, Myb]))
print('Group size:', len(G1), len(G2))
for i in range(len(G1)):
if G1[i] == Um:
print('Matrix rep of identity in G1')
print(G1[i].U)
if G2[i] == Um:
print('Matrix rep of identity in G2')
print(G2[i].U)
Notice that both cases return groups of length 6, but the double group should have 12 elements here. Essentially, the code does not account for the sign difference.