def setUp(self):
        self.L = 2 * pi
        self.nmax = 1
        self.m = 0.

        self.Emax = 5.
        #self.fermionBasis = FermionBasis(L=2*pi, Emax=self.Emax, m=0.)

        self.state = FermionState([1, 0, 1], [1, 0, 1], self.nmax, self.L,
                                  self.m)

        #create an operator that annihilates a particle of momentum 1
        self.operator = FermionOperator(clist=[],
                                        dlist=[1],
                                        anticlist=[],
                                        antidlist=[],
                                        L=self.L,
                                        m=self.m,
                                        normed=True,
                                        extracoeff=1)
    def setUp(self):
        self.L = 2 * pi
        self.nmax = 0.5
        self.m = 0.

        #initialize a FermionState with half-integer nmax=0.5
        self.state = FermionState([1, 1], [1, 1], self.nmax, self.L, self.m)
        self.operator = FermionOperator(clist=[],
                                        dlist=[],
                                        anticlist=[],
                                        antidlist=[0.5],
                                        L=self.L,
                                        m=self.m,
                                        normed=True)
    def testOrderingParticleAntiparticles(self):
        state1 = FermionState([0, 1, 0], [0, 0, 0],
                              2,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)
        state2 = FermionState([1, 1, 0], [0, 0, 0],
                              2,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)
        state3 = FermionState([1, 1, 0], [1, 0, 0],
                              2,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)
        state4 = FermionState([1, 1, 0], [1, 0, 1],
                              2,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)

        op1 = FermionOperator([2], [], [], [], self.L, self.m, normed=True)

        n, newState = op1._transformState(state1, returnCoeff=True)
        #one anticommutation to get to the right spot
        self.assertEqual(n, -1)

        #two anticommutations
        n, newState = op1._transformState(state2, returnCoeff=True)
        self.assertEqual(n, 1)

        #three anticommutations
        n, newState = op1._transformState(state3, returnCoeff=True)
        self.assertEqual(n, -1)

        #four anticommutations ah ah ah
        n, newState = op1._transformState(state4, returnCoeff=True)
        self.assertEqual(n, 1)
    def testCreationOperatorOrdering(self):
        # these operators have the creation operators in a different order
        # so there should be a relative sign in applying these operators
        op1 = FermionOperator([-1, 1], [], [], [], self.L, self.m, normed=True)
        op2 = FermionOperator([1, -1], [], [], [], self.L, self.m, normed=True)

        # do this also for antiparticle creation operators
        op3 = FermionOperator([], [], [-1, 1], [], self.L, self.m, normed=True)
        op4 = FermionOperator([], [], [1, -1], [], self.L, self.m, normed=True)

        state = FermionState([0, 0, 0], [0, 0, 0],
                             self.nmax,
                             self.L,
                             self.m,
                             checkAtRest=False,
                             checkChargeNeutral=False)

        outState = FermionState([1, 0, 1], [0, 0, 0],
                                self.nmax,
                                self.L,
                                self.m,
                                checkAtRest=False,
                                checkChargeNeutral=False)
        outState2 = FermionState([0, 0, 0], [1, 0, 1],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)

        n, newState = op1._transformState(state, returnCoeff=True)
        self.assertEqual(n, 1)
        self.assertEqual(newState, outState)

        n, newState = op2._transformState(state, returnCoeff=True)
        self.assertEqual(n, -1)
        self.assertEqual(newState, outState)

        n, newState = op3._transformState(state, returnCoeff=True)
        self.assertEqual(n, 1)
        self.assertEqual(newState, outState2)

        n, newState = op4._transformState(state, returnCoeff=True)
        self.assertEqual(n, -1)
        self.assertEqual(newState, outState2)
    def testDestructionOperatorSigns(self):
        # test that destruction operators correctly anticommute when applied
        # to states with our convention
        dOperator = FermionOperator(clist=[],
                                    dlist=[1],
                                    anticlist=[],
                                    antidlist=[],
                                    L=self.L,
                                    m=self.m,
                                    normed=True,
                                    extracoeff=1)

        # this state has excitations in the n=+1 and n=-1 modes
        # so there is one trivial anticommutation
        state1 = FermionState([1, 0, 1], [0, 0, 0],
                              self.nmax,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)
        # this state only has an excitation in the +1 mode
        state2 = FermionState([0, 0, 1], [0, 0, 0],
                              self.nmax,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)
        # this state has a particle and an antiparticle
        # so there is one trivial anticommutation with the antiparticle op
        state3 = FermionState([0, 0, 1], [0, 0, 1],
                              self.nmax,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)

        outState1 = FermionState([1, 0, 0], [0, 0, 0],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)
        outState2 = FermionState([0, 0, 0], [0, 0, 0],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)
        outState3 = FermionState([0, 0, 0], [0, 0, 1],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)

        n, newState = dOperator._transformState(state1, returnCoeff=True)
        self.assertEqual(n, -1)
        self.assertEqual(newState, outState1)

        n, newState = dOperator._transformState(state2, returnCoeff=True)
        self.assertEqual(n, 1)
        self.assertEqual(newState, outState2)

        n, newState = dOperator._transformState(state3, returnCoeff=True)
        self.assertEqual(n, -1)
        self.assertEqual(newState, outState3)
    def testApplyOperator(self):
        n, newState = self.operator._transformState(self.state,
                                                    returnCoeff=True)
        #print(np.transpose(newState.occs))

        self.assertEqual(n, -1)

        #test that adding a particle to a filled state annihilates it
        for c1 in (-1, 1):
            operator = FermionOperator([c1], [], [], [], self.L, self.m)
            self.assertEqual(operator._transformState(self.state), (0, None))

        for c2 in (-1, 1):
            operator = FermionOperator([], [], [c2], [], self.L, self.m)
            self.assertEqual(operator._transformState(self.state), (0, None))

        #test that removing a particle from an empty state annihilates it
        #note: we shouldn't really act on the zero mode at all
        #because it is not well-defined for the massless fermion
        operator = FermionOperator([], [0], [], [],
                                   self.L,
                                   self.m,
                                   normed=True)
        self.assertEqual(operator._transformState(self.state), (0, None))

        operator = FermionOperator([], [], [], [0],
                                   self.L,
                                   self.m,
                                   normed=True)
        self.assertEqual(operator._transformState(self.state), (0, None))
