def check_orthogonalities(self):
     # check row orthogonality
     check1 = np.zeros((self.nclasses, self.nclasses), dtype=complex)
     for i in range(self.nclasses):
         for j in range(self.nclasses):
             res = 0.
             for k in range(self.nclasses):
                 res += self.tchar[i,
                                   k] * self.tchar[j,
                                                   k].conj() * self.cdim[k]
             check1[i, j] = res
     tmp = self.order * np.identity(self.nclasses)
     t1 = utils._eq(check1, tmp)
     # check column orthogonality
     check2 = np.zeros((self.nclasses, self.nclasses), dtype=complex)
     for i in range(self.nclasses):
         for j in range(self.nclasses):
             res = 0.
             for k in range(self.nclasses):
                 res += self.tchar[k, i] * self.tchar[k, j].conj()
             check2[i, j] = res
     tmp = np.diag(
         np.ones((self.nclasses, )) * self.order / np.asarray(self.cdim))
     t2 = utils._eq(check2, tmp)
     return t1, t2
Exemple #2
0
 def check_coset(self, pref, p, coset):
     res = []
     for elem in coset:
         rot = _all_rotations[elem]
         rvec = rot.rot_vector(pref)
         c1 = utils._eq(rvec, p)
         c2 = utils._eq(rvec, -p)
         if c1 or c2:
             res.append(True)
         else:
             res.append(False)
     return res
 def is_faithful(self):
     # check if complete
     self.faithful = True
     checksum = np.ones((self.order, )) * np.sum(self.lelements)
     u, ind = np.unique(self.tmult, return_index=True)
     if len(u) != self.order:
         self.faithful = False
     tmp = np.sum(self.tmult_global, axis=0)
     if not utils._eq(tmp, checksum):
         self.faithful = False
     tmp = np.sum(self.tmult_global, axis=1)
     if not utils._eq(tmp, checksum):
         self.faithful = False
Exemple #4
0
 def sort_momenta(self):
     # check if cosets exists
     if self.coset1 is None or self.coset2 is None:
         self.smomenta1 = None
         self.smomenta2 = None
         return
     # search for conjugacy class so that
     # R*p_ref = p
     res1 = []
     res2 = []
     for p, p1, p2 in self.allmomenta:
         #print("momentum coset search")
         done = False
         # check if already in list
         for r in res1:
             if utils._eq(r[0], p1):
                 done = True
                 break
         # if not get coset
         if not done:
             #print("%r not in list" % p1)
             for i, c in enumerate(self.coset1):
                 t = self.check_coset(self.pref1, p1, c)
                 #print(t)
                 if np.all(t):
                     #print(" in coset %d" %i)
                     res1.append((p1, i))
                     break
                 #else:
                 #    print(" not in coset %d" %i)
         #else:
         #    print("%r already in list" % p1)
         done = False
         # check if already in list
         for r in res2:
             if utils._eq(r[0], p2):
                 done = True
                 break
         if not done:
             for i, c in enumerate(self.coset2):
                 t = self.check_coset(self.pref2, p2, c)
                 if np.all(t):
                     res2.append((p2, i))
                     break
     self.smomenta1 = res1
     if len(self.smomenta1) != len(self.momenta1):
         print("some vectors not sorted")
     self.smomenta2 = res2
     if len(self.smomenta2) != len(self.momenta2):
         print("some vectors not sorted")
 def check_all_cosets(self, p, p1, p2):
     j1, j2 = None, None
     for m, j in self.smomenta1:
         if utils._eq(p1, m):
             j1 = j
             break
     if j1 is None:
         print("j1 is None")
     for m, j in self.smomenta2:
         if utils._eq(p2, m):
             j2 = j
             break
     if j2 is None:
         print("j2 is None")
     return j1, j2
    def gen_momenta(self, pm=4):
        print("pm=%d" % pm)

        # pm: maximum component in each direction
        def _abs(x):
            return np.vdot(x, x) <= pm

        def _abs1(x, a):
            return np.vdot(x, x) == a

        gen = it.ifilter(_abs, it.product(range(-pm, pm + 1), repeat=3))
        lp3 = [np.asarray(y, dtype=int) for y in gen]
        self.momenta = [
            self._U.dot(y) for y in it.ifilter(lambda x: _abs1(x, self.p), lp3)
        ]
        self.momenta1 = [
            self._U.dot(y)
            for y in it.ifilter(lambda x: _abs1(x, self.p1), lp3)
        ]
        self.momenta2 = [
            self._U.dot(y)
            for y in it.ifilter(lambda x: _abs1(x, self.p2), lp3)
        ]
        # check allowed momentum combinations
        self.allmomenta = []
        for p in self.momenta:
            for p1 in self.momenta1:
                for p2 in self.momenta2:
                    if utils._eq(p1 + p2 - p):
                        self.allmomenta.append((p, p1, p2))
        if not self.allmomenta:
            raise RuntimeError("no valid momentum combination found")
