MKL package wrong results

Enlil50
Mon, 19 Feb 2024 14:27:14 +0000
General Usage

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

7 posts - 3 participants