Solving eigenvalue linear system with Fortran using Lapack zggev routine - fortran

I am trying to use the ZGGEV routine from Lapack to solve the general eigen value problem, namely, A x=v B x. Where v is the eigen-value. I'm doing a small test on some random matrixes. Let's say
A=[ -21.10-22.50i 53.50-50.50i -34.50+127.50i 7.50+0.50i;
-0.46-7.78i -3.50-37.50i -15.50+58.50i -10.50-1.50i;
4.30-5.50i 39.70-17.10i -68.50+12.50i -7.50-3.50i;
5.50+4.40i 14.40+43.30i -32.50-46.00i -19.00-32.50i]
B=[ 1.00-5.00i 1.60+1.20i -3.00+0.00i 0.00-1.00i ;
0.80-0.60i 3.00-5.00i -4.00+3.00i -2.40-3.20i ;
1.00+0.00i 2.40+1.80i -4.00-5.00i 0.00-3.00i ;
0.00+1.00i -1.80+2.40i 0.00-4.00i 4.00-5.00i]
my Fortran codes are as followed:
program testz
implicit none
integer, parameter :: N=4, nb=64, Nmax=10
integer :: lda,ldb,ldvr,lwork
parameter (lda=Nmax, ldb=Nmax, ldvr=Nmax,lwork=Nmax+Nmax*nb)
integer :: i,j,info
complex(kind=16) :: A(lda,Nmax), alpha(Nmax), B(ldb,Nmax),
& beta(Nmax), dummy(1,1), vr(ldvr,Nmax), work(lwork), eig(Nmax)
double precision :: rwork(8*Nmax)
A(1,1)=(-21.10,-22.50);A(1,2)=(53.50,-50.50)
A(1,3)=(-34.50,127.50);A(1,4)=(7.50,0.50)
A(2,1)=(-0.46,7.78);A(2,2)=(-3.5,-37.5)
A(2,3)=(-15.5,58.5);A(2,4)=(-10.5,-1.5)
A(3,1)=(4.3,-5.5);A(3,2)=(39.7,-17.1)
A(3,3)=(-68.5,12.5);A(3,4)=(-7.5,-3.5)
A(4,1)=(5.5,4.4);A(4,2)=(14.4,43.3)
A(4,3)=(-32.5,-46);A(4,4)=(-19,32.5)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
B(1,1)=(1,-5);B(1,2)=(1.6,1.2)
B(1,3)=(-3,0);B(1,4)=(0,-1)
B(2,1)=(0.8,-0.6);B(2,2)=(3,-5)
B(2,3)=(-4,3);B(2,4)=(-2.4,-3.2)
B(3,1)=(1,0);B(3,2)=(2.4,1.8)
B(3,3)=(-4,-5);B(3,4)=(0,-3)
B(4,1)=(0,1);B(4,2)=(-1.8,2.4)
B(4,3)=(0,-4);B(4,4)=(4,-5)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
call zggev('n','v',N,A,lda,B,ldb,alpha,beta,dummy,1,vr,ldvr,
& work,lwork,rwork,info)
eig=alpha/beta
!here skip the heading to the file
do j=1,N
write(7,12) eig(j)
12 format('(',2F8.4,')')!,'(',2F8.4,')','(',2F8.4,')','(',2F8.4,')')
end do
end program
my results are:
( NaN NaN)
(****************)
( 0.0000 0.0000)
( 0.0000 0.0000)
while the correct answer should be
Eigenvalue( 1) = ( 3.0000E+00,-9.0000E+00)
Eigenvalue( 2) = ( 2.0000E+00,-5.0000E+00)
Eigenvalue( 3) = ( 3.0000E+00,-1.0000E+00)
Eigenvalue( 4) = ( 4.0000E+00,-5.0000E+00)

Related

How can I make the difference between a result and the preceding one in do loops?