class TestFermionOperator(unittest.TestCase):
    def setUp(self):
        self.L = 2 * pi
        self.nmax = 1
        self.m = 0.

        self.Emax = 5.
        #self.fermionBasis = FermionBasis(L=2*pi, Emax=self.Emax, m=0.)

        self.state = FermionState([1, 0, 1], [1, 0, 1], self.nmax, self.L,
                                  self.m)

        #create an operator that annihilates a particle of momentum 1
        self.operator = FermionOperator(clist=[],
                                        dlist=[1],
                                        anticlist=[],
                                        antidlist=[],
                                        L=self.L,
                                        m=self.m,
                                        normed=True,
                                        extracoeff=1)

    def testApplyOperator(self):
        n, newState = self.operator._transformState(self.state,
                                                    returnCoeff=True)
        #print(np.transpose(newState.occs))

        self.assertEqual(n, -1)

        #test that adding a particle to a filled state annihilates it
        for c1 in (-1, 1):
            operator = FermionOperator([c1], [], [], [], self.L, self.m)
            self.assertEqual(operator._transformState(self.state), (0, None))

        for c2 in (-1, 1):
            operator = FermionOperator([], [], [c2], [], self.L, self.m)
            self.assertEqual(operator._transformState(self.state), (0, None))

        #test that removing a particle from an empty state annihilates it
        #note: we shouldn't really act on the zero mode at all
        #because it is not well-defined for the massless fermion
        operator = FermionOperator([], [0], [], [],
                                   self.L,
                                   self.m,
                                   normed=True)
        self.assertEqual(operator._transformState(self.state), (0, None))

        operator = FermionOperator([], [], [], [0],
                                   self.L,
                                   self.m,
                                   normed=True)
        self.assertEqual(operator._transformState(self.state), (0, None))

    def testDestructionOperatorSigns(self):
        # test that destruction operators correctly anticommute when applied
        # to states with our convention
        dOperator = FermionOperator(clist=[],
                                    dlist=[1],
                                    anticlist=[],
                                    antidlist=[],
                                    L=self.L,
                                    m=self.m,
                                    normed=True,
                                    extracoeff=1)

        # this state has excitations in the n=+1 and n=-1 modes
        # so there is one trivial anticommutation
        state1 = FermionState([1, 0, 1], [0, 0, 0],
                              self.nmax,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)
        # this state only has an excitation in the +1 mode
        state2 = FermionState([0, 0, 1], [0, 0, 0],
                              self.nmax,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)
        # this state has a particle and an antiparticle
        # so there is one trivial anticommutation with the antiparticle op
        state3 = FermionState([0, 0, 1], [0, 0, 1],
                              self.nmax,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)

        outState1 = FermionState([1, 0, 0], [0, 0, 0],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)
        outState2 = FermionState([0, 0, 0], [0, 0, 0],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)
        outState3 = FermionState([0, 0, 0], [0, 0, 1],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)

        n, newState = dOperator._transformState(state1, returnCoeff=True)
        self.assertEqual(n, -1)
        self.assertEqual(newState, outState1)

        n, newState = dOperator._transformState(state2, returnCoeff=True)
        self.assertEqual(n, 1)
        self.assertEqual(newState, outState2)

        n, newState = dOperator._transformState(state3, returnCoeff=True)
        self.assertEqual(n, -1)
        self.assertEqual(newState, outState3)

    def testCreationOperatorOrdering(self):
        # these operators have the creation operators in a different order
        # so there should be a relative sign in applying these operators
        op1 = FermionOperator([-1, 1], [], [], [], self.L, self.m, normed=True)
        op2 = FermionOperator([1, -1], [], [], [], self.L, self.m, normed=True)

        # do this also for antiparticle creation operators
        op3 = FermionOperator([], [], [-1, 1], [], self.L, self.m, normed=True)
        op4 = FermionOperator([], [], [1, -1], [], self.L, self.m, normed=True)

        state = FermionState([0, 0, 0], [0, 0, 0],
                             self.nmax,
                             self.L,
                             self.m,
                             checkAtRest=False,
                             checkChargeNeutral=False)

        outState = FermionState([1, 0, 1], [0, 0, 0],
                                self.nmax,
                                self.L,
                                self.m,
                                checkAtRest=False,
                                checkChargeNeutral=False)
        outState2 = FermionState([0, 0, 0], [1, 0, 1],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)

        n, newState = op1._transformState(state, returnCoeff=True)
        self.assertEqual(n, 1)
        self.assertEqual(newState, outState)

        n, newState = op2._transformState(state, returnCoeff=True)
        self.assertEqual(n, -1)
        self.assertEqual(newState, outState)

        n, newState = op3._transformState(state, returnCoeff=True)
        self.assertEqual(n, 1)
        self.assertEqual(newState, outState2)

        n, newState = op4._transformState(state, returnCoeff=True)
        self.assertEqual(n, -1)
        self.assertEqual(newState, outState2)

    def testOrderingParticleAntiparticles(self):
        state1 = FermionState([0, 1, 0], [0, 0, 0],
                              2,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)
        state2 = FermionState([1, 1, 0], [0, 0, 0],
                              2,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)
        state3 = FermionState([1, 1, 0], [1, 0, 0],
                              2,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)
        state4 = FermionState([1, 1, 0], [1, 0, 1],
                              2,
                              self.L,
                              self.m,
                              checkAtRest=False,
                              checkChargeNeutral=False)

        op1 = FermionOperator([2], [], [], [], self.L, self.m, normed=True)

        n, newState = op1._transformState(state1, returnCoeff=True)
        #one anticommutation to get to the right spot
        self.assertEqual(n, -1)

        #two anticommutations
        n, newState = op1._transformState(state2, returnCoeff=True)
        self.assertEqual(n, 1)

        #three anticommutations
        n, newState = op1._transformState(state3, returnCoeff=True)
        self.assertEqual(n, -1)

        #four anticommutations ah ah ah
        n, newState = op1._transformState(state4, returnCoeff=True)
        self.assertEqual(n, 1)