Exemple #7
0
    def get_all_ops(self, jmax):
        res = []
        ind = []
        srange = self.s1+self.s2+1
        _s1, _s2 = int(2*self.s1+1), int(2*self.s2+1)
        for j in range(jmax):
            jmult = int(2*j+1)
            for mj in range(jmult):
                for s in range(srange):
                    for l in range(j+srange):
                        c = self.calc_op(j, mj, l, s)
                        if utils._eq(c):
                            continue
                        # orthonormalize to previos vectors
                        for m1, m2 in it.product(range(_s1), range(_s2)):
                            _c = c[:,m1,m2]
                            n = np.sqrt(np.vdot(_c, _c))
                            if n < self.prec:
                                continue
                            #_c /= n
                            #for old, oldi in zip(res, ind):
                            #    #if oldi[0] != j:
                            #    #    continue
                            #    _c = utils.gram_schmidt(_c, old)
                            #    n = np.sqrt(np.vdot(_c, _c))
                            #    if n < self.prec:
                            #        break
                            #if n < self.prec:
                            #    continue
                            res.append(_c.copy())
                            ind.append([j,mj-j,l,s,m1-self.s1,m2-self.s2])

        res = np.asarray(res)
        ind = np.asarray(ind)
        return res, ind
Exemple #8
0
 def check_all_cosets(self, p, p1, p2):
     j1, j2 = None, None
     i1, i2 = None, None
     for m, j in self.smomenta1:
         if utils._eq(p1, m):
             j1 = j
             break
     for m, j in self.smomenta2:
         if utils._eq(p2, m):
             j2 = j
             break
     for m, k1, k2 in self.i1i2:
         if utils._eq(p, m):
             i1, i2 = k1, k2
             break
     return j1, j2, i1, i2
