def getTridiagonal(HL, HR, H, k, psi, psiCompare=None): accuracy = 1e-10 # 1e-12 v = bops.multiContraction(psi[k], psi[k + 1], '2', '0') # Small innaccuracies ruin everything! v.set_tensor(v.get_tensor() / bops.getNodeNorm(v)) psiCopy = bops.copyState(psi) base = [] base.append(v) Hv = applyHToM(HL, HR, H, v, k) alpha = bops.multiContraction(v, Hv, '0123', '0123*').get_tensor() if psiCompare is not None: copyV = bops.copyState([v])[0] psiCopy = bops.assignNewSiteTensors(psiCopy, k, copyV, '>>')[0] E = stateEnergy(psi, H) w = bops.addNodes(Hv, bops.multNode(v, -alpha)) beta = bops.getNodeNorm(w) # Start with T as an array and turn into tridiagonal matrix at the end. Tarr = [[0, 0, 0]] Tarr[0][1] = alpha counter = 0 formBeta = 2 * beta # This is just some value to init formBeta > beta. while (beta > accuracy) and (counter <= 50) and (beta < formBeta): Tarr[counter][2] = beta Tarr.append([0, 0, 0]) Tarr[counter + 1][0] = beta counter += 1 v = bops.multNode(w, 1 / beta) base.append(v) if psiCompare is not None: copyV = bops.copyState([v])[0] psiCopy = bops.assignNewSiteTensors(psiCopy, k, copyV, '>>')[0] Hv = applyHToM(HL, HR, H, v, k) alpha = bops.multiContraction(v, Hv, '0123', '0123*').get_tensor() Tarr[counter][1] = alpha w = bops.addNodes(bops.addNodes(Hv, bops.multNode(v, -alpha)), \ bops.multNode(base[counter-1], -beta)) formBeta = beta beta = bops.getNodeNorm(w) T = np.zeros((len(Tarr), len(Tarr)), dtype=complex) T[0][0] = Tarr[0][1] if len(Tarr) > 1: T[0][1] = Tarr[0][2] for i in range(1, len(Tarr)-1): T[i][i-1] = Tarr[i][0] T[i][i] = Tarr[i][1] T[i][i+1] = Tarr[i][2] T[len(Tarr)-1][len(Tarr)-2] = Tarr[len(Tarr)-1][0] T[len(Tarr) - 1][len(Tarr) - 1] = Tarr[len(Tarr) - 1][1] return [T, base]
def stateEnergy(psi: List[tn.Node], H: HOp): E = 0 for i in range(len(psi)): psiCopy = bops.copyState(psi) single_i = bops.copyState([H.singles[i]])[0] psiCopy[i] = bops.permute(tn.contract(psiCopy[i][1] ^ single_i[0], name=('site' + str(i))), [0, 2, 1]) E += bops.getOverlap(psiCopy, psi) bops.removeState(psiCopy) tn.remove_node(single_i) for i in range(len(psi) - 1): psiCopy = bops.copyState(psi) r2l = bops.copyState([H.r2l[i+1]])[0] l2r = bops.copyState([H.l2r[i]])[0] psiCopy[i][2] ^ psiCopy[i+1][0] psiCopy[i][1] ^ l2r[0] r2l[0] ^ psiCopy[i+1][1] l2r[2] ^ r2l[2] M = tn.contract_between(psiCopy[i], \ tn.contract_between(l2r, tn.contract_between(r2l, psiCopy[i+1]))) if bops.multiContraction(M, M, '0123', '0123*').tensor != 0: [psiCopy, te] = bops.assignNewSiteTensors(psiCopy, i, M, '>>') E += bops.getOverlap(psiCopy, psi) bops.removeState(psiCopy) tn.remove_node(r2l) tn.remove_node(l2r) return E
def dmrgStep(HL, HR, H, psi, k, dir, psiCompare=None, opts=None): # Perform a single DMRG step: # 1. Contracts psi(k) and psi(k + dir) to get M. # 2. Performs lancsoz and get a new contracted M. # 3. Performs an SVD in order to get the new working site, at k + dir. # 4. Calculates HL(k) / HR(k) (according to dir) k1 = k k2 = k + 1 [M, E0] = lanczos(HL, HR, H, k1, psi, psiCompare) [psi, truncErr] = bops.assignNewSiteTensors(psi, k, M, dir) if dir == '>>': if psiCompare is not None: for state in psiCompare: state = bops.shiftWorkingSite(state, k, '>>') psi = bops.getOrthogonalState(state, psiInitial=psi) HLs, HRs = getHLRs(H, psi, workingSite=k+1) return psi, HLs, HRs, E0, truncErr else: newHL = getHLR(psi, k, H, dir, HL) return psi, newHL, E0, truncErr else: if psiCompare is not None: for state in psiCompare: state = bops.shiftWorkingSite(state, k, '<<') psi = bops.getOrthogonalState(state, psiInitial=psi) HLs, HRs = getHLRs(H, psi, workingSite=k) return psi, HLs, HRs, E0, truncErr else: newHR = getHLR(psi, k+1, H, dir, HR) return psi, newHR, E0, truncErr
def applyH(psi: List[tn.Node], H: HOp): psiCopy = bops.copyState(psi) single_0 = bops.copyState([H.singles[0]])[0] psiCopy[0] = bops.permute(tn.contract(psiCopy[0][1] ^ single_0[0], name=('site' + str(0))), [0, 2, 1]) result = psiCopy for i in range(1, len(psi)): psiCopy = bops.copyState(psi) single_i = bops.copyState([H.singles[i]])[0] psiCopy[i] = bops.permute(tn.contract(psiCopy[i][1] ^ single_i[0], name=('site' + str(i))), [0, 2, 1]) result = bops.addStates(result, psiCopy) for i in range(len(psi) - 1): psiCopy = bops.copyState(psi) r2l = bops.copyState([H.r2l[i+1]])[0] l2r = bops.copyState([H.l2r[i]])[0] psiCopy[i][2] ^ psiCopy[i+1][0] psiCopy[i][1] ^ l2r[0] r2l[0] ^ psiCopy[i+1][1] l2r[2] ^ r2l[2] M = tn.contract_between(psiCopy[i], \ tn.contract_between(l2r, tn.contract_between(r2l, psiCopy[i+1]))) [psiCopy, te] = bops.assignNewSiteTensors(psiCopy, i, M, '>>') result = bops.addStates(result, psiCopy) return result