Example #8
0
    def makeInteractionOps(self,
                           clist,
                           dlist,
                           anticlist,
                           antidlist,
                           nmax,
                           spinors,
                           coeff=1.,
                           deltacondition=None):
        """
        Takes a set of field labels for (anti)particle creation/annihilation
        operators and generates all corresponding strings of operators with
        momenta up to nmax, subject to (optional) delta function constraints.

        Parameters
        ----------
        clist : list of int
            labels for which fields the particle creation operators come from,
            e.g. [1,3] indicates that the first and third fields contributed
            a daggers.
        dlist : list of int
            labels for which fields the particle annihilation operators come from
        anticlist : list of int
            labels for which fields the antiparticle creation operators come from
        antidlist : list of int
            labels for which fields the antiparticle annihilation operators come from
        nmax : int
            maximum value of wavenumber in the truncation
        spinors : string
            A four-character string representing the contracted spinor
            wavefunctions to be computed. For example, udagger u vdagger v
            is just given as "uuvv".
        coeff : float, optional
            Extra coefficients for this operator. The default is 1.
        deltacondition : tuple, optional
            Any pairs of momenta that are to be set equal by Kronecker deltas,
            e.g. (1,2) is \delta_{k1,k2}. The default is None.

        Returns
        -------
        ops : list of FermionOperators
            All fermion operators matching the input parameters. The normalization
            is for 1/2k^2 * |\psi^\dagger \psi|^2, i.e. it contains the spinor
            inner products and also the 1/L factor. The g^2 then multiplies
            the matrix entries of V.

        """

        momenta = np.array([[k1, k2, k3, -k1 - k2 - k3]
                            for k1 in np.arange(-nmax, nmax + 1)
                            for k2 in np.arange(-nmax, nmax + 1)
                            for k3 in np.arange(-nmax, nmax + 1)
                            if k1 + k2 != 0 and abs(k1 + k2 + k3) <= nmax])

        # note: easily modified for multiple delta functions
        # just make it a list of tuples and iterate over the masking conditions
        # a minus sign is needed for the delta conditions with this convention
        # since we have a_k1 and a^\dagger_{-k2}
        if deltacondition:
            mask = momenta[:, deltacondition[0] -
                           1] == -momenta[:, deltacondition[1] - 1]
            momenta = momenta[mask]

        # for kvals in momenta:
        #     assert(kvals[2]+kvals[3] != 0)
        #     assert(kvals[0]+kvals[1] + kvals[2] + kvals[3] == 0)

        # return the right functions for the spinor inner products
        # with this convention, vs and udaggers get minus signs
        spinor_lookup = {
            "uu": lambda k1, k2: self.udotu(-k1, k2),
            "uv": lambda k1, k2: self.udotv(-k1, -k2),
            "vu": lambda k1, k2: self.vdotu(k1, k2),
            "vv": lambda k1, k2: self.vdotv(k1, -k2)
        }

        assert len(spinors) == 4
        firstspinor = spinor_lookup[spinors[0:2]]
        secondspinor = spinor_lookup[spinors[2:4]]

        ops = []
        for kvals in momenta:
            spinorfactor = (firstspinor(kvals[0], kvals[1]) *
                            secondspinor(kvals[2], kvals[3]))
            if spinorfactor == 0: continue
            # print(firstspinor(kvals[0],kvals[1]))
            # print(secondspinor(kvals[2],kvals[3]))
            # print(spinorfactor)
            # print(kvals)
            ksquared = 1 / (kvals[0] + kvals[1])**2
            #creation operators get the minus sign on k
            ops += [
                FermionOperator(-kvals[np.array(clist, dtype=int) - 1],
                                kvals[np.array(dlist, dtype=int) - 1],
                                -kvals[np.array(anticlist, dtype=int) - 1],
                                kvals[np.array(antidlist, dtype=int) - 1],
                                self.L,
                                self.m,
                                extracoeff=coeff * spinorfactor * ksquared /
                                (2 * self.L),
                                normed=True)
            ]

        return ops
