|
| 1 | +using ITensors |
| 2 | +using ITensorInfiniteMPS |
| 3 | +using Test |
| 4 | +# |
| 5 | +# InfiniteMPO has dangling links at the end of the chain. We contract these on the outside |
| 6 | +# with l,r terminating vectors, to make a finite lattice MPO. |
| 7 | +# |
| 8 | +function terminate(h::InfiniteMPO)::MPO |
| 9 | + Ncell = nsites(h) |
| 10 | + # left termination vector |
| 11 | + il0 = commonind(h[1], h[0]) |
| 12 | + l = ITensor(0.0, il0) |
| 13 | + l[il0 => dim(il0)] = 1.0 #assuming lower reg form in h |
| 14 | + # right termination vector |
| 15 | + iln = commonind(h[Ncell], h[Ncell + 1]) |
| 16 | + r = ITensor(0.0, iln) |
| 17 | + r[iln => 1] = 1.0 #assuming lower reg form in h |
| 18 | + # build up a finite MPO |
| 19 | + hf = MPO(Ncell) |
| 20 | + hf[1] = dag(l) * h[1] #left terminate |
| 21 | + hf[Ncell] = h[Ncell] * dag(r) #right terminate |
| 22 | + for n in 2:(Ncell - 1) |
| 23 | + hf[n] = h[n] #fill in the bulk. |
| 24 | + end |
| 25 | + return hf |
| 26 | +end |
| 27 | +# |
| 28 | +# Terminate and then call expect |
| 29 | +# for inf ψ and finite h, which is already supported in src/infinitecanonicalmps.jl |
| 30 | +# |
| 31 | +function ITensors.expect(ψ::InfiniteCanonicalMPS, h::InfiniteMPO) |
| 32 | + return expect(ψ, terminate(h)) #defer to src/infinitecanonicalmps.jl |
| 33 | +end |
| 34 | + |
| 35 | +#H = ΣⱼΣn (½ S⁺ⱼS⁻ⱼ₊n + ½ S⁻ⱼS⁺ⱼ₊n + SᶻⱼSᶻⱼ₊n) |
| 36 | +function ITensorInfiniteMPS.unit_cell_terms(::Model"heisenbergNNN"; NNN::Int64) |
| 37 | + opsum = OpSum() |
| 38 | + for n in 1:NNN |
| 39 | + J = 1.0 / n |
| 40 | + opsum += J * 0.5, "S+", 1, "S-", 1 + n |
| 41 | + opsum += J * 0.5, "S-", 1, "S+", 1 + n |
| 42 | + opsum += J, "Sz", 1, "Sz", 1 + n |
| 43 | + end |
| 44 | + return opsum |
| 45 | +end |
| 46 | + |
| 47 | +function ITensorInfiniteMPS.unit_cell_terms(::Model"hubbardNNN"; NNN::Int64) |
| 48 | + U::Float64 = 0.25 |
| 49 | + t::Float64 = 1.0 |
| 50 | + V::Float64 = 0.5 |
| 51 | + opsum = OpSum() |
| 52 | + opsum += (U, "Nupdn", 1) |
| 53 | + for n in 1:NNN |
| 54 | + tj, Vj = t / n, V / n |
| 55 | + opsum += -tj, "Cdagup", 1, "Cup", 1 + n |
| 56 | + opsum += -tj, "Cdagup", 1 + n, "Cup", 1 |
| 57 | + opsum += -tj, "Cdagdn", 1, "Cdn", 1 + n |
| 58 | + opsum += -tj, "Cdagdn", 1 + n, "Cdn", 1 |
| 59 | + opsum += Vj, "Ntot", 1, "Ntot", 1 + n |
| 60 | + end |
| 61 | + return opsum |
| 62 | +end |
| 63 | + |
| 64 | +function ITensors.space(::SiteType"FermionK", pos::Int; p=1, q=1, conserve_momentum=true) |
| 65 | + if !conserve_momentum |
| 66 | + return [QN("Nf", -p) => 1, QN("Nf", q - p) => 1] |
| 67 | + else |
| 68 | + return [ |
| 69 | + QN(("Nf", -p), ("NfMom", -p * pos)) => 1, |
| 70 | + QN(("Nf", q - p), ("NfMom", (q - p) * pos)) => 1, |
| 71 | + ] |
| 72 | + end |
| 73 | +end |
| 74 | + |
| 75 | +function fermion_momentum_translator(i::Index, n::Integer; N=6) |
| 76 | + #@show n |
| 77 | + ts = tags(i) |
| 78 | + translated_ts = ITensorInfiniteMPS.translatecelltags(ts, n) |
| 79 | + new_i = replacetags(i, ts => translated_ts) |
| 80 | + for j in 1:length(new_i.space) |
| 81 | + ch = new_i.space[j][1][1].val |
| 82 | + mom = new_i.space[j][1][2].val |
| 83 | + new_i.space[j] = Pair(QN(("Nf", ch), ("NfMom", mom + n * N * ch)), new_i.space[j][2]) |
| 84 | + end |
| 85 | + return new_i |
| 86 | +end |
| 87 | + |
| 88 | +function ITensors.op!(Op::ITensor, opname::OpName, ::SiteType"FermionK", s::Index...) |
| 89 | + return ITensors.op!(Op, opname, SiteType("Fermion"), s...) |
| 90 | +end |
| 91 | + |
| 92 | +@testset verbose = true "InfiniteMPOMatrix -> InfiniteMPO" begin |
| 93 | + ferro(n) = "↑" |
| 94 | + antiferro(n) = isodd(n) ? "↑" : "↓" |
| 95 | + |
| 96 | + models = [(Model"heisenbergNNN"(), "S=1/2"), (Model"hubbardNNN"(), "Electron")] |
| 97 | + @testset "H=$model, Ncell=$Ncell, NNN=$NNN, Antiferro=$Af, qns=$qns" for (model, site) in |
| 98 | + models, |
| 99 | + qns in [false, true], |
| 100 | + Ncell in 2:6, |
| 101 | + NNN in 1:(Ncell - 1), |
| 102 | + Af in [true, false] |
| 103 | + |
| 104 | + if isodd(Ncell) && Af #skip test since Af state does fit inside odd cells. |
| 105 | + continue |
| 106 | + end |
| 107 | + initstate(n) = Af ? antiferro(n) : ferro(n) |
| 108 | + model_kwargs = (NNN=NNN,) |
| 109 | + s = infsiteinds(site, Ncell; initstate, conserve_qns=qns) |
| 110 | + ψ = InfMPS(s, initstate) |
| 111 | + Hi = InfiniteMPO(model, s; model_kwargs...) |
| 112 | + Hs = InfiniteSum{MPO}(model, s; model_kwargs...) |
| 113 | + Es = expect(ψ, Hs) |
| 114 | + Ei = expect(ψ, Hi) |
| 115 | + #@show Es Ei |
| 116 | + @test sum(Es[1:(Ncell - NNN)]) ≈ Ei atol = 1e-14 |
| 117 | + end |
| 118 | + |
| 119 | + @testset "FQHE Hamitonian" begin |
| 120 | + N = 6 |
| 121 | + model = Model"fqhe_2b_pot"() |
| 122 | + model_params = (Vs=[1.0, 0.0, 1.0, 0.0, 0.1], Ly=3.0, prec=1e-8) |
| 123 | + trf = fermion_momentum_translator |
| 124 | + function initstate(n) |
| 125 | + mod1(n, 3) == 1 && return 2 |
| 126 | + return 1 |
| 127 | + end |
| 128 | + p = 1 |
| 129 | + q = 3 |
| 130 | + conserve_momentum = true |
| 131 | + s = infsiteinds("FermionK", N; translator=trf, initstate, conserve_momentum, p, q) |
| 132 | + ψ = InfMPS(s, initstate) |
| 133 | + Hs = InfiniteSum{MPO}(model, s; model_params...) |
| 134 | + Hi = InfiniteMPO(model, s, trf; model_params...) |
| 135 | + Es = expect(ψ, Hs) |
| 136 | + Ei = expect(ψ, Hi) |
| 137 | + #@show Es Ei |
| 138 | + @test Es[1] ≈ Ei atol = 1e-14 |
| 139 | + end |
| 140 | +end |
| 141 | +nothing |
0 commit comments