Exemple #9
0
    def gen_momenta(self):
        pm = 4  # maximum component in each direction

        def _abs(x):
            return np.dot(x, x) <= pm

        def _abs1(x, a):
            return np.dot(x, x) == a

        gen = it.ifilter(_abs, it.product(range(-pm, pm + 1), repeat=3))
        lp3 = [np.asarray(y, dtype=int) for y in gen]
        self.momenta = [y for y in it.ifilter(lambda x: _abs1(x, self.p), lp3)]
        self.momenta1 = [
            y for y in it.ifilter(lambda x: _abs1(x, self.p1), lp3)
        ]
        self.momenta2 = [
            y for y in it.ifilter(lambda x: _abs1(x, self.p2), lp3)
        ]

        self.allmomenta = []
        # only save allowed momenta combinations
        for p in self.momenta:
            for p1 in self.momenta1:
                for p2 in self.momenta2:
                    if utils._eq(p1 + p2 - p):
                        self.allmomenta.append((p, p1, p2))
    def select_elements(self):
        # self.elements contains the quaternions
        # self.lelements contains the "global" (unique) index of the element,
        # making the elements comparable between different groups
        self.elements = []
        self.lelements = []
        # all possible elements for the double cover octahedral group

        # all elements of O
        for i, el in enumerate(quat.qPar):
            self.elements.append(quat.QNew.create_from_vector(el, 1))
            self.lelements.append(i)
        # all elements of O with inversion
        if self.withinversion:
            for i, el in enumerate(quat.qPar):
                self.elements.append(quat.QNew.create_from_vector(el, -1))
                self.lelements.append(i + 24)
        # all elements in the double cover of O
        for i, el in enumerate(quat.qPar):
            self.elements.append(quat.QNew.create_from_vector(-el, 1))
            self.lelements.append(i + 48)
        # all elements in the double cover of O with inversion
        if self.withinversion:
            for i, el in enumerate(quat.qPar):
                self.elements.append(quat.QNew.create_from_vector(-el, -1))
                self.lelements.append(i + 72)

        if self.pref is None:
            self.p2 = 0
        else:
            self.p2 = np.vdot(self.pref_cart, self.pref_cart)
        # select elements when pref is given
        if self.pref is not None and self.p2 > 1e-6:
            selected = []
            elem = []
            # change reference momentum to T1u basis
            bpref = self.U3.dot(self.pref)
            T1irrep = gg.genT1CMF(self.elements, inv=True, U=self.U3)

            # Go through all elements of T1 and check whether they leave pref
            # unchanged
            for mat, el, num in zip(T1irrep, self.elements, self.lelements):
                tmp = mat.dot(bpref)
                c1 = utils._eq(tmp - bpref)
                # if mat * bpref == bpref, the quaternion belongs to subgroup
                # invariant under pref and is appended
                if c1:
                    selected.append(num)
                    elem.append(el)
            if self.debug > 0:
                print("The group with P_ref = %r has %d elements:" %
                      (self.pref_cart.__str__(), len(elem)))
                tmpstr = ["%d" % x for x in selected]
                tmpstr = ", ".join(tmpstr)
                print("[%s]" % tmpstr)
            # replace self.elements with only the relevant subgroup
            self.elements = elem
            self.lelements = selected
Exemple #11
0
 def Check1(self):
     for i in range(self.nirreps):
         for j in range(self.nirreps):
             res = 0.
             for k in range(self.nclasses):
                 res += self.tchar[i, k] * self.tchar[
                     j, k].conj() * self.sclass[k]
             self.tcheck1[i, j] = res
     # check against
     tmp = self.order * np.identity(self.nclasses)
     return utils._eq(self.tcheck1, tmp)
Exemple #12
0
 def Check2(self):
     for i in range(self.nclasses):
         for j in range(self.nclasses):
             res = 0.
             for k in range(self.nirreps):
                 res += self.tchar[k, i] * self.tchar[k, j].conj()
             self.tcheck2[i, j] = res
     # check against
     tmp = np.diag(
         np.ones((self.nirreps, )) * self.order / np.asarray(self.sclass))
     return utils._eq(self.tcheck2, tmp)
Exemple #13
0
 def check_coset(g0, pref, p, coset):
     res = []
     # check needs to be done in basis of T1u
     for elem in coset:
         look = g0.lelements.index(elem)
         rvec = T1irrep.mx[look].dot(pref)
         c1 = utils._eq(rvec, p)
         if c1:
             res.append(True)
         else:
             res.append(False)
     return res