Example #9
0
    def generateOperators(self):
        """
        Generates a dictionary of normal-ordered operators corresponding
        to the operator (\psi^\dagger \psi)_k for all values of k within range.

        Returns
        -------
        opsList : dict of FermionOperators
            A dictionary whose keys are values of k, i.e. which Fourier mode
            of psi^\dagger \psi is under consideration, and whose entries are
            the corresponding set of operators.

        """

        opsList = {}

        # we will generate (psi^\dagger psi)_k
        for k in np.arange(-self.fullBasis.nmax, self.fullBasis.nmax + 1):
            opsList[k] = []
            if k == 0:
                continue
            # note: what is the range on n? revisit. All valid ns such that
            # -nmax <= k+n <= nmax and -nmax <= n <= nmax
            for n in np.arange(-self.fullBasis.nmax, self.fullBasis.nmax + 1):
                if not (-self.fullBasis.nmax <= k - n <= self.fullBasis.nmax):
                    continue
                # zero mode spinor wavefunctions fixed, can remove this?
                # if k-n == 0 or n == 0:
                #     continue

                coeff = np.vdot(uspinor(n - k, self.L, self.m, normed=True),
                                uspinor(n, self.L, self.m, normed=True))
                adaggera = FermionOperator([n - k], [n], [], [],
                                           self.L,
                                           self.m,
                                           extracoeff=coeff / np.sqrt(self.L),
                                           normed=True)
                #n.b. -1 from anticommutation of bdagger and adagger
                coeff = -1 * np.vdot(
                    uspinor(n - k, self.L, self.m, normed=True),
                    vspinor(-n, self.L, self.m, normed=True))
                bdaggeradagger = FermionOperator([n - k], [], [-n], [],
                                                 self.L,
                                                 self.m,
                                                 extracoeff=coeff /
                                                 np.sqrt(self.L),
                                                 normed=True)

                coeff = np.vdot(vspinor(k - n, self.L, self.m, normed=True),
                                uspinor(n, self.L, self.m, normed=True))
                ba = FermionOperator([], [n], [], [k - n],
                                     self.L,
                                     self.m,
                                     extracoeff=coeff / np.sqrt(self.L),
                                     normed=True)
                # -1 from anticommuting b and b dagger
                coeff = -1 * np.vdot(
                    vspinor(k - n, self.L, self.m, normed=True),
                    vspinor(-n, self.L, self.m, normed=True))
                bdaggerb = FermionOperator([], [], [-n], [k - n],
                                           self.L,
                                           self.m,
                                           extracoeff=coeff / np.sqrt(self.L),
                                           normed=True)
                #the anticommutator is always trivial because k-n = -n -> k=0
                #and we've precluded this possiblity since k != 0

                opsList[k] += [adaggera, bdaggeradagger, ba, bdaggerb]

        return opsList
    def testOperator(self):

        #test that adding a particle to a filled state annihilates it
        for c1 in (-0.5, 0.5):
            operator = FermionOperator([c1], [], [], [], self.L, self.m)
            self.assertEqual(operator._transformState(self.state), (0, None))

        for c2 in (-0.5, 0.5):
            operator = FermionOperator([], [], [c2], [], self.L, self.m)
            self.assertEqual(operator._transformState(self.state), (0, None))

        op1 = FermionOperator([], [-0.5], [], [], self.L, self.m, normed=True)
        outState1 = FermionState([0, 1], [1, 1],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)
        n, newState = op1._transformState(self.state, returnCoeff=True)
        self.assertEqual(n, 1)
        self.assertEqual(newState, outState1)

        op2 = FermionOperator([], [0.5], [], [], self.L, self.m, normed=True)
        outState2 = FermionState([1, 0], [1, 1],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)
        n, newState = op2._transformState(self.state, returnCoeff=True)
        self.assertEqual(n, -1)
        self.assertEqual(newState, outState2)

        op3 = FermionOperator([], [], [], [-0.5], self.L, self.m, normed=True)
        outState3 = FermionState([1, 1], [0, 1],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)
        n, newState = op3._transformState(self.state, returnCoeff=True)
        self.assertEqual(n, 1)
        self.assertEqual(newState, outState3)

        op4 = FermionOperator([], [], [], [0.5], self.L, self.m, normed=True)
        outState4 = FermionState([1, 1], [1, 0],
                                 self.nmax,
                                 self.L,
                                 self.m,
                                 checkAtRest=False,
                                 checkChargeNeutral=False)
        n, newState = op4._transformState(self.state, returnCoeff=True)
        self.assertEqual(n, -1)
        self.assertEqual(newState, outState4)