I tried to simplify on the fly a program I’m passing around different threads this days, ahha. Sorry for the useless sparse notation, but removing it doesn’t really work well, probably cause I’m trying to write it fast (Murhpy is here).
using SparseArrays
using LinearAlgebra
function NRG(tol_zeros::Real, Delta::Real, max_states::Integer, NIter::Integer, Energy::Vector)
Sz = Float64[[0.5, 0] [0, -0.5]]
Sp = Float64[[0, 0] [1.0, 0]]
Sm = Float64[[0, 1.0] [0, 0]]
Ham = zeros(2,2)
Block_Sp = Sp
Block_Sm = Sm
Block_Sz = Sz
Block_Ham = Ham
temp_matr = Array{Float64}(undef, max_states*max_states, max_states)
m::Int64 = 2 #hilbert size
for i = 1:NIter
lattice_size::Int64 = 2^i #spatial row_size
#Hamiltonian constructor
H_super = kron(Block_Ham, sparse(I,m,m)) .+ kron(sparse(I,m,m), Block_Ham) .- Delta*kron(Block_Sz, Block_Sz) .+ 0.5*(kron(Block_Sp, Block_Sm) .+ kron(Block_Sm, Block_Sp))
H_dense_super = collect(H_super) #I make a dense matrix as this is a dummy example with full diagonalization.
H_dense_super .= ifelse.(abs.(H_dense_super) .< tol_zeros, 0, H_dense_super)
#trunc index
m_next = m*m # hilbert space row_size after kron products (mul!)
trunc_index = min(m_next,max_states)
#Diagonalization part
evals, evecs = eigen!(H_dense_super) #ascendent ordered
Energy[i] = evals[1]
trunc_matrx = @view evecs[:,1:trunc_index]
# Preallocation for mul!
temp = @view temp_matr[1:m_next,1:trunc_index]
#Higher dimension kron
mul!(temp, H_super, trunc_matrx)
Block_Ham = trunc_matrx' * temp
mul!(temp, kron(I(m), Block_Sz), trunc_matrx)
Block_Sz = trunc_matrx' * temp
mul!(temp, kron(I(m), Block_Sp), trunc_matrx)
Block_Sp = trunc_matrx' * temp
mul!(temp, kron(I(m), Block_Sm), trunc_matrx)
Block_Sm = trunc_matrx' * temp
m = trunc_index # hilbert space row_size before next kron products
end
end
#Definition of starting parameters
tol_zeros = 1e-15
Delta::Float64 = 0.5
max_states::Int16 = 5
NIter::Int32 = 5
#output vectors
Energy = Vector{Float64}(undef, NIter)
NRG(tol_zeros, Delta, max_states, NIter, Energy)
for i = 1:NIter
println(lpad(2^i, 2, "0"), " | ", Energy[i])
end
If you comment line 26, which is the one in charge of cutting of noise, you will see the change in the printed numbers. If you want another change: you can cut off all the noise after multiplications of Block_stuff matrices too. It will change it a little.
Results with line 26 commented:
02 | -0.37499999999999944
04 | -0.9098524898764077
08 | -2.68529096887001
16 | -5.43894887951664
32 | -11.008233268476827
Results with line 26 not commented:
02 | -0.37499999999999944
04 | -0.909852489876408
08 | -1.958441200217832
16 | -4.031578973828303
32 | -8.18579752200281
These are the ground state (the smallest eigenvalues) of H_super. eigen! is ascendent ordered if not specified otherwise.
If you increase NIter, the accumulation of issue is really shown:
NIter=15
line 26 commented:
02 | -0.37499999999999944
04 | -0.9098524898764077
08 | -2.68529096887001
16 | -5.43894887951664
32 | -11.008233268476827
64 | -22.155185075093485
128 | -44.46508413287744
256 | -89.08621024836387
512 | -178.3284940709981
1024 | -356.81306310289483
2048 | -882.4065129795858
4096 | -1764.6907549298428
8192 | -3546.6964588803635
16384 | -7836.724421763094
32768 | -18904.125726973307
line 26 not commented:
02 | -0.37499999999999944
04 | -0.909852489876408
08 | -1.958441200217832
16 | -4.031578973828303
32 | -8.18579752200281
64 | -16.509651353250305
128 | -33.15732186748891
256 | -66.45256376684209
512 | -133.0429487095539
1024 | -266.22370226104385
2048 | -532.5852061229483
4096 | -1065.3082131523727
8192 | -2130.754292870491
16384 | -4261.646287787542
32768 | -8523.464327368076
Obvious to say that the better ones are the line 26 not commented results