Example #1
0
 def __init__(self, particleOccs, antiparticleOccs, zeromode, nmax,
              L=None, m=None, fast=False, checkAtRest=True,
              checkChargeNeutral=True, e_var=1):
     """ 
     Args:
         antiparticleOccs: occupation number list
         particleOccs: occupation number list
         zeromode (int): int specifying eigenstate of the A1 zero mode
         nmax (int): wave number of the last element in occs
         fast (bool): a flag for when occs and nmax are all that are needed
             (see transformState in oscillators.py)
         checkAtRest (bool): a flag to check if the total momentum is zero
         e_var (float): charge (default 1), used in calculating zero mode energy
     
     """
     #assert m >= 0, "Negative or zero mass"
     #assert L > 0, "Circumference must be positive"
     assert zeromode >= 0, "zeromode eigenstate label should be >=0"
     
     self.zeromode = zeromode
     self.omega0 = e_var/sqrt(pi)
     
     
     FermionState.__init__(self, particleOccs, antiparticleOccs, nmax,
                                         L, m, fast, checkAtRest, checkChargeNeutral)
     self.isDressed = True
     if fast: return
     
     
     self.energy += self.zeromode * self.omega0
    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)
    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)
    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 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 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)
Example #8
0
 def __buildRMlist(self):
     """ sets list of all right-moving states with particles of individual wave number 
     <= nmax, total momentum <= Emax/2 and total energy <= Emax
     This function works by first filling in n=1 mode in all possible ways, then n=2 mode
     in all possible ways assuming the occupation of n=1 mode, etc
     
     This is modified for fermionic states. In the fermionic case,
     occupation numbers are zero or one due to Pauli exclusion.
     """
     
     if self.nmax == 0:
         self.__RMlist = [FermionState([],[],nmax=0,L=self.L,m=self.m,
                                       checkAtRest=False,
                                       checkChargeNeutral=False)]
         return
     
     # for zero-momentum states, the maximum value of k is as follows.
     kmax = max(0., np.sqrt((self.Emax/2.)**2.-self.m**2.))
             
     # the max occupation number of the n=1 mode is either kmax divided 
     # by the momentum at n=1 or Emax/omega, whichever is less
     # the 2 here accounts for that we can have a single particle and an 
     # antiparticle in n=1
     if self.bcs == "periodic":
         seedN = 1
     elif self.bcs == "antiperiodic":
         seedN = 0.5
     
     maxN1 = min([math.floor(kmax/k(seedN,self.L)),
                  math.floor(self.Emax/omega(seedN,self.L,self.m)),
                  2])
     
     if maxN1 <= 0:
         nextOccs = [[0,0]]
     elif maxN1 == 1:
         nextOccs = [[0,0],[0,1],[1,0]]
     else:
         nextOccs = [[0,0],[0,1],[1,0],[1,1]]
     
     RMlist0 = [FermionState([occs[0]],[occs[1]],seedN,L=self.L,m=self.m,checkAtRest=False,
                      checkChargeNeutral=False) for occs in nextOccs]
     # seed list of RM states,all possible n=1 mode occupation numbers
     
     
     for n in np.arange(seedN+1,self.nmax+1): #go over all other modes
         RMlist1=[] #we will take states out of RMlist0, augment them and add to RMlist1
         for RMstate in RMlist0: # cycle over all RMstates
             p0 = RMstate.momentum
             e0 = RMstate.energy
             
             # maximal occupation number of mode n given the momentum/energy
             # in all previous modes. The sqrt term accounts for the
             # ground state energy of the overall state, while e0 gives
             # the energy in each of the mode excitations.
             maxNn = min([math.floor((kmax-p0)/k(n,self.L)),
                          math.floor((self.Emax-np.sqrt(self.m**2+p0**2)-e0)/omega(n,self.L,self.m)),
                          2])
             
             if maxNn <= 0:
                 nextOccsList = [[0,0]]
             elif maxNn == 1:
                 nextOccsList = [[0,0],[0,1],[1,0]]
             else:
                 nextOccsList = [[0,0],[0,1],[1,0],[1,1]]
             
             assert maxNn <= 2, f"maxNn was {maxNn}"
             # got to here in edits.
             # should we maybe just write a numpy function to calculate
             # energy and momentum from the occs list?
             # update: i did this. But it would take an extra
             # function call instead of accessing state properties.
             
             #print(f"RMstate occs are {RMstate.occs}")
             for nextOccs in nextOccsList:
                 longerstate = np.append(RMstate.occs,[nextOccs],axis=0)
                 RMlist1.append(FermionState(longerstate[:,0],
                                             longerstate[:,1],
                                             nmax=n,L=self.L,m=self.m,
                                             checkAtRest=False,
                                             checkChargeNeutral=False))
         #RMlist1 created, copy it back to RMlist0
         RMlist0 = RMlist1
     
     self.__RMlist = RMlist0 #save list of RMstates in an internal variable 