Exemple #14
0
 def calc_index(self):
     def _r1(k):
         kn = np.vdot(k, k)
         if kn < self.prec or self.p1 == 0:
             return 0., 0.
         theta = np.arccos(k[2]/kn)
         phi = np.arctan2(k[1], k[0])
         return theta, phi
     #self.rot_index = np.zeros((1, self.elength), dtype=int)
     self.angles = np.zeros((self.mlength, self.elength, 2))
     self.rot_index = np.zeros((self.mlength, self.elength), dtype=int)
     # use the T1u irrep for the rotations, change to non-symmetric
     # spherical harmonics base
     s = 1./np.sqrt(2.)
     U = np.asarray([[0,-1.j,0],[0,0,1],[-1,0,0]])
     Ui = U.conj().T
     rot = gen.genT1CMF(self.elements, inv=True)
     lpref = [[0,0,0],[0,0,1],[1,1,0],[1,1,1]]
     pref = np.asarray(lpref[self.p1])
     for i, q in enumerate(rot):
         #_p1 = Ui.dot(q.dot(U.dot(pref))).real
         #theta, phi = _r1(_p1)
         #for l, (_k, k1, k2) in enumerate(self.allmomenta):
         #    if utils._eq(_p1, k1):
         #        self.rot_index[0,i] = l
         #        self.angles[l] = np.asarray([theta,phi])
         #        break
         for j, (_p, _p1, _p2) in enumerate(self.allmomenta):
             p = Ui.dot(q.dot(U.dot(_p)))
             p1 = Ui.dot(q.dot(U.dot(_p1))).real
             ang = _r1(p1)
             p2 = Ui.dot(q.dot(U.dot(_p2)))
             if not utils._eq(_p1+_p2-_p):
                 raise RuntimeError("some rotation does not conserve momentum!")
             for l, (_k, _k1, _k2) in enumerate(self.allmomenta):
                 if utils._eq(p1, _k1) and utils._eq(p2, _k2):
                     self.rot_index[j,i] = l
                     self.angles[j,i] = np.asarray(ang)
                     break
 def characters(self, representatives):
     if self.mx is None:
         return np.nan
     elif ((self.char is not None) and (self.rep is not None)
           and (utils._eq(self.rep, representatives))):
         return self.char
     else:
         char = np.zeros((len(representatives), ), dtype=complex)
         for i, r in enumerate(representatives):
             char[i] = np.trace(self.mx[r])
         self.char = char
         self.rep = representatives
         return char
 def select_elements(self):
     # self.elements contains the quaternions
     # self.lelements contains the "global" (unique) index of the element,
     # making the elements comparable between different groups
     self.elements = []
     self.lelements = []
     # all possible elements for the double cover octahedral group
     for i, el in enumerate(quat.qPar):
         self.elements.append(quat.QNew.create_from_vector(el, 1))
         self.lelements.append(i)
     if self.withinversion:
         for i, el in enumerate(quat.qPar):
             self.elements.append(quat.QNew.create_from_vector(el, -1))
             self.lelements.append(i + 24)
     for i, el in enumerate(quat.qPar):
         self.elements.append(quat.QNew.create_from_vector(-el, 1))
         self.lelements.append(i + 48)
     if self.withinversion:
         for i, el in enumerate(quat.qPar):
             self.elements.append(quat.QNew.create_from_vector(-el, -1))
             self.lelements.append(i + 72)
     if self.pref is None:
         self.p2 = 0
     else:
         self.p2 = np.vdot(self.pref_cart, self.pref_cart)
     # select elements when pref is given
     if self.pref is not None and self.p2 > 1e-6:
         selected = []
         elem = []
         # change reference momentum to T1u basis
         bpref = self.U3.dot(self.pref)
         T1irrep = gg.genT1CMF(self.elements, inv=True, U=self.U3)
         #for el, num in zip(self.elements, self.lelements):
         for mat, el, num in zip(T1irrep, self.elements, self.lelements):
             tmp = mat.dot(bpref)
             #tmp = mat.dot(self.pref)
             #tmp = el.rotation_matrix(self.withinversion).dot(self.pref)
             c1 = utils._eq(tmp - bpref)
             #c1 = utils._eq(tmp - self.pref)
             if c1:
                 selected.append(num)
                 elem.append(el)
         if self.debug > 0:
             print("The group with P_ref = %r has %d elements:" %
                   (self.pref_cart.__str__(), len(elem)))
             tmpstr = ["%d" % x for x in selected]
             tmpstr = ", ".join(tmpstr)
             print("[%s]" % tmpstr)
         self.elements = elem
         self.lelements = selected
 def check_ortho(self, irrep):
     if len(self.irreps) == 0:
         return True
     char = irrep.characters(self.crep)
     n = len(self.irreps)
     # check row orthogonality
     check1 = np.zeros((n, ), dtype=complex)
     for i in range(n):
         res = 0.
         for k in range(self.nclasses):
             res += self.tchar[i, k] * char[k].conj() * self.cdim[k]
         check1[i] = res
     t1 = utils._eq(check1)
     return t1
