Routine: PDSYEVD()  File: SRC\pdsyevd.f

 
 
# lines: 352
  # code: 352
  # comment: 0
  # blank:0
# Variables:70
# Callers:0
# Callings:8
# Words:209
# Keywords:126
 

 

..
     .. Array Arguments ..
     ..
  Purpose
  =======
  PDSYEVD computes  all the eigenvalues and eigenvectors
  of a real symmetric matrix A by calling the recommended sequence
  of ScaLAPACK routines.
  In its present form, PDSYEVD assumes a homogeneous system and makes
  no checks for consistency of the eigenvalues or eigenvectors across
  the different processes.  Because of this, it is possible that a
  heterogeneous system may return incorrect results without any error
  messages.
  Arguments
  =========
     NP = the number of rows local to a given process.
     NQ = the number of columns local to a given process.
  JOBZ    (input) CHARACTER*1
          = 'N':  Compute eigenvalues only;     (NOT IMPLEMENTED YET)
          = 'V':  Compute eigenvalues and eigenvectors.
  UPLO    (global input) CHARACTER*1
          Specifies whether the upper or lower triangular part of the
          symmetric matrix A is stored:
          = 'U':  Upper triangular
          = 'L':  Lower triangular
  N       (global input) INTEGER
          The number of rows and columns to be operated on, i.e. the
          order of the distributed submatrix sub( A ). N >= 0.
  A       (local input/workspace) block cyclic DOUBLE PRECISION array,
          global dimension (N, N), local dimension ( LLD_A,
          LOCc(JA+N-1) )
          On entry, the symmetric matrix A.  If UPLO = 'U', only the
          upper triangular part of A is used to define the elements of
          the symmetric matrix.  If UPLO = 'L', only the lower
          triangular part of A is used to define the elements of the
          symmetric matrix.
          On exit, the lower triangle (if UPLO='L') or the upper
          triangle (if UPLO='U') of A, including the diagonal, is
          destroyed.
  IA      (global input) INTEGER
          A's global row index, which points to the beginning of the
          submatrix which is to be operated on.
  JA      (global input) INTEGER
          A's global column index, which points to the beginning of
          the submatrix which is to be operated on.
  DESCA   (global and local input) INTEGER array of dimension DLEN_.
          The array descriptor for the distributed matrix A.
  W       (global output) DOUBLE PRECISION array, dimension (N)
          If INFO=0, the eigenvalues in ascending order.
  Z       (local output) DOUBLE PRECISION array,
          global dimension (N, N),
          local dimension ( LLD_Z, LOCc(JZ+N-1) )
          Z contains the orthonormal eigenvectors
          of the symmetric matrix A.
  IZ      (global input) INTEGER
          Z's global row index, which points to the beginning of the
          submatrix which is to be operated on.
  JZ      (global input) INTEGER
          Z's global column index, which points to the beginning of
          the submatrix which is to be operated on.
  DESCZ   (global and local input) INTEGER array of dimension DLEN_.
          The array descriptor for the distributed matrix Z.
          DESCZ( CTXT_ ) must equal DESCA( CTXT_ )
  WORK    (local workspace/output) DOUBLE PRECISION array,
          dimension (LWORK)
          On output, WORK(1) returns the workspace required.
  LWORK   (local input) INTEGER
          LWORK >= MAX( 1+6*N+2*NP*NQ, TRILWMIN ) + 2*N
          TRILWMIN = 3*N + MAX( NB*( NP+1 ), 3*NB )
          NP = NUMROC( N, NB, MYROW, IAROW, NPROW )
          NQ = NUMROC( N, NB, MYCOL, IACOL, NPCOL )
          If LWORK = -1, the LWORK is global input and a workspace
          query is assumed; the routine only calculates the minimum
          size for the WORK array.  The required workspace is returned
          as the first element of WORK and no error message is issued
          by PXERBLA.
  IWORK   (local workspace/output) INTEGER array, dimension (LIWORK)
          On exit, if LIWORK > 0, IWORK(1) returns the optimal LIWORK.
  LIWORK  (input) INTEGER
          The dimension of the array IWORK.
          LIWORK = 7*N + 8*NPCOL + 2
  INFO    (global output) INTEGER
          = 0:  successful exit
          < 0:  If the i-th argument is an array and the j-entry had
                an illegal value, then INFO = -(i*100+j), if the i-th
                argument is a scalar and had an illegal value, then
                INFO = -i.
          > 0:  The algorithm failed to compute the INFO/(N+1) th
                eigenvalue while working on the submatrix lying in
                global rows and columns mod(INFO,N+1).
  Alignment requirements
  ======================
  The distributed submatrices sub( A ), sub( Z ) must verify
  some alignment properties, namely the following expression
  should be true:
  ( MB_A.EQ.NB_A.EQ.MB_Z.EQ.NB_Z .AND. IROFFA.EQ.ICOFFA .AND.
    IROFFA.EQ.0 .AND.IROFFA.EQ.IROFFZ. AND. IAROW.EQ.IZROW)
    with IROFFA = MOD( IA-1, MB_A )
     and ICOFFA = MOD( JA-1, NB_A ).
  Further Details
  ======= =======
  Contributed by Francoise Tisseur, University of Manchester.
  Reference:  F. Tisseur and J. Dongarra, "A Parallel Divide and
              Conquer Algorithm for the Symmetric Eigenvalue Problem
              on Distributed Memory Architectures",
              SIAM J. Sci. Comput., 6:20 (1999), pp. 2223--2236.
              (see also LAPACK Working Note 132)
                http://www.netlib.org/lapack/lawns/lawn132.ps
  =====================================================================
     .. Parameters ..

 
