ITensorNHDMRG.jl is a library containing algorithms for non-hermitian density-matrix renormalization (DMRG) algorithms based on ITensor.jl and ITensorMPS.jl.
The object is given an operator
The ITensorNHDMRG package can be installed with the Julia package manager.
From the Julia REPL, type ] to enter the Pkg REPL mode and run:
~ julia
julia> ]
pkg> add https://github.com/tipfom/ITensorNHDMRG.jlNon-hermitian DMRG is currently supported for systems with and without quantum numbers.
Both one-sided Krylov iteration, i.e., the analog of solving biorthoblock [2] as well as the fidelity algorithm [3].
The current interface provided by nhdmrg is very similar to the dmrg function in ITensorMPS.jl and works with the libraries datatypes MPO and MPS.
An exemplary application of nhdmrg is provided in the following snippet for a non-Hermitian SSH chain.
using ITensors, ITensorMPS, ITensorNHDMRG, Random
let
# Create 200 Fermionic indices
N = 50
sites = siteinds("Fermion", 2N; conserve_qns=true)
# Input operator terms which define
# a Hamiltonian matrix, and convert
# these terms to an MPO tensor network
t2, tL, tR = 1.0, 0.9, 1.1
os = OpSum()
for j in 1:N
ja = 2(j - 1) + 1 # index on the a subsystem
jb = 2(j - 1) + 2 # index on the b subsystem
os += tL, "Cdag", ja, "C", jb
os += tR, "Cdag", jb, "C", ja
end
# intercell hopping
for l in 1:(N - 1)
lb = 2(l - 1) + 2 # index on the b subsystem
lna = 2(l - 1) + 3 # neighbor index on the a subsystem
os += t2, "Cdag", lb, "C", lna
os += t2, "Cdag", lna, "C", lb
end
H = MPO(os, sites)
# make results reproducible
rng = Xoshiro(1234)
# Create an initial random matrix product state
# with half filling
psi0 = random_mps(rng, sites, [ifelse(mod(i, 2) == 0, "Occ", "Emp") for i in 1:2N])
# Plan to do 15 passes or 'sweeps' of DMRG,
# setting maximum MPS internal dimensions
# for each sweep and maximum truncation cutoff
# used when adapting internal dimensions:
nsweeps = 5
maxdim = [20, 50, 100]
cutoff = 1E-10
noise = [1e-5, 1e-7, 0.0]
# Run the DMRG algorithm, returning energy
# (dominant eigenvalue) and optimized left- and right- MPS
energy, psil, psir = nhdmrg(H, psi0, psi0; nsweeps, maxdim, cutoff, noise, alg="onesided")
println("Final energy = $energy")
return nothing
end
# Output:
# After sweep 1 energy=-62.968112390229436 + 0.0im maxlinkdim=20 maxerr=8.22E-05 time=0.522
# After sweep 2 energy=-63.112380103700644 + 0.0im maxlinkdim=50 maxerr=5.40E-07 time=1.464
# After sweep 3 energy=-63.14434243476322 + 0.0im maxlinkdim=100 maxerr=5.96E-08 time=3.641
# After sweep 4 energy=-63.134169852574004 + 0.0im maxlinkdim=100 maxerr=9.50E-08 time=3.531
# After sweep 5 energy=-63.13514581299604 + 0.0im maxlinkdim=100 maxerr=4.64E-08 time=3.793
# Final energy = -63.13514581299604 + 0.0imThe eigen routine may be chosen by supplying either "onesided" or "twosided" as the keyword alg for nhdmrg; the biorthogonalization routine may be chosen by supplying either "biorthoblock" or "fidelity" as the biorthoalg keyword.
The system in Ref. [2] provided in the example folder.
For the two-sided Krylov solver we implemented
in KrylovKit.jl.
The biorthoblock algorithm is introduced in
The fidelity algorithm is introduced in