Exemple #18
0
    def calc_pion_cg(self, p, p1, p2, irname):
        """Calculate the elements of the Clebsch-Gordan matrix.

        Assumes that p=p1+p2, where all three are 3-vectors.
        """
        # get irrep of group g
        ir = self.g.instances[self.g.lirreps.index(irname)]
        # j1 and j2 are the conjugacy classes containing
        # the given momenta p1 and p2
        j1, j2, i1, i2 = self.check_all_cosets(p, p1, p2)
        #print(j1, j2, p1)
        cg = np.zeros((ir.dim, ir.dim), dtype=complex)
        for ind, r in enumerate(self.g.lrotations):
            rep = ir.mx[ind]
            # hard coded for pi-pi scattering
            g1 = self.gamma1[r, j1, i1]
            if utils._eq(g1):
                continue
            g2 = self.gamma2[r, j2, i2]
            if utils._eq(g2):
                continue
            cg += rep.conj() * g1 * g2
        cg *= float(ir.dim) / self.g.order
        return cg
    def get_cg(self, p1, p2, irrep, change_basis=True):
        """Pass the 3-momenta of both particles,
        check for correct order of momenta.
        """
        # change the basis to the one used
        if change_basis:
            _p1 = self._U.dot(p1)
            _p2 = self._U.dot(p2)
        else:
            _p1 = np.asarray(p1)
            _p2 = np.asarray(p2)
        cg = []
        index = None
        # select correct momentum
        for ind, (p, k1, k2) in enumerate(self.allmomenta):
            if utils._eq(k1, _p1) and utils._eq(k2, _p2):
                index = ind
                break
        # select correct momentum
        #for ind, (p, k1, k2) in enumerate(self.allmomenta):
        #    if utils._eq(k1, p1) and utils._eq(k2, p2):
        #        index = ind
        #        break
        # if momentum not allowed, return None
        if index is None:
            #print("Momentum not present!")
            return None

        # get coefficients
        for i, (name, multi, dim) in enumerate(self.cgnames):
            if irrep != name:
                continue
            #print(self.cg.shape)
            cg = self.cg[i, :multi, :dim, index]
            return cg
        return None
Exemple #20
0
 def print_old(self, j):
     line = "-" * (3*6+5+len(self.allmomenta)*12)
     print("O_s=%d(p_1) x O_s=%d(p_2) -> O(P)_{S,L}^{J,m_J}"%(
             self.s1, self.s2))
     self.print_head(colsize=3*6+5)
     print(line)
     jmult = int(2*j+1)
     srange = self.s1+self.s2+1
     for mj in range(jmult):
         for s in range(srange):
             for l in range(j+srange):
                 c = self.calc_op(j, mj, l, s)
                 if utils._eq(c):
                     continue
                 #print("j, mj, l, s = %d, %d, %d, %d" % (j, mj-j, l, s))
                 self.print_coeffs(c, [j,mj-j,l,s])
                 print(line)
 def is_representation(self, tmult, verbose=False):
     n = self.mx.shape[0]
     for i in range(n):
         mxi = self.mx[i]
         for j in range(n):
             mxj = self.mx[j]
             mxk = self.mx[tmult[i, j]]
             mxij = mxi.dot(mxj)
             if not utils._eq(mxij, mxk):
                 if verbose:
                     print("elements %d * %d not the same as %d:" %
                           (i, j, tmult[i, j]))
                     print("multiplied:")
                     print(mxi)
                     print(mxj)
                     print("result:")
                     print(mxij)
                     print("expected:")
                     print(mxk)
                     #print("elements %d * %d (%r * %r) not the same as %d (%r / %r)" % (i, j, mxi, mxj, tmult[i,j], mxij, mxk))
                 return False
     return True