Example #9
0
    def _transformState(self, state0, returnCoeff=False, dressed=False):
        """
        Applies the normal ordered operator to a given state.
        
        Args:
            state0 (State): an input FermionState for this operator
            returncoeff (bool): boolean representing whether or not to
                include the factor self.coeff with the returned state
        
        Returns:
            A tuple representing the input state after being acted on by
            the normal-ordered operator and any multiplicative factors
            from performing the commutations.
        
        Example:
            For a state with nmax=1 and state0.occs = [0,0,2] 
            (2 excitations in the n=+1 mode, since counting starts at
            -nmax) if the operator is a_{k=1}, corresponding to
            clist = []
            dlist = [1]
            coeff = 1
            then this will return a state with occs [0,0,1] and a prefactor of
            2 (for the two commutations).
            
        """
        if not self.uniqueOps:
            return (0, None)
        #make a copy of this state up to occupation numbers and nmax
        #use DressedFermionState if the original state is dressed
        #otherwise use FermionState
        if state0.isDressed:
            state = DressedFermionState(particleOccs=state0.occs[:, 0],
                                        antiparticleOccs=state0.occs[:, 1],
                                        zeromode=state0.getAZeroMode(),
                                        nmax=state0.nmax,
                                        fast=True)
        else:
            state = FermionState(particleOccs=state0.occs[:, 0],
                                 antiparticleOccs=state0.occs[:, 1],
                                 nmax=state0.nmax,
                                 fast=True)

        # note: there may be an easier way for fermionic states
        # however, these loops are short and fast, so NumPy shortcuts probably
        # will not provide too much speed-up at this level.

        norm = 1

        for i in self.dlist:
            if state[i][0] == 0:
                return (0, None)
            state[i][0] -= 1
            # we have to anticommute past all the antiparticle creation ops
            # and the particle creation ops up to i
            norm *= (-1)**(np.sum(state.occs[:, 1]) +
                           np.sum(state.occs[:int(i - state.nmin), 0]))

        for i in self.antidlist:
            if state[i][1] == 0:
                return (0, None)
            state[i][1] -= 1
            # anticommute past the antiparticle creation ops up to i
            norm *= (-1)**(np.sum(state.occs[:int(i - state.nmin), 1]))

        for i in self.clist:
            # by Pauli exclusion, states can have at most one excitation
            # in a mode
            if state[i][0] == 1:
                return (0, None)
            state[i][0] += 1
            # anticommute past all the antiparticle creation ops and the
            # particle creation ops through i
            norm *= (-1)**(np.sum(state.occs[:, 1]) +
                           np.sum(state.occs[:int(i - state.nmin), 0]))

        for i in self.anticlist:
            if state[i][1] == 1:
                return (0, None)
            state[i][1] += 1
            # anticommute past the antiparticle creation ops
            norm *= (-1)**(np.sum(state.occs[:int(i - state.nmin), 1]))

        # We never pick up a nontrivial normalization factor for fermionic
        # states since the occupation numbers are either one or zero.
        # The only option is if we wish to return the overall coefficient
        # of this operator or not.
        if returnCoeff:
            return (norm * self.coeff, state)
        return (norm, state)