This subroutine uses to determine composite Trapezoid so
I want to abstract(Difference) between the final result(Integration) and the previous one(Integeration-1) and use the difference as a limit for duplicate my number of interval.
Subroutine Trapezoid(a,b,n,integration)
real,external :: f
real :: h,a,b,summ,p
real,intent(out) :: integration
integer :: n
integer :: i,j
!Here as we have the whole equation is (h/2)*[f(a)+f(b)+2*sum(Xi)
!So we calculate the first part (h/2)*[f(a)+f(b) and then calculate the anoter part
do i=1,n
n=2**i !Double the number of interval
h=(b-a)/n !Calculate the delta X
p=(h/2.)*(f(a)+f(b))
summ=0
do j=1,n-1
summ=summ+h*f(a+j*h) !h/2 *2* sum[f(Xi)
enddo
if(n == 256) then !put a limit for the number of interval
Stop
end if
integration = p + summ !Here the sum the both parts
print*,n,' ',integration
enddo
end Subroutine
So instead of the limit is 250 , I want to determine the difference and when this difference smaller than 10*-8, Stop
I tried a lot, but I didn't get what I want.
I would do it something like the below (very quickly hacked together). Note that with default kind reals 1e-8 is an unrealistic accuracy to expect - hence the lower tolerance. If you want higher accuracy you will need to use a higher precision kind real.
Note also I have turned this into a complete program. In questions please do this yourself. In purely selfish terms you will be much more likely to get a useful answer.
Anyway here is the code
Program integ
Implicit None
Real, Parameter :: pi = 3.1415927
Real :: value, delta
Integer :: n_used
Intrinsic :: sin
Call Trapezoid( sin, 0.0, pi / 2.0, 20, n_used, value, delta )
Write( *, * ) 'final result', value, ' with ', 2 ** n_used, ' intervals'
Contains
Subroutine Trapezoid(f,a,b,n_max,n_used,integration,delta)
Implicit None
Real, Parameter :: tol = 1e-4
Interface
Function f( x ) Result( r )
Real :: r
Real, Intent( In ) :: x
End Function f
End Interface
Real , Intent( In ) :: a
Real , Intent( In ) :: b
Integer, Intent( In ) :: n_max
Integer, Intent( Out ) :: n_used
Real , Intent( Out ) :: integration
Real , Intent( Out ) :: delta
Real :: h,summ,p
Real :: integration_old
Integer :: n
Integer :: i,j
!Here as we have the whole equation is (h/2)*[f(a)+f(b)+2*sum(Xi)
!So we calculate the first part (h/2)*[f(a)+f(b) and then calculate the anoter part
delta = - Huge( delta )
integration_old = Huge( integration_old )
Do i=1,n_max
n=2**i !Double the number of interval
h=(b-a)/n !Calculate the delta X
p=(h/2.)*(f(a)+f(b))
summ=0
Do j=1,n-1
summ=summ+h*f(a+j*h) !h/2 *2* sum[f(Xi)
Enddo
integration = p + summ !Here the sum the both parts
If( i /= 1 ) Then
delta = integration - integration_old
Write( *, * ) n,' ',integration , delta
If( Abs( delta ) < tol ) Exit
End If
integration_old = integration
Enddo
n_used = i
End Subroutine Trapezoid
End Program
ian#eris:~/work/stack$ gfortran --version
GNU Fortran (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ian#eris:~/work/stack$ gfortran -Wall -Wextra -fcheck=all -O -std=f2008 integ.f90
ian#eris:~/work/stack$ ./a.out
4 0.987115800 3.90563607E-02
8 0.996785223 9.66942310E-03
16 0.999196708 2.41148472E-03
32 0.999799252 6.02543354E-04
64 0.999949872 1.50620937E-04
128 0.999987483 3.76105309E-05
final result 0.999987483 with 128 intervals

Very small number turns negative in Fortran

I'm doing a program in Fortran90 which do a sum from i=1 to i=n where nis given. The sum is sum_{i=1}^{i=n}1/(i*(i+1)*(i+2)). This sum converges to 0.25. This is the code:
PROGRAM main
INTEGER n(4)
DOUBLE PRECISION s(4)
INTEGER i
OPEN(11,FILE='input')
OPEN(12,FILE='output')
DO i=1,4
READ(11,*) n(i)
END DO
PRINT*,n
CALL suma(n,s)
PRINT*, s
END
SUBROUTINE suma(n,s)
INTEGER n(4),j,k
DOUBLE PRECISION s(4),add
s=0
DO k=1,4
DO j=1,n(k)
add=1./(j*(j+1)*(j+2))
s(k)=s(k)+add
END DO
END DO
END SUBROUTINE
input
178
1586
18232
142705
The output file is now empty, I need to code it. I'm just printing the results, which are:
0.249984481688 0.249999400246 0.248687836759 0.247565846142
The problem comes with the variable add. When j is bigger, add turns negative, and the sum doesn't converge well. How can I fix it?
The problem is an integer overflow. 142705142706142707 is a number that is too large for a 4-byte integer.
What happens then is that the number overflows and loops back to negative numbers.
As #albert said in his comment, one solution is to convert it to double precision every step of the way: ((1.d0/j) / (j+1)) / (j+2). That way, it is calculating with floating point values.
Another option would be to use 8-byte integers:
integer, parameter :: int64 = selected_int_kind(17)
integer(kind=int64) :: j
You should be very careful with your calculations, though. Finer is not always better. I recommend that you look at how floating point arithmetic is performed by a computer, and what issues this can create. See for example here on wikipedia.
This is likely a better way to achieve what you want. I did remove the IO. The output from the program is
% gfortran -o z a.f90 && ./z
178 0.249984481688392
1586 0.249999801599584
18232 0.249999998496064
142705 0.249999999975453
program main
implicit none ! Never write a program without this statement
integer, parameter :: knd = kind(1.d0) ! double precision kind
integer n(4)
real(knd) s(4)
integer i
n = [178, 1586, 18232, 142705]
call suma(n, s)
do i = 1, 4
print '(I6,F18.15)', n(i), s(i)
end do
contains
!
! Recursively, sum a(j+1) = j * a(j) / (j + 1)
!
subroutine suma(n, s)
integer, intent(in) :: n(4)
real(knd), intent(out) :: s(4)
real(knd) aj
integer j, k
s = 0
do k = 1, 4
aj = 1 / real(1 * 2 * 3, knd) ! a(1)
do j = 1, n(k)
s(k) = s(k) + aj
aj = j * aj / (j + 3)
end do
end do
end subroutine
end program main

Fortran Error: 'y' argument of 'datan2' intrinsic at (1) must be REAL

I want to calculate z value as the coordinate in range of x:-50~50 and y:-50~50 like below code.
program test
implicit none
! --- [local entities]
real*8 :: rrr,th,U0,amp,alp,Ndiv
real*8 :: pi,alpR,NR,Rmin,Rmax,z
integer :: ir, i, j
do i=0, 50
do j=0, 50
th=datan2(i,j)
pi=datan(1.d0)*4.d0
!
Ndiv= 24.d0 !! Number of circumferential division
alp = 90.d0/180.d0*pi !! phase [rad]
U0 = 11.4d0 !! average velocity
amp = 0.5d0 !! amplitude of velocity
Rmin = 10 !! [m]
Rmax = 50 !! [m]
NR = 6.d0 !! Number of radial division
!
rrr=dsqrt(i**2+j**2)
ir=int((rrr-Rmin)/(Rmax-Rmin)*NR)
alpR=2.d0*pi/dble(Ndiv)*dble(mod(ir,2))
z=U0*(1.d0+amp*dsin(0.5d0*Ndiv*th+alp+alpR))
write(*,*) 'i, j, z'
write(*,*) i, j, z
end do
end do
stop
end program test
But I couldn't make it work like below error. I think because i, j are in datan(i,j). How should I change these code?
test.f90:10.16:
th=datan2(i,j)
1
Error: 'y' argument of 'datan2' intrinsic at (1) must be REAL
test.f90:21.16:
rrr=dsqrt(i**2+j**2)
1
Error: 'x' argument of 'dsqrt' intrinsic at (1) must be REAL
Inspired by the comments of #Rodrigo Rodrigues, #Ian Bush, and #Richard, here is a suggested rewrite of the code segment from #SW. Kim
program test
use, intrinsic :: iso_fortran_env, only : real64
implicit none
! --- [local entities]
! Determine the kind of your real variables (select one):
! for specifying a given numerical precision
integer, parameter :: wp = selected_real_kind(15, 307) !15 digits, 10**307 range
! for specifying a given number of bits
! integer, parameter :: wp = real64
real(kind=wp), parameter :: pi = atan(1._wp)*4._wp
real(kind=wp) :: rrr, th, U0, amp, alp, Ndiv
real(kind=wp) :: alpR, NR, Rmin, Rmax, z
integer :: ir, i, j
do i = 0, 50
do j = 0, 50
th = atan2(real(i, kind=wp), real(j, kind=wp))
!
Ndiv= 24._wp !! Number of circumferential division
alp = 90._wp/180._wp*pi !! phase [rad]
U0 = 11.4_wp !! average velocity
amp = 0.5_wp !! amplitude of velocity
Rmin = 10 !! [m]
Rmax = 50 !! [m]
NR = 6._wp !! Number of radial division
!
rrr = sqrt(real(i, kind=wp)**2 + real(j, kind=wp)**2)
ir = int((rrr - Rmin) / (Rmax - Rmin) * NR)
alpR = 2._wp * pi / Ndiv * mod(ir, 2)
z = U0 * (1._wp + amp * sin(0.5_wp * Ndiv * th + alp + alpR))
!
write(*,*) 'i, j, z'
write(*,*) i, j, z
end do
end do
stop
end program test
Specifically, the following changes were made with respect to the original code posted:
Minimum change to answer the question: casting integer variables i and j to real values for using them in the real valued functions datan and dsqrt.
Using generic names for intrinsic procedures, i.e sqrt instead of dsqrt, atan instead of datan, and sin instead of dsin. One benefit of this approach, is that the kind of working precision wp can be changed in one place, without requiring explicit changes elsewhere in the code.
Defining the kind of real variables and calling it wp. Extended discussion of this topic, its implications and consequences can be found on this site, for example here and here. Also #Steve Lionel has an in depth post on his blog, where his general advice is to use selected_real_kind.
Defining pi as a parameter calculating its value once, instead of calculating the same value repeatedly within the nested for loops.

Evaluating the fast Fourier transform of Gaussian function in FORTRAN using FFTW3 library

I am trying to write a FORTRAN code to evaluate the fast Fourier transform of the Gaussian function f(r)=exp(-(r^2)) using FFTW3 library. As everyone knows, the Fourier transform of the Gaussian function is another Gaussian function.
I consider evaluating the Fourier-transform integral of the Gaussian function in the spherical coordinate.
Hence the resulting integral can be simplified to be integral of [r*exp(-(r^2))*sin(kr)]dr.
I wrote the following FORTRAN code to evaluate the discrete SINE transform DST which is the discrete Fourier transform DFT using a PURELY real input array. DST is performed by C_FFTW_RODFT00 existing in FFTW3, taking into account that the discrete values in position space are r=i*delta (i=1,2,...,1024), and the input array for DST is the function r*exp(-(r^2)) NOT the Gaussian. The sine function in the integral of [r*exp(-(r^2))*sin(kr)]dr resulting from the INTEGRATION over the SPHERICAL coordinates, and it is NOT the imaginary part of exp(ik.r) that appears when taking the analytic Fourier transform in general.
However, the result is not a Gaussian function in the momentum space.
Module FFTW3
use, intrinsic :: iso_c_binding
include 'fftw3.f03'
end module
program sine_FFT_transform
use FFTW3
implicit none
integer, parameter :: dp=selected_real_kind(8)
real(kind=dp), parameter :: pi=acos(-1.0_dp)
integer, parameter :: n=1024
real(kind=dp) :: delta, k
real(kind=dp) :: numerical_F_transform
integer :: i
type(C_PTR) :: my_plan
real(C_DOUBLE), dimension(1024) :: y
real(C_DOUBLE), dimension(1024) :: yy, yk
integer(C_FFTW_R2R_KIND) :: C_FFTW_RODFT00
my_plan= fftw_plan_r2r_1d(1024,y,yy,FFTW_FORWARD, FFTW_ESTIMATE)
delta=0.0125_dp
do i=1, n !inserting the input one-dimension position function
y(i)= 2*(delta)*(i-1)*exp(-((i-1)*delta)**2)
! I multiplied by 2 due to the definition of C_FFTW_RODFT00 in FFTW3
end do
call fftw_execute_r2r(my_plan, y,yy)
do i=2, n
k = (i-1)*pi/n/delta
yk(i) = 4*pi*delta*yy(i)/2 !I divide by 2 due to the definition of
!C_FFTW_RODFT00
numerical_F_transform=yk(i)/k
write(11,*) i,k,numerical_F_transform
end do
call fftw_destroy_plan(my_plan)
end program
Executing the previous code gives the following plot which is not for Gaussian function.
Can anyone help me understand what the problem is? I guess the problem is mainly due to FFTW3. Maybe I did not use it properly especially concerning the boundary conditions.
Looking at the related pages in the FFTW site (Real-to-Real Transforms, transform kinds, Real-odd DFT (DST)) and the header file for Fortran, it seems that FFTW expects FFTW_RODFT00 etc rather than FFTW_FORWARD for specifying the kind of
real-to-real transform. For example,
! my_plan= fftw_plan_r2r_1d( n, y, yy, FFTW_FORWARD, FFTW_ESTIMATE )
my_plan= fftw_plan_r2r_1d( n, y, yy, FFTW_RODFT00, FFTW_ESTIMATE )
performs the "type-I" discrete sine transform (DST-I) shown in the above page. This modification seems to fix the problem (i.e., makes the Fourier transform a Gaussian with positive values).
The following is a slightly modified version of OP's code to experiment the above modification:
! ... only the modified part is shown...
real(dp) :: delta, k, r, fftw, num, ana
integer :: i, j, n
type(C_PTR) :: my_plan
real(C_DOUBLE), allocatable :: y(:), yy(:)
delta = 0.0125_dp ; n = 1024 ! rmax = 12.8
! delta = 0.1_dp ; n = 128 ! rmax = 12.8
! delta = 0.2_dp ; n = 64 ! rmax = 12.8
! delta = 0.4_dp ; n = 32 ! rmax = 12.8
allocate( y( n ), yy( n ) )
! my_plan= fftw_plan_r2r_1d( n, y, yy, FFTW_FORWARD, FFTW_ESTIMATE )
my_plan= fftw_plan_r2r_1d( n, y, yy, FFTW_RODFT00, FFTW_ESTIMATE )
! Loop over r-grid
do i = 1, n
r = i * delta ! (2-a)
y( i )= r * exp( -r**2 )
end do
call fftw_execute_r2r( my_plan, y, yy )
! Loop over k-grid
do i = 1, n
! Result of FFTW
k = i * pi / ((n + 1) * delta) ! (2-b)
fftw = 4 * pi * delta * yy( i ) / k / 2 ! the last 2 due to RODFT00
! Numerical result via quadrature
num = 0
do j = 1, n
r = j * delta
num = num + r * exp( -r**2 ) * sin( k * r )
enddo
num = num * 4 * pi * delta / k
! Analytical result
ana = sqrt( pi )**3 * exp( -k**2 / 4 )
! Output
write(10,*) k, fftw
write(20,*) k, num
write(30,*) k, ana
end do
Compile (with gfortran-8.2 + FFTW3.3.8 + OSX10.11):
$ gfortran -fcheck=all -Wall sine.f90 -I/usr/local/Cellar/fftw/3.3.8/include -L/usr/local/Cellar/fftw/3.3.8/lib -lfftw3
If we use FFTW_FORWARD as in the original code, we get
which has a negative lobe (where fort.10, fort.20, and fort.30 correspond to FFTW, quadrature, and analytical results). Modifying the code to use FFTW_RODFT00 changes the result as below, so the modification seems to be working (but please see below for the grid definition).
Additional notes
I have slightly modified the grid definition for r and k in my code (Lines (2-a) and (2-b)), which is found to improve the accuracy. But I'm still not sure whether the above definition matches the definition used by FFTW, so please read the manual for details...
The fftw3.f03 header file gives the interface for fftw_plan_r2r_1d
type(C_PTR) function fftw_plan_r2r_1d(n,in,out,kind,flags) bind(C, name='fftw_plan_r2r_1d')
import
integer(C_INT), value :: n
real(C_DOUBLE), dimension(*), intent(out) :: in
real(C_DOUBLE), dimension(*), intent(out) :: out
integer(C_FFTW_R2R_KIND), value :: kind
integer(C_INT), value :: flags
end function fftw_plan_r2r_1d
(Because of no Tex support, this part is very ugly...) The integral of 4 pi r^2 * exp(-r^2) * sin(kr)/(kr) for r = 0 -> infinite is pi^(3/2) * exp(-k^2 / 4) (obtained from Wolfram Alpha or by noting that this is actually a 3-D Fourier transform of exp(-(x^2 + y^2 + z^2)) by exp(-i*(k1 x + k2 y + k3 z)) with k =(k1,k2,k3)). So, although a bit counter-intuitive, the result becomes a positive Gaussian.
I guess the r-grid can be chosen much coarser (e.g. delta up to 0.4), which gives almost the same accuracy as long as it covers the frequency domain of the transformed function (here exp(-r^2)).
Of course there are negative components of the real part to the FFT of a limited Gaussian spectrum. You are just using the real part of the transform. So your plot is absolutely correct.
You seem to be mistaking the real part with the magnitude, which of course would not be negative. For that you would need to fftw_plan_dft_r2c_1d and then calculate the absolute values of the complex coefficients. Or you might be mistaking the Fourier transform with a limited DFT.
You might want to check here to convince yourself of the correctness of you calculation above:
http://docs.mantidproject.org/nightly/algorithms/FFT-v1.html
Please do keep in mind that the plots on the above page are shifted, so that the 0 frequency is in the middle of the spectrum.
Citing yourself, the nummeric integration of [r*exp(-(r^2))*sin(kr)]dr would have negative components for all k>1 if normalised to 0 for highest frequency.
TLDR: Your plot is absolute state of the art and inline with discrete and limited functional analysis.

lapack zheevd gives wrong results

I am trying to use lapack's zheevd in order to diagonalize a complex Hermitian matrix. I' ve written a small example which doesn't produce any compile or run time error but gives wrong results for the eigenvalues... Here's the code:
program test
implicit none
INTEGER, PARAMETER :: N=4
INTEGER, PARAMETER :: LDA = N
INTEGER, PARAMETER :: LWMAX = 1000
INTEGER :: INFO, LWORK, LIWORK, LRWORK,i,j
INTEGER :: IWORK( LWMAX )
REAL(8) :: W(N), RWORK( LWMAX )
COMPLEX(16) :: A(LDA, N), WORK(LWMAX), zero
character(len=1) :: job,uplo
! the matrix I want to diagonalize is:
! ( 3.40, 0.00) ( -2.36, -1.93) ( -4.68, 9.55) ( 5.37, -1.23)
! A= ( -2.36, 1.93) ( 6.94, 0.00) ( 8.13, -1.47) ( 2.07, -5.78)
! ( -4.68, -9.55) ( 8.13, 1.47) ( -2.14, 0.00) ( 4.68, 7.44)
! ( 5.37, 1.23) ( 2.07, 5.78) ( 4.68, -7.44) ( -7.42, 0.00)
zero=dcmplx(0.0d0,0.0d0)
A=zero
A(1,1)= dcmplx( 3.40d0, 0.0d0); A(1,2)=dcmplx(-2.36d0, -1.93d0); A(1,3)= dcmplx(-4.68d0,9.55d0)
A(1,4)= dcmplx( 5.37d0, -1.23d0)
A(2,2)= dcmplx( 6.94d0, 0.0d0); A(2,3)=dcmplx( 8.13d0, -1.47d0); A(2,4)= dcmplx( 2.07d0, -5.78d0)
A(3,3)= dcmplx(-2.14d0, 0.0d0); A(3,4)=dcmplx( 4.68d0, 7.44d0); A(4,4)= dcmplx(-7.42d0, 0.0d0)
job='V'; uplo='U'
LWORK= N**2 + 2*N; LRWORK= 2*N**2 + 5*N + 1; LIWORK= 5*N+3
CALL ZHEEVD( job, uplo, N, A, LDA, W, WORK, LWORK, RWORK,LRWORK,IWORK,LIWORK, INFO )
IF( INFO > 0 ) THEN
WRITE(*,*)'The algorithm failed to compute eigenvalues.'
STOP
END IF
print*, 'eigenvalues found'
do i=1,N
print*, W(i)
end do
open(1, file='eigenvectors.dat')
write(1,10) ((A(i,j),j=1,N),i=1,N)
10 format(4(F10.5,2X,F10.5))
end program test
when I run the code the results I get for the eigenvalues are:
-2.8413, 0, 0, 2.8413
while the actual eigenvalues are: -21.968, 16.3387, 6.45946, -0.0501069
I keep seeing the routine's reference guide and it seems I have everything correct so it should work properly expect it doesn't... Has anyone an idea about what is wrong with my code?
Thanks
There are three main problems here that I can see:
The most serious issue is that you have translated the COMPLEX*16 types in the MKL example you have based your code on as COMPLEX(16). That is incorrect. You should use COMPLEX(8). I don't know whether your toolchain actually has an extended precision complex type, but there could be a size mismatch between your code and the LAPACK call
There is a typo in the code that means that the values of the matrix you pass to LAPACK are not the same as in your comments (and presumably also not the same as the matrix you computed the eigenvalues for)
Lastly, and just as importantly, you have not defined an interface for ZHEEVD (or declared it as external). This will lead to an implicit interface being guessed by the compiler, and it is quite probable that there are inconsistencies between the argument passing within your code and what LAPACK expects. Especially given the type mismatch in the complex arguments.
I would expect that some combination of all three should fix the results.