Exemple #22
0
 def get_pion_cg(self, irname):
     try:
         ind = self.irreps.index(irname)
         return irname, self.cgs[ind], self.allmomenta
     except:
         pass
     result = []
     # iterate over momenta
     for p, p1, p2 in self.allmomenta:
         res = self.calc_pion_cg(p, p1, p2, irname)
         if res is None:
             continue
         result.append(res)
     result = np.asarray(result)
     # check if all coefficients are zero
     if utils._eq(result):
         cgs = None
     else:
         # orthonormalize the basis
         cgs = self._norm_cgs(result)
     self.irreps.append(irname)
     self.cgs.append(cgs)
     return irname, cgs, self.allmomenta
 def find_flip_vectors(self):
     irrep = TOh1D(self.elements)
     flips = []
     n = self.nclasses
     mx_backup = irrep.mx.copy()
     # flip classes
     for k in range(1, n):
         #print("flip %d classes" % k)
         for ind in it.combinations(range(1, n), k):
             fvec = np.ones((n, ))
             for x in ind:
                 fvec[x] *= -1
             irrep.flip_classes(fvec, self.lclasses)
             check1 = np.sum(irrep.mx)
             check2 = irrep.is_representation(self.tmult, verbose=False)
             irrep.mx = mx_backup.copy()
             if utils._eq(check1) and check2:
                 flips.append(fvec.copy())
             if self.debug > 1:
                 print("fvec: %s" % fvec.__str__())
                 print("sum check %r, irrep check %r" % (check1, check2))
     flips = np.asarray(flips, dtype=int)
     self.flip, self.suffixes = self.sort_flip_vectors(flips)
Exemple #24
0
 def MkMultTbl(self):
     mt = np.zeros((self.order, self.order), dtype=int)
     for i in range(self.order):
         mxi = self.mx[i]
         for j in range(self.order):
             mxj = self.mx[j]
             prodij = np.dot(mxi, mxj)
             for k in range(self.order):
                 mxk = self.mx[k]
                 if utils._eq(prodij, mxk, self.prec):
                     mt[i, j] = k
                 self.tmult[i, j] = mt[i, j]
     # check if faithful
     if self.dim == 1:
         # 1D irreps are not faithful
         self.faithful = False
     else:
         self.faithful = True
         for i in range(self.order):
             row = np.unique(mt[i])
             col = np.unique(mt[:, i])
             if row.size != self.order or col.size != self.order:
                 self.faithful = False
                 break
Exemple #25
0
 def test_3D_no_inversion(self):
     res = gg.gen3D(self.elements)
     for i in res:
         self.assertFalse(utils._eq(i))
Exemple #26
0
 def test_4D_inversion(self):
     res = gg.gen4D(self.elements, inv=True)
     for i in res:
         self.assertFalse(utils._eq(i))