Display dynamic version Find AutoScroll Reload FontSize: - + Hide Comments Hide Blanks Frame FullScreen MailPrint

 
001        SUBROUTINE PDSYEVD( JOBZ , UPLO , N , A , IA , JA , DESCA , W , Z , IZ , JZ ,
002       $DESCZ , WORK , LWORK , IWORK , LIWORK , INFO )
003  
004  *     -- ScaLAPACK routine(version 1.7) --
005  *     University of Tennessee , Knoxville , Oak Ridge National Laboratory ,
006  *     and University of California , Berkeley.
007  *     March 14 , 2000
008  
009  *     .. Scalar Arguments ..
010        CHARACTER JOBZ , UPLO
011        INTEGER IA , INFO , IZ , JA , JZ , LIWORK , LWORK , N
012        INTEGER BLOCK_CYCLIC_2D , DLEN_ , DTYPE_ , CTXT_ , M_ , N_ ,
013       $MB_ , NB_ , RSRC_ , CSRC_ , LLD_
014        PARAMETER( BLOCK_CYCLIC_2D = 1 , DLEN_ = 9 , DTYPE_ = 1 ,
015       $CTXT_ = 2 , M_ = 3 , N_ = 4 , MB_ = 5 , NB_ = 6 ,
016       $RSRC_ = 7 , CSRC_ = 8 , LLD_ = 9 )
017        DOUBLE PRECISION ZERO , ONE
018        PARAMETER( ZERO = 0.0D + 0 , ONE = 1.0D + 0 )
019  *     ..
020  *     .. Local Scalars ..
021        LOGICAL LQUERY , UPPER
022        INTEGER IACOL , IAROW , ICOFFA , ICOFFZ , ICTXT , IINFO ,
023       $INDD , INDE , INDE2 , INDTAU , INDWORK , INDWORK2 ,
024       $IROFFA , IROFFZ , ISCALE , LIWMIN , LLWORK ,
025       $LLWORK2 , LWMIN , MYCOL , MYROW , NB , NP , NPCOL ,
026       $NPROW , NQ , OFFSET , TRILWMIN
027        DOUBLE PRECISION ANRM , BIGNUM , EPS , RMAX , RMIN , SAFMIN , SIGMA ,
028       $SMLNUM
029  *     ..
030  *     .. Local Arrays ..
031  *     ..
032        INTEGER IDUM1( 2 ) , IDUM2( 2 )
033  *     ..
034  *     .. External Functions ..
035        LOGICAL LSAME
036        INTEGER INDXG2P , NUMROC
037        DOUBLE PRECISION PDLAMCH , PDLANSY
038        EXTERNAL LSAME , INDXG2P , NUMROC , PDLAMCH , PDLANSY
039  *     ..
040  *     .. External Subroutines ..
041        EXTERNAL BLACS_GRIDINFO , CHK1MAT , DSCAL , PCHK1MAT ,
042       $PDLARED1D , PDLASCL , PDLASET , PDORMTR , PDSTEDC ,
043       $PDSYTRD , PXERBLA
044  *     ..
045  *     .. Intrinsic Functions ..
046        INTRINSIC DBLE , ICHAR , MAX , MIN , MOD , SQRT
047  *     ..
048  *     .. Executable Statements ..
049  *     This is just to keep ftnchek and toolpack / 1 happy
050        IF( BLOCK_CYCLIC_2D*CSRC_*CTXT_*DLEN_*DTYPE_*LLD_*MB_*M_*NB_*N_*
051       $    RSRC_.LT.0 )RETURN
052  
053  *         Quick return
054  
055            IF( N.EQ.0 )
056       $        RETURN
057  
058  *             Test the input arguments.
059  
060                CALL BLACS_GRIDINFO( DESCZ( CTXT_ ) , NPROW , NPCOL , MYROW , MYCOL )
061  
062                INFO = 0
063                IF( NPROW.EQ. - 1 ) THEN
064                    INFO = - ( 600 + CTXT_ )
065                ELSE
066                    CALL CHK1MAT( N , 3 , N , 3 , IA , JA , DESCA , 7 , INFO )
067                    CALL CHK1MAT( N , 3 , N , 3 , IZ , JZ , DESCZ , 12 , INFO )
068                    IF( INFO.EQ.0 ) THEN
069                        UPPER = LSAME( UPLO , 'U' )
070                        NB = DESCA( NB_ )
071                        IROFFA = MOD( IA - 1 , DESCA( MB_ ) )
072                        ICOFFA = MOD( JA - 1 , DESCA( NB_ ) )
073                        IROFFZ = MOD( IZ - 1 , DESCZ( MB_ ) )
074                        ICOFFZ = MOD( JZ - 1 , DESCZ( NB_ ) )
075                        IAROW = INDXG2P( IA , NB , MYROW , DESCA( RSRC_ ) , NPROW )
076                        IACOL = INDXG2P( JA , NB , MYCOL , DESCA( CSRC_ ) , NPCOL )
077                        NP = NUMROC( N , NB , MYROW , IAROW , NPROW )
078                        NQ = NUMROC( N , NB , MYCOL , IACOL , NPCOL )
079  
080                        LQUERY =( LWORK.EQ. - 1 )
081                        TRILWMIN = 3*N + MAX( NB*( NP + 1 ) , 3*NB )
082                        LWMIN = MAX( 1 + 6*N + 2*NP*NQ , TRILWMIN ) + 2*N
083                        LIWMIN = 7*N + 8*NPCOL + 2
084                        WORK( 1 ) = DBLE( LWMIN )
085                        IWORK( 1 ) = LIWMIN
086                        IF( .NOT.LSAME( JOBZ , 'V' ) ) THEN
087                            INFO = - 1
088                        ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO , 'L' ) ) THEN
089                            INFO = - 2
090                        ELSE IF( IROFFA.NE.ICOFFA .OR. ICOFFA.NE.0 ) THEN
091                            INFO = - 6
092                        ELSE IF( IROFFA.NE.IROFFZ .OR. ICOFFA.NE.ICOFFZ ) THEN
093                            INFO = - 10
094                        ELSE IF( DESCA( M_ ).NE.DESCZ( M_ ) ) THEN
095                            INFO = - ( 1200 + M_ )
096                        ELSE IF( DESCA( MB_ ).NE.DESCA( NB_ ) ) THEN
097                            INFO = - ( 700 + NB_ )
098                        ELSE IF( DESCZ( MB_ ).NE.DESCZ( NB_ ) ) THEN
099                            INFO = - ( 1200 + NB_ )
100                        ELSE IF( DESCA( MB_ ).NE.DESCZ( MB_ ) ) THEN
101                            INFO = - ( 1200 + MB_ )
102                        ELSE IF( DESCA( CTXT_ ).NE.DESCZ( CTXT_ ) ) THEN
103                            INFO = - ( 1200 + CTXT_ )
104                        ELSE IF( DESCA( RSRC_ ).NE.DESCZ( RSRC_ ) ) THEN
105                            INFO = - ( 1200 + RSRC_ )
106                        ELSE IF( DESCA( CSRC_ ).NE.DESCZ( CSRC_ ) ) THEN
107                            INFO = - ( 1200 + CSRC_ )
108                        ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN
109                            INFO = - 14
110                        ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THEN
111                            INFO = - 16
112                        END IF
113                    END IF
114                    IF( UPPER ) THEN
115                        IDUM1( 1 ) = ICHAR( 'U' )
116                    ELSE
117                        IDUM1( 1 ) = ICHAR( 'L' )
118                    END IF
119                    IDUM2( 1 ) = 2
120                    IF( LWORK.EQ. - 1 ) THEN
121                        IDUM1( 2 ) = - 1
122                    ELSE
123                        IDUM1( 2 ) = 1
124                    END IF
125                    IDUM2( 2 ) = 14
126                    CALL PCHK1MAT( N , 3 , N , 3 , IA , JA , DESCA , 7 , 2 , IDUM1 , IDUM2 ,
127       $            INFO )
128                END IF
129                IF( INFO.NE.0 ) THEN
130                    CALL PXERBLA( ICTXT , 'PDSYEVD' , - INFO )
131                    RETURN
132                ELSE IF( LQUERY ) THEN
133                    RETURN
134                END IF
135  
136  *             Set up pointers into the WORK array
137  
138                INDTAU = 1
139                INDE = INDTAU + N
140                INDD = INDE + N
141                INDE2 = INDD + N
142                INDWORK = INDE2 + N
143                LLWORK = LWORK - INDWORK + 1
144                INDWORK2 = INDD
145                LLWORK2 = LWORK - INDWORK2 + 1
146  
147  *             Scale matrix to allowable range , if necessary.
148  
149                ISCALE = 0
150                SAFMIN = PDLAMCH( DESCA( CTXT_ ) , 'Safe minimum' )
151                EPS = PDLAMCH( DESCA( CTXT_ ) , 'Precision' )
152                SMLNUM = SAFMIN / EPS
153                BIGNUM = ONE / SMLNUM
154                RMIN = SQRT( SMLNUM )
155                RMAX = MIN( SQRT( BIGNUM ) , ONE / SQRT( SQRT( SAFMIN ) ) )
156                ANRM = PDLANSY( 'M' , UPLO , N , A , IA , JA , DESCA , WORK( INDWORK ) )
157  
158                IF( ANRM.GT.ZERO .AND. ANRM.LT.RMIN ) THEN
159                    ISCALE = 1
160                    SIGMA = RMIN / ANRM
161                ELSE IF( ANRM.GT.RMAX ) THEN
162                    ISCALE = 1
163                    SIGMA = RMAX / ANRM
164                END IF
165  
166                IF( ISCALE.EQ.1 ) THEN
167                    CALL PDLASCL ( UPLO , ONE , SIGMA , N , N , A , IA , JA , DESCA , IINFO )
168                END IF
169  
170  *             Reduce symmetric matrix to tridiagonal form.
171  
172                CALL PDSYTRD ( UPLO , N , A , IA , JA , DESCA , WORK( INDD ) ,
173       $        WORK( INDE2 ) , WORK( INDTAU ) , WORK( INDWORK ) ,
174       $        LLWORK , IINFO )
175  
176  *             Copy the values of D , E to all processes.
177  
178                CALL PDLARED1D ( N , IA , JA , DESCA , WORK( INDD ) , W ,
179       $        WORK( INDWORK ) , LLWORK )
180  
181                CALL PDLARED1D ( N , IA , JA , DESCA , WORK( INDE2 ) , WORK( INDE ) ,
182       $        WORK( INDWORK ) , LLWORK )
183  
184                CALL PDLASET ( 'Full' , N , N , ZERO , ONE , Z , 1 , 1 , DESCZ )
185  
186                IF( UPPER ) THEN
187                    OFFSET = 1
188                ELSE
189                    OFFSET = 0
190                END IF
191                CALL PDSTEDC ( 'I' , N , W , WORK( INDE + OFFSET ) , Z , IZ , JZ , DESCZ ,
192       $        WORK( INDWORK2 ) , LLWORK2 , IWORK , LIWORK , INFO )
193  
194                CALL PDORMTR ( 'L' , UPLO , 'N' , N , N , A , IA , JA , DESCA ,
195       $        WORK( INDTAU ) , Z , IZ , JZ , DESCZ , WORK( INDWORK2 ) ,
196       $        LLWORK2 , IINFO )
197  
198  *             If matrix was scaled , then rescale eigenvalues appropriately.
199  
200                IF( ISCALE.EQ.1 ) THEN
201                    CALL DSCAL( N , ONE / SIGMA , W , 1 )
202                END IF
203  
204                RETURN
205  
206  *             End of PDSYEVD
207  
208            END