Question

I am having some problems using the subroutine DSYGV of Lapack:

DSYGV( ITYPE, JOBZ, UPLO, N, A, LDA, B, LDB, W, WORK,LWORK, INFO )

This is the diagonalization I want to carry out:

v_mat*x = eig*t_mat*x

This is the crucial piece of my code:

program pruebadiago

real, dimension(:,:), allocatable :: v_mat, t_mat

real, dimension(:), allocatable   :: eig,WORK

real , parameter                  :: k=3.0,m=4.0

integer, parameter                :: n=2

integer                           :: i

! EXPECTED EIGENVALUES AND EIGENVECTORS

!eig = 0.286475  ------>  u = (0.262866 , 0.425325)

!eig = 1.96353   ------>  u = (0.425325, -0.262866)

allocate(v_mat(n,n),t_mat(n,n),eig(n))

!--------------------------

v_mat(1,1:2) = (/2.0*k,-k/)

v_mat(2,1:2) = (/-k,k/)

!--------------------------

!--------------------------

t_mat(1,1:2) = (/m,0.0/)

t_mat(2,1:2) = (/0.0,m/)

!---------------------------

!diagonalizacion

call DSYGV( 1, 'v', 'u', n , v_mat, 2 , t_mat, 2, eig, WORK,-1, INF )

LWORK=WORK(1)

allocate(WORK(LWORK))

call  DSYGV( 1, 'v', 'u', n , v_mat, 2 , t_mat, 2, eig, WORK,LWORK, INF )

open(unit=100,file="pruebadiago.dat",status="replace",action="write")

do i = 1,n

write(unit=100,fmt=*) "E",i,"=",eig(i),(v_mat(i,j),j=1,n)

!autofuntzioak zutabeka doaz"(100f12.6)"

enddo

close(unit=100)

deallocate(v_mat,t_mat,eig,WORK)

end program pruebadiago

I think I understood everything given in this document:

http://www.netlib.org/lapack/lapack-3.1.1/html/dsygv.f.html

But the argument LWORK which I did not understand so I just try different values.

I know something is wrong because I know what are the eigenvalues and eigenvectors of this matrix and I get wrong eigenvalues and eigenvectors, and I am doing such a simple calculation in order to understand the way it works and then compute huge diagonalizations.

Does anybody see what is the problem?

Thank you

Was it helpful?

Solution

There are missing some elements from the code you posted. Basically the array declarations of WORK,eig,v_mat and t_mat.

Anyway, LWORK argument actually is the size of WORK vector. i.e

DOUBLE PRECISION WORK(100)
LWORK=100

Lapack specifies as minimum value of LWORK=3*N-1. In your case N=2.

For this example case I would suggested to use a big WORK vector (i.e. 100) so that you will not encounter any problems from that.

For large matrices you should use double call of DSYGV.

  • First call with LWORK=-1 and get suggested size from WORK(1)
  • Allocate a NEW WORK vector with suggested size.
  • Finally solve eigenproblem with DSYGV.

Sample code is:

CALL DSYGV( 1, 'V', 'U', 2 , v_mat, 2 , t_mat, 2, eig, W, -1, INF )
LWORK=W(1)
ALLOCATE ( WORK(LWORK) )
CALL DSYGV( 1, 'V', 'U', 2 , v_mat, 2 , t_mat, 2, eig, WORK, LWORK, INF ) 

Additionally, you need to check INF value after DSYGV call. If it is not zero then an error occurred.

EDIT: Fixed source code

program pruebadiago

double precision, dimension(:,:), allocatable :: v_mat, t_mat
double precision, dimension(:), allocatable :: eig,WORK
double precision :: W
double precision , parameter :: k=3.0,m=4.0
integer, parameter :: n=2
integer :: i

! EXPECTED EIGENVALUES AND EIGENVECTORS
!eig = 0.286475 ------> u = (0.262866 , 0.425325)
!eig = 1.96353 ------> u = (0.425325, -0.262866)

allocate(v_mat(n,n),t_mat(n,n),eig(n))

!--------------------------
v_mat(1,1:2) = (/2.0*k,-k/)
v_mat(2,1:2) = (/-k,k/)
!--------------------------
t_mat(1,1:2) = (/m,0.0d0/)
t_mat(2,1:2) = (/0.0d0,m/)
!---------------------------

call DSYGV( 1, 'v', 'u', n , v_mat, 2 , t_mat, 2, eig, W,-1, INF )

LWORK=W
allocate(WORK(LWORK))

call DSYGV( 1, 'v', 'u', n , v_mat, 2 , t_mat, 2, eig, WORK,LWORK, INF )
open(unit=100,file="pruebadiago.dat",status="replace",action="write")
do i = 1,n
  write(unit=100,fmt=*) "E",i,"=",eig(i),(v_mat(i,j),j=1,n)
enddo

close(unit=100)
deallocate(v_mat,t_mat,eig,WORK)

end program pruebadiago
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top