Non-Hermitian DMRG in ITensor

Hello everyone,

I implemented a non-Hermitian DMRG variant [1, 2] in ITensor, which is available at https://github.com/tipfom/ITensorNHDMRG.jl.
Using the library is very straightforward and amounts to replacing the call to dmrg with a call to nhdmrg, see the example in the REAMDE or the examples at https://github.com/tipfom/ITensorNHDMRG.jl/tree/main/examples.
All normal functionality such as QN conservation should be supported.

If you have any use for the library, feel free to check it out and let me know if you find are any bugs.

[1] doi: 10.1103/5vnl-w9p4
[2] doi: 10.1103/PhysRevB.105.205125

5 Likes

This is very interesting to see. Thanks for sharing about it, and some of us or our collaborators may give it a try soon and we can then give you feedback about how it’s working for our cases.

1 Like

Interesting and nice work. In the example 2401.15000_nhdmrg.jl, the codes can not obtain the correct result, if we change biorthoalg = “biorthoblock”.

LoadError: Index arrows must be the same to add, subtract, map, or scale QN ITensors
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:35
[2] _map!!(f::Function, R::NDTensors.BlockSparseTensor{ComplexF64, 2, Tuple{Index{Vector{Pair{QN, Int64}}}, Index{Vector{Pair{QN, Int64}}}}, NDTensors.BlockSparse{ComplexF64, Vector{ComplexF64}, 2}}, T1::NDTensors.BlockSparseTensor{ComplexF64, 2, Tuple{Index{Vector{Pair{QN, Int64}}}, Index{Vector{Pair{QN, Int64}}}}, NDTensors.BlockSparse{ComplexF64, Vector{ComplexF64}, 2}}, T2::NDTensors.BlockSparseTensor{ComplexF64, 2, Tuple{Index{Vector{Pair{QN, Int64}}}, Index{Vector{Pair{QN, Int64}}}}, NDTensors.BlockSparse{ComplexF64, Vector{ComplexF64}, 2}})
@ ITensors ~/.julia/packages/ITensors/SOADD/src/itensor.jl:1912
[3] map!(f::Function, R::ITensor, T1::ITensor, T2::ITensor)
@ ITensors ~/.julia/packages/ITensors/SOADD/src/itensor.jl:1921
[4] copyto!
@ ~/.julia/packages/ITensors/SOADD/src/broadcast.jl:309 [inlined]
[5] materialize!
@ ./broadcast.jl:878 [inlined]
[6] materialize!
@ ./broadcast.jl:875 [inlined]
[7] _add(A::NDTensors.BlockSparseTensor{ComplexF64, 2, Tuple{Index{Vector{Pair{QN, Int64}}}, Index{Vector{Pair{QN, Int64}}}}, NDTensors.BlockSparse{ComplexF64, Vector{ComplexF64}, 2}}, B::NDTensors.BlockSparseTensor{ComplexF64, 2, Tuple{Index{Vector{Pair{QN, Int64}}}, Index{Vector{Pair{QN, Int64}}}}, NDTensors.BlockSparse{ComplexF64, Vector{ComplexF64}, 2}})
@ ITensors ~/.julia/packages/ITensors/SOADD/src/itensor.jl:1815
[8] +(A::ITensor, B::ITensor)
@ ITensors ~/.julia/packages/ITensors/SOADD/src/itensor.jl:1823
[9] nhfactorize(::NDTensors.BackendSelection.Algorithm{:biorthoblock, @NamedTuple{}}, phil::ITensor, phir::ITensor, drho::ITensor, lindsl::Vector{Index{Vector{Pair{QN, Int64}}}}, lindsr::Vector{Index{Vector{Pair{QN, Int64}}}}, targettags::ITensors.TagSets.GenericTagSet{BitIntegers.UInt256, 4}, identities::Nothing; kwargs::@Kwargs{mindim::Int64, maxdim::Int64, cutoff::Float64})
@ ITensorNHDMRG ~/.julia/dev/ITensorNHDMRG/src/nhfactorize.jl:16
[10] nhreplacebond!(Ml::MPS, Mr::MPS, b::Int64, phil::ITensor, phir::ITensor, alg::String, identities::Nothing; ortho::String, eigen_perturbation::ITensor, mindim::Int64, maxdim::Int64, cutoff::Float64, kwargs::@Kwargs{})
@ ITensorNHDMRG ~/.julia/dev/ITensorNHDMRG/src/nhfactorize.jl:100
[11] nhreplacebond!
@ ~/.julia/dev/ITensorNHDMRG/src/nhfactorize.jl:65 [inlined]
[12] macro expansion
@ ~/.julia/dev/ITensorNHDMRG/src/nhdmrg.jl:243 [inlined]
[13] macro expansion
@ ./timing.jl:421 [inlined]
[14] nhdmrg(PH::ITensorNHDMRG.ProjNHMPO, psil0::MPS, psir0::MPS, sweeps::Sweeps; alg::String, biorthoalg::String, isbiortho::Bool, observer::NoObserver, outputlevel::Int64, eigsolve_tol::Float64, eigsolve_krylovdim::Int64, eigsolve_maxiter::Int64, eigsolve_verbosity::Int64, eigsolve_which_eigenvalue::Symbol, biorthokwargs::@Kwargs{})
@ ITensorNHDMRG ~/.julia/dev/ITensorNHDMRG/src/nhdmrg.jl:186
[15] nhdmrg
@ ~/.julia/dev/ITensorNHDMRG/src/nhdmrg.jl:125 [inlined]
[16] #nhdmrg#8
@ ~/.julia/dev/ITensorNHDMRG/src/nhdmrg.jl:17 [inlined]
[17] nhdmrg
@ ~/.julia/dev/ITensorNHDMRG/src/nhdmrg.jl:8 [inlined]
[18] gap(N::Int64; alg::String, biorthoalg::String, t1::Float64, γ::Float64, V::Float64, t2::Float64, u::Float64, nexcitedstates::Int64, weight::Float64, offset::Nothing, scale::Float64)
@ Main ~/.julia/packages/ITensorNHDMRG/iZOiP/examples/2401.15000_nhdmrg.jl:96
[19] gap
@ ~/.julia/packages/ITensorNHDMRG/iZOiP/examples/2401.15000_nhdmrg.jl:45 [inlined]
[20] main()
@ Main ~/.julia/packages/ITensorNHDMRG/iZOiP/examples/2401.15000_nhdmrg.jl:163
[21] top-level scope
@ ~/.julia/packages/ITensorNHDMRG/iZOiP/examples/2401.15000_nhdmrg.jl:170
in expression starting at /Users/renjie/.julia/packages/ITensorNHDMRG/iZOiP/examples/2401.15000_nhdmrg.jl:170

Dear @Jren,

thanks for bringing this up! It is fixed now in the repository. Sorry for taking so long, I overlooked the notification.

Let me know if there is anything else I can help with!

Bests,
tipfom

Hello tipfom,

Thanks for sharing about it,I have a somewhat naive question: how do you calculate the expectation value under a biorthogonal basis?

Bests,

jie