I have this program. I post it as it is.
If I write:
using MKL
using MKLSparse
It gives me (that’s an iteration of results with a matrix parameter on the first column):
02 | -0.37499999999999944 | 0.0 | -0.18749999999999972
04 | -0.375 | -2.7755575615628914e-16 | -0.09375
08 | -0.875 | -0.125 | -0.109375
16 | -3.2757653911111717 | -0.30009567388889646 | -0.20473533694444823
32 | -7.198931123379452 | -0.24519785826676754 | -0.2249665976056079
If i don’t use them, it gives me:
02 | -0.37499999999999944 | 0.0 | -0.18749999999999972
04 | -0.9098524898764077 | -0.2674262449382041 | -0.2274631224691019
08 | -2.68529096887001 | -0.4438596197484006 | -0.33566137110875127
16 | -5.43894887951664 | -0.3442072388308287 | -0.33993430496979
32 | -11.008233268476827 | -0.3480802743100117 | -0.34400728963990085
If instead of kron, you add kronecker package, nothing changes without MKL.
If you add MKL too, then it gives:
02 | -0.37499999999999944 | 0.0 | -0.18749999999999972
04 | -0.7838137951917248 | -0.20440689759586267 | -0.1959534487979312
08 | -1.603161567518434 | -0.20483694308167733 | -0.20039519593980426
16 | -3.9978146703099906 | -0.29933163784894457 | -0.2498634168943744
32 | -8.178459637176488 | -0.26129031042915607 | -0.25557686366176524
In the following text i will provide 2 versions of the code. The first one allocates a temporary matrix each iteration, called temp. See around line 45.
The first version gives the results above.
The second version prallocates temp with the maximum size it reaches through all the iterations. I view inside of it each iteration.
Without using MKL it works and the results are the same.
When using MKL it gives:
ERROR: LoadError: InexactError: Float64(-0.9999999999999998 + 1.4994064124073605e-43im)
Stacktrace:
[1] Real
@ ./complex.jl:44 [inlined]
[2] convert
@ ./number.jl:7 [inlined]
[3] setindex!(A::Vector{Float64}, x::ComplexF64, i1::Int64)
@ Base ./array.jl:1021
[4] NRG(Delta::Float64, max_states::Int16, NIter::Int32, Energy::Vector{Float64}, Energy_2::Vector{Float64}, Energy_bond::Vector{Float64})
@ Main ~/Desktop/Programmi/MODULO_05/executable_and_libraries/bin/simple_nrg_optimized.jl:36
[5] top-level scope
Instead of writing two different version, i will write the additional 2 lines of the second version and comment on the right
using SparseArrays
using LinearAlgebra
using BenchmarkTools
using MKL
using MKLSparse
function NRG(Delta::Real, max_states::Integer, NIter::Integer, Energy::Vector, Energy_2::Vector, Energy_bond::Vector)
Sz = sparse(Float64[[0.5, 0] [0, -0.5]])
Sp = sparse(Float64[[0, 0] [1.0, 0]])
Sm = sparse(Float64[[0, 1.0] [0, 0]])
Ham = sparse(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) # ENABLE IN VERSION 2
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.
#trunc index
m_next = m*m # H_super size
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]
Energy_2[i] = Energy[i]/lattice_size
if i> 1
Energy_bond[i] = (Energy[i] - Energy[i-1]) / (lattice_size/2)
end
# Preallocation for mul!
#temp = @view temp_matr[1:m_next,1:trunc_index] # ENABLE IN VERSION 2
temp = Array{Float64}(undef, m_next, trunc_index) # DISABLE IN VERSION 2
#Higher dimension kron
mul!(temp, H_super, trunc_matrx)
Block_Ham = trunc_matrx' * temp
mul!(temp, kron(sparse(I, m, m), Block_Sz), trunc_matrx)
Block_Sz = trunc_matrx' * temp
mul!(temp, kron(sparse(I, m, m), Block_Sp), trunc_matrx)
Block_Sp = trunc_matrx' * temp
mul!(temp, kron(sparse(I, m, m), Block_Sm), trunc_matrx)
Block_Sm = trunc_matrx' * temp
m = trunc_index # for next iterations
end
end
#Definition of starting parameters
Delta::Float64 = 0.5
max_states::Int16 = 5
NIter::Int32 = 5 #Final lattice size: 2^Iter
#output vectors
Energy = Vector{Float64}(undef, NIter)
Energy_2 = Vector{Float64}(undef, NIter)
Energy_bond = Vector{Float64}(undef, NIter)
Energy_bond[1] = 0 #no bond
NRG(Delta, max_states, NIter, Energy, Energy_2, Energy_bond)
for i = 1:NIter
println(lpad(2^i, 2, "0"), " | ", Energy[i], " | ", Energy_bond[i], " | ", Energy_2[i])
end