I am working in a code that computes the eigenvalues and eigenvectors using PSSYEV routine. The code has been tested/verified using the different matrices provided in the Scalapack examples website and the results (eigenvalues and eigenvectors) are exactly the same reported on the website. My ultimate goal is to use the code to solve the eigenproblem for large matrices. Right now I am working with a matrix of dimension 4455 x 4455 and the code runs fast (a couple of minutes with 4 CPUs). However, the results I am getting are way different compared to those obtained using EISPACK. I have used EISPACK in the past so there is not problem with the EISPACK code. I would like to know if It is possible that PSSYEV doesn't handle properly such large matrices, or, if there is something wrong with the code itself. Any help on this is much appreciated.
The code
===========================================================================
- Code: Select all
PROGRAM TEST
INTEGER :: irec,i,j,l,k,LWORK,MAXN,LDA
REAL :: ZERO =0.,MONE=-1.
INTEGER MEMSIZ, TOTMEM
INTEGER, PARAMETER :: REALSZ = 4
INTEGER, PARAMETER :: INTGSZ = 4
INTEGER, PARAMETER :: BLOCK_CYCLIC_2D = 1
INTEGER, PARAMETER :: DLEN_ = 9, DT_ = 1,CTXT_ = 2, M_ = 3
INTEGER, PARAMETER :: N_ = 4, MB_ = 5, NB_ = 6, RSRC_ = 7
INTEGER, PARAMETER :: CSRC_ = 8, LLD_ = 9
REAL, PARAMETER :: ONE = 1.0E+0
CHARACTER*80 :: OUTFILE
INTEGER :: IAM, ICTXT, INFO, IPA, IPACPY, IPB, IPPIV, IPX
INTEGER :: IPW, LIPIV, MYCOL, MYROW, N, NB, NOUT, NPCOL
INTEGER :: NPROCS, NPROW, NP, NQ, NQRHS, NRHS, WORKSIZ
REAL :: ANORM, BNORM, EPS, XNORM, RESID
REAL :: slambda
INTEGER :: DESCA( DLEN_ ), DESCB( DLEN_ ), DESCX( DLEN_ )
INTEGER :: DESCZ(DLEN_)
REAL, DIMENSION(:), ALLOCATABLE :: MEM
REAL, DIMENSION(:,:), ALLOCATABLE :: Z
REAL, DIMENSION(:), ALLOCATABLE :: W
REAL, DIMENSION(:), ALLOCATABLE :: WORK
EXTERNAL :: BLACS_EXIT, BLACS_GET, BLACS_GRIDEXIT
EXTERNAL :: BLACS_GRIDINFO, BLACS_GRIDINIT
EXTERNAL :: BLACS_SETUP, PDLAMODHILB, PSSYEV
EXTERNAL :: BLACS_PINFO, DESCINIT, IGSUM2D, PDSCAEXINFO, PSGESV
EXTERNAL :: PSGEMM, PSLACPY, PSLAPRNT, PSLAREAD, PSLAWRITE
* ..
* .. External Functions ..
INTEGER :: ICEIL, NUMROC
REAL :: PSLAMCH, PSLANGE
EXTERNAL :: ICEIL, NUMROC
* ..
* .. Intrinsic Functions ..
INTRINSIC :: DBLE, MAX, ABS
LWORK=4455*4455*8
MAXN=4455
LDA=MAXN
ALLOCATE(WORK(LWORK))
ALLOCATE(Z(LDA,LDA))
ALLOCATE(W(LDA))
TOTMEM = 495437044
* TOTMEM = 2000000
MEMSIZ = TOTMEM / REALSZ
ALLOCATE(MEM(MEMSIZ))
* Get starting information
*
CALL BLACS_PINFO( IAM, NPROCS )
CALL PDSCAEXINFO( OUTFILE, NOUT, N, NRHS, NB, NPROW, NPCOL, MEM,
$ IAM, NPROCS )
*
* Define process grid
*
CALL BLACS_GET( -1, 0, ICTXT )
CALL BLACS_GRIDINIT( ICTXT, 'Row-major', NPROW, NPCOL )
CALL BLACS_GRIDINFO( ICTXT, NPROW, NPCOL, MYROW, MYCOL )
*
* Go to bottom of process grid loop if this case doesn't use my
* process
*
IF( MYROW.GE.NPROW .OR. MYCOL.GE.NPCOL )
$ GO TO 20
*
NP = NUMROC( N, NB, MYROW, 0, NPROW )
NQ = NUMROC( N, NB, MYCOL, 0, NPCOL )
*
* Initialize the array descriptor for the matrix A and B
*
CALL DESCINIT( DESCA, N, N, NB, NB, 0, 0, ICTXT, MAX( 1, NP ),
$ INFO )
CALL DESCINIT( DESCZ, N, N, NB, NB, 0, 0, ICTXT, MAX( 1, NP ),
$ INFO )
IF( IAM.EQ.0 ) THEN
PRINT*,'....1.....THIS..PART..IS.OK'
ENDIF
*
* Assign pointers into MEM for SCALAPACK arrays, A is
* allocated starting at position MEM( 1 )
*
IPA = 1
IPACPY = IPA + DESCA( LLD_ )*NQ
IPB = IPACPY + DESCA( LLD_ )*NQ
LIPIV = ICEIL( INTGSZ*( NP+NB ), REALSZ )
IPW = IPB+MAX( NP, LIPIV )
*
WORKSIZ = NB
*
* Check for adequate memory for problem size
*
INFO = 0
IF( IPW+WORKSIZ.GT.MEMSIZ ) THEN
IF( IAM.EQ.0 )
$ WRITE( NOUT, FMT = 9998 ) 'test', ( IPW+WORKSIZ )*REALSZ
INFO = 1
END IF
*
* Check all processes for an error
*
CALL IGSUM2D( ICTXT, 'All', ' ', 1, 1, INFO, 1, -1, 0 )
IF( INFO.GT.0 ) THEN
IF( IAM.EQ.0 )
$ WRITE( NOUT, FMT = 9999 ) 'MEMORY'
GO TO 10
END IF
*
* Read from file and distribute matrix A
*
CALL PSLAREAD( 'test4455x4455.dat', MEM( IPA ), DESCA, 0, 0,
$ MEM( IPW ) )
*
* Make a copy of A for checking purposes
*
IF( IAM.EQ.0 ) THEN
PRINT*,'....2..THIS...PART...OK..'
ENDIF
CALL PSLACPY( 'All', N, N, MEM( IPA ), 1, 1, DESCA,
$ MEM( IPACPY ), 1, 1, DESCA )
IF( IAM.EQ.0 ) THEN
PRINT*,'....3..THIS...PART...OK..'
ENDIF
CALL PSSYEV( 'V', 'U', N, MEM(IPA), 1, 1, DESCA, W, Z, 1, 1,
$ DESCZ, MEM(IPW), LWORK, INFO )
CALL PSLAPRNT( N, N, Z, 1, 1, DESCZ, 0, 0, 'Z', 6, MEM(IPW) )
CALL PSLAWRITE( 'EIGVSOL.dat', N, N, Z, 1, 1, DESCZ,
$ 0, 0, MEM( IPW ) )
IF( MYROW.EQ.0 .AND. MYCOL.EQ.0 ) THEN
PRINT *, ' N =', N
slambda = 0.0
do 60 l=1,N
slambda = slambda + W(l)
60 continue
DO 100 I = N, N-10,-1
PRINT *, ' W(', I, ')=', W(I)/slambda*100., ';'
100 CONTINUE
END IF
10 CONTINUE
*
CALL BLACS_GRIDEXIT( ICTXT )
*
20 CONTINUE
*
* Print ending messages and close output file
*
IF( IAM.EQ.0 ) THEN
WRITE( NOUT, FMT = * )
WRITE( NOUT, FMT = * )
WRITE( NOUT, FMT = 9997 )
WRITE( NOUT, FMT = * )
IF( NOUT.NE.6 .AND. NOUT.NE.0 )
$ CLOSE ( NOUT )
END IF
*
CALL BLACS_EXIT( 0 )
*
9999 FORMAT( 'Bad ', A6, ' parameters: going on to next test case.' )
9998 FORMAT( 'Unable to perform ', A, ': need TOTMEM of at least',
$ I11 )
9997 FORMAT( 'END OF TESTS.' )
*
STOP
*
* End of TEST
*
END

