LAPACK: ZHEEV routine failing for large matrices

0

I have a Fortran 90 code which is finding the eigenvalues of a spin-chain Hamiltonian after block-diagonalizing. I diagonalize each block as they are generated, and this seems to work just fine until the size of the block gets too large, at which point I get the error.

Exception thrown at 0x05E8A247 (mkl_avx2.dll) in spinchain.exe: 0xC0000005: Access violation writing location 0x054E8000.

where I am using the Intel Fortran compiler with MKL libraries in Visual Studio 2017. From what I can tell it appears that when the order of the block matrix is larger than around 60 I get this error. Running in Release mode (as opposed to Debug) the code will run all the way through without any complaints, but I assume the output is incorrect.

I wrote a short code to create an N x N hermitian matrix and run it through the zheev routine. For simplicity I chose the matrix of all ones, which has N-1 zero eigenvalues and a single eigenvalue N. I simply loop through values of N, generating the matrix and diagonalizing it with zheev(), printing N, the max eigenvalue, and the sum of all eigenvalues. I find that everything is fine up to N=51, at which point the maximum eigenvalue returns 52 and then I get an exception when I try to deallocate the arrays with the error Critical error detected c0000374.

Hitting "continue" the exception turns into

Unhandled exception at 0x77A5A879 (ntdll.dll) in Eigtest.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77A95910).

Code below:

program Eigenvalues
    implicit none
    integer, parameter :: dp = kind(0.d0)
    integer :: N, lwork, info, i
    real(dp), allocatable :: lambda(:), work(:), rwork(:)
    complex(dp), allocatable :: H(:,:)

    do N = 1,70

        lwork = 3*N
        allocate(H(N,N))
        allocate(lambda(N))
        allocate(work(lwork))
        allocate(rwork(lwork))

        H = dcmplx(1.0_dp,0)

        call zheev('N','U',N,H,N,lambda,work,lwork,rwork,info)

        if (info == 0) then
                write(*,'(I5, F16.12, F16.12)'), N, lambda(N), sum(lambda)
        else
            print*, "diagonalization failed: info = ", info
            read*, i
            stop
        end if

        deallocate(H,lambda,work,rwork)

    end do

    read*, i

end program

I also wrote another version of the code where I fix N as a parameter at the beginning and define the arrays without allocatable, which will run without any exceptions but gives the wrong eigenvalues for N=51 and most values above N=51.

Forgive me if my code is bad, I'm a physicist, not a programmer. Comments or suggestions appreciated.

fortran
fortran90
lapack
intel-fortran
intel-mkl
asked on Stack Overflow Mar 30, 2018 by Kai • edited Mar 30, 2018 by Kai

1 Answer

1

According to the man page of zheev, the array work is expected to be complex*16, so we probably need something like

real(dp), allocatable :: lambda(:), rwork(:)
complex(dp), allocatable :: H(:,:), work(:)

(this seems to be working with gfortran on my computer).

answered on Stack Overflow Mar 30, 2018 by roygvib

User contributions licensed under CC BY-SA 3.0