Exemple #27
0
    def __init__(self, p, p1, p2, groups=None):
        """p, p1, and p2 are the magnitudes of the momenta.
        """
        self.prec = 1e-6
        # save the norm of the momenta for the combined system
        # and each particle
        self.p = p
        self.p1 = p1
        self.p2 = p2
        # lookup table for reference momenta
        lpref = [
            np.asarray([0., 0., 0.]),
            np.asarray([0., 0., 1.]),
            np.asarray([1., 1., 0.]),
            np.asarray([1., 1., 1.])
        ]
        # save reference momenta
        self.pref = lpref[p]
        self.pref1 = lpref[p1]
        self.pref2 = lpref[p2]

        # get the basic groups
        if groups is None:
            self.g0 = None
            self.g = None
            self.g1 = None
            self.g2 = None
        else:
            self.g0 = groups[0]
            self.g = groups[p]
            self.g1 = groups[p1]
            self.g2 = groups[p2]

        # get the cosets, always in the maximal group (2O here)
        # is set to None if at least one group is None
        self.coset1 = self.gen_coset(self.g1)
        self.coset2 = self.gen_coset(self.g2)
        #print(self.coset1)
        #print(self.coset2)

        # generate the allowed momentum combinations and sort them into cosets
        self.gen_momenta()
        if groups is not None:
            self.sort_momenta()

        # calculate induced rep gamma
        # here for p1 and p2 the A1(A2) irreps are hard-coded
        # since only these contribute to pi-pi scattering
        if groups is None:
            self.gamma1 = None
            self.gamma2 = None
        else:
            irstr = "A1" if p1 < 1e-6 else "A2"
            self.gamma1 = self.gen_ind_reps(self.g, self.g1, irstr,
                                            self.coset1)
            irstr = "A1" if p2 < 1e-6 else "A2"
            self.gamma2 = self.gen_ind_reps(self.g, self.g2, irstr,
                                            self.coset2)
        #print(self.gamma1[:5])

        self.irreps = []
        self.cgs = []

        # choose mu1, mu2 and i1, i2, according to Dudek paper
        # since A1 and A2 are 1D, set mu to 0
        self.mu1 = 0
        self.mu2 = 0
        if self.p == 0:
            # in this case chose the hightest option
            self.i1 = -1
            self.i2 = -1
            self.i1i2 = [(self.pref, -1, -1)]
        else:
            self.i1i2 = []
            for m in self.momenta:
                for ((m1, i1), (m2, i2)) in it.product(self.smomenta1,
                                                       self.smomenta2):
                    if utils._eq(m1 + m2 - m):
                        self.i1i2.append((m, i1, i2))
                        self.i1 = i1
                        self.i2 = i2
                        break
    def find_flip_vectors_imaginary(self):
        irrep = TOh1D(self.elements)
        flips = []

        def check_index(i1, i2):
            for x in i2:
                try:
                    i1.index(x)
                    return True
                except ValueError:
                    continue
            return False

        def f_vec(n, ind1, ind2, indm):
            fvec = np.ones((n, ), dtype=complex)
            for i in ind1:
                fvec[i] *= 1.j
            for i in ind2:
                fvec[i] *= -1.j
            for i in indm:
                fvec[i] *= -1.
            return fvec

        n = self.nclasses
        mx_backup = irrep.mx.copy()
        count = 0
        if self.debug > 0:
            print("find imaginary flips")
            print("number of classes %d" % n)
        # multiply classes with -1, i and -i,
        # always the same number of classes with +i and -i
        # total number of classes flipped
        for kt in range(1, n):
            if self.debug > 1:
                print("flip %d classes" % (kt))
            # half the number of classes with imaginary flip
            for ki in range(1, kt // 2 + 1):
                if self.debug > 1:
                    print("number of imaginary classes: %d" % (2 * ki))
                # get indices for classes with +/- i
                for ind1 in it.combinations(range(1, n), ki):
                    for ind2 in it.combinations(range(1, n), ki):
                        # check if some class is in both index arrays
                        # and skip if it is
                        if check_index(ind1, ind2):
                            if self.debug > 1:
                                print("collision for +/-i:")
                                print("+i: %s" % ind1.__str__())
                                print("-i: %s" % ind2.__str__())
                            continue
                        # get indices for classes with -1
                        for indm in it.combinations(range(1, n), kt - 2 * ki):
                            # check if some class is already taken
                            # and skip if it is
                            if check_index(ind1, indm):
                                if self.debug > 1:
                                    print("collision for +i/-1:")
                                    print("+i: %s" % ind1.__str__())
                                    print("-i: %s" % indm.__str__())
                                continue
                            # check if some class is already taken
                            # and skip if it is
                            if check_index(ind2, indm):
                                if self.debug > 1:
                                    print("collision for -i/-1:")
                                    print("+i: %s" % ind2.__str__())
                                    print("-i: %s" % indm.__str__())
                                continue
                            fvec = f_vec(n, ind1, ind2, indm)
                            irrep.flip_classes(fvec, self.lclasses)
                            check1 = np.sum(irrep.mx)
                            check2 = irrep.is_representation(self.tmult)
                            irrep.mx = mx_backup.copy()
                            if self.debug > 0:
                                print("fvec: %s" % fvec.__str__())
                                print("sum check %r, irrep check %r" %
                                      (check1, check2))
                            if utils._eq(check1) and check2:
                                count += 1
                                flips.append(fvec.copy())
                                # hard-coded due to long runtime
                                if count == 4:
                                    return
        flips = np.asarray(flips, dtype=complex)
        self.flip_i, self.suffixes_i = self.sort_flip_vectors(flips,
                                                              special=True)
Exemple #29
0
 def test_different_vectors_complex(self):
     vec = np.ones((3, ), dtype=complex) + 0.5j
     vec1 = np.ones((3, ), dtype=complex) * 0.5 + 2.j
     self.assertFalse(ut._eq(vec, vec1))
    def __init__(self, p, p1, p2, groups=None, ir1=None, ir2=None):
        """p, p1, and p2 are the magnitudes of the momenta.
        """
        self.prec = 1e-6
        # save the norm of the momenta for the combined system
        # and each particle
        self.p = p
        self.p1 = p1
        self.p2 = p2
        indp0, indp1, indp2, indp = None, None, None, None
        self.U0 = None
        # transformation from cartesian to symmetrized spherical
        # harmonics
        self._U = np.asarray([[0., -1.j, 0.], [0., 0., 1.], [-1., 0., 0.]])
        if groups is not None:
            pindex = [x.p2 for x in groups]
            try:
                indp0 = pindex.index(0)
                indp = pindex.index(p)
                indp1 = pindex.index(p1)
                indp2 = pindex.index(p2)
            except IndexError:
                raise RuntimeError("no group with P^2 = %d (%d, %d) found" %
                                   (p, p1, p2))
            self.U0 = groups[indp0].U3
            self.T0 = groups[indp0].U2
            if (not utils._eq(self.U0, groups[indp].U3)) or (not utils._eq(
                    self.T0, groups[indp].U2)):
                raise RuntimeError(
                    "The group projecting to has different basis")
            if (not utils._eq(self.U0, groups[indp1].U3)) or (not utils._eq(
                    self.T0, groups[indp1].U2)):
                raise RuntimeError("The group of op 1 has different basis")
            if (not utils._eq(self.U0, groups[indp1].U3)) or (not utils._eq(
                    self.T0, groups[indp1].U2)):
                raise RuntimeError("The group of op 2 has different basis")
            self._U = self.U0.dot(self._U)
            # save reference momenta
            self.pref = self._U.dot(groups[indp0].pref_cart)
            self.pref1 = self._U.dot(groups[indp1].pref_cart)
            self.pref2 = self._U.dot(groups[indp2].pref_cart)

        # get the cosets, always in the maximal group (2O here)
        # returns None if groups is None
        self.coset1 = self.gen_coset(groups, indp0, indp1)
        self.coset2 = self.gen_coset(groups, indp0, indp2)
        #print(self.coset1)
        #print(self.coset2)

        # generate the allowed momentum combinations and sort them into cosets
        self.gen_momenta(pm=max(p, p1, p2, 4))

        # calculate induced rep gamma
        # here for p1 and p2 the A1(A2) irreps are hard-coded
        # since only these contribute to pi-pi scattering
        if groups is None:
            self.gamma1 = None
            self.gamma2 = None
            self.dim1 = 0
            self.dim2 = 0
            self.irstr1 = ir1
            self.irstr2 = ir2
        else:
            if ir1 is None:
                self.irstr1 = "A1u" if int(p1) in [0, 3, 5, 6] else "A2u"
            else:
                self.irstr1 = ir1
            if self.irstr1 not in groups[indp1].irrepsname:
                raise RuntimeError("irrep %s not in group 1!" % self.irstr1)
            else:
                self.dim1 = groups[indp1].irrepsname.index(self.irstr1)
                self.dim1 = groups[indp1].irrepdim[self.dim1]
            self.gamma1 = self.gen_ind_reps(groups, indp0, indp1, self.irstr1,
                                            self.coset1)
            #print(self.gamma1[:5])

            if ir2 is None:
                self.irstr2 = "A1u" if int(p2) in [0, 3, 5, 6] else "A2u"
            else:
                self.irstr2 = ir2
            if self.irstr2 not in groups[indp2].irrepsname:
                raise RuntimeError("irrep %s not in group 2!" % self.irstr2)
            else:
                self.dim2 = groups[indp2].irrepsname.index(self.irstr2)
                self.dim2 = groups[indp2].irrepdim[self.dim2]
            self.gamma2 = self.gen_ind_reps(groups, indp0, indp2, self.irstr2,
                                            self.coset2)
            #print(self.gamma2[:5])

            self.sort_momenta(groups[indp0])

        self.calc_cg_ha(groups, indp)