def nAverage_fpeps2by2(peps0): debug = False nr, nc = peps0.shape # <P|P> tmp = peps0[0, 1].copy() p23 = tmp.ptys[0] d23 = tmp.dims[0] p1 = tmp.ptys[2] d1 = tmp.dims[2] swap = fpeps_util.genSwap(p23, d23, p1, d1) peps1 = peps.copy(peps0) peps1[0, 1] = einsum('pludr,pUuP->PlUdr', peps1[0, 1], swap) ovlp = peps.dot(peps1, peps1) if debug: print print "Ovlp=", peps.dot(peps0, peps0) print "Ovlp=", ovlp nloc = fpeps_util.genNloc() # \hat{N} is a sum of local terms nav = 0.0 for i in range(nr): for j in range(nc): peps2 = peps.copy(peps1) peps2[i, j] = einsum('Pp,pludr->Pludr', nloc, peps1[i, j]) nav += peps.dot(peps1, peps2) return ovlp, nav
def nAverage_fpeps3by3(peps0): nr, nc = peps0.shape # <P|P> peps0b = reflection(peps0) peps1b = peps.copy(peps0b) for i in range(nr): for j in range(nc): tmp = peps1b[i, j].copy() p0 = tmp.ptys[1] d0 = tmp.dims[1] p1 = tmp.ptys[2] d1 = tmp.dims[2] swapLU = fpeps_util.genSwap(p0, d0, p1, d1) tmp = einsum('luUL,pLUdr->pludr', swapLU, tmp) p0 = tmp.ptys[4] d0 = tmp.dims[4] p1 = tmp.ptys[3] d1 = tmp.dims[3] swapRD = fpeps_util.genSwap(p0, d0, p1, d1) tmp = einsum('RDdr,pluDR->pludr', swapRD, tmp) peps1b[i, j] = tmp.copy() ovlp = fpeps_util.fdot(peps0b, peps1b) if debug: print print "Ovlp=", peps.dot(peps0, peps0) print "Ovlp=", ovlp nloc = fpeps_util.genNloc() # \hat{N} is a sum of local terms nav = 0.0 for j in range(nc): for i in range(nr): # Measure each local occupation <Ni> peps2b = peps.copy(peps1b) peps2b[i, j] = einsum('Pp,pludr->Pludr', nloc, peps1b[i, j]) nii = fpeps_util.fdot(peps0b, peps2b) nav += nii print '(i,j)=', (i, j), '<Nloc>=', nii, nii / ovlp print 'nav=', ovlp, nav, nav / ovlp return ovlp, nav
def dump2by3(peps0): p1 = peps0[0, 1].ptys[0] d1 = peps0[0, 1].dims[0] p23 = peps0[1, 0].ptys[4] d23 = peps0[1, 0].dims[4] swap = fpeps_util.genSwap(p23, d23, p1, d1) coeff = einsum('amEpJ,IJHqK,bnrEF,FcIG,dGsHL,LeOM,OKNuw,fMtNv->abcdefnmpqurstvw',\ peps0[0,0],peps0[0,1],peps0[1,0],swap,peps0[1,1],\ swap,peps0[0,2],peps0[1,2]) # abcdef|nmpqurstvw => Only four auxilliary indices left !!! coeff = coeff.merge([[0],[1],[2],[3],[4],[5],\ [6,7],[8,9,10],[11,12,13],[14,15]]) coeff.prt() # 4^6 = 4096 print 'einsum<PEPS|PEPS>=', einsum('abcdefMNOP,abcdefMNOP', coeff, coeff) nr, nc = peps0.shape nsite = nr * nc vtensor = np.zeros([4] * nsite) for qa in range(2): for qb in range(2): for qc in range(2): for qd in range(2): for qe in range(2): for qf in range(2): if coeff[qa, qb, qc, qd, qe, qf, 0, 0, 0, 0].shape == 0: continue c0 = coeff[qa, qb, qc, qd, qe, qf, 0, 0, 0, 0].reshape([2] * nsite) for ia in range(2): for ib in range(2): for ic in range(2): for id in range(2): for ie in range(2): for if0 in range(2): xa = addr[qa, ia] xb = addr[qb, ib] xc = addr[qc, ic] xd = addr[qd, id] xe = addr[qe, ie] xf = addr[qf, if0] vtensor[xa, xb, xc, xd, xe, xf] = c0[ia, ib, ic, id, ie, if0] vcoeff = vtensor.flatten() return vcoeff
def dump2by2(peps0): p1 = peps0[0, 1].ptys[0] d1 = peps0[0, 1].dims[0] p23 = peps0[1, 0].ptys[4] d23 = peps0[1, 0].dims[4] swap = fpeps_util.genSwap(p23, d23, p1, d1) coeff = einsum('amEpJ,IJHqk,bnrEF,FcIG,dGsHl->abcdnmpqrslk',\ peps0[0,0],peps0[0,1],peps0[1,0],swap,peps0[1,1]) # 0123456789|10|11 coeff = coeff.merge([[0],[1],[2],[3],\ [4,5],[6,7],[8,9],[10,11]]) coeff.prt() print 'einsum<PEPS|PEPS>=', einsum('abcdNPRL,abcdNPRL', coeff, coeff) nr, nc = peps0.shape nsite = nr * nc vtensor = np.zeros([4] * nsite) for qa in range(2): for qb in range(2): for qc in range(2): for qd in range(2): if coeff[qa, qb, qc, qd, 0, 0, 0, 0].shape == 0: continue c0 = coeff[qa, qb, qc, qd, 0, 0, 0, 0].reshape(2, 2, 2, 2) for ia in range(2): for ib in range(2): for ic in range(2): for id in range(2): xa = addr[qa, ia] xb = addr[qb, ib] xc = addr[qc, ic] xd = addr[qd, id] vtensor[xa, xb, xc, xd] = c0[ia, ib, ic, id] vcoeff = vtensor.flatten() return vcoeff
def energy_fpeps3by3(peps0): nr, nc = peps0.shape # <P|P> peps0b = reflection(peps0) peps1b = peps.copy(peps0b) for i in range(nr): for j in range(nc): tmp = peps1b[i, j].copy() p0 = tmp.ptys[1] d0 = tmp.dims[1] p1 = tmp.ptys[2] d1 = tmp.dims[2] swapLU = fpeps_util.genSwap(p0, d0, p1, d1) tmp = einsum('luUL,pLUdr->pludr', swapLU, tmp) p0 = tmp.ptys[4] d0 = tmp.dims[4] p1 = tmp.ptys[3] d1 = tmp.dims[3] swapRD = fpeps_util.genSwap(p0, d0, p1, d1) tmp = einsum('RDdr,pluDR->pludr', swapRD, tmp) peps1b[i, j] = tmp.copy() ovlp = fpeps_util.fdot(peps0b, peps1b) if debug: print print "Ovlp=", peps.dot(peps0, peps0) print "Ovlp=", ovlp etot = 0.0 # <P|U[i]|P> if debug: print "\nU-terms:" uterm = fpeps_util.genUterm(U) for j in range(nc): for i in range(nr): peps2 = peps.copy(peps0) peps2[i, j] = einsum('Pp,pludr->Pludr', uterm, peps0[i, j]) peps2b = reflection(peps2) eloc = fpeps_util.fdot(peps2b, peps1b) if debug: print '(i,j)=', (i, j), ' <U>=', eloc etot += eloc # # T-term # tC_aa, tA_aa = fpeps_util.genTaa() tC_bb, tA_bb = fpeps_util.genTbb() # Jordan-Wigner sign factor for i\=j parity = fpeps_util.genParitySgn([0, 1], [2, 2]) tC_aa = einsum('xqp,pr->xqr', tC_aa, parity) tC_bb = einsum('xqp,pr->xqr', tC_bb, parity) # Vertical bond => Simple is the chosen embedding if debug: print "\nVbonds:" for j in range(nc): for i in range(nr - 1): eloc = [0, 0] for idx, thops in enumerate([[tC_aa, tA_aa], [tC_bb, tA_bb]]): tC, tA = thops peps2 = peps.copy(peps0) peps2[i, j] = einsum('xqp,pludr->qlxudr', tC, peps2[i, j]).merge_adjpair(2, 3) peps2[i + 1, j] = einsum('xqp,pludr->qluxdr', tA, peps2[i + 1, j]).merge_adjpair(3, 4) sgn = fpeps_util.genParitySgn(peps2[i + 1, j].ptys[1], peps2[i + 1, j].dims[1]) peps2[i + 1, j] = einsum('lL,qLudr->qludr', sgn, peps2[i + 1, j]) peps2b = reflection(peps2) eloc[idx] = 2.0 * fpeps_util.fdot(peps2b, peps1b) if debug: print 't<i,j>=', (i, j), 'eloc=', sum(eloc), eloc etot += sum(eloc) # horizontal bond # |/ |/ # --A----B-- # /| /| # *----* # | | if debug: print "\nHbonds:" for i in range(nr): for j in range(nc - 1): for idx, thops in enumerate([[tC_aa, tA_aa], [tC_bb, tA_bb]]): tC, tA = thops peps2 = peps.copy(peps0) peps2[i, j] = einsum('xqp,pludr->qludxr', tC, peps2[i, j]).merge_adjpair(4, 5) peps2[i, j + 1] = einsum('xqp,pludr->qxludr', tA, peps2[i, j + 1]).merge_adjpair(1, 2) sgn = fpeps_util.genParitySgn(peps2[i, j].ptys[2], peps2[i, j].dims[2]) peps2[i, j] = einsum('uU,qlUdr->qludr', sgn, peps2[i, j]) #??? WHY??? => ABSORBED. #for k in range(i): # sgn = fpeps_util.genParitySgn(peps2[k,j+1].ptys[0],peps2[k,j+1].dims[0]) # peps2[k,j+1] = einsum('qQ,Qludr->qludr',sgn,peps2[k,j+1]) peps2b = reflection(peps2) eloc[idx] = 2.0 * fpeps_util.fdot(peps2b, peps1b) if debug: print 't<i,j>=', (i, j), 'eloc=', sum(eloc), eloc etot += sum(eloc) return ovlp, etot
def energy_fpeps2by2(peps0): debug = True nr, nc = peps0.shape # <P|P> tmp = peps0[0, 1].copy() p23 = tmp.ptys[0] d23 = tmp.dims[0] p1 = tmp.ptys[1] d1 = tmp.dims[1] swap1 = fpeps_util.genSwap(p23, d23, p1, d1) # In fact, for 'uniform' distribution swap1=swap2 tmp = peps0[0, 2].copy() p23 = tmp.ptys[0] d23 = tmp.dims[0] p1 = tmp.ptys[2] d1 = tmp.dims[2] swap2 = fpeps_util.genSwap(p23, d23, p1, d1) # 'Bosonic peps' peps1 = peps.copy(peps0) peps1[0, 1] = einsum('pludr,pLlP->PLudr', peps1[0, 1], swap1) peps1[0, 2] = einsum('pludr,pUuP->PlUdr', peps1[0, 2], swap2) ovlp = peps.dot(peps1, peps1) if debug: print print "Ovlp(bare)=", peps.dot(peps0, peps0) print "Ovlp(swap)=", ovlp etot = 0.0 # <P|U[i]|P> if debug: print "\nU-terms:" U = 1.5 uterm = fpeps_util.genUterm(U) for j in range(nc): for i in range(nr): peps2 = peps.copy(peps1) peps2[i, j] = einsum('Pp,pludr->Pludr', uterm, peps1[i, j]) eloc = peps.dot(peps1, peps2) if debug: print '(i,j)=', (i, j), ' <U>=', eloc etot = etot + eloc exit() # # # # a b c d # # | | | | # # | 2--*-3 # # |/ |/ # # 0----1 # # # tC_aa,tA_aa = fpeps_util.genTaa() # tC_bb,tA_bb = fpeps_util.genTbb() # # # H02 = vertical bond # peps2 = peps1.copy() # peps2[0,0] = einsum('xqp,pludr->qlxudr',tC_aa,peps1[0,0]).merge_adjpair(2,3) # peps2[1,0] = einsum('xqp,pludr->qluxdr',tA_aa,peps1[1,0]).merge_adjpair(3,4) # elocA = peps.dot(peps1,peps2) # peps2 = peps1.copy() # peps2[0,0] = einsum('xqp,pludr->qlxudr',tC_bb,peps1[0,0]).merge_adjpair(2,3) # peps2[1,0] = einsum('xqp,pludr->qluxdr',tA_bb,peps1[1,0]).merge_adjpair(3,4) # elocB = peps.dot(peps1,peps2) # etot = etot + 2.0*(elocA+elocB) # if debug: # print # print 't02aa=',elocA # print 't02bb=',elocB # # # H23 = horizontal bond # # | | # # *----* # # |/ |/ # # --2----3-- # # / / # peps2 = peps1.copy() # peps2[1,0] = einsum('xqp,pludr->qludxr',tC_aa,peps1[1,0]).merge_adjpair(4,5) # peps2[1,1] = einsum('xqp,pludr->qxludr',tA_aa,peps1[1,1]).merge_adjpair(1,2) # elocA = peps.dot(peps1,peps2) # peps2 = peps1.copy() # peps2[1,0] = einsum('xqp,pludr->qludxr',tC_bb,peps1[1,0]).merge_adjpair(4,5) # peps2[1,1] = einsum('xqp,pludr->qxludr',tA_bb,peps1[1,1]).merge_adjpair(1,2) # elocB = peps.dot(peps1,peps2) # etot = etot + 2.0*(elocA+elocB) # if debug: # print # print 't23aa=',elocA # print 't23bb=',elocB # # # parity along physical index # parity = fpeps_util.genParitySgn([0,1],[2,2]) # # # H01 - hbond # peps2 = peps1.copy() # peps2[0,0] = einsum('xqp,pludr->qludxr',tC_aa,peps1[0,0]).merge_adjpair(4,5) # peps2[0,1] = einsum('xqp,pludr->qxludr',tA_aa,peps1[0,1]).merge_adjpair(1,2) # peps2[1,0] = einsum( 'qp,pludr->qludr',parity,peps1[1,0]) # peps2[1,1] = einsum( 'qp,pludr->qludr',parity,peps1[1,1]) # elocA = peps.dot(peps1,peps2) # peps2 = peps1.copy() # peps2[0,0] = einsum('xqp,pludr->qludxr',tC_bb,peps1[0,0]).merge_adjpair(4,5) # peps2[0,1] = einsum('xqp,pludr->qxludr',tA_bb,peps1[0,1]).merge_adjpair(1,2) # peps2[1,0] = einsum( 'qp,pludr->qludr',parity,peps1[1,0]) # peps2[1,1] = einsum( 'qp,pludr->qludr',parity,peps1[1,1]) # elocB = peps.dot(peps1,peps2) # etot = etot + 2.0*(elocA+elocB) # if debug: # print # print 't01aa=',elocA # print 't01bb=',elocB # # # H13 - vbond # peps2 = peps1.copy() # peps2[0,1] = einsum( 'qp,pludr->qludr',parity,peps1[0,1]) # peps2[0,1] = einsum('xqp,pludr->qlxudr',tC_aa,peps2[0,1]).merge_adjpair(2,3) # peps2[1,1] = einsum('xqp,pludr->qluxdr',tA_aa,peps1[1,1]).merge_adjpair(3,4) # peps2[1,1] = einsum( 'qp,pludr->qludr',parity,peps2[1,1]) # elocA = peps.dot(peps1,peps2) # peps2 = peps1.copy() # peps2[0,1] = einsum( 'qp,pludr->qludr',parity,peps1[0,1]) # peps2[0,1] = einsum('xqp,pludr->qlxudr',tC_bb,peps2[0,1]).merge_adjpair(2,3) # peps2[1,1] = einsum('xqp,pludr->qluxdr',tA_bb,peps1[1,1]).merge_adjpair(3,4) # peps2[1,1] = einsum( 'qp,pludr->qludr',parity,peps2[1,1]) # elocB = peps.dot(peps1,peps2) # etot = etot + 2.0*(elocA+elocB) # if debug: # print # print 't13aa=',elocA # print 't13bb=',elocB return ovlp, etot
def energy_fpeps2by2(peps0): nr, nc = peps0.shape # <P|P> tmp = peps0[0, 1].copy() p23 = tmp.ptys[0] d23 = tmp.dims[0] p1 = tmp.ptys[2] d1 = tmp.dims[2] swap = fpeps_util.genSwap(p23, d23, p1, d1) peps1 = peps.copy(peps0) peps1[0, 1] = einsum('pludr,pUuP->PlUdr', peps1[0, 1], swap) ovlp = peps.dot(peps1, peps1) if debug: print print "Ovlp=", peps.dot(peps0, peps0) print "Ovlp=", ovlp etot = 0.0 # <P|U[i]|P> if debug: print "\nU-terms:" uterm = fpeps_util.genUterm(U) for i in range(nr): for j in range(nc): peps2 = peps.copy(peps1) peps2[i, j] = einsum('Pp,pludr->Pludr', uterm, peps1[i, j]) eloc = peps.dot(peps1, peps2) if debug: print '(i,j)=', (i, j), ' <U>=', eloc etot = etot + eloc # # a b c d # | | | | # | 1--*-3 # |/ |/ # 0----2 # tC_aa, tA_aa = fpeps_util.genTaa() tC_bb, tA_bb = fpeps_util.genTbb() # Test local terms: if debug: tCA_aa = einsum('xqr,xrp->qp', tC_aa, tA_aa) tCA_bb = einsum('xqr,xrp->qp', tC_bb, tA_bb) for i in [0, 1]: peps2 = peps.copy(peps1) peps2[i, 0] = einsum('qp,pludr->qludr', tCA_aa, peps1[i, 0]) elocA = 2.0 * peps.dot(peps1, peps2) print 't[' + str(i) + ']aa=', elocA peps2 = peps.copy(peps1) peps2[i, 0] = einsum('qp,pludr->qludr', tCA_bb, peps1[i, 0]) elocA = 2.0 * peps.dot(peps1, peps2) print 't[' + str(i) + ']bb=', elocA # Jordan-Wigner sign factor for i\=j parity = fpeps_util.genParitySgn([0, 1], [2, 2]) tC_aa = einsum('xqp,pr->xqr', tC_aa, parity) tC_bb = einsum('xqp,pr->xqr', tC_bb, parity) # H01 = vertical bond peps2 = peps.copy(peps1) peps2[0, 0] = einsum('xqp,pludr->qlxudr', tC_aa, peps1[0, 0]).merge_adjpair(2, 3) peps2[1, 0] = einsum('xqp,pludr->qluxdr', tA_aa, peps1[1, 0]).merge_adjpair(3, 4) elocA = 2.0 * peps.dot(peps1, peps2) peps2 = peps.copy(peps1) peps2[0, 0] = einsum('xqp,pludr->qlxudr', tC_bb, peps1[0, 0]).merge_adjpair(2, 3) peps2[1, 0] = einsum('xqp,pludr->qluxdr', tA_bb, peps1[1, 0]).merge_adjpair(3, 4) elocB = 2.0 * peps.dot(peps1, peps2) etot = etot + (elocA + elocB) if debug: print print 't01aa=', elocA print 't01bb=', elocB # H13 = horizontal bond # | | # *----* # |/ |/ # --1----3-- # / / peps2 = peps.copy(peps1) peps2[1, 0] = einsum('xqp,pludr->qludxr', tC_aa, peps1[1, 0]).merge_adjpair(4, 5) peps2[1, 1] = einsum('xqp,pludr->qxludr', tA_aa, peps1[1, 1]).merge_adjpair(1, 2) elocA = 2.0 * peps.dot(peps1, peps2) peps2 = peps.copy(peps1) peps2[1, 0] = einsum('xqp,pludr->qludxr', tC_bb, peps1[1, 0]).merge_adjpair(4, 5) peps2[1, 1] = einsum('xqp,pludr->qxludr', tA_bb, peps1[1, 1]).merge_adjpair(1, 2) elocB = 2.0 * peps.dot(peps1, peps2) etot = etot + (elocA + elocB) if debug: print print 't13aa=', elocA print 't13bb=', elocB # H02 - hbond peps2 = peps.copy(peps1) peps2[0, 0] = einsum('xqp,pludr->qludxr', tC_aa, peps1[0, 0]).merge_adjpair(4, 5) peps2[0, 1] = einsum('xqp,pludr->qxludr', tA_aa, peps1[0, 1]).merge_adjpair(1, 2) peps2[1, 0] = einsum('qp,pludr->qludr', parity, peps1[1, 0]) peps2[1, 1] = einsum('qp,pludr->qludr', parity, peps1[1, 1]) elocA = 2.0 * peps.dot(peps1, peps2) peps2 = peps.copy(peps1) peps2[0, 0] = einsum('xqp,pludr->qludxr', tC_bb, peps1[0, 0]).merge_adjpair(4, 5) peps2[0, 1] = einsum('xqp,pludr->qxludr', tA_bb, peps1[0, 1]).merge_adjpair(1, 2) peps2[1, 0] = einsum('qp,pludr->qludr', parity, peps1[1, 0]) peps2[1, 1] = einsum('qp,pludr->qludr', parity, peps1[1, 1]) elocB = 2.0 * peps.dot(peps1, peps2) etot = etot + (elocA + elocB) if debug: print print 't02aa=', elocA print 't02bb=', elocB # H23 - vbond peps2 = peps.copy(peps1) peps2[0, 1] = einsum('qp,pludr->qludr', parity, peps1[0, 1]) peps2[0, 1] = einsum('xqp,pludr->qlxudr', tC_aa, peps2[0, 1]).merge_adjpair(2, 3) peps2[1, 1] = einsum('xqp,pludr->qluxdr', tA_aa, peps1[1, 1]).merge_adjpair(3, 4) peps2[1, 1] = einsum('qp,pludr->qludr', parity, peps2[1, 1]) elocA = 2.0 * peps.dot(peps1, peps2) peps2 = peps.copy(peps1) peps2[0, 1] = einsum('qp,pludr->qludr', parity, peps1[0, 1]) peps2[0, 1] = einsum('xqp,pludr->qlxudr', tC_bb, peps2[0, 1]).merge_adjpair(2, 3) peps2[1, 1] = einsum('xqp,pludr->qluxdr', tA_bb, peps1[1, 1]).merge_adjpair(3, 4) peps2[1, 1] = einsum('qp,pludr->qludr', parity, peps2[1, 1]) elocB = 2.0 * peps.dot(peps1, peps2) etot = etot + (elocA + elocB) if debug: print print 't23aa=', elocA print 't23bb=', elocB print print 'ovlp,etot=', ovlp, etot return ovlp, etot
def dump3by3(peps0): p1 = peps0[0, 1].ptys[0] d1 = peps0[0, 1].dims[0] p23 = peps0[1, 0].ptys[4] d23 = peps0[1, 0].dims[4] swap = fpeps_util.genSwap(p23, d23, p1, d1) coeff = einsum('alAsC,bkBAD,DGIH,LHMJO,ICJtN,cjpBE,EdGF,FeLK,fKqMP,PgRQ,QhWV,iVrXm,ORTS,WSXUn,TNUuo->abcdefghijklpqrstumno',\ peps0[0,0],peps0[1,0],swap,peps0[1,1],peps0[0,1],\ peps0[2,0],swap,swap,peps0[2,1],\ swap,swap,peps0[2,2],swap,peps0[1,2],peps0[0,2]) # abcdef|nmpqurstvw => Only four auxilliary indices left !!! coeff = coeff.merge([[0],[1],[2],[3],[4],[5],[6],[7],[8],\ [9,10,11],[12,13,14],[15,16,17],[18,19,20]]) coeff.prt() # 4^9 print 'einsum<PEPS|PEPS>=', einsum('abcdefghiMNOP,abcdefghiMNOP', coeff, coeff) nr, nc = peps0.shape nsite = nr * nc vtensor = np.zeros([4] * nsite) for qa in range(2): for qb in range(2): for qc in range(2): for qd in range(2): for qe in range(2): for qf in range(2): for qg in range(2): for qh in range(2): for qi in range(2): if coeff[qa, qb, qc, qd, qe, qf, qg, qh, qi, 0, 0, 0, 0].shape == 0: continue c0 = coeff[qa, qb, qc, qd, qe, qf, qg, qh, qi, 0, 0, 0, 0].reshape([2] * nsite) for ia in range(2): for ib in range(2): for ic in range(2): for id in range(2): for ie in range(2): for if0 in range( 2): for ig in range( 2): for ih in range( 2): for ii in range( 2 ): xa = addr[ qa, ia] xb = addr[ qb, ib] xc = addr[ qc, ic] xd = addr[ qd, id] xe = addr[ qe, ie] xf = addr[ qf, if0] xg = addr[ qg, ig] xh = addr[ qh, ih] xi = addr[ qi, ii] vtensor[xa,xb,xc,xd,xe,xf,xg,xh,xi] = \ c0[ia,ib,ic,id,ie,if0,ig,ih,ii] vcoeff = vtensor.flatten() return vcoeff