Added arpack with bindings from scipy sandbox.

This commit is contained in:
2007-10-11 09:45:05 +00:00
parent e932022249
commit e8b1980775
103 changed files with 37986 additions and 0 deletions

View File

@@ -0,0 +1,384 @@
SUBROUTINE CLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, W, ILOZ,
$ IHIZ, Z, LDZ, INFO )
*
* -- LAPACK auxiliary routine (version 2.0) --
* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
* Courant Institute, Argonne National Lab, and Rice University
* September 30, 1994
*
* .. Scalar Arguments ..
LOGICAL WANTT, WANTZ
INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, N
* ..
* .. Array Arguments ..
COMPLEX H( LDH, * ), W( * ), Z( LDZ, * )
* ..
*
* Purpose
* =======
*
* CLAHQR is an auxiliary routine called by CHSEQR to update the
* eigenvalues and Schur decomposition already computed by CHSEQR, by
* dealing with the Hessenberg submatrix in rows and columns ILO to IHI.
*
* Arguments
* =========
*
* WANTT (input) LOGICAL
* = .TRUE. : the full Schur form T is required;
* = .FALSE.: only eigenvalues are required.
*
* WANTZ (input) LOGICAL
* = .TRUE. : the matrix of Schur vectors Z is required;
* = .FALSE.: Schur vectors are not required.
*
* N (input) INTEGER
* The order of the matrix H. N >= 0.
*
* ILO (input) INTEGER
* IHI (input) INTEGER
* It is assumed that H is already upper triangular in rows and
* columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless ILO = 1).
* CLAHQR works primarily with the Hessenberg submatrix in rows
* and columns ILO to IHI, but applies transformations to all of
* H if WANTT is .TRUE..
* 1 <= ILO <= max(1,IHI); IHI <= N.
*
* H (input/output) COMPLEX array, dimension (LDH,N)
* On entry, the upper Hessenberg matrix H.
* On exit, if WANTT is .TRUE., H is upper triangular in rows
* and columns ILO:IHI, with any 2-by-2 diagonal blocks in
* standard form. If WANTT is .FALSE., the contents of H are
* unspecified on exit.
*
* LDH (input) INTEGER
* The leading dimension of the array H. LDH >= max(1,N).
*
* W (output) COMPLEX array, dimension (N)
* The computed eigenvalues ILO to IHI are stored in the
* corresponding elements of W. If WANTT is .TRUE., the
* eigenvalues are stored in the same order as on the diagonal
* of the Schur form returned in H, with W(i) = H(i,i).
*
* ILOZ (input) INTEGER
* IHIZ (input) INTEGER
* Specify the rows of Z to which transformations must be
* applied if WANTZ is .TRUE..
* 1 <= ILOZ <= ILO; IHI <= IHIZ <= N.
*
* Z (input/output) COMPLEX array, dimension (LDZ,N)
* If WANTZ is .TRUE., on entry Z must contain the current
* matrix Z of transformations accumulated by CHSEQR, and on
* exit Z has been updated; transformations are applied only to
* the submatrix Z(ILOZ:IHIZ,ILO:IHI).
* If WANTZ is .FALSE., Z is not referenced.
*
* LDZ (input) INTEGER
* The leading dimension of the array Z. LDZ >= max(1,N).
*
* INFO (output) INTEGER
* = 0: successful exit
* > 0: if INFO = i, CLAHQR failed to compute all the
* eigenvalues ILO to IHI in a total of 30*(IHI-ILO+1)
* iterations; elements i+1:ihi of W contain those
* eigenvalues which have been successfully computed.
*
* =====================================================================
*
* .. Parameters ..
COMPLEX ZERO, ONE
PARAMETER ( ZERO = ( 0.0E+0, 0.0E+0 ),
$ ONE = ( 1.0E+0, 0.0E+0 ) )
REAL RZERO, HALF
PARAMETER ( RZERO = 0.0E+0, HALF = 0.5E+0 )
* ..
* .. Local Scalars ..
INTEGER I, I1, I2, ITN, ITS, J, K, L, M, NH, NZ
REAL H10, H21, RTEMP, S, SMLNUM, T2, TST1, ULP
COMPLEX CDUM, H11, H11S, H22, SUM, T, T1, TEMP, U, V2,
$ X, Y
* ..
* .. Local Arrays ..
REAL RWORK( 1 )
COMPLEX V( 2 )
* ..
* .. External Functions ..
REAL CLANHS, SLAMCH
COMPLEX CLADIV
EXTERNAL CLANHS, SLAMCH, CLADIV
* ..
* .. External Subroutines ..
EXTERNAL CCOPY, CLARFG, CSCAL
* ..
* .. Intrinsic Functions ..
INTRINSIC ABS, AIMAG, CONJG, MAX, MIN, REAL, SQRT
* ..
* .. Statement Functions ..
REAL CABS1
* ..
* .. Statement Function definitions ..
CABS1( CDUM ) = ABS( REAL( CDUM ) ) + ABS( AIMAG( CDUM ) )
* ..
* .. Executable Statements ..
*
INFO = 0
*
* Quick return if possible
*
IF( N.EQ.0 )
$ RETURN
IF( ILO.EQ.IHI ) THEN
W( ILO ) = H( ILO, ILO )
RETURN
END IF
*
NH = IHI - ILO + 1
NZ = IHIZ - ILOZ + 1
*
* Set machine-dependent constants for the stopping criterion.
* If norm(H) <= sqrt(OVFL), overflow should not occur.
*
ULP = SLAMCH( 'Precision' )
SMLNUM = SLAMCH( 'Safe minimum' ) / ULP
*
* I1 and I2 are the indices of the first row and last column of H
* to which transformations must be applied. If eigenvalues only are
* being computed, I1 and I2 are set inside the main loop.
*
IF( WANTT ) THEN
I1 = 1
I2 = N
END IF
*
* ITN is the total number of QR iterations allowed.
*
ITN = 30*NH
*
* The main loop begins here. I is the loop index and decreases from
* IHI to ILO in steps of 1. Each iteration of the loop works
* with the active submatrix in rows and columns L to I.
* Eigenvalues I+1 to IHI have already converged. Either L = ILO, or
* H(L,L-1) is negligible so that the matrix splits.
*
I = IHI
10 CONTINUE
IF( I.LT.ILO )
$ GO TO 130
*
* Perform QR iterations on rows and columns ILO to I until a
* submatrix of order 1 splits off at the bottom because a
* subdiagonal element has become negligible.
*
L = ILO
DO 110 ITS = 0, ITN
*
* Look for a single small subdiagonal element.
*
DO 20 K = I, L + 1, -1
TST1 = CABS1( H( K-1, K-1 ) ) + CABS1( H( K, K ) )
IF( TST1.EQ.RZERO )
$ TST1 = CLANHS( '1', I-L+1, H( L, L ), LDH, RWORK )
IF( ABS( REAL( H( K, K-1 ) ) ).LE.MAX( ULP*TST1, SMLNUM ) )
$ GO TO 30
20 CONTINUE
30 CONTINUE
L = K
IF( L.GT.ILO ) THEN
*
* H(L,L-1) is negligible
*
H( L, L-1 ) = ZERO
END IF
*
* Exit from loop if a submatrix of order 1 has split off.
*
IF( L.GE.I )
$ GO TO 120
*
* Now the active submatrix is in rows and columns L to I. If
* eigenvalues only are being computed, only the active submatrix
* need be transformed.
*
IF( .NOT.WANTT ) THEN
I1 = L
I2 = I
END IF
*
IF( ITS.EQ.10 .OR. ITS.EQ.20 ) THEN
*
* Exceptional shift.
*
T = ABS( REAL( H( I, I-1 ) ) ) +
$ ABS( REAL( H( I-1, I-2 ) ) )
ELSE
*
* Wilkinson's shift.
*
T = H( I, I )
U = H( I-1, I )*REAL( H( I, I-1 ) )
IF( U.NE.ZERO ) THEN
X = HALF*( H( I-1, I-1 )-T )
Y = SQRT( X*X+U )
IF( REAL( X )*REAL( Y )+AIMAG( X )*AIMAG( Y ).LT.RZERO )
$ Y = -Y
T = T - CLADIV( U, ( X+Y ) )
END IF
END IF
*
* Look for two consecutive small subdiagonal elements.
*
DO 40 M = I - 1, L + 1, -1
*
* Determine the effect of starting the single-shift QR
* iteration at row M, and see if this would make H(M,M-1)
* negligible.
*
H11 = H( M, M )
H22 = H( M+1, M+1 )
H11S = H11 - T
H21 = H( M+1, M )
S = CABS1( H11S ) + ABS( H21 )
H11S = H11S / S
H21 = H21 / S
V( 1 ) = H11S
V( 2 ) = H21
H10 = H( M, M-1 )
TST1 = CABS1( H11S )*( CABS1( H11 )+CABS1( H22 ) )
IF( ABS( H10*H21 ).LE.ULP*TST1 )
$ GO TO 50
40 CONTINUE
H11 = H( L, L )
H22 = H( L+1, L+1 )
H11S = H11 - T
H21 = H( L+1, L )
S = CABS1( H11S ) + ABS( H21 )
H11S = H11S / S
H21 = H21 / S
V( 1 ) = H11S
V( 2 ) = H21
50 CONTINUE
*
* Single-shift QR step
*
DO 100 K = M, I - 1
*
* The first iteration of this loop determines a reflection G
* from the vector V and applies it from left and right to H,
* thus creating a nonzero bulge below the subdiagonal.
*
* Each subsequent iteration determines a reflection G to
* restore the Hessenberg form in the (K-1)th column, and thus
* chases the bulge one step toward the bottom of the active
* submatrix.
*
* V(2) is always real before the call to CLARFG, and hence
* after the call T2 ( = T1*V(2) ) is also real.
*
IF( K.GT.M )
$ CALL CCOPY( 2, H( K, K-1 ), 1, V, 1 )
CALL CLARFG( 2, V( 1 ), V( 2 ), 1, T1 )
IF( K.GT.M ) THEN
H( K, K-1 ) = V( 1 )
H( K+1, K-1 ) = ZERO
END IF
V2 = V( 2 )
T2 = REAL( T1*V2 )
*
* Apply G from the left to transform the rows of the matrix
* in columns K to I2.
*
DO 60 J = K, I2
SUM = CONJG( T1 )*H( K, J ) + T2*H( K+1, J )
H( K, J ) = H( K, J ) - SUM
H( K+1, J ) = H( K+1, J ) - SUM*V2
60 CONTINUE
*
* Apply G from the right to transform the columns of the
* matrix in rows I1 to min(K+2,I).
*
DO 70 J = I1, MIN( K+2, I )
SUM = T1*H( J, K ) + T2*H( J, K+1 )
H( J, K ) = H( J, K ) - SUM
H( J, K+1 ) = H( J, K+1 ) - SUM*CONJG( V2 )
70 CONTINUE
*
IF( WANTZ ) THEN
*
* Accumulate transformations in the matrix Z
*
DO 80 J = ILOZ, IHIZ
SUM = T1*Z( J, K ) + T2*Z( J, K+1 )
Z( J, K ) = Z( J, K ) - SUM
Z( J, K+1 ) = Z( J, K+1 ) - SUM*CONJG( V2 )
80 CONTINUE
END IF
*
IF( K.EQ.M .AND. M.GT.L ) THEN
*
* If the QR step was started at row M > L because two
* consecutive small subdiagonals were found, then extra
* scaling must be performed to ensure that H(M,M-1) remains
* real.
*
TEMP = ONE - T1
TEMP = TEMP / ABS( TEMP )
H( M+1, M ) = H( M+1, M )*CONJG( TEMP )
IF( M+2.LE.I )
$ H( M+2, M+1 ) = H( M+2, M+1 )*TEMP
DO 90 J = M, I
IF( J.NE.M+1 ) THEN
IF( I2.GT.J )
$ CALL CSCAL( I2-J, TEMP, H( J, J+1 ), LDH )
CALL CSCAL( J-I1, CONJG( TEMP ), H( I1, J ), 1 )
IF( WANTZ ) THEN
CALL CSCAL( NZ, CONJG( TEMP ), Z( ILOZ, J ), 1 )
END IF
END IF
90 CONTINUE
END IF
100 CONTINUE
*
* Ensure that H(I,I-1) is real.
*
TEMP = H( I, I-1 )
IF( AIMAG( TEMP ).NE.RZERO ) THEN
RTEMP = ABS( TEMP )
H( I, I-1 ) = RTEMP
TEMP = TEMP / RTEMP
IF( I2.GT.I )
$ CALL CSCAL( I2-I, CONJG( TEMP ), H( I, I+1 ), LDH )
CALL CSCAL( I-I1, TEMP, H( I1, I ), 1 )
IF( WANTZ ) THEN
CALL CSCAL( NZ, TEMP, Z( ILOZ, I ), 1 )
END IF
END IF
*
110 CONTINUE
*
* Failure to converge in remaining number of iterations
*
INFO = I
RETURN
*
120 CONTINUE
*
* H(I,I-1) is negligible: one eigenvalue has converged.
*
W( I ) = H( I, I )
*
* Decrement number of remaining iterations, and return to start of
* the main loop with new value of I.
*
ITN = ITN - ITS
I = L - 1
GO TO 10
*
130 CONTINUE
RETURN
*
* End of CLAHQR
*
END

View File

@@ -0,0 +1,410 @@
SUBROUTINE DLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI,
$ ILOZ, IHIZ, Z, LDZ, INFO )
*
* -- LAPACK auxiliary routine (version 2.0) --
* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
* Courant Institute, Argonne National Lab, and Rice University
* October 31, 1992
*
* .. Scalar Arguments ..
LOGICAL WANTT, WANTZ
INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, N
* ..
* .. Array Arguments ..
DOUBLE PRECISION H( LDH, * ), WI( * ), WR( * ), Z( LDZ, * )
* ..
*
* Purpose
* =======
*
* DLAHQR is an auxiliary routine called by DHSEQR to update the
* eigenvalues and Schur decomposition already computed by DHSEQR, by
* dealing with the Hessenberg submatrix in rows and columns ILO to IHI.
*
* Arguments
* =========
*
* WANTT (input) LOGICAL
* = .TRUE. : the full Schur form T is required;
* = .FALSE.: only eigenvalues are required.
*
* WANTZ (input) LOGICAL
* = .TRUE. : the matrix of Schur vectors Z is required;
* = .FALSE.: Schur vectors are not required.
*
* N (input) INTEGER
* The order of the matrix H. N >= 0.
*
* ILO (input) INTEGER
* IHI (input) INTEGER
* It is assumed that H is already upper quasi-triangular in
* rows and columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless
* ILO = 1). DLAHQR works primarily with the Hessenberg
* submatrix in rows and columns ILO to IHI, but applies
* transformations to all of H if WANTT is .TRUE..
* 1 <= ILO <= max(1,IHI); IHI <= N.
*
* H (input/output) DOUBLE PRECISION array, dimension (LDH,N)
* On entry, the upper Hessenberg matrix H.
* On exit, if WANTT is .TRUE., H is upper quasi-triangular in
* rows and columns ILO:IHI, with any 2-by-2 diagonal blocks in
* standard form. If WANTT is .FALSE., the contents of H are
* unspecified on exit.
*
* LDH (input) INTEGER
* The leading dimension of the array H. LDH >= max(1,N).
*
* WR (output) DOUBLE PRECISION array, dimension (N)
* WI (output) DOUBLE PRECISION array, dimension (N)
* The real and imaginary parts, respectively, of the computed
* eigenvalues ILO to IHI are stored in the corresponding
* elements of WR and WI. If two eigenvalues are computed as a
* complex conjugate pair, they are stored in consecutive
* elements of WR and WI, say the i-th and (i+1)th, with
* WI(i) > 0 and WI(i+1) < 0. If WANTT is .TRUE., the
* eigenvalues are stored in the same order as on the diagonal
* of the Schur form returned in H, with WR(i) = H(i,i), and, if
* H(i:i+1,i:i+1) is a 2-by-2 diagonal block,
* WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and WI(i+1) = -WI(i).
*
* ILOZ (input) INTEGER
* IHIZ (input) INTEGER
* Specify the rows of Z to which transformations must be
* applied if WANTZ is .TRUE..
* 1 <= ILOZ <= ILO; IHI <= IHIZ <= N.
*
* Z (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
* If WANTZ is .TRUE., on entry Z must contain the current
* matrix Z of transformations accumulated by DHSEQR, and on
* exit Z has been updated; transformations are applied only to
* the submatrix Z(ILOZ:IHIZ,ILO:IHI).
* If WANTZ is .FALSE., Z is not referenced.
*
* LDZ (input) INTEGER
* The leading dimension of the array Z. LDZ >= max(1,N).
*
* INFO (output) INTEGER
* = 0: successful exit
* > 0: DLAHQR failed to compute all the eigenvalues ILO to IHI
* in a total of 30*(IHI-ILO+1) iterations; if INFO = i,
* elements i+1:ihi of WR and WI contain those eigenvalues
* which have been successfully computed.
*
* =====================================================================
*
* .. Parameters ..
DOUBLE PRECISION ZERO, ONE
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
DOUBLE PRECISION DAT1, DAT2
PARAMETER ( DAT1 = 0.75D+0, DAT2 = -0.4375D+0 )
* ..
* .. Local Scalars ..
INTEGER I, I1, I2, ITN, ITS, J, K, L, M, NH, NR, NZ
DOUBLE PRECISION CS, H00, H10, H11, H12, H21, H22, H33, H33S,
$ H43H34, H44, H44S, OVFL, S, SMLNUM, SN, SUM,
$ T1, T2, T3, TST1, ULP, UNFL, V1, V2, V3
* ..
* .. Local Arrays ..
DOUBLE PRECISION V( 3 ), WORK( 1 )
* ..
* .. External Functions ..
DOUBLE PRECISION DLAMCH, DLANHS
EXTERNAL DLAMCH, DLANHS
* ..
* .. External Subroutines ..
EXTERNAL DCOPY, DLABAD, DLANV2, DLARFG, DROT
* ..
* .. Intrinsic Functions ..
INTRINSIC ABS, MAX, MIN
* ..
* .. Executable Statements ..
*
INFO = 0
*
* Quick return if possible
*
IF( N.EQ.0 )
$ RETURN
IF( ILO.EQ.IHI ) THEN
WR( ILO ) = H( ILO, ILO )
WI( ILO ) = ZERO
RETURN
END IF
*
NH = IHI - ILO + 1
NZ = IHIZ - ILOZ + 1
*
* Set machine-dependent constants for the stopping criterion.
* If norm(H) <= sqrt(OVFL), overflow should not occur.
*
UNFL = DLAMCH( 'Safe minimum' )
OVFL = ONE / UNFL
CALL DLABAD( UNFL, OVFL )
ULP = DLAMCH( 'Precision' )
SMLNUM = UNFL*( NH / ULP )
*
* I1 and I2 are the indices of the first row and last column of H
* to which transformations must be applied. If eigenvalues only are
* being computed, I1 and I2 are set inside the main loop.
*
IF( WANTT ) THEN
I1 = 1
I2 = N
END IF
*
* ITN is the total number of QR iterations allowed.
*
ITN = 30*NH
*
* The main loop begins here. I is the loop index and decreases from
* IHI to ILO in steps of 1 or 2. Each iteration of the loop works
* with the active submatrix in rows and columns L to I.
* Eigenvalues I+1 to IHI have already converged. Either L = ILO or
* H(L,L-1) is negligible so that the matrix splits.
*
I = IHI
10 CONTINUE
L = ILO
IF( I.LT.ILO )
$ GO TO 150
*
* Perform QR iterations on rows and columns ILO to I until a
* submatrix of order 1 or 2 splits off at the bottom because a
* subdiagonal element has become negligible.
*
DO 130 ITS = 0, ITN
*
* Look for a single small subdiagonal element.
*
DO 20 K = I, L + 1, -1
TST1 = ABS( H( K-1, K-1 ) ) + ABS( H( K, K ) )
IF( TST1.EQ.ZERO )
$ TST1 = DLANHS( '1', I-L+1, H( L, L ), LDH, WORK )
IF( ABS( H( K, K-1 ) ).LE.MAX( ULP*TST1, SMLNUM ) )
$ GO TO 30
20 CONTINUE
30 CONTINUE
L = K
IF( L.GT.ILO ) THEN
*
* H(L,L-1) is negligible
*
H( L, L-1 ) = ZERO
END IF
*
* Exit from loop if a submatrix of order 1 or 2 has split off.
*
IF( L.GE.I-1 )
$ GO TO 140
*
* Now the active submatrix is in rows and columns L to I. If
* eigenvalues only are being computed, only the active submatrix
* need be transformed.
*
IF( .NOT.WANTT ) THEN
I1 = L
I2 = I
END IF
*
IF( ITS.EQ.10 .OR. ITS.EQ.20 ) THEN
*
* Exceptional shift.
*
S = ABS( H( I, I-1 ) ) + ABS( H( I-1, I-2 ) )
H44 = DAT1*S
H33 = H44
H43H34 = DAT2*S*S
ELSE
*
* Prepare to use Wilkinson's double shift
*
H44 = H( I, I )
H33 = H( I-1, I-1 )
H43H34 = H( I, I-1 )*H( I-1, I )
END IF
*
* Look for two consecutive small subdiagonal elements.
*
DO 40 M = I - 2, L, -1
*
* Determine the effect of starting the double-shift QR
* iteration at row M, and see if this would make H(M,M-1)
* negligible.
*
H11 = H( M, M )
H22 = H( M+1, M+1 )
H21 = H( M+1, M )
H12 = H( M, M+1 )
H44S = H44 - H11
H33S = H33 - H11
V1 = ( H33S*H44S-H43H34 ) / H21 + H12
V2 = H22 - H11 - H33S - H44S
V3 = H( M+2, M+1 )
S = ABS( V1 ) + ABS( V2 ) + ABS( V3 )
V1 = V1 / S
V2 = V2 / S
V3 = V3 / S
V( 1 ) = V1
V( 2 ) = V2
V( 3 ) = V3
IF( M.EQ.L )
$ GO TO 50
H00 = H( M-1, M-1 )
H10 = H( M, M-1 )
TST1 = ABS( V1 )*( ABS( H00 )+ABS( H11 )+ABS( H22 ) )
IF( ABS( H10 )*( ABS( V2 )+ABS( V3 ) ).LE.ULP*TST1 )
$ GO TO 50
40 CONTINUE
50 CONTINUE
*
* Double-shift QR step
*
DO 120 K = M, I - 1
*
* The first iteration of this loop determines a reflection G
* from the vector V and applies it from left and right to H,
* thus creating a nonzero bulge below the subdiagonal.
*
* Each subsequent iteration determines a reflection G to
* restore the Hessenberg form in the (K-1)th column, and thus
* chases the bulge one step toward the bottom of the active
* submatrix. NR is the order of G.
*
NR = MIN( 3, I-K+1 )
IF( K.GT.M )
$ CALL DCOPY( NR, H( K, K-1 ), 1, V, 1 )
CALL DLARFG( NR, V( 1 ), V( 2 ), 1, T1 )
IF( K.GT.M ) THEN
H( K, K-1 ) = V( 1 )
H( K+1, K-1 ) = ZERO
IF( K.LT.I-1 )
$ H( K+2, K-1 ) = ZERO
ELSE IF( M.GT.L ) THEN
H( K, K-1 ) = -H( K, K-1 )
END IF
V2 = V( 2 )
T2 = T1*V2
IF( NR.EQ.3 ) THEN
V3 = V( 3 )
T3 = T1*V3
*
* Apply G from the left to transform the rows of the matrix
* in columns K to I2.
*
DO 60 J = K, I2
SUM = H( K, J ) + V2*H( K+1, J ) + V3*H( K+2, J )
H( K, J ) = H( K, J ) - SUM*T1
H( K+1, J ) = H( K+1, J ) - SUM*T2
H( K+2, J ) = H( K+2, J ) - SUM*T3
60 CONTINUE
*
* Apply G from the right to transform the columns of the
* matrix in rows I1 to min(K+3,I).
*
DO 70 J = I1, MIN( K+3, I )
SUM = H( J, K ) + V2*H( J, K+1 ) + V3*H( J, K+2 )
H( J, K ) = H( J, K ) - SUM*T1
H( J, K+1 ) = H( J, K+1 ) - SUM*T2
H( J, K+2 ) = H( J, K+2 ) - SUM*T3
70 CONTINUE
*
IF( WANTZ ) THEN
*
* Accumulate transformations in the matrix Z
*
DO 80 J = ILOZ, IHIZ
SUM = Z( J, K ) + V2*Z( J, K+1 ) + V3*Z( J, K+2 )
Z( J, K ) = Z( J, K ) - SUM*T1
Z( J, K+1 ) = Z( J, K+1 ) - SUM*T2
Z( J, K+2 ) = Z( J, K+2 ) - SUM*T3
80 CONTINUE
END IF
ELSE IF( NR.EQ.2 ) THEN
*
* Apply G from the left to transform the rows of the matrix
* in columns K to I2.
*
DO 90 J = K, I2
SUM = H( K, J ) + V2*H( K+1, J )
H( K, J ) = H( K, J ) - SUM*T1
H( K+1, J ) = H( K+1, J ) - SUM*T2
90 CONTINUE
*
* Apply G from the right to transform the columns of the
* matrix in rows I1 to min(K+3,I).
*
DO 100 J = I1, I
SUM = H( J, K ) + V2*H( J, K+1 )
H( J, K ) = H( J, K ) - SUM*T1
H( J, K+1 ) = H( J, K+1 ) - SUM*T2
100 CONTINUE
*
IF( WANTZ ) THEN
*
* Accumulate transformations in the matrix Z
*
DO 110 J = ILOZ, IHIZ
SUM = Z( J, K ) + V2*Z( J, K+1 )
Z( J, K ) = Z( J, K ) - SUM*T1
Z( J, K+1 ) = Z( J, K+1 ) - SUM*T2
110 CONTINUE
END IF
END IF
120 CONTINUE
*
130 CONTINUE
*
* Failure to converge in remaining number of iterations
*
INFO = I
RETURN
*
140 CONTINUE
*
IF( L.EQ.I ) THEN
*
* H(I,I-1) is negligible: one eigenvalue has converged.
*
WR( I ) = H( I, I )
WI( I ) = ZERO
ELSE IF( L.EQ.I-1 ) THEN
*
* H(I-1,I-2) is negligible: a pair of eigenvalues have converged.
*
* Transform the 2-by-2 submatrix to standard Schur form,
* and compute and store the eigenvalues.
*
CALL DLANV2( H( I-1, I-1 ), H( I-1, I ), H( I, I-1 ),
$ H( I, I ), WR( I-1 ), WI( I-1 ), WR( I ), WI( I ),
$ CS, SN )
*
IF( WANTT ) THEN
*
* Apply the transformation to the rest of H.
*
IF( I2.GT.I )
$ CALL DROT( I2-I, H( I-1, I+1 ), LDH, H( I, I+1 ), LDH,
$ CS, SN )
CALL DROT( I-I1-1, H( I1, I-1 ), 1, H( I1, I ), 1, CS, SN )
END IF
IF( WANTZ ) THEN
*
* Apply the transformation to Z.
*
CALL DROT( NZ, Z( ILOZ, I-1 ), 1, Z( ILOZ, I ), 1, CS, SN )
END IF
END IF
*
* Decrement number of remaining iterations, and return to start of
* the main loop with new value of I.
*
ITN = ITN - ITS
I = L - 1
GO TO 10
*
150 CONTINUE
RETURN
*
* End of DLAHQR
*
END

View File

@@ -0,0 +1,410 @@
SUBROUTINE SLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, WR, WI,
$ ILOZ, IHIZ, Z, LDZ, INFO )
*
* -- LAPACK auxiliary routine (version 2.0) --
* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
* Courant Institute, Argonne National Lab, and Rice University
* October 31, 1992
*
* .. Scalar Arguments ..
LOGICAL WANTT, WANTZ
INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, N
* ..
* .. Array Arguments ..
REAL H( LDH, * ), WI( * ), WR( * ), Z( LDZ, * )
* ..
*
* Purpose
* =======
*
* SLAHQR is an auxiliary routine called by SHSEQR to update the
* eigenvalues and Schur decomposition already computed by SHSEQR, by
* dealing with the Hessenberg submatrix in rows and columns ILO to IHI.
*
* Arguments
* =========
*
* WANTT (input) LOGICAL
* = .TRUE. : the full Schur form T is required;
* = .FALSE.: only eigenvalues are required.
*
* WANTZ (input) LOGICAL
* = .TRUE. : the matrix of Schur vectors Z is required;
* = .FALSE.: Schur vectors are not required.
*
* N (input) INTEGER
* The order of the matrix H. N >= 0.
*
* ILO (input) INTEGER
* IHI (input) INTEGER
* It is assumed that H is already upper quasi-triangular in
* rows and columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless
* ILO = 1). SLAHQR works primarily with the Hessenberg
* submatrix in rows and columns ILO to IHI, but applies
* transformations to all of H if WANTT is .TRUE..
* 1 <= ILO <= max(1,IHI); IHI <= N.
*
* H (input/output) REAL array, dimension (LDH,N)
* On entry, the upper Hessenberg matrix H.
* On exit, if WANTT is .TRUE., H is upper quasi-triangular in
* rows and columns ILO:IHI, with any 2-by-2 diagonal blocks in
* standard form. If WANTT is .FALSE., the contents of H are
* unspecified on exit.
*
* LDH (input) INTEGER
* The leading dimension of the array H. LDH >= max(1,N).
*
* WR (output) REAL array, dimension (N)
* WI (output) REAL array, dimension (N)
* The real and imaginary parts, respectively, of the computed
* eigenvalues ILO to IHI are stored in the corresponding
* elements of WR and WI. If two eigenvalues are computed as a
* complex conjugate pair, they are stored in consecutive
* elements of WR and WI, say the i-th and (i+1)th, with
* WI(i) > 0 and WI(i+1) < 0. If WANTT is .TRUE., the
* eigenvalues are stored in the same order as on the diagonal
* of the Schur form returned in H, with WR(i) = H(i,i), and, if
* H(i:i+1,i:i+1) is a 2-by-2 diagonal block,
* WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and WI(i+1) = -WI(i).
*
* ILOZ (input) INTEGER
* IHIZ (input) INTEGER
* Specify the rows of Z to which transformations must be
* applied if WANTZ is .TRUE..
* 1 <= ILOZ <= ILO; IHI <= IHIZ <= N.
*
* Z (input/output) REAL array, dimension (LDZ,N)
* If WANTZ is .TRUE., on entry Z must contain the current
* matrix Z of transformations accumulated by SHSEQR, and on
* exit Z has been updated; transformations are applied only to
* the submatrix Z(ILOZ:IHIZ,ILO:IHI).
* If WANTZ is .FALSE., Z is not referenced.
*
* LDZ (input) INTEGER
* The leading dimension of the array Z. LDZ >= max(1,N).
*
* INFO (output) INTEGER
* = 0: successful exit
* > 0: SLAHQR failed to compute all the eigenvalues ILO to IHI
* in a total of 30*(IHI-ILO+1) iterations; if INFO = i,
* elements i+1:ihi of WR and WI contain those eigenvalues
* which have been successfully computed.
*
* =====================================================================
*
* .. Parameters ..
REAL ZERO, ONE
PARAMETER ( ZERO = 0.0E+0, ONE = 1.0E+0 )
REAL DAT1, DAT2
PARAMETER ( DAT1 = 0.75E+0, DAT2 = -0.4375E+0 )
* ..
* .. Local Scalars ..
INTEGER I, I1, I2, ITN, ITS, J, K, L, M, NH, NR, NZ
REAL CS, H00, H10, H11, H12, H21, H22, H33, H33S,
$ H43H34, H44, H44S, OVFL, S, SMLNUM, SN, SUM,
$ T1, T2, T3, TST1, ULP, UNFL, V1, V2, V3
* ..
* .. Local Arrays ..
REAL V( 3 ), WORK( 1 )
* ..
* .. External Functions ..
REAL SLAMCH, SLANHS
EXTERNAL SLAMCH, SLANHS
* ..
* .. External Subroutines ..
EXTERNAL SCOPY, SLABAD, SLANV2, SLARFG, SROT
* ..
* .. Intrinsic Functions ..
INTRINSIC ABS, MAX, MIN
* ..
* .. Executable Statements ..
*
INFO = 0
*
* Quick return if possible
*
IF( N.EQ.0 )
$ RETURN
IF( ILO.EQ.IHI ) THEN
WR( ILO ) = H( ILO, ILO )
WI( ILO ) = ZERO
RETURN
END IF
*
NH = IHI - ILO + 1
NZ = IHIZ - ILOZ + 1
*
* Set machine-dependent constants for the stopping criterion.
* If norm(H) <= sqrt(OVFL), overflow should not occur.
*
UNFL = SLAMCH( 'Safe minimum' )
OVFL = ONE / UNFL
CALL SLABAD( UNFL, OVFL )
ULP = SLAMCH( 'Precision' )
SMLNUM = UNFL*( NH / ULP )
*
* I1 and I2 are the indices of the first row and last column of H
* to which transformations must be applied. If eigenvalues only are
* being computed, I1 and I2 are set inside the main loop.
*
IF( WANTT ) THEN
I1 = 1
I2 = N
END IF
*
* ITN is the total number of QR iterations allowed.
*
ITN = 30*NH
*
* The main loop begins here. I is the loop index and decreases from
* IHI to ILO in steps of 1 or 2. Each iteration of the loop works
* with the active submatrix in rows and columns L to I.
* Eigenvalues I+1 to IHI have already converged. Either L = ILO or
* H(L,L-1) is negligible so that the matrix splits.
*
I = IHI
10 CONTINUE
L = ILO
IF( I.LT.ILO )
$ GO TO 150
*
* Perform QR iterations on rows and columns ILO to I until a
* submatrix of order 1 or 2 splits off at the bottom because a
* subdiagonal element has become negligible.
*
DO 130 ITS = 0, ITN
*
* Look for a single small subdiagonal element.
*
DO 20 K = I, L + 1, -1
TST1 = ABS( H( K-1, K-1 ) ) + ABS( H( K, K ) )
IF( TST1.EQ.ZERO )
$ TST1 = SLANHS( '1', I-L+1, H( L, L ), LDH, WORK )
IF( ABS( H( K, K-1 ) ).LE.MAX( ULP*TST1, SMLNUM ) )
$ GO TO 30
20 CONTINUE
30 CONTINUE
L = K
IF( L.GT.ILO ) THEN
*
* H(L,L-1) is negligible
*
H( L, L-1 ) = ZERO
END IF
*
* Exit from loop if a submatrix of order 1 or 2 has split off.
*
IF( L.GE.I-1 )
$ GO TO 140
*
* Now the active submatrix is in rows and columns L to I. If
* eigenvalues only are being computed, only the active submatrix
* need be transformed.
*
IF( .NOT.WANTT ) THEN
I1 = L
I2 = I
END IF
*
IF( ITS.EQ.10 .OR. ITS.EQ.20 ) THEN
*
* Exceptional shift.
*
S = ABS( H( I, I-1 ) ) + ABS( H( I-1, I-2 ) )
H44 = DAT1*S
H33 = H44
H43H34 = DAT2*S*S
ELSE
*
* Prepare to use Wilkinson's double shift
*
H44 = H( I, I )
H33 = H( I-1, I-1 )
H43H34 = H( I, I-1 )*H( I-1, I )
END IF
*
* Look for two consecutive small subdiagonal elements.
*
DO 40 M = I - 2, L, -1
*
* Determine the effect of starting the double-shift QR
* iteration at row M, and see if this would make H(M,M-1)
* negligible.
*
H11 = H( M, M )
H22 = H( M+1, M+1 )
H21 = H( M+1, M )
H12 = H( M, M+1 )
H44S = H44 - H11
H33S = H33 - H11
V1 = ( H33S*H44S-H43H34 ) / H21 + H12
V2 = H22 - H11 - H33S - H44S
V3 = H( M+2, M+1 )
S = ABS( V1 ) + ABS( V2 ) + ABS( V3 )
V1 = V1 / S
V2 = V2 / S
V3 = V3 / S
V( 1 ) = V1
V( 2 ) = V2
V( 3 ) = V3
IF( M.EQ.L )
$ GO TO 50
H00 = H( M-1, M-1 )
H10 = H( M, M-1 )
TST1 = ABS( V1 )*( ABS( H00 )+ABS( H11 )+ABS( H22 ) )
IF( ABS( H10 )*( ABS( V2 )+ABS( V3 ) ).LE.ULP*TST1 )
$ GO TO 50
40 CONTINUE
50 CONTINUE
*
* Double-shift QR step
*
DO 120 K = M, I - 1
*
* The first iteration of this loop determines a reflection G
* from the vector V and applies it from left and right to H,
* thus creating a nonzero bulge below the subdiagonal.
*
* Each subsequent iteration determines a reflection G to
* restore the Hessenberg form in the (K-1)th column, and thus
* chases the bulge one step toward the bottom of the active
* submatrix. NR is the order of G.
*
NR = MIN( 3, I-K+1 )
IF( K.GT.M )
$ CALL SCOPY( NR, H( K, K-1 ), 1, V, 1 )
CALL SLARFG( NR, V( 1 ), V( 2 ), 1, T1 )
IF( K.GT.M ) THEN
H( K, K-1 ) = V( 1 )
H( K+1, K-1 ) = ZERO
IF( K.LT.I-1 )
$ H( K+2, K-1 ) = ZERO
ELSE IF( M.GT.L ) THEN
H( K, K-1 ) = -H( K, K-1 )
END IF
V2 = V( 2 )
T2 = T1*V2
IF( NR.EQ.3 ) THEN
V3 = V( 3 )
T3 = T1*V3
*
* Apply G from the left to transform the rows of the matrix
* in columns K to I2.
*
DO 60 J = K, I2
SUM = H( K, J ) + V2*H( K+1, J ) + V3*H( K+2, J )
H( K, J ) = H( K, J ) - SUM*T1
H( K+1, J ) = H( K+1, J ) - SUM*T2
H( K+2, J ) = H( K+2, J ) - SUM*T3
60 CONTINUE
*
* Apply G from the right to transform the columns of the
* matrix in rows I1 to min(K+3,I).
*
DO 70 J = I1, MIN( K+3, I )
SUM = H( J, K ) + V2*H( J, K+1 ) + V3*H( J, K+2 )
H( J, K ) = H( J, K ) - SUM*T1
H( J, K+1 ) = H( J, K+1 ) - SUM*T2
H( J, K+2 ) = H( J, K+2 ) - SUM*T3
70 CONTINUE
*
IF( WANTZ ) THEN
*
* Accumulate transformations in the matrix Z
*
DO 80 J = ILOZ, IHIZ
SUM = Z( J, K ) + V2*Z( J, K+1 ) + V3*Z( J, K+2 )
Z( J, K ) = Z( J, K ) - SUM*T1
Z( J, K+1 ) = Z( J, K+1 ) - SUM*T2
Z( J, K+2 ) = Z( J, K+2 ) - SUM*T3
80 CONTINUE
END IF
ELSE IF( NR.EQ.2 ) THEN
*
* Apply G from the left to transform the rows of the matrix
* in columns K to I2.
*
DO 90 J = K, I2
SUM = H( K, J ) + V2*H( K+1, J )
H( K, J ) = H( K, J ) - SUM*T1
H( K+1, J ) = H( K+1, J ) - SUM*T2
90 CONTINUE
*
* Apply G from the right to transform the columns of the
* matrix in rows I1 to min(K+3,I).
*
DO 100 J = I1, I
SUM = H( J, K ) + V2*H( J, K+1 )
H( J, K ) = H( J, K ) - SUM*T1
H( J, K+1 ) = H( J, K+1 ) - SUM*T2
100 CONTINUE
*
IF( WANTZ ) THEN
*
* Accumulate transformations in the matrix Z
*
DO 110 J = ILOZ, IHIZ
SUM = Z( J, K ) + V2*Z( J, K+1 )
Z( J, K ) = Z( J, K ) - SUM*T1
Z( J, K+1 ) = Z( J, K+1 ) - SUM*T2
110 CONTINUE
END IF
END IF
120 CONTINUE
*
130 CONTINUE
*
* Failure to converge in remaining number of iterations
*
INFO = I
RETURN
*
140 CONTINUE
*
IF( L.EQ.I ) THEN
*
* H(I,I-1) is negligible: one eigenvalue has converged.
*
WR( I ) = H( I, I )
WI( I ) = ZERO
ELSE IF( L.EQ.I-1 ) THEN
*
* H(I-1,I-2) is negligible: a pair of eigenvalues have converged.
*
* Transform the 2-by-2 submatrix to standard Schur form,
* and compute and store the eigenvalues.
*
CALL SLANV2( H( I-1, I-1 ), H( I-1, I ), H( I, I-1 ),
$ H( I, I ), WR( I-1 ), WI( I-1 ), WR( I ), WI( I ),
$ CS, SN )
*
IF( WANTT ) THEN
*
* Apply the transformation to the rest of H.
*
IF( I2.GT.I )
$ CALL SROT( I2-I, H( I-1, I+1 ), LDH, H( I, I+1 ), LDH,
$ CS, SN )
CALL SROT( I-I1-1, H( I1, I-1 ), 1, H( I1, I ), 1, CS, SN )
END IF
IF( WANTZ ) THEN
*
* Apply the transformation to Z.
*
CALL SROT( NZ, Z( ILOZ, I-1 ), 1, Z( ILOZ, I ), 1, CS, SN )
END IF
END IF
*
* Decrement number of remaining iterations, and return to start of
* the main loop with new value of I.
*
ITN = ITN - ITS
I = L - 1
GO TO 10
*
150 CONTINUE
RETURN
*
* End of SLAHQR
*
END

View File

@@ -0,0 +1,385 @@
SUBROUTINE ZLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, W, ILOZ,
$ IHIZ, Z, LDZ, INFO )
*
* -- LAPACK auxiliary routine (version 2.0) --
* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
* Courant Institute, Argonne National Lab, and Rice University
* September 30, 1994
*
* .. Scalar Arguments ..
LOGICAL WANTT, WANTZ
INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, N
* ..
* .. Array Arguments ..
COMPLEX*16 H( LDH, * ), W( * ), Z( LDZ, * )
* ..
*
* Purpose
* =======
*
* ZLAHQR is an auxiliary routine called by CHSEQR to update the
* eigenvalues and Schur decomposition already computed by CHSEQR, by
* dealing with the Hessenberg submatrix in rows and columns ILO to IHI.
*
* Arguments
* =========
*
* WANTT (input) LOGICAL
* = .TRUE. : the full Schur form T is required;
* = .FALSE.: only eigenvalues are required.
*
* WANTZ (input) LOGICAL
* = .TRUE. : the matrix of Schur vectors Z is required;
* = .FALSE.: Schur vectors are not required.
*
* N (input) INTEGER
* The order of the matrix H. N >= 0.
*
* ILO (input) INTEGER
* IHI (input) INTEGER
* It is assumed that H is already upper triangular in rows and
* columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless ILO = 1).
* ZLAHQR works primarily with the Hessenberg submatrix in rows
* and columns ILO to IHI, but applies transformations to all of
* H if WANTT is .TRUE..
* 1 <= ILO <= max(1,IHI); IHI <= N.
*
* H (input/output) COMPLEX*16 array, dimension (LDH,N)
* On entry, the upper Hessenberg matrix H.
* On exit, if WANTT is .TRUE., H is upper triangular in rows
* and columns ILO:IHI, with any 2-by-2 diagonal blocks in
* standard form. If WANTT is .FALSE., the contents of H are
* unspecified on exit.
*
* LDH (input) INTEGER
* The leading dimension of the array H. LDH >= max(1,N).
*
* W (output) COMPLEX*16 array, dimension (N)
* The computed eigenvalues ILO to IHI are stored in the
* corresponding elements of W. If WANTT is .TRUE., the
* eigenvalues are stored in the same order as on the diagonal
* of the Schur form returned in H, with W(i) = H(i,i).
*
* ILOZ (input) INTEGER
* IHIZ (input) INTEGER
* Specify the rows of Z to which transformations must be
* applied if WANTZ is .TRUE..
* 1 <= ILOZ <= ILO; IHI <= IHIZ <= N.
*
* Z (input/output) COMPLEX*16 array, dimension (LDZ,N)
* If WANTZ is .TRUE., on entry Z must contain the current
* matrix Z of transformations accumulated by CHSEQR, and on
* exit Z has been updated; transformations are applied only to
* the submatrix Z(ILOZ:IHIZ,ILO:IHI).
* If WANTZ is .FALSE., Z is not referenced.
*
* LDZ (input) INTEGER
* The leading dimension of the array Z. LDZ >= max(1,N).
*
* INFO (output) INTEGER
* = 0: successful exit
* > 0: if INFO = i, ZLAHQR failed to compute all the
* eigenvalues ILO to IHI in a total of 30*(IHI-ILO+1)
* iterations; elements i+1:ihi of W contain those
* eigenvalues which have been successfully computed.
*
* =====================================================================
*
* .. Parameters ..
COMPLEX*16 ZERO, ONE
PARAMETER ( ZERO = ( 0.0D+0, 0.0D+0 ),
$ ONE = ( 1.0D+0, 0.0D+0 ) )
DOUBLE PRECISION RZERO, HALF
PARAMETER ( RZERO = 0.0D+0, HALF = 0.5D+0 )
* ..
* .. Local Scalars ..
INTEGER I, I1, I2, ITN, ITS, J, K, L, M, NH, NZ
DOUBLE PRECISION H10, H21, RTEMP, S, SMLNUM, T2, TST1, ULP
COMPLEX*16 CDUM, H11, H11S, H22, SUM, T, T1, TEMP, U, V2,
$ X, Y
* ..
* .. Local Arrays ..
DOUBLE PRECISION RWORK( 1 )
COMPLEX*16 V( 2 )
* ..
* .. External Functions ..
DOUBLE PRECISION ZLANHS, DLAMCH
COMPLEX*16 ZLADIV
EXTERNAL ZLANHS, DLAMCH, ZLADIV
* ..
* .. External Subroutines ..
EXTERNAL ZCOPY, ZLARFG, ZSCAL
* ..
* .. Intrinsic Functions ..
INTRINSIC ABS, DIMAG, DCONJG, MAX, MIN, DBLE, SQRT
* ..
* .. Statement Functions ..
DOUBLE PRECISION CABS1
* ..
* .. Statement Function definitions ..
CABS1( CDUM ) = ABS( DBLE( CDUM ) ) + ABS( DIMAG( CDUM ) )
* ..
* .. Executable Statements ..
*
INFO = 0
*
* Quick return if possible
*
IF( N.EQ.0 )
$ RETURN
IF( ILO.EQ.IHI ) THEN
W( ILO ) = H( ILO, ILO )
RETURN
END IF
*
NH = IHI - ILO + 1
NZ = IHIZ - ILOZ + 1
*
* Set machine-dependent constants for the stopping criterion.
* If norm(H) <= sqrt(OVFL), overflow should not occur.
*
ULP = DLAMCH( 'Precision' )
SMLNUM = DLAMCH( 'Safe minimum' ) / ULP
*
* I1 and I2 are the indices of the first row and last column of H
* to which transformations must be applied. If eigenvalues only are
* being computed, I1 and I2 are set inside the main loop.
*
IF( WANTT ) THEN
I1 = 1
I2 = N
END IF
*
* ITN is the total number of QR iterations allowed.
*
ITN = 30*NH
*
* The main loop begins here. I is the loop index and decreases from
* IHI to ILO in steps of 1. Each iteration of the loop works
* with the active submatrix in rows and columns L to I.
* Eigenvalues I+1 to IHI have already converged. Either L = ILO, or
* H(L,L-1) is negligible so that the matrix splits.
*
I = IHI
10 CONTINUE
IF( I.LT.ILO )
$ GO TO 130
*
* Perform QR iterations on rows and columns ILO to I until a
* submatrix of order 1 splits off at the bottom because a
* subdiagonal element has become negligible.
*
L = ILO
DO 110 ITS = 0, ITN
*
* Look for a single small subdiagonal element.
*
DO 20 K = I, L + 1, -1
TST1 = CABS1( H( K-1, K-1 ) ) + CABS1( H( K, K ) )
IF( TST1.EQ.RZERO )
$ TST1 = ZLANHS( '1', I-L+1, H( L, L ), LDH, RWORK )
IF( ABS( DBLE( H( K, K-1 ) ) ).LE.MAX( ULP*TST1, SMLNUM ) )
$ GO TO 30
20 CONTINUE
30 CONTINUE
L = K
IF( L.GT.ILO ) THEN
*
* H(L,L-1) is negligible
*
H( L, L-1 ) = ZERO
END IF
*
* Exit from loop if a submatrix of order 1 has split off.
*
IF( L.GE.I )
$ GO TO 120
*
* Now the active submatrix is in rows and columns L to I. If
* eigenvalues only are being computed, only the active submatrix
* need be transformed.
*
IF( .NOT.WANTT ) THEN
I1 = L
I2 = I
END IF
*
IF( ITS.EQ.10 .OR. ITS.EQ.20 ) THEN
*
* Exceptional shift.
*
T = ABS( DBLE( H( I, I-1 ) ) ) +
$ ABS( DBLE( H( I-1, I-2 ) ) )
ELSE
*
* Wilkinson's shift.
*
T = H( I, I )
U = H( I-1, I )*DBLE( H( I, I-1 ) )
IF( U.NE.ZERO ) THEN
X = HALF*( H( I-1, I-1 )-T )
Y = SQRT( X*X+U )
IF( DBLE( X )*DBLE( Y )+DIMAG( X )*DIMAG( Y ).LT.RZERO )
$ Y = -Y
T = T - ZLADIV( U, ( X+Y ) )
END IF
END IF
*
* Look for two consecutive small subdiagonal elements.
*
DO 40 M = I - 1, L + 1, -1
*
* Determine the effect of starting the single-shift QR
* iteration at row M, and see if this would make H(M,M-1)
* negligible.
*
H11 = H( M, M )
H22 = H( M+1, M+1 )
H11S = H11 - T
H21 = H( M+1, M )
S = CABS1( H11S ) + ABS( H21 )
H11S = H11S / S
H21 = H21 / S
V( 1 ) = H11S
V( 2 ) = H21
H10 = H( M, M-1 )
TST1 = CABS1( H11S )*( CABS1( H11 )+CABS1( H22 ) )
IF( ABS( H10*H21 ).LE.ULP*TST1 )
$ GO TO 50
40 CONTINUE
H11 = H( L, L )
H22 = H( L+1, L+1 )
H11S = H11 - T
H21 = H( L+1, L )
S = CABS1( H11S ) + ABS( H21 )
H11S = H11S / S
H21 = H21 / S
V( 1 ) = H11S
V( 2 ) = H21
50 CONTINUE
*
* Single-shift QR step
*
DO 100 K = M, I - 1
*
* The first iteration of this loop determines a reflection G
* from the vector V and applies it from left and right to H,
* thus creating a nonzero bulge below the subdiagonal.
*
* Each subsequent iteration determines a reflection G to
* restore the Hessenberg form in the (K-1)th column, and thus
* chases the bulge one step toward the bottom of the active
* submatrix.
*
* V(2) is always real before the call to ZLARFG, and hence
* after the call T2 ( = T1*V(2) ) is also real.
*
IF( K.GT.M )
$ CALL ZCOPY( 2, H( K, K-1 ), 1, V, 1 )
CALL ZLARFG( 2, V( 1 ), V( 2 ), 1, T1 )
IF( K.GT.M ) THEN
H( K, K-1 ) = V( 1 )
H( K+1, K-1 ) = ZERO
END IF
V2 = V( 2 )
T2 = DBLE( T1*V2 )
*
* Apply G from the left to transform the rows of the matrix
* in columns K to I2.
*
DO 60 J = K, I2
SUM = DCONJG( T1 )*H( K, J ) + T2*H( K+1, J )
H( K, J ) = H( K, J ) - SUM
H( K+1, J ) = H( K+1, J ) - SUM*V2
60 CONTINUE
*
* Apply G from the right to transform the columns of the
* matrix in rows I1 to min(K+2,I).
*
DO 70 J = I1, MIN( K+2, I )
SUM = T1*H( J, K ) + T2*H( J, K+1 )
H( J, K ) = H( J, K ) - SUM
H( J, K+1 ) = H( J, K+1 ) - SUM*DCONJG( V2 )
70 CONTINUE
*
IF( WANTZ ) THEN
*
* Accumulate transformations in the matrix Z
*
DO 80 J = ILOZ, IHIZ
SUM = T1*Z( J, K ) + T2*Z( J, K+1 )
Z( J, K ) = Z( J, K ) - SUM
Z( J, K+1 ) = Z( J, K+1 ) - SUM*DCONJG( V2 )
80 CONTINUE
END IF
*
IF( K.EQ.M .AND. M.GT.L ) THEN
*
* If the QR step was started at row M > L because two
* consecutive small subdiagonals were found, then extra
* scaling must be performed to ensure that H(M,M-1) remains
* real.
*
TEMP = ONE - T1
TEMP = TEMP / ABS( TEMP )
H( M+1, M ) = H( M+1, M )*DCONJG( TEMP )
IF( M+2.LE.I )
$ H( M+2, M+1 ) = H( M+2, M+1 )*TEMP
DO 90 J = M, I
IF( J.NE.M+1 ) THEN
IF( I2.GT.J )
$ CALL ZSCAL( I2-J, TEMP, H( J, J+1 ), LDH )
CALL ZSCAL( J-I1, DCONJG( TEMP ), H( I1, J ), 1 )
IF( WANTZ ) THEN
CALL ZSCAL( NZ, DCONJG( TEMP ),
$ Z( ILOZ, J ), 1 )
END IF
END IF
90 CONTINUE
END IF
100 CONTINUE
*
* Ensure that H(I,I-1) is real.
*
TEMP = H( I, I-1 )
IF( DIMAG( TEMP ).NE.RZERO ) THEN
RTEMP = ABS( TEMP )
H( I, I-1 ) = RTEMP
TEMP = TEMP / RTEMP
IF( I2.GT.I )
$ CALL ZSCAL( I2-I, DCONJG( TEMP ), H( I, I+1 ), LDH )
CALL ZSCAL( I-I1, TEMP, H( I1, I ), 1 )
IF( WANTZ ) THEN
CALL ZSCAL( NZ, TEMP, Z( ILOZ, I ), 1 )
END IF
END IF
*
110 CONTINUE
*
* Failure to converge in remaining number of iterations
*
INFO = I
RETURN
*
120 CONTINUE
*
* H(I,I-1) is negligible: one eigenvalue has converged.
*
W( I ) = H( I, I )
*
* Decrement number of remaining iterations, and return to start of
* the main loop with new value of I.
*
ITN = ITN - ITS
I = L - 1
GO TO 10
*
130 CONTINUE
RETURN
*
* End of ZLAHQR
*
END

111
arpack/ARPACK/README Normal file
View File

@@ -0,0 +1,111 @@
1. You have successfully unbundled ARPACK and are now in the ARPACK
directory that was created for you.
2. Recent bug fixes are included in patch.tar.gz and ppatch.tar.gz
(only needed if you are using PARPACK also.) If you have not
retrieved these files, please do so and place them in the
directory right above the current directory. (They should
be in the same directory where arpack96.tar reside).
Use uncompress or gunzip to unzip the tar files, and use 'tar -xvf '
to unbundle these patches. The source codes in these patches will
overwrite those contained in arpack96.tar and parpack96.tar.
3. Upon executing the 'ls | more ' command you should see
BLAS
DOCUMENTS
EXAMPLES
LAPACK
README
SRC
UTIL
Makefile
ARmake.inc
ARMAKES
The following entries are directories:
ARMAKES, BLAS, DOCUMENTS, EXAMPLES, LAPACK, SRC, UTIL
The directory SRC contains the top level routines including
the highest level reverse communication interface routines
ssaupd, dsaupd - symmetric single and double precision
snaupd, dnaupd - non-symmetric single and double precision
cnaupd, cnaupd - complex non-symmetric single and double precision
The headers of these routines contain full documentation of calling
sequence and usage. Additional information is in the DOCUMENTS directory.
4. Example driver programs that illustrate all the computational modes,
data types and precisions may be found in the EXAMPLES directory.
Upon executing the 'ls EXAMPLES | more ' command you should see
BAND
COMPLEX
NONSYM
README
SIMPLE
SVD
SYM
Example programs for banded, complex, nonsymmetric, symmetric,
and singular value decomposition may be found in the directories
BAND, COMPLEX, NONSYM, SYM, SVD respectively. Look at the README
file for further information. To get started, get into the SIMPLE
directory to see example programs that illustrate the use of ARPACK in
the simplest modes of operation for the most commonly posed
standard eigenvalue problems.
The following instructions explain how to make the ARPACK library.
5. Before you can compile anything, you must first edit and correct the file
ARmake.inc. Sample ARmake.inc's can be found in the ARMAKES directory.
Edit "ARmake.inc" and change the definition "home" to the root of the
source tree (Top level of ARPACK directory)
The makefile is set up to build a self-contained library which includes
the needed BLAS 1/2/3 and LAPACK routines. If you already have the
BLAS and LAPACK libraries installed on your system you might want to
change the definition of DIRS as indicated in the ARmake.inc file.
*** NOTE *** Unless the LAPACK library on your system is version 2.0,
we strongly recommend that you install the LAPACK routines provided with
ARPACK. Note that the current LAPACK release is version 3.0; if you are
not sure which version of LAPACK is installed, pleaase compile and link
to the subset of LAPACK included with ARPACK.
6. You will also need to change the file "second.f" in the UTIL directory
to whatever is appropriate for timing on your system. The "second" routine
provided works on most workstations. If you are running on a Cray,
you can just edit the makefile in UTIL and take out the reference to
"second.o" to use the system second routine.
7. Do "make lib" in the current directory to build the standard library
"libarpack_$(PLAT).a"
8. Within DOCUMENTS directory there are three files
ex-sym.doc
ex-nonsym.doc and
ex-complex.doc
for templates on how to invoke the computational modes of ARPACK.
Also look in the README file for explanations concerning the
other documents.
Danny Sorensen at sorensen@caam.rice.edu
Richard Lehoucq at rblehou@sandia.gov
Chao Yang at cyang@lbl.gov
Kristi Maschhoff at kristyn@tera.com
If you have questions regarding using ARPACK, please send email
to arpack@caam.rice.edu.
Good luck and enjoy.

View File

@@ -0,0 +1,83 @@
############################################################################
#
# Program: ARPACK
#
# Module: Makefile
#
# Purpose: Sources Makefile
#
# Creation date: February 22, 1996
#
# Modified: September 9, 1996
#
# Send bug reports, comments or suggestions to arpack.caam.rice.edu
#
############################################################################
#\SCCS Information: @(#)
# FILE: Makefile SID: 2.1 DATE OF SID: 9/9/96 RELEASE: 2
include ../ARmake.inc
############################################################################
# To create or add to the library, enter make followed by one or
# more of the precisions desired. Some examples:
# make single
# make single complex
# make single double complex complex16
# Alternatively, the command
# make
# without any arguments creates a library of all four precisions.
# The name of the library is defined by $(ARPACKLIB) in
# ../ARmake.inc and is created at the next higher directory level.
SOBJ = sgetv0.o slaqrb.o sstqrb.o ssortc.o ssortr.o sstatn.o sstats.o \
snaitr.o snapps.o snaup2.o snaupd.o snconv.o sneigh.o sngets.o \
ssaitr.o ssapps.o ssaup2.o ssaupd.o ssconv.o sseigt.o ssgets.o \
sneupd.o sseupd.o ssesrt.o
DOBJ = dgetv0.o dlaqrb.o dstqrb.o dsortc.o dsortr.o dstatn.o dstats.o \
dnaitr.o dnapps.o dnaup2.o dnaupd.o dnconv.o dneigh.o dngets.o \
dsaitr.o dsapps.o dsaup2.o dsaupd.o dsconv.o dseigt.o dsgets.o \
dneupd.o dseupd.o dsesrt.o
COBJ = cnaitr.o cnapps.o cnaup2.o cnaupd.o cneigh.o cneupd.o cngets.o \
cgetv0.o csortc.o cstatn.o
ZOBJ = znaitr.o znapps.o znaup2.o znaupd.o zneigh.o zneupd.o zngets.o \
zgetv0.o zsortc.o zstatn.o
.f.o:
$(FC) $(FFLAGS) -c $<
all: single double complex complex16
single: $(SOBJ)
$(AR) $(ARFLAGS) $(ARPACKLIB) $(SOBJ)
$(RANLIB) $(ARPACKLIB)
double: $(DOBJ)
$(AR) $(ARFLAGS) $(ARPACKLIB) $(DOBJ)
$(RANLIB) $(ARPACKLIB)
complex: $(COBJ)
$(AR) $(ARFLAGS) $(ARPACKLIB) $(COBJ)
$(RANLIB) $(ARPACKLIB)
complex16: $(ZOBJ)
$(AR) $(ARFLAGS) $(ARPACKLIB) $(ZOBJ)
$(RANLIB) $(ARPACKLIB)
#
sdrv:
ddrv:
cdrv:
zdrv:
#
# clean - remove all object files
#
clean:
rm -f *.o a.out core

414
arpack/ARPACK/SRC/cgetv0.f Normal file
View File

@@ -0,0 +1,414 @@
c\BeginDoc
c
c\Name: cgetv0
c
c\Description:
c Generate a random initial residual vector for the Arnoldi process.
c Force the residual vector to be in the range of the operator OP.
c
c\Usage:
c call cgetv0
c ( IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM,
c IPNTR, WORKD, IERR )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag. IDO must be zero on the first
c call to cgetv0.
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c This is for the initialization phase to force the
c starting vector into the range of OP.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c IDO = 99: done
c -------------------------------------------------------------
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B in the (generalized)
c eigenvalue problem A*x = lambda*B*x.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x
c
c ITRY Integer. (INPUT)
c ITRY counts the number of times that cgetv0 is called.
c It should be set to 1 on the initial call to cgetv0.
c
c INITV Logical variable. (INPUT)
c .TRUE. => the initial residual vector is given in RESID.
c .FALSE. => generate a random initial residual vector.
c
c N Integer. (INPUT)
c Dimension of the problem.
c
c J Integer. (INPUT)
c Index of the residual vector to be generated, with respect to
c the Arnoldi process. J > 1 in case of a "restart".
c
c V Complex N by J array. (INPUT)
c The first J-1 columns of V contain the current Arnoldi basis
c if this is a "restart".
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c RESID Complex array of length N. (INPUT/OUTPUT)
c Initial residual vector to be generated. If RESID is
c provided, force RESID into the range of the operator OP.
c
c RNORM Real scalar. (OUTPUT)
c B-norm of the generated residual.
c
c IPNTR Integer array of length 3. (OUTPUT)
c
c WORKD Complex work array of length 2*N. (REVERSE COMMUNICATION).
c On exit, WORK(1:N) = B*RESID to be used in SSAITR.
c
c IERR Integer. (OUTPUT)
c = 0: Normal exit.
c = -1: Cannot generate a nontrivial restarted residual vector
c in the range of the operator OP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c
c\Routines called:
c second ARPACK utility routine for timing.
c cvout ARPACK utility routine that prints vectors.
c clarnv LAPACK routine for generating a random vector.
c cgemv Level 2 BLAS routine for matrix vector multiplication.
c ccopy Level 1 BLAS that copies one vector to another.
c cdotc Level 1 BLAS that computes the scalar product of two vectors.
c scnrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: getv0.F SID: 2.3 DATE OF SID: 08/27/96 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine cgetv0
& ( ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm,
& ipntr, workd, ierr )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1
logical initv
integer ido, ierr, itry, j, ldv, n
Real
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Complex
& resid(n), v(ldv,j), workd(2*n)
c
c %------------%
c | Parameters |
c %------------%
c
Complex
& one, zero
Real
& rzero
parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0),
& rzero = 0.0E+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
logical first, inits, orth
integer idist, iseed(4), iter, msglvl, jj
Real
& rnorm0
Complex
& cnorm
save first, iseed, inits, iter, msglvl, orth, rnorm0
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external ccopy, cgemv, clarnv, cvout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& scnrm2, slapy2
Complex
& cdotc
external cdotc, scnrm2, slapy2
c
c %-----------------%
c | Data Statements |
c %-----------------%
c
data inits /.true./
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c
c %-----------------------------------%
c | Initialize the seed of the LAPACK |
c | random number generator |
c %-----------------------------------%
c
if (inits) then
iseed(1) = 1
iseed(2) = 3
iseed(3) = 5
iseed(4) = 7
inits = .false.
end if
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mgetv0
c
ierr = 0
iter = 0
first = .FALSE.
orth = .FALSE.
c
c %-----------------------------------------------------%
c | Possibly generate a random starting vector in RESID |
c | Use a LAPACK random number generator used by the |
c | matrix generation routines. |
c | idist = 1: uniform (0,1) distribution; |
c | idist = 2: uniform (-1,1) distribution; |
c | idist = 3: normal (0,1) distribution; |
c %-----------------------------------------------------%
c
if (.not.initv) then
idist = 2
call clarnv (idist, iseed, n, resid)
end if
c
c %----------------------------------------------------------%
c | Force the starting vector into the range of OP to handle |
c | the generalized problem when B is possibly (singular). |
c %----------------------------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nopx = nopx + 1
ipntr(1) = 1
ipntr(2) = n + 1
call ccopy (n, resid, 1, workd, 1)
ido = -1
go to 9000
end if
end if
c
c %----------------------------------------%
c | Back from computing B*(initial-vector) |
c %----------------------------------------%
c
if (first) go to 20
c
c %-----------------------------------------------%
c | Back from computing B*(orthogonalized-vector) |
c %-----------------------------------------------%
c
if (orth) go to 40
c
call second (t3)
tmvopx = tmvopx + (t3 - t2)
c
c %------------------------------------------------------%
c | Starting vector is now in the range of OP; r = OP*r; |
c | Compute B-norm of starting vector. |
c %------------------------------------------------------%
c
call second (t2)
first = .TRUE.
if (bmat .eq. 'G') then
nbx = nbx + 1
call ccopy (n, workd(n+1), 1, resid, 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
go to 9000
else if (bmat .eq. 'I') then
call ccopy (n, resid, 1, workd, 1)
end if
c
20 continue
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
first = .FALSE.
if (bmat .eq. 'G') then
cnorm = cdotc (n, resid, 1, workd, 1)
rnorm0 = sqrt(slapy2(real(cnorm),aimag(cnorm)))
else if (bmat .eq. 'I') then
rnorm0 = scnrm2(n, resid, 1)
end if
rnorm = rnorm0
c
c %---------------------------------------------%
c | Exit if this is the very first Arnoldi step |
c %---------------------------------------------%
c
if (j .eq. 1) go to 50
c
c %----------------------------------------------------------------
c | Otherwise need to B-orthogonalize the starting vector against |
c | the current Arnoldi basis using Gram-Schmidt with iter. ref. |
c | This is the case where an invariant subspace is encountered |
c | in the middle of the Arnoldi factorization. |
c | |
c | s = V^{T}*B*r; r = r - V*s; |
c | |
c | Stopping criteria used for iter. ref. is discussed in |
c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. |
c %---------------------------------------------------------------%
c
orth = .TRUE.
30 continue
c
call cgemv ('C', n, j-1, one, v, ldv, workd, 1,
& zero, workd(n+1), 1)
call cgemv ('N', n, j-1, -one, v, ldv, workd(n+1), 1,
& one, resid, 1)
c
c %----------------------------------------------------------%
c | Compute the B-norm of the orthogonalized starting vector |
c %----------------------------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call ccopy (n, resid, 1, workd(n+1), 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
go to 9000
else if (bmat .eq. 'I') then
call ccopy (n, resid, 1, workd, 1)
end if
c
40 continue
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
if (bmat .eq. 'G') then
cnorm = cdotc (n, resid, 1, workd, 1)
rnorm = sqrt(slapy2(real(cnorm),aimag(cnorm)))
else if (bmat .eq. 'I') then
rnorm = scnrm2(n, resid, 1)
end if
c
c %--------------------------------------%
c | Check for further orthogonalization. |
c %--------------------------------------%
c
if (msglvl .gt. 2) then
call svout (logfil, 1, rnorm0, ndigit,
& '_getv0: re-orthonalization ; rnorm0 is')
call svout (logfil, 1, rnorm, ndigit,
& '_getv0: re-orthonalization ; rnorm is')
end if
c
if (rnorm .gt. 0.717*rnorm0) go to 50
c
iter = iter + 1
if (iter .le. 1) then
c
c %-----------------------------------%
c | Perform iterative refinement step |
c %-----------------------------------%
c
rnorm0 = rnorm
go to 30
else
c
c %------------------------------------%
c | Iterative refinement step "failed" |
c %------------------------------------%
c
do 45 jj = 1, n
resid(jj) = zero
45 continue
rnorm = rzero
ierr = -1
end if
c
50 continue
c
if (msglvl .gt. 0) then
call svout (logfil, 1, rnorm, ndigit,
& '_getv0: B-norm of initial / restarted starting vector')
end if
if (msglvl .gt. 2) then
call cvout (logfil, n, resid, ndigit,
& '_getv0: initial / restarted starting vector')
end if
ido = 99
c
call second (t1)
tgetv0 = tgetv0 + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of cgetv0 |
c %---------------%
c
end

850
arpack/ARPACK/SRC/cnaitr.f Normal file
View File

@@ -0,0 +1,850 @@
c\BeginDoc
c
c\Name: cnaitr
c
c\Description:
c Reverse communication interface for applying NP additional steps to
c a K step nonsymmetric Arnoldi factorization.
c
c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T
c
c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0.
c
c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T
c
c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0.
c
c where OP and B are as in cnaupd. The B-norm of r_{k+p} is also
c computed and returned.
c
c\Usage:
c call cnaitr
c ( IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH,
c IPNTR, WORKD, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag.
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c This is for the restart phase to force the new
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y,
c IPNTR(3) is the pointer into WORK for B * X.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c IDO = 99: done
c -------------------------------------------------------------
c When the routine is used in the "shift-and-invert" mode, the
c vector B * Q is already available and do not need to be
c recomputed in forming OP * Q.
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B that defines the
c semi-inner product for the operator OP. See cnaupd.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c K Integer. (INPUT)
c Current size of V and H.
c
c NP Integer. (INPUT)
c Number of additional Arnoldi steps to take.
c
c NB Integer. (INPUT)
c Blocksize to be used in the recurrence.
c Only work for NB = 1 right now. The goal is to have a
c program that implement both the block and non-block method.
c
c RESID Complex array of length N. (INPUT/OUTPUT)
c On INPUT: RESID contains the residual vector r_{k}.
c On OUTPUT: RESID contains the residual vector r_{k+p}.
c
c RNORM Real scalar. (INPUT/OUTPUT)
c B-norm of the starting residual on input.
c B-norm of the updated residual r_{k+p} on output.
c
c V Complex N by K+NP array. (INPUT/OUTPUT)
c On INPUT: V contains the Arnoldi vectors in the first K
c columns.
c On OUTPUT: V contains the new NP Arnoldi vectors in the next
c NP columns. The first K columns are unchanged.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Complex (K+NP) by (K+NP) array. (INPUT/OUTPUT)
c H is used to store the generated upper Hessenberg matrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORK for
c vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in the
c shift-and-invert mode. X is the current operand.
c -------------------------------------------------------------
c
c WORKD Complex work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The calling program should not
c use WORKD as temporary workspace during the iteration !!!!!!
c On input, WORKD(1:N) = B*RESID and is used to save some
c computation at the first step.
c
c INFO Integer. (OUTPUT)
c = 0: Normal exit.
c > 0: Size of the spanning invariant subspace of OP found.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c cgetv0 ARPACK routine to generate the initial vector.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c cmout ARPACK utility routine that prints matrices
c cvout ARPACK utility routine that prints vectors.
c clanhs LAPACK routine that computes various norms of a matrix.
c clascl LAPACK routine for careful scaling of a matrix.
c slabad LAPACK routine for defining the underflow and overflow
c limits.
c slamch LAPACK routine that determines machine constants.
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c cgemv Level 2 BLAS routine for matrix vector multiplication.
c caxpy Level 1 BLAS that computes a vector triad.
c ccopy Level 1 BLAS that copies one vector to another .
c cdotc Level 1 BLAS that computes the scalar product of two vectors.
c cscal Level 1 BLAS that scales a vector.
c csscal Level 1 BLAS that scales a complex vector by a real number.
c scnrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: naitr.F SID: 2.3 DATE OF SID: 8/27/96 RELEASE: 2
c
c\Remarks
c The algorithm implemented is:
c
c restart = .false.
c Given V_{k} = [v_{1}, ..., v_{k}], r_{k};
c r_{k} contains the initial residual vector even for k = 0;
c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already
c computed by the calling program.
c
c betaj = rnorm ; p_{k+1} = B*r_{k} ;
c For j = k+1, ..., k+np Do
c 1) if ( betaj < tol ) stop or restart depending on j.
c ( At present tol is zero )
c if ( restart ) generate a new starting vector.
c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}];
c p_{j} = p_{j}/betaj
c 3) r_{j} = OP*v_{j} where OP is defined as in cnaupd
c For shift-invert mode p_{j} = B*v_{j} is already available.
c wnorm = || OP*v_{j} ||
c 4) Compute the j-th step residual vector.
c w_{j} = V_{j}^T * B * OP * v_{j}
c r_{j} = OP*v_{j} - V_{j} * w_{j}
c H(:,j) = w_{j};
c H(j,j-1) = rnorm
c rnorm = || r_(j) ||
c If (rnorm > 0.717*wnorm) accept step and go back to 1)
c 5) Re-orthogonalization step:
c s = V_{j}'*B*r_{j}
c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} ||
c alphaj = alphaj + s_{j};
c 6) Iterative refinement step:
c If (rnorm1 > 0.717*rnorm) then
c rnorm = rnorm1
c accept step and go back to 1)
c Else
c rnorm = rnorm1
c If this is the first time in step 6), go to 5)
c Else r_{j} lies in the span of V_{j} numerically.
c Set r_{j} = 0 and rnorm = 0; go to 1)
c EndIf
c End Do
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine cnaitr
& (ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh,
& ipntr, workd, info)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1
integer ido, info, k, ldh, ldv, n, nb, np
Real
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Complex
& h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n)
c
c %------------%
c | Parameters |
c %------------%
c
Complex
& one, zero
Real
& rone, rzero
parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0),
& rone = 1.0E+0, rzero = 0.0E+0)
c
c %--------------%
c | Local Arrays |
c %--------------%
c
Real
& rtemp(2)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
logical first, orth1, orth2, rstart, step3, step4
integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl,
& jj
Real
& ovfl, smlnum, tst1, ulp, unfl, betaj,
& temp1, rnorm1, wnorm
Complex
& cnorm
c
save first, orth1, orth2, rstart, step3, step4,
& ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl,
& betaj, rnorm1, smlnum, ulp, unfl, wnorm
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external caxpy, ccopy, cscal, csscal, cgemv, cgetv0,
& slabad, cvout, cmout, ivout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Complex
& cdotc
Real
& slamch, scnrm2, clanhs, slapy2
external cdotc, scnrm2, clanhs, slamch, slapy2
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic aimag, real, max, sqrt
c
c %-----------------%
c | Data statements |
c %-----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
c
c %-----------------------------------------%
c | Set machine-dependent constants for the |
c | the splitting and deflation criterion. |
c | If norm(H) <= sqrt(OVFL), |
c | overflow should not occur. |
c | REFERENCE: LAPACK subroutine clahqr |
c %-----------------------------------------%
c
unfl = slamch( 'safe minimum' )
ovfl = real(one / unfl)
call slabad( unfl, ovfl )
ulp = slamch( 'precision' )
smlnum = unfl*( n / ulp )
first = .false.
end if
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mcaitr
c
c %------------------------------%
c | Initial call to this routine |
c %------------------------------%
c
info = 0
step3 = .false.
step4 = .false.
rstart = .false.
orth1 = .false.
orth2 = .false.
j = k + 1
ipj = 1
irj = ipj + n
ivj = irj + n
end if
c
c %-------------------------------------------------%
c | When in reverse communication mode one of: |
c | STEP3, STEP4, ORTH1, ORTH2, RSTART |
c | will be .true. when .... |
c | STEP3: return from computing OP*v_{j}. |
c | STEP4: return from computing B-norm of OP*v_{j} |
c | ORTH1: return from computing B-norm of r_{j+1} |
c | ORTH2: return from computing B-norm of |
c | correction to the residual vector. |
c | RSTART: return from OP computations needed by |
c | cgetv0. |
c %-------------------------------------------------%
c
if (step3) go to 50
if (step4) go to 60
if (orth1) go to 70
if (orth2) go to 90
if (rstart) go to 30
c
c %-----------------------------%
c | Else this is the first step |
c %-----------------------------%
c
c %--------------------------------------------------------------%
c | |
c | A R N O L D I I T E R A T I O N L O O P |
c | |
c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) |
c %--------------------------------------------------------------%
1000 continue
c
if (msglvl .gt. 1) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: generating Arnoldi vector number')
call svout (logfil, 1, rnorm, ndigit,
& '_naitr: B-norm of the current residual is')
end if
c
c %---------------------------------------------------%
c | STEP 1: Check if the B norm of j-th residual |
c | vector is zero. Equivalent to determine whether |
c | an exact j-step Arnoldi factorization is present. |
c %---------------------------------------------------%
c
betaj = rnorm
if (rnorm .gt. rzero) go to 40
c
c %---------------------------------------------------%
c | Invariant subspace found, generate a new starting |
c | vector which is orthogonal to the current Arnoldi |
c | basis and continue the iteration. |
c %---------------------------------------------------%
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: ****** RESTART AT STEP ******')
end if
c
c %---------------------------------------------%
c | ITRY is the loop variable that controls the |
c | maximum amount of times that a restart is |
c | attempted. NRSTRT is used by stat.h |
c %---------------------------------------------%
c
betaj = rzero
nrstrt = nrstrt + 1
itry = 1
20 continue
rstart = .true.
ido = 0
30 continue
c
c %--------------------------------------%
c | If in reverse communication mode and |
c | RSTART = .true. flow returns here. |
c %--------------------------------------%
c
call cgetv0 (ido, bmat, itry, .false., n, j, v, ldv,
& resid, rnorm, ipntr, workd, ierr)
if (ido .ne. 99) go to 9000
if (ierr .lt. 0) then
itry = itry + 1
if (itry .le. 3) go to 20
c
c %------------------------------------------------%
c | Give up after several restart attempts. |
c | Set INFO to the size of the invariant subspace |
c | which spans OP and exit. |
c %------------------------------------------------%
c
info = j - 1
call second (t1)
tcaitr = tcaitr + (t1 - t0)
ido = 99
go to 9000
end if
c
40 continue
c
c %---------------------------------------------------------%
c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm |
c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow |
c | when reciprocating a small RNORM, test against lower |
c | machine bound. |
c %---------------------------------------------------------%
c
call ccopy (n, resid, 1, v(1,j), 1)
if ( rnorm .ge. unfl) then
temp1 = rone / rnorm
call csscal (n, temp1, v(1,j), 1)
call csscal (n, temp1, workd(ipj), 1)
else
c
c %-----------------------------------------%
c | To scale both v_{j} and p_{j} carefully |
c | use LAPACK routine clascl |
c %-----------------------------------------%
c
call clascl ('General', i, i, rnorm, rone,
& n, 1, v(1,j), n, infol)
call clascl ('General', i, i, rnorm, rone,
& n, 1, workd(ipj), n, infol)
end if
c
c %------------------------------------------------------%
c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} |
c | Note that this is not quite yet r_{j}. See STEP 4 |
c %------------------------------------------------------%
c
step3 = .true.
nopx = nopx + 1
call second (t2)
call ccopy (n, v(1,j), 1, workd(ivj), 1)
ipntr(1) = ivj
ipntr(2) = irj
ipntr(3) = ipj
ido = 1
c
c %-----------------------------------%
c | Exit in order to compute OP*v_{j} |
c %-----------------------------------%
c
go to 9000
50 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} |
c | if step3 = .true. |
c %----------------------------------%
c
call second (t3)
tmvopx = tmvopx + (t3 - t2)
step3 = .false.
c
c %------------------------------------------%
c | Put another copy of OP*v_{j} into RESID. |
c %------------------------------------------%
c
call ccopy (n, workd(irj), 1, resid, 1)
c
c %---------------------------------------%
c | STEP 4: Finish extending the Arnoldi |
c | factorization to length j. |
c %---------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
step4 = .true.
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-------------------------------------%
c | Exit in order to compute B*OP*v_{j} |
c %-------------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call ccopy (n, resid, 1, workd(ipj), 1)
end if
60 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} |
c | if step4 = .true. |
c %----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
step4 = .false.
c
c %-------------------------------------%
c | The following is needed for STEP 5. |
c | Compute the B-norm of OP*v_{j}. |
c %-------------------------------------%
c
if (bmat .eq. 'G') then
cnorm = cdotc (n, resid, 1, workd(ipj), 1)
wnorm = sqrt( slapy2(real(cnorm),aimag(cnorm)) )
else if (bmat .eq. 'I') then
wnorm = scnrm2(n, resid, 1)
end if
c
c %-----------------------------------------%
c | Compute the j-th residual corresponding |
c | to the j step factorization. |
c | Use Classical Gram Schmidt and compute: |
c | w_{j} <- V_{j}^T * B * OP * v_{j} |
c | r_{j} <- OP*v_{j} - V_{j} * w_{j} |
c %-----------------------------------------%
c
c
c %------------------------------------------%
c | Compute the j Fourier coefficients w_{j} |
c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. |
c %------------------------------------------%
c
call cgemv ('C', n, j, one, v, ldv, workd(ipj), 1,
& zero, h(1,j), 1)
c
c %--------------------------------------%
c | Orthogonalize r_{j} against V_{j}. |
c | RESID contains OP*v_{j}. See STEP 3. |
c %--------------------------------------%
c
call cgemv ('N', n, j, -one, v, ldv, h(1,j), 1,
& one, resid, 1)
c
if (j .gt. 1) h(j,j-1) = cmplx(betaj, rzero)
c
call second (t4)
c
orth1 = .true.
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call ccopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*r_{j} |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call ccopy (n, resid, 1, workd(ipj), 1)
end if
70 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH1 = .true. |
c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
orth1 = .false.
c
c %------------------------------%
c | Compute the B-norm of r_{j}. |
c %------------------------------%
c
if (bmat .eq. 'G') then
cnorm = cdotc (n, resid, 1, workd(ipj), 1)
rnorm = sqrt( slapy2(real(cnorm),aimag(cnorm)) )
else if (bmat .eq. 'I') then
rnorm = scnrm2(n, resid, 1)
end if
c
c %-----------------------------------------------------------%
c | STEP 5: Re-orthogonalization / Iterative refinement phase |
c | Maximum NITER_ITREF tries. |
c | |
c | s = V_{j}^T * B * r_{j} |
c | r_{j} = r_{j} - V_{j}*s |
c | alphaj = alphaj + s_{j} |
c | |
c | The stopping criteria used for iterative refinement is |
c | discussed in Parlett's book SEP, page 107 and in Gragg & |
c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. |
c | Determine if we need to correct the residual. The goal is |
c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || |
c | The following test determines whether the sine of the |
c | angle between OP*x and the computed residual is less |
c | than or equal to 0.717. |
c %-----------------------------------------------------------%
c
if ( rnorm .gt. 0.717*wnorm ) go to 100
c
iter = 0
nrorth = nrorth + 1
c
c %---------------------------------------------------%
c | Enter the Iterative refinement phase. If further |
c | refinement is necessary, loop back here. The loop |
c | variable is ITER. Perform a step of Classical |
c | Gram-Schmidt using all the Arnoldi vectors V_{j} |
c %---------------------------------------------------%
c
80 continue
c
if (msglvl .gt. 2) then
rtemp(1) = wnorm
rtemp(2) = rnorm
call svout (logfil, 2, rtemp, ndigit,
& '_naitr: re-orthogonalization; wnorm and rnorm are')
call cvout (logfil, j, h(1,j), ndigit,
& '_naitr: j-th column of H')
end if
c
c %----------------------------------------------------%
c | Compute V_{j}^T * B * r_{j}. |
c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). |
c %----------------------------------------------------%
c
call cgemv ('C', n, j, one, v, ldv, workd(ipj), 1,
& zero, workd(irj), 1)
c
c %---------------------------------------------%
c | Compute the correction to the residual: |
c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). |
c | The correction to H is v(:,1:J)*H(1:J,1:J) |
c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. |
c %---------------------------------------------%
c
call cgemv ('N', n, j, -one, v, ldv, workd(irj), 1,
& one, resid, 1)
call caxpy (j, one, workd(irj), 1, h(1,j), 1)
c
orth2 = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call ccopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-----------------------------------%
c | Exit in order to compute B*r_{j}. |
c | r_{j} is the corrected residual. |
c %-----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call ccopy (n, resid, 1, workd(ipj), 1)
end if
90 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH2 = .true. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
c %-----------------------------------------------------%
c | Compute the B-norm of the corrected residual r_{j}. |
c %-----------------------------------------------------%
c
if (bmat .eq. 'G') then
cnorm = cdotc (n, resid, 1, workd(ipj), 1)
rnorm1 = sqrt( slapy2(real(cnorm),aimag(cnorm)) )
else if (bmat .eq. 'I') then
rnorm1 = scnrm2(n, resid, 1)
end if
c
if (msglvl .gt. 0 .and. iter .gt. 0 ) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: Iterative refinement for Arnoldi residual')
if (msglvl .gt. 2) then
rtemp(1) = rnorm
rtemp(2) = rnorm1
call svout (logfil, 2, rtemp, ndigit,
& '_naitr: iterative refinement ; rnorm and rnorm1 are')
end if
end if
c
c %-----------------------------------------%
c | Determine if we need to perform another |
c | step of re-orthogonalization. |
c %-----------------------------------------%
c
if ( rnorm1 .gt. 0.717*rnorm ) then
c
c %---------------------------------------%
c | No need for further refinement. |
c | The cosine of the angle between the |
c | corrected residual vector and the old |
c | residual vector is greater than 0.717 |
c | In other words the corrected residual |
c | and the old residual vector share an |
c | angle of less than arcCOS(0.717) |
c %---------------------------------------%
c
rnorm = rnorm1
c
else
c
c %-------------------------------------------%
c | Another step of iterative refinement step |
c | is required. NITREF is used by stat.h |
c %-------------------------------------------%
c
nitref = nitref + 1
rnorm = rnorm1
iter = iter + 1
if (iter .le. 1) go to 80
c
c %-------------------------------------------------%
c | Otherwise RESID is numerically in the span of V |
c %-------------------------------------------------%
c
do 95 jj = 1, n
resid(jj) = zero
95 continue
rnorm = rzero
end if
c
c %----------------------------------------------%
c | Branch here directly if iterative refinement |
c | wasn't necessary or after at most NITER_REF |
c | steps of iterative refinement. |
c %----------------------------------------------%
c
100 continue
c
rstart = .false.
orth2 = .false.
c
call second (t5)
titref = titref + (t5 - t4)
c
c %------------------------------------%
c | STEP 6: Update j = j+1; Continue |
c %------------------------------------%
c
j = j + 1
if (j .gt. k+np) then
call second (t1)
tcaitr = tcaitr + (t1 - t0)
ido = 99
do 110 i = max(1,k), k+np-1
c
c %--------------------------------------------%
c | Check for splitting and deflation. |
c | Use a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine clahqr |
c %--------------------------------------------%
c
tst1 = slapy2(real(h(i,i)),aimag(h(i,i)))
& + slapy2(real(h(i+1,i+1)), aimag(h(i+1,i+1)))
if( tst1.eq.real(zero) )
& tst1 = clanhs( '1', k+np, h, ldh, workd(n+1) )
if( slapy2(real(h(i+1,i)),aimag(h(i+1,i))) .le.
& max( ulp*tst1, smlnum ) )
& h(i+1,i) = zero
110 continue
c
if (msglvl .gt. 2) then
call cmout (logfil, k+np, k+np, h, ldh, ndigit,
& '_naitr: Final upper Hessenberg matrix H of order K+NP')
end if
c
go to 9000
end if
c
c %--------------------------------------------------------%
c | Loop back to extend the factorization by another step. |
c %--------------------------------------------------------%
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
9000 continue
return
c
c %---------------%
c | End of cnaitr |
c %---------------%
c
end

507
arpack/ARPACK/SRC/cnapps.f Normal file
View File

@@ -0,0 +1,507 @@
c\BeginDoc
c
c\Name: cnapps
c
c\Description:
c Given the Arnoldi factorization
c
c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T,
c
c apply NP implicit shifts resulting in
c
c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q
c
c where Q is an orthogonal matrix which is the product of rotations
c and reflections resulting from the NP bulge change sweeps.
c The updated Arnoldi factorization becomes:
c
c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T.
c
c\Usage:
c call cnapps
c ( N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ,
c WORKL, WORKD )
c
c\Arguments
c N Integer. (INPUT)
c Problem size, i.e. size of matrix A.
c
c KEV Integer. (INPUT/OUTPUT)
c KEV+NP is the size of the input matrix H.
c KEV is the size of the updated matrix HNEW.
c
c NP Integer. (INPUT)
c Number of implicit shifts to be applied.
c
c SHIFT Complex array of length NP. (INPUT)
c The shifts to be applied.
c
c V Complex N by (KEV+NP) array. (INPUT/OUTPUT)
c On INPUT, V contains the current KEV+NP Arnoldi vectors.
c On OUTPUT, V contains the updated KEV Arnoldi vectors
c in the first KEV columns of V.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Complex (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT)
c On INPUT, H contains the current KEV+NP by KEV+NP upper
c Hessenberg matrix of the Arnoldi factorization.
c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg
c matrix in the KEV leading submatrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RESID Complex array of length N. (INPUT/OUTPUT)
c On INPUT, RESID contains the the residual vector r_{k+p}.
c On OUTPUT, RESID is the update residual vector rnew_{k}
c in the first KEV locations.
c
c Q Complex KEV+NP by KEV+NP work array. (WORKSPACE)
c Work array used to accumulate the rotations and reflections
c during the bulge chase sweep.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Complex work array of length (KEV+NP). (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c WORKD Complex work array of length 2*N. (WORKSPACE)
c Distributed array used in the application of the accumulated
c orthogonal matrix Q.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c
c\Routines called:
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c cmout ARPACK utility routine that prints matrices
c cvout ARPACK utility routine that prints vectors.
c clacpy LAPACK matrix copy routine.
c clanhs LAPACK routine that computes various norms of a matrix.
c clartg LAPACK Givens rotation construction routine.
c claset LAPACK matrix initialization routine.
c slabad LAPACK routine for defining the underflow and overflow
c limits.
c slamch LAPACK routine that determines machine constants.
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c cgemv Level 2 BLAS routine for matrix vector multiplication.
c caxpy Level 1 BLAS that computes a vector triad.
c ccopy Level 1 BLAS that copies one vector to another.
c cscal Level 1 BLAS that scales a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: napps.F SID: 2.3 DATE OF SID: 3/28/97 RELEASE: 2
c
c\Remarks
c 1. In this version, each shift is applied to all the sublocks of
c the Hessenberg matrix H and not just to the submatrix that it
c comes from. Deflation as in LAPACK routine clahqr (QR algorithm
c for upper Hessenberg matrices ) is used.
c Upon output, the subdiagonals of H are enforced to be non-negative
c real numbers.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine cnapps
& ( n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq,
& workl, workd )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer kev, ldh, ldq, ldv, n, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Complex
& h(ldh,kev+np), resid(n), shift(np),
& v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np)
c
c %------------%
c | Parameters |
c %------------%
c
Complex
& one, zero
Real
& rzero
parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0),
& rzero = 0.0E+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
integer i, iend, istart, j, jj, kplusp, msglvl
logical first
Complex
& cdum, f, g, h11, h21, r, s, sigma, t
Real
& c, ovfl, smlnum, ulp, unfl, tst1
save first, ovfl, smlnum, ulp, unfl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external caxpy, ccopy, cgemv, cscal, clacpy, clartg,
& cvout, claset, slabad, cmout, second, ivout
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& clanhs, slamch, slapy2
external clanhs, slamch, slapy2
c
c %----------------------%
c | Intrinsics Functions |
c %----------------------%
c
intrinsic abs, aimag, conjg, cmplx, max, min, real
c
c %---------------------%
c | Statement Functions |
c %---------------------%
c
Real
& cabs1
cabs1( cdum ) = abs( real( cdum ) ) + abs( aimag( cdum ) )
c
c %----------------%
c | Data statments |
c %----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
c
c %-----------------------------------------------%
c | Set machine-dependent constants for the |
c | stopping criterion. If norm(H) <= sqrt(OVFL), |
c | overflow should not occur. |
c | REFERENCE: LAPACK subroutine clahqr |
c %-----------------------------------------------%
c
unfl = slamch( 'safe minimum' )
ovfl = real(one / unfl)
call slabad( unfl, ovfl )
ulp = slamch( 'precision' )
smlnum = unfl*( n / ulp )
first = .false.
end if
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mcapps
c
kplusp = kev + np
c
c %--------------------------------------------%
c | Initialize Q to the identity to accumulate |
c | the rotations and reflections |
c %--------------------------------------------%
c
call claset ('All', kplusp, kplusp, zero, one, q, ldq)
c
c %----------------------------------------------%
c | Quick return if there are no shifts to apply |
c %----------------------------------------------%
c
if (np .eq. 0) go to 9000
c
c %----------------------------------------------%
c | Chase the bulge with the application of each |
c | implicit shift. Each shift is applied to the |
c | whole matrix including each block. |
c %----------------------------------------------%
c
do 110 jj = 1, np
sigma = shift(jj)
c
if (msglvl .gt. 2 ) then
call ivout (logfil, 1, jj, ndigit,
& '_napps: shift number.')
call cvout (logfil, 1, sigma, ndigit,
& '_napps: Value of the shift ')
end if
c
istart = 1
20 continue
c
do 30 i = istart, kplusp-1
c
c %----------------------------------------%
c | Check for splitting and deflation. Use |
c | a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine clahqr |
c %----------------------------------------%
c
tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) )
if( tst1.eq.rzero )
& tst1 = clanhs( '1', kplusp-jj+1, h, ldh, workl )
if ( abs(real(h(i+1,i)))
& .le. max(ulp*tst1, smlnum) ) then
if (msglvl .gt. 0) then
call ivout (logfil, 1, i, ndigit,
& '_napps: matrix splitting at row/column no.')
call ivout (logfil, 1, jj, ndigit,
& '_napps: matrix splitting with shift number.')
call cvout (logfil, 1, h(i+1,i), ndigit,
& '_napps: off diagonal element.')
end if
iend = i
h(i+1,i) = zero
go to 40
end if
30 continue
iend = kplusp
40 continue
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, istart, ndigit,
& '_napps: Start of current block ')
call ivout (logfil, 1, iend, ndigit,
& '_napps: End of current block ')
end if
c
c %------------------------------------------------%
c | No reason to apply a shift to block of order 1 |
c | or if the current block starts after the point |
c | of compression since we'll discard this stuff |
c %------------------------------------------------%
c
if ( istart .eq. iend .or. istart .gt. kev) go to 100
c
h11 = h(istart,istart)
h21 = h(istart+1,istart)
f = h11 - sigma
g = h21
c
do 80 i = istart, iend-1
c
c %------------------------------------------------------%
c | Construct the plane rotation G to zero out the bulge |
c %------------------------------------------------------%
c
call clartg (f, g, c, s, r)
if (i .gt. istart) then
h(i,i-1) = r
h(i+1,i-1) = zero
end if
c
c %---------------------------------------------%
c | Apply rotation to the left of H; H <- G'*H |
c %---------------------------------------------%
c
do 50 j = i, kplusp
t = c*h(i,j) + s*h(i+1,j)
h(i+1,j) = -conjg(s)*h(i,j) + c*h(i+1,j)
h(i,j) = t
50 continue
c
c %---------------------------------------------%
c | Apply rotation to the right of H; H <- H*G |
c %---------------------------------------------%
c
do 60 j = 1, min(i+2,iend)
t = c*h(j,i) + conjg(s)*h(j,i+1)
h(j,i+1) = -s*h(j,i) + c*h(j,i+1)
h(j,i) = t
60 continue
c
c %-----------------------------------------------------%
c | Accumulate the rotation in the matrix Q; Q <- Q*G' |
c %-----------------------------------------------------%
c
do 70 j = 1, min(i+jj, kplusp)
t = c*q(j,i) + conjg(s)*q(j,i+1)
q(j,i+1) = - s*q(j,i) + c*q(j,i+1)
q(j,i) = t
70 continue
c
c %---------------------------%
c | Prepare for next rotation |
c %---------------------------%
c
if (i .lt. iend-1) then
f = h(i+1,i)
g = h(i+2,i)
end if
80 continue
c
c %-------------------------------%
c | Finished applying the shift. |
c %-------------------------------%
c
100 continue
c
c %---------------------------------------------------------%
c | Apply the same shift to the next block if there is any. |
c %---------------------------------------------------------%
c
istart = iend + 1
if (iend .lt. kplusp) go to 20
c
c %---------------------------------------------%
c | Loop back to the top to get the next shift. |
c %---------------------------------------------%
c
110 continue
c
c %---------------------------------------------------%
c | Perform a similarity transformation that makes |
c | sure that the compressed H will have non-negative |
c | real subdiagonal elements. |
c %---------------------------------------------------%
c
do 120 j=1,kev
if ( real( h(j+1,j) ) .lt. rzero .or.
& aimag( h(j+1,j) ) .ne. rzero ) then
t = h(j+1,j) / slapy2(real(h(j+1,j)),aimag(h(j+1,j)))
call cscal( kplusp-j+1, conjg(t), h(j+1,j), ldh )
call cscal( min(j+2, kplusp), t, h(1,j+1), 1 )
call cscal( min(j+np+1,kplusp), t, q(1,j+1), 1 )
h(j+1,j) = cmplx( real( h(j+1,j) ), rzero )
end if
120 continue
c
do 130 i = 1, kev
c
c %--------------------------------------------%
c | Final check for splitting and deflation. |
c | Use a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine clahqr. |
c | Note: Since the subdiagonals of the |
c | compressed H are nonnegative real numbers, |
c | we take advantage of this. |
c %--------------------------------------------%
c
tst1 = cabs1( h( i, i ) ) + cabs1( h( i+1, i+1 ) )
if( tst1 .eq. rzero )
& tst1 = clanhs( '1', kev, h, ldh, workl )
if( real( h( i+1,i ) ) .le. max( ulp*tst1, smlnum ) )
& h(i+1,i) = zero
130 continue
c
c %-------------------------------------------------%
c | Compute the (kev+1)-st column of (V*Q) and |
c | temporarily store the result in WORKD(N+1:2*N). |
c | This is needed in the residual update since we |
c | cannot GUARANTEE that the corresponding entry |
c | of H would be zero as in exact arithmetic. |
c %-------------------------------------------------%
c
if ( real( h(kev+1,kev) ) .gt. rzero )
& call cgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero,
& workd(n+1), 1)
c
c %----------------------------------------------------------%
c | Compute column 1 to kev of (V*Q) in backward order |
c | taking advantage of the upper Hessenberg structure of Q. |
c %----------------------------------------------------------%
c
do 140 i = 1, kev
call cgemv ('N', n, kplusp-i+1, one, v, ldv,
& q(1,kev-i+1), 1, zero, workd, 1)
call ccopy (n, workd, 1, v(1,kplusp-i+1), 1)
140 continue
c
c %-------------------------------------------------%
c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). |
c %-------------------------------------------------%
c
call clacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv)
c
c %--------------------------------------------------------------%
c | Copy the (kev+1)-st column of (V*Q) in the appropriate place |
c %--------------------------------------------------------------%
c
if ( real( h(kev+1,kev) ) .gt. rzero )
& call ccopy (n, workd(n+1), 1, v(1,kev+1), 1)
c
c %-------------------------------------%
c | Update the residual vector: |
c | r <- sigmak*r + betak*v(:,kev+1) |
c | where |
c | sigmak = (e_{kev+p}'*Q)*e_{kev} |
c | betak = e_{kev+1}'*H*e_{kev} |
c %-------------------------------------%
c
call cscal (n, q(kplusp,kev), resid, 1)
if ( real( h(kev+1,kev) ) .gt. rzero )
& call caxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1)
c
if (msglvl .gt. 1) then
call cvout (logfil, 1, q(kplusp,kev), ndigit,
& '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}')
call cvout (logfil, 1, h(kev+1,kev), ndigit,
& '_napps: betak = e_{kev+1}^T*H*e_{kev}')
call ivout (logfil, 1, kev, ndigit,
& '_napps: Order of the final Hessenberg matrix ')
if (msglvl .gt. 2) then
call cmout (logfil, kev, kev, h, ldh, ndigit,
& '_napps: updated Hessenberg matrix H for next iteration')
end if
c
end if
c
9000 continue
call second (t1)
tcapps = tcapps + (t1 - t0)
c
return
c
c %---------------%
c | End of cnapps |
c %---------------%
c
end

801
arpack/ARPACK/SRC/cnaup2.f Normal file
View File

@@ -0,0 +1,801 @@
c\BeginDoc
c
c\Name: cnaup2
c
c\Description:
c Intermediate level interface called by cnaupd.
c
c\Usage:
c call cnaup2
c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD,
c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS,
c Q, LDQ, WORKL, IPNTR, WORKD, RWORK, INFO )
c
c\Arguments
c
c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in cnaupd.
c MODE, ISHIFT, MXITER: see the definition of IPARAM in cnaupd.
c
c NP Integer. (INPUT/OUTPUT)
c Contains the number of implicit shifts to apply during
c each Arnoldi iteration.
c If ISHIFT=1, NP is adjusted dynamically at each iteration
c to accelerate convergence and prevent stagnation.
c This is also roughly equal to the number of matrix-vector
c products (involving the operator OP) per Arnoldi iteration.
c The logic for adjusting is contained within the current
c subroutine.
c If ISHIFT=0, NP is the number of shifts the user needs
c to provide via reverse comunication. 0 < NP < NCV-NEV.
c NP may be less than NCV-NEV since a leading block of the current
c upper Hessenberg matrix has split off and contains "unwanted"
c Ritz values.
c Upon termination of the IRA iteration, NP contains the number
c of "converged" wanted Ritz values.
c
c IUPD Integer. (INPUT)
c IUPD .EQ. 0: use explicit restart instead implicit update.
c IUPD .NE. 0: use implicit update.
c
c V Complex N by (NEV+NP) array. (INPUT/OUTPUT)
c The Arnoldi basis vectors are returned in the first NEV
c columns of V.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Complex (NEV+NP) by (NEV+NP) array. (OUTPUT)
c H is used to store the generated upper Hessenberg matrix
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RITZ Complex array of length NEV+NP. (OUTPUT)
c RITZ(1:NEV) contains the computed Ritz values of OP.
c
c BOUNDS Complex array of length NEV+NP. (OUTPUT)
c BOUNDS(1:NEV) contain the error bounds corresponding to
c the computed Ritz values.
c
c Q Complex (NEV+NP) by (NEV+NP) array. (WORKSPACE)
c Private (replicated) work array used to accumulate the
c rotation in the shift application step.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Complex work array of length at least
c (NEV+NP)**2 + 3*(NEV+NP). (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. It is used in shifts calculation, shifts
c application and convergence checking.
c
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORKD for
c vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in the
c shift-and-invert mode. X is the current operand.
c -------------------------------------------------------------
c
c WORKD Complex work array of length 3*N. (WORKSPACE)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration !!!!!!!!!!
c See Data Distribution Note in CNAUPD.
c
c RWORK Real work array of length NEV+NP ( WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal return.
c = 1: Maximum number of iterations taken.
c All possible eigenvalues of OP has been found.
c NP returns the number of converged Ritz values.
c = 2: No shifts could be applied.
c = -8: Error return from LAPACK eigenvalue calculation;
c This should never happen.
c = -9: Starting vector is zero.
c = -9999: Could not build an Arnoldi factorization.
c Size that was built in returned in NP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c cgetv0 ARPACK initial vector generation routine.
c cnaitr ARPACK Arnoldi factorization routine.
c cnapps ARPACK application of implicit shifts routine.
c cneigh ARPACK compute Ritz values and error bounds routine.
c cngets ARPACK reorder Ritz values and error bounds routine.
c csortc ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c cmout ARPACK utility routine that prints matrices
c cvout ARPACK utility routine that prints vectors.
c svout ARPACK utility routine that prints vectors.
c slamch LAPACK routine that determines machine constants.
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c ccopy Level 1 BLAS that copies one vector to another .
c cdotc Level 1 BLAS that computes the scalar product of two vectors.
c cswap Level 1 BLAS that swaps two vectors.
c scnrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice Universitya
c Chao Yang Houston, Texas
c Dept. of Computational &
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: naup2.F SID: 2.6 DATE OF SID: 06/01/00 RELEASE: 2
c
c\Remarks
c 1. None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine cnaup2
& ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, h, ldh, ritz, bounds,
& q, ldq, workl, ipntr, workd, rwork, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter,
& n, nev, np
Real
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(13)
Complex
& bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np),
& resid(n), ritz(nev+np), v(ldv,nev+np),
& workd(3*n), workl( (nev+np)*(nev+np+3) )
Real
& rwork(nev+np)
c
c %------------%
c | Parameters |
c %------------%
c
Complex
& one, zero
Real
& rzero
parameter (one = (1.0E+0, 0.0E+0) , zero = (0.0E+0, 0.0E+0) ,
& rzero = 0.0E+0 )
c
c %---------------%
c | Local Scalars |
c %---------------%
c
logical cnorm , getv0, initv , update, ushift
integer ierr , iter , kplusp, msglvl, nconv,
& nevbef, nev0 , np0 , nptemp, i ,
& j
Complex
& cmpnorm
Real
& rnorm , eps23, rtemp
character wprime*2
c
save cnorm, getv0, initv , update, ushift,
& rnorm, iter , kplusp, msglvl, nconv ,
& nevbef, nev0 , np0 , eps23
c
c
c %-----------------------%
c | Local array arguments |
c %-----------------------%
c
integer kp(3)
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external ccopy, cgetv0, cnaitr, cneigh, cngets, cnapps,
& csortc, cswap, cmout, cvout, ivout, second
c
c %--------------------%
c | External functions |
c %--------------------%
c
Complex
& cdotc
Real
& scnrm2, slamch, slapy2
external cdotc, scnrm2, slamch, slapy2
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic aimag, real , min, max
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
call second (t0)
c
msglvl = mcaup2
c
nev0 = nev
np0 = np
c
c %-------------------------------------%
c | kplusp is the bound on the largest |
c | Lanczos factorization built. |
c | nconv is the current number of |
c | "converged" eigenvalues. |
c | iter is the counter on the current |
c | iteration step. |
c %-------------------------------------%
c
kplusp = nev + np
nconv = 0
iter = 0
c
c %---------------------------------%
c | Get machine dependent constant. |
c %---------------------------------%
c
eps23 = slamch('Epsilon-Machine')
eps23 = eps23**(2.0E+0 / 3.0E+0 )
c
c %---------------------------------------%
c | Set flags for computing the first NEV |
c | steps of the Arnoldi factorization. |
c %---------------------------------------%
c
getv0 = .true.
update = .false.
ushift = .false.
cnorm = .false.
c
if (info .ne. 0) then
c
c %--------------------------------------------%
c | User provides the initial residual vector. |
c %--------------------------------------------%
c
initv = .true.
info = 0
else
initv = .false.
end if
end if
c
c %---------------------------------------------%
c | Get a possibly random starting vector and |
c | force it into the range of the operator OP. |
c %---------------------------------------------%
c
10 continue
c
if (getv0) then
call cgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm,
& ipntr, workd, info)
c
if (ido .ne. 99) go to 9000
c
if (rnorm .eq. rzero) then
c
c %-----------------------------------------%
c | The initial vector is zero. Error exit. |
c %-----------------------------------------%
c
info = -9
go to 1100
end if
getv0 = .false.
ido = 0
end if
c
c %-----------------------------------%
c | Back from reverse communication : |
c | continue with update step |
c %-----------------------------------%
c
if (update) go to 20
c
c %-------------------------------------------%
c | Back from computing user specified shifts |
c %-------------------------------------------%
c
if (ushift) go to 50
c
c %-------------------------------------%
c | Back from computing residual norm |
c | at the end of the current iteration |
c %-------------------------------------%
c
if (cnorm) go to 100
c
c %----------------------------------------------------------%
c | Compute the first NEV steps of the Arnoldi factorization |
c %----------------------------------------------------------%
c
call cnaitr (ido, bmat, n, 0, nev, mode, resid, rnorm, v, ldv,
& h, ldh, ipntr, workd, info)
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
np = info
mxiter = iter
info = -9999
go to 1200
end if
c
c %--------------------------------------------------------------%
c | |
c | M A I N ARNOLDI I T E R A T I O N L O O P |
c | Each iteration implicitly restarts the Arnoldi |
c | factorization in place. |
c | |
c %--------------------------------------------------------------%
c
1000 continue
c
iter = iter + 1
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, iter, ndigit,
& '_naup2: **** Start of major iteration number ****')
end if
c
c %-----------------------------------------------------------%
c | Compute NP additional steps of the Arnoldi factorization. |
c | Adjust NP since NEV might have been updated by last call |
c | to the shift application routine cnapps. |
c %-----------------------------------------------------------%
c
np = kplusp - nev
c
if (msglvl .gt. 1) then
call ivout (logfil, 1, nev, ndigit,
& '_naup2: The length of the current Arnoldi factorization')
call ivout (logfil, 1, np, ndigit,
& '_naup2: Extend the Arnoldi factorization by')
end if
c
c %-----------------------------------------------------------%
c | Compute NP additional steps of the Arnoldi factorization. |
c %-----------------------------------------------------------%
c
ido = 0
20 continue
update = .true.
c
call cnaitr(ido, bmat, n, nev, np, mode, resid, rnorm,
& v , ldv , h, ldh, ipntr, workd, info)
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
np = info
mxiter = iter
info = -9999
go to 1200
end if
update = .false.
c
if (msglvl .gt. 1) then
call svout (logfil, 1, rnorm, ndigit,
& '_naup2: Corresponding B-norm of the residual')
end if
c
c %--------------------------------------------------------%
c | Compute the eigenvalues and corresponding error bounds |
c | of the current upper Hessenberg matrix. |
c %--------------------------------------------------------%
c
call cneigh (rnorm, kplusp, h, ldh, ritz, bounds,
& q, ldq, workl, rwork, ierr)
c
if (ierr .ne. 0) then
info = -8
go to 1200
end if
c
c %---------------------------------------------------%
c | Select the wanted Ritz values and their bounds |
c | to be used in the convergence test. |
c | The wanted part of the spectrum and corresponding |
c | error bounds are in the last NEV loc. of RITZ, |
c | and BOUNDS respectively. |
c %---------------------------------------------------%
c
nev = nev0
np = np0
c
c %--------------------------------------------------%
c | Make a copy of Ritz values and the corresponding |
c | Ritz estimates obtained from cneigh. |
c %--------------------------------------------------%
c
call ccopy(kplusp,ritz,1,workl(kplusp**2+1),1)
call ccopy(kplusp,bounds,1,workl(kplusp**2+kplusp+1),1)
c
c %---------------------------------------------------%
c | Select the wanted Ritz values and their bounds |
c | to be used in the convergence test. |
c | The wanted part of the spectrum and corresponding |
c | bounds are in the last NEV loc. of RITZ |
c | BOUNDS respectively. |
c %---------------------------------------------------%
c
call cngets (ishift, which, nev, np, ritz, bounds)
c
c %------------------------------------------------------------%
c | Convergence test: currently we use the following criteria. |
c | The relative accuracy of a Ritz value is considered |
c | acceptable if: |
c | |
c | error_bounds(i) .le. tol*max(eps23, magnitude_of_ritz(i)). |
c | |
c %------------------------------------------------------------%
c
nconv = 0
c
do 25 i = 1, nev
rtemp = max( eps23, slapy2( real (ritz(np+i)),
& aimag(ritz(np+i)) ) )
if ( slapy2(real (bounds(np+i)),aimag(bounds(np+i)))
& .le. tol*rtemp ) then
nconv = nconv + 1
end if
25 continue
c
if (msglvl .gt. 2) then
kp(1) = nev
kp(2) = np
kp(3) = nconv
call ivout (logfil, 3, kp, ndigit,
& '_naup2: NEV, NP, NCONV are')
call cvout (logfil, kplusp, ritz, ndigit,
& '_naup2: The eigenvalues of H')
call cvout (logfil, kplusp, bounds, ndigit,
& '_naup2: Ritz estimates of the current NCV Ritz values')
end if
c
c %---------------------------------------------------------%
c | Count the number of unwanted Ritz values that have zero |
c | Ritz estimates. If any Ritz estimates are equal to zero |
c | then a leading block of H of order equal to at least |
c | the number of Ritz values with zero Ritz estimates has |
c | split off. None of these Ritz values may be removed by |
c | shifting. Decrease NP the number of shifts to apply. If |
c | no shifts may be applied, then prepare to exit |
c %---------------------------------------------------------%
c
nptemp = np
do 30 j=1, nptemp
if (bounds(j) .eq. zero) then
np = np - 1
nev = nev + 1
end if
30 continue
c
if ( (nconv .ge. nev0) .or.
& (iter .gt. mxiter) .or.
& (np .eq. 0) ) then
c
if (msglvl .gt. 4) then
call cvout(logfil, kplusp, workl(kplusp**2+1), ndigit,
& '_naup2: Eigenvalues computed by _neigh:')
call cvout(logfil, kplusp, workl(kplusp**2+kplusp+1),
& ndigit,
& '_naup2: Ritz estimates computed by _neigh:')
end if
c
c %------------------------------------------------%
c | Prepare to exit. Put the converged Ritz values |
c | and corresponding bounds in RITZ(1:NCONV) and |
c | BOUNDS(1:NCONV) respectively. Then sort. Be |
c | careful when NCONV > NP |
c %------------------------------------------------%
c
c %------------------------------------------%
c | Use h( 3,1 ) as storage to communicate |
c | rnorm to cneupd if needed |
c %------------------------------------------%
h(3,1) = cmplx(rnorm,rzero)
c
c %----------------------------------------------%
c | Sort Ritz values so that converged Ritz |
c | values appear within the first NEV locations |
c | of ritz and bounds, and the most desired one |
c | appears at the front. |
c %----------------------------------------------%
c
if (which .eq. 'LM') wprime = 'SM'
if (which .eq. 'SM') wprime = 'LM'
if (which .eq. 'LR') wprime = 'SR'
if (which .eq. 'SR') wprime = 'LR'
if (which .eq. 'LI') wprime = 'SI'
if (which .eq. 'SI') wprime = 'LI'
c
call csortc(wprime, .true., kplusp, ritz, bounds)
c
c %--------------------------------------------------%
c | Scale the Ritz estimate of each Ritz value |
c | by 1 / max(eps23, magnitude of the Ritz value). |
c %--------------------------------------------------%
c
do 35 j = 1, nev0
rtemp = max( eps23, slapy2( real (ritz(j)),
& aimag(ritz(j)) ) )
bounds(j) = bounds(j)/rtemp
35 continue
c
c %---------------------------------------------------%
c | Sort the Ritz values according to the scaled Ritz |
c | estimates. This will push all the converged ones |
c | towards the front of ritz, bounds (in the case |
c | when NCONV < NEV.) |
c %---------------------------------------------------%
c
wprime = 'LM'
call csortc(wprime, .true., nev0, bounds, ritz)
c
c %----------------------------------------------%
c | Scale the Ritz estimate back to its original |
c | value. |
c %----------------------------------------------%
c
do 40 j = 1, nev0
rtemp = max( eps23, slapy2( real (ritz(j)),
& aimag(ritz(j)) ) )
bounds(j) = bounds(j)*rtemp
40 continue
c
c %-----------------------------------------------%
c | Sort the converged Ritz values again so that |
c | the "threshold" value appears at the front of |
c | ritz and bound. |
c %-----------------------------------------------%
c
call csortc(which, .true., nconv, ritz, bounds)
c
if (msglvl .gt. 1) then
call cvout (logfil, kplusp, ritz, ndigit,
& '_naup2: Sorted eigenvalues')
call cvout (logfil, kplusp, bounds, ndigit,
& '_naup2: Sorted ritz estimates.')
end if
c
c %------------------------------------%
c | Max iterations have been exceeded. |
c %------------------------------------%
c
if (iter .gt. mxiter .and. nconv .lt. nev0) info = 1
c
c %---------------------%
c | No shifts to apply. |
c %---------------------%
c
if (np .eq. 0 .and. nconv .lt. nev0) info = 2
c
np = nconv
go to 1100
c
else if ( (nconv .lt. nev0) .and. (ishift .eq. 1) ) then
c
c %-------------------------------------------------%
c | Do not have all the requested eigenvalues yet. |
c | To prevent possible stagnation, adjust the size |
c | of NEV. |
c %-------------------------------------------------%
c
nevbef = nev
nev = nev + min(nconv, np/2)
if (nev .eq. 1 .and. kplusp .ge. 6) then
nev = kplusp / 2
else if (nev .eq. 1 .and. kplusp .gt. 3) then
nev = 2
end if
np = kplusp - nev
c
c %---------------------------------------%
c | If the size of NEV was just increased |
c | resort the eigenvalues. |
c %---------------------------------------%
c
if (nevbef .lt. nev)
& call cngets (ishift, which, nev, np, ritz, bounds)
c
end if
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, nconv, ndigit,
& '_naup2: no. of "converged" Ritz values at this iter.')
if (msglvl .gt. 1) then
kp(1) = nev
kp(2) = np
call ivout (logfil, 2, kp, ndigit,
& '_naup2: NEV and NP are')
call cvout (logfil, nev, ritz(np+1), ndigit,
& '_naup2: "wanted" Ritz values ')
call cvout (logfil, nev, bounds(np+1), ndigit,
& '_naup2: Ritz estimates of the "wanted" values ')
end if
end if
c
if (ishift .eq. 0) then
c
c %-------------------------------------------------------%
c | User specified shifts: pop back out to get the shifts |
c | and return them in the first 2*NP locations of WORKL. |
c %-------------------------------------------------------%
c
ushift = .true.
ido = 3
go to 9000
end if
50 continue
ushift = .false.
c
if ( ishift .ne. 1 ) then
c
c %----------------------------------%
c | Move the NP shifts from WORKL to |
c | RITZ, to free up WORKL |
c | for non-exact shift case. |
c %----------------------------------%
c
call ccopy (np, workl, 1, ritz, 1)
end if
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, np, ndigit,
& '_naup2: The number of shifts to apply ')
call cvout (logfil, np, ritz, ndigit,
& '_naup2: values of the shifts')
if ( ishift .eq. 1 )
& call cvout (logfil, np, bounds, ndigit,
& '_naup2: Ritz estimates of the shifts')
end if
c
c %---------------------------------------------------------%
c | Apply the NP implicit shifts by QR bulge chasing. |
c | Each shift is applied to the whole upper Hessenberg |
c | matrix H. |
c | The first 2*N locations of WORKD are used as workspace. |
c %---------------------------------------------------------%
c
call cnapps (n, nev, np, ritz, v, ldv,
& h, ldh, resid, q, ldq, workl, workd)
c
c %---------------------------------------------%
c | Compute the B-norm of the updated residual. |
c | Keep B*RESID in WORKD(1:N) to be used in |
c | the first step of the next call to cnaitr. |
c %---------------------------------------------%
c
cnorm = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call ccopy (n, resid, 1, workd(n+1), 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*RESID |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call ccopy (n, resid, 1, workd, 1)
end if
c
100 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(1:N) := B*RESID |
c %----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
if (bmat .eq. 'G') then
cmpnorm = cdotc (n, resid, 1, workd, 1)
rnorm = sqrt(slapy2(real (cmpnorm),aimag(cmpnorm)))
else if (bmat .eq. 'I') then
rnorm = scnrm2(n, resid, 1)
end if
cnorm = .false.
c
if (msglvl .gt. 2) then
call svout (logfil, 1, rnorm, ndigit,
& '_naup2: B-norm of residual for compressed factorization')
call cmout (logfil, nev, nev, h, ldh, ndigit,
& '_naup2: Compressed upper Hessenberg matrix H')
end if
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
1100 continue
c
mxiter = iter
nev = nconv
c
1200 continue
ido = 99
c
c %------------%
c | Error Exit |
c %------------%
c
call second (t1)
tcaup2 = t1 - t0
c
9000 continue
c
c %---------------%
c | End of cnaup2 |
c %---------------%
c
return
end

664
arpack/ARPACK/SRC/cnaupd.f Normal file
View File

@@ -0,0 +1,664 @@
c\BeginDoc
c
c\Name: cnaupd
c
c\Description:
c Reverse communication interface for the Implicitly Restarted Arnoldi
c iteration. This is intended to be used to find a few eigenpairs of a
c complex linear operator OP with respect to a semi-inner product defined
c by a hermitian positive semi-definite real matrix B. B may be the identity
c matrix. NOTE: if both OP and B are real, then ssaupd or snaupd should
c be used.
c
c
c The computed approximate eigenvalues are called Ritz values and
c the corresponding approximate eigenvectors are called Ritz vectors.
c
c cnaupd is usually called iteratively to solve one of the
c following problems:
c
c Mode 1: A*x = lambda*x.
c ===> OP = A and B = I.
c
c Mode 2: A*x = lambda*M*x, M hermitian positive definite
c ===> OP = inv[M]*A and B = M.
c ===> (If M can be factored see remark 3 below)
c
c Mode 3: A*x = lambda*M*x, M hermitian semi-definite
c ===> OP = inv[A - sigma*M]*M and B = M.
c ===> shift-and-invert mode
c If OP*x = amu*x, then lambda = sigma + 1/amu.
c
c
c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v
c should be accomplished either by a direct method
c using a sparse matrix factorization and solving
c
c [A - sigma*M]*w = v or M*w = v,
c
c or through an iterative method for solving these
c systems. If an iterative method is used, the
c convergence test must be more stringent than
c the accuracy requirements for the eigenvalue
c approximations.
c
c\Usage:
c call cnaupd
c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM,
c IPNTR, WORKD, WORKL, LWORKL, RWORK, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag. IDO must be zero on the first
c call to cnaupd. IDO will be set internally to
c indicate the type of operation to be performed. Control is
c then given back to the calling routine which has the
c responsibility to carry out the requested operation and call
c cnaupd with the result. The operand is given in
c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)).
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c This is for the initialization phase to force the
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c In mode 3, the vector B * X is already
c available in WORKD(ipntr(3)). It does not
c need to be recomputed in forming OP * X.
c IDO = 2: compute Y = M * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c IDO = 3: compute and return the shifts in the first
c NP locations of WORKL.
c IDO = 99: done
c -------------------------------------------------------------
c After the initialization phase, when the routine is used in
c the "shift-and-invert" mode, the vector M * X is already
c available and does not need to be recomputed in forming OP*X.
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B that defines the
c semi-inner product for the operator OP.
c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x
c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c WHICH Character*2. (INPUT)
c 'LM' -> want the NEV eigenvalues of largest magnitude.
c 'SM' -> want the NEV eigenvalues of smallest magnitude.
c 'LR' -> want the NEV eigenvalues of largest real part.
c 'SR' -> want the NEV eigenvalues of smallest real part.
c 'LI' -> want the NEV eigenvalues of largest imaginary part.
c 'SI' -> want the NEV eigenvalues of smallest imaginary part.
c
c NEV Integer. (INPUT)
c Number of eigenvalues of OP to be computed. 0 < NEV < N-1.
c
c TOL Real scalar. (INPUT)
c Stopping criteria: the relative accuracy of the Ritz value
c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I))
c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex.
c DEFAULT = slamch('EPS') (machine precision as computed
c by the LAPACK auxiliary subroutine slamch).
c
c RESID Complex array of length N. (INPUT/OUTPUT)
c On INPUT:
c If INFO .EQ. 0, a random initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c On OUTPUT:
c RESID contains the final residual vector.
c
c NCV Integer. (INPUT)
c Number of columns of the matrix V. NCV must satisfy the two
c inequalities 1 <= NCV-NEV and NCV <= N.
c This will indicate how many Arnoldi vectors are generated
c at each iteration. After the startup phase in which NEV
c Arnoldi vectors are generated, the algorithm generates
c approximately NCV-NEV Arnoldi vectors at each subsequent update
c iteration. Most of the cost in generating each Arnoldi vector is
c in the matrix-vector operation OP*x. (See remark 4 below.)
c
c V Complex array N by NCV. (OUTPUT)
c Contains the final set of Arnoldi basis vectors.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling program.
c
c IPARAM Integer array of length 11. (INPUT/OUTPUT)
c IPARAM(1) = ISHIFT: method for selecting the implicit shifts.
c The shifts selected at each iteration are used to filter out
c the components of the unwanted eigenvector.
c -------------------------------------------------------------
c ISHIFT = 0: the shifts are to be provided by the user via
c reverse communication. The NCV eigenvalues of
c the Hessenberg matrix H are returned in the part
c of WORKL array corresponding to RITZ.
c ISHIFT = 1: exact shifts with respect to the current
c Hessenberg matrix H. This is equivalent to
c restarting the iteration from the beginning
c after updating the starting vector with a linear
c combination of Ritz vectors associated with the
c "wanted" eigenvalues.
c ISHIFT = 2: other choice of internal shift to be defined.
c -------------------------------------------------------------
c
c IPARAM(2) = No longer referenced
c
c IPARAM(3) = MXITER
c On INPUT: maximum number of Arnoldi update iterations allowed.
c On OUTPUT: actual number of Arnoldi update iterations taken.
c
c IPARAM(4) = NB: blocksize to be used in the recurrence.
c The code currently works only for NB = 1.
c
c IPARAM(5) = NCONV: number of "converged" Ritz values.
c This represents the number of Ritz values that satisfy
c the convergence criterion.
c
c IPARAM(6) = IUPD
c No longer referenced. Implicit restarting is ALWAYS used.
c
c IPARAM(7) = MODE
c On INPUT determines what type of eigenproblem is being solved.
c Must be 1,2,3; See under \Description of cnaupd for the
c four modes available.
c
c IPARAM(8) = NP
c When ido = 3 and the user provides shifts through reverse
c communication (IPARAM(1)=0), _naupd returns NP, the number
c of shifts the user is to provide. 0 < NP < NCV-NEV.
c
c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO,
c OUTPUT: NUMOP = total number of OP*x operations,
c NUMOPB = total number of B*x operations if BMAT='G',
c NUMREO = total number of steps of re-orthogonalization.
c
c IPNTR Integer array of length 14. (OUTPUT)
c Pointer to mark the starting locations in the WORKD and WORKL
c arrays for matrices/vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X in WORKD.
c IPNTR(2): pointer to the current result vector Y in WORKD.
c IPNTR(3): pointer to the vector B * X in WORKD when used in
c the shift-and-invert mode.
c IPNTR(4): pointer to the next available location in WORKL
c that is untouched by the program.
c IPNTR(5): pointer to the NCV by NCV upper Hessenberg
c matrix H in WORKL.
c IPNTR(6): pointer to the ritz value array RITZ
c IPNTR(7): pointer to the (projected) ritz vector array Q
c IPNTR(8): pointer to the error BOUNDS array in WORKL.
c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below.
c
c Note: IPNTR(9:13) is only referenced by cneupd. See Remark 2 below.
c
c IPNTR(9): pointer to the NCV RITZ values of the
c original system.
c IPNTR(10): Not Used
c IPNTR(11): pointer to the NCV corresponding error bounds.
c IPNTR(12): pointer to the NCV by NCV upper triangular
c Schur matrix for H.
c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors
c of the upper Hessenberg matrix H. Only referenced by
c cneupd if RVEC = .TRUE. See Remark 2 below.
c
c -------------------------------------------------------------
c
c WORKD Complex work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration !!!!!!!!!!
c See Data Distribution Note below.
c
c WORKL Complex work array of length LWORKL. (OUTPUT/WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. See Data Distribution Note below.
c
c LWORKL Integer. (INPUT)
c LWORKL must be at least 3*NCV**2 + 5*NCV.
c
c RWORK Real work array of length NCV (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal exit.
c = 1: Maximum number of iterations taken.
c All possible eigenvalues of OP has been found. IPARAM(5)
c returns the number of wanted converged Ritz values.
c = 2: No longer an informational error. Deprecated starting
c with release 2 of ARPACK.
c = 3: No shifts could be applied during a cycle of the
c Implicitly restarted Arnoldi iteration. One possibility
c is to increase the size of NCV relative to NEV.
c See remark 4 below.
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV-NEV >= 1 and less than or equal to N.
c = -4: The maximum number of Arnoldi update iteration
c must be greater than zero.
c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work array is not sufficient.
c = -8: Error return from LAPACK eigenvalue calculation;
c = -9: Starting vector is zero.
c = -10: IPARAM(7) must be 1,2,3.
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.
c = -12: IPARAM(1) must be equal to 0 or 1.
c = -9999: Could not build an Arnoldi factorization.
c User input error highly likely. Please
c check actual array dimensions and layout.
c IPARAM(5) returns the size of the current Arnoldi
c factorization.
c
c\Remarks
c 1. The computed Ritz values are approximate eigenvalues of OP. The
c selection of WHICH should be made with this in mind when using
c Mode = 3. When operating in Mode = 3 setting WHICH = 'LM' will
c compute the NEV eigenvalues of the original problem that are
c closest to the shift SIGMA . After convergence, approximate eigenvalues
c of the original problem may be obtained with the ARPACK subroutine cneupd.
c
c 2. If a basis for the invariant subspace corresponding to the converged Ritz
c values is needed, the user must call cneupd immediately following
c completion of cnaupd. This is new starting with release 2 of ARPACK.
c
c 3. If M can be factored into a Cholesky factorization M = LL`
c then Mode = 2 should not be selected. Instead one should use
c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular
c linear systems should be solved with L and L` rather
c than computing inverses. After convergence, an approximate
c eigenvector z of the original problem is recovered by solving
c L`z = x where x is a Ritz vector of OP.
c
c 4. At present there is no a-priori analysis to guide the selection
c of NCV relative to NEV. The only formal requirement is that NCV > NEV + 1.
c However, it is recommended that NCV .ge. 2*NEV. If many problems of
c the same type are to be solved, one should experiment with increasing
c NCV while keeping NEV fixed for a given test problem. This will
c usually decrease the required number of OP*x operations but it
c also increases the work and storage required to maintain the orthogonal
c basis vectors. The optimal "cross-over" with respect to CPU time
c is problem dependent and must be determined empirically.
c See Chapter 8 of Reference 2 for further information.
c
c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the
c NP = IPARAM(8) complex shifts in locations
c WORKL(IPNTR(14)), WORKL(IPNTR(14)+1), ... , WORKL(IPNTR(14)+NP).
c Eigenvalues of the current upper Hessenberg matrix are located in
c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are ordered
c according to the order defined by WHICH. The associated Ritz estimates
c are located in WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... ,
c WORKL(IPNTR(8)+NCV-1).
c
c-----------------------------------------------------------------------
c
c\Data Distribution Note:
c
c Fortran-D syntax:
c ================
c Complex resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
c decompose d1(n), d2(n,ncv)
c align resid(i) with d1(i)
c align v(i,j) with d2(i,j)
c align workd(i) with d1(i) range (1:n)
c align workd(i) with d1(i-n) range (n+1:2*n)
c align workd(i) with d1(i-2*n) range (2*n+1:3*n)
c distribute d1(block), d2(block,:)
c replicated workl(lworkl)
c
c Cray MPP syntax:
c ===============
c Complex resid(n), v(ldv,ncv), workd(n,3), workl(lworkl)
c shared resid(block), v(block,:), workd(block,:)
c replicated workl(lworkl)
c
c CM2/CM5 syntax:
c ==============
c
c-----------------------------------------------------------------------
c
c include 'ex-nonsym.doc'
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett & Y. Saad, "_Complex_ Shift and Invert Strategies for
c Real Matrices", Linear Algebra and its Applications, vol 88/89,
c pp 575-595, (1987).
c
c\Routines called:
c cnaup2 ARPACK routine that implements the Implicitly Restarted
c Arnoldi Iteration.
c cstatn ARPACK routine that initializes the timing variables.
c ivout ARPACK utility routine that prints integers.
c cvout ARPACK utility routine that prints vectors.
c second ARPACK utility routine for timing.
c slamch LAPACK routine that determines machine constants.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: naupd.F SID: 2.9 DATE OF SID: 07/21/02 RELEASE: 2
c
c\Remarks
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine cnaupd
& ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam,
& ipntr, workd, workl, lworkl, rwork, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ldv, lworkl, n, ncv, nev
Real
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(11), ipntr(14)
Complex
& resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
Real
& rwork(ncv)
c
c %------------%
c | Parameters |
c %------------%
c
Complex
& one, zero
parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0))
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer bounds, ierr, ih, iq, ishift, iupd, iw,
& ldh, ldq, levec, mode, msglvl, mxiter, nb,
& nev0, next, np, ritz, j
save bounds, ih, iq, ishift, iupd, iw,
& ldh, ldq, levec, mode, msglvl, mxiter, nb,
& nev0, next, np, ritz
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external cnaup2, cvout, ivout, second, cstatn
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& slamch
external slamch
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call cstatn
call second (t0)
msglvl = mcaupd
c
c %----------------%
c | Error checking |
c %----------------%
c
ierr = 0
ishift = iparam(1)
c levec = iparam(2)
mxiter = iparam(3)
c nb = iparam(4)
nb = 1
c
c %--------------------------------------------%
c | Revision 2 performs only implicit restart. |
c %--------------------------------------------%
c
iupd = 1
mode = iparam(7)
c
if (n .le. 0) then
ierr = -1
else if (nev .le. 0) then
ierr = -2
else if (ncv .le. nev .or. ncv .gt. n) then
ierr = -3
else if (mxiter .le. 0) then
ierr = -4
else if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LR' .and.
& which .ne. 'SR' .and.
& which .ne. 'LI' .and.
& which .ne. 'SI') then
ierr = -5
else if (bmat .ne. 'I' .and. bmat .ne. 'G') then
ierr = -6
else if (lworkl .lt. 3*ncv**2 + 5*ncv) then
ierr = -7
else if (mode .lt. 1 .or. mode .gt. 3) then
ierr = -10
else if (mode .eq. 1 .and. bmat .eq. 'G') then
ierr = -11
end if
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
ido = 99
go to 9000
end if
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
if (nb .le. 0) nb = 1
if (tol .le. 0.0E+0 ) tol = slamch('EpsMach')
if (ishift .ne. 0 .and.
& ishift .ne. 1 .and.
& ishift .ne. 2) ishift = 1
c
c %----------------------------------------------%
c | NP is the number of additional steps to |
c | extend the length NEV Lanczos factorization. |
c | NEV0 is the local variable designating the |
c | size of the invariant subspace desired. |
c %----------------------------------------------%
c
np = ncv - nev
nev0 = nev
c
c %-----------------------------%
c | Zero out internal workspace |
c %-----------------------------%
c
do 10 j = 1, 3*ncv**2 + 5*ncv
workl(j) = zero
10 continue
c
c %-------------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:ncv*ncv) := generated Hessenberg matrix |
c | workl(ncv*ncv+1:ncv*ncv+ncv) := the ritz values |
c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds |
c | workl(ncv*ncv+2*ncv+1:2*ncv*ncv+2*ncv) := rotation matrix Q |
c | workl(2*ncv*ncv+2*ncv+1:3*ncv*ncv+5*ncv) := workspace |
c | The final workspace is needed by subroutine cneigh called |
c | by cnaup2. Subroutine cneigh calls LAPACK routines for |
c | calculating eigenvalues and the last row of the eigenvector |
c | matrix. |
c %-------------------------------------------------------------%
c
ldh = ncv
ldq = ncv
ih = 1
ritz = ih + ldh*ncv
bounds = ritz + ncv
iq = bounds + ncv
iw = iq + ldq*ncv
next = iw + ncv**2 + 3*ncv
c
ipntr(4) = next
ipntr(5) = ih
ipntr(6) = ritz
ipntr(7) = iq
ipntr(8) = bounds
ipntr(14) = iw
end if
c
c %-------------------------------------------------------%
c | Carry out the Implicitly restarted Arnoldi Iteration. |
c %-------------------------------------------------------%
c
call cnaup2
& ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz),
& workl(bounds), workl(iq), ldq, workl(iw),
& ipntr, workd, rwork, info )
c
c %--------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP. |
c %--------------------------------------------------%
c
if (ido .eq. 3) iparam(8) = np
if (ido .ne. 99) go to 9000
c
iparam(3) = mxiter
iparam(5) = np
iparam(9) = nopx
iparam(10) = nbx
iparam(11) = nrorth
c
c %------------------------------------%
c | Exit if there was an informational |
c | error within cnaup2. |
c %------------------------------------%
c
if (info .lt. 0) go to 9000
if (info .eq. 2) info = 3
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, mxiter, ndigit,
& '_naupd: Number of update iterations taken')
call ivout (logfil, 1, np, ndigit,
& '_naupd: Number of wanted "converged" Ritz values')
call cvout (logfil, np, workl(ritz), ndigit,
& '_naupd: The final Ritz values')
call cvout (logfil, np, workl(bounds), ndigit,
& '_naupd: Associated Ritz estimates')
end if
c
call second (t1)
tcaupd = t1 - t0
c
if (msglvl .gt. 0) then
c
c %--------------------------------------------------------%
c | Version Number & Version Date are defined in version.h |
c %--------------------------------------------------------%
c
write (6,1000)
write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt,
& tmvopx, tmvbx, tcaupd, tcaup2, tcaitr, titref,
& tgetv0, tceigh, tcgets, tcapps, tcconv, trvec
1000 format (//,
& 5x, '=============================================',/
& 5x, '= Complex implicit Arnoldi update code =',/
& 5x, '= Version Number: ', ' 2.3', 21x, ' =',/
& 5x, '= Version Date: ', ' 07/31/96', 16x, ' =',/
& 5x, '=============================================',/
& 5x, '= Summary of timing statistics =',/
& 5x, '=============================================',//)
1100 format (
& 5x, 'Total number update iterations = ', i5,/
& 5x, 'Total number of OP*x operations = ', i5,/
& 5x, 'Total number of B*x operations = ', i5,/
& 5x, 'Total number of reorthogonalization steps = ', i5,/
& 5x, 'Total number of iterative refinement steps = ', i5,/
& 5x, 'Total number of restart steps = ', i5,/
& 5x, 'Total time in user OP*x operation = ', f12.6,/
& 5x, 'Total time in user B*x operation = ', f12.6,/
& 5x, 'Total time in Arnoldi update routine = ', f12.6,/
& 5x, 'Total time in naup2 routine = ', f12.6,/
& 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/
& 5x, 'Total time in reorthogonalization phase = ', f12.6,/
& 5x, 'Total time in (re)start vector generation = ', f12.6,/
& 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/
& 5x, 'Total time in getting the shifts = ', f12.6,/
& 5x, 'Total time in applying the shifts = ', f12.6,/
& 5x, 'Total time in convergence testing = ', f12.6,/
& 5x, 'Total time in computing final Ritz vectors = ', f12.6/)
end if
c
9000 continue
c
return
c
c %---------------%
c | End of cnaupd |
c %---------------%
c
end

257
arpack/ARPACK/SRC/cneigh.f Normal file
View File

@@ -0,0 +1,257 @@
c\BeginDoc
c
c\Name: cneigh
c
c\Description:
c Compute the eigenvalues of the current upper Hessenberg matrix
c and the corresponding Ritz estimates given the current residual norm.
c
c\Usage:
c call cneigh
c ( RNORM, N, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, RWORK, IERR )
c
c\Arguments
c RNORM Real scalar. (INPUT)
c Residual norm corresponding to the current upper Hessenberg
c matrix H.
c
c N Integer. (INPUT)
c Size of the matrix H.
c
c H Complex N by N array. (INPUT)
c H contains the current upper Hessenberg matrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RITZ Complex array of length N. (OUTPUT)
c On output, RITZ(1:N) contains the eigenvalues of H.
c
c BOUNDS Complex array of length N. (OUTPUT)
c On output, BOUNDS contains the Ritz estimates associated with
c the eigenvalues held in RITZ. This is equal to RNORM
c times the last components of the eigenvectors corresponding
c to the eigenvalues in RITZ.
c
c Q Complex N by N array. (WORKSPACE)
c Workspace needed to store the eigenvectors of H.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Complex work array of length N**2 + 3*N. (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. This is needed to keep the full Schur form
c of H and also in the calculation of the eigenvectors of H.
c
c RWORK Real work array of length N (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c IERR Integer. (OUTPUT)
c Error exit flag from clahqr or ctrevc.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex
c
c\Routines called:
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c cmout ARPACK utility routine that prints matrices
c cvout ARPACK utility routine that prints vectors.
c svout ARPACK utility routine that prints vectors.
c clacpy LAPACK matrix copy routine.
c clahqr LAPACK routine to compute the Schur form of an
c upper Hessenberg matrix.
c claset LAPACK matrix initialization routine.
c ctrevc LAPACK routine to compute the eigenvectors of a matrix
c in upper triangular form
c ccopy Level 1 BLAS that copies one vector to another.
c csscal Level 1 BLAS that scales a complex vector by a real number.
c scnrm2 Level 1 BLAS that computes the norm of a vector.
c
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: neigh.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2
c
c\Remarks
c None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine cneigh (rnorm, n, h, ldh, ritz, bounds,
& q, ldq, workl, rwork, ierr)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer ierr, n, ldh, ldq
Real
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Complex
& bounds(n), h(ldh,n), q(ldq,n), ritz(n),
& workl(n*(n+3))
Real
& rwork(n)
c
c %------------%
c | Parameters |
c %------------%
c
Complex
& one, zero
Real
& rone
parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0),
& rone = 1.0E+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
logical select(1)
integer j, msglvl
Complex
& vl(1)
Real
& temp
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external clacpy, clahqr, ctrevc, ccopy,
& csscal, cmout, cvout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& scnrm2
external scnrm2
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mceigh
c
if (msglvl .gt. 2) then
call cmout (logfil, n, n, h, ldh, ndigit,
& '_neigh: Entering upper Hessenberg matrix H ')
end if
c
c %----------------------------------------------------------%
c | 1. Compute the eigenvalues, the last components of the |
c | corresponding Schur vectors and the full Schur form T |
c | of the current upper Hessenberg matrix H. |
c | clahqr returns the full Schur form of H |
c | in WORKL(1:N**2), and the Schur vectors in q. |
c %----------------------------------------------------------%
c
call clacpy ('All', n, n, h, ldh, workl, n)
call claset ('All', n, n, zero, one, q, ldq)
call clahqr (.true., .true., n, 1, n, workl, ldh, ritz,
& 1, n, q, ldq, ierr)
if (ierr .ne. 0) go to 9000
c
call ccopy (n, q(n-1,1), ldq, bounds, 1)
if (msglvl .gt. 1) then
call cvout (logfil, n, bounds, ndigit,
& '_neigh: last row of the Schur matrix for H')
end if
c
c %----------------------------------------------------------%
c | 2. Compute the eigenvectors of the full Schur form T and |
c | apply the Schur vectors to get the corresponding |
c | eigenvectors. |
c %----------------------------------------------------------%
c
call ctrevc ('Right', 'Back', select, n, workl, n, vl, n, q,
& ldq, n, n, workl(n*n+1), rwork, ierr)
c
if (ierr .ne. 0) go to 9000
c
c %------------------------------------------------%
c | Scale the returning eigenvectors so that their |
c | Euclidean norms are all one. LAPACK subroutine |
c | ctrevc returns each eigenvector normalized so |
c | that the element of largest magnitude has |
c | magnitude 1; here the magnitude of a complex |
c | number (x,y) is taken to be |x| + |y|. |
c %------------------------------------------------%
c
do 10 j=1, n
temp = scnrm2( n, q(1,j), 1 )
call csscal ( n, rone / temp, q(1,j), 1 )
10 continue
c
if (msglvl .gt. 1) then
call ccopy(n, q(n,1), ldq, workl, 1)
call cvout (logfil, n, workl, ndigit,
& '_neigh: Last row of the eigenvector matrix for H')
end if
c
c %----------------------------%
c | Compute the Ritz estimates |
c %----------------------------%
c
call ccopy(n, q(n,1), n, bounds, 1)
call csscal(n, rnorm, bounds, 1)
c
if (msglvl .gt. 2) then
call cvout (logfil, n, ritz, ndigit,
& '_neigh: The eigenvalues of H')
call cvout (logfil, n, bounds, ndigit,
& '_neigh: Ritz estimates for the eigenvalues of H')
end if
c
call second(t1)
tceigh = tceigh + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of cneigh |
c %---------------%
c
end

872
arpack/ARPACK/SRC/cneupd.f Normal file
View File

@@ -0,0 +1,872 @@
c\BeginDoc
c
c\Name: cneupd
c
c\Description:
c This subroutine returns the converged approximations to eigenvalues
c of A*z = lambda*B*z and (optionally):
c
c (1) The corresponding approximate eigenvectors;
c
c (2) An orthonormal basis for the associated approximate
c invariant subspace;
c
c (3) Both.
c
c There is negligible additional cost to obtain eigenvectors. An orthonormal
c basis is always computed. There is an additional storage cost of n*nev
c if both are requested (in this case a separate array Z must be supplied).
c
c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z
c are derived from approximate eigenvalues and eigenvectors of
c of the linear operator OP prescribed by the MODE selection in the
c call to CNAUPD. CNAUPD must be called before this routine is called.
c These approximate eigenvalues and vectors are commonly called Ritz
c values and Ritz vectors respectively. They are referred to as such
c in the comments that follow. The computed orthonormal basis for the
c invariant subspace corresponding to these Ritz values is referred to as a
c Schur basis.
c
c The definition of OP as well as other terms and the relation of computed
c Ritz values and vectors of OP with respect to the given problem
c A*z = lambda*B*z may be found in the header of CNAUPD. For a brief
c description, see definitions of IPARAM(7), MODE and WHICH in the
c documentation of CNAUPD.
c
c\Usage:
c call cneupd
c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, WORKEV, BMAT,
c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD,
c WORKL, LWORKL, RWORK, INFO )
c
c\Arguments:
c RVEC LOGICAL (INPUT)
c Specifies whether a basis for the invariant subspace corresponding
c to the converged Ritz value approximations for the eigenproblem
c A*z = lambda*B*z is computed.
c
c RVEC = .FALSE. Compute Ritz values only.
c
c RVEC = .TRUE. Compute Ritz vectors or Schur vectors.
c See Remarks below.
c
c HOWMNY Character*1 (INPUT)
c Specifies the form of the basis for the invariant subspace
c corresponding to the converged Ritz values that is to be computed.
c
c = 'A': Compute NEV Ritz vectors;
c = 'P': Compute NEV Schur vectors;
c = 'S': compute some of the Ritz vectors, specified
c by the logical array SELECT.
c
c SELECT Logical array of dimension NCV. (INPUT)
c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be
c computed. To select the Ritz vector corresponding to a
c Ritz value D(j), SELECT(j) must be set to .TRUE..
c If HOWMNY = 'A' or 'P', SELECT need not be initialized
c but it is used as internal workspace.
c
c D Complex array of dimension NEV+1. (OUTPUT)
c On exit, D contains the Ritz approximations
c to the eigenvalues lambda for A*z = lambda*B*z.
c
c Z Complex N by NEV array (OUTPUT)
c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of
c Z represents approximate eigenvectors (Ritz vectors) corresponding
c to the NCONV=IPARAM(5) Ritz values for eigensystem
c A*z = lambda*B*z.
c
c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED.
c
c NOTE: If if RVEC = .TRUE. and a Schur basis is not required,
c the array Z may be set equal to first NEV+1 columns of the Arnoldi
c basis array V computed by CNAUPD. In this case the Arnoldi basis
c will be destroyed and overwritten with the eigenvector basis.
c
c LDZ Integer. (INPUT)
c The leading dimension of the array Z. If Ritz vectors are
c desired, then LDZ .ge. max( 1, N ) is required.
c In any case, LDZ .ge. 1 is required.
c
c SIGMA Complex (INPUT)
c If IPARAM(7) = 3 then SIGMA represents the shift.
c Not referenced if IPARAM(7) = 1 or 2.
c
c WORKEV Complex work array of dimension 2*NCV. (WORKSPACE)
c
c **** The remaining arguments MUST be the same as for the ****
c **** call to CNAUPD that was just completed. ****
c
c NOTE: The remaining arguments
c
c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR,
c WORKD, WORKL, LWORKL, RWORK, INFO
c
c must be passed directly to CNEUPD following the last call
c to CNAUPD. These arguments MUST NOT BE MODIFIED between
c the the last call to CNAUPD and the call to CNEUPD.
c
c Three of these parameters (V, WORKL and INFO) are also output parameters:
c
c V Complex N by NCV array. (INPUT/OUTPUT)
c
c Upon INPUT: the NCV columns of V contain the Arnoldi basis
c vectors for OP as constructed by CNAUPD .
c
c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns
c contain approximate Schur vectors that span the
c desired invariant subspace.
c
c NOTE: If the array Z has been set equal to first NEV+1 columns
c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the
c Arnoldi basis held by V has been overwritten by the desired
c Ritz vectors. If a separate array Z has been passed then
c the first NCONV=IPARAM(5) columns of V will contain approximate
c Schur vectors that span the desired invariant subspace.
c
c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE)
c WORKL(1:ncv*ncv+2*ncv) contains information obtained in
c cnaupd. They are not changed by cneupd.
c WORKL(ncv*ncv+2*ncv+1:3*ncv*ncv+4*ncv) holds the
c untransformed Ritz values, the untransformed error estimates of
c the Ritz values, the upper triangular matrix for H, and the
c associated matrix representation of the invariant subspace for H.
c
c Note: IPNTR(9:13) contains the pointer into WORKL for addresses
c of the above information computed by cneupd.
c -------------------------------------------------------------
c IPNTR(9): pointer to the NCV RITZ values of the
c original system.
c IPNTR(10): Not used
c IPNTR(11): pointer to the NCV corresponding error estimates.
c IPNTR(12): pointer to the NCV by NCV upper triangular
c Schur matrix for H.
c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors
c of the upper Hessenberg matrix H. Only referenced by
c cneupd if RVEC = .TRUE. See Remark 2 below.
c -------------------------------------------------------------
c
c INFO Integer. (OUTPUT)
c Error flag on output.
c = 0: Normal exit.
c
c = 1: The Schur form computed by LAPACK routine csheqr
c could not be reordered by LAPACK routine ctrsen.
c Re-enter subroutine cneupd with IPARAM(5)=NCV and
c increase the size of the array D to have
c dimension at least dimension NCV and allocate at least NCV
c columns for Z. NOTE: Not necessary if Z and V share
c the same space. Please notify the authors if this error
c occurs.
c
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV-NEV >= 1 and less than or equal to N.
c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work WORKL array is not sufficient.
c = -8: Error return from LAPACK eigenvalue calculation.
c This should never happened.
c = -9: Error return from calculation of eigenvectors.
c Informational error from LAPACK routine ctrevc.
c = -10: IPARAM(7) must be 1,2,3
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.
c = -12: HOWMNY = 'S' not yet implemented
c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true.
c = -14: CNAUPD did not find any eigenvalues to sufficient
c accuracy.
c = -15: CNEUPD got a different count of the number of converged
c Ritz values than CNAUPD got. This indicates the user
c probably made an error in passing data from CNAUPD to
c CNEUPD or that the data was modified before entering
c CNEUPD
c
c\BeginLib
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B. Nour-Omid, B. N. Parlett, T. Ericsson and P. S. Jensen,
c "How to Implement the Spectral Transformation", Math Comp.,
c Vol. 48, No. 178, April, 1987 pp. 664-673.
c
c\Routines called:
c ivout ARPACK utility routine that prints integers.
c cmout ARPACK utility routine that prints matrices
c cvout ARPACK utility routine that prints vectors.
c cgeqr2 LAPACK routine that computes the QR factorization of
c a matrix.
c clacpy LAPACK matrix copy routine.
c clahqr LAPACK routine that computes the Schur form of a
c upper Hessenberg matrix.
c claset LAPACK matrix initialization routine.
c ctrevc LAPACK routine to compute the eigenvectors of a matrix
c in upper triangular form.
c ctrsen LAPACK routine that re-orders the Schur form.
c cunm2r LAPACK routine that applies an orthogonal matrix in
c factored form.
c slamch LAPACK routine that determines machine constants.
c ctrmm Level 3 BLAS matrix times an upper triangular matrix.
c cgeru Level 2 BLAS rank one update to a matrix.
c ccopy Level 1 BLAS that copies one vector to another .
c cscal Level 1 BLAS that scales a vector.
c csscal Level 1 BLAS that scales a complex vector by a real number.
c scnrm2 Level 1 BLAS that computes the norm of a complex vector.
c
c\Remarks
c
c 1. Currently only HOWMNY = 'A' and 'P' are implemented.
c
c 2. Schur vectors are an orthogonal representation for the basis of
c Ritz vectors. Thus, their numerical properties are often superior.
c If RVEC = .true. then the relationship
c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and
c transpose( V(:,1:IPARAM(5)) ) * V(:,1:IPARAM(5)) = I
c are approximately satisfied.
c Here T is the leading submatrix of order IPARAM(5) of the
c upper triangular matrix stored workl(ipntr(12)).
c
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Chao Yang Houston, Texas
c Dept. of Computational &
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: neupd.F SID: 2.8 DATE OF SID: 07/21/02 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
subroutine cneupd(rvec , howmny, select, d ,
& z , ldz , sigma , workev,
& bmat , n , which , nev ,
& tol , resid , ncv , v ,
& ldv , iparam, ipntr , workd ,
& workl, lworkl, rwork , info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat, howmny, which*2
logical rvec
integer info, ldz, ldv, lworkl, n, ncv, nev
Complex
& sigma
Real
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(11), ipntr(14)
logical select(ncv)
Real
& rwork(ncv)
Complex
& d(nev) , resid(n) , v(ldv,ncv),
& z(ldz, nev),
& workd(3*n) , workl(lworkl), workev(2*ncv)
c
c %------------%
c | Parameters |
c %------------%
c
Complex
& one, zero
parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0))
c
c %---------------%
c | Local Scalars |
c %---------------%
c
character type*6
integer bounds, ierr , ih , ihbds, iheig , nconv ,
& invsub, iuptri, iwev , j , ldh , ldq ,
& mode , msglvl, ritz , wr , k , irz ,
& ibd , outncv, iq , np , numcnv, jj ,
& ishift
Complex
& rnorm, temp, vl(1)
Real
& conds, sep, rtemp, eps23
logical reord
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external ccopy , cgeru, cgeqr2, clacpy, cmout,
& cunm2r, ctrmm, cvout, ivout,
& clahqr
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& scnrm2, slamch, slapy2
external scnrm2, slamch, slapy2
c
Complex
& cdotc
external cdotc
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
msglvl = mceupd
mode = iparam(7)
nconv = iparam(5)
info = 0
c
c
c %---------------------------------%
c | Get machine dependent constant. |
c %---------------------------------%
c
eps23 = slamch('Epsilon-Machine')
eps23 = eps23**(2.0E+0 / 3.0E+0)
c
c %-------------------------------%
c | Quick return |
c | Check for incompatible input |
c %-------------------------------%
c
ierr = 0
c
if (nconv .le. 0) then
ierr = -14
else if (n .le. 0) then
ierr = -1
else if (nev .le. 0) then
ierr = -2
else if (ncv .le. nev .or. ncv .gt. n) then
ierr = -3
else if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LR' .and.
& which .ne. 'SR' .and.
& which .ne. 'LI' .and.
& which .ne. 'SI') then
ierr = -5
else if (bmat .ne. 'I' .and. bmat .ne. 'G') then
ierr = -6
else if (lworkl .lt. 3*ncv**2 + 4*ncv) then
ierr = -7
else if ( (howmny .ne. 'A' .and.
& howmny .ne. 'P' .and.
& howmny .ne. 'S') .and. rvec ) then
ierr = -13
else if (howmny .eq. 'S' ) then
ierr = -12
end if
c
if (mode .eq. 1 .or. mode .eq. 2) then
type = 'REGULR'
else if (mode .eq. 3 ) then
type = 'SHIFTI'
else
ierr = -10
end if
if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
go to 9000
end if
c
c %--------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, WORKEV, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:ncv*ncv) := generated Hessenberg matrix |
c | workl(ncv*ncv+1:ncv*ncv+ncv) := ritz values |
c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds |
c %--------------------------------------------------------%
c
c %-----------------------------------------------------------%
c | The following is used and set by CNEUPD. |
c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := The untransformed |
c | Ritz values. |
c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed |
c | error bounds of |
c | the Ritz values |
c | workl(ncv*ncv+4*ncv+1:2*ncv*ncv+4*ncv) := Holds the upper |
c | triangular matrix |
c | for H. |
c | workl(2*ncv*ncv+4*ncv+1: 3*ncv*ncv+4*ncv) := Holds the |
c | associated matrix |
c | representation of |
c | the invariant |
c | subspace for H. |
c | GRAND total of NCV * ( 3 * NCV + 4 ) locations. |
c %-----------------------------------------------------------%
c
ih = ipntr(5)
ritz = ipntr(6)
iq = ipntr(7)
bounds = ipntr(8)
ldh = ncv
ldq = ncv
iheig = bounds + ldh
ihbds = iheig + ldh
iuptri = ihbds + ldh
invsub = iuptri + ldh*ncv
ipntr(9) = iheig
ipntr(11) = ihbds
ipntr(12) = iuptri
ipntr(13) = invsub
wr = 1
iwev = wr + ncv
c
c %-----------------------------------------%
c | irz points to the Ritz values computed |
c | by _neigh before exiting _naup2. |
c | ibd points to the Ritz estimates |
c | computed by _neigh before exiting |
c | _naup2. |
c %-----------------------------------------%
c
irz = ipntr(14) + ncv*ncv
ibd = irz + ncv
c
c %------------------------------------%
c | RNORM is B-norm of the RESID(1:N). |
c %------------------------------------%
c
rnorm = workl(ih+2)
workl(ih+2) = zero
c
if (msglvl .gt. 2) then
call cvout(logfil, ncv, workl(irz), ndigit,
& '_neupd: Ritz values passed in from _NAUPD.')
call cvout(logfil, ncv, workl(ibd), ndigit,
& '_neupd: Ritz estimates passed in from _NAUPD.')
end if
c
if (rvec) then
c
reord = .false.
c
c %---------------------------------------------------%
c | Use the temporary bounds array to store indices |
c | These will be used to mark the select array later |
c %---------------------------------------------------%
c
do 10 j = 1,ncv
workl(bounds+j-1) = j
select(j) = .false.
10 continue
c
c %-------------------------------------%
c | Select the wanted Ritz values. |
c | Sort the Ritz values so that the |
c | wanted ones appear at the tailing |
c | NEV positions of workl(irr) and |
c | workl(iri). Move the corresponding |
c | error estimates in workl(ibd) |
c | accordingly. |
c %-------------------------------------%
c
np = ncv - nev
ishift = 0
call cngets(ishift, which , nev ,
& np , workl(irz), workl(bounds))
c
if (msglvl .gt. 2) then
call cvout (logfil, ncv, workl(irz), ndigit,
& '_neupd: Ritz values after calling _NGETS.')
call cvout (logfil, ncv, workl(bounds), ndigit,
& '_neupd: Ritz value indices after calling _NGETS.')
end if
c
c %-----------------------------------------------------%
c | Record indices of the converged wanted Ritz values |
c | Mark the select array for possible reordering |
c %-----------------------------------------------------%
c
numcnv = 0
do 11 j = 1,ncv
rtemp = max(eps23,
& slapy2 ( real(workl(irz+ncv-j)),
& aimag(workl(irz+ncv-j)) ))
jj = workl(bounds + ncv - j)
if (numcnv .lt. nconv .and.
& slapy2( real(workl(ibd+jj-1)),
& aimag(workl(ibd+jj-1)) )
& .le. tol*rtemp) then
select(jj) = .true.
numcnv = numcnv + 1
if (jj .gt. nev) reord = .true.
endif
11 continue
c
c %-----------------------------------------------------------%
c | Check the count (numcnv) of converged Ritz values with |
c | the number (nconv) reported by dnaupd. If these two |
c | are different then there has probably been an error |
c | caused by incorrect passing of the dnaupd data. |
c %-----------------------------------------------------------%
c
if (msglvl .gt. 2) then
call ivout(logfil, 1, numcnv, ndigit,
& '_neupd: Number of specified eigenvalues')
call ivout(logfil, 1, nconv, ndigit,
& '_neupd: Number of "converged" eigenvalues')
end if
c
if (numcnv .ne. nconv) then
info = -15
go to 9000
end if
c
c %-------------------------------------------------------%
c | Call LAPACK routine clahqr to compute the Schur form |
c | of the upper Hessenberg matrix returned by CNAUPD. |
c | Make a copy of the upper Hessenberg matrix. |
c | Initialize the Schur vector matrix Q to the identity. |
c %-------------------------------------------------------%
c
call ccopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1)
call claset('All', ncv, ncv ,
& zero , one, workl(invsub),
& ldq)
call clahqr(.true., .true. , ncv ,
& 1 , ncv , workl(iuptri),
& ldh , workl(iheig) , 1 ,
& ncv , workl(invsub), ldq ,
& ierr)
call ccopy(ncv , workl(invsub+ncv-1), ldq,
& workl(ihbds), 1)
c
if (ierr .ne. 0) then
info = -8
go to 9000
end if
c
if (msglvl .gt. 1) then
call cvout (logfil, ncv, workl(iheig), ndigit,
& '_neupd: Eigenvalues of H')
call cvout (logfil, ncv, workl(ihbds), ndigit,
& '_neupd: Last row of the Schur vector matrix')
if (msglvl .gt. 3) then
call cmout (logfil , ncv, ncv ,
& workl(iuptri), ldh, ndigit,
& '_neupd: The upper triangular matrix ')
end if
end if
c
if (reord) then
c
c %-----------------------------------------------%
c | Reorder the computed upper triangular matrix. |
c %-----------------------------------------------%
c
call ctrsen('None' , 'V' , select ,
& ncv , workl(iuptri), ldh ,
& workl(invsub), ldq , workl(iheig),
& nconv , conds , sep ,
& workev , ncv , ierr)
c
if (ierr .eq. 1) then
info = 1
go to 9000
end if
c
if (msglvl .gt. 2) then
call cvout (logfil, ncv, workl(iheig), ndigit,
& '_neupd: Eigenvalues of H--reordered')
if (msglvl .gt. 3) then
call cmout(logfil , ncv, ncv ,
& workl(iuptri), ldq, ndigit,
& '_neupd: Triangular matrix after re-ordering')
end if
end if
c
end if
c
c %---------------------------------------------%
c | Copy the last row of the Schur basis matrix |
c | to workl(ihbds). This vector will be used |
c | to compute the Ritz estimates of converged |
c | Ritz values. |
c %---------------------------------------------%
c
call ccopy(ncv , workl(invsub+ncv-1), ldq,
& workl(ihbds), 1)
c
c %--------------------------------------------%
c | Place the computed eigenvalues of H into D |
c | if a spectral transformation was not used. |
c %--------------------------------------------%
c
if (type .eq. 'REGULR') then
call ccopy(nconv, workl(iheig), 1, d, 1)
end if
c
c %----------------------------------------------------------%
c | Compute the QR factorization of the matrix representing |
c | the wanted invariant subspace located in the first NCONV |
c | columns of workl(invsub,ldq). |
c %----------------------------------------------------------%
c
call cgeqr2(ncv , nconv , workl(invsub),
& ldq , workev, workev(ncv+1),
& ierr)
c
c %--------------------------------------------------------%
c | * Postmultiply V by Q using cunm2r. |
c | * Copy the first NCONV columns of VQ into Z. |
c | * Postmultiply Z by R. |
c | The N by NCONV matrix Z is now a matrix representation |
c | of the approximate invariant subspace associated with |
c | the Ritz values in workl(iheig). The first NCONV |
c | columns of V are now approximate Schur vectors |
c | associated with the upper triangular matrix of order |
c | NCONV in workl(iuptri). |
c %--------------------------------------------------------%
c
call cunm2r('Right', 'Notranspose', n ,
& ncv , nconv , workl(invsub),
& ldq , workev , v ,
& ldv , workd(n+1) , ierr)
call clacpy('All', n, nconv, v, ldv, z, ldz)
c
do 20 j=1, nconv
c
c %---------------------------------------------------%
c | Perform both a column and row scaling if the |
c | diagonal element of workl(invsub,ldq) is negative |
c | I'm lazy and don't take advantage of the upper |
c | triangular form of workl(iuptri,ldq). |
c | Note that since Q is orthogonal, R is a diagonal |
c | matrix consisting of plus or minus ones. |
c %---------------------------------------------------%
c
if ( real( workl(invsub+(j-1)*ldq+j-1) ) .lt.
& real(zero) ) then
call cscal(nconv, -one, workl(iuptri+j-1), ldq)
call cscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1)
end if
c
20 continue
c
if (howmny .eq. 'A') then
c
c %--------------------------------------------%
c | Compute the NCONV wanted eigenvectors of T |
c | located in workl(iuptri,ldq). |
c %--------------------------------------------%
c
do 30 j=1, ncv
if (j .le. nconv) then
select(j) = .true.
else
select(j) = .false.
end if
30 continue
c
call ctrevc('Right', 'Select' , select ,
& ncv , workl(iuptri), ldq ,
& vl , 1 , workl(invsub),
& ldq , ncv , outncv ,
& workev , rwork , ierr)
c
if (ierr .ne. 0) then
info = -9
go to 9000
end if
c
c %------------------------------------------------%
c | Scale the returning eigenvectors so that their |
c | Euclidean norms are all one. LAPACK subroutine |
c | ctrevc returns each eigenvector normalized so |
c | that the element of largest magnitude has |
c | magnitude 1. |
c %------------------------------------------------%
c
do 40 j=1, nconv
rtemp = scnrm2(ncv, workl(invsub+(j-1)*ldq), 1)
rtemp = real(one) / rtemp
call csscal ( ncv, rtemp,
& workl(invsub+(j-1)*ldq), 1 )
c
c %------------------------------------------%
c | Ritz estimates can be obtained by taking |
c | the inner product of the last row of the |
c | Schur basis of H with eigenvectors of T. |
c | Note that the eigenvector matrix of T is |
c | upper triangular, thus the length of the |
c | inner product can be set to j. |
c %------------------------------------------%
c
workev(j) = cdotc(j, workl(ihbds), 1,
& workl(invsub+(j-1)*ldq), 1)
40 continue
c
if (msglvl .gt. 2) then
call ccopy(nconv, workl(invsub+ncv-1), ldq,
& workl(ihbds), 1)
call cvout (logfil, nconv, workl(ihbds), ndigit,
& '_neupd: Last row of the eigenvector matrix for T')
if (msglvl .gt. 3) then
call cmout(logfil , ncv, ncv ,
& workl(invsub), ldq, ndigit,
& '_neupd: The eigenvector matrix for T')
end if
end if
c
c %---------------------------------------%
c | Copy Ritz estimates into workl(ihbds) |
c %---------------------------------------%
c
call ccopy(nconv, workev, 1, workl(ihbds), 1)
c
c %----------------------------------------------%
c | The eigenvector matrix Q of T is triangular. |
c | Form Z*Q. |
c %----------------------------------------------%
c
call ctrmm('Right' , 'Upper' , 'No transpose',
& 'Non-unit', n , nconv ,
& one , workl(invsub), ldq ,
& z , ldz)
end if
c
else
c
c %--------------------------------------------------%
c | An approximate invariant subspace is not needed. |
c | Place the Ritz values computed CNAUPD into D. |
c %--------------------------------------------------%
c
call ccopy(nconv, workl(ritz), 1, d, 1)
call ccopy(nconv, workl(ritz), 1, workl(iheig), 1)
call ccopy(nconv, workl(bounds), 1, workl(ihbds), 1)
c
end if
c
c %------------------------------------------------%
c | Transform the Ritz values and possibly vectors |
c | and corresponding error bounds of OP to those |
c | of A*x = lambda*B*x. |
c %------------------------------------------------%
c
if (type .eq. 'REGULR') then
c
if (rvec)
& call cscal(ncv, rnorm, workl(ihbds), 1)
c
else
c
c %---------------------------------------%
c | A spectral transformation was used. |
c | * Determine the Ritz estimates of the |
c | Ritz values in the original system. |
c %---------------------------------------%
c
if (rvec)
& call cscal(ncv, rnorm, workl(ihbds), 1)
c
do 50 k=1, ncv
temp = workl(iheig+k-1)
workl(ihbds+k-1) = workl(ihbds+k-1) / temp / temp
50 continue
c
end if
c
c %-----------------------------------------------------------%
c | * Transform the Ritz values back to the original system. |
c | For TYPE = 'SHIFTI' the transformation is |
c | lambda = 1/theta + sigma |
c | NOTES: |
c | *The Ritz vectors are not affected by the transformation. |
c %-----------------------------------------------------------%
c
if (type .eq. 'SHIFTI') then
do 60 k=1, nconv
d(k) = one / workl(iheig+k-1) + sigma
60 continue
end if
c
if (type .ne. 'REGULR' .and. msglvl .gt. 1) then
call cvout (logfil, nconv, d, ndigit,
& '_neupd: Untransformed Ritz values.')
call cvout (logfil, nconv, workl(ihbds), ndigit,
& '_neupd: Ritz estimates of the untransformed Ritz values.')
else if ( msglvl .gt. 1) then
call cvout (logfil, nconv, d, ndigit,
& '_neupd: Converged Ritz values.')
call cvout (logfil, nconv, workl(ihbds), ndigit,
& '_neupd: Associated Ritz estimates.')
end if
c
c %-------------------------------------------------%
c | Eigenvector Purification step. Formally perform |
c | one of inverse subspace iteration. Only used |
c | for MODE = 3. See reference 3. |
c %-------------------------------------------------%
c
if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then
c
c %------------------------------------------------%
c | Purify the computed Ritz vectors by adding a |
c | little bit of the residual vector: |
c | T |
c | resid(:)*( e s ) / theta |
c | NCV |
c | where H s = s theta. |
c %------------------------------------------------%
c
do 100 j=1, nconv
if (workl(iheig+j-1) .ne. zero) then
workev(j) = workl(invsub+(j-1)*ldq+ncv-1) /
& workl(iheig+j-1)
endif
100 continue
c %---------------------------------------%
c | Perform a rank one update to Z and |
c | purify all the Ritz vectors together. |
c %---------------------------------------%
c
call cgeru (n, nconv, one, resid, 1, workev, 1, z, ldz)
c
end if
c
9000 continue
c
return
c
c %---------------%
c | End of cneupd|
c %---------------%
c
end

178
arpack/ARPACK/SRC/cngets.f Normal file
View File

@@ -0,0 +1,178 @@
c\BeginDoc
c
c\Name: cngets
c
c\Description:
c Given the eigenvalues of the upper Hessenberg matrix H,
c computes the NP shifts AMU that are zeros of the polynomial of
c degree NP which filters out components of the unwanted eigenvectors
c corresponding to the AMU's based on some given criteria.
c
c NOTE: call this even in the case of user specified shifts in order
c to sort the eigenvalues, and error bounds of H for later use.
c
c\Usage:
c call cngets
c ( ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS )
c
c\Arguments
c ISHIFT Integer. (INPUT)
c Method for selecting the implicit shifts at each iteration.
c ISHIFT = 0: user specified shifts
c ISHIFT = 1: exact shift with respect to the matrix H.
c
c WHICH Character*2. (INPUT)
c Shift selection criteria.
c 'LM' -> want the KEV eigenvalues of largest magnitude.
c 'SM' -> want the KEV eigenvalues of smallest magnitude.
c 'LR' -> want the KEV eigenvalues of largest REAL part.
c 'SR' -> want the KEV eigenvalues of smallest REAL part.
c 'LI' -> want the KEV eigenvalues of largest imaginary part.
c 'SI' -> want the KEV eigenvalues of smallest imaginary part.
c
c KEV Integer. (INPUT)
c The number of desired eigenvalues.
c
c NP Integer. (INPUT)
c The number of shifts to compute.
c
c RITZ Complex array of length KEV+NP. (INPUT/OUTPUT)
c On INPUT, RITZ contains the the eigenvalues of H.
c On OUTPUT, RITZ are sorted so that the unwanted
c eigenvalues are in the first NP locations and the wanted
c portion is in the last KEV locations. When exact shifts are
c selected, the unwanted part corresponds to the shifts to
c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues
c are further sorted so that the ones with largest Ritz values
c are first.
c
c BOUNDS Complex array of length KEV+NP. (INPUT/OUTPUT)
c Error bounds corresponding to the ordering in RITZ.
c
c
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex
c
c\Routines called:
c csortc ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c cvout ARPACK utility routine that prints vectors.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: ngets.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2
c
c\Remarks
c 1. This routine does not keep complex conjugate pairs of
c eigenvalues together.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine cngets ( ishift, which, kev, np, ritz, bounds)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
integer ishift, kev, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Complex
& bounds(kev+np), ritz(kev+np)
c
c %------------%
c | Parameters |
c %------------%
c
Complex
& one, zero
parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0))
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer msglvl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external cvout, csortc, second
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mcgets
c
call csortc (which, .true., kev+np, ritz, bounds)
c
if ( ishift .eq. 1 ) then
c
c %-------------------------------------------------------%
c | Sort the unwanted Ritz values used as shifts so that |
c | the ones with largest Ritz estimates are first |
c | This will tend to minimize the effects of the |
c | forward instability of the iteration when the shifts |
c | are applied in subroutine cnapps. |
c | Be careful and use 'SM' since we want to sort BOUNDS! |
c %-------------------------------------------------------%
c
call csortc ( 'SM', .true., np, bounds, ritz )
c
end if
c
call second (t1)
tcgets = tcgets + (t1 - t0)
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, kev, ndigit, '_ngets: KEV is')
call ivout (logfil, 1, np, ndigit, '_ngets: NP is')
call cvout (logfil, kev+np, ritz, ndigit,
& '_ngets: Eigenvalues of current H matrix ')
call cvout (logfil, kev+np, bounds, ndigit,
& '_ngets: Ritz estimates of the current KEV+NP Ritz values')
end if
c
return
c
c %---------------%
c | End of cngets |
c %---------------%
c
end

322
arpack/ARPACK/SRC/csortc.f Normal file
View File

@@ -0,0 +1,322 @@
c\BeginDoc
c
c\Name: csortc
c
c\Description:
c Sorts the Complex array in X into the order
c specified by WHICH and optionally applies the permutation to the
c Real array Y.
c
c\Usage:
c call csortc
c ( WHICH, APPLY, N, X, Y )
c
c\Arguments
c WHICH Character*2. (Input)
c 'LM' -> sort X into increasing order of magnitude.
c 'SM' -> sort X into decreasing order of magnitude.
c 'LR' -> sort X with real(X) in increasing algebraic order
c 'SR' -> sort X with real(X) in decreasing algebraic order
c 'LI' -> sort X with imag(X) in increasing algebraic order
c 'SI' -> sort X with imag(X) in decreasing algebraic order
c
c APPLY Logical. (Input)
c APPLY = .TRUE. -> apply the sorted order to array Y.
c APPLY = .FALSE. -> do not apply the sorted order to array Y.
c
c N Integer. (INPUT)
c Size of the arrays.
c
c X Complex array of length N. (INPUT/OUTPUT)
c This is the array to be sorted.
c
c Y Complex array of length N. (INPUT/OUTPUT)
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Routines called:
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c Adapted from the sort routine in LANSO.
c
c\SCCS Information: @(#)
c FILE: sortc.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine csortc (which, apply, n, x, y)
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
logical apply
integer n
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Complex
& x(0:n-1), y(0:n-1)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, igap, j
Complex
& temp
Real
& temp1, temp2
c
c %--------------------%
c | External functions |
c %--------------------%
c
Real
& slapy2
c
c %--------------------%
c | Intrinsic Functions |
c %--------------------%
Intrinsic
& real, aimag
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
igap = n / 2
c
if (which .eq. 'LM') then
c
c %--------------------------------------------%
c | Sort X into increasing order of magnitude. |
c %--------------------------------------------%
c
10 continue
if (igap .eq. 0) go to 9000
c
do 30 i = igap, n-1
j = i-igap
20 continue
c
if (j.lt.0) go to 30
c
temp1 = slapy2(real(x(j)),aimag(x(j)))
temp2 = slapy2(real(x(j+igap)),aimag(x(j+igap)))
c
if (temp1.gt.temp2) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 30
end if
j = j-igap
go to 20
30 continue
igap = igap / 2
go to 10
c
else if (which .eq. 'SM') then
c
c %--------------------------------------------%
c | Sort X into decreasing order of magnitude. |
c %--------------------------------------------%
c
40 continue
if (igap .eq. 0) go to 9000
c
do 60 i = igap, n-1
j = i-igap
50 continue
c
if (j .lt. 0) go to 60
c
temp1 = slapy2(real(x(j)),aimag(x(j)))
temp2 = slapy2(real(x(j+igap)),aimag(x(j+igap)))
c
if (temp1.lt.temp2) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 60
endif
j = j-igap
go to 50
60 continue
igap = igap / 2
go to 40
c
else if (which .eq. 'LR') then
c
c %------------------------------------------------%
c | Sort XREAL into increasing order of algebraic. |
c %------------------------------------------------%
c
70 continue
if (igap .eq. 0) go to 9000
c
do 90 i = igap, n-1
j = i-igap
80 continue
c
if (j.lt.0) go to 90
c
if (real(x(j)).gt.real(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 90
endif
j = j-igap
go to 80
90 continue
igap = igap / 2
go to 70
c
else if (which .eq. 'SR') then
c
c %------------------------------------------------%
c | Sort XREAL into decreasing order of algebraic. |
c %------------------------------------------------%
c
100 continue
if (igap .eq. 0) go to 9000
do 120 i = igap, n-1
j = i-igap
110 continue
c
if (j.lt.0) go to 120
c
if (real(x(j)).lt.real(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 120
endif
j = j-igap
go to 110
120 continue
igap = igap / 2
go to 100
c
else if (which .eq. 'LI') then
c
c %--------------------------------------------%
c | Sort XIMAG into increasing algebraic order |
c %--------------------------------------------%
c
130 continue
if (igap .eq. 0) go to 9000
do 150 i = igap, n-1
j = i-igap
140 continue
c
if (j.lt.0) go to 150
c
if (aimag(x(j)).gt.aimag(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 150
endif
j = j-igap
go to 140
150 continue
igap = igap / 2
go to 130
c
else if (which .eq. 'SI') then
c
c %---------------------------------------------%
c | Sort XIMAG into decreasing algebraic order |
c %---------------------------------------------%
c
160 continue
if (igap .eq. 0) go to 9000
do 180 i = igap, n-1
j = i-igap
170 continue
c
if (j.lt.0) go to 180
c
if (aimag(x(j)).lt.aimag(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 180
endif
j = j-igap
go to 170
180 continue
igap = igap / 2
go to 160
end if
c
9000 continue
return
c
c %---------------%
c | End of csortc |
c %---------------%
c
end

View File

@@ -0,0 +1,51 @@
c
c\SCCS Information: @(#)
c FILE: statn.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2
c
c %---------------------------------------------%
c | Initialize statistic and timing information |
c | for complex nonsymmetric Arnoldi code. |
c %---------------------------------------------%
subroutine cstatn
c
c %--------------------------------%
c | See stat.doc for documentation |
c %--------------------------------%
c
include 'stat.h'
c %-----------------------%
c | Executable Statements |
c %-----------------------%
nopx = 0
nbx = 0
nrorth = 0
nitref = 0
nrstrt = 0
tcaupd = 0.0E+0
tcaup2 = 0.0E+0
tcaitr = 0.0E+0
tceigh = 0.0E+0
tcgets = 0.0E+0
tcapps = 0.0E+0
tcconv = 0.0E+0
titref = 0.0E+0
tgetv0 = 0.0E+0
trvec = 0.0E+0
c %----------------------------------------------------%
c | User time including reverse communication overhead |
c %----------------------------------------------------%
tmvopx = 0.0E+0
tmvbx = 0.0E+0
return
c
c %---------------%
c | End of cstatn |
c %---------------%
c
end

16
arpack/ARPACK/SRC/debug.h Normal file
View File

@@ -0,0 +1,16 @@
c
c\SCCS Information: @(#)
c FILE: debug.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2
c
c %---------------------------------%
c | See debug.doc for documentation |
c %---------------------------------%
integer logfil, ndigit, mgetv0,
& msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd,
& mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd,
& mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd
common /debug/
& logfil, ndigit, mgetv0,
& msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd,
& mnaupd, mnaup2, mnaitr, mneigh, mnapps, mngets, mneupd,
& mcaupd, mcaup2, mcaitr, mceigh, mcapps, mcgets, mceupd

419
arpack/ARPACK/SRC/dgetv0.f Normal file
View File

@@ -0,0 +1,419 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dgetv0
c
c\Description:
c Generate a random initial residual vector for the Arnoldi process.
c Force the residual vector to be in the range of the operator OP.
c
c\Usage:
c call dgetv0
c ( IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM,
c IPNTR, WORKD, IERR )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag. IDO must be zero on the first
c call to dgetv0.
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c This is for the initialization phase to force the
c starting vector into the range of OP.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c IDO = 99: done
c -------------------------------------------------------------
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B in the (generalized)
c eigenvalue problem A*x = lambda*B*x.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x
c
c ITRY Integer. (INPUT)
c ITRY counts the number of times that dgetv0 is called.
c It should be set to 1 on the initial call to dgetv0.
c
c INITV Logical variable. (INPUT)
c .TRUE. => the initial residual vector is given in RESID.
c .FALSE. => generate a random initial residual vector.
c
c N Integer. (INPUT)
c Dimension of the problem.
c
c J Integer. (INPUT)
c Index of the residual vector to be generated, with respect to
c the Arnoldi process. J > 1 in case of a "restart".
c
c V Double precision N by J array. (INPUT)
c The first J-1 columns of V contain the current Arnoldi basis
c if this is a "restart".
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c RESID Double precision array of length N. (INPUT/OUTPUT)
c Initial residual vector to be generated. If RESID is
c provided, force RESID into the range of the operator OP.
c
c RNORM Double precision scalar. (OUTPUT)
c B-norm of the generated residual.
c
c IPNTR Integer array of length 3. (OUTPUT)
c
c WORKD Double precision work array of length 2*N. (REVERSE COMMUNICATION).
c On exit, WORK(1:N) = B*RESID to be used in SSAITR.
c
c IERR Integer. (OUTPUT)
c = 0: Normal exit.
c = -1: Cannot generate a nontrivial restarted residual vector
c in the range of the operator OP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c second ARPACK utility routine for timing.
c dvout ARPACK utility routine for vector output.
c dlarnv LAPACK routine for generating a random vector.
c dgemv Level 2 BLAS routine for matrix vector multiplication.
c dcopy Level 1 BLAS that copies one vector to another.
c ddot Level 1 BLAS that computes the scalar product of two vectors.
c dnrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: getv0.F SID: 2.7 DATE OF SID: 04/07/99 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dgetv0
& ( ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm,
& ipntr, workd, ierr )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1
logical initv
integer ido, ierr, itry, j, ldv, n
Double precision
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Double precision
& resid(n), v(ldv,j), workd(2*n)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0, zero = 0.0D+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
logical first, inits, orth
integer idist, iseed(4), iter, msglvl, jj
Double precision
& rnorm0
save first, iseed, inits, iter, msglvl, orth, rnorm0
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dlarnv, dvout, dcopy, dgemv, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& ddot, dnrm2
external ddot, dnrm2
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic abs, sqrt
c
c %-----------------%
c | Data Statements |
c %-----------------%
c
data inits /.true./
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c
c %-----------------------------------%
c | Initialize the seed of the LAPACK |
c | random number generator |
c %-----------------------------------%
c
if (inits) then
iseed(1) = 1
iseed(2) = 3
iseed(3) = 5
iseed(4) = 7
inits = .false.
end if
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mgetv0
c
ierr = 0
iter = 0
first = .FALSE.
orth = .FALSE.
c
c %-----------------------------------------------------%
c | Possibly generate a random starting vector in RESID |
c | Use a LAPACK random number generator used by the |
c | matrix generation routines. |
c | idist = 1: uniform (0,1) distribution; |
c | idist = 2: uniform (-1,1) distribution; |
c | idist = 3: normal (0,1) distribution; |
c %-----------------------------------------------------%
c
if (.not.initv) then
idist = 2
call dlarnv (idist, iseed, n, resid)
end if
c
c %----------------------------------------------------------%
c | Force the starting vector into the range of OP to handle |
c | the generalized problem when B is possibly (singular). |
c %----------------------------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nopx = nopx + 1
ipntr(1) = 1
ipntr(2) = n + 1
call dcopy (n, resid, 1, workd, 1)
ido = -1
go to 9000
end if
end if
c
c %-----------------------------------------%
c | Back from computing OP*(initial-vector) |
c %-----------------------------------------%
c
if (first) go to 20
c
c %-----------------------------------------------%
c | Back from computing B*(orthogonalized-vector) |
c %-----------------------------------------------%
c
if (orth) go to 40
c
if (bmat .eq. 'G') then
call second (t3)
tmvopx = tmvopx + (t3 - t2)
end if
c
c %------------------------------------------------------%
c | Starting vector is now in the range of OP; r = OP*r; |
c | Compute B-norm of starting vector. |
c %------------------------------------------------------%
c
call second (t2)
first = .TRUE.
if (bmat .eq. 'G') then
nbx = nbx + 1
call dcopy (n, workd(n+1), 1, resid, 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
go to 9000
else if (bmat .eq. 'I') then
call dcopy (n, resid, 1, workd, 1)
end if
c
20 continue
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
first = .FALSE.
if (bmat .eq. 'G') then
rnorm0 = ddot (n, resid, 1, workd, 1)
rnorm0 = sqrt(abs(rnorm0))
else if (bmat .eq. 'I') then
rnorm0 = dnrm2(n, resid, 1)
end if
rnorm = rnorm0
c
c %---------------------------------------------%
c | Exit if this is the very first Arnoldi step |
c %---------------------------------------------%
c
if (j .eq. 1) go to 50
c
c %----------------------------------------------------------------
c | Otherwise need to B-orthogonalize the starting vector against |
c | the current Arnoldi basis using Gram-Schmidt with iter. ref. |
c | This is the case where an invariant subspace is encountered |
c | in the middle of the Arnoldi factorization. |
c | |
c | s = V^{T}*B*r; r = r - V*s; |
c | |
c | Stopping criteria used for iter. ref. is discussed in |
c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. |
c %---------------------------------------------------------------%
c
orth = .TRUE.
30 continue
c
call dgemv ('T', n, j-1, one, v, ldv, workd, 1,
& zero, workd(n+1), 1)
call dgemv ('N', n, j-1, -one, v, ldv, workd(n+1), 1,
& one, resid, 1)
c
c %----------------------------------------------------------%
c | Compute the B-norm of the orthogonalized starting vector |
c %----------------------------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call dcopy (n, resid, 1, workd(n+1), 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
go to 9000
else if (bmat .eq. 'I') then
call dcopy (n, resid, 1, workd, 1)
end if
c
40 continue
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
if (bmat .eq. 'G') then
rnorm = ddot (n, resid, 1, workd, 1)
rnorm = sqrt(abs(rnorm))
else if (bmat .eq. 'I') then
rnorm = dnrm2(n, resid, 1)
end if
c
c %--------------------------------------%
c | Check for further orthogonalization. |
c %--------------------------------------%
c
if (msglvl .gt. 2) then
call dvout (logfil, 1, rnorm0, ndigit,
& '_getv0: re-orthonalization ; rnorm0 is')
call dvout (logfil, 1, rnorm, ndigit,
& '_getv0: re-orthonalization ; rnorm is')
end if
c
if (rnorm .gt. 0.717*rnorm0) go to 50
c
iter = iter + 1
if (iter .le. 5) then
c
c %-----------------------------------%
c | Perform iterative refinement step |
c %-----------------------------------%
c
rnorm0 = rnorm
go to 30
else
c
c %------------------------------------%
c | Iterative refinement step "failed" |
c %------------------------------------%
c
do 45 jj = 1, n
resid(jj) = zero
45 continue
rnorm = zero
ierr = -1
end if
c
50 continue
c
if (msglvl .gt. 0) then
call dvout (logfil, 1, rnorm, ndigit,
& '_getv0: B-norm of initial / restarted starting vector')
end if
if (msglvl .gt. 3) then
call dvout (logfil, n, resid, ndigit,
& '_getv0: initial / restarted starting vector')
end if
ido = 99
c
call second (t1)
tgetv0 = tgetv0 + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of dgetv0 |
c %---------------%
c
end

521
arpack/ARPACK/SRC/dlaqrb.f Normal file
View File

@@ -0,0 +1,521 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dlaqrb
c
c\Description:
c Compute the eigenvalues and the Schur decomposition of an upper
c Hessenberg submatrix in rows and columns ILO to IHI. Only the
c last component of the Schur vectors are computed.
c
c This is mostly a modification of the LAPACK routine dlahqr.
c
c\Usage:
c call dlaqrb
c ( WANTT, N, ILO, IHI, H, LDH, WR, WI, Z, INFO )
c
c\Arguments
c WANTT Logical variable. (INPUT)
c = .TRUE. : the full Schur form T is required;
c = .FALSE.: only eigenvalues are required.
c
c N Integer. (INPUT)
c The order of the matrix H. N >= 0.
c
c ILO Integer. (INPUT)
c IHI Integer. (INPUT)
c It is assumed that H is already upper quasi-triangular in
c rows and columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless
c ILO = 1). SLAQRB works primarily with the Hessenberg
c submatrix in rows and columns ILO to IHI, but applies
c transformations to all of H if WANTT is .TRUE..
c 1 <= ILO <= max(1,IHI); IHI <= N.
c
c H Double precision array, dimension (LDH,N). (INPUT/OUTPUT)
c On entry, the upper Hessenberg matrix H.
c On exit, if WANTT is .TRUE., H is upper quasi-triangular in
c rows and columns ILO:IHI, with any 2-by-2 diagonal blocks in
c standard form. If WANTT is .FALSE., the contents of H are
c unspecified on exit.
c
c LDH Integer. (INPUT)
c The leading dimension of the array H. LDH >= max(1,N).
c
c WR Double precision array, dimension (N). (OUTPUT)
c WI Double precision array, dimension (N). (OUTPUT)
c The real and imaginary parts, respectively, of the computed
c eigenvalues ILO to IHI are stored in the corresponding
c elements of WR and WI. If two eigenvalues are computed as a
c complex conjugate pair, they are stored in consecutive
c elements of WR and WI, say the i-th and (i+1)th, with
c WI(i) > 0 and WI(i+1) < 0. If WANTT is .TRUE., the
c eigenvalues are stored in the same order as on the diagonal
c of the Schur form returned in H, with WR(i) = H(i,i), and, if
c H(i:i+1,i:i+1) is a 2-by-2 diagonal block,
c WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and WI(i+1) = -WI(i).
c
c Z Double precision array, dimension (N). (OUTPUT)
c On exit Z contains the last components of the Schur vectors.
c
c INFO Integer. (OUPUT)
c = 0: successful exit
c > 0: SLAQRB failed to compute all the eigenvalues ILO to IHI
c in a total of 30*(IHI-ILO+1) iterations; if INFO = i,
c elements i+1:ihi of WR and WI contain those eigenvalues
c which have been successfully computed.
c
c\Remarks
c 1. None.
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c dlabad LAPACK routine that computes machine constants.
c dlamch LAPACK routine that determines machine constants.
c dlanhs LAPACK routine that computes various norms of a matrix.
c dlanv2 LAPACK routine that computes the Schur factorization of
c 2 by 2 nonsymmetric matrix in standard form.
c dlarfg LAPACK Householder reflection construction routine.
c dcopy Level 1 BLAS that copies one vector to another.
c drot Level 1 BLAS that applies a rotation to a 2 by 2 matrix.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.4'
c Modified from the LAPACK routine dlahqr so that only the
c last component of the Schur vectors are computed.
c
c\SCCS Information: @(#)
c FILE: laqrb.F SID: 2.2 DATE OF SID: 8/27/96 RELEASE: 2
c
c\Remarks
c 1. None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dlaqrb ( wantt, n, ilo, ihi, h, ldh, wr, wi,
& z, info )
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
logical wantt
integer ihi, ilo, info, ldh, n
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& h( ldh, * ), wi( * ), wr( * ), z( * )
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& zero, one, dat1, dat2
parameter (zero = 0.0D+0, one = 1.0D+0, dat1 = 7.5D-1,
& dat2 = -4.375D-1)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
integer i, i1, i2, itn, its, j, k, l, m, nh, nr
Double precision
& cs, h00, h10, h11, h12, h21, h22, h33, h33s,
& h43h34, h44, h44s, ovfl, s, smlnum, sn, sum,
& t1, t2, t3, tst1, ulp, unfl, v1, v2, v3
Double precision
& v( 3 ), work( 1 )
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dlamch, dlanhs
external dlamch, dlanhs
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dcopy, dlabad, dlanv2, dlarfg, drot
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
info = 0
c
c %--------------------------%
c | Quick return if possible |
c %--------------------------%
c
if( n.eq.0 )
& return
if( ilo.eq.ihi ) then
wr( ilo ) = h( ilo, ilo )
wi( ilo ) = zero
return
end if
c
c %---------------------------------------------%
c | Initialize the vector of last components of |
c | the Schur vectors for accumulation. |
c %---------------------------------------------%
c
do 5 j = 1, n-1
z(j) = zero
5 continue
z(n) = one
c
nh = ihi - ilo + 1
c
c %-------------------------------------------------------------%
c | Set machine-dependent constants for the stopping criterion. |
c | If norm(H) <= sqrt(OVFL), overflow should not occur. |
c %-------------------------------------------------------------%
c
unfl = dlamch( 'safe minimum' )
ovfl = one / unfl
call dlabad( unfl, ovfl )
ulp = dlamch( 'precision' )
smlnum = unfl*( nh / ulp )
c
c %---------------------------------------------------------------%
c | I1 and I2 are the indices of the first row and last column |
c | of H to which transformations must be applied. If eigenvalues |
c | only are computed, I1 and I2 are set inside the main loop. |
c | Zero out H(J+2,J) = ZERO for J=1:N if WANTT = .TRUE. |
c | else H(J+2,J) for J=ILO:IHI-ILO-1 if WANTT = .FALSE. |
c %---------------------------------------------------------------%
c
if( wantt ) then
i1 = 1
i2 = n
do 8 i=1,i2-2
h(i1+i+1,i) = zero
8 continue
else
do 9 i=1, ihi-ilo-1
h(ilo+i+1,ilo+i-1) = zero
9 continue
end if
c
c %---------------------------------------------------%
c | ITN is the total number of QR iterations allowed. |
c %---------------------------------------------------%
c
itn = 30*nh
c
c ------------------------------------------------------------------
c The main loop begins here. I is the loop index and decreases from
c IHI to ILO in steps of 1 or 2. Each iteration of the loop works
c with the active submatrix in rows and columns L to I.
c Eigenvalues I+1 to IHI have already converged. Either L = ILO or
c H(L,L-1) is negligible so that the matrix splits.
c ------------------------------------------------------------------
c
i = ihi
10 continue
l = ilo
if( i.lt.ilo )
& go to 150
c %--------------------------------------------------------------%
c | Perform QR iterations on rows and columns ILO to I until a |
c | submatrix of order 1 or 2 splits off at the bottom because a |
c | subdiagonal element has become negligible. |
c %--------------------------------------------------------------%
do 130 its = 0, itn
c
c %----------------------------------------------%
c | Look for a single small subdiagonal element. |
c %----------------------------------------------%
c
do 20 k = i, l + 1, -1
tst1 = abs( h( k-1, k-1 ) ) + abs( h( k, k ) )
if( tst1.eq.zero )
& tst1 = dlanhs( '1', i-l+1, h( l, l ), ldh, work )
if( abs( h( k, k-1 ) ).le.max( ulp*tst1, smlnum ) )
& go to 30
20 continue
30 continue
l = k
if( l.gt.ilo ) then
c
c %------------------------%
c | H(L,L-1) is negligible |
c %------------------------%
c
h( l, l-1 ) = zero
end if
c
c %-------------------------------------------------------------%
c | Exit from loop if a submatrix of order 1 or 2 has split off |
c %-------------------------------------------------------------%
c
if( l.ge.i-1 )
& go to 140
c
c %---------------------------------------------------------%
c | Now the active submatrix is in rows and columns L to I. |
c | If eigenvalues only are being computed, only the active |
c | submatrix need be transformed. |
c %---------------------------------------------------------%
c
if( .not.wantt ) then
i1 = l
i2 = i
end if
c
if( its.eq.10 .or. its.eq.20 ) then
c
c %-------------------%
c | Exceptional shift |
c %-------------------%
c
s = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) )
h44 = dat1*s
h33 = h44
h43h34 = dat2*s*s
c
else
c
c %-----------------------------------------%
c | Prepare to use Wilkinson's double shift |
c %-----------------------------------------%
c
h44 = h( i, i )
h33 = h( i-1, i-1 )
h43h34 = h( i, i-1 )*h( i-1, i )
end if
c
c %-----------------------------------------------------%
c | Look for two consecutive small subdiagonal elements |
c %-----------------------------------------------------%
c
do 40 m = i - 2, l, -1
c
c %---------------------------------------------------------%
c | Determine the effect of starting the double-shift QR |
c | iteration at row M, and see if this would make H(M,M-1) |
c | negligible. |
c %---------------------------------------------------------%
c
h11 = h( m, m )
h22 = h( m+1, m+1 )
h21 = h( m+1, m )
h12 = h( m, m+1 )
h44s = h44 - h11
h33s = h33 - h11
v1 = ( h33s*h44s-h43h34 ) / h21 + h12
v2 = h22 - h11 - h33s - h44s
v3 = h( m+2, m+1 )
s = abs( v1 ) + abs( v2 ) + abs( v3 )
v1 = v1 / s
v2 = v2 / s
v3 = v3 / s
v( 1 ) = v1
v( 2 ) = v2
v( 3 ) = v3
if( m.eq.l )
& go to 50
h00 = h( m-1, m-1 )
h10 = h( m, m-1 )
tst1 = abs( v1 )*( abs( h00 )+abs( h11 )+abs( h22 ) )
if( abs( h10 )*( abs( v2 )+abs( v3 ) ).le.ulp*tst1 )
& go to 50
40 continue
50 continue
c
c %----------------------%
c | Double-shift QR step |
c %----------------------%
c
do 120 k = m, i - 1
c
c ------------------------------------------------------------
c The first iteration of this loop determines a reflection G
c from the vector V and applies it from left and right to H,
c thus creating a nonzero bulge below the subdiagonal.
c
c Each subsequent iteration determines a reflection G to
c restore the Hessenberg form in the (K-1)th column, and thus
c chases the bulge one step toward the bottom of the active
c submatrix. NR is the order of G.
c ------------------------------------------------------------
c
nr = min( 3, i-k+1 )
if( k.gt.m )
& call dcopy( nr, h( k, k-1 ), 1, v, 1 )
call dlarfg( nr, v( 1 ), v( 2 ), 1, t1 )
if( k.gt.m ) then
h( k, k-1 ) = v( 1 )
h( k+1, k-1 ) = zero
if( k.lt.i-1 )
& h( k+2, k-1 ) = zero
else if( m.gt.l ) then
h( k, k-1 ) = -h( k, k-1 )
end if
v2 = v( 2 )
t2 = t1*v2
if( nr.eq.3 ) then
v3 = v( 3 )
t3 = t1*v3
c
c %------------------------------------------------%
c | Apply G from the left to transform the rows of |
c | the matrix in columns K to I2. |
c %------------------------------------------------%
c
do 60 j = k, i2
sum = h( k, j ) + v2*h( k+1, j ) + v3*h( k+2, j )
h( k, j ) = h( k, j ) - sum*t1
h( k+1, j ) = h( k+1, j ) - sum*t2
h( k+2, j ) = h( k+2, j ) - sum*t3
60 continue
c
c %----------------------------------------------------%
c | Apply G from the right to transform the columns of |
c | the matrix in rows I1 to min(K+3,I). |
c %----------------------------------------------------%
c
do 70 j = i1, min( k+3, i )
sum = h( j, k ) + v2*h( j, k+1 ) + v3*h( j, k+2 )
h( j, k ) = h( j, k ) - sum*t1
h( j, k+1 ) = h( j, k+1 ) - sum*t2
h( j, k+2 ) = h( j, k+2 ) - sum*t3
70 continue
c
c %----------------------------------%
c | Accumulate transformations for Z |
c %----------------------------------%
c
sum = z( k ) + v2*z( k+1 ) + v3*z( k+2 )
z( k ) = z( k ) - sum*t1
z( k+1 ) = z( k+1 ) - sum*t2
z( k+2 ) = z( k+2 ) - sum*t3
else if( nr.eq.2 ) then
c
c %------------------------------------------------%
c | Apply G from the left to transform the rows of |
c | the matrix in columns K to I2. |
c %------------------------------------------------%
c
do 90 j = k, i2
sum = h( k, j ) + v2*h( k+1, j )
h( k, j ) = h( k, j ) - sum*t1
h( k+1, j ) = h( k+1, j ) - sum*t2
90 continue
c
c %----------------------------------------------------%
c | Apply G from the right to transform the columns of |
c | the matrix in rows I1 to min(K+3,I). |
c %----------------------------------------------------%
c
do 100 j = i1, i
sum = h( j, k ) + v2*h( j, k+1 )
h( j, k ) = h( j, k ) - sum*t1
h( j, k+1 ) = h( j, k+1 ) - sum*t2
100 continue
c
c %----------------------------------%
c | Accumulate transformations for Z |
c %----------------------------------%
c
sum = z( k ) + v2*z( k+1 )
z( k ) = z( k ) - sum*t1
z( k+1 ) = z( k+1 ) - sum*t2
end if
120 continue
130 continue
c
c %-------------------------------------------------------%
c | Failure to converge in remaining number of iterations |
c %-------------------------------------------------------%
c
info = i
return
140 continue
if( l.eq.i ) then
c
c %------------------------------------------------------%
c | H(I,I-1) is negligible: one eigenvalue has converged |
c %------------------------------------------------------%
c
wr( i ) = h( i, i )
wi( i ) = zero
else if( l.eq.i-1 ) then
c
c %--------------------------------------------------------%
c | H(I-1,I-2) is negligible; |
c | a pair of eigenvalues have converged. |
c | |
c | Transform the 2-by-2 submatrix to standard Schur form, |
c | and compute and store the eigenvalues. |
c %--------------------------------------------------------%
c
call dlanv2( h( i-1, i-1 ), h( i-1, i ), h( i, i-1 ),
& h( i, i ), wr( i-1 ), wi( i-1 ), wr( i ), wi( i ),
& cs, sn )
if( wantt ) then
c
c %-----------------------------------------------------%
c | Apply the transformation to the rest of H and to Z, |
c | as required. |
c %-----------------------------------------------------%
c
if( i2.gt.i )
& call drot( i2-i, h( i-1, i+1 ), ldh, h( i, i+1 ), ldh,
& cs, sn )
call drot( i-i1-1, h( i1, i-1 ), 1, h( i1, i ), 1, cs, sn )
sum = cs*z( i-1 ) + sn*z( i )
z( i ) = cs*z( i ) - sn*z( i-1 )
z( i-1 ) = sum
end if
end if
c
c %---------------------------------------------------------%
c | Decrement number of remaining iterations, and return to |
c | start of the main loop with new value of I. |
c %---------------------------------------------------------%
c
itn = itn - its
i = l - 1
go to 10
150 continue
return
c
c %---------------%
c | End of dlaqrb |
c %---------------%
c
end

840
arpack/ARPACK/SRC/dnaitr.f Normal file
View File

@@ -0,0 +1,840 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dnaitr
c
c\Description:
c Reverse communication interface for applying NP additional steps to
c a K step nonsymmetric Arnoldi factorization.
c
c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T
c
c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0.
c
c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T
c
c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0.
c
c where OP and B are as in dnaupd. The B-norm of r_{k+p} is also
c computed and returned.
c
c\Usage:
c call dnaitr
c ( IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH,
c IPNTR, WORKD, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag.
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c This is for the restart phase to force the new
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y,
c IPNTR(3) is the pointer into WORK for B * X.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c IDO = 99: done
c -------------------------------------------------------------
c When the routine is used in the "shift-and-invert" mode, the
c vector B * Q is already available and do not need to be
c recompute in forming OP * Q.
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B that defines the
c semi-inner product for the operator OP. See dnaupd.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c K Integer. (INPUT)
c Current size of V and H.
c
c NP Integer. (INPUT)
c Number of additional Arnoldi steps to take.
c
c NB Integer. (INPUT)
c Blocksize to be used in the recurrence.
c Only work for NB = 1 right now. The goal is to have a
c program that implement both the block and non-block method.
c
c RESID Double precision array of length N. (INPUT/OUTPUT)
c On INPUT: RESID contains the residual vector r_{k}.
c On OUTPUT: RESID contains the residual vector r_{k+p}.
c
c RNORM Double precision scalar. (INPUT/OUTPUT)
c B-norm of the starting residual on input.
c B-norm of the updated residual r_{k+p} on output.
c
c V Double precision N by K+NP array. (INPUT/OUTPUT)
c On INPUT: V contains the Arnoldi vectors in the first K
c columns.
c On OUTPUT: V contains the new NP Arnoldi vectors in the next
c NP columns. The first K columns are unchanged.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Double precision (K+NP) by (K+NP) array. (INPUT/OUTPUT)
c H is used to store the generated upper Hessenberg matrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORK for
c vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in the
c shift-and-invert mode. X is the current operand.
c -------------------------------------------------------------
c
c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The calling program should not
c use WORKD as temporary workspace during the iteration !!!!!!
c On input, WORKD(1:N) = B*RESID and is used to save some
c computation at the first step.
c
c INFO Integer. (OUTPUT)
c = 0: Normal exit.
c > 0: Size of the spanning invariant subspace of OP found.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c dgetv0 ARPACK routine to generate the initial vector.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c dmout ARPACK utility routine that prints matrices
c dvout ARPACK utility routine that prints vectors.
c dlabad LAPACK routine that computes machine constants.
c dlamch LAPACK routine that determines machine constants.
c dlascl LAPACK routine for careful scaling of a matrix.
c dlanhs LAPACK routine that computes various norms of a matrix.
c dgemv Level 2 BLAS routine for matrix vector multiplication.
c daxpy Level 1 BLAS that computes a vector triad.
c dscal Level 1 BLAS that scales a vector.
c dcopy Level 1 BLAS that copies one vector to another .
c ddot Level 1 BLAS that computes the scalar product of two vectors.
c dnrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: naitr.F SID: 2.4 DATE OF SID: 8/27/96 RELEASE: 2
c
c\Remarks
c The algorithm implemented is:
c
c restart = .false.
c Given V_{k} = [v_{1}, ..., v_{k}], r_{k};
c r_{k} contains the initial residual vector even for k = 0;
c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already
c computed by the calling program.
c
c betaj = rnorm ; p_{k+1} = B*r_{k} ;
c For j = k+1, ..., k+np Do
c 1) if ( betaj < tol ) stop or restart depending on j.
c ( At present tol is zero )
c if ( restart ) generate a new starting vector.
c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}];
c p_{j} = p_{j}/betaj
c 3) r_{j} = OP*v_{j} where OP is defined as in dnaupd
c For shift-invert mode p_{j} = B*v_{j} is already available.
c wnorm = || OP*v_{j} ||
c 4) Compute the j-th step residual vector.
c w_{j} = V_{j}^T * B * OP * v_{j}
c r_{j} = OP*v_{j} - V_{j} * w_{j}
c H(:,j) = w_{j};
c H(j,j-1) = rnorm
c rnorm = || r_(j) ||
c If (rnorm > 0.717*wnorm) accept step and go back to 1)
c 5) Re-orthogonalization step:
c s = V_{j}'*B*r_{j}
c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} ||
c alphaj = alphaj + s_{j};
c 6) Iterative refinement step:
c If (rnorm1 > 0.717*rnorm) then
c rnorm = rnorm1
c accept step and go back to 1)
c Else
c rnorm = rnorm1
c If this is the first time in step 6), go to 5)
c Else r_{j} lies in the span of V_{j} numerically.
c Set r_{j} = 0 and rnorm = 0; go to 1)
c EndIf
c End Do
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dnaitr
& (ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh,
& ipntr, workd, info)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1
integer ido, info, k, ldh, ldv, n, nb, np
Double precision
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Double precision
& h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0, zero = 0.0D+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
logical first, orth1, orth2, rstart, step3, step4
integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl,
& jj
Double precision
& betaj, ovfl, temp1, rnorm1, smlnum, tst1, ulp, unfl,
& wnorm
save first, orth1, orth2, rstart, step3, step4,
& ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl,
& betaj, rnorm1, smlnum, ulp, unfl, wnorm
c
c %-----------------------%
c | Local Array Arguments |
c %-----------------------%
c
Double precision
& xtemp(2)
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external daxpy, dcopy, dscal, dgemv, dgetv0, dlabad,
& dvout, dmout, ivout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& ddot, dnrm2, dlanhs, dlamch
external ddot, dnrm2, dlanhs, dlamch
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic abs, sqrt
c
c %-----------------%
c | Data statements |
c %-----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
c
c %-----------------------------------------%
c | Set machine-dependent constants for the |
c | the splitting and deflation criterion. |
c | If norm(H) <= sqrt(OVFL), |
c | overflow should not occur. |
c | REFERENCE: LAPACK subroutine dlahqr |
c %-----------------------------------------%
c
unfl = dlamch( 'safe minimum' )
ovfl = one / unfl
call dlabad( unfl, ovfl )
ulp = dlamch( 'precision' )
smlnum = unfl*( n / ulp )
first = .false.
end if
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mnaitr
c
c %------------------------------%
c | Initial call to this routine |
c %------------------------------%
c
info = 0
step3 = .false.
step4 = .false.
rstart = .false.
orth1 = .false.
orth2 = .false.
j = k + 1
ipj = 1
irj = ipj + n
ivj = irj + n
end if
c
c %-------------------------------------------------%
c | When in reverse communication mode one of: |
c | STEP3, STEP4, ORTH1, ORTH2, RSTART |
c | will be .true. when .... |
c | STEP3: return from computing OP*v_{j}. |
c | STEP4: return from computing B-norm of OP*v_{j} |
c | ORTH1: return from computing B-norm of r_{j+1} |
c | ORTH2: return from computing B-norm of |
c | correction to the residual vector. |
c | RSTART: return from OP computations needed by |
c | dgetv0. |
c %-------------------------------------------------%
c
if (step3) go to 50
if (step4) go to 60
if (orth1) go to 70
if (orth2) go to 90
if (rstart) go to 30
c
c %-----------------------------%
c | Else this is the first step |
c %-----------------------------%
c
c %--------------------------------------------------------------%
c | |
c | A R N O L D I I T E R A T I O N L O O P |
c | |
c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) |
c %--------------------------------------------------------------%
1000 continue
c
if (msglvl .gt. 1) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: generating Arnoldi vector number')
call dvout (logfil, 1, rnorm, ndigit,
& '_naitr: B-norm of the current residual is')
end if
c
c %---------------------------------------------------%
c | STEP 1: Check if the B norm of j-th residual |
c | vector is zero. Equivalent to determing whether |
c | an exact j-step Arnoldi factorization is present. |
c %---------------------------------------------------%
c
betaj = rnorm
if (rnorm .gt. zero) go to 40
c
c %---------------------------------------------------%
c | Invariant subspace found, generate a new starting |
c | vector which is orthogonal to the current Arnoldi |
c | basis and continue the iteration. |
c %---------------------------------------------------%
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: ****** RESTART AT STEP ******')
end if
c
c %---------------------------------------------%
c | ITRY is the loop variable that controls the |
c | maximum amount of times that a restart is |
c | attempted. NRSTRT is used by stat.h |
c %---------------------------------------------%
c
betaj = zero
nrstrt = nrstrt + 1
itry = 1
20 continue
rstart = .true.
ido = 0
30 continue
c
c %--------------------------------------%
c | If in reverse communication mode and |
c | RSTART = .true. flow returns here. |
c %--------------------------------------%
c
call dgetv0 (ido, bmat, itry, .false., n, j, v, ldv,
& resid, rnorm, ipntr, workd, ierr)
if (ido .ne. 99) go to 9000
if (ierr .lt. 0) then
itry = itry + 1
if (itry .le. 3) go to 20
c
c %------------------------------------------------%
c | Give up after several restart attempts. |
c | Set INFO to the size of the invariant subspace |
c | which spans OP and exit. |
c %------------------------------------------------%
c
info = j - 1
call second (t1)
tnaitr = tnaitr + (t1 - t0)
ido = 99
go to 9000
end if
c
40 continue
c
c %---------------------------------------------------------%
c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm |
c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow |
c | when reciprocating a small RNORM, test against lower |
c | machine bound. |
c %---------------------------------------------------------%
c
call dcopy (n, resid, 1, v(1,j), 1)
if (rnorm .ge. unfl) then
temp1 = one / rnorm
call dscal (n, temp1, v(1,j), 1)
call dscal (n, temp1, workd(ipj), 1)
else
c
c %-----------------------------------------%
c | To scale both v_{j} and p_{j} carefully |
c | use LAPACK routine SLASCL |
c %-----------------------------------------%
c
call dlascl ('General', i, i, rnorm, one, n, 1,
& v(1,j), n, infol)
call dlascl ('General', i, i, rnorm, one, n, 1,
& workd(ipj), n, infol)
end if
c
c %------------------------------------------------------%
c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} |
c | Note that this is not quite yet r_{j}. See STEP 4 |
c %------------------------------------------------------%
c
step3 = .true.
nopx = nopx + 1
call second (t2)
call dcopy (n, v(1,j), 1, workd(ivj), 1)
ipntr(1) = ivj
ipntr(2) = irj
ipntr(3) = ipj
ido = 1
c
c %-----------------------------------%
c | Exit in order to compute OP*v_{j} |
c %-----------------------------------%
c
go to 9000
50 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} |
c | if step3 = .true. |
c %----------------------------------%
c
call second (t3)
tmvopx = tmvopx + (t3 - t2)
step3 = .false.
c
c %------------------------------------------%
c | Put another copy of OP*v_{j} into RESID. |
c %------------------------------------------%
c
call dcopy (n, workd(irj), 1, resid, 1)
c
c %---------------------------------------%
c | STEP 4: Finish extending the Arnoldi |
c | factorization to length j. |
c %---------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
step4 = .true.
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-------------------------------------%
c | Exit in order to compute B*OP*v_{j} |
c %-------------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call dcopy (n, resid, 1, workd(ipj), 1)
end if
60 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} |
c | if step4 = .true. |
c %----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
step4 = .false.
c
c %-------------------------------------%
c | The following is needed for STEP 5. |
c | Compute the B-norm of OP*v_{j}. |
c %-------------------------------------%
c
if (bmat .eq. 'G') then
wnorm = ddot (n, resid, 1, workd(ipj), 1)
wnorm = sqrt(abs(wnorm))
else if (bmat .eq. 'I') then
wnorm = dnrm2(n, resid, 1)
end if
c
c %-----------------------------------------%
c | Compute the j-th residual corresponding |
c | to the j step factorization. |
c | Use Classical Gram Schmidt and compute: |
c | w_{j} <- V_{j}^T * B * OP * v_{j} |
c | r_{j} <- OP*v_{j} - V_{j} * w_{j} |
c %-----------------------------------------%
c
c
c %------------------------------------------%
c | Compute the j Fourier coefficients w_{j} |
c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. |
c %------------------------------------------%
c
call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1,
& zero, h(1,j), 1)
c
c %--------------------------------------%
c | Orthogonalize r_{j} against V_{j}. |
c | RESID contains OP*v_{j}. See STEP 3. |
c %--------------------------------------%
c
call dgemv ('N', n, j, -one, v, ldv, h(1,j), 1,
& one, resid, 1)
c
if (j .gt. 1) h(j,j-1) = betaj
c
call second (t4)
c
orth1 = .true.
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call dcopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*r_{j} |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call dcopy (n, resid, 1, workd(ipj), 1)
end if
70 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH1 = .true. |
c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
orth1 = .false.
c
c %------------------------------%
c | Compute the B-norm of r_{j}. |
c %------------------------------%
c
if (bmat .eq. 'G') then
rnorm = ddot (n, resid, 1, workd(ipj), 1)
rnorm = sqrt(abs(rnorm))
else if (bmat .eq. 'I') then
rnorm = dnrm2(n, resid, 1)
end if
c
c %-----------------------------------------------------------%
c | STEP 5: Re-orthogonalization / Iterative refinement phase |
c | Maximum NITER_ITREF tries. |
c | |
c | s = V_{j}^T * B * r_{j} |
c | r_{j} = r_{j} - V_{j}*s |
c | alphaj = alphaj + s_{j} |
c | |
c | The stopping criteria used for iterative refinement is |
c | discussed in Parlett's book SEP, page 107 and in Gragg & |
c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. |
c | Determine if we need to correct the residual. The goal is |
c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || |
c | The following test determines whether the sine of the |
c | angle between OP*x and the computed residual is less |
c | than or equal to 0.717. |
c %-----------------------------------------------------------%
c
if (rnorm .gt. 0.717*wnorm) go to 100
iter = 0
nrorth = nrorth + 1
c
c %---------------------------------------------------%
c | Enter the Iterative refinement phase. If further |
c | refinement is necessary, loop back here. The loop |
c | variable is ITER. Perform a step of Classical |
c | Gram-Schmidt using all the Arnoldi vectors V_{j} |
c %---------------------------------------------------%
c
80 continue
c
if (msglvl .gt. 2) then
xtemp(1) = wnorm
xtemp(2) = rnorm
call dvout (logfil, 2, xtemp, ndigit,
& '_naitr: re-orthonalization; wnorm and rnorm are')
call dvout (logfil, j, h(1,j), ndigit,
& '_naitr: j-th column of H')
end if
c
c %----------------------------------------------------%
c | Compute V_{j}^T * B * r_{j}. |
c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). |
c %----------------------------------------------------%
c
call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1,
& zero, workd(irj), 1)
c
c %---------------------------------------------%
c | Compute the correction to the residual: |
c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). |
c | The correction to H is v(:,1:J)*H(1:J,1:J) |
c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. |
c %---------------------------------------------%
c
call dgemv ('N', n, j, -one, v, ldv, workd(irj), 1,
& one, resid, 1)
call daxpy (j, one, workd(irj), 1, h(1,j), 1)
c
orth2 = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call dcopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-----------------------------------%
c | Exit in order to compute B*r_{j}. |
c | r_{j} is the corrected residual. |
c %-----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call dcopy (n, resid, 1, workd(ipj), 1)
end if
90 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH2 = .true. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
c %-----------------------------------------------------%
c | Compute the B-norm of the corrected residual r_{j}. |
c %-----------------------------------------------------%
c
if (bmat .eq. 'G') then
rnorm1 = ddot (n, resid, 1, workd(ipj), 1)
rnorm1 = sqrt(abs(rnorm1))
else if (bmat .eq. 'I') then
rnorm1 = dnrm2(n, resid, 1)
end if
c
if (msglvl .gt. 0 .and. iter .gt. 0) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: Iterative refinement for Arnoldi residual')
if (msglvl .gt. 2) then
xtemp(1) = rnorm
xtemp(2) = rnorm1
call dvout (logfil, 2, xtemp, ndigit,
& '_naitr: iterative refinement ; rnorm and rnorm1 are')
end if
end if
c
c %-----------------------------------------%
c | Determine if we need to perform another |
c | step of re-orthogonalization. |
c %-----------------------------------------%
c
if (rnorm1 .gt. 0.717*rnorm) then
c
c %---------------------------------------%
c | No need for further refinement. |
c | The cosine of the angle between the |
c | corrected residual vector and the old |
c | residual vector is greater than 0.717 |
c | In other words the corrected residual |
c | and the old residual vector share an |
c | angle of less than arcCOS(0.717) |
c %---------------------------------------%
c
rnorm = rnorm1
c
else
c
c %-------------------------------------------%
c | Another step of iterative refinement step |
c | is required. NITREF is used by stat.h |
c %-------------------------------------------%
c
nitref = nitref + 1
rnorm = rnorm1
iter = iter + 1
if (iter .le. 1) go to 80
c
c %-------------------------------------------------%
c | Otherwise RESID is numerically in the span of V |
c %-------------------------------------------------%
c
do 95 jj = 1, n
resid(jj) = zero
95 continue
rnorm = zero
end if
c
c %----------------------------------------------%
c | Branch here directly if iterative refinement |
c | wasn't necessary or after at most NITER_REF |
c | steps of iterative refinement. |
c %----------------------------------------------%
c
100 continue
c
rstart = .false.
orth2 = .false.
c
call second (t5)
titref = titref + (t5 - t4)
c
c %------------------------------------%
c | STEP 6: Update j = j+1; Continue |
c %------------------------------------%
c
j = j + 1
if (j .gt. k+np) then
call second (t1)
tnaitr = tnaitr + (t1 - t0)
ido = 99
do 110 i = max(1,k), k+np-1
c
c %--------------------------------------------%
c | Check for splitting and deflation. |
c | Use a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine dlahqr |
c %--------------------------------------------%
c
tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) )
if( tst1.eq.zero )
& tst1 = dlanhs( '1', k+np, h, ldh, workd(n+1) )
if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) )
& h(i+1,i) = zero
110 continue
c
if (msglvl .gt. 2) then
call dmout (logfil, k+np, k+np, h, ldh, ndigit,
& '_naitr: Final upper Hessenberg matrix H of order K+NP')
end if
c
go to 9000
end if
c
c %--------------------------------------------------------%
c | Loop back to extend the factorization by another step. |
c %--------------------------------------------------------%
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
9000 continue
return
c
c %---------------%
c | End of dnaitr |
c %---------------%
c
end

647
arpack/ARPACK/SRC/dnapps.f Normal file
View File

@@ -0,0 +1,647 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dnapps
c
c\Description:
c Given the Arnoldi factorization
c
c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T,
c
c apply NP implicit shifts resulting in
c
c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q
c
c where Q is an orthogonal matrix which is the product of rotations
c and reflections resulting from the NP bulge chage sweeps.
c The updated Arnoldi factorization becomes:
c
c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T.
c
c\Usage:
c call dnapps
c ( N, KEV, NP, SHIFTR, SHIFTI, V, LDV, H, LDH, RESID, Q, LDQ,
c WORKL, WORKD )
c
c\Arguments
c N Integer. (INPUT)
c Problem size, i.e. size of matrix A.
c
c KEV Integer. (INPUT/OUTPUT)
c KEV+NP is the size of the input matrix H.
c KEV is the size of the updated matrix HNEW. KEV is only
c updated on ouput when fewer than NP shifts are applied in
c order to keep the conjugate pair together.
c
c NP Integer. (INPUT)
c Number of implicit shifts to be applied.
c
c SHIFTR, Double precision array of length NP. (INPUT)
c SHIFTI Real and imaginary part of the shifts to be applied.
c Upon, entry to dnapps, the shifts must be sorted so that the
c conjugate pairs are in consecutive locations.
c
c V Double precision N by (KEV+NP) array. (INPUT/OUTPUT)
c On INPUT, V contains the current KEV+NP Arnoldi vectors.
c On OUTPUT, V contains the updated KEV Arnoldi vectors
c in the first KEV columns of V.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Double precision (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT)
c On INPUT, H contains the current KEV+NP by KEV+NP upper
c Hessenber matrix of the Arnoldi factorization.
c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg
c matrix in the KEV leading submatrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RESID Double precision array of length N. (INPUT/OUTPUT)
c On INPUT, RESID contains the the residual vector r_{k+p}.
c On OUTPUT, RESID is the update residual vector rnew_{k}
c in the first KEV locations.
c
c Q Double precision KEV+NP by KEV+NP work array. (WORKSPACE)
c Work array used to accumulate the rotations and reflections
c during the bulge chase sweep.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Double precision work array of length (KEV+NP). (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c WORKD Double precision work array of length 2*N. (WORKSPACE)
c Distributed array used in the application of the accumulated
c orthogonal matrix Q.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c
c\Routines called:
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c dmout ARPACK utility routine that prints matrices.
c dvout ARPACK utility routine that prints vectors.
c dlabad LAPACK routine that computes machine constants.
c dlacpy LAPACK matrix copy routine.
c dlamch LAPACK routine that determines machine constants.
c dlanhs LAPACK routine that computes various norms of a matrix.
c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c dlarf LAPACK routine that applies Householder reflection to
c a matrix.
c dlarfg LAPACK Householder reflection construction routine.
c dlartg LAPACK Givens rotation construction routine.
c dlaset LAPACK matrix initialization routine.
c dgemv Level 2 BLAS routine for matrix vector multiplication.
c daxpy Level 1 BLAS that computes a vector triad.
c dcopy Level 1 BLAS that copies one vector to another .
c dscal Level 1 BLAS that scales a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: napps.F SID: 2.4 DATE OF SID: 3/28/97 RELEASE: 2
c
c\Remarks
c 1. In this version, each shift is applied to all the sublocks of
c the Hessenberg matrix H and not just to the submatrix that it
c comes from. Deflation as in LAPACK routine dlahqr (QR algorithm
c for upper Hessenberg matrices ) is used.
c The subdiagonals of H are enforced to be non-negative.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dnapps
& ( n, kev, np, shiftr, shifti, v, ldv, h, ldh, resid, q, ldq,
& workl, workd )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer kev, ldh, ldq, ldv, n, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& h(ldh,kev+np), resid(n), shifti(np), shiftr(np),
& v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0, zero = 0.0D+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
integer i, iend, ir, istart, j, jj, kplusp, msglvl, nr
logical cconj, first
Double precision
& c, f, g, h11, h12, h21, h22, h32, ovfl, r, s, sigmai,
& sigmar, smlnum, ulp, unfl, u(3), t, tau, tst1
save first, ovfl, smlnum, ulp, unfl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external daxpy, dcopy, dscal, dlacpy, dlarfg, dlarf,
& dlaset, dlabad, second, dlartg
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dlamch, dlanhs, dlapy2
external dlamch, dlanhs, dlapy2
c
c %----------------------%
c | Intrinsics Functions |
c %----------------------%
c
intrinsic abs, max, min
c
c %----------------%
c | Data statments |
c %----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
c
c %-----------------------------------------------%
c | Set machine-dependent constants for the |
c | stopping criterion. If norm(H) <= sqrt(OVFL), |
c | overflow should not occur. |
c | REFERENCE: LAPACK subroutine dlahqr |
c %-----------------------------------------------%
c
unfl = dlamch( 'safe minimum' )
ovfl = one / unfl
call dlabad( unfl, ovfl )
ulp = dlamch( 'precision' )
smlnum = unfl*( n / ulp )
first = .false.
end if
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mnapps
kplusp = kev + np
c
c %--------------------------------------------%
c | Initialize Q to the identity to accumulate |
c | the rotations and reflections |
c %--------------------------------------------%
c
call dlaset ('All', kplusp, kplusp, zero, one, q, ldq)
c
c %----------------------------------------------%
c | Quick return if there are no shifts to apply |
c %----------------------------------------------%
c
if (np .eq. 0) go to 9000
c
c %----------------------------------------------%
c | Chase the bulge with the application of each |
c | implicit shift. Each shift is applied to the |
c | whole matrix including each block. |
c %----------------------------------------------%
c
cconj = .false.
do 110 jj = 1, np
sigmar = shiftr(jj)
sigmai = shifti(jj)
c
if (msglvl .gt. 2 ) then
call ivout (logfil, 1, jj, ndigit,
& '_napps: shift number.')
call dvout (logfil, 1, sigmar, ndigit,
& '_napps: The real part of the shift ')
call dvout (logfil, 1, sigmai, ndigit,
& '_napps: The imaginary part of the shift ')
end if
c
c %-------------------------------------------------%
c | The following set of conditionals is necessary |
c | in order that complex conjugate pairs of shifts |
c | are applied together or not at all. |
c %-------------------------------------------------%
c
if ( cconj ) then
c
c %-----------------------------------------%
c | cconj = .true. means the previous shift |
c | had non-zero imaginary part. |
c %-----------------------------------------%
c
cconj = .false.
go to 110
else if ( jj .lt. np .and. abs( sigmai ) .gt. zero ) then
c
c %------------------------------------%
c | Start of a complex conjugate pair. |
c %------------------------------------%
c
cconj = .true.
else if ( jj .eq. np .and. abs( sigmai ) .gt. zero ) then
c
c %----------------------------------------------%
c | The last shift has a nonzero imaginary part. |
c | Don't apply it; thus the order of the |
c | compressed H is order KEV+1 since only np-1 |
c | were applied. |
c %----------------------------------------------%
c
kev = kev + 1
go to 110
end if
istart = 1
20 continue
c
c %--------------------------------------------------%
c | if sigmai = 0 then |
c | Apply the jj-th shift ... |
c | else |
c | Apply the jj-th and (jj+1)-th together ... |
c | (Note that jj < np at this point in the code) |
c | end |
c | to the current block of H. The next do loop |
c | determines the current block ; |
c %--------------------------------------------------%
c
do 30 i = istart, kplusp-1
c
c %----------------------------------------%
c | Check for splitting and deflation. Use |
c | a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine dlahqr |
c %----------------------------------------%
c
tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) )
if( tst1.eq.zero )
& tst1 = dlanhs( '1', kplusp-jj+1, h, ldh, workl )
if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) then
if (msglvl .gt. 0) then
call ivout (logfil, 1, i, ndigit,
& '_napps: matrix splitting at row/column no.')
call ivout (logfil, 1, jj, ndigit,
& '_napps: matrix splitting with shift number.')
call dvout (logfil, 1, h(i+1,i), ndigit,
& '_napps: off diagonal element.')
end if
iend = i
h(i+1,i) = zero
go to 40
end if
30 continue
iend = kplusp
40 continue
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, istart, ndigit,
& '_napps: Start of current block ')
call ivout (logfil, 1, iend, ndigit,
& '_napps: End of current block ')
end if
c
c %------------------------------------------------%
c | No reason to apply a shift to block of order 1 |
c %------------------------------------------------%
c
if ( istart .eq. iend ) go to 100
c
c %------------------------------------------------------%
c | If istart + 1 = iend then no reason to apply a |
c | complex conjugate pair of shifts on a 2 by 2 matrix. |
c %------------------------------------------------------%
c
if ( istart + 1 .eq. iend .and. abs( sigmai ) .gt. zero )
& go to 100
c
h11 = h(istart,istart)
h21 = h(istart+1,istart)
if ( abs( sigmai ) .le. zero ) then
c
c %---------------------------------------------%
c | Real-valued shift ==> apply single shift QR |
c %---------------------------------------------%
c
f = h11 - sigmar
g = h21
c
do 80 i = istart, iend-1
c
c %-----------------------------------------------------%
c | Contruct the plane rotation G to zero out the bulge |
c %-----------------------------------------------------%
c
call dlartg (f, g, c, s, r)
if (i .gt. istart) then
c
c %-------------------------------------------%
c | The following ensures that h(1:iend-1,1), |
c | the first iend-2 off diagonal of elements |
c | H, remain non negative. |
c %-------------------------------------------%
c
if (r .lt. zero) then
r = -r
c = -c
s = -s
end if
h(i,i-1) = r
h(i+1,i-1) = zero
end if
c
c %---------------------------------------------%
c | Apply rotation to the left of H; H <- G'*H |
c %---------------------------------------------%
c
do 50 j = i, kplusp
t = c*h(i,j) + s*h(i+1,j)
h(i+1,j) = -s*h(i,j) + c*h(i+1,j)
h(i,j) = t
50 continue
c
c %---------------------------------------------%
c | Apply rotation to the right of H; H <- H*G |
c %---------------------------------------------%
c
do 60 j = 1, min(i+2,iend)
t = c*h(j,i) + s*h(j,i+1)
h(j,i+1) = -s*h(j,i) + c*h(j,i+1)
h(j,i) = t
60 continue
c
c %----------------------------------------------------%
c | Accumulate the rotation in the matrix Q; Q <- Q*G |
c %----------------------------------------------------%
c
do 70 j = 1, min( i+jj, kplusp )
t = c*q(j,i) + s*q(j,i+1)
q(j,i+1) = - s*q(j,i) + c*q(j,i+1)
q(j,i) = t
70 continue
c
c %---------------------------%
c | Prepare for next rotation |
c %---------------------------%
c
if (i .lt. iend-1) then
f = h(i+1,i)
g = h(i+2,i)
end if
80 continue
c
c %-----------------------------------%
c | Finished applying the real shift. |
c %-----------------------------------%
c
else
c
c %----------------------------------------------------%
c | Complex conjugate shifts ==> apply double shift QR |
c %----------------------------------------------------%
c
h12 = h(istart,istart+1)
h22 = h(istart+1,istart+1)
h32 = h(istart+2,istart+1)
c
c %---------------------------------------------------------%
c | Compute 1st column of (H - shift*I)*(H - conj(shift)*I) |
c %---------------------------------------------------------%
c
s = 2.0*sigmar
t = dlapy2 ( sigmar, sigmai )
u(1) = ( h11 * (h11 - s) + t * t ) / h21 + h12
u(2) = h11 + h22 - s
u(3) = h32
c
do 90 i = istart, iend-1
c
nr = min ( 3, iend-i+1 )
c
c %-----------------------------------------------------%
c | Construct Householder reflector G to zero out u(1). |
c | G is of the form I - tau*( 1 u )' * ( 1 u' ). |
c %-----------------------------------------------------%
c
call dlarfg ( nr, u(1), u(2), 1, tau )
c
if (i .gt. istart) then
h(i,i-1) = u(1)
h(i+1,i-1) = zero
if (i .lt. iend-1) h(i+2,i-1) = zero
end if
u(1) = one
c
c %--------------------------------------%
c | Apply the reflector to the left of H |
c %--------------------------------------%
c
call dlarf ('Left', nr, kplusp-i+1, u, 1, tau,
& h(i,i), ldh, workl)
c
c %---------------------------------------%
c | Apply the reflector to the right of H |
c %---------------------------------------%
c
ir = min ( i+3, iend )
call dlarf ('Right', ir, nr, u, 1, tau,
& h(1,i), ldh, workl)
c
c %-----------------------------------------------------%
c | Accumulate the reflector in the matrix Q; Q <- Q*G |
c %-----------------------------------------------------%
c
call dlarf ('Right', kplusp, nr, u, 1, tau,
& q(1,i), ldq, workl)
c
c %----------------------------%
c | Prepare for next reflector |
c %----------------------------%
c
if (i .lt. iend-1) then
u(1) = h(i+1,i)
u(2) = h(i+2,i)
if (i .lt. iend-2) u(3) = h(i+3,i)
end if
c
90 continue
c
c %--------------------------------------------%
c | Finished applying a complex pair of shifts |
c | to the current block |
c %--------------------------------------------%
c
end if
c
100 continue
c
c %---------------------------------------------------------%
c | Apply the same shift to the next block if there is any. |
c %---------------------------------------------------------%
c
istart = iend + 1
if (iend .lt. kplusp) go to 20
c
c %---------------------------------------------%
c | Loop back to the top to get the next shift. |
c %---------------------------------------------%
c
110 continue
c
c %--------------------------------------------------%
c | Perform a similarity transformation that makes |
c | sure that H will have non negative sub diagonals |
c %--------------------------------------------------%
c
do 120 j=1,kev
if ( h(j+1,j) .lt. zero ) then
call dscal( kplusp-j+1, -one, h(j+1,j), ldh )
call dscal( min(j+2, kplusp), -one, h(1,j+1), 1 )
call dscal( min(j+np+1,kplusp), -one, q(1,j+1), 1 )
end if
120 continue
c
do 130 i = 1, kev
c
c %--------------------------------------------%
c | Final check for splitting and deflation. |
c | Use a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine dlahqr |
c %--------------------------------------------%
c
tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) )
if( tst1.eq.zero )
& tst1 = dlanhs( '1', kev, h, ldh, workl )
if( h( i+1,i ) .le. max( ulp*tst1, smlnum ) )
& h(i+1,i) = zero
130 continue
c
c %-------------------------------------------------%
c | Compute the (kev+1)-st column of (V*Q) and |
c | temporarily store the result in WORKD(N+1:2*N). |
c | This is needed in the residual update since we |
c | cannot GUARANTEE that the corresponding entry |
c | of H would be zero as in exact arithmetic. |
c %-------------------------------------------------%
c
if (h(kev+1,kev) .gt. zero)
& call dgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero,
& workd(n+1), 1)
c
c %----------------------------------------------------------%
c | Compute column 1 to kev of (V*Q) in backward order |
c | taking advantage of the upper Hessenberg structure of Q. |
c %----------------------------------------------------------%
c
do 140 i = 1, kev
call dgemv ('N', n, kplusp-i+1, one, v, ldv,
& q(1,kev-i+1), 1, zero, workd, 1)
call dcopy (n, workd, 1, v(1,kplusp-i+1), 1)
140 continue
c
c %-------------------------------------------------%
c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). |
c %-------------------------------------------------%
c
call dlacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv)
c
c %--------------------------------------------------------------%
c | Copy the (kev+1)-st column of (V*Q) in the appropriate place |
c %--------------------------------------------------------------%
c
if (h(kev+1,kev) .gt. zero)
& call dcopy (n, workd(n+1), 1, v(1,kev+1), 1)
c
c %-------------------------------------%
c | Update the residual vector: |
c | r <- sigmak*r + betak*v(:,kev+1) |
c | where |
c | sigmak = (e_{kplusp}'*Q)*e_{kev} |
c | betak = e_{kev+1}'*H*e_{kev} |
c %-------------------------------------%
c
call dscal (n, q(kplusp,kev), resid, 1)
if (h(kev+1,kev) .gt. zero)
& call daxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1)
c
if (msglvl .gt. 1) then
call dvout (logfil, 1, q(kplusp,kev), ndigit,
& '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}')
call dvout (logfil, 1, h(kev+1,kev), ndigit,
& '_napps: betak = e_{kev+1}^T*H*e_{kev}')
call ivout (logfil, 1, kev, ndigit,
& '_napps: Order of the final Hessenberg matrix ')
if (msglvl .gt. 2) then
call dmout (logfil, kev, kev, h, ldh, ndigit,
& '_napps: updated Hessenberg matrix H for next iteration')
end if
c
end if
c
9000 continue
call second (t1)
tnapps = tnapps + (t1 - t0)
c
return
c
c %---------------%
c | End of dnapps |
c %---------------%
c
end

835
arpack/ARPACK/SRC/dnaup2.f Normal file
View File

@@ -0,0 +1,835 @@
c\BeginDoc
c
c\Name: dnaup2
c
c\Description:
c Intermediate level interface called by dnaupd.
c
c\Usage:
c call dnaup2
c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD,
c ISHIFT, MXITER, V, LDV, H, LDH, RITZR, RITZI, BOUNDS,
c Q, LDQ, WORKL, IPNTR, WORKD, INFO )
c
c\Arguments
c
c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in dnaupd.
c MODE, ISHIFT, MXITER: see the definition of IPARAM in dnaupd.
c
c NP Integer. (INPUT/OUTPUT)
c Contains the number of implicit shifts to apply during
c each Arnoldi iteration.
c If ISHIFT=1, NP is adjusted dynamically at each iteration
c to accelerate convergence and prevent stagnation.
c This is also roughly equal to the number of matrix-vector
c products (involving the operator OP) per Arnoldi iteration.
c The logic for adjusting is contained within the current
c subroutine.
c If ISHIFT=0, NP is the number of shifts the user needs
c to provide via reverse comunication. 0 < NP < NCV-NEV.
c NP may be less than NCV-NEV for two reasons. The first, is
c to keep complex conjugate pairs of "wanted" Ritz values
c together. The second, is that a leading block of the current
c upper Hessenberg matrix has split off and contains "unwanted"
c Ritz values.
c Upon termination of the IRA iteration, NP contains the number
c of "converged" wanted Ritz values.
c
c IUPD Integer. (INPUT)
c IUPD .EQ. 0: use explicit restart instead implicit update.
c IUPD .NE. 0: use implicit update.
c
c V Double precision N by (NEV+NP) array. (INPUT/OUTPUT)
c The Arnoldi basis vectors are returned in the first NEV
c columns of V.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Double precision (NEV+NP) by (NEV+NP) array. (OUTPUT)
c H is used to store the generated upper Hessenberg matrix
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RITZR, Double precision arrays of length NEV+NP. (OUTPUT)
c RITZI RITZR(1:NEV) (resp. RITZI(1:NEV)) contains the real (resp.
c imaginary) part of the computed Ritz values of OP.
c
c BOUNDS Double precision array of length NEV+NP. (OUTPUT)
c BOUNDS(1:NEV) contain the error bounds corresponding to
c the computed Ritz values.
c
c Q Double precision (NEV+NP) by (NEV+NP) array. (WORKSPACE)
c Private (replicated) work array used to accumulate the
c rotation in the shift application step.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Double precision work array of length at least
c (NEV+NP)**2 + 3*(NEV+NP). (INPUT/WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. It is used in shifts calculation, shifts
c application and convergence checking.
c
c On exit, the last 3*(NEV+NP) locations of WORKL contain
c the Ritz values (real,imaginary) and associated Ritz
c estimates of the current Hessenberg matrix. They are
c listed in the same order as returned from dneigh.
c
c If ISHIFT .EQ. O and IDO .EQ. 3, the first 2*NP locations
c of WORKL are used in reverse communication to hold the user
c supplied shifts.
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORKD for
c vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in the
c shift-and-invert mode. X is the current operand.
c -------------------------------------------------------------
c
c WORKD Double precision work array of length 3*N. (WORKSPACE)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration !!!!!!!!!!
c See Data Distribution Note in DNAUPD.
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal return.
c = 1: Maximum number of iterations taken.
c All possible eigenvalues of OP has been found.
c NP returns the number of converged Ritz values.
c = 2: No shifts could be applied.
c = -8: Error return from LAPACK eigenvalue calculation;
c This should never happen.
c = -9: Starting vector is zero.
c = -9999: Could not build an Arnoldi factorization.
c Size that was built in returned in NP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c dgetv0 ARPACK initial vector generation routine.
c dnaitr ARPACK Arnoldi factorization routine.
c dnapps ARPACK application of implicit shifts routine.
c dnconv ARPACK convergence of Ritz values routine.
c dneigh ARPACK compute Ritz values and error bounds routine.
c dngets ARPACK reorder Ritz values and error bounds routine.
c dsortc ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c dmout ARPACK utility routine that prints matrices
c dvout ARPACK utility routine that prints vectors.
c dlamch LAPACK routine that determines machine constants.
c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c dcopy Level 1 BLAS that copies one vector to another .
c ddot Level 1 BLAS that computes the scalar product of two vectors.
c dnrm2 Level 1 BLAS that computes the norm of a vector.
c dswap Level 1 BLAS that swaps two vectors.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: naup2.F SID: 2.8 DATE OF SID: 10/17/00 RELEASE: 2
c
c\Remarks
c 1. None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dnaup2
& ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, h, ldh, ritzr, ritzi, bounds,
& q, ldq, workl, ipntr, workd, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter,
& n, nev, np
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(13)
Double precision
& bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), resid(n),
& ritzi(nev+np), ritzr(nev+np), v(ldv,nev+np),
& workd(3*n), workl( (nev+np)*(nev+np+3) )
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0, zero = 0.0D+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
character wprime*2
logical cnorm , getv0, initv, update, ushift
integer ierr , iter , j , kplusp, msglvl, nconv,
& nevbef, nev0 , np0 , nptemp, numcnv
Double precision
& rnorm , temp , eps23
save cnorm , getv0, initv, update, ushift,
& rnorm , iter , eps23, kplusp, msglvl, nconv ,
& nevbef, nev0 , np0 , numcnv
c
c %-----------------------%
c | Local array arguments |
c %-----------------------%
c
integer kp(4)
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dcopy , dgetv0, dnaitr, dnconv, dneigh,
& dngets, dnapps, dvout , ivout , second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& ddot, dnrm2, dlapy2, dlamch
external ddot, dnrm2, dlapy2, dlamch
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic min, max, abs, sqrt
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
call second (t0)
c
msglvl = mnaup2
c
c %-------------------------------------%
c | Get the machine dependent constant. |
c %-------------------------------------%
c
eps23 = dlamch('Epsilon-Machine')
eps23 = eps23**(2.0D+0 / 3.0D+0)
c
nev0 = nev
np0 = np
c
c %-------------------------------------%
c | kplusp is the bound on the largest |
c | Lanczos factorization built. |
c | nconv is the current number of |
c | "converged" eigenvlues. |
c | iter is the counter on the current |
c | iteration step. |
c %-------------------------------------%
c
kplusp = nev + np
nconv = 0
iter = 0
c
c %---------------------------------------%
c | Set flags for computing the first NEV |
c | steps of the Arnoldi factorization. |
c %---------------------------------------%
c
getv0 = .true.
update = .false.
ushift = .false.
cnorm = .false.
c
if (info .ne. 0) then
c
c %--------------------------------------------%
c | User provides the initial residual vector. |
c %--------------------------------------------%
c
initv = .true.
info = 0
else
initv = .false.
end if
end if
c
c %---------------------------------------------%
c | Get a possibly random starting vector and |
c | force it into the range of the operator OP. |
c %---------------------------------------------%
c
10 continue
c
if (getv0) then
call dgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm,
& ipntr, workd, info)
c
if (ido .ne. 99) go to 9000
c
if (rnorm .eq. zero) then
c
c %-----------------------------------------%
c | The initial vector is zero. Error exit. |
c %-----------------------------------------%
c
info = -9
go to 1100
end if
getv0 = .false.
ido = 0
end if
c
c %-----------------------------------%
c | Back from reverse communication : |
c | continue with update step |
c %-----------------------------------%
c
if (update) go to 20
c
c %-------------------------------------------%
c | Back from computing user specified shifts |
c %-------------------------------------------%
c
if (ushift) go to 50
c
c %-------------------------------------%
c | Back from computing residual norm |
c | at the end of the current iteration |
c %-------------------------------------%
c
if (cnorm) go to 100
c
c %----------------------------------------------------------%
c | Compute the first NEV steps of the Arnoldi factorization |
c %----------------------------------------------------------%
c
call dnaitr (ido, bmat, n, 0, nev, mode, resid, rnorm, v, ldv,
& h, ldh, ipntr, workd, info)
c
c %---------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP and possibly B |
c %---------------------------------------------------%
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
np = info
mxiter = iter
info = -9999
go to 1200
end if
c
c %--------------------------------------------------------------%
c | |
c | M A I N ARNOLDI I T E R A T I O N L O O P |
c | Each iteration implicitly restarts the Arnoldi |
c | factorization in place. |
c | |
c %--------------------------------------------------------------%
c
1000 continue
c
iter = iter + 1
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, iter, ndigit,
& '_naup2: **** Start of major iteration number ****')
end if
c
c %-----------------------------------------------------------%
c | Compute NP additional steps of the Arnoldi factorization. |
c | Adjust NP since NEV might have been updated by last call |
c | to the shift application routine dnapps. |
c %-----------------------------------------------------------%
c
np = kplusp - nev
c
if (msglvl .gt. 1) then
call ivout (logfil, 1, nev, ndigit,
& '_naup2: The length of the current Arnoldi factorization')
call ivout (logfil, 1, np, ndigit,
& '_naup2: Extend the Arnoldi factorization by')
end if
c
c %-----------------------------------------------------------%
c | Compute NP additional steps of the Arnoldi factorization. |
c %-----------------------------------------------------------%
c
ido = 0
20 continue
update = .true.
c
call dnaitr (ido , bmat, n , nev, np , mode , resid,
& rnorm, v , ldv, h , ldh, ipntr, workd,
& info)
c
c %---------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP and possibly B |
c %---------------------------------------------------%
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
np = info
mxiter = iter
info = -9999
go to 1200
end if
update = .false.
c
if (msglvl .gt. 1) then
call dvout (logfil, 1, rnorm, ndigit,
& '_naup2: Corresponding B-norm of the residual')
end if
c
c %--------------------------------------------------------%
c | Compute the eigenvalues and corresponding error bounds |
c | of the current upper Hessenberg matrix. |
c %--------------------------------------------------------%
c
call dneigh (rnorm, kplusp, h, ldh, ritzr, ritzi, bounds,
& q, ldq, workl, ierr)
c
if (ierr .ne. 0) then
info = -8
go to 1200
end if
c
c %----------------------------------------------------%
c | Make a copy of eigenvalues and corresponding error |
c | bounds obtained from dneigh. |
c %----------------------------------------------------%
c
call dcopy(kplusp, ritzr, 1, workl(kplusp**2+1), 1)
call dcopy(kplusp, ritzi, 1, workl(kplusp**2+kplusp+1), 1)
call dcopy(kplusp, bounds, 1, workl(kplusp**2+2*kplusp+1), 1)
c
c %---------------------------------------------------%
c | Select the wanted Ritz values and their bounds |
c | to be used in the convergence test. |
c | The wanted part of the spectrum and corresponding |
c | error bounds are in the last NEV loc. of RITZR, |
c | RITZI and BOUNDS respectively. The variables NEV |
c | and NP may be updated if the NEV-th wanted Ritz |
c | value has a non zero imaginary part. In this case |
c | NEV is increased by one and NP decreased by one. |
c | NOTE: The last two arguments of dngets are no |
c | longer used as of version 2.1. |
c %---------------------------------------------------%
c
nev = nev0
np = np0
numcnv = nev
call dngets (ishift, which, nev, np, ritzr, ritzi,
& bounds, workl, workl(np+1))
if (nev .eq. nev0+1) numcnv = nev0+1
c
c %-------------------%
c | Convergence test. |
c %-------------------%
c
call dcopy (nev, bounds(np+1), 1, workl(2*np+1), 1)
call dnconv (nev, ritzr(np+1), ritzi(np+1), workl(2*np+1),
& tol, nconv)
c
if (msglvl .gt. 2) then
kp(1) = nev
kp(2) = np
kp(3) = numcnv
kp(4) = nconv
call ivout (logfil, 4, kp, ndigit,
& '_naup2: NEV, NP, NUMCNV, NCONV are')
call dvout (logfil, kplusp, ritzr, ndigit,
& '_naup2: Real part of the eigenvalues of H')
call dvout (logfil, kplusp, ritzi, ndigit,
& '_naup2: Imaginary part of the eigenvalues of H')
call dvout (logfil, kplusp, bounds, ndigit,
& '_naup2: Ritz estimates of the current NCV Ritz values')
end if
c
c %---------------------------------------------------------%
c | Count the number of unwanted Ritz values that have zero |
c | Ritz estimates. If any Ritz estimates are equal to zero |
c | then a leading block of H of order equal to at least |
c | the number of Ritz values with zero Ritz estimates has |
c | split off. None of these Ritz values may be removed by |
c | shifting. Decrease NP the number of shifts to apply. If |
c | no shifts may be applied, then prepare to exit |
c %---------------------------------------------------------%
c
nptemp = np
do 30 j=1, nptemp
if (bounds(j) .eq. zero) then
np = np - 1
nev = nev + 1
end if
30 continue
c
if ( (nconv .ge. numcnv) .or.
& (iter .gt. mxiter) .or.
& (np .eq. 0) ) then
c
if (msglvl .gt. 4) then
call dvout(logfil, kplusp, workl(kplusp**2+1), ndigit,
& '_naup2: Real part of the eig computed by _neigh:')
call dvout(logfil, kplusp, workl(kplusp**2+kplusp+1),
& ndigit,
& '_naup2: Imag part of the eig computed by _neigh:')
call dvout(logfil, kplusp, workl(kplusp**2+kplusp*2+1),
& ndigit,
& '_naup2: Ritz eistmates computed by _neigh:')
end if
c
c %------------------------------------------------%
c | Prepare to exit. Put the converged Ritz values |
c | and corresponding bounds in RITZ(1:NCONV) and |
c | BOUNDS(1:NCONV) respectively. Then sort. Be |
c | careful when NCONV > NP |
c %------------------------------------------------%
c
c %------------------------------------------%
c | Use h( 3,1 ) as storage to communicate |
c | rnorm to _neupd if needed |
c %------------------------------------------%
h(3,1) = rnorm
c
c %----------------------------------------------%
c | To be consistent with dngets, we first do a |
c | pre-processing sort in order to keep complex |
c | conjugate pairs together. This is similar |
c | to the pre-processing sort used in dngets |
c | except that the sort is done in the opposite |
c | order. |
c %----------------------------------------------%
c
if (which .eq. 'LM') wprime = 'SR'
if (which .eq. 'SM') wprime = 'LR'
if (which .eq. 'LR') wprime = 'SM'
if (which .eq. 'SR') wprime = 'LM'
if (which .eq. 'LI') wprime = 'SM'
if (which .eq. 'SI') wprime = 'LM'
c
call dsortc (wprime, .true., kplusp, ritzr, ritzi, bounds)
c
c %----------------------------------------------%
c | Now sort Ritz values so that converged Ritz |
c | values appear within the first NEV locations |
c | of ritzr, ritzi and bounds, and the most |
c | desired one appears at the front. |
c %----------------------------------------------%
c
if (which .eq. 'LM') wprime = 'SM'
if (which .eq. 'SM') wprime = 'LM'
if (which .eq. 'LR') wprime = 'SR'
if (which .eq. 'SR') wprime = 'LR'
if (which .eq. 'LI') wprime = 'SI'
if (which .eq. 'SI') wprime = 'LI'
c
call dsortc(wprime, .true., kplusp, ritzr, ritzi, bounds)
c
c %--------------------------------------------------%
c | Scale the Ritz estimate of each Ritz value |
c | by 1 / max(eps23,magnitude of the Ritz value). |
c %--------------------------------------------------%
c
do 35 j = 1, numcnv
temp = max(eps23,dlapy2(ritzr(j),
& ritzi(j)))
bounds(j) = bounds(j)/temp
35 continue
c
c %----------------------------------------------------%
c | Sort the Ritz values according to the scaled Ritz |
c | esitmates. This will push all the converged ones |
c | towards the front of ritzr, ritzi, bounds |
c | (in the case when NCONV < NEV.) |
c %----------------------------------------------------%
c
wprime = 'LR'
call dsortc(wprime, .true., numcnv, bounds, ritzr, ritzi)
c
c %----------------------------------------------%
c | Scale the Ritz estimate back to its original |
c | value. |
c %----------------------------------------------%
c
do 40 j = 1, numcnv
temp = max(eps23, dlapy2(ritzr(j),
& ritzi(j)))
bounds(j) = bounds(j)*temp
40 continue
c
c %------------------------------------------------%
c | Sort the converged Ritz values again so that |
c | the "threshold" value appears at the front of |
c | ritzr, ritzi and bound. |
c %------------------------------------------------%
c
call dsortc(which, .true., nconv, ritzr, ritzi, bounds)
c
if (msglvl .gt. 1) then
call dvout (logfil, kplusp, ritzr, ndigit,
& '_naup2: Sorted real part of the eigenvalues')
call dvout (logfil, kplusp, ritzi, ndigit,
& '_naup2: Sorted imaginary part of the eigenvalues')
call dvout (logfil, kplusp, bounds, ndigit,
& '_naup2: Sorted ritz estimates.')
end if
c
c %------------------------------------%
c | Max iterations have been exceeded. |
c %------------------------------------%
c
if (iter .gt. mxiter .and. nconv .lt. numcnv) info = 1
c
c %---------------------%
c | No shifts to apply. |
c %---------------------%
c
if (np .eq. 0 .and. nconv .lt. numcnv) info = 2
c
np = nconv
go to 1100
c
else if ( (nconv .lt. numcnv) .and. (ishift .eq. 1) ) then
c
c %-------------------------------------------------%
c | Do not have all the requested eigenvalues yet. |
c | To prevent possible stagnation, adjust the size |
c | of NEV. |
c %-------------------------------------------------%
c
nevbef = nev
nev = nev + min(nconv, np/2)
if (nev .eq. 1 .and. kplusp .ge. 6) then
nev = kplusp / 2
else if (nev .eq. 1 .and. kplusp .gt. 3) then
nev = 2
end if
np = kplusp - nev
c
c %---------------------------------------%
c | If the size of NEV was just increased |
c | resort the eigenvalues. |
c %---------------------------------------%
c
if (nevbef .lt. nev)
& call dngets (ishift, which, nev, np, ritzr, ritzi,
& bounds, workl, workl(np+1))
c
end if
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, nconv, ndigit,
& '_naup2: no. of "converged" Ritz values at this iter.')
if (msglvl .gt. 1) then
kp(1) = nev
kp(2) = np
call ivout (logfil, 2, kp, ndigit,
& '_naup2: NEV and NP are')
call dvout (logfil, nev, ritzr(np+1), ndigit,
& '_naup2: "wanted" Ritz values -- real part')
call dvout (logfil, nev, ritzi(np+1), ndigit,
& '_naup2: "wanted" Ritz values -- imag part')
call dvout (logfil, nev, bounds(np+1), ndigit,
& '_naup2: Ritz estimates of the "wanted" values ')
end if
end if
c
if (ishift .eq. 0) then
c
c %-------------------------------------------------------%
c | User specified shifts: reverse comminucation to |
c | compute the shifts. They are returned in the first |
c | 2*NP locations of WORKL. |
c %-------------------------------------------------------%
c
ushift = .true.
ido = 3
go to 9000
end if
c
50 continue
c
c %------------------------------------%
c | Back from reverse communication; |
c | User specified shifts are returned |
c | in WORKL(1:2*NP) |
c %------------------------------------%
c
ushift = .false.
c
if ( ishift .eq. 0 ) then
c
c %----------------------------------%
c | Move the NP shifts from WORKL to |
c | RITZR, RITZI to free up WORKL |
c | for non-exact shift case. |
c %----------------------------------%
c
call dcopy (np, workl, 1, ritzr, 1)
call dcopy (np, workl(np+1), 1, ritzi, 1)
end if
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, np, ndigit,
& '_naup2: The number of shifts to apply ')
call dvout (logfil, np, ritzr, ndigit,
& '_naup2: Real part of the shifts')
call dvout (logfil, np, ritzi, ndigit,
& '_naup2: Imaginary part of the shifts')
if ( ishift .eq. 1 )
& call dvout (logfil, np, bounds, ndigit,
& '_naup2: Ritz estimates of the shifts')
end if
c
c %---------------------------------------------------------%
c | Apply the NP implicit shifts by QR bulge chasing. |
c | Each shift is applied to the whole upper Hessenberg |
c | matrix H. |
c | The first 2*N locations of WORKD are used as workspace. |
c %---------------------------------------------------------%
c
call dnapps (n, nev, np, ritzr, ritzi, v, ldv,
& h, ldh, resid, q, ldq, workl, workd)
c
c %---------------------------------------------%
c | Compute the B-norm of the updated residual. |
c | Keep B*RESID in WORKD(1:N) to be used in |
c | the first step of the next call to dnaitr. |
c %---------------------------------------------%
c
cnorm = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call dcopy (n, resid, 1, workd(n+1), 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*RESID |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call dcopy (n, resid, 1, workd, 1)
end if
c
100 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(1:N) := B*RESID |
c %----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
if (bmat .eq. 'G') then
rnorm = ddot (n, resid, 1, workd, 1)
rnorm = sqrt(abs(rnorm))
else if (bmat .eq. 'I') then
rnorm = dnrm2(n, resid, 1)
end if
cnorm = .false.
c
if (msglvl .gt. 2) then
call dvout (logfil, 1, rnorm, ndigit,
& '_naup2: B-norm of residual for compressed factorization')
call dmout (logfil, nev, nev, h, ldh, ndigit,
& '_naup2: Compressed upper Hessenberg matrix H')
end if
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
1100 continue
c
mxiter = iter
nev = numcnv
c
1200 continue
ido = 99
c
c %------------%
c | Error Exit |
c %------------%
c
call second (t1)
tnaup2 = t1 - t0
c
9000 continue
c
c %---------------%
c | End of dnaup2 |
c %---------------%
c
return
end

693
arpack/ARPACK/SRC/dnaupd.f Normal file
View File

@@ -0,0 +1,693 @@
c\BeginDoc
c
c\Name: dnaupd
c
c\Description:
c Reverse communication interface for the Implicitly Restarted Arnoldi
c iteration. This subroutine computes approximations to a few eigenpairs
c of a linear operator "OP" with respect to a semi-inner product defined by
c a symmetric positive semi-definite real matrix B. B may be the identity
c matrix. NOTE: If the linear operator "OP" is real and symmetric
c with respect to the real positive semi-definite symmetric matrix B,
c i.e. B*OP = (OP`)*B, then subroutine dsaupd should be used instead.
c
c The computed approximate eigenvalues are called Ritz values and
c the corresponding approximate eigenvectors are called Ritz vectors.
c
c dnaupd is usually called iteratively to solve one of the
c following problems:
c
c Mode 1: A*x = lambda*x.
c ===> OP = A and B = I.
c
c Mode 2: A*x = lambda*M*x, M symmetric positive definite
c ===> OP = inv[M]*A and B = M.
c ===> (If M can be factored see remark 3 below)
c
c Mode 3: A*x = lambda*M*x, M symmetric semi-definite
c ===> OP = Real_Part{ inv[A - sigma*M]*M } and B = M.
c ===> shift-and-invert mode (in real arithmetic)
c If OP*x = amu*x, then
c amu = 1/2 * [ 1/(lambda-sigma) + 1/(lambda-conjg(sigma)) ].
c Note: If sigma is real, i.e. imaginary part of sigma is zero;
c Real_Part{ inv[A - sigma*M]*M } == inv[A - sigma*M]*M
c amu == 1/(lambda-sigma).
c
c Mode 4: A*x = lambda*M*x, M symmetric semi-definite
c ===> OP = Imaginary_Part{ inv[A - sigma*M]*M } and B = M.
c ===> shift-and-invert mode (in real arithmetic)
c If OP*x = amu*x, then
c amu = 1/2i * [ 1/(lambda-sigma) - 1/(lambda-conjg(sigma)) ].
c
c Both mode 3 and 4 give the same enhancement to eigenvalues close to
c the (complex) shift sigma. However, as lambda goes to infinity,
c the operator OP in mode 4 dampens the eigenvalues more strongly than
c does OP defined in mode 3.
c
c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v
c should be accomplished either by a direct method
c using a sparse matrix factorization and solving
c
c [A - sigma*M]*w = v or M*w = v,
c
c or through an iterative method for solving these
c systems. If an iterative method is used, the
c convergence test must be more stringent than
c the accuracy requirements for the eigenvalue
c approximations.
c
c\Usage:
c call dnaupd
c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM,
c IPNTR, WORKD, WORKL, LWORKL, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag. IDO must be zero on the first
c call to dnaupd. IDO will be set internally to
c indicate the type of operation to be performed. Control is
c then given back to the calling routine which has the
c responsibility to carry out the requested operation and call
c dnaupd with the result. The operand is given in
c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)).
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c This is for the initialization phase to force the
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c In mode 3 and 4, the vector B * X is already
c available in WORKD(ipntr(3)). It does not
c need to be recomputed in forming OP * X.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c IDO = 3: compute the IPARAM(8) real and imaginary parts
c of the shifts where INPTR(14) is the pointer
c into WORKL for placing the shifts. See Remark
c 5 below.
c IDO = 99: done
c -------------------------------------------------------------
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B that defines the
c semi-inner product for the operator OP.
c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x
c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*B*x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c WHICH Character*2. (INPUT)
c 'LM' -> want the NEV eigenvalues of largest magnitude.
c 'SM' -> want the NEV eigenvalues of smallest magnitude.
c 'LR' -> want the NEV eigenvalues of largest real part.
c 'SR' -> want the NEV eigenvalues of smallest real part.
c 'LI' -> want the NEV eigenvalues of largest imaginary part.
c 'SI' -> want the NEV eigenvalues of smallest imaginary part.
c
c NEV Integer. (INPUT/OUTPUT)
c Number of eigenvalues of OP to be computed. 0 < NEV < N-1.
c
c TOL Double precision scalar. (INPUT)
c Stopping criterion: the relative accuracy of the Ritz value
c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I))
c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex.
c DEFAULT = DLAMCH('EPS') (machine precision as computed
c by the LAPACK auxiliary subroutine DLAMCH).
c
c RESID Double precision array of length N. (INPUT/OUTPUT)
c On INPUT:
c If INFO .EQ. 0, a random initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c On OUTPUT:
c RESID contains the final residual vector.
c
c NCV Integer. (INPUT)
c Number of columns of the matrix V. NCV must satisfy the two
c inequalities 2 <= NCV-NEV and NCV <= N.
c This will indicate how many Arnoldi vectors are generated
c at each iteration. After the startup phase in which NEV
c Arnoldi vectors are generated, the algorithm generates
c approximately NCV-NEV Arnoldi vectors at each subsequent update
c iteration. Most of the cost in generating each Arnoldi vector is
c in the matrix-vector operation OP*x.
c NOTE: 2 <= NCV-NEV in order that complex conjugate pairs of Ritz
c values are kept together. (See remark 4 below)
c
c V Double precision array N by NCV. (OUTPUT)
c Contains the final set of Arnoldi basis vectors.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling program.
c
c IPARAM Integer array of length 11. (INPUT/OUTPUT)
c IPARAM(1) = ISHIFT: method for selecting the implicit shifts.
c The shifts selected at each iteration are used to restart
c the Arnoldi iteration in an implicit fashion.
c -------------------------------------------------------------
c ISHIFT = 0: the shifts are provided by the user via
c reverse communication. The real and imaginary
c parts of the NCV eigenvalues of the Hessenberg
c matrix H are returned in the part of the WORKL
c array corresponding to RITZR and RITZI. See remark
c 5 below.
c ISHIFT = 1: exact shifts with respect to the current
c Hessenberg matrix H. This is equivalent to
c restarting the iteration with a starting vector
c that is a linear combination of approximate Schur
c vectors associated with the "wanted" Ritz values.
c -------------------------------------------------------------
c
c IPARAM(2) = No longer referenced.
c
c IPARAM(3) = MXITER
c On INPUT: maximum number of Arnoldi update iterations allowed.
c On OUTPUT: actual number of Arnoldi update iterations taken.
c
c IPARAM(4) = NB: blocksize to be used in the recurrence.
c The code currently works only for NB = 1.
c
c IPARAM(5) = NCONV: number of "converged" Ritz values.
c This represents the number of Ritz values that satisfy
c the convergence criterion.
c
c IPARAM(6) = IUPD
c No longer referenced. Implicit restarting is ALWAYS used.
c
c IPARAM(7) = MODE
c On INPUT determines what type of eigenproblem is being solved.
c Must be 1,2,3,4; See under \Description of dnaupd for the
c four modes available.
c
c IPARAM(8) = NP
c When ido = 3 and the user provides shifts through reverse
c communication (IPARAM(1)=0), dnaupd returns NP, the number
c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark
c 5 below.
c
c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO,
c OUTPUT: NUMOP = total number of OP*x operations,
c NUMOPB = total number of B*x operations if BMAT='G',
c NUMREO = total number of steps of re-orthogonalization.
c
c IPNTR Integer array of length 14. (OUTPUT)
c Pointer to mark the starting locations in the WORKD and WORKL
c arrays for matrices/vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X in WORKD.
c IPNTR(2): pointer to the current result vector Y in WORKD.
c IPNTR(3): pointer to the vector B * X in WORKD when used in
c the shift-and-invert mode.
c IPNTR(4): pointer to the next available location in WORKL
c that is untouched by the program.
c IPNTR(5): pointer to the NCV by NCV upper Hessenberg matrix
c H in WORKL.
c IPNTR(6): pointer to the real part of the ritz value array
c RITZR in WORKL.
c IPNTR(7): pointer to the imaginary part of the ritz value array
c RITZI in WORKL.
c IPNTR(8): pointer to the Ritz estimates in array WORKL associated
c with the Ritz values located in RITZR and RITZI in WORKL.
c
c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below.
c
c Note: IPNTR(9:13) is only referenced by dneupd. See Remark 2 below.
c
c IPNTR(9): pointer to the real part of the NCV RITZ values of the
c original system.
c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of
c the original system.
c IPNTR(11): pointer to the NCV corresponding error bounds.
c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular
c Schur matrix for H.
c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors
c of the upper Hessenberg matrix H. Only referenced by
c dneupd if RVEC = .TRUE. See Remark 2 below.
c -------------------------------------------------------------
c
c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration. Upon termination
c WORKD(1:N) contains B*RESID(1:N). If an invariant subspace
c associated with the converged Ritz values is desired, see remark
c 2 below, subroutine dneupd uses this output.
c See Data Distribution Note below.
c
c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. See Data Distribution Note below.
c
c LWORKL Integer. (INPUT)
c LWORKL must be at least 3*NCV**2 + 6*NCV.
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal exit.
c = 1: Maximum number of iterations taken.
c All possible eigenvalues of OP has been found. IPARAM(5)
c returns the number of wanted converged Ritz values.
c = 2: No longer an informational error. Deprecated starting
c with release 2 of ARPACK.
c = 3: No shifts could be applied during a cycle of the
c Implicitly restarted Arnoldi iteration. One possibility
c is to increase the size of NCV relative to NEV.
c See remark 4 below.
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV-NEV >= 2 and less than or equal to N.
c = -4: The maximum number of Arnoldi update iteration
c must be greater than zero.
c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work array is not sufficient.
c = -8: Error return from LAPACK eigenvalue calculation;
c = -9: Starting vector is zero.
c = -10: IPARAM(7) must be 1,2,3,4.
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable.
c = -12: IPARAM(1) must be equal to 0 or 1.
c = -9999: Could not build an Arnoldi factorization.
c IPARAM(5) returns the size of the current Arnoldi
c factorization.
c
c\Remarks
c 1. The computed Ritz values are approximate eigenvalues of OP. The
c selection of WHICH should be made with this in mind when
c Mode = 3 and 4. After convergence, approximate eigenvalues of the
c original problem may be obtained with the ARPACK subroutine dneupd.
c
c 2. If a basis for the invariant subspace corresponding to the converged Ritz
c values is needed, the user must call dneupd immediately following
c completion of dnaupd. This is new starting with release 2 of ARPACK.
c
c 3. If M can be factored into a Cholesky factorization M = LL`
c then Mode = 2 should not be selected. Instead one should use
c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular
c linear systems should be solved with L and L` rather
c than computing inverses. After convergence, an approximate
c eigenvector z of the original problem is recovered by solving
c L`z = x where x is a Ritz vector of OP.
c
c 4. At present there is no a-priori analysis to guide the selection
c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 2.
c However, it is recommended that NCV .ge. 2*NEV+1. If many problems of
c the same type are to be solved, one should experiment with increasing
c NCV while keeping NEV fixed for a given test problem. This will
c usually decrease the required number of OP*x operations but it
c also increases the work and storage required to maintain the orthogonal
c basis vectors. The optimal "cross-over" with respect to CPU time
c is problem dependent and must be determined empirically.
c See Chapter 8 of Reference 2 for further information.
c
c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the
c NP = IPARAM(8) real and imaginary parts of the shifts in locations
c real part imaginary part
c ----------------------- --------------
c 1 WORKL(IPNTR(14)) WORKL(IPNTR(14)+NP)
c 2 WORKL(IPNTR(14)+1) WORKL(IPNTR(14)+NP+1)
c . .
c . .
c . .
c NP WORKL(IPNTR(14)+NP-1) WORKL(IPNTR(14)+2*NP-1).
c
c Only complex conjugate pairs of shifts may be applied and the pairs
c must be placed in consecutive locations. The real part of the
c eigenvalues of the current upper Hessenberg matrix are located in
c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1) and the imaginary part
c in WORKL(IPNTR(7)) through WORKL(IPNTR(7)+NCV-1). They are ordered
c according to the order defined by WHICH. The complex conjugate
c pairs are kept together and the associated Ritz estimates are located in
c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1).
c
c-----------------------------------------------------------------------
c
c\Data Distribution Note:
c
c Fortran-D syntax:
c ================
c Double precision resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
c decompose d1(n), d2(n,ncv)
c align resid(i) with d1(i)
c align v(i,j) with d2(i,j)
c align workd(i) with d1(i) range (1:n)
c align workd(i) with d1(i-n) range (n+1:2*n)
c align workd(i) with d1(i-2*n) range (2*n+1:3*n)
c distribute d1(block), d2(block,:)
c replicated workl(lworkl)
c
c Cray MPP syntax:
c ===============
c Double precision resid(n), v(ldv,ncv), workd(n,3), workl(lworkl)
c shared resid(block), v(block,:), workd(block,:)
c replicated workl(lworkl)
c
c CM2/CM5 syntax:
c ==============
c
c-----------------------------------------------------------------------
c
c include 'ex-nonsym.doc'
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for
c Real Matrices", Linear Algebra and its Applications, vol 88/89,
c pp 575-595, (1987).
c
c\Routines called:
c dnaup2 ARPACK routine that implements the Implicitly Restarted
c Arnoldi Iteration.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c dvout ARPACK utility routine that prints vectors.
c dlamch LAPACK routine that determines machine constants.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/16/93: Version '1.1'
c
c\SCCS Information: @(#)
c FILE: naupd.F SID: 2.10 DATE OF SID: 08/23/02 RELEASE: 2
c
c\Remarks
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dnaupd
& ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam,
& ipntr, workd, workl, lworkl, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ldv, lworkl, n, ncv, nev
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(11), ipntr(14)
Double precision
& resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0, zero = 0.0D+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer bounds, ierr, ih, iq, ishift, iupd, iw,
& ldh, ldq, levec, mode, msglvl, mxiter, nb,
& nev0, next, np, ritzi, ritzr, j
save bounds, ih, iq, ishift, iupd, iw, ldh, ldq,
& levec, mode, msglvl, mxiter, nb, nev0, next,
& np, ritzi, ritzr
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dnaup2, dvout, ivout, second, dstatn
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dlamch
external dlamch
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call dstatn
call second (t0)
msglvl = mnaupd
c
c %----------------%
c | Error checking |
c %----------------%
c
ierr = 0
ishift = iparam(1)
c levec = iparam(2)
mxiter = iparam(3)
c nb = iparam(4)
nb = 1
c
c %--------------------------------------------%
c | Revision 2 performs only implicit restart. |
c %--------------------------------------------%
c
iupd = 1
mode = iparam(7)
c
if (n .le. 0) then
ierr = -1
else if (nev .le. 0) then
ierr = -2
else if (ncv .le. nev+1 .or. ncv .gt. n) then
ierr = -3
else if (mxiter .le. 0) then
ierr = 4
else if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LR' .and.
& which .ne. 'SR' .and.
& which .ne. 'LI' .and.
& which .ne. 'SI') then
ierr = -5
else if (bmat .ne. 'I' .and. bmat .ne. 'G') then
ierr = -6
else if (lworkl .lt. 3*ncv**2 + 6*ncv) then
ierr = -7
else if (mode .lt. 1 .or. mode .gt. 4) then
ierr = -10
else if (mode .eq. 1 .and. bmat .eq. 'G') then
ierr = -11
else if (ishift .lt. 0 .or. ishift .gt. 1) then
ierr = -12
end if
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
ido = 99
go to 9000
end if
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
if (nb .le. 0) nb = 1
if (tol .le. zero) tol = dlamch('EpsMach')
c
c %----------------------------------------------%
c | NP is the number of additional steps to |
c | extend the length NEV Lanczos factorization. |
c | NEV0 is the local variable designating the |
c | size of the invariant subspace desired. |
c %----------------------------------------------%
c
np = ncv - nev
nev0 = nev
c
c %-----------------------------%
c | Zero out internal workspace |
c %-----------------------------%
c
do 10 j = 1, 3*ncv**2 + 6*ncv
workl(j) = zero
10 continue
c
c %-------------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:ncv*ncv) := generated Hessenberg matrix |
c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary |
c | parts of ritz values |
c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds |
c | workl(ncv*ncv+3*ncv+1:2*ncv*ncv+3*ncv) := rotation matrix Q |
c | workl(2*ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) := workspace |
c | The final workspace is needed by subroutine dneigh called |
c | by dnaup2. Subroutine dneigh calls LAPACK routines for |
c | calculating eigenvalues and the last row of the eigenvector |
c | matrix. |
c %-------------------------------------------------------------%
c
ldh = ncv
ldq = ncv
ih = 1
ritzr = ih + ldh*ncv
ritzi = ritzr + ncv
bounds = ritzi + ncv
iq = bounds + ncv
iw = iq + ldq*ncv
next = iw + ncv**2 + 3*ncv
c
ipntr(4) = next
ipntr(5) = ih
ipntr(6) = ritzr
ipntr(7) = ritzi
ipntr(8) = bounds
ipntr(14) = iw
c
end if
c
c %-------------------------------------------------------%
c | Carry out the Implicitly restarted Arnoldi Iteration. |
c %-------------------------------------------------------%
c
call dnaup2
& ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritzr),
& workl(ritzi), workl(bounds), workl(iq), ldq, workl(iw),
& ipntr, workd, info )
c
c %--------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP or shifts. |
c %--------------------------------------------------%
c
if (ido .eq. 3) iparam(8) = np
if (ido .ne. 99) go to 9000
c
iparam(3) = mxiter
iparam(5) = np
iparam(9) = nopx
iparam(10) = nbx
iparam(11) = nrorth
c
c %------------------------------------%
c | Exit if there was an informational |
c | error within dnaup2. |
c %------------------------------------%
c
if (info .lt. 0) go to 9000
if (info .eq. 2) info = 3
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, mxiter, ndigit,
& '_naupd: Number of update iterations taken')
call ivout (logfil, 1, np, ndigit,
& '_naupd: Number of wanted "converged" Ritz values')
call dvout (logfil, np, workl(ritzr), ndigit,
& '_naupd: Real part of the final Ritz values')
call dvout (logfil, np, workl(ritzi), ndigit,
& '_naupd: Imaginary part of the final Ritz values')
call dvout (logfil, np, workl(bounds), ndigit,
& '_naupd: Associated Ritz estimates')
end if
c
call second (t1)
tnaupd = t1 - t0
c
if (msglvl .gt. 0) then
c
c %--------------------------------------------------------%
c | Version Number & Version Date are defined in version.h |
c %--------------------------------------------------------%
c
write (6,1000)
write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt,
& tmvopx, tmvbx, tnaupd, tnaup2, tnaitr, titref,
& tgetv0, tneigh, tngets, tnapps, tnconv, trvec
1000 format (//,
& 5x, '=============================================',/
& 5x, '= Nonsymmetric implicit Arnoldi update code =',/
& 5x, '= Version Number: ', ' 2.4', 21x, ' =',/
& 5x, '= Version Date: ', ' 07/31/96', 16x, ' =',/
& 5x, '=============================================',/
& 5x, '= Summary of timing statistics =',/
& 5x, '=============================================',//)
1100 format (
& 5x, 'Total number update iterations = ', i5,/
& 5x, 'Total number of OP*x operations = ', i5,/
& 5x, 'Total number of B*x operations = ', i5,/
& 5x, 'Total number of reorthogonalization steps = ', i5,/
& 5x, 'Total number of iterative refinement steps = ', i5,/
& 5x, 'Total number of restart steps = ', i5,/
& 5x, 'Total time in user OP*x operation = ', f12.6,/
& 5x, 'Total time in user B*x operation = ', f12.6,/
& 5x, 'Total time in Arnoldi update routine = ', f12.6,/
& 5x, 'Total time in naup2 routine = ', f12.6,/
& 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/
& 5x, 'Total time in reorthogonalization phase = ', f12.6,/
& 5x, 'Total time in (re)start vector generation = ', f12.6,/
& 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/
& 5x, 'Total time in getting the shifts = ', f12.6,/
& 5x, 'Total time in applying the shifts = ', f12.6,/
& 5x, 'Total time in convergence testing = ', f12.6,/
& 5x, 'Total time in computing final Ritz vectors = ', f12.6/)
end if
c
9000 continue
c
return
c
c %---------------%
c | End of dnaupd |
c %---------------%
c
end

View File

146
arpack/ARPACK/SRC/dnconv.f Normal file
View File

@@ -0,0 +1,146 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dnconv
c
c\Description:
c Convergence testing for the nonsymmetric Arnoldi eigenvalue routine.
c
c\Usage:
c call dnconv
c ( N, RITZR, RITZI, BOUNDS, TOL, NCONV )
c
c\Arguments
c N Integer. (INPUT)
c Number of Ritz values to check for convergence.
c
c RITZR, Double precision arrays of length N. (INPUT)
c RITZI Real and imaginary parts of the Ritz values to be checked
c for convergence.
c BOUNDS Double precision array of length N. (INPUT)
c Ritz estimates for the Ritz values in RITZR and RITZI.
c
c TOL Double precision scalar. (INPUT)
c Desired backward error for a Ritz value to be considered
c "converged".
c
c NCONV Integer scalar. (OUTPUT)
c Number of "converged" Ritz values.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c second ARPACK utility routine for timing.
c dlamch LAPACK routine that determines machine constants.
c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: nconv.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2
c
c\Remarks
c 1. xxxx
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dnconv (n, ritzr, ritzi, bounds, tol, nconv)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer n, nconv
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
Double precision
& ritzr(n), ritzi(n), bounds(n)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i
Double precision
& temp, eps23
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dlapy2, dlamch
external dlapy2, dlamch
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------------------------------------%
c | Convergence test: unlike in the symmetric code, I am not |
c | using things like refined error bounds and gap condition |
c | because I don't know the exact equivalent concept. |
c | |
c | Instead the i-th Ritz value is considered "converged" when: |
c | |
c | bounds(i) .le. ( TOL * | ritz | ) |
c | |
c | for some appropriate choice of norm. |
c %-------------------------------------------------------------%
c
call second (t0)
c
c %---------------------------------%
c | Get machine dependent constant. |
c %---------------------------------%
c
eps23 = dlamch('Epsilon-Machine')
eps23 = eps23**(2.0D+0 / 3.0D+0)
c
nconv = 0
do 20 i = 1, n
temp = max( eps23, dlapy2( ritzr(i), ritzi(i) ) )
if (bounds(i) .le. tol*temp) nconv = nconv + 1
20 continue
c
call second (t1)
tnconv = tnconv + (t1 - t0)
c
return
c
c %---------------%
c | End of dnconv |
c %---------------%
c
end

314
arpack/ARPACK/SRC/dneigh.f Normal file
View File

@@ -0,0 +1,314 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dneigh
c
c\Description:
c Compute the eigenvalues of the current upper Hessenberg matrix
c and the corresponding Ritz estimates given the current residual norm.
c
c\Usage:
c call dneigh
c ( RNORM, N, H, LDH, RITZR, RITZI, BOUNDS, Q, LDQ, WORKL, IERR )
c
c\Arguments
c RNORM Double precision scalar. (INPUT)
c Residual norm corresponding to the current upper Hessenberg
c matrix H.
c
c N Integer. (INPUT)
c Size of the matrix H.
c
c H Double precision N by N array. (INPUT)
c H contains the current upper Hessenberg matrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RITZR, Double precision arrays of length N. (OUTPUT)
c RITZI On output, RITZR(1:N) (resp. RITZI(1:N)) contains the real
c (respectively imaginary) parts of the eigenvalues of H.
c
c BOUNDS Double precision array of length N. (OUTPUT)
c On output, BOUNDS contains the Ritz estimates associated with
c the eigenvalues RITZR and RITZI. This is equal to RNORM
c times the last components of the eigenvectors corresponding
c to the eigenvalues in RITZR and RITZI.
c
c Q Double precision N by N array. (WORKSPACE)
c Workspace needed to store the eigenvectors of H.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Double precision work array of length N**2 + 3*N. (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. This is needed to keep the full Schur form
c of H and also in the calculation of the eigenvectors of H.
c
c IERR Integer. (OUTPUT)
c Error exit flag from dlaqrb or dtrevc.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c dlaqrb ARPACK routine to compute the real Schur form of an
c upper Hessenberg matrix and last row of the Schur vectors.
c second ARPACK utility routine for timing.
c dmout ARPACK utility routine that prints matrices
c dvout ARPACK utility routine that prints vectors.
c dlacpy LAPACK matrix copy routine.
c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c dtrevc LAPACK routine to compute the eigenvectors of a matrix
c in upper quasi-triangular form
c dgemv Level 2 BLAS routine for matrix vector multiplication.
c dcopy Level 1 BLAS that copies one vector to another .
c dnrm2 Level 1 BLAS that computes the norm of a vector.
c dscal Level 1 BLAS that scales a vector.
c
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: neigh.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2
c
c\Remarks
c None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dneigh (rnorm, n, h, ldh, ritzr, ritzi, bounds,
& q, ldq, workl, ierr)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer ierr, n, ldh, ldq
Double precision
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& bounds(n), h(ldh,n), q(ldq,n), ritzi(n), ritzr(n),
& workl(n*(n+3))
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0, zero = 0.0D+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
logical select(1)
integer i, iconj, msglvl
Double precision
& temp, vl(1)
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dcopy, dlacpy, dlaqrb, dtrevc, dvout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dlapy2, dnrm2
external dlapy2, dnrm2
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic abs
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mneigh
c
if (msglvl .gt. 2) then
call dmout (logfil, n, n, h, ldh, ndigit,
& '_neigh: Entering upper Hessenberg matrix H ')
end if
c
c %-----------------------------------------------------------%
c | 1. Compute the eigenvalues, the last components of the |
c | corresponding Schur vectors and the full Schur form T |
c | of the current upper Hessenberg matrix H. |
c | dlaqrb returns the full Schur form of H in WORKL(1:N**2) |
c | and the last components of the Schur vectors in BOUNDS. |
c %-----------------------------------------------------------%
c
call dlacpy ('All', n, n, h, ldh, workl, n)
call dlaqrb (.true., n, 1, n, workl, n, ritzr, ritzi, bounds,
& ierr)
if (ierr .ne. 0) go to 9000
c
if (msglvl .gt. 1) then
call dvout (logfil, n, bounds, ndigit,
& '_neigh: last row of the Schur matrix for H')
end if
c
c %-----------------------------------------------------------%
c | 2. Compute the eigenvectors of the full Schur form T and |
c | apply the last components of the Schur vectors to get |
c | the last components of the corresponding eigenvectors. |
c | Remember that if the i-th and (i+1)-st eigenvalues are |
c | complex conjugate pairs, then the real & imaginary part |
c | of the eigenvector components are split across adjacent |
c | columns of Q. |
c %-----------------------------------------------------------%
c
call dtrevc ('R', 'A', select, n, workl, n, vl, n, q, ldq,
& n, n, workl(n*n+1), ierr)
c
if (ierr .ne. 0) go to 9000
c
c %------------------------------------------------%
c | Scale the returning eigenvectors so that their |
c | euclidean norms are all one. LAPACK subroutine |
c | dtrevc returns each eigenvector normalized so |
c | that the element of largest magnitude has |
c | magnitude 1; here the magnitude of a complex |
c | number (x,y) is taken to be |x| + |y|. |
c %------------------------------------------------%
c
iconj = 0
do 10 i=1, n
if ( abs( ritzi(i) ) .le. zero ) then
c
c %----------------------%
c | Real eigenvalue case |
c %----------------------%
c
temp = dnrm2( n, q(1,i), 1 )
call dscal ( n, one / temp, q(1,i), 1 )
else
c
c %-------------------------------------------%
c | Complex conjugate pair case. Note that |
c | since the real and imaginary part of |
c | the eigenvector are stored in consecutive |
c | columns, we further normalize by the |
c | square root of two. |
c %-------------------------------------------%
c
if (iconj .eq. 0) then
temp = dlapy2( dnrm2( n, q(1,i), 1 ),
& dnrm2( n, q(1,i+1), 1 ) )
call dscal ( n, one / temp, q(1,i), 1 )
call dscal ( n, one / temp, q(1,i+1), 1 )
iconj = 1
else
iconj = 0
end if
end if
10 continue
c
call dgemv ('T', n, n, one, q, ldq, bounds, 1, zero, workl, 1)
c
if (msglvl .gt. 1) then
call dvout (logfil, n, workl, ndigit,
& '_neigh: Last row of the eigenvector matrix for H')
end if
c
c %----------------------------%
c | Compute the Ritz estimates |
c %----------------------------%
c
iconj = 0
do 20 i = 1, n
if ( abs( ritzi(i) ) .le. zero ) then
c
c %----------------------%
c | Real eigenvalue case |
c %----------------------%
c
bounds(i) = rnorm * abs( workl(i) )
else
c
c %-------------------------------------------%
c | Complex conjugate pair case. Note that |
c | since the real and imaginary part of |
c | the eigenvector are stored in consecutive |
c | columns, we need to take the magnitude |
c | of the last components of the two vectors |
c %-------------------------------------------%
c
if (iconj .eq. 0) then
bounds(i) = rnorm * dlapy2( workl(i), workl(i+1) )
bounds(i+1) = bounds(i)
iconj = 1
else
iconj = 0
end if
end if
20 continue
c
if (msglvl .gt. 2) then
call dvout (logfil, n, ritzr, ndigit,
& '_neigh: Real part of the eigenvalues of H')
call dvout (logfil, n, ritzi, ndigit,
& '_neigh: Imaginary part of the eigenvalues of H')
call dvout (logfil, n, bounds, ndigit,
& '_neigh: Ritz estimates for the eigenvalues of H')
end if
c
call second (t1)
tneigh = tneigh + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of dneigh |
c %---------------%
c
end

1063
arpack/ARPACK/SRC/dneupd.f Normal file

File diff suppressed because it is too large Load Diff

231
arpack/ARPACK/SRC/dngets.f Normal file
View File

@@ -0,0 +1,231 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dngets
c
c\Description:
c Given the eigenvalues of the upper Hessenberg matrix H,
c computes the NP shifts AMU that are zeros of the polynomial of
c degree NP which filters out components of the unwanted eigenvectors
c corresponding to the AMU's based on some given criteria.
c
c NOTE: call this even in the case of user specified shifts in order
c to sort the eigenvalues, and error bounds of H for later use.
c
c\Usage:
c call dngets
c ( ISHIFT, WHICH, KEV, NP, RITZR, RITZI, BOUNDS, SHIFTR, SHIFTI )
c
c\Arguments
c ISHIFT Integer. (INPUT)
c Method for selecting the implicit shifts at each iteration.
c ISHIFT = 0: user specified shifts
c ISHIFT = 1: exact shift with respect to the matrix H.
c
c WHICH Character*2. (INPUT)
c Shift selection criteria.
c 'LM' -> want the KEV eigenvalues of largest magnitude.
c 'SM' -> want the KEV eigenvalues of smallest magnitude.
c 'LR' -> want the KEV eigenvalues of largest real part.
c 'SR' -> want the KEV eigenvalues of smallest real part.
c 'LI' -> want the KEV eigenvalues of largest imaginary part.
c 'SI' -> want the KEV eigenvalues of smallest imaginary part.
c
c KEV Integer. (INPUT/OUTPUT)
c INPUT: KEV+NP is the size of the matrix H.
c OUTPUT: Possibly increases KEV by one to keep complex conjugate
c pairs together.
c
c NP Integer. (INPUT/OUTPUT)
c Number of implicit shifts to be computed.
c OUTPUT: Possibly decreases NP by one to keep complex conjugate
c pairs together.
c
c RITZR, Double precision array of length KEV+NP. (INPUT/OUTPUT)
c RITZI On INPUT, RITZR and RITZI contain the real and imaginary
c parts of the eigenvalues of H.
c On OUTPUT, RITZR and RITZI are sorted so that the unwanted
c eigenvalues are in the first NP locations and the wanted
c portion is in the last KEV locations. When exact shifts are
c selected, the unwanted part corresponds to the shifts to
c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues
c are further sorted so that the ones with largest Ritz values
c are first.
c
c BOUNDS Double precision array of length KEV+NP. (INPUT/OUTPUT)
c Error bounds corresponding to the ordering in RITZ.
c
c SHIFTR, SHIFTI *** USE deprecated as of version 2.1. ***
c
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c dsortc ARPACK sorting routine.
c dcopy Level 1 BLAS that copies one vector to another .
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: ngets.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2
c
c\Remarks
c 1. xxxx
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dngets ( ishift, which, kev, np, ritzr, ritzi, bounds,
& shiftr, shifti )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
integer ishift, kev, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& bounds(kev+np), ritzr(kev+np), ritzi(kev+np),
& shiftr(1), shifti(1)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0, zero = 0.0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer msglvl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dcopy, dsortc, second
c
c %----------------------%
c | Intrinsics Functions |
c %----------------------%
c
intrinsic abs
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mngets
c
c %----------------------------------------------------%
c | LM, SM, LR, SR, LI, SI case. |
c | Sort the eigenvalues of H into the desired order |
c | and apply the resulting order to BOUNDS. |
c | The eigenvalues are sorted so that the wanted part |
c | are always in the last KEV locations. |
c | We first do a pre-processing sort in order to keep |
c | complex conjugate pairs together |
c %----------------------------------------------------%
c
if (which .eq. 'LM') then
call dsortc ('LR', .true., kev+np, ritzr, ritzi, bounds)
else if (which .eq. 'SM') then
call dsortc ('SR', .true., kev+np, ritzr, ritzi, bounds)
else if (which .eq. 'LR') then
call dsortc ('LM', .true., kev+np, ritzr, ritzi, bounds)
else if (which .eq. 'SR') then
call dsortc ('SM', .true., kev+np, ritzr, ritzi, bounds)
else if (which .eq. 'LI') then
call dsortc ('LM', .true., kev+np, ritzr, ritzi, bounds)
else if (which .eq. 'SI') then
call dsortc ('SM', .true., kev+np, ritzr, ritzi, bounds)
end if
c
call dsortc (which, .true., kev+np, ritzr, ritzi, bounds)
c
c %-------------------------------------------------------%
c | Increase KEV by one if the ( ritzr(np),ritzi(np) ) |
c | = ( ritzr(np+1),-ritzi(np+1) ) and ritz(np) .ne. zero |
c | Accordingly decrease NP by one. In other words keep |
c | complex conjugate pairs together. |
c %-------------------------------------------------------%
c
if ( ( ritzr(np+1) - ritzr(np) ) .eq. zero
& .and. ( ritzi(np+1) + ritzi(np) ) .eq. zero ) then
np = np - 1
kev = kev + 1
end if
c
if ( ishift .eq. 1 ) then
c
c %-------------------------------------------------------%
c | Sort the unwanted Ritz values used as shifts so that |
c | the ones with largest Ritz estimates are first |
c | This will tend to minimize the effects of the |
c | forward instability of the iteration when they shifts |
c | are applied in subroutine dnapps. |
c | Be careful and use 'SR' since we want to sort BOUNDS! |
c %-------------------------------------------------------%
c
call dsortc ( 'SR', .true., np, bounds, ritzr, ritzi )
end if
c
call second (t1)
tngets = tngets + (t1 - t0)
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, kev, ndigit, '_ngets: KEV is')
call ivout (logfil, 1, np, ndigit, '_ngets: NP is')
call dvout (logfil, kev+np, ritzr, ndigit,
& '_ngets: Eigenvalues of current H matrix -- real part')
call dvout (logfil, kev+np, ritzi, ndigit,
& '_ngets: Eigenvalues of current H matrix -- imag part')
call dvout (logfil, kev+np, bounds, ndigit,
& '_ngets: Ritz estimates of the current KEV+NP Ritz values')
end if
c
return
c
c %---------------%
c | End of dngets |
c %---------------%
c
end

853
arpack/ARPACK/SRC/dsaitr.f Normal file
View File

@@ -0,0 +1,853 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dsaitr
c
c\Description:
c Reverse communication interface for applying NP additional steps to
c a K step symmetric Arnoldi factorization.
c
c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T
c
c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0.
c
c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T
c
c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0.
c
c where OP and B are as in dsaupd. The B-norm of r_{k+p} is also
c computed and returned.
c
c\Usage:
c call dsaitr
c ( IDO, BMAT, N, K, NP, MODE, RESID, RNORM, V, LDV, H, LDH,
c IPNTR, WORKD, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag.
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c This is for the restart phase to force the new
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y,
c IPNTR(3) is the pointer into WORK for B * X.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c IDO = 99: done
c -------------------------------------------------------------
c When the routine is used in the "shift-and-invert" mode, the
c vector B * Q is already available and does not need to be
c recomputed in forming OP * Q.
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of matrix B that defines the
c semi-inner product for the operator OP. See dsaupd.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*M*x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c K Integer. (INPUT)
c Current order of H and the number of columns of V.
c
c NP Integer. (INPUT)
c Number of additional Arnoldi steps to take.
c
c MODE Integer. (INPUT)
c Signifies which form for "OP". If MODE=2 then
c a reduction in the number of B matrix vector multiplies
c is possible since the B-norm of OP*x is equivalent to
c the inv(B)-norm of A*x.
c
c RESID Double precision array of length N. (INPUT/OUTPUT)
c On INPUT: RESID contains the residual vector r_{k}.
c On OUTPUT: RESID contains the residual vector r_{k+p}.
c
c RNORM Double precision scalar. (INPUT/OUTPUT)
c On INPUT the B-norm of r_{k}.
c On OUTPUT the B-norm of the updated residual r_{k+p}.
c
c V Double precision N by K+NP array. (INPUT/OUTPUT)
c On INPUT: V contains the Arnoldi vectors in the first K
c columns.
c On OUTPUT: V contains the new NP Arnoldi vectors in the next
c NP columns. The first K columns are unchanged.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Double precision (K+NP) by 2 array. (INPUT/OUTPUT)
c H is used to store the generated symmetric tridiagonal matrix
c with the subdiagonal in the first column starting at H(2,1)
c and the main diagonal in the second column.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORK for
c vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in the
c shift-and-invert mode. X is the current operand.
c -------------------------------------------------------------
c
c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The calling program should not
c use WORKD as temporary workspace during the iteration !!!!!!
c On INPUT, WORKD(1:N) = B*RESID where RESID is associated
c with the K step Arnoldi factorization. Used to save some
c computation at the first step.
c On OUTPUT, WORKD(1:N) = B*RESID where RESID is associated
c with the K+NP step Arnoldi factorization.
c
c INFO Integer. (OUTPUT)
c = 0: Normal exit.
c > 0: Size of an invariant subspace of OP is found that is
c less than K + NP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c dgetv0 ARPACK routine to generate the initial vector.
c ivout ARPACK utility routine that prints integers.
c dmout ARPACK utility routine that prints matrices.
c dvout ARPACK utility routine that prints vectors.
c dlamch LAPACK routine that determines machine constants.
c dlascl LAPACK routine for careful scaling of a matrix.
c dgemv Level 2 BLAS routine for matrix vector multiplication.
c daxpy Level 1 BLAS that computes a vector triad.
c dscal Level 1 BLAS that scales a vector.
c dcopy Level 1 BLAS that copies one vector to another .
c ddot Level 1 BLAS that computes the scalar product of two vectors.
c dnrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/93: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: saitr.F SID: 2.6 DATE OF SID: 8/28/96 RELEASE: 2
c
c\Remarks
c The algorithm implemented is:
c
c restart = .false.
c Given V_{k} = [v_{1}, ..., v_{k}], r_{k};
c r_{k} contains the initial residual vector even for k = 0;
c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already
c computed by the calling program.
c
c betaj = rnorm ; p_{k+1} = B*r_{k} ;
c For j = k+1, ..., k+np Do
c 1) if ( betaj < tol ) stop or restart depending on j.
c if ( restart ) generate a new starting vector.
c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}];
c p_{j} = p_{j}/betaj
c 3) r_{j} = OP*v_{j} where OP is defined as in dsaupd
c For shift-invert mode p_{j} = B*v_{j} is already available.
c wnorm = || OP*v_{j} ||
c 4) Compute the j-th step residual vector.
c w_{j} = V_{j}^T * B * OP * v_{j}
c r_{j} = OP*v_{j} - V_{j} * w_{j}
c alphaj <- j-th component of w_{j}
c rnorm = || r_{j} ||
c betaj+1 = rnorm
c If (rnorm > 0.717*wnorm) accept step and go back to 1)
c 5) Re-orthogonalization step:
c s = V_{j}'*B*r_{j}
c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} ||
c alphaj = alphaj + s_{j};
c 6) Iterative refinement step:
c If (rnorm1 > 0.717*rnorm) then
c rnorm = rnorm1
c accept step and go back to 1)
c Else
c rnorm = rnorm1
c If this is the first time in step 6), go to 5)
c Else r_{j} lies in the span of V_{j} numerically.
c Set r_{j} = 0 and rnorm = 0; go to 1)
c EndIf
c End Do
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dsaitr
& (ido, bmat, n, k, np, mode, resid, rnorm, v, ldv, h, ldh,
& ipntr, workd, info)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1
integer ido, info, k, ldh, ldv, n, mode, np
Double precision
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Double precision
& h(ldh,2), resid(n), v(ldv,k+np), workd(3*n)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0, zero = 0.0D+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
logical first, orth1, orth2, rstart, step3, step4
integer i, ierr, ipj, irj, ivj, iter, itry, j, msglvl,
& infol, jj
Double precision
& rnorm1, wnorm, safmin, temp1
save orth1, orth2, rstart, step3, step4,
& ierr, ipj, irj, ivj, iter, itry, j, msglvl,
& rnorm1, safmin, wnorm
c
c %-----------------------%
c | Local Array Arguments |
c %-----------------------%
c
Double precision
& xtemp(2)
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external daxpy, dcopy, dscal, dgemv, dgetv0, dvout, dmout,
& dlascl, ivout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& ddot, dnrm2, dlamch
external ddot, dnrm2, dlamch
c
c %-----------------%
c | Data statements |
c %-----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
first = .false.
c
c %--------------------------------%
c | safmin = safe minimum is such |
c | that 1/sfmin does not overflow |
c %--------------------------------%
c
safmin = dlamch('safmin')
end if
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = msaitr
c
c %------------------------------%
c | Initial call to this routine |
c %------------------------------%
c
info = 0
step3 = .false.
step4 = .false.
rstart = .false.
orth1 = .false.
orth2 = .false.
c
c %--------------------------------%
c | Pointer to the current step of |
c | the factorization to build |
c %--------------------------------%
c
j = k + 1
c
c %------------------------------------------%
c | Pointers used for reverse communication |
c | when using WORKD. |
c %------------------------------------------%
c
ipj = 1
irj = ipj + n
ivj = irj + n
end if
c
c %-------------------------------------------------%
c | When in reverse communication mode one of: |
c | STEP3, STEP4, ORTH1, ORTH2, RSTART |
c | will be .true. |
c | STEP3: return from computing OP*v_{j}. |
c | STEP4: return from computing B-norm of OP*v_{j} |
c | ORTH1: return from computing B-norm of r_{j+1} |
c | ORTH2: return from computing B-norm of |
c | correction to the residual vector. |
c | RSTART: return from OP computations needed by |
c | dgetv0. |
c %-------------------------------------------------%
c
if (step3) go to 50
if (step4) go to 60
if (orth1) go to 70
if (orth2) go to 90
if (rstart) go to 30
c
c %------------------------------%
c | Else this is the first step. |
c %------------------------------%
c
c %--------------------------------------------------------------%
c | |
c | A R N O L D I I T E R A T I O N L O O P |
c | |
c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) |
c %--------------------------------------------------------------%
c
1000 continue
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, j, ndigit,
& '_saitr: generating Arnoldi vector no.')
call dvout (logfil, 1, rnorm, ndigit,
& '_saitr: B-norm of the current residual =')
end if
c
c %---------------------------------------------------------%
c | Check for exact zero. Equivalent to determing whether a |
c | j-step Arnoldi factorization is present. |
c %---------------------------------------------------------%
c
if (rnorm .gt. zero) go to 40
c
c %---------------------------------------------------%
c | Invariant subspace found, generate a new starting |
c | vector which is orthogonal to the current Arnoldi |
c | basis and continue the iteration. |
c %---------------------------------------------------%
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, j, ndigit,
& '_saitr: ****** restart at step ******')
end if
c
c %---------------------------------------------%
c | ITRY is the loop variable that controls the |
c | maximum amount of times that a restart is |
c | attempted. NRSTRT is used by stat.h |
c %---------------------------------------------%
c
nrstrt = nrstrt + 1
itry = 1
20 continue
rstart = .true.
ido = 0
30 continue
c
c %--------------------------------------%
c | If in reverse communication mode and |
c | RSTART = .true. flow returns here. |
c %--------------------------------------%
c
call dgetv0 (ido, bmat, itry, .false., n, j, v, ldv,
& resid, rnorm, ipntr, workd, ierr)
if (ido .ne. 99) go to 9000
if (ierr .lt. 0) then
itry = itry + 1
if (itry .le. 3) go to 20
c
c %------------------------------------------------%
c | Give up after several restart attempts. |
c | Set INFO to the size of the invariant subspace |
c | which spans OP and exit. |
c %------------------------------------------------%
c
info = j - 1
call second (t1)
tsaitr = tsaitr + (t1 - t0)
ido = 99
go to 9000
end if
c
40 continue
c
c %---------------------------------------------------------%
c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm |
c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow |
c | when reciprocating a small RNORM, test against lower |
c | machine bound. |
c %---------------------------------------------------------%
c
call dcopy (n, resid, 1, v(1,j), 1)
if (rnorm .ge. safmin) then
temp1 = one / rnorm
call dscal (n, temp1, v(1,j), 1)
call dscal (n, temp1, workd(ipj), 1)
else
c
c %-----------------------------------------%
c | To scale both v_{j} and p_{j} carefully |
c | use LAPACK routine SLASCL |
c %-----------------------------------------%
c
call dlascl ('General', i, i, rnorm, one, n, 1,
& v(1,j), n, infol)
call dlascl ('General', i, i, rnorm, one, n, 1,
& workd(ipj), n, infol)
end if
c
c %------------------------------------------------------%
c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} |
c | Note that this is not quite yet r_{j}. See STEP 4 |
c %------------------------------------------------------%
c
step3 = .true.
nopx = nopx + 1
call second (t2)
call dcopy (n, v(1,j), 1, workd(ivj), 1)
ipntr(1) = ivj
ipntr(2) = irj
ipntr(3) = ipj
ido = 1
c
c %-----------------------------------%
c | Exit in order to compute OP*v_{j} |
c %-----------------------------------%
c
go to 9000
50 continue
c
c %-----------------------------------%
c | Back from reverse communication; |
c | WORKD(IRJ:IRJ+N-1) := OP*v_{j}. |
c %-----------------------------------%
c
call second (t3)
tmvopx = tmvopx + (t3 - t2)
c
step3 = .false.
c
c %------------------------------------------%
c | Put another copy of OP*v_{j} into RESID. |
c %------------------------------------------%
c
call dcopy (n, workd(irj), 1, resid, 1)
c
c %-------------------------------------------%
c | STEP 4: Finish extending the symmetric |
c | Arnoldi to length j. If MODE = 2 |
c | then B*OP = B*inv(B)*A = A and |
c | we don't need to compute B*OP. |
c | NOTE: If MODE = 2 WORKD(IVJ:IVJ+N-1) is |
c | assumed to have A*v_{j}. |
c %-------------------------------------------%
c
if (mode .eq. 2) go to 65
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
step4 = .true.
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-------------------------------------%
c | Exit in order to compute B*OP*v_{j} |
c %-------------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call dcopy(n, resid, 1 , workd(ipj), 1)
end if
60 continue
c
c %-----------------------------------%
c | Back from reverse communication; |
c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j}. |
c %-----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
step4 = .false.
c
c %-------------------------------------%
c | The following is needed for STEP 5. |
c | Compute the B-norm of OP*v_{j}. |
c %-------------------------------------%
c
65 continue
if (mode .eq. 2) then
c
c %----------------------------------%
c | Note that the B-norm of OP*v_{j} |
c | is the inv(B)-norm of A*v_{j}. |
c %----------------------------------%
c
wnorm = ddot (n, resid, 1, workd(ivj), 1)
wnorm = sqrt(abs(wnorm))
else if (bmat .eq. 'G') then
wnorm = ddot (n, resid, 1, workd(ipj), 1)
wnorm = sqrt(abs(wnorm))
else if (bmat .eq. 'I') then
wnorm = dnrm2(n, resid, 1)
end if
c
c %-----------------------------------------%
c | Compute the j-th residual corresponding |
c | to the j step factorization. |
c | Use Classical Gram Schmidt and compute: |
c | w_{j} <- V_{j}^T * B * OP * v_{j} |
c | r_{j} <- OP*v_{j} - V_{j} * w_{j} |
c %-----------------------------------------%
c
c
c %------------------------------------------%
c | Compute the j Fourier coefficients w_{j} |
c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. |
c %------------------------------------------%
c
if (mode .ne. 2 ) then
call dgemv('T', n, j, one, v, ldv, workd(ipj), 1, zero,
& workd(irj), 1)
else if (mode .eq. 2) then
call dgemv('T', n, j, one, v, ldv, workd(ivj), 1, zero,
& workd(irj), 1)
end if
c
c %--------------------------------------%
c | Orthgonalize r_{j} against V_{j}. |
c | RESID contains OP*v_{j}. See STEP 3. |
c %--------------------------------------%
c
call dgemv('N', n, j, -one, v, ldv, workd(irj), 1, one,
& resid, 1)
c
c %--------------------------------------%
c | Extend H to have j rows and columns. |
c %--------------------------------------%
c
h(j,2) = workd(irj + j - 1)
if (j .eq. 1 .or. rstart) then
h(j,1) = zero
else
h(j,1) = rnorm
end if
call second (t4)
c
orth1 = .true.
iter = 0
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call dcopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*r_{j} |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call dcopy (n, resid, 1, workd(ipj), 1)
end if
70 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH1 = .true. |
c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
orth1 = .false.
c
c %------------------------------%
c | Compute the B-norm of r_{j}. |
c %------------------------------%
c
if (bmat .eq. 'G') then
rnorm = ddot (n, resid, 1, workd(ipj), 1)
rnorm = sqrt(abs(rnorm))
else if (bmat .eq. 'I') then
rnorm = dnrm2(n, resid, 1)
end if
c
c %-----------------------------------------------------------%
c | STEP 5: Re-orthogonalization / Iterative refinement phase |
c | Maximum NITER_ITREF tries. |
c | |
c | s = V_{j}^T * B * r_{j} |
c | r_{j} = r_{j} - V_{j}*s |
c | alphaj = alphaj + s_{j} |
c | |
c | The stopping criteria used for iterative refinement is |
c | discussed in Parlett's book SEP, page 107 and in Gragg & |
c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. |
c | Determine if we need to correct the residual. The goal is |
c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || |
c %-----------------------------------------------------------%
c
if (rnorm .gt. 0.717*wnorm) go to 100
nrorth = nrorth + 1
c
c %---------------------------------------------------%
c | Enter the Iterative refinement phase. If further |
c | refinement is necessary, loop back here. The loop |
c | variable is ITER. Perform a step of Classical |
c | Gram-Schmidt using all the Arnoldi vectors V_{j} |
c %---------------------------------------------------%
c
80 continue
c
if (msglvl .gt. 2) then
xtemp(1) = wnorm
xtemp(2) = rnorm
call dvout (logfil, 2, xtemp, ndigit,
& '_saitr: re-orthonalization ; wnorm and rnorm are')
end if
c
c %----------------------------------------------------%
c | Compute V_{j}^T * B * r_{j}. |
c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). |
c %----------------------------------------------------%
c
call dgemv ('T', n, j, one, v, ldv, workd(ipj), 1,
& zero, workd(irj), 1)
c
c %----------------------------------------------%
c | Compute the correction to the residual: |
c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). |
c | The correction to H is v(:,1:J)*H(1:J,1:J) + |
c | v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j, but only |
c | H(j,j) is updated. |
c %----------------------------------------------%
c
call dgemv ('N', n, j, -one, v, ldv, workd(irj), 1,
& one, resid, 1)
c
if (j .eq. 1 .or. rstart) h(j,1) = zero
h(j,2) = h(j,2) + workd(irj + j - 1)
c
orth2 = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call dcopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-----------------------------------%
c | Exit in order to compute B*r_{j}. |
c | r_{j} is the corrected residual. |
c %-----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call dcopy (n, resid, 1, workd(ipj), 1)
end if
90 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH2 = .true. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
c %-----------------------------------------------------%
c | Compute the B-norm of the corrected residual r_{j}. |
c %-----------------------------------------------------%
c
if (bmat .eq. 'G') then
rnorm1 = ddot (n, resid, 1, workd(ipj), 1)
rnorm1 = sqrt(abs(rnorm1))
else if (bmat .eq. 'I') then
rnorm1 = dnrm2(n, resid, 1)
end if
c
if (msglvl .gt. 0 .and. iter .gt. 0) then
call ivout (logfil, 1, j, ndigit,
& '_saitr: Iterative refinement for Arnoldi residual')
if (msglvl .gt. 2) then
xtemp(1) = rnorm
xtemp(2) = rnorm1
call dvout (logfil, 2, xtemp, ndigit,
& '_saitr: iterative refinement ; rnorm and rnorm1 are')
end if
end if
c
c %-----------------------------------------%
c | Determine if we need to perform another |
c | step of re-orthogonalization. |
c %-----------------------------------------%
c
if (rnorm1 .gt. 0.717*rnorm) then
c
c %--------------------------------%
c | No need for further refinement |
c %--------------------------------%
c
rnorm = rnorm1
c
else
c
c %-------------------------------------------%
c | Another step of iterative refinement step |
c | is required. NITREF is used by stat.h |
c %-------------------------------------------%
c
nitref = nitref + 1
rnorm = rnorm1
iter = iter + 1
if (iter .le. 1) go to 80
c
c %-------------------------------------------------%
c | Otherwise RESID is numerically in the span of V |
c %-------------------------------------------------%
c
do 95 jj = 1, n
resid(jj) = zero
95 continue
rnorm = zero
end if
c
c %----------------------------------------------%
c | Branch here directly if iterative refinement |
c | wasn't necessary or after at most NITER_REF |
c | steps of iterative refinement. |
c %----------------------------------------------%
c
100 continue
c
rstart = .false.
orth2 = .false.
c
call second (t5)
titref = titref + (t5 - t4)
c
c %----------------------------------------------------------%
c | Make sure the last off-diagonal element is non negative |
c | If not perform a similarity transformation on H(1:j,1:j) |
c | and scale v(:,j) by -1. |
c %----------------------------------------------------------%
c
if (h(j,1) .lt. zero) then
h(j,1) = -h(j,1)
if ( j .lt. k+np) then
call dscal(n, -one, v(1,j+1), 1)
else
call dscal(n, -one, resid, 1)
end if
end if
c
c %------------------------------------%
c | STEP 6: Update j = j+1; Continue |
c %------------------------------------%
c
j = j + 1
if (j .gt. k+np) then
call second (t1)
tsaitr = tsaitr + (t1 - t0)
ido = 99
c
if (msglvl .gt. 1) then
call dvout (logfil, k+np, h(1,2), ndigit,
& '_saitr: main diagonal of matrix H of step K+NP.')
if (k+np .gt. 1) then
call dvout (logfil, k+np-1, h(2,1), ndigit,
& '_saitr: sub diagonal of matrix H of step K+NP.')
end if
end if
c
go to 9000
end if
c
c %--------------------------------------------------------%
c | Loop back to extend the factorization by another step. |
c %--------------------------------------------------------%
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
9000 continue
return
c
c %---------------%
c | End of dsaitr |
c %---------------%
c
end

516
arpack/ARPACK/SRC/dsapps.f Normal file
View File

@@ -0,0 +1,516 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dsapps
c
c\Description:
c Given the Arnoldi factorization
c
c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T,
c
c apply NP shifts implicitly resulting in
c
c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q
c
c where Q is an orthogonal matrix of order KEV+NP. Q is the product of
c rotations resulting from the NP bulge chasing sweeps. The updated Arnoldi
c factorization becomes:
c
c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T.
c
c\Usage:
c call dsapps
c ( N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, WORKD )
c
c\Arguments
c N Integer. (INPUT)
c Problem size, i.e. dimension of matrix A.
c
c KEV Integer. (INPUT)
c INPUT: KEV+NP is the size of the input matrix H.
c OUTPUT: KEV is the size of the updated matrix HNEW.
c
c NP Integer. (INPUT)
c Number of implicit shifts to be applied.
c
c SHIFT Double precision array of length NP. (INPUT)
c The shifts to be applied.
c
c V Double precision N by (KEV+NP) array. (INPUT/OUTPUT)
c INPUT: V contains the current KEV+NP Arnoldi vectors.
c OUTPUT: VNEW = V(1:n,1:KEV); the updated Arnoldi vectors
c are in the first KEV columns of V.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Double precision (KEV+NP) by 2 array. (INPUT/OUTPUT)
c INPUT: H contains the symmetric tridiagonal matrix of the
c Arnoldi factorization with the subdiagonal in the 1st column
c starting at H(2,1) and the main diagonal in the 2nd column.
c OUTPUT: H contains the updated tridiagonal matrix in the
c KEV leading submatrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RESID Double precision array of length (N). (INPUT/OUTPUT)
c INPUT: RESID contains the the residual vector r_{k+p}.
c OUTPUT: RESID is the updated residual vector rnew_{k}.
c
c Q Double precision KEV+NP by KEV+NP work array. (WORKSPACE)
c Work array used to accumulate the rotations during the bulge
c chase sweep.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKD Double precision work array of length 2*N. (WORKSPACE)
c Distributed array used in the application of the accumulated
c orthogonal matrix Q.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c dvout ARPACK utility routine that prints vectors.
c dlamch LAPACK routine that determines machine constants.
c dlartg LAPACK Givens rotation construction routine.
c dlacpy LAPACK matrix copy routine.
c dlaset LAPACK matrix initialization routine.
c dgemv Level 2 BLAS routine for matrix vector multiplication.
c daxpy Level 1 BLAS that computes a vector triad.
c dcopy Level 1 BLAS that copies one vector to another.
c dscal Level 1 BLAS that scales a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/16/93: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: sapps.F SID: 2.6 DATE OF SID: 3/28/97 RELEASE: 2
c
c\Remarks
c 1. In this version, each shift is applied to all the subblocks of
c the tridiagonal matrix H and not just to the submatrix that it
c comes from. This routine assumes that the subdiagonal elements
c of H that are stored in h(1:kev+np,1) are nonegative upon input
c and enforce this condition upon output. This version incorporates
c deflation. See code for documentation.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dsapps
& ( n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, workd )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer kev, ldh, ldq, ldv, n, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& h(ldh,2), q(ldq,kev+np), resid(n), shift(np),
& v(ldv,kev+np), workd(2*n)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0, zero = 0.0D+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, iend, istart, itop, j, jj, kplusp, msglvl
logical first
Double precision
& a1, a2, a3, a4, big, c, epsmch, f, g, r, s
save epsmch, first
c
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external daxpy, dcopy, dscal, dlacpy, dlartg, dlaset, dvout,
& ivout, second, dgemv
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dlamch
external dlamch
c
c %----------------------%
c | Intrinsics Functions |
c %----------------------%
c
intrinsic abs
c
c %----------------%
c | Data statments |
c %----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
epsmch = dlamch('Epsilon-Machine')
first = .false.
end if
itop = 1
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = msapps
c
kplusp = kev + np
c
c %----------------------------------------------%
c | Initialize Q to the identity matrix of order |
c | kplusp used to accumulate the rotations. |
c %----------------------------------------------%
c
call dlaset ('All', kplusp, kplusp, zero, one, q, ldq)
c
c %----------------------------------------------%
c | Quick return if there are no shifts to apply |
c %----------------------------------------------%
c
if (np .eq. 0) go to 9000
c
c %----------------------------------------------------------%
c | Apply the np shifts implicitly. Apply each shift to the |
c | whole matrix and not just to the submatrix from which it |
c | comes. |
c %----------------------------------------------------------%
c
do 90 jj = 1, np
c
istart = itop
c
c %----------------------------------------------------------%
c | Check for splitting and deflation. Currently we consider |
c | an off-diagonal element h(i+1,1) negligible if |
c | h(i+1,1) .le. epsmch*( |h(i,2)| + |h(i+1,2)| ) |
c | for i=1:KEV+NP-1. |
c | If above condition tests true then we set h(i+1,1) = 0. |
c | Note that h(1:KEV+NP,1) are assumed to be non negative. |
c %----------------------------------------------------------%
c
20 continue
c
c %------------------------------------------------%
c | The following loop exits early if we encounter |
c | a negligible off diagonal element. |
c %------------------------------------------------%
c
do 30 i = istart, kplusp-1
big = abs(h(i,2)) + abs(h(i+1,2))
if (h(i+1,1) .le. epsmch*big) then
if (msglvl .gt. 0) then
call ivout (logfil, 1, i, ndigit,
& '_sapps: deflation at row/column no.')
call ivout (logfil, 1, jj, ndigit,
& '_sapps: occured before shift number.')
call dvout (logfil, 1, h(i+1,1), ndigit,
& '_sapps: the corresponding off diagonal element')
end if
h(i+1,1) = zero
iend = i
go to 40
end if
30 continue
iend = kplusp
40 continue
c
if (istart .lt. iend) then
c
c %--------------------------------------------------------%
c | Construct the plane rotation G'(istart,istart+1,theta) |
c | that attempts to drive h(istart+1,1) to zero. |
c %--------------------------------------------------------%
c
f = h(istart,2) - shift(jj)
g = h(istart+1,1)
call dlartg (f, g, c, s, r)
c
c %-------------------------------------------------------%
c | Apply rotation to the left and right of H; |
c | H <- G' * H * G, where G = G(istart,istart+1,theta). |
c | This will create a "bulge". |
c %-------------------------------------------------------%
c
a1 = c*h(istart,2) + s*h(istart+1,1)
a2 = c*h(istart+1,1) + s*h(istart+1,2)
a4 = c*h(istart+1,2) - s*h(istart+1,1)
a3 = c*h(istart+1,1) - s*h(istart,2)
h(istart,2) = c*a1 + s*a2
h(istart+1,2) = c*a4 - s*a3
h(istart+1,1) = c*a3 + s*a4
c
c %----------------------------------------------------%
c | Accumulate the rotation in the matrix Q; Q <- Q*G |
c %----------------------------------------------------%
c
do 60 j = 1, min(istart+jj,kplusp)
a1 = c*q(j,istart) + s*q(j,istart+1)
q(j,istart+1) = - s*q(j,istart) + c*q(j,istart+1)
q(j,istart) = a1
60 continue
c
c
c %----------------------------------------------%
c | The following loop chases the bulge created. |
c | Note that the previous rotation may also be |
c | done within the following loop. But it is |
c | kept separate to make the distinction among |
c | the bulge chasing sweeps and the first plane |
c | rotation designed to drive h(istart+1,1) to |
c | zero. |
c %----------------------------------------------%
c
do 70 i = istart+1, iend-1
c
c %----------------------------------------------%
c | Construct the plane rotation G'(i,i+1,theta) |
c | that zeros the i-th bulge that was created |
c | by G(i-1,i,theta). g represents the bulge. |
c %----------------------------------------------%
c
f = h(i,1)
g = s*h(i+1,1)
c
c %----------------------------------%
c | Final update with G(i-1,i,theta) |
c %----------------------------------%
c
h(i+1,1) = c*h(i+1,1)
call dlartg (f, g, c, s, r)
c
c %-------------------------------------------%
c | The following ensures that h(1:iend-1,1), |
c | the first iend-2 off diagonal of elements |
c | H, remain non negative. |
c %-------------------------------------------%
c
if (r .lt. zero) then
r = -r
c = -c
s = -s
end if
c
c %--------------------------------------------%
c | Apply rotation to the left and right of H; |
c | H <- G * H * G', where G = G(i,i+1,theta) |
c %--------------------------------------------%
c
h(i,1) = r
c
a1 = c*h(i,2) + s*h(i+1,1)
a2 = c*h(i+1,1) + s*h(i+1,2)
a3 = c*h(i+1,1) - s*h(i,2)
a4 = c*h(i+1,2) - s*h(i+1,1)
c
h(i,2) = c*a1 + s*a2
h(i+1,2) = c*a4 - s*a3
h(i+1,1) = c*a3 + s*a4
c
c %----------------------------------------------------%
c | Accumulate the rotation in the matrix Q; Q <- Q*G |
c %----------------------------------------------------%
c
do 50 j = 1, min( i+jj, kplusp )
a1 = c*q(j,i) + s*q(j,i+1)
q(j,i+1) = - s*q(j,i) + c*q(j,i+1)
q(j,i) = a1
50 continue
c
70 continue
c
end if
c
c %--------------------------%
c | Update the block pointer |
c %--------------------------%
c
istart = iend + 1
c
c %------------------------------------------%
c | Make sure that h(iend,1) is non-negative |
c | If not then set h(iend,1) <-- -h(iend,1) |
c | and negate the last column of Q. |
c | We have effectively carried out a |
c | similarity on transformation H |
c %------------------------------------------%
c
if (h(iend,1) .lt. zero) then
h(iend,1) = -h(iend,1)
call dscal(kplusp, -one, q(1,iend), 1)
end if
c
c %--------------------------------------------------------%
c | Apply the same shift to the next block if there is any |
c %--------------------------------------------------------%
c
if (iend .lt. kplusp) go to 20
c
c %-----------------------------------------------------%
c | Check if we can increase the the start of the block |
c %-----------------------------------------------------%
c
do 80 i = itop, kplusp-1
if (h(i+1,1) .gt. zero) go to 90
itop = itop + 1
80 continue
c
c %-----------------------------------%
c | Finished applying the jj-th shift |
c %-----------------------------------%
c
90 continue
c
c %------------------------------------------%
c | All shifts have been applied. Check for |
c | more possible deflation that might occur |
c | after the last shift is applied. |
c %------------------------------------------%
c
do 100 i = itop, kplusp-1
big = abs(h(i,2)) + abs(h(i+1,2))
if (h(i+1,1) .le. epsmch*big) then
if (msglvl .gt. 0) then
call ivout (logfil, 1, i, ndigit,
& '_sapps: deflation at row/column no.')
call dvout (logfil, 1, h(i+1,1), ndigit,
& '_sapps: the corresponding off diagonal element')
end if
h(i+1,1) = zero
end if
100 continue
c
c %-------------------------------------------------%
c | Compute the (kev+1)-st column of (V*Q) and |
c | temporarily store the result in WORKD(N+1:2*N). |
c | This is not necessary if h(kev+1,1) = 0. |
c %-------------------------------------------------%
c
if ( h(kev+1,1) .gt. zero )
& call dgemv ('N', n, kplusp, one, v, ldv,
& q(1,kev+1), 1, zero, workd(n+1), 1)
c
c %-------------------------------------------------------%
c | Compute column 1 to kev of (V*Q) in backward order |
c | taking advantage that Q is an upper triangular matrix |
c | with lower bandwidth np. |
c | Place results in v(:,kplusp-kev:kplusp) temporarily. |
c %-------------------------------------------------------%
c
do 130 i = 1, kev
call dgemv ('N', n, kplusp-i+1, one, v, ldv,
& q(1,kev-i+1), 1, zero, workd, 1)
call dcopy (n, workd, 1, v(1,kplusp-i+1), 1)
130 continue
c
c %-------------------------------------------------%
c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). |
c %-------------------------------------------------%
c
call dlacpy ('All', n, kev, v(1,np+1), ldv, v, ldv)
c
c %--------------------------------------------%
c | Copy the (kev+1)-st column of (V*Q) in the |
c | appropriate place if h(kev+1,1) .ne. zero. |
c %--------------------------------------------%
c
if ( h(kev+1,1) .gt. zero )
& call dcopy (n, workd(n+1), 1, v(1,kev+1), 1)
c
c %-------------------------------------%
c | Update the residual vector: |
c | r <- sigmak*r + betak*v(:,kev+1) |
c | where |
c | sigmak = (e_{kev+p}'*Q)*e_{kev} |
c | betak = e_{kev+1}'*H*e_{kev} |
c %-------------------------------------%
c
call dscal (n, q(kplusp,kev), resid, 1)
if (h(kev+1,1) .gt. zero)
& call daxpy (n, h(kev+1,1), v(1,kev+1), 1, resid, 1)
c
if (msglvl .gt. 1) then
call dvout (logfil, 1, q(kplusp,kev), ndigit,
& '_sapps: sigmak of the updated residual vector')
call dvout (logfil, 1, h(kev+1,1), ndigit,
& '_sapps: betak of the updated residual vector')
call dvout (logfil, kev, h(1,2), ndigit,
& '_sapps: updated main diagonal of H for next iteration')
if (kev .gt. 1) then
call dvout (logfil, kev-1, h(2,1), ndigit,
& '_sapps: updated sub diagonal of H for next iteration')
end if
end if
c
call second (t1)
tsapps = tsapps + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of dsapps |
c %---------------%
c
end

850
arpack/ARPACK/SRC/dsaup2.f Normal file
View File

@@ -0,0 +1,850 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dsaup2
c
c\Description:
c Intermediate level interface called by dsaupd.
c
c\Usage:
c call dsaup2
c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD,
c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL,
c IPNTR, WORKD, INFO )
c
c\Arguments
c
c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in dsaupd.
c MODE, ISHIFT, MXITER: see the definition of IPARAM in dsaupd.
c
c NP Integer. (INPUT/OUTPUT)
c Contains the number of implicit shifts to apply during
c each Arnoldi/Lanczos iteration.
c If ISHIFT=1, NP is adjusted dynamically at each iteration
c to accelerate convergence and prevent stagnation.
c This is also roughly equal to the number of matrix-vector
c products (involving the operator OP) per Arnoldi iteration.
c The logic for adjusting is contained within the current
c subroutine.
c If ISHIFT=0, NP is the number of shifts the user needs
c to provide via reverse comunication. 0 < NP < NCV-NEV.
c NP may be less than NCV-NEV since a leading block of the current
c upper Tridiagonal matrix has split off and contains "unwanted"
c Ritz values.
c Upon termination of the IRA iteration, NP contains the number
c of "converged" wanted Ritz values.
c
c IUPD Integer. (INPUT)
c IUPD .EQ. 0: use explicit restart instead implicit update.
c IUPD .NE. 0: use implicit update.
c
c V Double precision N by (NEV+NP) array. (INPUT/OUTPUT)
c The Lanczos basis vectors.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Double precision (NEV+NP) by 2 array. (OUTPUT)
c H is used to store the generated symmetric tridiagonal matrix
c The subdiagonal is stored in the first column of H starting
c at H(2,1). The main diagonal is stored in the second column
c of H starting at H(1,2). If dsaup2 converges store the
c B-norm of the final residual vector in H(1,1).
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RITZ Double precision array of length NEV+NP. (OUTPUT)
c RITZ(1:NEV) contains the computed Ritz values of OP.
c
c BOUNDS Double precision array of length NEV+NP. (OUTPUT)
c BOUNDS(1:NEV) contain the error bounds corresponding to RITZ.
c
c Q Double precision (NEV+NP) by (NEV+NP) array. (WORKSPACE)
c Private (replicated) work array used to accumulate the
c rotation in the shift application step.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Double precision array of length at least 3*(NEV+NP). (INPUT/WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. It is used in the computation of the
c tridiagonal eigenvalue problem, the calculation and
c application of the shifts and convergence checking.
c If ISHIFT .EQ. O and IDO .EQ. 3, the first NP locations
c of WORKL are used in reverse communication to hold the user
c supplied shifts.
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORKD for
c vectors used by the Lanczos iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in one of
c the spectral transformation modes. X is the current
c operand.
c -------------------------------------------------------------
c
c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Lanczos iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration !!!!!!!!!!
c See Data Distribution Note in dsaupd.
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal return.
c = 1: All possible eigenvalues of OP has been found.
c NP returns the size of the invariant subspace
c spanning the operator OP.
c = 2: No shifts could be applied.
c = -8: Error return from trid. eigenvalue calculation;
c This should never happen.
c = -9: Starting vector is zero.
c = -9999: Could not build an Lanczos factorization.
c Size that was built in returned in NP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall,
c 1980.
c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program",
c Computer Physics Communications, 53 (1989), pp 169-179.
c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to
c Implement the Spectral Transformation", Math. Comp., 48 (1987),
c pp 663-673.
c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos
c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems",
c SIAM J. Matr. Anal. Apps., January (1993).
c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines
c for Updating the QR decomposition", ACM TOMS, December 1990,
c Volume 16 Number 4, pp 369-377.
c
c\Routines called:
c dgetv0 ARPACK initial vector generation routine.
c dsaitr ARPACK Lanczos factorization routine.
c dsapps ARPACK application of implicit shifts routine.
c dsconv ARPACK convergence of Ritz values routine.
c dseigt ARPACK compute Ritz values and error bounds routine.
c dsgets ARPACK reorder Ritz values and error bounds routine.
c dsortr ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c dvout ARPACK utility routine that prints vectors.
c dlamch LAPACK routine that determines machine constants.
c dcopy Level 1 BLAS that copies one vector to another.
c ddot Level 1 BLAS that computes the scalar product of two vectors.
c dnrm2 Level 1 BLAS that computes the norm of a vector.
c dscal Level 1 BLAS that scales a vector.
c dswap Level 1 BLAS that swaps two vectors.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/15/93: Version ' 2.4'
c xx/xx/95: Version ' 2.4'. (R.B. Lehoucq)
c
c\SCCS Information: @(#)
c FILE: saup2.F SID: 2.7 DATE OF SID: 5/19/98 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dsaup2
& ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, h, ldh, ritz, bounds,
& q, ldq, workl, ipntr, workd, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ishift, iupd, ldh, ldq, ldv, mxiter,
& n, mode, nev, np
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Double precision
& bounds(nev+np), h(ldh,2), q(ldq,nev+np), resid(n),
& ritz(nev+np), v(ldv,nev+np), workd(3*n),
& workl(3*(nev+np))
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0, zero = 0.0D+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
character wprime*2
logical cnorm, getv0, initv, update, ushift
integer ierr, iter, j, kplusp, msglvl, nconv, nevbef, nev0,
& np0, nptemp, nevd2, nevm2, kp(3)
Double precision
& rnorm, temp, eps23
save cnorm, getv0, initv, update, ushift,
& iter, kplusp, msglvl, nconv, nev0, np0,
& rnorm, eps23
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dcopy, dgetv0, dsaitr, dscal, dsconv, dseigt, dsgets,
& dsapps, dsortr, dvout, ivout, second, dswap
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& ddot, dnrm2, dlamch
external ddot, dnrm2, dlamch
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic min
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = msaup2
c
c %---------------------------------%
c | Set machine dependent constant. |
c %---------------------------------%
c
eps23 = dlamch('Epsilon-Machine')
eps23 = eps23**(2.0D+0/3.0D+0)
c
c %-------------------------------------%
c | nev0 and np0 are integer variables |
c | hold the initial values of NEV & NP |
c %-------------------------------------%
c
nev0 = nev
np0 = np
c
c %-------------------------------------%
c | kplusp is the bound on the largest |
c | Lanczos factorization built. |
c | nconv is the current number of |
c | "converged" eigenvlues. |
c | iter is the counter on the current |
c | iteration step. |
c %-------------------------------------%
c
kplusp = nev0 + np0
nconv = 0
iter = 0
c
c %--------------------------------------------%
c | Set flags for computing the first NEV steps |
c | of the Lanczos factorization. |
c %--------------------------------------------%
c
getv0 = .true.
update = .false.
ushift = .false.
cnorm = .false.
c
if (info .ne. 0) then
c
c %--------------------------------------------%
c | User provides the initial residual vector. |
c %--------------------------------------------%
c
initv = .true.
info = 0
else
initv = .false.
end if
end if
c
c %---------------------------------------------%
c | Get a possibly random starting vector and |
c | force it into the range of the operator OP. |
c %---------------------------------------------%
c
10 continue
c
if (getv0) then
call dgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm,
& ipntr, workd, info)
c
if (ido .ne. 99) go to 9000
c
if (rnorm .eq. zero) then
c
c %-----------------------------------------%
c | The initial vector is zero. Error exit. |
c %-----------------------------------------%
c
info = -9
go to 1200
end if
getv0 = .false.
ido = 0
end if
c
c %------------------------------------------------------------%
c | Back from reverse communication: continue with update step |
c %------------------------------------------------------------%
c
if (update) go to 20
c
c %-------------------------------------------%
c | Back from computing user specified shifts |
c %-------------------------------------------%
c
if (ushift) go to 50
c
c %-------------------------------------%
c | Back from computing residual norm |
c | at the end of the current iteration |
c %-------------------------------------%
c
if (cnorm) go to 100
c
c %----------------------------------------------------------%
c | Compute the first NEV steps of the Lanczos factorization |
c %----------------------------------------------------------%
c
call dsaitr (ido, bmat, n, 0, nev0, mode, resid, rnorm, v, ldv,
& h, ldh, ipntr, workd, info)
c
c %---------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP and possibly B |
c %---------------------------------------------------%
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
c
c %-----------------------------------------------------%
c | dsaitr was unable to build an Lanczos factorization |
c | of length NEV0. INFO is returned with the size of |
c | the factorization built. Exit main loop. |
c %-----------------------------------------------------%
c
np = info
mxiter = iter
info = -9999
go to 1200
end if
c
c %--------------------------------------------------------------%
c | |
c | M A I N LANCZOS I T E R A T I O N L O O P |
c | Each iteration implicitly restarts the Lanczos |
c | factorization in place. |
c | |
c %--------------------------------------------------------------%
c
1000 continue
c
iter = iter + 1
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, iter, ndigit,
& '_saup2: **** Start of major iteration number ****')
end if
if (msglvl .gt. 1) then
call ivout (logfil, 1, nev, ndigit,
& '_saup2: The length of the current Lanczos factorization')
call ivout (logfil, 1, np, ndigit,
& '_saup2: Extend the Lanczos factorization by')
end if
c
c %------------------------------------------------------------%
c | Compute NP additional steps of the Lanczos factorization. |
c %------------------------------------------------------------%
c
ido = 0
20 continue
update = .true.
c
call dsaitr (ido, bmat, n, nev, np, mode, resid, rnorm, v,
& ldv, h, ldh, ipntr, workd, info)
c
c %---------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP and possibly B |
c %---------------------------------------------------%
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
c
c %-----------------------------------------------------%
c | dsaitr was unable to build an Lanczos factorization |
c | of length NEV0+NP0. INFO is returned with the size |
c | of the factorization built. Exit main loop. |
c %-----------------------------------------------------%
c
np = info
mxiter = iter
info = -9999
go to 1200
end if
update = .false.
c
if (msglvl .gt. 1) then
call dvout (logfil, 1, rnorm, ndigit,
& '_saup2: Current B-norm of residual for factorization')
end if
c
c %--------------------------------------------------------%
c | Compute the eigenvalues and corresponding error bounds |
c | of the current symmetric tridiagonal matrix. |
c %--------------------------------------------------------%
c
call dseigt (rnorm, kplusp, h, ldh, ritz, bounds, workl, ierr)
c
if (ierr .ne. 0) then
info = -8
go to 1200
end if
c
c %----------------------------------------------------%
c | Make a copy of eigenvalues and corresponding error |
c | bounds obtained from _seigt. |
c %----------------------------------------------------%
c
call dcopy(kplusp, ritz, 1, workl(kplusp+1), 1)
call dcopy(kplusp, bounds, 1, workl(2*kplusp+1), 1)
c
c %---------------------------------------------------%
c | Select the wanted Ritz values and their bounds |
c | to be used in the convergence test. |
c | The selection is based on the requested number of |
c | eigenvalues instead of the current NEV and NP to |
c | prevent possible misconvergence. |
c | * Wanted Ritz values := RITZ(NP+1:NEV+NP) |
c | * Shifts := RITZ(1:NP) := WORKL(1:NP) |
c %---------------------------------------------------%
c
nev = nev0
np = np0
call dsgets (ishift, which, nev, np, ritz, bounds, workl)
c
c %-------------------%
c | Convergence test. |
c %-------------------%
c
call dcopy (nev, bounds(np+1), 1, workl(np+1), 1)
call dsconv (nev, ritz(np+1), workl(np+1), tol, nconv)
c
if (msglvl .gt. 2) then
kp(1) = nev
kp(2) = np
kp(3) = nconv
call ivout (logfil, 3, kp, ndigit,
& '_saup2: NEV, NP, NCONV are')
call dvout (logfil, kplusp, ritz, ndigit,
& '_saup2: The eigenvalues of H')
call dvout (logfil, kplusp, bounds, ndigit,
& '_saup2: Ritz estimates of the current NCV Ritz values')
end if
c
c %---------------------------------------------------------%
c | Count the number of unwanted Ritz values that have zero |
c | Ritz estimates. If any Ritz estimates are equal to zero |
c | then a leading block of H of order equal to at least |
c | the number of Ritz values with zero Ritz estimates has |
c | split off. None of these Ritz values may be removed by |
c | shifting. Decrease NP the number of shifts to apply. If |
c | no shifts may be applied, then prepare to exit |
c %---------------------------------------------------------%
c
nptemp = np
do 30 j=1, nptemp
if (bounds(j) .eq. zero) then
np = np - 1
nev = nev + 1
end if
30 continue
c
if ( (nconv .ge. nev0) .or.
& (iter .gt. mxiter) .or.
& (np .eq. 0) ) then
c
c %------------------------------------------------%
c | Prepare to exit. Put the converged Ritz values |
c | and corresponding bounds in RITZ(1:NCONV) and |
c | BOUNDS(1:NCONV) respectively. Then sort. Be |
c | careful when NCONV > NP since we don't want to |
c | swap overlapping locations. |
c %------------------------------------------------%
c
if (which .eq. 'BE') then
c
c %-----------------------------------------------------%
c | Both ends of the spectrum are requested. |
c | Sort the eigenvalues into algebraically decreasing |
c | order first then swap low end of the spectrum next |
c | to high end in appropriate locations. |
c | NOTE: when np < floor(nev/2) be careful not to swap |
c | overlapping locations. |
c %-----------------------------------------------------%
c
wprime = 'SA'
call dsortr (wprime, .true., kplusp, ritz, bounds)
nevd2 = nev0 / 2
nevm2 = nev0 - nevd2
if ( nev .gt. 1 ) then
call dswap ( min(nevd2,np), ritz(nevm2+1), 1,
& ritz( max(kplusp-nevd2+1,kplusp-np+1) ), 1)
call dswap ( min(nevd2,np), bounds(nevm2+1), 1,
& bounds( max(kplusp-nevd2+1,kplusp-np+1)), 1)
end if
c
else
c
c %--------------------------------------------------%
c | LM, SM, LA, SA case. |
c | Sort the eigenvalues of H into the an order that |
c | is opposite to WHICH, and apply the resulting |
c | order to BOUNDS. The eigenvalues are sorted so |
c | that the wanted part are always within the first |
c | NEV locations. |
c %--------------------------------------------------%
c
if (which .eq. 'LM') wprime = 'SM'
if (which .eq. 'SM') wprime = 'LM'
if (which .eq. 'LA') wprime = 'SA'
if (which .eq. 'SA') wprime = 'LA'
c
call dsortr (wprime, .true., kplusp, ritz, bounds)
c
end if
c
c %--------------------------------------------------%
c | Scale the Ritz estimate of each Ritz value |
c | by 1 / max(eps23,magnitude of the Ritz value). |
c %--------------------------------------------------%
c
do 35 j = 1, nev0
temp = max( eps23, abs(ritz(j)) )
bounds(j) = bounds(j)/temp
35 continue
c
c %----------------------------------------------------%
c | Sort the Ritz values according to the scaled Ritz |
c | esitmates. This will push all the converged ones |
c | towards the front of ritzr, ritzi, bounds |
c | (in the case when NCONV < NEV.) |
c %----------------------------------------------------%
c
wprime = 'LA'
call dsortr(wprime, .true., nev0, bounds, ritz)
c
c %----------------------------------------------%
c | Scale the Ritz estimate back to its original |
c | value. |
c %----------------------------------------------%
c
do 40 j = 1, nev0
temp = max( eps23, abs(ritz(j)) )
bounds(j) = bounds(j)*temp
40 continue
c
c %--------------------------------------------------%
c | Sort the "converged" Ritz values again so that |
c | the "threshold" values and their associated Ritz |
c | estimates appear at the appropriate position in |
c | ritz and bound. |
c %--------------------------------------------------%
c
if (which .eq. 'BE') then
c
c %------------------------------------------------%
c | Sort the "converged" Ritz values in increasing |
c | order. The "threshold" values are in the |
c | middle. |
c %------------------------------------------------%
c
wprime = 'LA'
call dsortr(wprime, .true., nconv, ritz, bounds)
c
else
c
c %----------------------------------------------%
c | In LM, SM, LA, SA case, sort the "converged" |
c | Ritz values according to WHICH so that the |
c | "threshold" value appears at the front of |
c | ritz. |
c %----------------------------------------------%
call dsortr(which, .true., nconv, ritz, bounds)
c
end if
c
c %------------------------------------------%
c | Use h( 1,1 ) as storage to communicate |
c | rnorm to _seupd if needed |
c %------------------------------------------%
c
h(1,1) = rnorm
c
if (msglvl .gt. 1) then
call dvout (logfil, kplusp, ritz, ndigit,
& '_saup2: Sorted Ritz values.')
call dvout (logfil, kplusp, bounds, ndigit,
& '_saup2: Sorted ritz estimates.')
end if
c
c %------------------------------------%
c | Max iterations have been exceeded. |
c %------------------------------------%
c
if (iter .gt. mxiter .and. nconv .lt. nev) info = 1
c
c %---------------------%
c | No shifts to apply. |
c %---------------------%
c
if (np .eq. 0 .and. nconv .lt. nev0) info = 2
c
np = nconv
go to 1100
c
else if (nconv .lt. nev .and. ishift .eq. 1) then
c
c %---------------------------------------------------%
c | Do not have all the requested eigenvalues yet. |
c | To prevent possible stagnation, adjust the number |
c | of Ritz values and the shifts. |
c %---------------------------------------------------%
c
nevbef = nev
nev = nev + min (nconv, np/2)
if (nev .eq. 1 .and. kplusp .ge. 6) then
nev = kplusp / 2
else if (nev .eq. 1 .and. kplusp .gt. 2) then
nev = 2
end if
np = kplusp - nev
c
c %---------------------------------------%
c | If the size of NEV was just increased |
c | resort the eigenvalues. |
c %---------------------------------------%
c
if (nevbef .lt. nev)
& call dsgets (ishift, which, nev, np, ritz, bounds,
& workl)
c
end if
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, nconv, ndigit,
& '_saup2: no. of "converged" Ritz values at this iter.')
if (msglvl .gt. 1) then
kp(1) = nev
kp(2) = np
call ivout (logfil, 2, kp, ndigit,
& '_saup2: NEV and NP are')
call dvout (logfil, nev, ritz(np+1), ndigit,
& '_saup2: "wanted" Ritz values.')
call dvout (logfil, nev, bounds(np+1), ndigit,
& '_saup2: Ritz estimates of the "wanted" values ')
end if
end if
c
if (ishift .eq. 0) then
c
c %-----------------------------------------------------%
c | User specified shifts: reverse communication to |
c | compute the shifts. They are returned in the first |
c | NP locations of WORKL. |
c %-----------------------------------------------------%
c
ushift = .true.
ido = 3
go to 9000
end if
c
50 continue
c
c %------------------------------------%
c | Back from reverse communication; |
c | User specified shifts are returned |
c | in WORKL(1:*NP) |
c %------------------------------------%
c
ushift = .false.
c
c
c %---------------------------------------------------------%
c | Move the NP shifts to the first NP locations of RITZ to |
c | free up WORKL. This is for the non-exact shift case; |
c | in the exact shift case, dsgets already handles this. |
c %---------------------------------------------------------%
c
if (ishift .eq. 0) call dcopy (np, workl, 1, ritz, 1)
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, np, ndigit,
& '_saup2: The number of shifts to apply ')
call dvout (logfil, np, workl, ndigit,
& '_saup2: shifts selected')
if (ishift .eq. 1) then
call dvout (logfil, np, bounds, ndigit,
& '_saup2: corresponding Ritz estimates')
end if
end if
c
c %---------------------------------------------------------%
c | Apply the NP0 implicit shifts by QR bulge chasing. |
c | Each shift is applied to the entire tridiagonal matrix. |
c | The first 2*N locations of WORKD are used as workspace. |
c | After dsapps is done, we have a Lanczos |
c | factorization of length NEV. |
c %---------------------------------------------------------%
c
call dsapps (n, nev, np, ritz, v, ldv, h, ldh, resid, q, ldq,
& workd)
c
c %---------------------------------------------%
c | Compute the B-norm of the updated residual. |
c | Keep B*RESID in WORKD(1:N) to be used in |
c | the first step of the next call to dsaitr. |
c %---------------------------------------------%
c
cnorm = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call dcopy (n, resid, 1, workd(n+1), 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*RESID |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call dcopy (n, resid, 1, workd, 1)
end if
c
100 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(1:N) := B*RESID |
c %----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
if (bmat .eq. 'G') then
rnorm = ddot (n, resid, 1, workd, 1)
rnorm = sqrt(abs(rnorm))
else if (bmat .eq. 'I') then
rnorm = dnrm2(n, resid, 1)
end if
cnorm = .false.
130 continue
c
if (msglvl .gt. 2) then
call dvout (logfil, 1, rnorm, ndigit,
& '_saup2: B-norm of residual for NEV factorization')
call dvout (logfil, nev, h(1,2), ndigit,
& '_saup2: main diagonal of compressed H matrix')
call dvout (logfil, nev-1, h(2,1), ndigit,
& '_saup2: subdiagonal of compressed H matrix')
end if
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
1100 continue
c
mxiter = iter
nev = nconv
c
1200 continue
ido = 99
c
c %------------%
c | Error exit |
c %------------%
c
call second (t1)
tsaup2 = t1 - t0
c
9000 continue
return
c
c %---------------%
c | End of dsaup2 |
c %---------------%
c
end

690
arpack/ARPACK/SRC/dsaupd.f Normal file
View File

@@ -0,0 +1,690 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dsaupd
c
c\Description:
c
c Reverse communication interface for the Implicitly Restarted Arnoldi
c Iteration. For symmetric problems this reduces to a variant of the Lanczos
c method. This method has been designed to compute approximations to a
c few eigenpairs of a linear operator OP that is real and symmetric
c with respect to a real positive semi-definite symmetric matrix B,
c i.e.
c
c B*OP = (OP`)*B.
c
c Another way to express this condition is
c
c < x,OPy > = < OPx,y > where < z,w > = z`Bw .
c
c In the standard eigenproblem B is the identity matrix.
c ( A` denotes transpose of A)
c
c The computed approximate eigenvalues are called Ritz values and
c the corresponding approximate eigenvectors are called Ritz vectors.
c
c dsaupd is usually called iteratively to solve one of the
c following problems:
c
c Mode 1: A*x = lambda*x, A symmetric
c ===> OP = A and B = I.
c
c Mode 2: A*x = lambda*M*x, A symmetric, M symmetric positive definite
c ===> OP = inv[M]*A and B = M.
c ===> (If M can be factored see remark 3 below)
c
c Mode 3: K*x = lambda*M*x, K symmetric, M symmetric positive semi-definite
c ===> OP = (inv[K - sigma*M])*M and B = M.
c ===> Shift-and-Invert mode
c
c Mode 4: K*x = lambda*KG*x, K symmetric positive semi-definite,
c KG symmetric indefinite
c ===> OP = (inv[K - sigma*KG])*K and B = K.
c ===> Buckling mode
c
c Mode 5: A*x = lambda*M*x, A symmetric, M symmetric positive semi-definite
c ===> OP = inv[A - sigma*M]*[A + sigma*M] and B = M.
c ===> Cayley transformed mode
c
c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v
c should be accomplished either by a direct method
c using a sparse matrix factorization and solving
c
c [A - sigma*M]*w = v or M*w = v,
c
c or through an iterative method for solving these
c systems. If an iterative method is used, the
c convergence test must be more stringent than
c the accuracy requirements for the eigenvalue
c approximations.
c
c\Usage:
c call dsaupd
c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM,
c IPNTR, WORKD, WORKL, LWORKL, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag. IDO must be zero on the first
c call to dsaupd . IDO will be set internally to
c indicate the type of operation to be performed. Control is
c then given back to the calling routine which has the
c responsibility to carry out the requested operation and call
c dsaupd with the result. The operand is given in
c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)).
c (If Mode = 2 see remark 5 below)
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c This is for the initialization phase to force the
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c In mode 3,4 and 5, the vector B * X is already
c available in WORKD(ipntr(3)). It does not
c need to be recomputed in forming OP * X.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c IDO = 3: compute the IPARAM(8) shifts where
c IPNTR(11) is the pointer into WORKL for
c placing the shifts. See remark 6 below.
c IDO = 99: done
c -------------------------------------------------------------
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B that defines the
c semi-inner product for the operator OP.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c WHICH Character*2. (INPUT)
c Specify which of the Ritz values of OP to compute.
c
c 'LA' - compute the NEV largest (algebraic) eigenvalues.
c 'SA' - compute the NEV smallest (algebraic) eigenvalues.
c 'LM' - compute the NEV largest (in magnitude) eigenvalues.
c 'SM' - compute the NEV smallest (in magnitude) eigenvalues.
c 'BE' - compute NEV eigenvalues, half from each end of the
c spectrum. When NEV is odd, compute one more from the
c high end than from the low end.
c (see remark 1 below)
c
c NEV Integer. (INPUT)
c Number of eigenvalues of OP to be computed. 0 < NEV < N.
c
c TOL Double precision scalar. (INPUT)
c Stopping criterion: the relative accuracy of the Ritz value
c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)).
c If TOL .LE. 0. is passed a default is set:
c DEFAULT = DLAMCH ('EPS') (machine precision as computed
c by the LAPACK auxiliary subroutine DLAMCH ).
c
c RESID Double precision array of length N. (INPUT/OUTPUT)
c On INPUT:
c If INFO .EQ. 0, a random initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c On OUTPUT:
c RESID contains the final residual vector.
c
c NCV Integer. (INPUT)
c Number of columns of the matrix V (less than or equal to N).
c This will indicate how many Lanczos vectors are generated
c at each iteration. After the startup phase in which NEV
c Lanczos vectors are generated, the algorithm generates
c NCV-NEV Lanczos vectors at each subsequent update iteration.
c Most of the cost in generating each Lanczos vector is in the
c matrix-vector product OP*x. (See remark 4 below).
c
c V Double precision N by NCV array. (OUTPUT)
c The NCV columns of V contain the Lanczos basis vectors.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c IPARAM Integer array of length 11. (INPUT/OUTPUT)
c IPARAM(1) = ISHIFT: method for selecting the implicit shifts.
c The shifts selected at each iteration are used to restart
c the Arnoldi iteration in an implicit fashion.
c -------------------------------------------------------------
c ISHIFT = 0: the shifts are provided by the user via
c reverse communication. The NCV eigenvalues of
c the current tridiagonal matrix T are returned in
c the part of WORKL array corresponding to RITZ.
c See remark 6 below.
c ISHIFT = 1: exact shifts with respect to the reduced
c tridiagonal matrix T. This is equivalent to
c restarting the iteration with a starting vector
c that is a linear combination of Ritz vectors
c associated with the "wanted" Ritz values.
c -------------------------------------------------------------
c
c IPARAM(2) = LEVEC
c No longer referenced. See remark 2 below.
c
c IPARAM(3) = MXITER
c On INPUT: maximum number of Arnoldi update iterations allowed.
c On OUTPUT: actual number of Arnoldi update iterations taken.
c
c IPARAM(4) = NB: blocksize to be used in the recurrence.
c The code currently works only for NB = 1.
c
c IPARAM(5) = NCONV: number of "converged" Ritz values.
c This represents the number of Ritz values that satisfy
c the convergence criterion.
c
c IPARAM(6) = IUPD
c No longer referenced. Implicit restarting is ALWAYS used.
c
c IPARAM(7) = MODE
c On INPUT determines what type of eigenproblem is being solved.
c Must be 1,2,3,4,5; See under \Description of dsaupd for the
c five modes available.
c
c IPARAM(8) = NP
c When ido = 3 and the user provides shifts through reverse
c communication (IPARAM(1)=0), dsaupd returns NP, the number
c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark
c 6 below.
c
c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO,
c OUTPUT: NUMOP = total number of OP*x operations,
c NUMOPB = total number of B*x operations if BMAT='G',
c NUMREO = total number of steps of re-orthogonalization.
c
c IPNTR Integer array of length 11. (OUTPUT)
c Pointer to mark the starting locations in the WORKD and WORKL
c arrays for matrices/vectors used by the Lanczos iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X in WORKD.
c IPNTR(2): pointer to the current result vector Y in WORKD.
c IPNTR(3): pointer to the vector B * X in WORKD when used in
c the shift-and-invert mode.
c IPNTR(4): pointer to the next available location in WORKL
c that is untouched by the program.
c IPNTR(5): pointer to the NCV by 2 tridiagonal matrix T in WORKL.
c IPNTR(6): pointer to the NCV RITZ values array in WORKL.
c IPNTR(7): pointer to the Ritz estimates in array WORKL associated
c with the Ritz values located in RITZ in WORKL.
c IPNTR(11): pointer to the NP shifts in WORKL. See Remark 6 below.
c
c Note: IPNTR(8:10) is only referenced by dseupd . See Remark 2.
c IPNTR(8): pointer to the NCV RITZ values of the original system.
c IPNTR(9): pointer to the NCV corresponding error bounds.
c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors
c of the tridiagonal matrix T. Only referenced by
c dseupd if RVEC = .TRUE. See Remarks.
c -------------------------------------------------------------
c
c WORKD Double precision work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration. Upon termination
c WORKD(1:N) contains B*RESID(1:N). If the Ritz vectors are desired
c subroutine dseupd uses this output.
c See Data Distribution Note below.
c
c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. See Data Distribution Note below.
c
c LWORKL Integer. (INPUT)
c LWORKL must be at least NCV**2 + 8*NCV .
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal exit.
c = 1: Maximum number of iterations taken.
c All possible eigenvalues of OP has been found. IPARAM(5)
c returns the number of wanted converged Ritz values.
c = 2: No longer an informational error. Deprecated starting
c with release 2 of ARPACK.
c = 3: No shifts could be applied during a cycle of the
c Implicitly restarted Arnoldi iteration. One possibility
c is to increase the size of NCV relative to NEV.
c See remark 4 below.
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV must be greater than NEV and less than or equal to N.
c = -4: The maximum number of Arnoldi update iterations allowed
c must be greater than zero.
c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'.
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work array WORKL is not sufficient.
c = -8: Error return from trid. eigenvalue calculation;
c Informatinal error from LAPACK routine dsteqr .
c = -9: Starting vector is zero.
c = -10: IPARAM(7) must be 1,2,3,4,5.
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable.
c = -12: IPARAM(1) must be equal to 0 or 1.
c = -13: NEV and WHICH = 'BE' are incompatable.
c = -9999: Could not build an Arnoldi factorization.
c IPARAM(5) returns the size of the current Arnoldi
c factorization. The user is advised to check that
c enough workspace and array storage has been allocated.
c
c
c\Remarks
c 1. The converged Ritz values are always returned in ascending
c algebraic order. The computed Ritz values are approximate
c eigenvalues of OP. The selection of WHICH should be made
c with this in mind when Mode = 3,4,5. After convergence,
c approximate eigenvalues of the original problem may be obtained
c with the ARPACK subroutine dseupd .
c
c 2. If the Ritz vectors corresponding to the converged Ritz values
c are needed, the user must call dseupd immediately following completion
c of dsaupd . This is new starting with version 2.1 of ARPACK.
c
c 3. If M can be factored into a Cholesky factorization M = LL`
c then Mode = 2 should not be selected. Instead one should use
c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular
c linear systems should be solved with L and L` rather
c than computing inverses. After convergence, an approximate
c eigenvector z of the original problem is recovered by solving
c L`z = x where x is a Ritz vector of OP.
c
c 4. At present there is no a-priori analysis to guide the selection
c of NCV relative to NEV. The only formal requrement is that NCV > NEV.
c However, it is recommended that NCV .ge. 2*NEV. If many problems of
c the same type are to be solved, one should experiment with increasing
c NCV while keeping NEV fixed for a given test problem. This will
c usually decrease the required number of OP*x operations but it
c also increases the work and storage required to maintain the orthogonal
c basis vectors. The optimal "cross-over" with respect to CPU time
c is problem dependent and must be determined empirically.
c
c 5. If IPARAM(7) = 2 then in the Reverse commuication interface the user
c must do the following. When IDO = 1, Y = OP * X is to be computed.
c When IPARAM(7) = 2 OP = inv(B)*A. After computing A*X the user
c must overwrite X with A*X. Y is then the solution to the linear set
c of equations B*Y = A*X.
c
c 6. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the
c NP = IPARAM(8) shifts in locations:
c 1 WORKL(IPNTR(11))
c 2 WORKL(IPNTR(11)+1)
c .
c .
c .
c NP WORKL(IPNTR(11)+NP-1).
c
c The eigenvalues of the current tridiagonal matrix are located in
c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are in the
c order defined by WHICH. The associated Ritz estimates are located in
c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1).
c
c-----------------------------------------------------------------------
c
c\Data Distribution Note:
c
c Fortran-D syntax:
c ================
c REAL RESID(N), V(LDV,NCV), WORKD(3*N), WORKL(LWORKL)
c DECOMPOSE D1(N), D2(N,NCV)
c ALIGN RESID(I) with D1(I)
c ALIGN V(I,J) with D2(I,J)
c ALIGN WORKD(I) with D1(I) range (1:N)
c ALIGN WORKD(I) with D1(I-N) range (N+1:2*N)
c ALIGN WORKD(I) with D1(I-2*N) range (2*N+1:3*N)
c DISTRIBUTE D1(BLOCK), D2(BLOCK,:)
c REPLICATED WORKL(LWORKL)
c
c Cray MPP syntax:
c ===============
c REAL RESID(N), V(LDV,NCV), WORKD(N,3), WORKL(LWORKL)
c SHARED RESID(BLOCK), V(BLOCK,:), WORKD(BLOCK,:)
c REPLICATED WORKL(LWORKL)
c
c
c\BeginLib
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall,
c 1980.
c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program",
c Computer Physics Communications, 53 (1989), pp 169-179.
c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to
c Implement the Spectral Transformation", Math. Comp., 48 (1987),
c pp 663-673.
c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos
c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems",
c SIAM J. Matr. Anal. Apps., January (1993).
c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines
c for Updating the QR decomposition", ACM TOMS, December 1990,
c Volume 16 Number 4, pp 369-377.
c 8. R.B. Lehoucq, D.C. Sorensen, "Implementation of Some Spectral
c Transformations in a k-Step Arnoldi Method". In Preparation.
c
c\Routines called:
c dsaup2 ARPACK routine that implements the Implicitly Restarted
c Arnoldi Iteration.
c dstats ARPACK routine that initialize timing and other statistics
c variables.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c dvout ARPACK utility routine that prints vectors.
c dlamch LAPACK routine that determines machine constants.
c
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/15/93: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: saupd.F SID: 2.8 DATE OF SID: 04/10/01 RELEASE: 2
c
c\Remarks
c 1. None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dsaupd
& ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam,
& ipntr, workd, workl, lworkl, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ldv, lworkl, n, ncv, nev
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(11), ipntr(11)
Double precision
& resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0 , zero = 0.0D+0 )
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer bounds, ierr, ih, iq, ishift, iupd, iw,
& ldh, ldq, msglvl, mxiter, mode, nb,
& nev0, next, np, ritz, j
save bounds, ierr, ih, iq, ishift, iupd, iw,
& ldh, ldq, msglvl, mxiter, mode, nb,
& nev0, next, np, ritz
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dsaup2 , dvout , ivout, second, dstats
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dlamch
external dlamch
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call dstats
call second (t0)
msglvl = msaupd
c
ierr = 0
ishift = iparam(1)
mxiter = iparam(3)
c nb = iparam(4)
nb = 1
c
c %--------------------------------------------%
c | Revision 2 performs only implicit restart. |
c %--------------------------------------------%
c
iupd = 1
mode = iparam(7)
c
c %----------------%
c | Error checking |
c %----------------%
c
if (n .le. 0) then
ierr = -1
else if (nev .le. 0) then
ierr = -2
else if (ncv .le. nev .or. ncv .gt. n) then
ierr = -3
end if
c
c %----------------------------------------------%
c | NP is the number of additional steps to |
c | extend the length NEV Lanczos factorization. |
c %----------------------------------------------%
c
np = ncv - nev
c
if (mxiter .le. 0) ierr = -4
if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LA' .and.
& which .ne. 'SA' .and.
& which .ne. 'BE') ierr = -5
if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6
c
if (lworkl .lt. ncv**2 + 8*ncv) ierr = -7
if (mode .lt. 1 .or. mode .gt. 5) then
ierr = -10
else if (mode .eq. 1 .and. bmat .eq. 'G') then
ierr = -11
else if (ishift .lt. 0 .or. ishift .gt. 1) then
ierr = -12
else if (nev .eq. 1 .and. which .eq. 'BE') then
ierr = -13
end if
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
ido = 99
go to 9000
end if
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
if (nb .le. 0) nb = 1
if (tol .le. zero) tol = dlamch ('EpsMach')
c
c %----------------------------------------------%
c | NP is the number of additional steps to |
c | extend the length NEV Lanczos factorization. |
c | NEV0 is the local variable designating the |
c | size of the invariant subspace desired. |
c %----------------------------------------------%
c
np = ncv - nev
nev0 = nev
c
c %-----------------------------%
c | Zero out internal workspace |
c %-----------------------------%
c
do 10 j = 1, ncv**2 + 8*ncv
workl(j) = zero
10 continue
c
c %-------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:2*ncv) := generated tridiagonal matrix |
c | workl(2*ncv+1:2*ncv+ncv) := ritz values |
c | workl(3*ncv+1:3*ncv+ncv) := computed error bounds |
c | workl(4*ncv+1:4*ncv+ncv*ncv) := rotation matrix Q |
c | workl(4*ncv+ncv*ncv+1:7*ncv+ncv*ncv) := workspace |
c %-------------------------------------------------------%
c
ldh = ncv
ldq = ncv
ih = 1
ritz = ih + 2*ldh
bounds = ritz + ncv
iq = bounds + ncv
iw = iq + ncv**2
next = iw + 3*ncv
c
ipntr(4) = next
ipntr(5) = ih
ipntr(6) = ritz
ipntr(7) = bounds
ipntr(11) = iw
end if
c
c %-------------------------------------------------------%
c | Carry out the Implicitly restarted Lanczos Iteration. |
c %-------------------------------------------------------%
c
call dsaup2
& ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz),
& workl(bounds), workl(iq), ldq, workl(iw), ipntr, workd,
& info )
c
c %--------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP or shifts. |
c %--------------------------------------------------%
c
if (ido .eq. 3) iparam(8) = np
if (ido .ne. 99) go to 9000
c
iparam(3) = mxiter
iparam(5) = np
iparam(9) = nopx
iparam(10) = nbx
iparam(11) = nrorth
c
c %------------------------------------%
c | Exit if there was an informational |
c | error within dsaup2 . |
c %------------------------------------%
c
if (info .lt. 0) go to 9000
if (info .eq. 2) info = 3
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, mxiter, ndigit,
& '_saupd: number of update iterations taken')
call ivout (logfil, 1, np, ndigit,
& '_saupd: number of "converged" Ritz values')
call dvout (logfil, np, workl(Ritz), ndigit,
& '_saupd: final Ritz values')
call dvout (logfil, np, workl(Bounds), ndigit,
& '_saupd: corresponding error bounds')
end if
c
call second (t1)
tsaupd = t1 - t0
c
if (msglvl .gt. 0) then
c
c %--------------------------------------------------------%
c | Version Number & Version Date are defined in version.h |
c %--------------------------------------------------------%
c
write (6,1000)
write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt,
& tmvopx, tmvbx, tsaupd, tsaup2, tsaitr, titref,
& tgetv0, tseigt, tsgets, tsapps, tsconv
1000 format (//,
& 5x, '==========================================',/
& 5x, '= Symmetric implicit Arnoldi update code =',/
& 5x, '= Version Number:', ' 2.4' , 19x, ' =',/
& 5x, '= Version Date: ', ' 07/31/96' , 14x, ' =',/
& 5x, '==========================================',/
& 5x, '= Summary of timing statistics =',/
& 5x, '==========================================',//)
1100 format (
& 5x, 'Total number update iterations = ', i5,/
& 5x, 'Total number of OP*x operations = ', i5,/
& 5x, 'Total number of B*x operations = ', i5,/
& 5x, 'Total number of reorthogonalization steps = ', i5,/
& 5x, 'Total number of iterative refinement steps = ', i5,/
& 5x, 'Total number of restart steps = ', i5,/
& 5x, 'Total time in user OP*x operation = ', f12.6,/
& 5x, 'Total time in user B*x operation = ', f12.6,/
& 5x, 'Total time in Arnoldi update routine = ', f12.6,/
& 5x, 'Total time in saup2 routine = ', f12.6,/
& 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/
& 5x, 'Total time in reorthogonalization phase = ', f12.6,/
& 5x, 'Total time in (re)start vector generation = ', f12.6,/
& 5x, 'Total time in trid eigenvalue subproblem = ', f12.6,/
& 5x, 'Total time in getting the shifts = ', f12.6,/
& 5x, 'Total time in applying the shifts = ', f12.6,/
& 5x, 'Total time in convergence testing = ', f12.6)
end if
c
9000 continue
c
return
c
c %---------------%
c | End of dsaupd |
c %---------------%
c
end

138
arpack/ARPACK/SRC/dsconv.f Normal file
View File

@@ -0,0 +1,138 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dsconv
c
c\Description:
c Convergence testing for the symmetric Arnoldi eigenvalue routine.
c
c\Usage:
c call dsconv
c ( N, RITZ, BOUNDS, TOL, NCONV )
c
c\Arguments
c N Integer. (INPUT)
c Number of Ritz values to check for convergence.
c
c RITZ Double precision array of length N. (INPUT)
c The Ritz values to be checked for convergence.
c
c BOUNDS Double precision array of length N. (INPUT)
c Ritz estimates associated with the Ritz values in RITZ.
c
c TOL Double precision scalar. (INPUT)
c Desired relative accuracy for a Ritz value to be considered
c "converged".
c
c NCONV Integer scalar. (OUTPUT)
c Number of "converged" Ritz values.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Routines called:
c second ARPACK utility routine for timing.
c dlamch LAPACK routine that determines machine constants.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: sconv.F SID: 2.4 DATE OF SID: 4/19/96 RELEASE: 2
c
c\Remarks
c 1. Starting with version 2.4, this routine no longer uses the
c Parlett strategy using the gap conditions.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dsconv (n, ritz, bounds, tol, nconv)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer n, nconv
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& ritz(n), bounds(n)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i
Double precision
& temp, eps23
c
c %-------------------%
c | External routines |
c %-------------------%
c
Double precision
& dlamch
external dlamch
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic abs
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
call second (t0)
c
eps23 = dlamch('Epsilon-Machine')
eps23 = eps23**(2.0D+0 / 3.0D+0)
c
nconv = 0
do 10 i = 1, n
c
c %-----------------------------------------------------%
c | The i-th Ritz value is considered "converged" |
c | when: bounds(i) .le. TOL*max(eps23, abs(ritz(i))) |
c %-----------------------------------------------------%
c
temp = max( eps23, abs(ritz(i)) )
if ( bounds(i) .le. tol*temp ) then
nconv = nconv + 1
end if
c
10 continue
c
call second (t1)
tsconv = tsconv + (t1 - t0)
c
return
c
c %---------------%
c | End of dsconv |
c %---------------%
c
end

181
arpack/ARPACK/SRC/dseigt.f Normal file
View File

@@ -0,0 +1,181 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dseigt
c
c\Description:
c Compute the eigenvalues of the current symmetric tridiagonal matrix
c and the corresponding error bounds given the current residual norm.
c
c\Usage:
c call dseigt
c ( RNORM, N, H, LDH, EIG, BOUNDS, WORKL, IERR )
c
c\Arguments
c RNORM Double precision scalar. (INPUT)
c RNORM contains the residual norm corresponding to the current
c symmetric tridiagonal matrix H.
c
c N Integer. (INPUT)
c Size of the symmetric tridiagonal matrix H.
c
c H Double precision N by 2 array. (INPUT)
c H contains the symmetric tridiagonal matrix with the
c subdiagonal in the first column starting at H(2,1) and the
c main diagonal in second column.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c EIG Double precision array of length N. (OUTPUT)
c On output, EIG contains the N eigenvalues of H possibly
c unsorted. The BOUNDS arrays are returned in the
c same sorted order as EIG.
c
c BOUNDS Double precision array of length N. (OUTPUT)
c On output, BOUNDS contains the error estimates corresponding
c to the eigenvalues EIG. This is equal to RNORM times the
c last components of the eigenvectors corresponding to the
c eigenvalues in EIG.
c
c WORKL Double precision work array of length 3*N. (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c IERR Integer. (OUTPUT)
c Error exit flag from dstqrb.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c dstqrb ARPACK routine that computes the eigenvalues and the
c last components of the eigenvectors of a symmetric
c and tridiagonal matrix.
c second ARPACK utility routine for timing.
c dvout ARPACK utility routine that prints vectors.
c dcopy Level 1 BLAS that copies one vector to another.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: seigt.F SID: 2.4 DATE OF SID: 8/27/96 RELEASE: 2
c
c\Remarks
c None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dseigt
& ( rnorm, n, h, ldh, eig, bounds, workl, ierr )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer ierr, ldh, n
Double precision
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& eig(n), bounds(n), h(ldh,2), workl(3*n)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& zero
parameter (zero = 0.0D+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, k, msglvl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dcopy, dstqrb, dvout, second
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mseigt
c
if (msglvl .gt. 0) then
call dvout (logfil, n, h(1,2), ndigit,
& '_seigt: main diagonal of matrix H')
if (n .gt. 1) then
call dvout (logfil, n-1, h(2,1), ndigit,
& '_seigt: sub diagonal of matrix H')
end if
end if
c
call dcopy (n, h(1,2), 1, eig, 1)
call dcopy (n-1, h(2,1), 1, workl, 1)
call dstqrb (n, eig, workl, bounds, workl(n+1), ierr)
if (ierr .ne. 0) go to 9000
if (msglvl .gt. 1) then
call dvout (logfil, n, bounds, ndigit,
& '_seigt: last row of the eigenvector matrix for H')
end if
c
c %-----------------------------------------------%
c | Finally determine the error bounds associated |
c | with the n Ritz values of H. |
c %-----------------------------------------------%
c
do 30 k = 1, n
bounds(k) = rnorm*abs(bounds(k))
30 continue
c
call second (t1)
tseigt = tseigt + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of dseigt |
c %---------------%
c
end

217
arpack/ARPACK/SRC/dsesrt.f Normal file
View File

@@ -0,0 +1,217 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dsesrt
c
c\Description:
c Sort the array X in the order specified by WHICH and optionally
c apply the permutation to the columns of the matrix A.
c
c\Usage:
c call dsesrt
c ( WHICH, APPLY, N, X, NA, A, LDA)
c
c\Arguments
c WHICH Character*2. (Input)
c 'LM' -> X is sorted into increasing order of magnitude.
c 'SM' -> X is sorted into decreasing order of magnitude.
c 'LA' -> X is sorted into increasing order of algebraic.
c 'SA' -> X is sorted into decreasing order of algebraic.
c
c APPLY Logical. (Input)
c APPLY = .TRUE. -> apply the sorted order to A.
c APPLY = .FALSE. -> do not apply the sorted order to A.
c
c N Integer. (INPUT)
c Dimension of the array X.
c
c X Double precision array of length N. (INPUT/OUTPUT)
c The array to be sorted.
c
c NA Integer. (INPUT)
c Number of rows of the matrix A.
c
c A Double precision array of length NA by N. (INPUT/OUTPUT)
c
c LDA Integer. (INPUT)
c Leading dimension of A.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Routines
c dswap Level 1 BLAS that swaps the contents of two vectors.
c
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/15/93: Version ' 2.1'.
c Adapted from the sort routine in LANSO and
c the ARPACK code dsortr
c
c\SCCS Information: @(#)
c FILE: sesrt.F SID: 2.3 DATE OF SID: 4/19/96 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dsesrt (which, apply, n, x, na, a, lda)
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
logical apply
integer lda, n, na
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& x(0:n-1), a(lda, 0:n-1)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, igap, j
Double precision
& temp
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dswap
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
igap = n / 2
c
if (which .eq. 'SA') then
c
c X is sorted into decreasing order of algebraic.
c
10 continue
if (igap .eq. 0) go to 9000
do 30 i = igap, n-1
j = i-igap
20 continue
c
if (j.lt.0) go to 30
c
if (x(j).lt.x(j+igap)) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
if (apply) call dswap( na, a(1, j), 1, a(1,j+igap), 1)
else
go to 30
endif
j = j-igap
go to 20
30 continue
igap = igap / 2
go to 10
c
else if (which .eq. 'SM') then
c
c X is sorted into decreasing order of magnitude.
c
40 continue
if (igap .eq. 0) go to 9000
do 60 i = igap, n-1
j = i-igap
50 continue
c
if (j.lt.0) go to 60
c
if (abs(x(j)).lt.abs(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
if (apply) call dswap( na, a(1, j), 1, a(1,j+igap), 1)
else
go to 60
endif
j = j-igap
go to 50
60 continue
igap = igap / 2
go to 40
c
else if (which .eq. 'LA') then
c
c X is sorted into increasing order of algebraic.
c
70 continue
if (igap .eq. 0) go to 9000
do 90 i = igap, n-1
j = i-igap
80 continue
c
if (j.lt.0) go to 90
c
if (x(j).gt.x(j+igap)) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
if (apply) call dswap( na, a(1, j), 1, a(1,j+igap), 1)
else
go to 90
endif
j = j-igap
go to 80
90 continue
igap = igap / 2
go to 70
c
else if (which .eq. 'LM') then
c
c X is sorted into increasing order of magnitude.
c
100 continue
if (igap .eq. 0) go to 9000
do 120 i = igap, n-1
j = i-igap
110 continue
c
if (j.lt.0) go to 120
c
if (abs(x(j)).gt.abs(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
if (apply) call dswap( na, a(1, j), 1, a(1,j+igap), 1)
else
go to 120
endif
j = j-igap
go to 110
120 continue
igap = igap / 2
go to 100
end if
c
9000 continue
return
c
c %---------------%
c | End of dsesrt |
c %---------------%
c
end

857
arpack/ARPACK/SRC/dseupd.f Normal file
View File

@@ -0,0 +1,857 @@
c\BeginDoc
c
c\Name: dseupd
c
c\Description:
c
c This subroutine returns the converged approximations to eigenvalues
c of A*z = lambda*B*z and (optionally):
c
c (1) the corresponding approximate eigenvectors,
c
c (2) an orthonormal (Lanczos) basis for the associated approximate
c invariant subspace,
c
c (3) Both.
c
c There is negligible additional cost to obtain eigenvectors. An orthonormal
c (Lanczos) basis is always computed. There is an additional storage cost
c of n*nev if both are requested (in this case a separate array Z must be
c supplied).
c
c These quantities are obtained from the Lanczos factorization computed
c by DSAUPD for the linear operator OP prescribed by the MODE selection
c (see IPARAM(7) in DSAUPD documentation.) DSAUPD must be called before
c this routine is called. These approximate eigenvalues and vectors are
c commonly called Ritz values and Ritz vectors respectively. They are
c referred to as such in the comments that follow. The computed orthonormal
c basis for the invariant subspace corresponding to these Ritz values is
c referred to as a Lanczos basis.
c
c See documentation in the header of the subroutine DSAUPD for a definition
c of OP as well as other terms and the relation of computed Ritz values
c and vectors of OP with respect to the given problem A*z = lambda*B*z.
c
c The approximate eigenvalues of the original problem are returned in
c ascending algebraic order. The user may elect to call this routine
c once for each desired Ritz vector and store it peripherally if desired.
c There is also the option of computing a selected set of these vectors
c with a single call.
c
c\Usage:
c call dseupd
c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, BMAT, N, WHICH, NEV, TOL,
c RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, LWORKL, INFO )
c
c RVEC LOGICAL (INPUT)
c Specifies whether Ritz vectors corresponding to the Ritz value
c approximations to the eigenproblem A*z = lambda*B*z are computed.
c
c RVEC = .FALSE. Compute Ritz values only.
c
c RVEC = .TRUE. Compute Ritz vectors.
c
c HOWMNY Character*1 (INPUT)
c Specifies how many Ritz vectors are wanted and the form of Z
c the matrix of Ritz vectors. See remark 1 below.
c = 'A': compute NEV Ritz vectors;
c = 'S': compute some of the Ritz vectors, specified
c by the logical array SELECT.
c
c SELECT Logical array of dimension NCV. (INPUT/WORKSPACE)
c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be
c computed. To select the Ritz vector corresponding to a
c Ritz value D(j), SELECT(j) must be set to .TRUE..
c If HOWMNY = 'A' , SELECT is used as a workspace for
c reordering the Ritz values.
c
c D Double precision array of dimension NEV. (OUTPUT)
c On exit, D contains the Ritz value approximations to the
c eigenvalues of A*z = lambda*B*z. The values are returned
c in ascending order. If IPARAM(7) = 3,4,5 then D represents
c the Ritz values of OP computed by dsaupd transformed to
c those of the original eigensystem A*z = lambda*B*z. If
c IPARAM(7) = 1,2 then the Ritz values of OP are the same
c as the those of A*z = lambda*B*z.
c
c Z Double precision N by NEV array if HOWMNY = 'A'. (OUTPUT)
c On exit, Z contains the B-orthonormal Ritz vectors of the
c eigensystem A*z = lambda*B*z corresponding to the Ritz
c value approximations.
c If RVEC = .FALSE. then Z is not referenced.
c NOTE: The array Z may be set equal to first NEV columns of the
c Arnoldi/Lanczos basis array V computed by DSAUPD .
c
c LDZ Integer. (INPUT)
c The leading dimension of the array Z. If Ritz vectors are
c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1.
c
c SIGMA Double precision (INPUT)
c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if
c IPARAM(7) = 1 or 2.
c
c
c **** The remaining arguments MUST be the same as for the ****
c **** call to DSAUPD that was just completed. ****
c
c NOTE: The remaining arguments
c
c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR,
c WORKD, WORKL, LWORKL, INFO
c
c must be passed directly to DSEUPD following the last call
c to DSAUPD . These arguments MUST NOT BE MODIFIED between
c the the last call to DSAUPD and the call to DSEUPD .
c
c Two of these parameters (WORKL, INFO) are also output parameters:
c
c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE)
c WORKL(1:4*ncv) contains information obtained in
c dsaupd . They are not changed by dseupd .
c WORKL(4*ncv+1:ncv*ncv+8*ncv) holds the
c untransformed Ritz values, the computed error estimates,
c and the associated eigenvector matrix of H.
c
c Note: IPNTR(8:10) contains the pointer into WORKL for addresses
c of the above information computed by dseupd .
c -------------------------------------------------------------
c IPNTR(8): pointer to the NCV RITZ values of the original system.
c IPNTR(9): pointer to the NCV corresponding error bounds.
c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors
c of the tridiagonal matrix T. Only referenced by
c dseupd if RVEC = .TRUE. See Remarks.
c -------------------------------------------------------------
c
c INFO Integer. (OUTPUT)
c Error flag on output.
c = 0: Normal exit.
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV must be greater than NEV and less than or equal to N.
c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'.
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work WORKL array is not sufficient.
c = -8: Error return from trid. eigenvalue calculation;
c Information error from LAPACK routine dsteqr .
c = -9: Starting vector is zero.
c = -10: IPARAM(7) must be 1,2,3,4,5.
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.
c = -12: NEV and WHICH = 'BE' are incompatible.
c = -14: DSAUPD did not find any eigenvalues to sufficient
c accuracy.
c = -15: HOWMNY must be one of 'A' or 'S' if RVEC = .true.
c = -16: HOWMNY = 'S' not yet implemented
c = -17: DSEUPD got a different count of the number of converged
c Ritz values than DSAUPD got. This indicates the user
c probably made an error in passing data from DSAUPD to
c DSEUPD or that the data was modified before entering
c DSEUPD .
c
c\BeginLib
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall,
c 1980.
c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program",
c Computer Physics Communications, 53 (1989), pp 169-179.
c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to
c Implement the Spectral Transformation", Math. Comp., 48 (1987),
c pp 663-673.
c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos
c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems",
c SIAM J. Matr. Anal. Apps., January (1993).
c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines
c for Updating the QR decomposition", ACM TOMS, December 1990,
c Volume 16 Number 4, pp 369-377.
c
c\Remarks
c 1. The converged Ritz values are always returned in increasing
c (algebraic) order.
c
c 2. Currently only HOWMNY = 'A' is implemented. It is included at this
c stage for the user who wants to incorporate it.
c
c\Routines called:
c dsesrt ARPACK routine that sorts an array X, and applies the
c corresponding permutation to a matrix A.
c dsortr dsortr ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c dvout ARPACK utility routine that prints vectors.
c dgeqr2 LAPACK routine that computes the QR factorization of
c a matrix.
c dlacpy LAPACK matrix copy routine.
c dlamch LAPACK routine that determines machine constants.
c dorm2r LAPACK routine that applies an orthogonal matrix in
c factored form.
c dsteqr LAPACK routine that computes eigenvalues and eigenvectors
c of a tridiagonal matrix.
c dger Level 2 BLAS rank one update to a matrix.
c dcopy Level 1 BLAS that copies one vector to another .
c dnrm2 Level 1 BLAS that computes the norm of a vector.
c dscal Level 1 BLAS that scales a vector.
c dswap Level 1 BLAS that swaps the contents of two vectors.
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Chao Yang Houston, Texas
c Dept. of Computational &
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/15/93: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: seupd.F SID: 2.11 DATE OF SID: 04/10/01 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
subroutine dseupd (rvec , howmny, select, d ,
& z , ldz , sigma , bmat ,
& n , which , nev , tol ,
& resid , ncv , v , ldv ,
& iparam, ipntr , workd , workl,
& lworkl, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat, howmny, which*2
logical rvec
integer info, ldz, ldv, lworkl, n, ncv, nev
Double precision
& sigma, tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(7), ipntr(11)
logical select(ncv)
Double precision
& d(nev) , resid(n) , v(ldv,ncv),
& z(ldz, nev), workd(2*n), workl(lworkl)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0 , zero = 0.0D+0 )
c
c %---------------%
c | Local Scalars |
c %---------------%
c
character type*6
integer bounds , ierr , ih , ihb , ihd ,
& iq , iw , j , k , ldh ,
& ldq , mode , msglvl, nconv , next ,
& ritz , irz , ibd , np , ishift,
& leftptr, rghtptr, numcnv, jj
Double precision
& bnorm2 , rnorm, temp, temp1, eps23
logical reord
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dcopy , dger , dgeqr2 , dlacpy , dorm2r , dscal ,
& dsesrt , dsteqr , dswap , dvout , ivout , dsortr
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dnrm2 , dlamch
external dnrm2 , dlamch
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic min
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
msglvl = mseupd
mode = iparam(7)
nconv = iparam(5)
info = 0
c
c %--------------%
c | Quick return |
c %--------------%
c
if (nconv .eq. 0) go to 9000
ierr = 0
c
if (nconv .le. 0) ierr = -14
if (n .le. 0) ierr = -1
if (nev .le. 0) ierr = -2
if (ncv .le. nev .or. ncv .gt. n) ierr = -3
if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LA' .and.
& which .ne. 'SA' .and.
& which .ne. 'BE') ierr = -5
if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6
if ( (howmny .ne. 'A' .and.
& howmny .ne. 'P' .and.
& howmny .ne. 'S') .and. rvec )
& ierr = -15
if (rvec .and. howmny .eq. 'S') ierr = -16
c
if (rvec .and. lworkl .lt. ncv**2+8*ncv) ierr = -7
c
if (mode .eq. 1 .or. mode .eq. 2) then
type = 'REGULR'
else if (mode .eq. 3 ) then
type = 'SHIFTI'
else if (mode .eq. 4 ) then
type = 'BUCKLE'
else if (mode .eq. 5 ) then
type = 'CAYLEY'
else
ierr = -10
end if
if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11
if (nev .eq. 1 .and. which .eq. 'BE') ierr = -12
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
go to 9000
end if
c
c %-------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:2*ncv) := generated tridiagonal matrix H |
c | The subdiagonal is stored in workl(2:ncv). |
c | The dead spot is workl(1) but upon exiting |
c | dsaupd stores the B-norm of the last residual |
c | vector in workl(1). We use this !!! |
c | workl(2*ncv+1:2*ncv+ncv) := ritz values |
c | The wanted values are in the first NCONV spots. |
c | workl(3*ncv+1:3*ncv+ncv) := computed Ritz estimates |
c | The wanted values are in the first NCONV spots. |
c | NOTE: workl(1:4*ncv) is set by dsaupd and is not |
c | modified by dseupd . |
c %-------------------------------------------------------%
c
c %-------------------------------------------------------%
c | The following is used and set by dseupd . |
c | workl(4*ncv+1:4*ncv+ncv) := used as workspace during |
c | computation of the eigenvectors of H. Stores |
c | the diagonal of H. Upon EXIT contains the NCV |
c | Ritz values of the original system. The first |
c | NCONV spots have the wanted values. If MODE = |
c | 1 or 2 then will equal workl(2*ncv+1:3*ncv). |
c | workl(5*ncv+1:5*ncv+ncv) := used as workspace during |
c | computation of the eigenvectors of H. Stores |
c | the subdiagonal of H. Upon EXIT contains the |
c | NCV corresponding Ritz estimates of the |
c | original system. The first NCONV spots have the |
c | wanted values. If MODE = 1,2 then will equal |
c | workl(3*ncv+1:4*ncv). |
c | workl(6*ncv+1:6*ncv+ncv*ncv) := orthogonal Q that is |
c | the eigenvector matrix for H as returned by |
c | dsteqr . Not referenced if RVEC = .False. |
c | Ordering follows that of workl(4*ncv+1:5*ncv) |
c | workl(6*ncv+ncv*ncv+1:6*ncv+ncv*ncv+2*ncv) := |
c | Workspace. Needed by dsteqr and by dseupd . |
c | GRAND total of NCV*(NCV+8) locations. |
c %-------------------------------------------------------%
c
c
ih = ipntr(5)
ritz = ipntr(6)
bounds = ipntr(7)
ldh = ncv
ldq = ncv
ihd = bounds + ldh
ihb = ihd + ldh
iq = ihb + ldh
iw = iq + ldh*ncv
next = iw + 2*ncv
ipntr(4) = next
ipntr(8) = ihd
ipntr(9) = ihb
ipntr(10) = iq
c
c %----------------------------------------%
c | irz points to the Ritz values computed |
c | by _seigt before exiting _saup2. |
c | ibd points to the Ritz estimates |
c | computed by _seigt before exiting |
c | _saup2. |
c %----------------------------------------%
c
irz = ipntr(11)+ncv
ibd = irz+ncv
c
c
c %---------------------------------%
c | Set machine dependent constant. |
c %---------------------------------%
c
eps23 = dlamch ('Epsilon-Machine')
eps23 = eps23**(2.0D+0 / 3.0D+0 )
c
c %---------------------------------------%
c | RNORM is B-norm of the RESID(1:N). |
c | BNORM2 is the 2 norm of B*RESID(1:N). |
c | Upon exit of dsaupd WORKD(1:N) has |
c | B*RESID(1:N). |
c %---------------------------------------%
c
rnorm = workl(ih)
if (bmat .eq. 'I') then
bnorm2 = rnorm
else if (bmat .eq. 'G') then
bnorm2 = dnrm2 (n, workd, 1)
end if
c
if (msglvl .gt. 2) then
call dvout (logfil, ncv, workl(irz), ndigit,
& '_seupd: Ritz values passed in from _SAUPD.')
call dvout (logfil, ncv, workl(ibd), ndigit,
& '_seupd: Ritz estimates passed in from _SAUPD.')
end if
c
if (rvec) then
c
reord = .false.
c
c %---------------------------------------------------%
c | Use the temporary bounds array to store indices |
c | These will be used to mark the select array later |
c %---------------------------------------------------%
c
do 10 j = 1,ncv
workl(bounds+j-1) = j
select(j) = .false.
10 continue
c
c %-------------------------------------%
c | Select the wanted Ritz values. |
c | Sort the Ritz values so that the |
c | wanted ones appear at the tailing |
c | NEV positions of workl(irr) and |
c | workl(iri). Move the corresponding |
c | error estimates in workl(bound) |
c | accordingly. |
c %-------------------------------------%
c
np = ncv - nev
ishift = 0
call dsgets (ishift, which , nev ,
& np , workl(irz) , workl(bounds),
& workl)
c
if (msglvl .gt. 2) then
call dvout (logfil, ncv, workl(irz), ndigit,
& '_seupd: Ritz values after calling _SGETS.')
call dvout (logfil, ncv, workl(bounds), ndigit,
& '_seupd: Ritz value indices after calling _SGETS.')
end if
c
c %-----------------------------------------------------%
c | Record indices of the converged wanted Ritz values |
c | Mark the select array for possible reordering |
c %-----------------------------------------------------%
c
numcnv = 0
do 11 j = 1,ncv
temp1 = max(eps23, abs(workl(irz+ncv-j)) )
jj = workl(bounds + ncv - j)
if (numcnv .lt. nconv .and.
& workl(ibd+jj-1) .le. tol*temp1) then
select(jj) = .true.
numcnv = numcnv + 1
if (jj .gt. nev) reord = .true.
endif
11 continue
c
c %-----------------------------------------------------------%
c | Check the count (numcnv) of converged Ritz values with |
c | the number (nconv) reported by _saupd. If these two |
c | are different then there has probably been an error |
c | caused by incorrect passing of the _saupd data. |
c %-----------------------------------------------------------%
c
if (msglvl .gt. 2) then
call ivout(logfil, 1, numcnv, ndigit,
& '_seupd: Number of specified eigenvalues')
call ivout(logfil, 1, nconv, ndigit,
& '_seupd: Number of "converged" eigenvalues')
end if
c
if (numcnv .ne. nconv) then
info = -17
go to 9000
end if
c
c %-----------------------------------------------------------%
c | Call LAPACK routine _steqr to compute the eigenvalues and |
c | eigenvectors of the final symmetric tridiagonal matrix H. |
c | Initialize the eigenvector matrix Q to the identity. |
c %-----------------------------------------------------------%
c
call dcopy (ncv-1, workl(ih+1), 1, workl(ihb), 1)
call dcopy (ncv, workl(ih+ldh), 1, workl(ihd), 1)
c
call dsteqr ('Identity', ncv, workl(ihd), workl(ihb),
& workl(iq) , ldq, workl(iw), ierr)
c
if (ierr .ne. 0) then
info = -8
go to 9000
end if
c
if (msglvl .gt. 1) then
call dcopy (ncv, workl(iq+ncv-1), ldq, workl(iw), 1)
call dvout (logfil, ncv, workl(ihd), ndigit,
& '_seupd: NCV Ritz values of the final H matrix')
call dvout (logfil, ncv, workl(iw), ndigit,
& '_seupd: last row of the eigenvector matrix for H')
end if
c
if (reord) then
c
c %---------------------------------------------%
c | Reordered the eigenvalues and eigenvectors |
c | computed by _steqr so that the "converged" |
c | eigenvalues appear in the first NCONV |
c | positions of workl(ihd), and the associated |
c | eigenvectors appear in the first NCONV |
c | columns. |
c %---------------------------------------------%
c
leftptr = 1
rghtptr = ncv
c
if (ncv .eq. 1) go to 30
c
20 if (select(leftptr)) then
c
c %-------------------------------------------%
c | Search, from the left, for the first Ritz |
c | value that has not converged. |
c %-------------------------------------------%
c
leftptr = leftptr + 1
c
else if ( .not. select(rghtptr)) then
c
c %----------------------------------------------%
c | Search, from the right, the first Ritz value |
c | that has converged. |
c %----------------------------------------------%
c
rghtptr = rghtptr - 1
c
else
c
c %----------------------------------------------%
c | Swap the Ritz value on the left that has not |
c | converged with the Ritz value on the right |
c | that has converged. Swap the associated |
c | eigenvector of the tridiagonal matrix H as |
c | well. |
c %----------------------------------------------%
c
temp = workl(ihd+leftptr-1)
workl(ihd+leftptr-1) = workl(ihd+rghtptr-1)
workl(ihd+rghtptr-1) = temp
call dcopy (ncv, workl(iq+ncv*(leftptr-1)), 1,
& workl(iw), 1)
call dcopy (ncv, workl(iq+ncv*(rghtptr-1)), 1,
& workl(iq+ncv*(leftptr-1)), 1)
call dcopy (ncv, workl(iw), 1,
& workl(iq+ncv*(rghtptr-1)), 1)
leftptr = leftptr + 1
rghtptr = rghtptr - 1
c
end if
c
if (leftptr .lt. rghtptr) go to 20
c
30 end if
c
if (msglvl .gt. 2) then
call dvout (logfil, ncv, workl(ihd), ndigit,
& '_seupd: The eigenvalues of H--reordered')
end if
c
c %----------------------------------------%
c | Load the converged Ritz values into D. |
c %----------------------------------------%
c
call dcopy (nconv, workl(ihd), 1, d, 1)
c
else
c
c %-----------------------------------------------------%
c | Ritz vectors not required. Load Ritz values into D. |
c %-----------------------------------------------------%
c
call dcopy (nconv, workl(ritz), 1, d, 1)
call dcopy (ncv, workl(ritz), 1, workl(ihd), 1)
c
end if
c
c %------------------------------------------------------------------%
c | Transform the Ritz values and possibly vectors and corresponding |
c | Ritz estimates of OP to those of A*x=lambda*B*x. The Ritz values |
c | (and corresponding data) are returned in ascending order. |
c %------------------------------------------------------------------%
c
if (type .eq. 'REGULR') then
c
c %---------------------------------------------------------%
c | Ascending sort of wanted Ritz values, vectors and error |
c | bounds. Not necessary if only Ritz values are desired. |
c %---------------------------------------------------------%
c
if (rvec) then
call dsesrt ('LA', rvec , nconv, d, ncv, workl(iq), ldq)
else
call dcopy (ncv, workl(bounds), 1, workl(ihb), 1)
end if
c
else
c
c %-------------------------------------------------------------%
c | * Make a copy of all the Ritz values. |
c | * Transform the Ritz values back to the original system. |
c | For TYPE = 'SHIFTI' the transformation is |
c | lambda = 1/theta + sigma |
c | For TYPE = 'BUCKLE' the transformation is |
c | lambda = sigma * theta / ( theta - 1 ) |
c | For TYPE = 'CAYLEY' the transformation is |
c | lambda = sigma * (theta + 1) / (theta - 1 ) |
c | where the theta are the Ritz values returned by dsaupd . |
c | NOTES: |
c | *The Ritz vectors are not affected by the transformation. |
c | They are only reordered. |
c %-------------------------------------------------------------%
c
call dcopy (ncv, workl(ihd), 1, workl(iw), 1)
if (type .eq. 'SHIFTI') then
do 40 k=1, ncv
workl(ihd+k-1) = one / workl(ihd+k-1) + sigma
40 continue
else if (type .eq. 'BUCKLE') then
do 50 k=1, ncv
workl(ihd+k-1) = sigma * workl(ihd+k-1) /
& (workl(ihd+k-1) - one)
50 continue
else if (type .eq. 'CAYLEY') then
do 60 k=1, ncv
workl(ihd+k-1) = sigma * (workl(ihd+k-1) + one) /
& (workl(ihd+k-1) - one)
60 continue
end if
c
c %-------------------------------------------------------------%
c | * Store the wanted NCONV lambda values into D. |
c | * Sort the NCONV wanted lambda in WORKL(IHD:IHD+NCONV-1) |
c | into ascending order and apply sort to the NCONV theta |
c | values in the transformed system. We will need this to |
c | compute Ritz estimates in the original system. |
c | * Finally sort the lambda`s into ascending order and apply |
c | to Ritz vectors if wanted. Else just sort lambda`s into |
c | ascending order. |
c | NOTES: |
c | *workl(iw:iw+ncv-1) contain the theta ordered so that they |
c | match the ordering of the lambda. We`ll use them again for |
c | Ritz vector purification. |
c %-------------------------------------------------------------%
c
call dcopy (nconv, workl(ihd), 1, d, 1)
call dsortr ('LA', .true., nconv, workl(ihd), workl(iw))
if (rvec) then
call dsesrt ('LA', rvec , nconv, d, ncv, workl(iq), ldq)
else
call dcopy (ncv, workl(bounds), 1, workl(ihb), 1)
call dscal (ncv, bnorm2/rnorm, workl(ihb), 1)
call dsortr ('LA', .true., nconv, d, workl(ihb))
end if
c
end if
c
c %------------------------------------------------%
c | Compute the Ritz vectors. Transform the wanted |
c | eigenvectors of the symmetric tridiagonal H by |
c | the Lanczos basis matrix V. |
c %------------------------------------------------%
c
if (rvec .and. howmny .eq. 'A') then
c
c %----------------------------------------------------------%
c | Compute the QR factorization of the matrix representing |
c | the wanted invariant subspace located in the first NCONV |
c | columns of workl(iq,ldq). |
c %----------------------------------------------------------%
c
call dgeqr2 (ncv, nconv , workl(iq) ,
& ldq, workl(iw+ncv), workl(ihb),
& ierr)
c
c %--------------------------------------------------------%
c | * Postmultiply V by Q. |
c | * Copy the first NCONV columns of VQ into Z. |
c | The N by NCONV matrix Z is now a matrix representation |
c | of the approximate invariant subspace associated with |
c | the Ritz values in workl(ihd). |
c %--------------------------------------------------------%
c
call dorm2r ('Right', 'Notranspose', n ,
& ncv , nconv , workl(iq),
& ldq , workl(iw+ncv), v ,
& ldv , workd(n+1) , ierr)
call dlacpy ('All', n, nconv, v, ldv, z, ldz)
c
c %-----------------------------------------------------%
c | In order to compute the Ritz estimates for the Ritz |
c | values in both systems, need the last row of the |
c | eigenvector matrix. Remember, it`s in factored form |
c %-----------------------------------------------------%
c
do 65 j = 1, ncv-1
workl(ihb+j-1) = zero
65 continue
workl(ihb+ncv-1) = one
call dorm2r ('Left', 'Transpose' , ncv ,
& 1 , nconv , workl(iq) ,
& ldq , workl(iw+ncv), workl(ihb),
& ncv , temp , ierr)
c
else if (rvec .and. howmny .eq. 'S') then
c
c Not yet implemented. See remark 2 above.
c
end if
c
if (type .eq. 'REGULR' .and. rvec) then
c
do 70 j=1, ncv
workl(ihb+j-1) = rnorm * abs( workl(ihb+j-1) )
70 continue
c
else if (type .ne. 'REGULR' .and. rvec) then
c
c %-------------------------------------------------%
c | * Determine Ritz estimates of the theta. |
c | If RVEC = .true. then compute Ritz estimates |
c | of the theta. |
c | If RVEC = .false. then copy Ritz estimates |
c | as computed by dsaupd . |
c | * Determine Ritz estimates of the lambda. |
c %-------------------------------------------------%
c
call dscal (ncv, bnorm2, workl(ihb), 1)
if (type .eq. 'SHIFTI') then
c
do 80 k=1, ncv
workl(ihb+k-1) = abs( workl(ihb+k-1) )
& / workl(iw+k-1)**2
80 continue
c
else if (type .eq. 'BUCKLE') then
c
do 90 k=1, ncv
workl(ihb+k-1) = sigma * abs( workl(ihb+k-1) )
& / (workl(iw+k-1)-one )**2
90 continue
c
else if (type .eq. 'CAYLEY') then
c
do 100 k=1, ncv
workl(ihb+k-1) = abs( workl(ihb+k-1)
& / workl(iw+k-1)*(workl(iw+k-1)-one) )
100 continue
c
end if
c
end if
c
if (type .ne. 'REGULR' .and. msglvl .gt. 1) then
call dvout (logfil, nconv, d, ndigit,
& '_seupd: Untransformed converged Ritz values')
call dvout (logfil, nconv, workl(ihb), ndigit,
& '_seupd: Ritz estimates of the untransformed Ritz values')
else if (msglvl .gt. 1) then
call dvout (logfil, nconv, d, ndigit,
& '_seupd: Converged Ritz values')
call dvout (logfil, nconv, workl(ihb), ndigit,
& '_seupd: Associated Ritz estimates')
end if
c
c %-------------------------------------------------%
c | Ritz vector purification step. Formally perform |
c | one of inverse subspace iteration. Only used |
c | for MODE = 3,4,5. See reference 7 |
c %-------------------------------------------------%
c
if (rvec .and. (type .eq. 'SHIFTI' .or. type .eq. 'CAYLEY')) then
c
do 110 k=0, nconv-1
workl(iw+k) = workl(iq+k*ldq+ncv-1)
& / workl(iw+k)
110 continue
c
else if (rvec .and. type .eq. 'BUCKLE') then
c
do 120 k=0, nconv-1
workl(iw+k) = workl(iq+k*ldq+ncv-1)
& / (workl(iw+k)-one)
120 continue
c
end if
c
if (type .ne. 'REGULR')
& call dger (n, nconv, one, resid, 1, workl(iw), 1, z, ldz)
c
9000 continue
c
return
c
c %---------------%
c | End of dseupd |
c %---------------%
c
end

219
arpack/ARPACK/SRC/dsgets.f Normal file
View File

@@ -0,0 +1,219 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dsgets
c
c\Description:
c Given the eigenvalues of the symmetric tridiagonal matrix H,
c computes the NP shifts AMU that are zeros of the polynomial of
c degree NP which filters out components of the unwanted eigenvectors
c corresponding to the AMU's based on some given criteria.
c
c NOTE: This is called even in the case of user specified shifts in
c order to sort the eigenvalues, and error bounds of H for later use.
c
c\Usage:
c call dsgets
c ( ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS, SHIFTS )
c
c\Arguments
c ISHIFT Integer. (INPUT)
c Method for selecting the implicit shifts at each iteration.
c ISHIFT = 0: user specified shifts
c ISHIFT = 1: exact shift with respect to the matrix H.
c
c WHICH Character*2. (INPUT)
c Shift selection criteria.
c 'LM' -> KEV eigenvalues of largest magnitude are retained.
c 'SM' -> KEV eigenvalues of smallest magnitude are retained.
c 'LA' -> KEV eigenvalues of largest value are retained.
c 'SA' -> KEV eigenvalues of smallest value are retained.
c 'BE' -> KEV eigenvalues, half from each end of the spectrum.
c If KEV is odd, compute one more from the high end.
c
c KEV Integer. (INPUT)
c KEV+NP is the size of the matrix H.
c
c NP Integer. (INPUT)
c Number of implicit shifts to be computed.
c
c RITZ Double precision array of length KEV+NP. (INPUT/OUTPUT)
c On INPUT, RITZ contains the eigenvalues of H.
c On OUTPUT, RITZ are sorted so that the unwanted eigenvalues
c are in the first NP locations and the wanted part is in
c the last KEV locations. When exact shifts are selected, the
c unwanted part corresponds to the shifts to be applied.
c
c BOUNDS Double precision array of length KEV+NP. (INPUT/OUTPUT)
c Error bounds corresponding to the ordering in RITZ.
c
c SHIFTS Double precision array of length NP. (INPUT/OUTPUT)
c On INPUT: contains the user specified shifts if ISHIFT = 0.
c On OUTPUT: contains the shifts sorted into decreasing order
c of magnitude with respect to the Ritz estimates contained in
c BOUNDS. If ISHIFT = 0, SHIFTS is not modified on exit.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c dsortr ARPACK utility sorting routine.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c dvout ARPACK utility routine that prints vectors.
c dcopy Level 1 BLAS that copies one vector to another.
c dswap Level 1 BLAS that swaps the contents of two vectors.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/93: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: sgets.F SID: 2.4 DATE OF SID: 4/19/96 RELEASE: 2
c
c\Remarks
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dsgets ( ishift, which, kev, np, ritz, bounds, shifts )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
integer ishift, kev, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& bounds(kev+np), ritz(kev+np), shifts(np)
c
c %------------%
c | Parameters |
c %------------%
c
Double precision
& one, zero
parameter (one = 1.0D+0, zero = 0.0D+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer kevd2, msglvl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external dswap, dcopy, dsortr, second
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic max, min
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = msgets
c
if (which .eq. 'BE') then
c
c %-----------------------------------------------------%
c | Both ends of the spectrum are requested. |
c | Sort the eigenvalues into algebraically increasing |
c | order first then swap high end of the spectrum next |
c | to low end in appropriate locations. |
c | NOTE: when np < floor(kev/2) be careful not to swap |
c | overlapping locations. |
c %-----------------------------------------------------%
c
call dsortr ('LA', .true., kev+np, ritz, bounds)
kevd2 = kev / 2
if ( kev .gt. 1 ) then
call dswap ( min(kevd2,np), ritz, 1,
& ritz( max(kevd2,np)+1 ), 1)
call dswap ( min(kevd2,np), bounds, 1,
& bounds( max(kevd2,np)+1 ), 1)
end if
c
else
c
c %----------------------------------------------------%
c | LM, SM, LA, SA case. |
c | Sort the eigenvalues of H into the desired order |
c | and apply the resulting order to BOUNDS. |
c | The eigenvalues are sorted so that the wanted part |
c | are always in the last KEV locations. |
c %----------------------------------------------------%
c
call dsortr (which, .true., kev+np, ritz, bounds)
end if
c
if (ishift .eq. 1 .and. np .gt. 0) then
c
c %-------------------------------------------------------%
c | Sort the unwanted Ritz values used as shifts so that |
c | the ones with largest Ritz estimates are first. |
c | This will tend to minimize the effects of the |
c | forward instability of the iteration when the shifts |
c | are applied in subroutine dsapps. |
c %-------------------------------------------------------%
c
call dsortr ('SM', .true., np, bounds, ritz)
call dcopy (np, ritz, 1, shifts, 1)
end if
c
call second (t1)
tsgets = tsgets + (t1 - t0)
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, kev, ndigit, '_sgets: KEV is')
call ivout (logfil, 1, np, ndigit, '_sgets: NP is')
call dvout (logfil, kev+np, ritz, ndigit,
& '_sgets: Eigenvalues of current H matrix')
call dvout (logfil, kev+np, bounds, ndigit,
& '_sgets: Associated Ritz estimates')
end if
c
return
c
c %---------------%
c | End of dsgets |
c %---------------%
c
end

344
arpack/ARPACK/SRC/dsortc.f Normal file
View File

@@ -0,0 +1,344 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dsortc
c
c\Description:
c Sorts the complex array in XREAL and XIMAG into the order
c specified by WHICH and optionally applies the permutation to the
c real array Y. It is assumed that if an element of XIMAG is
c nonzero, then its negative is also an element. In other words,
c both members of a complex conjugate pair are to be sorted and the
c pairs are kept adjacent to each other.
c
c\Usage:
c call dsortc
c ( WHICH, APPLY, N, XREAL, XIMAG, Y )
c
c\Arguments
c WHICH Character*2. (Input)
c 'LM' -> sort XREAL,XIMAG into increasing order of magnitude.
c 'SM' -> sort XREAL,XIMAG into decreasing order of magnitude.
c 'LR' -> sort XREAL into increasing order of algebraic.
c 'SR' -> sort XREAL into decreasing order of algebraic.
c 'LI' -> sort XIMAG into increasing order of magnitude.
c 'SI' -> sort XIMAG into decreasing order of magnitude.
c NOTE: If an element of XIMAG is non-zero, then its negative
c is also an element.
c
c APPLY Logical. (Input)
c APPLY = .TRUE. -> apply the sorted order to array Y.
c APPLY = .FALSE. -> do not apply the sorted order to array Y.
c
c N Integer. (INPUT)
c Size of the arrays.
c
c XREAL, Double precision array of length N. (INPUT/OUTPUT)
c XIMAG Real and imaginary part of the array to be sorted.
c
c Y Double precision array of length N. (INPUT/OUTPUT)
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.1'
c Adapted from the sort routine in LANSO.
c
c\SCCS Information: @(#)
c FILE: sortc.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dsortc (which, apply, n, xreal, ximag, y)
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
logical apply
integer n
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& xreal(0:n-1), ximag(0:n-1), y(0:n-1)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, igap, j
Double precision
& temp, temp1, temp2
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dlapy2
external dlapy2
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
igap = n / 2
c
if (which .eq. 'LM') then
c
c %------------------------------------------------------%
c | Sort XREAL,XIMAG into increasing order of magnitude. |
c %------------------------------------------------------%
c
10 continue
if (igap .eq. 0) go to 9000
c
do 30 i = igap, n-1
j = i-igap
20 continue
c
if (j.lt.0) go to 30
c
temp1 = dlapy2(xreal(j),ximag(j))
temp2 = dlapy2(xreal(j+igap),ximag(j+igap))
c
if (temp1.gt.temp2) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 30
end if
j = j-igap
go to 20
30 continue
igap = igap / 2
go to 10
c
else if (which .eq. 'SM') then
c
c %------------------------------------------------------%
c | Sort XREAL,XIMAG into decreasing order of magnitude. |
c %------------------------------------------------------%
c
40 continue
if (igap .eq. 0) go to 9000
c
do 60 i = igap, n-1
j = i-igap
50 continue
c
if (j .lt. 0) go to 60
c
temp1 = dlapy2(xreal(j),ximag(j))
temp2 = dlapy2(xreal(j+igap),ximag(j+igap))
c
if (temp1.lt.temp2) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 60
endif
j = j-igap
go to 50
60 continue
igap = igap / 2
go to 40
c
else if (which .eq. 'LR') then
c
c %------------------------------------------------%
c | Sort XREAL into increasing order of algebraic. |
c %------------------------------------------------%
c
70 continue
if (igap .eq. 0) go to 9000
c
do 90 i = igap, n-1
j = i-igap
80 continue
c
if (j.lt.0) go to 90
c
if (xreal(j).gt.xreal(j+igap)) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 90
endif
j = j-igap
go to 80
90 continue
igap = igap / 2
go to 70
c
else if (which .eq. 'SR') then
c
c %------------------------------------------------%
c | Sort XREAL into decreasing order of algebraic. |
c %------------------------------------------------%
c
100 continue
if (igap .eq. 0) go to 9000
do 120 i = igap, n-1
j = i-igap
110 continue
c
if (j.lt.0) go to 120
c
if (xreal(j).lt.xreal(j+igap)) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 120
endif
j = j-igap
go to 110
120 continue
igap = igap / 2
go to 100
c
else if (which .eq. 'LI') then
c
c %------------------------------------------------%
c | Sort XIMAG into increasing order of magnitude. |
c %------------------------------------------------%
c
130 continue
if (igap .eq. 0) go to 9000
do 150 i = igap, n-1
j = i-igap
140 continue
c
if (j.lt.0) go to 150
c
if (abs(ximag(j)).gt.abs(ximag(j+igap))) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 150
endif
j = j-igap
go to 140
150 continue
igap = igap / 2
go to 130
c
else if (which .eq. 'SI') then
c
c %------------------------------------------------%
c | Sort XIMAG into decreasing order of magnitude. |
c %------------------------------------------------%
c
160 continue
if (igap .eq. 0) go to 9000
do 180 i = igap, n-1
j = i-igap
170 continue
c
if (j.lt.0) go to 180
c
if (abs(ximag(j)).lt.abs(ximag(j+igap))) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 180
endif
j = j-igap
go to 170
180 continue
igap = igap / 2
go to 160
end if
c
9000 continue
return
c
c %---------------%
c | End of dsortc |
c %---------------%
c
end

218
arpack/ARPACK/SRC/dsortr.f Normal file
View File

@@ -0,0 +1,218 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dsortr
c
c\Description:
c Sort the array X1 in the order specified by WHICH and optionally
c applies the permutation to the array X2.
c
c\Usage:
c call dsortr
c ( WHICH, APPLY, N, X1, X2 )
c
c\Arguments
c WHICH Character*2. (Input)
c 'LM' -> X1 is sorted into increasing order of magnitude.
c 'SM' -> X1 is sorted into decreasing order of magnitude.
c 'LA' -> X1 is sorted into increasing order of algebraic.
c 'SA' -> X1 is sorted into decreasing order of algebraic.
c
c APPLY Logical. (Input)
c APPLY = .TRUE. -> apply the sorted order to X2.
c APPLY = .FALSE. -> do not apply the sorted order to X2.
c
c N Integer. (INPUT)
c Size of the arrays.
c
c X1 Double precision array of length N. (INPUT/OUTPUT)
c The array to be sorted.
c
c X2 Double precision array of length N. (INPUT/OUTPUT)
c Only referenced if APPLY = .TRUE.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/16/93: Version ' 2.1'.
c Adapted from the sort routine in LANSO.
c
c\SCCS Information: @(#)
c FILE: sortr.F SID: 2.3 DATE OF SID: 4/19/96 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dsortr (which, apply, n, x1, x2)
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
logical apply
integer n
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& x1(0:n-1), x2(0:n-1)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, igap, j
Double precision
& temp
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
igap = n / 2
c
if (which .eq. 'SA') then
c
c X1 is sorted into decreasing order of algebraic.
c
10 continue
if (igap .eq. 0) go to 9000
do 30 i = igap, n-1
j = i-igap
20 continue
c
if (j.lt.0) go to 30
c
if (x1(j).lt.x1(j+igap)) then
temp = x1(j)
x1(j) = x1(j+igap)
x1(j+igap) = temp
if (apply) then
temp = x2(j)
x2(j) = x2(j+igap)
x2(j+igap) = temp
end if
else
go to 30
endif
j = j-igap
go to 20
30 continue
igap = igap / 2
go to 10
c
else if (which .eq. 'SM') then
c
c X1 is sorted into decreasing order of magnitude.
c
40 continue
if (igap .eq. 0) go to 9000
do 60 i = igap, n-1
j = i-igap
50 continue
c
if (j.lt.0) go to 60
c
if (abs(x1(j)).lt.abs(x1(j+igap))) then
temp = x1(j)
x1(j) = x1(j+igap)
x1(j+igap) = temp
if (apply) then
temp = x2(j)
x2(j) = x2(j+igap)
x2(j+igap) = temp
end if
else
go to 60
endif
j = j-igap
go to 50
60 continue
igap = igap / 2
go to 40
c
else if (which .eq. 'LA') then
c
c X1 is sorted into increasing order of algebraic.
c
70 continue
if (igap .eq. 0) go to 9000
do 90 i = igap, n-1
j = i-igap
80 continue
c
if (j.lt.0) go to 90
c
if (x1(j).gt.x1(j+igap)) then
temp = x1(j)
x1(j) = x1(j+igap)
x1(j+igap) = temp
if (apply) then
temp = x2(j)
x2(j) = x2(j+igap)
x2(j+igap) = temp
end if
else
go to 90
endif
j = j-igap
go to 80
90 continue
igap = igap / 2
go to 70
c
else if (which .eq. 'LM') then
c
c X1 is sorted into increasing order of magnitude.
c
100 continue
if (igap .eq. 0) go to 9000
do 120 i = igap, n-1
j = i-igap
110 continue
c
if (j.lt.0) go to 120
c
if (abs(x1(j)).gt.abs(x1(j+igap))) then
temp = x1(j)
x1(j) = x1(j+igap)
x1(j+igap) = temp
if (apply) then
temp = x2(j)
x2(j) = x2(j+igap)
x2(j+igap) = temp
end if
else
go to 120
endif
j = j-igap
go to 110
120 continue
igap = igap / 2
go to 100
end if
c
9000 continue
return
c
c %---------------%
c | End of dsortr |
c %---------------%
c
end

View File

@@ -0,0 +1,61 @@
c
c %---------------------------------------------%
c | Initialize statistic and timing information |
c | for nonsymmetric Arnoldi code. |
c %---------------------------------------------%
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: statn.F SID: 2.4 DATE OF SID: 4/20/96 RELEASE: 2
c
subroutine dstatn
c
c %--------------------------------%
c | See stat.doc for documentation |
c %--------------------------------%
c
include 'stat.h'
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
nopx = 0
nbx = 0
nrorth = 0
nitref = 0
nrstrt = 0
c
tnaupd = 0.0D+0
tnaup2 = 0.0D+0
tnaitr = 0.0D+0
tneigh = 0.0D+0
tngets = 0.0D+0
tnapps = 0.0D+0
tnconv = 0.0D+0
titref = 0.0D+0
tgetv0 = 0.0D+0
trvec = 0.0D+0
c
c %----------------------------------------------------%
c | User time including reverse communication overhead |
c %----------------------------------------------------%
c
tmvopx = 0.0D+0
tmvbx = 0.0D+0
c
return
c
c
c %---------------%
c | End of dstatn |
c %---------------%
c
end

View File

@@ -0,0 +1,47 @@
c
c\SCCS Information: @(#)
c FILE: stats.F SID: 2.1 DATE OF SID: 4/19/96 RELEASE: 2
c %---------------------------------------------%
c | Initialize statistic and timing information |
c | for symmetric Arnoldi code. |
c %---------------------------------------------%
subroutine dstats
c %--------------------------------%
c | See stat.doc for documentation |
c %--------------------------------%
include 'stat.h'
c %-----------------------%
c | Executable Statements |
c %-----------------------%
nopx = 0
nbx = 0
nrorth = 0
nitref = 0
nrstrt = 0
tsaupd = 0.0D+0
tsaup2 = 0.0D+0
tsaitr = 0.0D+0
tseigt = 0.0D+0
tsgets = 0.0D+0
tsapps = 0.0D+0
tsconv = 0.0D+0
titref = 0.0D+0
tgetv0 = 0.0D+0
trvec = 0.0D+0
c %----------------------------------------------------%
c | User time including reverse communication overhead |
c %----------------------------------------------------%
tmvopx = 0.0D+0
tmvbx = 0.0D+0
return
c
c End of dstats
c
end

594
arpack/ARPACK/SRC/dstqrb.f Normal file
View File

@@ -0,0 +1,594 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: dstqrb
c
c\Description:
c Computes all eigenvalues and the last component of the eigenvectors
c of a symmetric tridiagonal matrix using the implicit QL or QR method.
c
c This is mostly a modification of the LAPACK routine dsteqr.
c See Remarks.
c
c\Usage:
c call dstqrb
c ( N, D, E, Z, WORK, INFO )
c
c\Arguments
c N Integer. (INPUT)
c The number of rows and columns in the matrix. N >= 0.
c
c D Double precision array, dimension (N). (INPUT/OUTPUT)
c On entry, D contains the diagonal elements of the
c tridiagonal matrix.
c On exit, D contains the eigenvalues, in ascending order.
c If an error exit is made, the eigenvalues are correct
c for indices 1,2,...,INFO-1, but they are unordered and
c may not be the smallest eigenvalues of the matrix.
c
c E Double precision array, dimension (N-1). (INPUT/OUTPUT)
c On entry, E contains the subdiagonal elements of the
c tridiagonal matrix in positions 1 through N-1.
c On exit, E has been destroyed.
c
c Z Double precision array, dimension (N). (OUTPUT)
c On exit, Z contains the last row of the orthonormal
c eigenvector matrix of the symmetric tridiagonal matrix.
c If an error exit is made, Z contains the last row of the
c eigenvector matrix associated with the stored eigenvalues.
c
c WORK Double precision array, dimension (max(1,2*N-2)). (WORKSPACE)
c Workspace used in accumulating the transformation for
c computing the last components of the eigenvectors.
c
c INFO Integer. (OUTPUT)
c = 0: normal return.
c < 0: if INFO = -i, the i-th argument had an illegal value.
c > 0: if INFO = +i, the i-th eigenvalue has not converged
c after a total of 30*N iterations.
c
c\Remarks
c 1. None.
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c daxpy Level 1 BLAS that computes a vector triad.
c dcopy Level 1 BLAS that copies one vector to another.
c dswap Level 1 BLAS that swaps the contents of two vectors.
c lsame LAPACK character comparison routine.
c dlae2 LAPACK routine that computes the eigenvalues of a 2-by-2
c symmetric matrix.
c dlaev2 LAPACK routine that eigendecomposition of a 2-by-2 symmetric
c matrix.
c dlamch LAPACK routine that determines machine constants.
c dlanst LAPACK routine that computes the norm of a matrix.
c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c dlartg LAPACK Givens rotation construction routine.
c dlascl LAPACK routine for careful scaling of a matrix.
c dlaset LAPACK matrix initialization routine.
c dlasr LAPACK routine that applies an orthogonal transformation to
c a matrix.
c dlasrt LAPACK sorting routine.
c dsteqr LAPACK routine that computes eigenvalues and eigenvectors
c of a symmetric tridiagonal matrix.
c xerbla LAPACK error handler routine.
c
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: stqrb.F SID: 2.5 DATE OF SID: 8/27/96 RELEASE: 2
c
c\Remarks
c 1. Starting with version 2.5, this routine is a modified version
c of LAPACK version 2.0 subroutine SSTEQR. No lines are deleted,
c only commeted out and new lines inserted.
c All lines commented out have "c$$$" at the beginning.
c Note that the LAPACK version 1.0 subroutine SSTEQR contained
c bugs.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine dstqrb ( n, d, e, z, work, info )
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer info, n
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Double precision
& d( n ), e( n-1 ), z( n ), work( 2*n-2 )
c
c .. parameters ..
Double precision
& zero, one, two, three
parameter ( zero = 0.0D+0, one = 1.0D+0,
& two = 2.0D+0, three = 3.0D+0 )
integer maxit
parameter ( maxit = 30 )
c ..
c .. local scalars ..
integer i, icompz, ii, iscale, j, jtot, k, l, l1, lend,
& lendm1, lendp1, lendsv, lm1, lsv, m, mm, mm1,
& nm1, nmaxit
Double precision
& anorm, b, c, eps, eps2, f, g, p, r, rt1, rt2,
& s, safmax, safmin, ssfmax, ssfmin, tst
c ..
c .. external functions ..
logical lsame
Double precision
& dlamch, dlanst, dlapy2
external lsame, dlamch, dlanst, dlapy2
c ..
c .. external subroutines ..
external dlae2, dlaev2, dlartg, dlascl, dlaset, dlasr,
& dlasrt, dswap, xerbla
c ..
c .. intrinsic functions ..
intrinsic abs, max, sign, sqrt
c ..
c .. executable statements ..
c
c test the input parameters.
c
info = 0
c
c$$$ IF( LSAME( COMPZ, 'N' ) ) THEN
c$$$ ICOMPZ = 0
c$$$ ELSE IF( LSAME( COMPZ, 'V' ) ) THEN
c$$$ ICOMPZ = 1
c$$$ ELSE IF( LSAME( COMPZ, 'I' ) ) THEN
c$$$ ICOMPZ = 2
c$$$ ELSE
c$$$ ICOMPZ = -1
c$$$ END IF
c$$$ IF( ICOMPZ.LT.0 ) THEN
c$$$ INFO = -1
c$$$ ELSE IF( N.LT.0 ) THEN
c$$$ INFO = -2
c$$$ ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1,
c$$$ $ N ) ) ) THEN
c$$$ INFO = -6
c$$$ END IF
c$$$ IF( INFO.NE.0 ) THEN
c$$$ CALL XERBLA( 'SSTEQR', -INFO )
c$$$ RETURN
c$$$ END IF
c
c *** New starting with version 2.5 ***
c
icompz = 2
c *************************************
c
c quick return if possible
c
if( n.eq.0 )
$ return
c
if( n.eq.1 ) then
if( icompz.eq.2 ) z( 1 ) = one
return
end if
c
c determine the unit roundoff and over/underflow thresholds.
c
eps = dlamch( 'e' )
eps2 = eps**2
safmin = dlamch( 's' )
safmax = one / safmin
ssfmax = sqrt( safmax ) / three
ssfmin = sqrt( safmin ) / eps2
c
c compute the eigenvalues and eigenvectors of the tridiagonal
c matrix.
c
c$$ if( icompz.eq.2 )
c$$$ $ call dlaset( 'full', n, n, zero, one, z, ldz )
c
c *** New starting with version 2.5 ***
c
if ( icompz .eq. 2 ) then
do 5 j = 1, n-1
z(j) = zero
5 continue
z( n ) = one
end if
c *************************************
c
nmaxit = n*maxit
jtot = 0
c
c determine where the matrix splits and choose ql or qr iteration
c for each block, according to whether top or bottom diagonal
c element is smaller.
c
l1 = 1
nm1 = n - 1
c
10 continue
if( l1.gt.n )
$ go to 160
if( l1.gt.1 )
$ e( l1-1 ) = zero
if( l1.le.nm1 ) then
do 20 m = l1, nm1
tst = abs( e( m ) )
if( tst.eq.zero )
$ go to 30
if( tst.le.( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+
$ 1 ) ) ) )*eps ) then
e( m ) = zero
go to 30
end if
20 continue
end if
m = n
c
30 continue
l = l1
lsv = l
lend = m
lendsv = lend
l1 = m + 1
if( lend.eq.l )
$ go to 10
c
c scale submatrix in rows and columns l to lend
c
anorm = dlanst( 'i', lend-l+1, d( l ), e( l ) )
iscale = 0
if( anorm.eq.zero )
$ go to 10
if( anorm.gt.ssfmax ) then
iscale = 1
call dlascl( 'g', 0, 0, anorm, ssfmax, lend-l+1, 1, d( l ), n,
$ info )
call dlascl( 'g', 0, 0, anorm, ssfmax, lend-l, 1, e( l ), n,
$ info )
else if( anorm.lt.ssfmin ) then
iscale = 2
call dlascl( 'g', 0, 0, anorm, ssfmin, lend-l+1, 1, d( l ), n,
$ info )
call dlascl( 'g', 0, 0, anorm, ssfmin, lend-l, 1, e( l ), n,
$ info )
end if
c
c choose between ql and qr iteration
c
if( abs( d( lend ) ).lt.abs( d( l ) ) ) then
lend = lsv
l = lendsv
end if
c
if( lend.gt.l ) then
c
c ql iteration
c
c look for small subdiagonal element.
c
40 continue
if( l.ne.lend ) then
lendm1 = lend - 1
do 50 m = l, lendm1
tst = abs( e( m ) )**2
if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+
$ safmin )go to 60
50 continue
end if
c
m = lend
c
60 continue
if( m.lt.lend )
$ e( m ) = zero
p = d( l )
if( m.eq.l )
$ go to 80
c
c if remaining matrix is 2-by-2, use dlae2 or dlaev2
c to compute its eigensystem.
c
if( m.eq.l+1 ) then
if( icompz.gt.0 ) then
call dlaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s )
work( l ) = c
work( n-1+l ) = s
c$$$ call dlasr( 'r', 'v', 'b', n, 2, work( l ),
c$$$ $ work( n-1+l ), z( 1, l ), ldz )
c
c *** New starting with version 2.5 ***
c
tst = z(l+1)
z(l+1) = c*tst - s*z(l)
z(l) = s*tst + c*z(l)
c *************************************
else
call dlae2( d( l ), e( l ), d( l+1 ), rt1, rt2 )
end if
d( l ) = rt1
d( l+1 ) = rt2
e( l ) = zero
l = l + 2
if( l.le.lend )
$ go to 40
go to 140
end if
c
if( jtot.eq.nmaxit )
$ go to 140
jtot = jtot + 1
c
c form shift.
c
g = ( d( l+1 )-p ) / ( two*e( l ) )
r = dlapy2( g, one )
g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) )
c
s = one
c = one
p = zero
c
c inner loop
c
mm1 = m - 1
do 70 i = mm1, l, -1
f = s*e( i )
b = c*e( i )
call dlartg( g, f, c, s, r )
if( i.ne.m-1 )
$ e( i+1 ) = r
g = d( i+1 ) - p
r = ( d( i )-g )*s + two*c*b
p = s*r
d( i+1 ) = g + p
g = c*r - b
c
c if eigenvectors are desired, then save rotations.
c
if( icompz.gt.0 ) then
work( i ) = c
work( n-1+i ) = -s
end if
c
70 continue
c
c if eigenvectors are desired, then apply saved rotations.
c
if( icompz.gt.0 ) then
mm = m - l + 1
c$$$ call dlasr( 'r', 'v', 'b', n, mm, work( l ), work( n-1+l ),
c$$$ $ z( 1, l ), ldz )
c
c *** New starting with version 2.5 ***
c
call dlasr( 'r', 'v', 'b', 1, mm, work( l ),
& work( n-1+l ), z( l ), 1 )
c *************************************
end if
c
d( l ) = d( l ) - p
e( l ) = g
go to 40
c
c eigenvalue found.
c
80 continue
d( l ) = p
c
l = l + 1
if( l.le.lend )
$ go to 40
go to 140
c
else
c
c qr iteration
c
c look for small superdiagonal element.
c
90 continue
if( l.ne.lend ) then
lendp1 = lend + 1
do 100 m = l, lendp1, -1
tst = abs( e( m-1 ) )**2
if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+
$ safmin )go to 110
100 continue
end if
c
m = lend
c
110 continue
if( m.gt.lend )
$ e( m-1 ) = zero
p = d( l )
if( m.eq.l )
$ go to 130
c
c if remaining matrix is 2-by-2, use dlae2 or dlaev2
c to compute its eigensystem.
c
if( m.eq.l-1 ) then
if( icompz.gt.0 ) then
call dlaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s )
c$$$ work( m ) = c
c$$$ work( n-1+m ) = s
c$$$ call dlasr( 'r', 'v', 'f', n, 2, work( m ),
c$$$ $ work( n-1+m ), z( 1, l-1 ), ldz )
c
c *** New starting with version 2.5 ***
c
tst = z(l)
z(l) = c*tst - s*z(l-1)
z(l-1) = s*tst + c*z(l-1)
c *************************************
else
call dlae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 )
end if
d( l-1 ) = rt1
d( l ) = rt2
e( l-1 ) = zero
l = l - 2
if( l.ge.lend )
$ go to 90
go to 140
end if
c
if( jtot.eq.nmaxit )
$ go to 140
jtot = jtot + 1
c
c form shift.
c
g = ( d( l-1 )-p ) / ( two*e( l-1 ) )
r = dlapy2( g, one )
g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) )
c
s = one
c = one
p = zero
c
c inner loop
c
lm1 = l - 1
do 120 i = m, lm1
f = s*e( i )
b = c*e( i )
call dlartg( g, f, c, s, r )
if( i.ne.m )
$ e( i-1 ) = r
g = d( i ) - p
r = ( d( i+1 )-g )*s + two*c*b
p = s*r
d( i ) = g + p
g = c*r - b
c
c if eigenvectors are desired, then save rotations.
c
if( icompz.gt.0 ) then
work( i ) = c
work( n-1+i ) = s
end if
c
120 continue
c
c if eigenvectors are desired, then apply saved rotations.
c
if( icompz.gt.0 ) then
mm = l - m + 1
c$$$ call dlasr( 'r', 'v', 'f', n, mm, work( m ), work( n-1+m ),
c$$$ $ z( 1, m ), ldz )
c
c *** New starting with version 2.5 ***
c
call dlasr( 'r', 'v', 'f', 1, mm, work( m ), work( n-1+m ),
& z( m ), 1 )
c *************************************
end if
c
d( l ) = d( l ) - p
e( lm1 ) = g
go to 90
c
c eigenvalue found.
c
130 continue
d( l ) = p
c
l = l - 1
if( l.ge.lend )
$ go to 90
go to 140
c
end if
c
c undo scaling if necessary
c
140 continue
if( iscale.eq.1 ) then
call dlascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv+1, 1,
$ d( lsv ), n, info )
call dlascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv, 1, e( lsv ),
$ n, info )
else if( iscale.eq.2 ) then
call dlascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv+1, 1,
$ d( lsv ), n, info )
call dlascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv, 1, e( lsv ),
$ n, info )
end if
c
c check for no convergence to an eigenvalue after a total
c of n*maxit iterations.
c
if( jtot.lt.nmaxit )
$ go to 10
do 150 i = 1, n - 1
if( e( i ).ne.zero )
$ info = info + 1
150 continue
go to 190
c
c order eigenvalues and eigenvectors.
c
160 continue
if( icompz.eq.0 ) then
c
c use quick sort
c
call dlasrt( 'i', n, d, info )
c
else
c
c use selection sort to minimize swaps of eigenvectors
c
do 180 ii = 2, n
i = ii - 1
k = i
p = d( i )
do 170 j = ii, n
if( d( j ).lt.p ) then
k = j
p = d( j )
end if
170 continue
if( k.ne.i ) then
d( k ) = d( i )
d( i ) = p
c$$$ call dswap( n, z( 1, i ), 1, z( 1, k ), 1 )
c *** New starting with version 2.5 ***
c
p = z(k)
z(k) = z(i)
z(i) = p
c *************************************
end if
180 continue
end if
c
190 continue
return
c
c %---------------%
c | End of dstqrb |
c %---------------%
c
end

419
arpack/ARPACK/SRC/sgetv0.f Normal file
View File

@@ -0,0 +1,419 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: sgetv0
c
c\Description:
c Generate a random initial residual vector for the Arnoldi process.
c Force the residual vector to be in the range of the operator OP.
c
c\Usage:
c call sgetv0
c ( IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM,
c IPNTR, WORKD, IERR )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag. IDO must be zero on the first
c call to sgetv0.
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c This is for the initialization phase to force the
c starting vector into the range of OP.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c IDO = 99: done
c -------------------------------------------------------------
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B in the (generalized)
c eigenvalue problem A*x = lambda*B*x.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x
c
c ITRY Integer. (INPUT)
c ITRY counts the number of times that sgetv0 is called.
c It should be set to 1 on the initial call to sgetv0.
c
c INITV Logical variable. (INPUT)
c .TRUE. => the initial residual vector is given in RESID.
c .FALSE. => generate a random initial residual vector.
c
c N Integer. (INPUT)
c Dimension of the problem.
c
c J Integer. (INPUT)
c Index of the residual vector to be generated, with respect to
c the Arnoldi process. J > 1 in case of a "restart".
c
c V Real N by J array. (INPUT)
c The first J-1 columns of V contain the current Arnoldi basis
c if this is a "restart".
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c RESID Real array of length N. (INPUT/OUTPUT)
c Initial residual vector to be generated. If RESID is
c provided, force RESID into the range of the operator OP.
c
c RNORM Real scalar. (OUTPUT)
c B-norm of the generated residual.
c
c IPNTR Integer array of length 3. (OUTPUT)
c
c WORKD Real work array of length 2*N. (REVERSE COMMUNICATION).
c On exit, WORK(1:N) = B*RESID to be used in SSAITR.
c
c IERR Integer. (OUTPUT)
c = 0: Normal exit.
c = -1: Cannot generate a nontrivial restarted residual vector
c in the range of the operator OP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c second ARPACK utility routine for timing.
c svout ARPACK utility routine for vector output.
c slarnv LAPACK routine for generating a random vector.
c sgemv Level 2 BLAS routine for matrix vector multiplication.
c scopy Level 1 BLAS that copies one vector to another.
c sdot Level 1 BLAS that computes the scalar product of two vectors.
c snrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: getv0.F SID: 2.7 DATE OF SID: 04/07/99 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine sgetv0
& ( ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm,
& ipntr, workd, ierr )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1
logical initv
integer ido, ierr, itry, j, ldv, n
Real
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Real
& resid(n), v(ldv,j), workd(2*n)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0, zero = 0.0E+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
logical first, inits, orth
integer idist, iseed(4), iter, msglvl, jj
Real
& rnorm0
save first, iseed, inits, iter, msglvl, orth, rnorm0
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external slarnv, svout, scopy, sgemv, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& sdot, snrm2
external sdot, snrm2
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic abs, sqrt
c
c %-----------------%
c | Data Statements |
c %-----------------%
c
data inits /.true./
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c
c %-----------------------------------%
c | Initialize the seed of the LAPACK |
c | random number generator |
c %-----------------------------------%
c
if (inits) then
iseed(1) = 1
iseed(2) = 3
iseed(3) = 5
iseed(4) = 7
inits = .false.
end if
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mgetv0
c
ierr = 0
iter = 0
first = .FALSE.
orth = .FALSE.
c
c %-----------------------------------------------------%
c | Possibly generate a random starting vector in RESID |
c | Use a LAPACK random number generator used by the |
c | matrix generation routines. |
c | idist = 1: uniform (0,1) distribution; |
c | idist = 2: uniform (-1,1) distribution; |
c | idist = 3: normal (0,1) distribution; |
c %-----------------------------------------------------%
c
if (.not.initv) then
idist = 2
call slarnv (idist, iseed, n, resid)
end if
c
c %----------------------------------------------------------%
c | Force the starting vector into the range of OP to handle |
c | the generalized problem when B is possibly (singular). |
c %----------------------------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nopx = nopx + 1
ipntr(1) = 1
ipntr(2) = n + 1
call scopy (n, resid, 1, workd, 1)
ido = -1
go to 9000
end if
end if
c
c %-----------------------------------------%
c | Back from computing OP*(initial-vector) |
c %-----------------------------------------%
c
if (first) go to 20
c
c %-----------------------------------------------%
c | Back from computing B*(orthogonalized-vector) |
c %-----------------------------------------------%
c
if (orth) go to 40
c
if (bmat .eq. 'G') then
call second (t3)
tmvopx = tmvopx + (t3 - t2)
end if
c
c %------------------------------------------------------%
c | Starting vector is now in the range of OP; r = OP*r; |
c | Compute B-norm of starting vector. |
c %------------------------------------------------------%
c
call second (t2)
first = .TRUE.
if (bmat .eq. 'G') then
nbx = nbx + 1
call scopy (n, workd(n+1), 1, resid, 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
go to 9000
else if (bmat .eq. 'I') then
call scopy (n, resid, 1, workd, 1)
end if
c
20 continue
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
first = .FALSE.
if (bmat .eq. 'G') then
rnorm0 = sdot (n, resid, 1, workd, 1)
rnorm0 = sqrt(abs(rnorm0))
else if (bmat .eq. 'I') then
rnorm0 = snrm2(n, resid, 1)
end if
rnorm = rnorm0
c
c %---------------------------------------------%
c | Exit if this is the very first Arnoldi step |
c %---------------------------------------------%
c
if (j .eq. 1) go to 50
c
c %----------------------------------------------------------------
c | Otherwise need to B-orthogonalize the starting vector against |
c | the current Arnoldi basis using Gram-Schmidt with iter. ref. |
c | This is the case where an invariant subspace is encountered |
c | in the middle of the Arnoldi factorization. |
c | |
c | s = V^{T}*B*r; r = r - V*s; |
c | |
c | Stopping criteria used for iter. ref. is discussed in |
c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. |
c %---------------------------------------------------------------%
c
orth = .TRUE.
30 continue
c
call sgemv ('T', n, j-1, one, v, ldv, workd, 1,
& zero, workd(n+1), 1)
call sgemv ('N', n, j-1, -one, v, ldv, workd(n+1), 1,
& one, resid, 1)
c
c %----------------------------------------------------------%
c | Compute the B-norm of the orthogonalized starting vector |
c %----------------------------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call scopy (n, resid, 1, workd(n+1), 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
go to 9000
else if (bmat .eq. 'I') then
call scopy (n, resid, 1, workd, 1)
end if
c
40 continue
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
if (bmat .eq. 'G') then
rnorm = sdot (n, resid, 1, workd, 1)
rnorm = sqrt(abs(rnorm))
else if (bmat .eq. 'I') then
rnorm = snrm2(n, resid, 1)
end if
c
c %--------------------------------------%
c | Check for further orthogonalization. |
c %--------------------------------------%
c
if (msglvl .gt. 2) then
call svout (logfil, 1, rnorm0, ndigit,
& '_getv0: re-orthonalization ; rnorm0 is')
call svout (logfil, 1, rnorm, ndigit,
& '_getv0: re-orthonalization ; rnorm is')
end if
c
if (rnorm .gt. 0.717*rnorm0) go to 50
c
iter = iter + 1
if (iter .le. 5) then
c
c %-----------------------------------%
c | Perform iterative refinement step |
c %-----------------------------------%
c
rnorm0 = rnorm
go to 30
else
c
c %------------------------------------%
c | Iterative refinement step "failed" |
c %------------------------------------%
c
do 45 jj = 1, n
resid(jj) = zero
45 continue
rnorm = zero
ierr = -1
end if
c
50 continue
c
if (msglvl .gt. 0) then
call svout (logfil, 1, rnorm, ndigit,
& '_getv0: B-norm of initial / restarted starting vector')
end if
if (msglvl .gt. 3) then
call svout (logfil, n, resid, ndigit,
& '_getv0: initial / restarted starting vector')
end if
ido = 99
c
call second (t1)
tgetv0 = tgetv0 + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of sgetv0 |
c %---------------%
c
end

521
arpack/ARPACK/SRC/slaqrb.f Normal file
View File

@@ -0,0 +1,521 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: slaqrb
c
c\Description:
c Compute the eigenvalues and the Schur decomposition of an upper
c Hessenberg submatrix in rows and columns ILO to IHI. Only the
c last component of the Schur vectors are computed.
c
c This is mostly a modification of the LAPACK routine slahqr.
c
c\Usage:
c call slaqrb
c ( WANTT, N, ILO, IHI, H, LDH, WR, WI, Z, INFO )
c
c\Arguments
c WANTT Logical variable. (INPUT)
c = .TRUE. : the full Schur form T is required;
c = .FALSE.: only eigenvalues are required.
c
c N Integer. (INPUT)
c The order of the matrix H. N >= 0.
c
c ILO Integer. (INPUT)
c IHI Integer. (INPUT)
c It is assumed that H is already upper quasi-triangular in
c rows and columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless
c ILO = 1). SLAQRB works primarily with the Hessenberg
c submatrix in rows and columns ILO to IHI, but applies
c transformations to all of H if WANTT is .TRUE..
c 1 <= ILO <= max(1,IHI); IHI <= N.
c
c H Real array, dimension (LDH,N). (INPUT/OUTPUT)
c On entry, the upper Hessenberg matrix H.
c On exit, if WANTT is .TRUE., H is upper quasi-triangular in
c rows and columns ILO:IHI, with any 2-by-2 diagonal blocks in
c standard form. If WANTT is .FALSE., the contents of H are
c unspecified on exit.
c
c LDH Integer. (INPUT)
c The leading dimension of the array H. LDH >= max(1,N).
c
c WR Real array, dimension (N). (OUTPUT)
c WI Real array, dimension (N). (OUTPUT)
c The real and imaginary parts, respectively, of the computed
c eigenvalues ILO to IHI are stored in the corresponding
c elements of WR and WI. If two eigenvalues are computed as a
c complex conjugate pair, they are stored in consecutive
c elements of WR and WI, say the i-th and (i+1)th, with
c WI(i) > 0 and WI(i+1) < 0. If WANTT is .TRUE., the
c eigenvalues are stored in the same order as on the diagonal
c of the Schur form returned in H, with WR(i) = H(i,i), and, if
c H(i:i+1,i:i+1) is a 2-by-2 diagonal block,
c WI(i) = sqrt(H(i+1,i)*H(i,i+1)) and WI(i+1) = -WI(i).
c
c Z Real array, dimension (N). (OUTPUT)
c On exit Z contains the last components of the Schur vectors.
c
c INFO Integer. (OUPUT)
c = 0: successful exit
c > 0: SLAQRB failed to compute all the eigenvalues ILO to IHI
c in a total of 30*(IHI-ILO+1) iterations; if INFO = i,
c elements i+1:ihi of WR and WI contain those eigenvalues
c which have been successfully computed.
c
c\Remarks
c 1. None.
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c slabad LAPACK routine that computes machine constants.
c slamch LAPACK routine that determines machine constants.
c slanhs LAPACK routine that computes various norms of a matrix.
c slanv2 LAPACK routine that computes the Schur factorization of
c 2 by 2 nonsymmetric matrix in standard form.
c slarfg LAPACK Householder reflection construction routine.
c scopy Level 1 BLAS that copies one vector to another.
c srot Level 1 BLAS that applies a rotation to a 2 by 2 matrix.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.4'
c Modified from the LAPACK routine slahqr so that only the
c last component of the Schur vectors are computed.
c
c\SCCS Information: @(#)
c FILE: laqrb.F SID: 2.2 DATE OF SID: 8/27/96 RELEASE: 2
c
c\Remarks
c 1. None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine slaqrb ( wantt, n, ilo, ihi, h, ldh, wr, wi,
& z, info )
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
logical wantt
integer ihi, ilo, info, ldh, n
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& h( ldh, * ), wi( * ), wr( * ), z( * )
c
c %------------%
c | Parameters |
c %------------%
c
Real
& zero, one, dat1, dat2
parameter (zero = 0.0E+0, one = 1.0E+0, dat1 = 7.5E-1,
& dat2 = -4.375E-1)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
integer i, i1, i2, itn, its, j, k, l, m, nh, nr
Real
& cs, h00, h10, h11, h12, h21, h22, h33, h33s,
& h43h34, h44, h44s, ovfl, s, smlnum, sn, sum,
& t1, t2, t3, tst1, ulp, unfl, v1, v2, v3
Real
& v( 3 ), work( 1 )
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& slamch, slanhs
external slamch, slanhs
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external scopy, slabad, slanv2, slarfg, srot
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
info = 0
c
c %--------------------------%
c | Quick return if possible |
c %--------------------------%
c
if( n.eq.0 )
& return
if( ilo.eq.ihi ) then
wr( ilo ) = h( ilo, ilo )
wi( ilo ) = zero
return
end if
c
c %---------------------------------------------%
c | Initialize the vector of last components of |
c | the Schur vectors for accumulation. |
c %---------------------------------------------%
c
do 5 j = 1, n-1
z(j) = zero
5 continue
z(n) = one
c
nh = ihi - ilo + 1
c
c %-------------------------------------------------------------%
c | Set machine-dependent constants for the stopping criterion. |
c | If norm(H) <= sqrt(OVFL), overflow should not occur. |
c %-------------------------------------------------------------%
c
unfl = slamch( 'safe minimum' )
ovfl = one / unfl
call slabad( unfl, ovfl )
ulp = slamch( 'precision' )
smlnum = unfl*( nh / ulp )
c
c %---------------------------------------------------------------%
c | I1 and I2 are the indices of the first row and last column |
c | of H to which transformations must be applied. If eigenvalues |
c | only are computed, I1 and I2 are set inside the main loop. |
c | Zero out H(J+2,J) = ZERO for J=1:N if WANTT = .TRUE. |
c | else H(J+2,J) for J=ILO:IHI-ILO-1 if WANTT = .FALSE. |
c %---------------------------------------------------------------%
c
if( wantt ) then
i1 = 1
i2 = n
do 8 i=1,i2-2
h(i1+i+1,i) = zero
8 continue
else
do 9 i=1, ihi-ilo-1
h(ilo+i+1,ilo+i-1) = zero
9 continue
end if
c
c %---------------------------------------------------%
c | ITN is the total number of QR iterations allowed. |
c %---------------------------------------------------%
c
itn = 30*nh
c
c ------------------------------------------------------------------
c The main loop begins here. I is the loop index and decreases from
c IHI to ILO in steps of 1 or 2. Each iteration of the loop works
c with the active submatrix in rows and columns L to I.
c Eigenvalues I+1 to IHI have already converged. Either L = ILO or
c H(L,L-1) is negligible so that the matrix splits.
c ------------------------------------------------------------------
c
i = ihi
10 continue
l = ilo
if( i.lt.ilo )
& go to 150
c %--------------------------------------------------------------%
c | Perform QR iterations on rows and columns ILO to I until a |
c | submatrix of order 1 or 2 splits off at the bottom because a |
c | subdiagonal element has become negligible. |
c %--------------------------------------------------------------%
do 130 its = 0, itn
c
c %----------------------------------------------%
c | Look for a single small subdiagonal element. |
c %----------------------------------------------%
c
do 20 k = i, l + 1, -1
tst1 = abs( h( k-1, k-1 ) ) + abs( h( k, k ) )
if( tst1.eq.zero )
& tst1 = slanhs( '1', i-l+1, h( l, l ), ldh, work )
if( abs( h( k, k-1 ) ).le.max( ulp*tst1, smlnum ) )
& go to 30
20 continue
30 continue
l = k
if( l.gt.ilo ) then
c
c %------------------------%
c | H(L,L-1) is negligible |
c %------------------------%
c
h( l, l-1 ) = zero
end if
c
c %-------------------------------------------------------------%
c | Exit from loop if a submatrix of order 1 or 2 has split off |
c %-------------------------------------------------------------%
c
if( l.ge.i-1 )
& go to 140
c
c %---------------------------------------------------------%
c | Now the active submatrix is in rows and columns L to I. |
c | If eigenvalues only are being computed, only the active |
c | submatrix need be transformed. |
c %---------------------------------------------------------%
c
if( .not.wantt ) then
i1 = l
i2 = i
end if
c
if( its.eq.10 .or. its.eq.20 ) then
c
c %-------------------%
c | Exceptional shift |
c %-------------------%
c
s = abs( h( i, i-1 ) ) + abs( h( i-1, i-2 ) )
h44 = dat1*s
h33 = h44
h43h34 = dat2*s*s
c
else
c
c %-----------------------------------------%
c | Prepare to use Wilkinson's double shift |
c %-----------------------------------------%
c
h44 = h( i, i )
h33 = h( i-1, i-1 )
h43h34 = h( i, i-1 )*h( i-1, i )
end if
c
c %-----------------------------------------------------%
c | Look for two consecutive small subdiagonal elements |
c %-----------------------------------------------------%
c
do 40 m = i - 2, l, -1
c
c %---------------------------------------------------------%
c | Determine the effect of starting the double-shift QR |
c | iteration at row M, and see if this would make H(M,M-1) |
c | negligible. |
c %---------------------------------------------------------%
c
h11 = h( m, m )
h22 = h( m+1, m+1 )
h21 = h( m+1, m )
h12 = h( m, m+1 )
h44s = h44 - h11
h33s = h33 - h11
v1 = ( h33s*h44s-h43h34 ) / h21 + h12
v2 = h22 - h11 - h33s - h44s
v3 = h( m+2, m+1 )
s = abs( v1 ) + abs( v2 ) + abs( v3 )
v1 = v1 / s
v2 = v2 / s
v3 = v3 / s
v( 1 ) = v1
v( 2 ) = v2
v( 3 ) = v3
if( m.eq.l )
& go to 50
h00 = h( m-1, m-1 )
h10 = h( m, m-1 )
tst1 = abs( v1 )*( abs( h00 )+abs( h11 )+abs( h22 ) )
if( abs( h10 )*( abs( v2 )+abs( v3 ) ).le.ulp*tst1 )
& go to 50
40 continue
50 continue
c
c %----------------------%
c | Double-shift QR step |
c %----------------------%
c
do 120 k = m, i - 1
c
c ------------------------------------------------------------
c The first iteration of this loop determines a reflection G
c from the vector V and applies it from left and right to H,
c thus creating a nonzero bulge below the subdiagonal.
c
c Each subsequent iteration determines a reflection G to
c restore the Hessenberg form in the (K-1)th column, and thus
c chases the bulge one step toward the bottom of the active
c submatrix. NR is the order of G.
c ------------------------------------------------------------
c
nr = min( 3, i-k+1 )
if( k.gt.m )
& call scopy( nr, h( k, k-1 ), 1, v, 1 )
call slarfg( nr, v( 1 ), v( 2 ), 1, t1 )
if( k.gt.m ) then
h( k, k-1 ) = v( 1 )
h( k+1, k-1 ) = zero
if( k.lt.i-1 )
& h( k+2, k-1 ) = zero
else if( m.gt.l ) then
h( k, k-1 ) = -h( k, k-1 )
end if
v2 = v( 2 )
t2 = t1*v2
if( nr.eq.3 ) then
v3 = v( 3 )
t3 = t1*v3
c
c %------------------------------------------------%
c | Apply G from the left to transform the rows of |
c | the matrix in columns K to I2. |
c %------------------------------------------------%
c
do 60 j = k, i2
sum = h( k, j ) + v2*h( k+1, j ) + v3*h( k+2, j )
h( k, j ) = h( k, j ) - sum*t1
h( k+1, j ) = h( k+1, j ) - sum*t2
h( k+2, j ) = h( k+2, j ) - sum*t3
60 continue
c
c %----------------------------------------------------%
c | Apply G from the right to transform the columns of |
c | the matrix in rows I1 to min(K+3,I). |
c %----------------------------------------------------%
c
do 70 j = i1, min( k+3, i )
sum = h( j, k ) + v2*h( j, k+1 ) + v3*h( j, k+2 )
h( j, k ) = h( j, k ) - sum*t1
h( j, k+1 ) = h( j, k+1 ) - sum*t2
h( j, k+2 ) = h( j, k+2 ) - sum*t3
70 continue
c
c %----------------------------------%
c | Accumulate transformations for Z |
c %----------------------------------%
c
sum = z( k ) + v2*z( k+1 ) + v3*z( k+2 )
z( k ) = z( k ) - sum*t1
z( k+1 ) = z( k+1 ) - sum*t2
z( k+2 ) = z( k+2 ) - sum*t3
else if( nr.eq.2 ) then
c
c %------------------------------------------------%
c | Apply G from the left to transform the rows of |
c | the matrix in columns K to I2. |
c %------------------------------------------------%
c
do 90 j = k, i2
sum = h( k, j ) + v2*h( k+1, j )
h( k, j ) = h( k, j ) - sum*t1
h( k+1, j ) = h( k+1, j ) - sum*t2
90 continue
c
c %----------------------------------------------------%
c | Apply G from the right to transform the columns of |
c | the matrix in rows I1 to min(K+3,I). |
c %----------------------------------------------------%
c
do 100 j = i1, i
sum = h( j, k ) + v2*h( j, k+1 )
h( j, k ) = h( j, k ) - sum*t1
h( j, k+1 ) = h( j, k+1 ) - sum*t2
100 continue
c
c %----------------------------------%
c | Accumulate transformations for Z |
c %----------------------------------%
c
sum = z( k ) + v2*z( k+1 )
z( k ) = z( k ) - sum*t1
z( k+1 ) = z( k+1 ) - sum*t2
end if
120 continue
130 continue
c
c %-------------------------------------------------------%
c | Failure to converge in remaining number of iterations |
c %-------------------------------------------------------%
c
info = i
return
140 continue
if( l.eq.i ) then
c
c %------------------------------------------------------%
c | H(I,I-1) is negligible: one eigenvalue has converged |
c %------------------------------------------------------%
c
wr( i ) = h( i, i )
wi( i ) = zero
else if( l.eq.i-1 ) then
c
c %--------------------------------------------------------%
c | H(I-1,I-2) is negligible; |
c | a pair of eigenvalues have converged. |
c | |
c | Transform the 2-by-2 submatrix to standard Schur form, |
c | and compute and store the eigenvalues. |
c %--------------------------------------------------------%
c
call slanv2( h( i-1, i-1 ), h( i-1, i ), h( i, i-1 ),
& h( i, i ), wr( i-1 ), wi( i-1 ), wr( i ), wi( i ),
& cs, sn )
if( wantt ) then
c
c %-----------------------------------------------------%
c | Apply the transformation to the rest of H and to Z, |
c | as required. |
c %-----------------------------------------------------%
c
if( i2.gt.i )
& call srot( i2-i, h( i-1, i+1 ), ldh, h( i, i+1 ), ldh,
& cs, sn )
call srot( i-i1-1, h( i1, i-1 ), 1, h( i1, i ), 1, cs, sn )
sum = cs*z( i-1 ) + sn*z( i )
z( i ) = cs*z( i ) - sn*z( i-1 )
z( i-1 ) = sum
end if
end if
c
c %---------------------------------------------------------%
c | Decrement number of remaining iterations, and return to |
c | start of the main loop with new value of I. |
c %---------------------------------------------------------%
c
itn = itn - its
i = l - 1
go to 10
150 continue
return
c
c %---------------%
c | End of slaqrb |
c %---------------%
c
end

840
arpack/ARPACK/SRC/snaitr.f Normal file
View File

@@ -0,0 +1,840 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: snaitr
c
c\Description:
c Reverse communication interface for applying NP additional steps to
c a K step nonsymmetric Arnoldi factorization.
c
c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T
c
c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0.
c
c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T
c
c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0.
c
c where OP and B are as in snaupd. The B-norm of r_{k+p} is also
c computed and returned.
c
c\Usage:
c call snaitr
c ( IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH,
c IPNTR, WORKD, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag.
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c This is for the restart phase to force the new
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y,
c IPNTR(3) is the pointer into WORK for B * X.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c IDO = 99: done
c -------------------------------------------------------------
c When the routine is used in the "shift-and-invert" mode, the
c vector B * Q is already available and do not need to be
c recompute in forming OP * Q.
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B that defines the
c semi-inner product for the operator OP. See snaupd.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c K Integer. (INPUT)
c Current size of V and H.
c
c NP Integer. (INPUT)
c Number of additional Arnoldi steps to take.
c
c NB Integer. (INPUT)
c Blocksize to be used in the recurrence.
c Only work for NB = 1 right now. The goal is to have a
c program that implement both the block and non-block method.
c
c RESID Real array of length N. (INPUT/OUTPUT)
c On INPUT: RESID contains the residual vector r_{k}.
c On OUTPUT: RESID contains the residual vector r_{k+p}.
c
c RNORM Real scalar. (INPUT/OUTPUT)
c B-norm of the starting residual on input.
c B-norm of the updated residual r_{k+p} on output.
c
c V Real N by K+NP array. (INPUT/OUTPUT)
c On INPUT: V contains the Arnoldi vectors in the first K
c columns.
c On OUTPUT: V contains the new NP Arnoldi vectors in the next
c NP columns. The first K columns are unchanged.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Real (K+NP) by (K+NP) array. (INPUT/OUTPUT)
c H is used to store the generated upper Hessenberg matrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORK for
c vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in the
c shift-and-invert mode. X is the current operand.
c -------------------------------------------------------------
c
c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The calling program should not
c use WORKD as temporary workspace during the iteration !!!!!!
c On input, WORKD(1:N) = B*RESID and is used to save some
c computation at the first step.
c
c INFO Integer. (OUTPUT)
c = 0: Normal exit.
c > 0: Size of the spanning invariant subspace of OP found.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c sgetv0 ARPACK routine to generate the initial vector.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c smout ARPACK utility routine that prints matrices
c svout ARPACK utility routine that prints vectors.
c slabad LAPACK routine that computes machine constants.
c slamch LAPACK routine that determines machine constants.
c slascl LAPACK routine for careful scaling of a matrix.
c slanhs LAPACK routine that computes various norms of a matrix.
c sgemv Level 2 BLAS routine for matrix vector multiplication.
c saxpy Level 1 BLAS that computes a vector triad.
c sscal Level 1 BLAS that scales a vector.
c scopy Level 1 BLAS that copies one vector to another .
c sdot Level 1 BLAS that computes the scalar product of two vectors.
c snrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: naitr.F SID: 2.4 DATE OF SID: 8/27/96 RELEASE: 2
c
c\Remarks
c The algorithm implemented is:
c
c restart = .false.
c Given V_{k} = [v_{1}, ..., v_{k}], r_{k};
c r_{k} contains the initial residual vector even for k = 0;
c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already
c computed by the calling program.
c
c betaj = rnorm ; p_{k+1} = B*r_{k} ;
c For j = k+1, ..., k+np Do
c 1) if ( betaj < tol ) stop or restart depending on j.
c ( At present tol is zero )
c if ( restart ) generate a new starting vector.
c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}];
c p_{j} = p_{j}/betaj
c 3) r_{j} = OP*v_{j} where OP is defined as in snaupd
c For shift-invert mode p_{j} = B*v_{j} is already available.
c wnorm = || OP*v_{j} ||
c 4) Compute the j-th step residual vector.
c w_{j} = V_{j}^T * B * OP * v_{j}
c r_{j} = OP*v_{j} - V_{j} * w_{j}
c H(:,j) = w_{j};
c H(j,j-1) = rnorm
c rnorm = || r_(j) ||
c If (rnorm > 0.717*wnorm) accept step and go back to 1)
c 5) Re-orthogonalization step:
c s = V_{j}'*B*r_{j}
c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} ||
c alphaj = alphaj + s_{j};
c 6) Iterative refinement step:
c If (rnorm1 > 0.717*rnorm) then
c rnorm = rnorm1
c accept step and go back to 1)
c Else
c rnorm = rnorm1
c If this is the first time in step 6), go to 5)
c Else r_{j} lies in the span of V_{j} numerically.
c Set r_{j} = 0 and rnorm = 0; go to 1)
c EndIf
c End Do
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine snaitr
& (ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh,
& ipntr, workd, info)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1
integer ido, info, k, ldh, ldv, n, nb, np
Real
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Real
& h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0, zero = 0.0E+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
logical first, orth1, orth2, rstart, step3, step4
integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl,
& jj
Real
& betaj, ovfl, temp1, rnorm1, smlnum, tst1, ulp, unfl,
& wnorm
save first, orth1, orth2, rstart, step3, step4,
& ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl,
& betaj, rnorm1, smlnum, ulp, unfl, wnorm
c
c %-----------------------%
c | Local Array Arguments |
c %-----------------------%
c
Real
& xtemp(2)
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external saxpy, scopy, sscal, sgemv, sgetv0, slabad,
& svout, smout, ivout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& sdot, snrm2, slanhs, slamch
external sdot, snrm2, slanhs, slamch
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic abs, sqrt
c
c %-----------------%
c | Data statements |
c %-----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
c
c %-----------------------------------------%
c | Set machine-dependent constants for the |
c | the splitting and deflation criterion. |
c | If norm(H) <= sqrt(OVFL), |
c | overflow should not occur. |
c | REFERENCE: LAPACK subroutine slahqr |
c %-----------------------------------------%
c
unfl = slamch( 'safe minimum' )
ovfl = one / unfl
call slabad( unfl, ovfl )
ulp = slamch( 'precision' )
smlnum = unfl*( n / ulp )
first = .false.
end if
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mnaitr
c
c %------------------------------%
c | Initial call to this routine |
c %------------------------------%
c
info = 0
step3 = .false.
step4 = .false.
rstart = .false.
orth1 = .false.
orth2 = .false.
j = k + 1
ipj = 1
irj = ipj + n
ivj = irj + n
end if
c
c %-------------------------------------------------%
c | When in reverse communication mode one of: |
c | STEP3, STEP4, ORTH1, ORTH2, RSTART |
c | will be .true. when .... |
c | STEP3: return from computing OP*v_{j}. |
c | STEP4: return from computing B-norm of OP*v_{j} |
c | ORTH1: return from computing B-norm of r_{j+1} |
c | ORTH2: return from computing B-norm of |
c | correction to the residual vector. |
c | RSTART: return from OP computations needed by |
c | sgetv0. |
c %-------------------------------------------------%
c
if (step3) go to 50
if (step4) go to 60
if (orth1) go to 70
if (orth2) go to 90
if (rstart) go to 30
c
c %-----------------------------%
c | Else this is the first step |
c %-----------------------------%
c
c %--------------------------------------------------------------%
c | |
c | A R N O L D I I T E R A T I O N L O O P |
c | |
c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) |
c %--------------------------------------------------------------%
1000 continue
c
if (msglvl .gt. 1) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: generating Arnoldi vector number')
call svout (logfil, 1, rnorm, ndigit,
& '_naitr: B-norm of the current residual is')
end if
c
c %---------------------------------------------------%
c | STEP 1: Check if the B norm of j-th residual |
c | vector is zero. Equivalent to determing whether |
c | an exact j-step Arnoldi factorization is present. |
c %---------------------------------------------------%
c
betaj = rnorm
if (rnorm .gt. zero) go to 40
c
c %---------------------------------------------------%
c | Invariant subspace found, generate a new starting |
c | vector which is orthogonal to the current Arnoldi |
c | basis and continue the iteration. |
c %---------------------------------------------------%
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: ****** RESTART AT STEP ******')
end if
c
c %---------------------------------------------%
c | ITRY is the loop variable that controls the |
c | maximum amount of times that a restart is |
c | attempted. NRSTRT is used by stat.h |
c %---------------------------------------------%
c
betaj = zero
nrstrt = nrstrt + 1
itry = 1
20 continue
rstart = .true.
ido = 0
30 continue
c
c %--------------------------------------%
c | If in reverse communication mode and |
c | RSTART = .true. flow returns here. |
c %--------------------------------------%
c
call sgetv0 (ido, bmat, itry, .false., n, j, v, ldv,
& resid, rnorm, ipntr, workd, ierr)
if (ido .ne. 99) go to 9000
if (ierr .lt. 0) then
itry = itry + 1
if (itry .le. 3) go to 20
c
c %------------------------------------------------%
c | Give up after several restart attempts. |
c | Set INFO to the size of the invariant subspace |
c | which spans OP and exit. |
c %------------------------------------------------%
c
info = j - 1
call second (t1)
tnaitr = tnaitr + (t1 - t0)
ido = 99
go to 9000
end if
c
40 continue
c
c %---------------------------------------------------------%
c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm |
c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow |
c | when reciprocating a small RNORM, test against lower |
c | machine bound. |
c %---------------------------------------------------------%
c
call scopy (n, resid, 1, v(1,j), 1)
if (rnorm .ge. unfl) then
temp1 = one / rnorm
call sscal (n, temp1, v(1,j), 1)
call sscal (n, temp1, workd(ipj), 1)
else
c
c %-----------------------------------------%
c | To scale both v_{j} and p_{j} carefully |
c | use LAPACK routine SLASCL |
c %-----------------------------------------%
c
call slascl ('General', i, i, rnorm, one, n, 1,
& v(1,j), n, infol)
call slascl ('General', i, i, rnorm, one, n, 1,
& workd(ipj), n, infol)
end if
c
c %------------------------------------------------------%
c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} |
c | Note that this is not quite yet r_{j}. See STEP 4 |
c %------------------------------------------------------%
c
step3 = .true.
nopx = nopx + 1
call second (t2)
call scopy (n, v(1,j), 1, workd(ivj), 1)
ipntr(1) = ivj
ipntr(2) = irj
ipntr(3) = ipj
ido = 1
c
c %-----------------------------------%
c | Exit in order to compute OP*v_{j} |
c %-----------------------------------%
c
go to 9000
50 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} |
c | if step3 = .true. |
c %----------------------------------%
c
call second (t3)
tmvopx = tmvopx + (t3 - t2)
step3 = .false.
c
c %------------------------------------------%
c | Put another copy of OP*v_{j} into RESID. |
c %------------------------------------------%
c
call scopy (n, workd(irj), 1, resid, 1)
c
c %---------------------------------------%
c | STEP 4: Finish extending the Arnoldi |
c | factorization to length j. |
c %---------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
step4 = .true.
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-------------------------------------%
c | Exit in order to compute B*OP*v_{j} |
c %-------------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call scopy (n, resid, 1, workd(ipj), 1)
end if
60 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} |
c | if step4 = .true. |
c %----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
step4 = .false.
c
c %-------------------------------------%
c | The following is needed for STEP 5. |
c | Compute the B-norm of OP*v_{j}. |
c %-------------------------------------%
c
if (bmat .eq. 'G') then
wnorm = sdot (n, resid, 1, workd(ipj), 1)
wnorm = sqrt(abs(wnorm))
else if (bmat .eq. 'I') then
wnorm = snrm2(n, resid, 1)
end if
c
c %-----------------------------------------%
c | Compute the j-th residual corresponding |
c | to the j step factorization. |
c | Use Classical Gram Schmidt and compute: |
c | w_{j} <- V_{j}^T * B * OP * v_{j} |
c | r_{j} <- OP*v_{j} - V_{j} * w_{j} |
c %-----------------------------------------%
c
c
c %------------------------------------------%
c | Compute the j Fourier coefficients w_{j} |
c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. |
c %------------------------------------------%
c
call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1,
& zero, h(1,j), 1)
c
c %--------------------------------------%
c | Orthogonalize r_{j} against V_{j}. |
c | RESID contains OP*v_{j}. See STEP 3. |
c %--------------------------------------%
c
call sgemv ('N', n, j, -one, v, ldv, h(1,j), 1,
& one, resid, 1)
c
if (j .gt. 1) h(j,j-1) = betaj
c
call second (t4)
c
orth1 = .true.
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call scopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*r_{j} |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call scopy (n, resid, 1, workd(ipj), 1)
end if
70 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH1 = .true. |
c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
orth1 = .false.
c
c %------------------------------%
c | Compute the B-norm of r_{j}. |
c %------------------------------%
c
if (bmat .eq. 'G') then
rnorm = sdot (n, resid, 1, workd(ipj), 1)
rnorm = sqrt(abs(rnorm))
else if (bmat .eq. 'I') then
rnorm = snrm2(n, resid, 1)
end if
c
c %-----------------------------------------------------------%
c | STEP 5: Re-orthogonalization / Iterative refinement phase |
c | Maximum NITER_ITREF tries. |
c | |
c | s = V_{j}^T * B * r_{j} |
c | r_{j} = r_{j} - V_{j}*s |
c | alphaj = alphaj + s_{j} |
c | |
c | The stopping criteria used for iterative refinement is |
c | discussed in Parlett's book SEP, page 107 and in Gragg & |
c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. |
c | Determine if we need to correct the residual. The goal is |
c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || |
c | The following test determines whether the sine of the |
c | angle between OP*x and the computed residual is less |
c | than or equal to 0.717. |
c %-----------------------------------------------------------%
c
if (rnorm .gt. 0.717*wnorm) go to 100
iter = 0
nrorth = nrorth + 1
c
c %---------------------------------------------------%
c | Enter the Iterative refinement phase. If further |
c | refinement is necessary, loop back here. The loop |
c | variable is ITER. Perform a step of Classical |
c | Gram-Schmidt using all the Arnoldi vectors V_{j} |
c %---------------------------------------------------%
c
80 continue
c
if (msglvl .gt. 2) then
xtemp(1) = wnorm
xtemp(2) = rnorm
call svout (logfil, 2, xtemp, ndigit,
& '_naitr: re-orthonalization; wnorm and rnorm are')
call svout (logfil, j, h(1,j), ndigit,
& '_naitr: j-th column of H')
end if
c
c %----------------------------------------------------%
c | Compute V_{j}^T * B * r_{j}. |
c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). |
c %----------------------------------------------------%
c
call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1,
& zero, workd(irj), 1)
c
c %---------------------------------------------%
c | Compute the correction to the residual: |
c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). |
c | The correction to H is v(:,1:J)*H(1:J,1:J) |
c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. |
c %---------------------------------------------%
c
call sgemv ('N', n, j, -one, v, ldv, workd(irj), 1,
& one, resid, 1)
call saxpy (j, one, workd(irj), 1, h(1,j), 1)
c
orth2 = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call scopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-----------------------------------%
c | Exit in order to compute B*r_{j}. |
c | r_{j} is the corrected residual. |
c %-----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call scopy (n, resid, 1, workd(ipj), 1)
end if
90 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH2 = .true. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
c %-----------------------------------------------------%
c | Compute the B-norm of the corrected residual r_{j}. |
c %-----------------------------------------------------%
c
if (bmat .eq. 'G') then
rnorm1 = sdot (n, resid, 1, workd(ipj), 1)
rnorm1 = sqrt(abs(rnorm1))
else if (bmat .eq. 'I') then
rnorm1 = snrm2(n, resid, 1)
end if
c
if (msglvl .gt. 0 .and. iter .gt. 0) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: Iterative refinement for Arnoldi residual')
if (msglvl .gt. 2) then
xtemp(1) = rnorm
xtemp(2) = rnorm1
call svout (logfil, 2, xtemp, ndigit,
& '_naitr: iterative refinement ; rnorm and rnorm1 are')
end if
end if
c
c %-----------------------------------------%
c | Determine if we need to perform another |
c | step of re-orthogonalization. |
c %-----------------------------------------%
c
if (rnorm1 .gt. 0.717*rnorm) then
c
c %---------------------------------------%
c | No need for further refinement. |
c | The cosine of the angle between the |
c | corrected residual vector and the old |
c | residual vector is greater than 0.717 |
c | In other words the corrected residual |
c | and the old residual vector share an |
c | angle of less than arcCOS(0.717) |
c %---------------------------------------%
c
rnorm = rnorm1
c
else
c
c %-------------------------------------------%
c | Another step of iterative refinement step |
c | is required. NITREF is used by stat.h |
c %-------------------------------------------%
c
nitref = nitref + 1
rnorm = rnorm1
iter = iter + 1
if (iter .le. 1) go to 80
c
c %-------------------------------------------------%
c | Otherwise RESID is numerically in the span of V |
c %-------------------------------------------------%
c
do 95 jj = 1, n
resid(jj) = zero
95 continue
rnorm = zero
end if
c
c %----------------------------------------------%
c | Branch here directly if iterative refinement |
c | wasn't necessary or after at most NITER_REF |
c | steps of iterative refinement. |
c %----------------------------------------------%
c
100 continue
c
rstart = .false.
orth2 = .false.
c
call second (t5)
titref = titref + (t5 - t4)
c
c %------------------------------------%
c | STEP 6: Update j = j+1; Continue |
c %------------------------------------%
c
j = j + 1
if (j .gt. k+np) then
call second (t1)
tnaitr = tnaitr + (t1 - t0)
ido = 99
do 110 i = max(1,k), k+np-1
c
c %--------------------------------------------%
c | Check for splitting and deflation. |
c | Use a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine slahqr |
c %--------------------------------------------%
c
tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) )
if( tst1.eq.zero )
& tst1 = slanhs( '1', k+np, h, ldh, workd(n+1) )
if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) )
& h(i+1,i) = zero
110 continue
c
if (msglvl .gt. 2) then
call smout (logfil, k+np, k+np, h, ldh, ndigit,
& '_naitr: Final upper Hessenberg matrix H of order K+NP')
end if
c
go to 9000
end if
c
c %--------------------------------------------------------%
c | Loop back to extend the factorization by another step. |
c %--------------------------------------------------------%
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
9000 continue
return
c
c %---------------%
c | End of snaitr |
c %---------------%
c
end

647
arpack/ARPACK/SRC/snapps.f Normal file
View File

@@ -0,0 +1,647 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: snapps
c
c\Description:
c Given the Arnoldi factorization
c
c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T,
c
c apply NP implicit shifts resulting in
c
c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q
c
c where Q is an orthogonal matrix which is the product of rotations
c and reflections resulting from the NP bulge chage sweeps.
c The updated Arnoldi factorization becomes:
c
c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T.
c
c\Usage:
c call snapps
c ( N, KEV, NP, SHIFTR, SHIFTI, V, LDV, H, LDH, RESID, Q, LDQ,
c WORKL, WORKD )
c
c\Arguments
c N Integer. (INPUT)
c Problem size, i.e. size of matrix A.
c
c KEV Integer. (INPUT/OUTPUT)
c KEV+NP is the size of the input matrix H.
c KEV is the size of the updated matrix HNEW. KEV is only
c updated on ouput when fewer than NP shifts are applied in
c order to keep the conjugate pair together.
c
c NP Integer. (INPUT)
c Number of implicit shifts to be applied.
c
c SHIFTR, Real array of length NP. (INPUT)
c SHIFTI Real and imaginary part of the shifts to be applied.
c Upon, entry to snapps, the shifts must be sorted so that the
c conjugate pairs are in consecutive locations.
c
c V Real N by (KEV+NP) array. (INPUT/OUTPUT)
c On INPUT, V contains the current KEV+NP Arnoldi vectors.
c On OUTPUT, V contains the updated KEV Arnoldi vectors
c in the first KEV columns of V.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Real (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT)
c On INPUT, H contains the current KEV+NP by KEV+NP upper
c Hessenber matrix of the Arnoldi factorization.
c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg
c matrix in the KEV leading submatrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RESID Real array of length N. (INPUT/OUTPUT)
c On INPUT, RESID contains the the residual vector r_{k+p}.
c On OUTPUT, RESID is the update residual vector rnew_{k}
c in the first KEV locations.
c
c Q Real KEV+NP by KEV+NP work array. (WORKSPACE)
c Work array used to accumulate the rotations and reflections
c during the bulge chase sweep.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Real work array of length (KEV+NP). (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c WORKD Real work array of length 2*N. (WORKSPACE)
c Distributed array used in the application of the accumulated
c orthogonal matrix Q.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c
c\Routines called:
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c smout ARPACK utility routine that prints matrices.
c svout ARPACK utility routine that prints vectors.
c slabad LAPACK routine that computes machine constants.
c slacpy LAPACK matrix copy routine.
c slamch LAPACK routine that determines machine constants.
c slanhs LAPACK routine that computes various norms of a matrix.
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c slarf LAPACK routine that applies Householder reflection to
c a matrix.
c slarfg LAPACK Householder reflection construction routine.
c slartg LAPACK Givens rotation construction routine.
c slaset LAPACK matrix initialization routine.
c sgemv Level 2 BLAS routine for matrix vector multiplication.
c saxpy Level 1 BLAS that computes a vector triad.
c scopy Level 1 BLAS that copies one vector to another .
c sscal Level 1 BLAS that scales a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: napps.F SID: 2.4 DATE OF SID: 3/28/97 RELEASE: 2
c
c\Remarks
c 1. In this version, each shift is applied to all the sublocks of
c the Hessenberg matrix H and not just to the submatrix that it
c comes from. Deflation as in LAPACK routine slahqr (QR algorithm
c for upper Hessenberg matrices ) is used.
c The subdiagonals of H are enforced to be non-negative.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine snapps
& ( n, kev, np, shiftr, shifti, v, ldv, h, ldh, resid, q, ldq,
& workl, workd )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer kev, ldh, ldq, ldv, n, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& h(ldh,kev+np), resid(n), shifti(np), shiftr(np),
& v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0, zero = 0.0E+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
integer i, iend, ir, istart, j, jj, kplusp, msglvl, nr
logical cconj, first
Real
& c, f, g, h11, h12, h21, h22, h32, ovfl, r, s, sigmai,
& sigmar, smlnum, ulp, unfl, u(3), t, tau, tst1
save first, ovfl, smlnum, ulp, unfl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external saxpy, scopy, sscal, slacpy, slarfg, slarf,
& slaset, slabad, second, slartg
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& slamch, slanhs, slapy2
external slamch, slanhs, slapy2
c
c %----------------------%
c | Intrinsics Functions |
c %----------------------%
c
intrinsic abs, max, min
c
c %----------------%
c | Data statments |
c %----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
c
c %-----------------------------------------------%
c | Set machine-dependent constants for the |
c | stopping criterion. If norm(H) <= sqrt(OVFL), |
c | overflow should not occur. |
c | REFERENCE: LAPACK subroutine slahqr |
c %-----------------------------------------------%
c
unfl = slamch( 'safe minimum' )
ovfl = one / unfl
call slabad( unfl, ovfl )
ulp = slamch( 'precision' )
smlnum = unfl*( n / ulp )
first = .false.
end if
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mnapps
kplusp = kev + np
c
c %--------------------------------------------%
c | Initialize Q to the identity to accumulate |
c | the rotations and reflections |
c %--------------------------------------------%
c
call slaset ('All', kplusp, kplusp, zero, one, q, ldq)
c
c %----------------------------------------------%
c | Quick return if there are no shifts to apply |
c %----------------------------------------------%
c
if (np .eq. 0) go to 9000
c
c %----------------------------------------------%
c | Chase the bulge with the application of each |
c | implicit shift. Each shift is applied to the |
c | whole matrix including each block. |
c %----------------------------------------------%
c
cconj = .false.
do 110 jj = 1, np
sigmar = shiftr(jj)
sigmai = shifti(jj)
c
if (msglvl .gt. 2 ) then
call ivout (logfil, 1, jj, ndigit,
& '_napps: shift number.')
call svout (logfil, 1, sigmar, ndigit,
& '_napps: The real part of the shift ')
call svout (logfil, 1, sigmai, ndigit,
& '_napps: The imaginary part of the shift ')
end if
c
c %-------------------------------------------------%
c | The following set of conditionals is necessary |
c | in order that complex conjugate pairs of shifts |
c | are applied together or not at all. |
c %-------------------------------------------------%
c
if ( cconj ) then
c
c %-----------------------------------------%
c | cconj = .true. means the previous shift |
c | had non-zero imaginary part. |
c %-----------------------------------------%
c
cconj = .false.
go to 110
else if ( jj .lt. np .and. abs( sigmai ) .gt. zero ) then
c
c %------------------------------------%
c | Start of a complex conjugate pair. |
c %------------------------------------%
c
cconj = .true.
else if ( jj .eq. np .and. abs( sigmai ) .gt. zero ) then
c
c %----------------------------------------------%
c | The last shift has a nonzero imaginary part. |
c | Don't apply it; thus the order of the |
c | compressed H is order KEV+1 since only np-1 |
c | were applied. |
c %----------------------------------------------%
c
kev = kev + 1
go to 110
end if
istart = 1
20 continue
c
c %--------------------------------------------------%
c | if sigmai = 0 then |
c | Apply the jj-th shift ... |
c | else |
c | Apply the jj-th and (jj+1)-th together ... |
c | (Note that jj < np at this point in the code) |
c | end |
c | to the current block of H. The next do loop |
c | determines the current block ; |
c %--------------------------------------------------%
c
do 30 i = istart, kplusp-1
c
c %----------------------------------------%
c | Check for splitting and deflation. Use |
c | a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine slahqr |
c %----------------------------------------%
c
tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) )
if( tst1.eq.zero )
& tst1 = slanhs( '1', kplusp-jj+1, h, ldh, workl )
if( abs( h( i+1,i ) ).le.max( ulp*tst1, smlnum ) ) then
if (msglvl .gt. 0) then
call ivout (logfil, 1, i, ndigit,
& '_napps: matrix splitting at row/column no.')
call ivout (logfil, 1, jj, ndigit,
& '_napps: matrix splitting with shift number.')
call svout (logfil, 1, h(i+1,i), ndigit,
& '_napps: off diagonal element.')
end if
iend = i
h(i+1,i) = zero
go to 40
end if
30 continue
iend = kplusp
40 continue
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, istart, ndigit,
& '_napps: Start of current block ')
call ivout (logfil, 1, iend, ndigit,
& '_napps: End of current block ')
end if
c
c %------------------------------------------------%
c | No reason to apply a shift to block of order 1 |
c %------------------------------------------------%
c
if ( istart .eq. iend ) go to 100
c
c %------------------------------------------------------%
c | If istart + 1 = iend then no reason to apply a |
c | complex conjugate pair of shifts on a 2 by 2 matrix. |
c %------------------------------------------------------%
c
if ( istart + 1 .eq. iend .and. abs( sigmai ) .gt. zero )
& go to 100
c
h11 = h(istart,istart)
h21 = h(istart+1,istart)
if ( abs( sigmai ) .le. zero ) then
c
c %---------------------------------------------%
c | Real-valued shift ==> apply single shift QR |
c %---------------------------------------------%
c
f = h11 - sigmar
g = h21
c
do 80 i = istart, iend-1
c
c %-----------------------------------------------------%
c | Contruct the plane rotation G to zero out the bulge |
c %-----------------------------------------------------%
c
call slartg (f, g, c, s, r)
if (i .gt. istart) then
c
c %-------------------------------------------%
c | The following ensures that h(1:iend-1,1), |
c | the first iend-2 off diagonal of elements |
c | H, remain non negative. |
c %-------------------------------------------%
c
if (r .lt. zero) then
r = -r
c = -c
s = -s
end if
h(i,i-1) = r
h(i+1,i-1) = zero
end if
c
c %---------------------------------------------%
c | Apply rotation to the left of H; H <- G'*H |
c %---------------------------------------------%
c
do 50 j = i, kplusp
t = c*h(i,j) + s*h(i+1,j)
h(i+1,j) = -s*h(i,j) + c*h(i+1,j)
h(i,j) = t
50 continue
c
c %---------------------------------------------%
c | Apply rotation to the right of H; H <- H*G |
c %---------------------------------------------%
c
do 60 j = 1, min(i+2,iend)
t = c*h(j,i) + s*h(j,i+1)
h(j,i+1) = -s*h(j,i) + c*h(j,i+1)
h(j,i) = t
60 continue
c
c %----------------------------------------------------%
c | Accumulate the rotation in the matrix Q; Q <- Q*G |
c %----------------------------------------------------%
c
do 70 j = 1, min( i+jj, kplusp )
t = c*q(j,i) + s*q(j,i+1)
q(j,i+1) = - s*q(j,i) + c*q(j,i+1)
q(j,i) = t
70 continue
c
c %---------------------------%
c | Prepare for next rotation |
c %---------------------------%
c
if (i .lt. iend-1) then
f = h(i+1,i)
g = h(i+2,i)
end if
80 continue
c
c %-----------------------------------%
c | Finished applying the real shift. |
c %-----------------------------------%
c
else
c
c %----------------------------------------------------%
c | Complex conjugate shifts ==> apply double shift QR |
c %----------------------------------------------------%
c
h12 = h(istart,istart+1)
h22 = h(istart+1,istart+1)
h32 = h(istart+2,istart+1)
c
c %---------------------------------------------------------%
c | Compute 1st column of (H - shift*I)*(H - conj(shift)*I) |
c %---------------------------------------------------------%
c
s = 2.0*sigmar
t = slapy2 ( sigmar, sigmai )
u(1) = ( h11 * (h11 - s) + t * t ) / h21 + h12
u(2) = h11 + h22 - s
u(3) = h32
c
do 90 i = istart, iend-1
c
nr = min ( 3, iend-i+1 )
c
c %-----------------------------------------------------%
c | Construct Householder reflector G to zero out u(1). |
c | G is of the form I - tau*( 1 u )' * ( 1 u' ). |
c %-----------------------------------------------------%
c
call slarfg ( nr, u(1), u(2), 1, tau )
c
if (i .gt. istart) then
h(i,i-1) = u(1)
h(i+1,i-1) = zero
if (i .lt. iend-1) h(i+2,i-1) = zero
end if
u(1) = one
c
c %--------------------------------------%
c | Apply the reflector to the left of H |
c %--------------------------------------%
c
call slarf ('Left', nr, kplusp-i+1, u, 1, tau,
& h(i,i), ldh, workl)
c
c %---------------------------------------%
c | Apply the reflector to the right of H |
c %---------------------------------------%
c
ir = min ( i+3, iend )
call slarf ('Right', ir, nr, u, 1, tau,
& h(1,i), ldh, workl)
c
c %-----------------------------------------------------%
c | Accumulate the reflector in the matrix Q; Q <- Q*G |
c %-----------------------------------------------------%
c
call slarf ('Right', kplusp, nr, u, 1, tau,
& q(1,i), ldq, workl)
c
c %----------------------------%
c | Prepare for next reflector |
c %----------------------------%
c
if (i .lt. iend-1) then
u(1) = h(i+1,i)
u(2) = h(i+2,i)
if (i .lt. iend-2) u(3) = h(i+3,i)
end if
c
90 continue
c
c %--------------------------------------------%
c | Finished applying a complex pair of shifts |
c | to the current block |
c %--------------------------------------------%
c
end if
c
100 continue
c
c %---------------------------------------------------------%
c | Apply the same shift to the next block if there is any. |
c %---------------------------------------------------------%
c
istart = iend + 1
if (iend .lt. kplusp) go to 20
c
c %---------------------------------------------%
c | Loop back to the top to get the next shift. |
c %---------------------------------------------%
c
110 continue
c
c %--------------------------------------------------%
c | Perform a similarity transformation that makes |
c | sure that H will have non negative sub diagonals |
c %--------------------------------------------------%
c
do 120 j=1,kev
if ( h(j+1,j) .lt. zero ) then
call sscal( kplusp-j+1, -one, h(j+1,j), ldh )
call sscal( min(j+2, kplusp), -one, h(1,j+1), 1 )
call sscal( min(j+np+1,kplusp), -one, q(1,j+1), 1 )
end if
120 continue
c
do 130 i = 1, kev
c
c %--------------------------------------------%
c | Final check for splitting and deflation. |
c | Use a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine slahqr |
c %--------------------------------------------%
c
tst1 = abs( h( i, i ) ) + abs( h( i+1, i+1 ) )
if( tst1.eq.zero )
& tst1 = slanhs( '1', kev, h, ldh, workl )
if( h( i+1,i ) .le. max( ulp*tst1, smlnum ) )
& h(i+1,i) = zero
130 continue
c
c %-------------------------------------------------%
c | Compute the (kev+1)-st column of (V*Q) and |
c | temporarily store the result in WORKD(N+1:2*N). |
c | This is needed in the residual update since we |
c | cannot GUARANTEE that the corresponding entry |
c | of H would be zero as in exact arithmetic. |
c %-------------------------------------------------%
c
if (h(kev+1,kev) .gt. zero)
& call sgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero,
& workd(n+1), 1)
c
c %----------------------------------------------------------%
c | Compute column 1 to kev of (V*Q) in backward order |
c | taking advantage of the upper Hessenberg structure of Q. |
c %----------------------------------------------------------%
c
do 140 i = 1, kev
call sgemv ('N', n, kplusp-i+1, one, v, ldv,
& q(1,kev-i+1), 1, zero, workd, 1)
call scopy (n, workd, 1, v(1,kplusp-i+1), 1)
140 continue
c
c %-------------------------------------------------%
c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). |
c %-------------------------------------------------%
c
call slacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv)
c
c %--------------------------------------------------------------%
c | Copy the (kev+1)-st column of (V*Q) in the appropriate place |
c %--------------------------------------------------------------%
c
if (h(kev+1,kev) .gt. zero)
& call scopy (n, workd(n+1), 1, v(1,kev+1), 1)
c
c %-------------------------------------%
c | Update the residual vector: |
c | r <- sigmak*r + betak*v(:,kev+1) |
c | where |
c | sigmak = (e_{kplusp}'*Q)*e_{kev} |
c | betak = e_{kev+1}'*H*e_{kev} |
c %-------------------------------------%
c
call sscal (n, q(kplusp,kev), resid, 1)
if (h(kev+1,kev) .gt. zero)
& call saxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1)
c
if (msglvl .gt. 1) then
call svout (logfil, 1, q(kplusp,kev), ndigit,
& '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}')
call svout (logfil, 1, h(kev+1,kev), ndigit,
& '_napps: betak = e_{kev+1}^T*H*e_{kev}')
call ivout (logfil, 1, kev, ndigit,
& '_napps: Order of the final Hessenberg matrix ')
if (msglvl .gt. 2) then
call smout (logfil, kev, kev, h, ldh, ndigit,
& '_napps: updated Hessenberg matrix H for next iteration')
end if
c
end if
c
9000 continue
call second (t1)
tnapps = tnapps + (t1 - t0)
c
return
c
c %---------------%
c | End of snapps |
c %---------------%
c
end

835
arpack/ARPACK/SRC/snaup2.f Normal file
View File

@@ -0,0 +1,835 @@
c\BeginDoc
c
c\Name: snaup2
c
c\Description:
c Intermediate level interface called by snaupd.
c
c\Usage:
c call snaup2
c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD,
c ISHIFT, MXITER, V, LDV, H, LDH, RITZR, RITZI, BOUNDS,
c Q, LDQ, WORKL, IPNTR, WORKD, INFO )
c
c\Arguments
c
c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in snaupd.
c MODE, ISHIFT, MXITER: see the definition of IPARAM in snaupd.
c
c NP Integer. (INPUT/OUTPUT)
c Contains the number of implicit shifts to apply during
c each Arnoldi iteration.
c If ISHIFT=1, NP is adjusted dynamically at each iteration
c to accelerate convergence and prevent stagnation.
c This is also roughly equal to the number of matrix-vector
c products (involving the operator OP) per Arnoldi iteration.
c The logic for adjusting is contained within the current
c subroutine.
c If ISHIFT=0, NP is the number of shifts the user needs
c to provide via reverse comunication. 0 < NP < NCV-NEV.
c NP may be less than NCV-NEV for two reasons. The first, is
c to keep complex conjugate pairs of "wanted" Ritz values
c together. The second, is that a leading block of the current
c upper Hessenberg matrix has split off and contains "unwanted"
c Ritz values.
c Upon termination of the IRA iteration, NP contains the number
c of "converged" wanted Ritz values.
c
c IUPD Integer. (INPUT)
c IUPD .EQ. 0: use explicit restart instead implicit update.
c IUPD .NE. 0: use implicit update.
c
c V Real N by (NEV+NP) array. (INPUT/OUTPUT)
c The Arnoldi basis vectors are returned in the first NEV
c columns of V.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Real (NEV+NP) by (NEV+NP) array. (OUTPUT)
c H is used to store the generated upper Hessenberg matrix
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RITZR, Real arrays of length NEV+NP. (OUTPUT)
c RITZI RITZR(1:NEV) (resp. RITZI(1:NEV)) contains the real (resp.
c imaginary) part of the computed Ritz values of OP.
c
c BOUNDS Real array of length NEV+NP. (OUTPUT)
c BOUNDS(1:NEV) contain the error bounds corresponding to
c the computed Ritz values.
c
c Q Real (NEV+NP) by (NEV+NP) array. (WORKSPACE)
c Private (replicated) work array used to accumulate the
c rotation in the shift application step.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Real work array of length at least
c (NEV+NP)**2 + 3*(NEV+NP). (INPUT/WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. It is used in shifts calculation, shifts
c application and convergence checking.
c
c On exit, the last 3*(NEV+NP) locations of WORKL contain
c the Ritz values (real,imaginary) and associated Ritz
c estimates of the current Hessenberg matrix. They are
c listed in the same order as returned from sneigh.
c
c If ISHIFT .EQ. O and IDO .EQ. 3, the first 2*NP locations
c of WORKL are used in reverse communication to hold the user
c supplied shifts.
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORKD for
c vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in the
c shift-and-invert mode. X is the current operand.
c -------------------------------------------------------------
c
c WORKD Real work array of length 3*N. (WORKSPACE)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration !!!!!!!!!!
c See Data Distribution Note in DNAUPD.
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal return.
c = 1: Maximum number of iterations taken.
c All possible eigenvalues of OP has been found.
c NP returns the number of converged Ritz values.
c = 2: No shifts could be applied.
c = -8: Error return from LAPACK eigenvalue calculation;
c This should never happen.
c = -9: Starting vector is zero.
c = -9999: Could not build an Arnoldi factorization.
c Size that was built in returned in NP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c sgetv0 ARPACK initial vector generation routine.
c snaitr ARPACK Arnoldi factorization routine.
c snapps ARPACK application of implicit shifts routine.
c snconv ARPACK convergence of Ritz values routine.
c sneigh ARPACK compute Ritz values and error bounds routine.
c sngets ARPACK reorder Ritz values and error bounds routine.
c ssortc ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c smout ARPACK utility routine that prints matrices
c svout ARPACK utility routine that prints vectors.
c slamch LAPACK routine that determines machine constants.
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c scopy Level 1 BLAS that copies one vector to another .
c sdot Level 1 BLAS that computes the scalar product of two vectors.
c snrm2 Level 1 BLAS that computes the norm of a vector.
c sswap Level 1 BLAS that swaps two vectors.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: naup2.F SID: 2.8 DATE OF SID: 10/17/00 RELEASE: 2
c
c\Remarks
c 1. None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine snaup2
& ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, h, ldh, ritzr, ritzi, bounds,
& q, ldq, workl, ipntr, workd, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter,
& n, nev, np
Real
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(13)
Real
& bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), resid(n),
& ritzi(nev+np), ritzr(nev+np), v(ldv,nev+np),
& workd(3*n), workl( (nev+np)*(nev+np+3) )
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0, zero = 0.0E+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
character wprime*2
logical cnorm , getv0, initv, update, ushift
integer ierr , iter , j , kplusp, msglvl, nconv,
& nevbef, nev0 , np0 , nptemp, numcnv
Real
& rnorm , temp , eps23
save cnorm , getv0, initv, update, ushift,
& rnorm , iter , eps23, kplusp, msglvl, nconv ,
& nevbef, nev0 , np0 , numcnv
c
c %-----------------------%
c | Local array arguments |
c %-----------------------%
c
integer kp(4)
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external scopy , sgetv0, snaitr, snconv, sneigh,
& sngets, snapps, svout , ivout , second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& sdot, snrm2, slapy2, slamch
external sdot, snrm2, slapy2, slamch
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic min, max, abs, sqrt
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
call second (t0)
c
msglvl = mnaup2
c
c %-------------------------------------%
c | Get the machine dependent constant. |
c %-------------------------------------%
c
eps23 = slamch('Epsilon-Machine')
eps23 = eps23**(2.0E+0 / 3.0E+0)
c
nev0 = nev
np0 = np
c
c %-------------------------------------%
c | kplusp is the bound on the largest |
c | Lanczos factorization built. |
c | nconv is the current number of |
c | "converged" eigenvlues. |
c | iter is the counter on the current |
c | iteration step. |
c %-------------------------------------%
c
kplusp = nev + np
nconv = 0
iter = 0
c
c %---------------------------------------%
c | Set flags for computing the first NEV |
c | steps of the Arnoldi factorization. |
c %---------------------------------------%
c
getv0 = .true.
update = .false.
ushift = .false.
cnorm = .false.
c
if (info .ne. 0) then
c
c %--------------------------------------------%
c | User provides the initial residual vector. |
c %--------------------------------------------%
c
initv = .true.
info = 0
else
initv = .false.
end if
end if
c
c %---------------------------------------------%
c | Get a possibly random starting vector and |
c | force it into the range of the operator OP. |
c %---------------------------------------------%
c
10 continue
c
if (getv0) then
call sgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm,
& ipntr, workd, info)
c
if (ido .ne. 99) go to 9000
c
if (rnorm .eq. zero) then
c
c %-----------------------------------------%
c | The initial vector is zero. Error exit. |
c %-----------------------------------------%
c
info = -9
go to 1100
end if
getv0 = .false.
ido = 0
end if
c
c %-----------------------------------%
c | Back from reverse communication : |
c | continue with update step |
c %-----------------------------------%
c
if (update) go to 20
c
c %-------------------------------------------%
c | Back from computing user specified shifts |
c %-------------------------------------------%
c
if (ushift) go to 50
c
c %-------------------------------------%
c | Back from computing residual norm |
c | at the end of the current iteration |
c %-------------------------------------%
c
if (cnorm) go to 100
c
c %----------------------------------------------------------%
c | Compute the first NEV steps of the Arnoldi factorization |
c %----------------------------------------------------------%
c
call snaitr (ido, bmat, n, 0, nev, mode, resid, rnorm, v, ldv,
& h, ldh, ipntr, workd, info)
c
c %---------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP and possibly B |
c %---------------------------------------------------%
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
np = info
mxiter = iter
info = -9999
go to 1200
end if
c
c %--------------------------------------------------------------%
c | |
c | M A I N ARNOLDI I T E R A T I O N L O O P |
c | Each iteration implicitly restarts the Arnoldi |
c | factorization in place. |
c | |
c %--------------------------------------------------------------%
c
1000 continue
c
iter = iter + 1
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, iter, ndigit,
& '_naup2: **** Start of major iteration number ****')
end if
c
c %-----------------------------------------------------------%
c | Compute NP additional steps of the Arnoldi factorization. |
c | Adjust NP since NEV might have been updated by last call |
c | to the shift application routine snapps. |
c %-----------------------------------------------------------%
c
np = kplusp - nev
c
if (msglvl .gt. 1) then
call ivout (logfil, 1, nev, ndigit,
& '_naup2: The length of the current Arnoldi factorization')
call ivout (logfil, 1, np, ndigit,
& '_naup2: Extend the Arnoldi factorization by')
end if
c
c %-----------------------------------------------------------%
c | Compute NP additional steps of the Arnoldi factorization. |
c %-----------------------------------------------------------%
c
ido = 0
20 continue
update = .true.
c
call snaitr (ido , bmat, n , nev, np , mode , resid,
& rnorm, v , ldv, h , ldh, ipntr, workd,
& info)
c
c %---------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP and possibly B |
c %---------------------------------------------------%
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
np = info
mxiter = iter
info = -9999
go to 1200
end if
update = .false.
c
if (msglvl .gt. 1) then
call svout (logfil, 1, rnorm, ndigit,
& '_naup2: Corresponding B-norm of the residual')
end if
c
c %--------------------------------------------------------%
c | Compute the eigenvalues and corresponding error bounds |
c | of the current upper Hessenberg matrix. |
c %--------------------------------------------------------%
c
call sneigh (rnorm, kplusp, h, ldh, ritzr, ritzi, bounds,
& q, ldq, workl, ierr)
c
if (ierr .ne. 0) then
info = -8
go to 1200
end if
c
c %----------------------------------------------------%
c | Make a copy of eigenvalues and corresponding error |
c | bounds obtained from sneigh. |
c %----------------------------------------------------%
c
call scopy(kplusp, ritzr, 1, workl(kplusp**2+1), 1)
call scopy(kplusp, ritzi, 1, workl(kplusp**2+kplusp+1), 1)
call scopy(kplusp, bounds, 1, workl(kplusp**2+2*kplusp+1), 1)
c
c %---------------------------------------------------%
c | Select the wanted Ritz values and their bounds |
c | to be used in the convergence test. |
c | The wanted part of the spectrum and corresponding |
c | error bounds are in the last NEV loc. of RITZR, |
c | RITZI and BOUNDS respectively. The variables NEV |
c | and NP may be updated if the NEV-th wanted Ritz |
c | value has a non zero imaginary part. In this case |
c | NEV is increased by one and NP decreased by one. |
c | NOTE: The last two arguments of sngets are no |
c | longer used as of version 2.1. |
c %---------------------------------------------------%
c
nev = nev0
np = np0
numcnv = nev
call sngets (ishift, which, nev, np, ritzr, ritzi,
& bounds, workl, workl(np+1))
if (nev .eq. nev0+1) numcnv = nev0+1
c
c %-------------------%
c | Convergence test. |
c %-------------------%
c
call scopy (nev, bounds(np+1), 1, workl(2*np+1), 1)
call snconv (nev, ritzr(np+1), ritzi(np+1), workl(2*np+1),
& tol, nconv)
c
if (msglvl .gt. 2) then
kp(1) = nev
kp(2) = np
kp(3) = numcnv
kp(4) = nconv
call ivout (logfil, 4, kp, ndigit,
& '_naup2: NEV, NP, NUMCNV, NCONV are')
call svout (logfil, kplusp, ritzr, ndigit,
& '_naup2: Real part of the eigenvalues of H')
call svout (logfil, kplusp, ritzi, ndigit,
& '_naup2: Imaginary part of the eigenvalues of H')
call svout (logfil, kplusp, bounds, ndigit,
& '_naup2: Ritz estimates of the current NCV Ritz values')
end if
c
c %---------------------------------------------------------%
c | Count the number of unwanted Ritz values that have zero |
c | Ritz estimates. If any Ritz estimates are equal to zero |
c | then a leading block of H of order equal to at least |
c | the number of Ritz values with zero Ritz estimates has |
c | split off. None of these Ritz values may be removed by |
c | shifting. Decrease NP the number of shifts to apply. If |
c | no shifts may be applied, then prepare to exit |
c %---------------------------------------------------------%
c
nptemp = np
do 30 j=1, nptemp
if (bounds(j) .eq. zero) then
np = np - 1
nev = nev + 1
end if
30 continue
c
if ( (nconv .ge. numcnv) .or.
& (iter .gt. mxiter) .or.
& (np .eq. 0) ) then
c
if (msglvl .gt. 4) then
call svout(logfil, kplusp, workl(kplusp**2+1), ndigit,
& '_naup2: Real part of the eig computed by _neigh:')
call svout(logfil, kplusp, workl(kplusp**2+kplusp+1),
& ndigit,
& '_naup2: Imag part of the eig computed by _neigh:')
call svout(logfil, kplusp, workl(kplusp**2+kplusp*2+1),
& ndigit,
& '_naup2: Ritz eistmates computed by _neigh:')
end if
c
c %------------------------------------------------%
c | Prepare to exit. Put the converged Ritz values |
c | and corresponding bounds in RITZ(1:NCONV) and |
c | BOUNDS(1:NCONV) respectively. Then sort. Be |
c | careful when NCONV > NP |
c %------------------------------------------------%
c
c %------------------------------------------%
c | Use h( 3,1 ) as storage to communicate |
c | rnorm to _neupd if needed |
c %------------------------------------------%
h(3,1) = rnorm
c
c %----------------------------------------------%
c | To be consistent with sngets, we first do a |
c | pre-processing sort in order to keep complex |
c | conjugate pairs together. This is similar |
c | to the pre-processing sort used in sngets |
c | except that the sort is done in the opposite |
c | order. |
c %----------------------------------------------%
c
if (which .eq. 'LM') wprime = 'SR'
if (which .eq. 'SM') wprime = 'LR'
if (which .eq. 'LR') wprime = 'SM'
if (which .eq. 'SR') wprime = 'LM'
if (which .eq. 'LI') wprime = 'SM'
if (which .eq. 'SI') wprime = 'LM'
c
call ssortc (wprime, .true., kplusp, ritzr, ritzi, bounds)
c
c %----------------------------------------------%
c | Now sort Ritz values so that converged Ritz |
c | values appear within the first NEV locations |
c | of ritzr, ritzi and bounds, and the most |
c | desired one appears at the front. |
c %----------------------------------------------%
c
if (which .eq. 'LM') wprime = 'SM'
if (which .eq. 'SM') wprime = 'LM'
if (which .eq. 'LR') wprime = 'SR'
if (which .eq. 'SR') wprime = 'LR'
if (which .eq. 'LI') wprime = 'SI'
if (which .eq. 'SI') wprime = 'LI'
c
call ssortc(wprime, .true., kplusp, ritzr, ritzi, bounds)
c
c %--------------------------------------------------%
c | Scale the Ritz estimate of each Ritz value |
c | by 1 / max(eps23,magnitude of the Ritz value). |
c %--------------------------------------------------%
c
do 35 j = 1, numcnv
temp = max(eps23,slapy2(ritzr(j),
& ritzi(j)))
bounds(j) = bounds(j)/temp
35 continue
c
c %----------------------------------------------------%
c | Sort the Ritz values according to the scaled Ritz |
c | esitmates. This will push all the converged ones |
c | towards the front of ritzr, ritzi, bounds |
c | (in the case when NCONV < NEV.) |
c %----------------------------------------------------%
c
wprime = 'LR'
call ssortc(wprime, .true., numcnv, bounds, ritzr, ritzi)
c
c %----------------------------------------------%
c | Scale the Ritz estimate back to its original |
c | value. |
c %----------------------------------------------%
c
do 40 j = 1, numcnv
temp = max(eps23, slapy2(ritzr(j),
& ritzi(j)))
bounds(j) = bounds(j)*temp
40 continue
c
c %------------------------------------------------%
c | Sort the converged Ritz values again so that |
c | the "threshold" value appears at the front of |
c | ritzr, ritzi and bound. |
c %------------------------------------------------%
c
call ssortc(which, .true., nconv, ritzr, ritzi, bounds)
c
if (msglvl .gt. 1) then
call svout (logfil, kplusp, ritzr, ndigit,
& '_naup2: Sorted real part of the eigenvalues')
call svout (logfil, kplusp, ritzi, ndigit,
& '_naup2: Sorted imaginary part of the eigenvalues')
call svout (logfil, kplusp, bounds, ndigit,
& '_naup2: Sorted ritz estimates.')
end if
c
c %------------------------------------%
c | Max iterations have been exceeded. |
c %------------------------------------%
c
if (iter .gt. mxiter .and. nconv .lt. numcnv) info = 1
c
c %---------------------%
c | No shifts to apply. |
c %---------------------%
c
if (np .eq. 0 .and. nconv .lt. numcnv) info = 2
c
np = nconv
go to 1100
c
else if ( (nconv .lt. numcnv) .and. (ishift .eq. 1) ) then
c
c %-------------------------------------------------%
c | Do not have all the requested eigenvalues yet. |
c | To prevent possible stagnation, adjust the size |
c | of NEV. |
c %-------------------------------------------------%
c
nevbef = nev
nev = nev + min(nconv, np/2)
if (nev .eq. 1 .and. kplusp .ge. 6) then
nev = kplusp / 2
else if (nev .eq. 1 .and. kplusp .gt. 3) then
nev = 2
end if
np = kplusp - nev
c
c %---------------------------------------%
c | If the size of NEV was just increased |
c | resort the eigenvalues. |
c %---------------------------------------%
c
if (nevbef .lt. nev)
& call sngets (ishift, which, nev, np, ritzr, ritzi,
& bounds, workl, workl(np+1))
c
end if
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, nconv, ndigit,
& '_naup2: no. of "converged" Ritz values at this iter.')
if (msglvl .gt. 1) then
kp(1) = nev
kp(2) = np
call ivout (logfil, 2, kp, ndigit,
& '_naup2: NEV and NP are')
call svout (logfil, nev, ritzr(np+1), ndigit,
& '_naup2: "wanted" Ritz values -- real part')
call svout (logfil, nev, ritzi(np+1), ndigit,
& '_naup2: "wanted" Ritz values -- imag part')
call svout (logfil, nev, bounds(np+1), ndigit,
& '_naup2: Ritz estimates of the "wanted" values ')
end if
end if
c
if (ishift .eq. 0) then
c
c %-------------------------------------------------------%
c | User specified shifts: reverse comminucation to |
c | compute the shifts. They are returned in the first |
c | 2*NP locations of WORKL. |
c %-------------------------------------------------------%
c
ushift = .true.
ido = 3
go to 9000
end if
c
50 continue
c
c %------------------------------------%
c | Back from reverse communication; |
c | User specified shifts are returned |
c | in WORKL(1:2*NP) |
c %------------------------------------%
c
ushift = .false.
c
if ( ishift .eq. 0 ) then
c
c %----------------------------------%
c | Move the NP shifts from WORKL to |
c | RITZR, RITZI to free up WORKL |
c | for non-exact shift case. |
c %----------------------------------%
c
call scopy (np, workl, 1, ritzr, 1)
call scopy (np, workl(np+1), 1, ritzi, 1)
end if
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, np, ndigit,
& '_naup2: The number of shifts to apply ')
call svout (logfil, np, ritzr, ndigit,
& '_naup2: Real part of the shifts')
call svout (logfil, np, ritzi, ndigit,
& '_naup2: Imaginary part of the shifts')
if ( ishift .eq. 1 )
& call svout (logfil, np, bounds, ndigit,
& '_naup2: Ritz estimates of the shifts')
end if
c
c %---------------------------------------------------------%
c | Apply the NP implicit shifts by QR bulge chasing. |
c | Each shift is applied to the whole upper Hessenberg |
c | matrix H. |
c | The first 2*N locations of WORKD are used as workspace. |
c %---------------------------------------------------------%
c
call snapps (n, nev, np, ritzr, ritzi, v, ldv,
& h, ldh, resid, q, ldq, workl, workd)
c
c %---------------------------------------------%
c | Compute the B-norm of the updated residual. |
c | Keep B*RESID in WORKD(1:N) to be used in |
c | the first step of the next call to snaitr. |
c %---------------------------------------------%
c
cnorm = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call scopy (n, resid, 1, workd(n+1), 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*RESID |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call scopy (n, resid, 1, workd, 1)
end if
c
100 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(1:N) := B*RESID |
c %----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
if (bmat .eq. 'G') then
rnorm = sdot (n, resid, 1, workd, 1)
rnorm = sqrt(abs(rnorm))
else if (bmat .eq. 'I') then
rnorm = snrm2(n, resid, 1)
end if
cnorm = .false.
c
if (msglvl .gt. 2) then
call svout (logfil, 1, rnorm, ndigit,
& '_naup2: B-norm of residual for compressed factorization')
call smout (logfil, nev, nev, h, ldh, ndigit,
& '_naup2: Compressed upper Hessenberg matrix H')
end if
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
1100 continue
c
mxiter = iter
nev = numcnv
c
1200 continue
ido = 99
c
c %------------%
c | Error Exit |
c %------------%
c
call second (t1)
tnaup2 = t1 - t0
c
9000 continue
c
c %---------------%
c | End of snaup2 |
c %---------------%
c
return
end

693
arpack/ARPACK/SRC/snaupd.f Normal file
View File

@@ -0,0 +1,693 @@
c\BeginDoc
c
c\Name: snaupd
c
c\Description:
c Reverse communication interface for the Implicitly Restarted Arnoldi
c iteration. This subroutine computes approximations to a few eigenpairs
c of a linear operator "OP" with respect to a semi-inner product defined by
c a symmetric positive semi-definite real matrix B. B may be the identity
c matrix. NOTE: If the linear operator "OP" is real and symmetric
c with respect to the real positive semi-definite symmetric matrix B,
c i.e. B*OP = (OP`)*B, then subroutine ssaupd should be used instead.
c
c The computed approximate eigenvalues are called Ritz values and
c the corresponding approximate eigenvectors are called Ritz vectors.
c
c snaupd is usually called iteratively to solve one of the
c following problems:
c
c Mode 1: A*x = lambda*x.
c ===> OP = A and B = I.
c
c Mode 2: A*x = lambda*M*x, M symmetric positive definite
c ===> OP = inv[M]*A and B = M.
c ===> (If M can be factored see remark 3 below)
c
c Mode 3: A*x = lambda*M*x, M symmetric semi-definite
c ===> OP = Real_Part{ inv[A - sigma*M]*M } and B = M.
c ===> shift-and-invert mode (in real arithmetic)
c If OP*x = amu*x, then
c amu = 1/2 * [ 1/(lambda-sigma) + 1/(lambda-conjg(sigma)) ].
c Note: If sigma is real, i.e. imaginary part of sigma is zero;
c Real_Part{ inv[A - sigma*M]*M } == inv[A - sigma*M]*M
c amu == 1/(lambda-sigma).
c
c Mode 4: A*x = lambda*M*x, M symmetric semi-definite
c ===> OP = Imaginary_Part{ inv[A - sigma*M]*M } and B = M.
c ===> shift-and-invert mode (in real arithmetic)
c If OP*x = amu*x, then
c amu = 1/2i * [ 1/(lambda-sigma) - 1/(lambda-conjg(sigma)) ].
c
c Both mode 3 and 4 give the same enhancement to eigenvalues close to
c the (complex) shift sigma. However, as lambda goes to infinity,
c the operator OP in mode 4 dampens the eigenvalues more strongly than
c does OP defined in mode 3.
c
c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v
c should be accomplished either by a direct method
c using a sparse matrix factorization and solving
c
c [A - sigma*M]*w = v or M*w = v,
c
c or through an iterative method for solving these
c systems. If an iterative method is used, the
c convergence test must be more stringent than
c the accuracy requirements for the eigenvalue
c approximations.
c
c\Usage:
c call snaupd
c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM,
c IPNTR, WORKD, WORKL, LWORKL, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag. IDO must be zero on the first
c call to snaupd. IDO will be set internally to
c indicate the type of operation to be performed. Control is
c then given back to the calling routine which has the
c responsibility to carry out the requested operation and call
c snaupd with the result. The operand is given in
c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)).
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c This is for the initialization phase to force the
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c In mode 3 and 4, the vector B * X is already
c available in WORKD(ipntr(3)). It does not
c need to be recomputed in forming OP * X.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c IDO = 3: compute the IPARAM(8) real and imaginary parts
c of the shifts where INPTR(14) is the pointer
c into WORKL for placing the shifts. See Remark
c 5 below.
c IDO = 99: done
c -------------------------------------------------------------
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B that defines the
c semi-inner product for the operator OP.
c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x
c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*B*x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c WHICH Character*2. (INPUT)
c 'LM' -> want the NEV eigenvalues of largest magnitude.
c 'SM' -> want the NEV eigenvalues of smallest magnitude.
c 'LR' -> want the NEV eigenvalues of largest real part.
c 'SR' -> want the NEV eigenvalues of smallest real part.
c 'LI' -> want the NEV eigenvalues of largest imaginary part.
c 'SI' -> want the NEV eigenvalues of smallest imaginary part.
c
c NEV Integer. (INPUT/OUTPUT)
c Number of eigenvalues of OP to be computed. 0 < NEV < N-1.
c
c TOL Real scalar. (INPUT)
c Stopping criterion: the relative accuracy of the Ritz value
c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I))
c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex.
c DEFAULT = SLAMCH('EPS') (machine precision as computed
c by the LAPACK auxiliary subroutine SLAMCH).
c
c RESID Real array of length N. (INPUT/OUTPUT)
c On INPUT:
c If INFO .EQ. 0, a random initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c On OUTPUT:
c RESID contains the final residual vector.
c
c NCV Integer. (INPUT)
c Number of columns of the matrix V. NCV must satisfy the two
c inequalities 2 <= NCV-NEV and NCV <= N.
c This will indicate how many Arnoldi vectors are generated
c at each iteration. After the startup phase in which NEV
c Arnoldi vectors are generated, the algorithm generates
c approximately NCV-NEV Arnoldi vectors at each subsequent update
c iteration. Most of the cost in generating each Arnoldi vector is
c in the matrix-vector operation OP*x.
c NOTE: 2 <= NCV-NEV in order that complex conjugate pairs of Ritz
c values are kept together. (See remark 4 below)
c
c V Real array N by NCV. (OUTPUT)
c Contains the final set of Arnoldi basis vectors.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling program.
c
c IPARAM Integer array of length 11. (INPUT/OUTPUT)
c IPARAM(1) = ISHIFT: method for selecting the implicit shifts.
c The shifts selected at each iteration are used to restart
c the Arnoldi iteration in an implicit fashion.
c -------------------------------------------------------------
c ISHIFT = 0: the shifts are provided by the user via
c reverse communication. The real and imaginary
c parts of the NCV eigenvalues of the Hessenberg
c matrix H are returned in the part of the WORKL
c array corresponding to RITZR and RITZI. See remark
c 5 below.
c ISHIFT = 1: exact shifts with respect to the current
c Hessenberg matrix H. This is equivalent to
c restarting the iteration with a starting vector
c that is a linear combination of approximate Schur
c vectors associated with the "wanted" Ritz values.
c -------------------------------------------------------------
c
c IPARAM(2) = No longer referenced.
c
c IPARAM(3) = MXITER
c On INPUT: maximum number of Arnoldi update iterations allowed.
c On OUTPUT: actual number of Arnoldi update iterations taken.
c
c IPARAM(4) = NB: blocksize to be used in the recurrence.
c The code currently works only for NB = 1.
c
c IPARAM(5) = NCONV: number of "converged" Ritz values.
c This represents the number of Ritz values that satisfy
c the convergence criterion.
c
c IPARAM(6) = IUPD
c No longer referenced. Implicit restarting is ALWAYS used.
c
c IPARAM(7) = MODE
c On INPUT determines what type of eigenproblem is being solved.
c Must be 1,2,3,4; See under \Description of snaupd for the
c four modes available.
c
c IPARAM(8) = NP
c When ido = 3 and the user provides shifts through reverse
c communication (IPARAM(1)=0), snaupd returns NP, the number
c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark
c 5 below.
c
c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO,
c OUTPUT: NUMOP = total number of OP*x operations,
c NUMOPB = total number of B*x operations if BMAT='G',
c NUMREO = total number of steps of re-orthogonalization.
c
c IPNTR Integer array of length 14. (OUTPUT)
c Pointer to mark the starting locations in the WORKD and WORKL
c arrays for matrices/vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X in WORKD.
c IPNTR(2): pointer to the current result vector Y in WORKD.
c IPNTR(3): pointer to the vector B * X in WORKD when used in
c the shift-and-invert mode.
c IPNTR(4): pointer to the next available location in WORKL
c that is untouched by the program.
c IPNTR(5): pointer to the NCV by NCV upper Hessenberg matrix
c H in WORKL.
c IPNTR(6): pointer to the real part of the ritz value array
c RITZR in WORKL.
c IPNTR(7): pointer to the imaginary part of the ritz value array
c RITZI in WORKL.
c IPNTR(8): pointer to the Ritz estimates in array WORKL associated
c with the Ritz values located in RITZR and RITZI in WORKL.
c
c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below.
c
c Note: IPNTR(9:13) is only referenced by sneupd. See Remark 2 below.
c
c IPNTR(9): pointer to the real part of the NCV RITZ values of the
c original system.
c IPNTR(10): pointer to the imaginary part of the NCV RITZ values of
c the original system.
c IPNTR(11): pointer to the NCV corresponding error bounds.
c IPNTR(12): pointer to the NCV by NCV upper quasi-triangular
c Schur matrix for H.
c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors
c of the upper Hessenberg matrix H. Only referenced by
c sneupd if RVEC = .TRUE. See Remark 2 below.
c -------------------------------------------------------------
c
c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration. Upon termination
c WORKD(1:N) contains B*RESID(1:N). If an invariant subspace
c associated with the converged Ritz values is desired, see remark
c 2 below, subroutine sneupd uses this output.
c See Data Distribution Note below.
c
c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. See Data Distribution Note below.
c
c LWORKL Integer. (INPUT)
c LWORKL must be at least 3*NCV**2 + 6*NCV.
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal exit.
c = 1: Maximum number of iterations taken.
c All possible eigenvalues of OP has been found. IPARAM(5)
c returns the number of wanted converged Ritz values.
c = 2: No longer an informational error. Deprecated starting
c with release 2 of ARPACK.
c = 3: No shifts could be applied during a cycle of the
c Implicitly restarted Arnoldi iteration. One possibility
c is to increase the size of NCV relative to NEV.
c See remark 4 below.
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV-NEV >= 2 and less than or equal to N.
c = -4: The maximum number of Arnoldi update iteration
c must be greater than zero.
c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work array is not sufficient.
c = -8: Error return from LAPACK eigenvalue calculation;
c = -9: Starting vector is zero.
c = -10: IPARAM(7) must be 1,2,3,4.
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable.
c = -12: IPARAM(1) must be equal to 0 or 1.
c = -9999: Could not build an Arnoldi factorization.
c IPARAM(5) returns the size of the current Arnoldi
c factorization.
c
c\Remarks
c 1. The computed Ritz values are approximate eigenvalues of OP. The
c selection of WHICH should be made with this in mind when
c Mode = 3 and 4. After convergence, approximate eigenvalues of the
c original problem may be obtained with the ARPACK subroutine sneupd.
c
c 2. If a basis for the invariant subspace corresponding to the converged Ritz
c values is needed, the user must call sneupd immediately following
c completion of snaupd. This is new starting with release 2 of ARPACK.
c
c 3. If M can be factored into a Cholesky factorization M = LL`
c then Mode = 2 should not be selected. Instead one should use
c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular
c linear systems should be solved with L and L` rather
c than computing inverses. After convergence, an approximate
c eigenvector z of the original problem is recovered by solving
c L`z = x where x is a Ritz vector of OP.
c
c 4. At present there is no a-priori analysis to guide the selection
c of NCV relative to NEV. The only formal requrement is that NCV > NEV + 2.
c However, it is recommended that NCV .ge. 2*NEV+1. If many problems of
c the same type are to be solved, one should experiment with increasing
c NCV while keeping NEV fixed for a given test problem. This will
c usually decrease the required number of OP*x operations but it
c also increases the work and storage required to maintain the orthogonal
c basis vectors. The optimal "cross-over" with respect to CPU time
c is problem dependent and must be determined empirically.
c See Chapter 8 of Reference 2 for further information.
c
c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the
c NP = IPARAM(8) real and imaginary parts of the shifts in locations
c real part imaginary part
c ----------------------- --------------
c 1 WORKL(IPNTR(14)) WORKL(IPNTR(14)+NP)
c 2 WORKL(IPNTR(14)+1) WORKL(IPNTR(14)+NP+1)
c . .
c . .
c . .
c NP WORKL(IPNTR(14)+NP-1) WORKL(IPNTR(14)+2*NP-1).
c
c Only complex conjugate pairs of shifts may be applied and the pairs
c must be placed in consecutive locations. The real part of the
c eigenvalues of the current upper Hessenberg matrix are located in
c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1) and the imaginary part
c in WORKL(IPNTR(7)) through WORKL(IPNTR(7)+NCV-1). They are ordered
c according to the order defined by WHICH. The complex conjugate
c pairs are kept together and the associated Ritz estimates are located in
c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1).
c
c-----------------------------------------------------------------------
c
c\Data Distribution Note:
c
c Fortran-D syntax:
c ================
c Real resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
c decompose d1(n), d2(n,ncv)
c align resid(i) with d1(i)
c align v(i,j) with d2(i,j)
c align workd(i) with d1(i) range (1:n)
c align workd(i) with d1(i-n) range (n+1:2*n)
c align workd(i) with d1(i-2*n) range (2*n+1:3*n)
c distribute d1(block), d2(block,:)
c replicated workl(lworkl)
c
c Cray MPP syntax:
c ===============
c Real resid(n), v(ldv,ncv), workd(n,3), workl(lworkl)
c shared resid(block), v(block,:), workd(block,:)
c replicated workl(lworkl)
c
c CM2/CM5 syntax:
c ==============
c
c-----------------------------------------------------------------------
c
c include 'ex-nonsym.doc'
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett & Y. Saad, "Complex Shift and Invert Strategies for
c Real Matrices", Linear Algebra and its Applications, vol 88/89,
c pp 575-595, (1987).
c
c\Routines called:
c snaup2 ARPACK routine that implements the Implicitly Restarted
c Arnoldi Iteration.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c svout ARPACK utility routine that prints vectors.
c slamch LAPACK routine that determines machine constants.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/16/93: Version '1.1'
c
c\SCCS Information: @(#)
c FILE: naupd.F SID: 2.10 DATE OF SID: 08/23/02 RELEASE: 2
c
c\Remarks
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine snaupd
& ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam,
& ipntr, workd, workl, lworkl, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ldv, lworkl, n, ncv, nev
Real
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(11), ipntr(14)
Real
& resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0, zero = 0.0E+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer bounds, ierr, ih, iq, ishift, iupd, iw,
& ldh, ldq, levec, mode, msglvl, mxiter, nb,
& nev0, next, np, ritzi, ritzr, j
save bounds, ih, iq, ishift, iupd, iw, ldh, ldq,
& levec, mode, msglvl, mxiter, nb, nev0, next,
& np, ritzi, ritzr
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external snaup2, svout, ivout, second, sstatn
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& slamch
external slamch
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call sstatn
call second (t0)
msglvl = mnaupd
c
c %----------------%
c | Error checking |
c %----------------%
c
ierr = 0
ishift = iparam(1)
c levec = iparam(2)
mxiter = iparam(3)
c nb = iparam(4)
nb = 1
c
c %--------------------------------------------%
c | Revision 2 performs only implicit restart. |
c %--------------------------------------------%
c
iupd = 1
mode = iparam(7)
c
if (n .le. 0) then
ierr = -1
else if (nev .le. 0) then
ierr = -2
else if (ncv .le. nev+1 .or. ncv .gt. n) then
ierr = -3
else if (mxiter .le. 0) then
ierr = 4
else if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LR' .and.
& which .ne. 'SR' .and.
& which .ne. 'LI' .and.
& which .ne. 'SI') then
ierr = -5
else if (bmat .ne. 'I' .and. bmat .ne. 'G') then
ierr = -6
else if (lworkl .lt. 3*ncv**2 + 6*ncv) then
ierr = -7
else if (mode .lt. 1 .or. mode .gt. 4) then
ierr = -10
else if (mode .eq. 1 .and. bmat .eq. 'G') then
ierr = -11
else if (ishift .lt. 0 .or. ishift .gt. 1) then
ierr = -12
end if
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
ido = 99
go to 9000
end if
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
if (nb .le. 0) nb = 1
if (tol .le. zero) tol = slamch('EpsMach')
c
c %----------------------------------------------%
c | NP is the number of additional steps to |
c | extend the length NEV Lanczos factorization. |
c | NEV0 is the local variable designating the |
c | size of the invariant subspace desired. |
c %----------------------------------------------%
c
np = ncv - nev
nev0 = nev
c
c %-----------------------------%
c | Zero out internal workspace |
c %-----------------------------%
c
do 10 j = 1, 3*ncv**2 + 6*ncv
workl(j) = zero
10 continue
c
c %-------------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:ncv*ncv) := generated Hessenberg matrix |
c | workl(ncv*ncv+1:ncv*ncv+2*ncv) := real and imaginary |
c | parts of ritz values |
c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := error bounds |
c | workl(ncv*ncv+3*ncv+1:2*ncv*ncv+3*ncv) := rotation matrix Q |
c | workl(2*ncv*ncv+3*ncv+1:3*ncv*ncv+6*ncv) := workspace |
c | The final workspace is needed by subroutine sneigh called |
c | by snaup2. Subroutine sneigh calls LAPACK routines for |
c | calculating eigenvalues and the last row of the eigenvector |
c | matrix. |
c %-------------------------------------------------------------%
c
ldh = ncv
ldq = ncv
ih = 1
ritzr = ih + ldh*ncv
ritzi = ritzr + ncv
bounds = ritzi + ncv
iq = bounds + ncv
iw = iq + ldq*ncv
next = iw + ncv**2 + 3*ncv
c
ipntr(4) = next
ipntr(5) = ih
ipntr(6) = ritzr
ipntr(7) = ritzi
ipntr(8) = bounds
ipntr(14) = iw
c
end if
c
c %-------------------------------------------------------%
c | Carry out the Implicitly restarted Arnoldi Iteration. |
c %-------------------------------------------------------%
c
call snaup2
& ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritzr),
& workl(ritzi), workl(bounds), workl(iq), ldq, workl(iw),
& ipntr, workd, info )
c
c %--------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP or shifts. |
c %--------------------------------------------------%
c
if (ido .eq. 3) iparam(8) = np
if (ido .ne. 99) go to 9000
c
iparam(3) = mxiter
iparam(5) = np
iparam(9) = nopx
iparam(10) = nbx
iparam(11) = nrorth
c
c %------------------------------------%
c | Exit if there was an informational |
c | error within snaup2. |
c %------------------------------------%
c
if (info .lt. 0) go to 9000
if (info .eq. 2) info = 3
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, mxiter, ndigit,
& '_naupd: Number of update iterations taken')
call ivout (logfil, 1, np, ndigit,
& '_naupd: Number of wanted "converged" Ritz values')
call svout (logfil, np, workl(ritzr), ndigit,
& '_naupd: Real part of the final Ritz values')
call svout (logfil, np, workl(ritzi), ndigit,
& '_naupd: Imaginary part of the final Ritz values')
call svout (logfil, np, workl(bounds), ndigit,
& '_naupd: Associated Ritz estimates')
end if
c
call second (t1)
tnaupd = t1 - t0
c
if (msglvl .gt. 0) then
c
c %--------------------------------------------------------%
c | Version Number & Version Date are defined in version.h |
c %--------------------------------------------------------%
c
write (6,1000)
write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt,
& tmvopx, tmvbx, tnaupd, tnaup2, tnaitr, titref,
& tgetv0, tneigh, tngets, tnapps, tnconv, trvec
1000 format (//,
& 5x, '=============================================',/
& 5x, '= Nonsymmetric implicit Arnoldi update code =',/
& 5x, '= Version Number: ', ' 2.4', 21x, ' =',/
& 5x, '= Version Date: ', ' 07/31/96', 16x, ' =',/
& 5x, '=============================================',/
& 5x, '= Summary of timing statistics =',/
& 5x, '=============================================',//)
1100 format (
& 5x, 'Total number update iterations = ', i5,/
& 5x, 'Total number of OP*x operations = ', i5,/
& 5x, 'Total number of B*x operations = ', i5,/
& 5x, 'Total number of reorthogonalization steps = ', i5,/
& 5x, 'Total number of iterative refinement steps = ', i5,/
& 5x, 'Total number of restart steps = ', i5,/
& 5x, 'Total time in user OP*x operation = ', f12.6,/
& 5x, 'Total time in user B*x operation = ', f12.6,/
& 5x, 'Total time in Arnoldi update routine = ', f12.6,/
& 5x, 'Total time in naup2 routine = ', f12.6,/
& 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/
& 5x, 'Total time in reorthogonalization phase = ', f12.6,/
& 5x, 'Total time in (re)start vector generation = ', f12.6,/
& 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/
& 5x, 'Total time in getting the shifts = ', f12.6,/
& 5x, 'Total time in applying the shifts = ', f12.6,/
& 5x, 'Total time in convergence testing = ', f12.6,/
& 5x, 'Total time in computing final Ritz vectors = ', f12.6/)
end if
c
9000 continue
c
return
c
c %---------------%
c | End of snaupd |
c %---------------%
c
end

View File

146
arpack/ARPACK/SRC/snconv.f Normal file
View File

@@ -0,0 +1,146 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: snconv
c
c\Description:
c Convergence testing for the nonsymmetric Arnoldi eigenvalue routine.
c
c\Usage:
c call snconv
c ( N, RITZR, RITZI, BOUNDS, TOL, NCONV )
c
c\Arguments
c N Integer. (INPUT)
c Number of Ritz values to check for convergence.
c
c RITZR, Real arrays of length N. (INPUT)
c RITZI Real and imaginary parts of the Ritz values to be checked
c for convergence.
c BOUNDS Real array of length N. (INPUT)
c Ritz estimates for the Ritz values in RITZR and RITZI.
c
c TOL Real scalar. (INPUT)
c Desired backward error for a Ritz value to be considered
c "converged".
c
c NCONV Integer scalar. (OUTPUT)
c Number of "converged" Ritz values.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c second ARPACK utility routine for timing.
c slamch LAPACK routine that determines machine constants.
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: nconv.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2
c
c\Remarks
c 1. xxxx
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine snconv (n, ritzr, ritzi, bounds, tol, nconv)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer n, nconv
Real
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
Real
& ritzr(n), ritzi(n), bounds(n)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i
Real
& temp, eps23
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& slapy2, slamch
external slapy2, slamch
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------------------------------------%
c | Convergence test: unlike in the symmetric code, I am not |
c | using things like refined error bounds and gap condition |
c | because I don't know the exact equivalent concept. |
c | |
c | Instead the i-th Ritz value is considered "converged" when: |
c | |
c | bounds(i) .le. ( TOL * | ritz | ) |
c | |
c | for some appropriate choice of norm. |
c %-------------------------------------------------------------%
c
call second (t0)
c
c %---------------------------------%
c | Get machine dependent constant. |
c %---------------------------------%
c
eps23 = slamch('Epsilon-Machine')
eps23 = eps23**(2.0E+0 / 3.0E+0)
c
nconv = 0
do 20 i = 1, n
temp = max( eps23, slapy2( ritzr(i), ritzi(i) ) )
if (bounds(i) .le. tol*temp) nconv = nconv + 1
20 continue
c
call second (t1)
tnconv = tnconv + (t1 - t0)
c
return
c
c %---------------%
c | End of snconv |
c %---------------%
c
end

314
arpack/ARPACK/SRC/sneigh.f Normal file
View File

@@ -0,0 +1,314 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: sneigh
c
c\Description:
c Compute the eigenvalues of the current upper Hessenberg matrix
c and the corresponding Ritz estimates given the current residual norm.
c
c\Usage:
c call sneigh
c ( RNORM, N, H, LDH, RITZR, RITZI, BOUNDS, Q, LDQ, WORKL, IERR )
c
c\Arguments
c RNORM Real scalar. (INPUT)
c Residual norm corresponding to the current upper Hessenberg
c matrix H.
c
c N Integer. (INPUT)
c Size of the matrix H.
c
c H Real N by N array. (INPUT)
c H contains the current upper Hessenberg matrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RITZR, Real arrays of length N. (OUTPUT)
c RITZI On output, RITZR(1:N) (resp. RITZI(1:N)) contains the real
c (respectively imaginary) parts of the eigenvalues of H.
c
c BOUNDS Real array of length N. (OUTPUT)
c On output, BOUNDS contains the Ritz estimates associated with
c the eigenvalues RITZR and RITZI. This is equal to RNORM
c times the last components of the eigenvectors corresponding
c to the eigenvalues in RITZR and RITZI.
c
c Q Real N by N array. (WORKSPACE)
c Workspace needed to store the eigenvectors of H.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Real work array of length N**2 + 3*N. (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. This is needed to keep the full Schur form
c of H and also in the calculation of the eigenvectors of H.
c
c IERR Integer. (OUTPUT)
c Error exit flag from slaqrb or strevc.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c slaqrb ARPACK routine to compute the real Schur form of an
c upper Hessenberg matrix and last row of the Schur vectors.
c second ARPACK utility routine for timing.
c smout ARPACK utility routine that prints matrices
c svout ARPACK utility routine that prints vectors.
c slacpy LAPACK matrix copy routine.
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c strevc LAPACK routine to compute the eigenvectors of a matrix
c in upper quasi-triangular form
c sgemv Level 2 BLAS routine for matrix vector multiplication.
c scopy Level 1 BLAS that copies one vector to another .
c snrm2 Level 1 BLAS that computes the norm of a vector.
c sscal Level 1 BLAS that scales a vector.
c
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: neigh.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2
c
c\Remarks
c None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine sneigh (rnorm, n, h, ldh, ritzr, ritzi, bounds,
& q, ldq, workl, ierr)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer ierr, n, ldh, ldq
Real
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& bounds(n), h(ldh,n), q(ldq,n), ritzi(n), ritzr(n),
& workl(n*(n+3))
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0, zero = 0.0E+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
logical select(1)
integer i, iconj, msglvl
Real
& temp, vl(1)
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external scopy, slacpy, slaqrb, strevc, svout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& slapy2, snrm2
external slapy2, snrm2
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic abs
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mneigh
c
if (msglvl .gt. 2) then
call smout (logfil, n, n, h, ldh, ndigit,
& '_neigh: Entering upper Hessenberg matrix H ')
end if
c
c %-----------------------------------------------------------%
c | 1. Compute the eigenvalues, the last components of the |
c | corresponding Schur vectors and the full Schur form T |
c | of the current upper Hessenberg matrix H. |
c | slaqrb returns the full Schur form of H in WORKL(1:N**2) |
c | and the last components of the Schur vectors in BOUNDS. |
c %-----------------------------------------------------------%
c
call slacpy ('All', n, n, h, ldh, workl, n)
call slaqrb (.true., n, 1, n, workl, n, ritzr, ritzi, bounds,
& ierr)
if (ierr .ne. 0) go to 9000
c
if (msglvl .gt. 1) then
call svout (logfil, n, bounds, ndigit,
& '_neigh: last row of the Schur matrix for H')
end if
c
c %-----------------------------------------------------------%
c | 2. Compute the eigenvectors of the full Schur form T and |
c | apply the last components of the Schur vectors to get |
c | the last components of the corresponding eigenvectors. |
c | Remember that if the i-th and (i+1)-st eigenvalues are |
c | complex conjugate pairs, then the real & imaginary part |
c | of the eigenvector components are split across adjacent |
c | columns of Q. |
c %-----------------------------------------------------------%
c
call strevc ('R', 'A', select, n, workl, n, vl, n, q, ldq,
& n, n, workl(n*n+1), ierr)
c
if (ierr .ne. 0) go to 9000
c
c %------------------------------------------------%
c | Scale the returning eigenvectors so that their |
c | euclidean norms are all one. LAPACK subroutine |
c | strevc returns each eigenvector normalized so |
c | that the element of largest magnitude has |
c | magnitude 1; here the magnitude of a complex |
c | number (x,y) is taken to be |x| + |y|. |
c %------------------------------------------------%
c
iconj = 0
do 10 i=1, n
if ( abs( ritzi(i) ) .le. zero ) then
c
c %----------------------%
c | Real eigenvalue case |
c %----------------------%
c
temp = snrm2( n, q(1,i), 1 )
call sscal ( n, one / temp, q(1,i), 1 )
else
c
c %-------------------------------------------%
c | Complex conjugate pair case. Note that |
c | since the real and imaginary part of |
c | the eigenvector are stored in consecutive |
c | columns, we further normalize by the |
c | square root of two. |
c %-------------------------------------------%
c
if (iconj .eq. 0) then
temp = slapy2( snrm2( n, q(1,i), 1 ),
& snrm2( n, q(1,i+1), 1 ) )
call sscal ( n, one / temp, q(1,i), 1 )
call sscal ( n, one / temp, q(1,i+1), 1 )
iconj = 1
else
iconj = 0
end if
end if
10 continue
c
call sgemv ('T', n, n, one, q, ldq, bounds, 1, zero, workl, 1)
c
if (msglvl .gt. 1) then
call svout (logfil, n, workl, ndigit,
& '_neigh: Last row of the eigenvector matrix for H')
end if
c
c %----------------------------%
c | Compute the Ritz estimates |
c %----------------------------%
c
iconj = 0
do 20 i = 1, n
if ( abs( ritzi(i) ) .le. zero ) then
c
c %----------------------%
c | Real eigenvalue case |
c %----------------------%
c
bounds(i) = rnorm * abs( workl(i) )
else
c
c %-------------------------------------------%
c | Complex conjugate pair case. Note that |
c | since the real and imaginary part of |
c | the eigenvector are stored in consecutive |
c | columns, we need to take the magnitude |
c | of the last components of the two vectors |
c %-------------------------------------------%
c
if (iconj .eq. 0) then
bounds(i) = rnorm * slapy2( workl(i), workl(i+1) )
bounds(i+1) = bounds(i)
iconj = 1
else
iconj = 0
end if
end if
20 continue
c
if (msglvl .gt. 2) then
call svout (logfil, n, ritzr, ndigit,
& '_neigh: Real part of the eigenvalues of H')
call svout (logfil, n, ritzi, ndigit,
& '_neigh: Imaginary part of the eigenvalues of H')
call svout (logfil, n, bounds, ndigit,
& '_neigh: Ritz estimates for the eigenvalues of H')
end if
c
call second (t1)
tneigh = tneigh + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of sneigh |
c %---------------%
c
end

1063
arpack/ARPACK/SRC/sneupd.f Normal file

File diff suppressed because it is too large Load Diff

231
arpack/ARPACK/SRC/sngets.f Normal file
View File

@@ -0,0 +1,231 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: sngets
c
c\Description:
c Given the eigenvalues of the upper Hessenberg matrix H,
c computes the NP shifts AMU that are zeros of the polynomial of
c degree NP which filters out components of the unwanted eigenvectors
c corresponding to the AMU's based on some given criteria.
c
c NOTE: call this even in the case of user specified shifts in order
c to sort the eigenvalues, and error bounds of H for later use.
c
c\Usage:
c call sngets
c ( ISHIFT, WHICH, KEV, NP, RITZR, RITZI, BOUNDS, SHIFTR, SHIFTI )
c
c\Arguments
c ISHIFT Integer. (INPUT)
c Method for selecting the implicit shifts at each iteration.
c ISHIFT = 0: user specified shifts
c ISHIFT = 1: exact shift with respect to the matrix H.
c
c WHICH Character*2. (INPUT)
c Shift selection criteria.
c 'LM' -> want the KEV eigenvalues of largest magnitude.
c 'SM' -> want the KEV eigenvalues of smallest magnitude.
c 'LR' -> want the KEV eigenvalues of largest real part.
c 'SR' -> want the KEV eigenvalues of smallest real part.
c 'LI' -> want the KEV eigenvalues of largest imaginary part.
c 'SI' -> want the KEV eigenvalues of smallest imaginary part.
c
c KEV Integer. (INPUT/OUTPUT)
c INPUT: KEV+NP is the size of the matrix H.
c OUTPUT: Possibly increases KEV by one to keep complex conjugate
c pairs together.
c
c NP Integer. (INPUT/OUTPUT)
c Number of implicit shifts to be computed.
c OUTPUT: Possibly decreases NP by one to keep complex conjugate
c pairs together.
c
c RITZR, Real array of length KEV+NP. (INPUT/OUTPUT)
c RITZI On INPUT, RITZR and RITZI contain the real and imaginary
c parts of the eigenvalues of H.
c On OUTPUT, RITZR and RITZI are sorted so that the unwanted
c eigenvalues are in the first NP locations and the wanted
c portion is in the last KEV locations. When exact shifts are
c selected, the unwanted part corresponds to the shifts to
c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues
c are further sorted so that the ones with largest Ritz values
c are first.
c
c BOUNDS Real array of length KEV+NP. (INPUT/OUTPUT)
c Error bounds corresponding to the ordering in RITZ.
c
c SHIFTR, SHIFTI *** USE deprecated as of version 2.1. ***
c
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c ssortc ARPACK sorting routine.
c scopy Level 1 BLAS that copies one vector to another .
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: ngets.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2
c
c\Remarks
c 1. xxxx
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine sngets ( ishift, which, kev, np, ritzr, ritzi, bounds,
& shiftr, shifti )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
integer ishift, kev, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& bounds(kev+np), ritzr(kev+np), ritzi(kev+np),
& shiftr(1), shifti(1)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0, zero = 0.0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer msglvl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external scopy, ssortc, second
c
c %----------------------%
c | Intrinsics Functions |
c %----------------------%
c
intrinsic abs
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mngets
c
c %----------------------------------------------------%
c | LM, SM, LR, SR, LI, SI case. |
c | Sort the eigenvalues of H into the desired order |
c | and apply the resulting order to BOUNDS. |
c | The eigenvalues are sorted so that the wanted part |
c | are always in the last KEV locations. |
c | We first do a pre-processing sort in order to keep |
c | complex conjugate pairs together |
c %----------------------------------------------------%
c
if (which .eq. 'LM') then
call ssortc ('LR', .true., kev+np, ritzr, ritzi, bounds)
else if (which .eq. 'SM') then
call ssortc ('SR', .true., kev+np, ritzr, ritzi, bounds)
else if (which .eq. 'LR') then
call ssortc ('LM', .true., kev+np, ritzr, ritzi, bounds)
else if (which .eq. 'SR') then
call ssortc ('SM', .true., kev+np, ritzr, ritzi, bounds)
else if (which .eq. 'LI') then
call ssortc ('LM', .true., kev+np, ritzr, ritzi, bounds)
else if (which .eq. 'SI') then
call ssortc ('SM', .true., kev+np, ritzr, ritzi, bounds)
end if
c
call ssortc (which, .true., kev+np, ritzr, ritzi, bounds)
c
c %-------------------------------------------------------%
c | Increase KEV by one if the ( ritzr(np),ritzi(np) ) |
c | = ( ritzr(np+1),-ritzi(np+1) ) and ritz(np) .ne. zero |
c | Accordingly decrease NP by one. In other words keep |
c | complex conjugate pairs together. |
c %-------------------------------------------------------%
c
if ( ( ritzr(np+1) - ritzr(np) ) .eq. zero
& .and. ( ritzi(np+1) + ritzi(np) ) .eq. zero ) then
np = np - 1
kev = kev + 1
end if
c
if ( ishift .eq. 1 ) then
c
c %-------------------------------------------------------%
c | Sort the unwanted Ritz values used as shifts so that |
c | the ones with largest Ritz estimates are first |
c | This will tend to minimize the effects of the |
c | forward instability of the iteration when they shifts |
c | are applied in subroutine snapps. |
c | Be careful and use 'SR' since we want to sort BOUNDS! |
c %-------------------------------------------------------%
c
call ssortc ( 'SR', .true., np, bounds, ritzr, ritzi )
end if
c
call second (t1)
tngets = tngets + (t1 - t0)
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, kev, ndigit, '_ngets: KEV is')
call ivout (logfil, 1, np, ndigit, '_ngets: NP is')
call svout (logfil, kev+np, ritzr, ndigit,
& '_ngets: Eigenvalues of current H matrix -- real part')
call svout (logfil, kev+np, ritzi, ndigit,
& '_ngets: Eigenvalues of current H matrix -- imag part')
call svout (logfil, kev+np, bounds, ndigit,
& '_ngets: Ritz estimates of the current KEV+NP Ritz values')
end if
c
return
c
c %---------------%
c | End of sngets |
c %---------------%
c
end

853
arpack/ARPACK/SRC/ssaitr.f Normal file
View File

@@ -0,0 +1,853 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: ssaitr
c
c\Description:
c Reverse communication interface for applying NP additional steps to
c a K step symmetric Arnoldi factorization.
c
c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T
c
c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0.
c
c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T
c
c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0.
c
c where OP and B are as in ssaupd. The B-norm of r_{k+p} is also
c computed and returned.
c
c\Usage:
c call ssaitr
c ( IDO, BMAT, N, K, NP, MODE, RESID, RNORM, V, LDV, H, LDH,
c IPNTR, WORKD, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag.
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c This is for the restart phase to force the new
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y,
c IPNTR(3) is the pointer into WORK for B * X.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c IDO = 99: done
c -------------------------------------------------------------
c When the routine is used in the "shift-and-invert" mode, the
c vector B * Q is already available and does not need to be
c recomputed in forming OP * Q.
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of matrix B that defines the
c semi-inner product for the operator OP. See ssaupd.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*M*x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c K Integer. (INPUT)
c Current order of H and the number of columns of V.
c
c NP Integer. (INPUT)
c Number of additional Arnoldi steps to take.
c
c MODE Integer. (INPUT)
c Signifies which form for "OP". If MODE=2 then
c a reduction in the number of B matrix vector multiplies
c is possible since the B-norm of OP*x is equivalent to
c the inv(B)-norm of A*x.
c
c RESID Real array of length N. (INPUT/OUTPUT)
c On INPUT: RESID contains the residual vector r_{k}.
c On OUTPUT: RESID contains the residual vector r_{k+p}.
c
c RNORM Real scalar. (INPUT/OUTPUT)
c On INPUT the B-norm of r_{k}.
c On OUTPUT the B-norm of the updated residual r_{k+p}.
c
c V Real N by K+NP array. (INPUT/OUTPUT)
c On INPUT: V contains the Arnoldi vectors in the first K
c columns.
c On OUTPUT: V contains the new NP Arnoldi vectors in the next
c NP columns. The first K columns are unchanged.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Real (K+NP) by 2 array. (INPUT/OUTPUT)
c H is used to store the generated symmetric tridiagonal matrix
c with the subdiagonal in the first column starting at H(2,1)
c and the main diagonal in the second column.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORK for
c vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in the
c shift-and-invert mode. X is the current operand.
c -------------------------------------------------------------
c
c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The calling program should not
c use WORKD as temporary workspace during the iteration !!!!!!
c On INPUT, WORKD(1:N) = B*RESID where RESID is associated
c with the K step Arnoldi factorization. Used to save some
c computation at the first step.
c On OUTPUT, WORKD(1:N) = B*RESID where RESID is associated
c with the K+NP step Arnoldi factorization.
c
c INFO Integer. (OUTPUT)
c = 0: Normal exit.
c > 0: Size of an invariant subspace of OP is found that is
c less than K + NP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c sgetv0 ARPACK routine to generate the initial vector.
c ivout ARPACK utility routine that prints integers.
c smout ARPACK utility routine that prints matrices.
c svout ARPACK utility routine that prints vectors.
c slamch LAPACK routine that determines machine constants.
c slascl LAPACK routine for careful scaling of a matrix.
c sgemv Level 2 BLAS routine for matrix vector multiplication.
c saxpy Level 1 BLAS that computes a vector triad.
c sscal Level 1 BLAS that scales a vector.
c scopy Level 1 BLAS that copies one vector to another .
c sdot Level 1 BLAS that computes the scalar product of two vectors.
c snrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/93: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: saitr.F SID: 2.6 DATE OF SID: 8/28/96 RELEASE: 2
c
c\Remarks
c The algorithm implemented is:
c
c restart = .false.
c Given V_{k} = [v_{1}, ..., v_{k}], r_{k};
c r_{k} contains the initial residual vector even for k = 0;
c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already
c computed by the calling program.
c
c betaj = rnorm ; p_{k+1} = B*r_{k} ;
c For j = k+1, ..., k+np Do
c 1) if ( betaj < tol ) stop or restart depending on j.
c if ( restart ) generate a new starting vector.
c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}];
c p_{j} = p_{j}/betaj
c 3) r_{j} = OP*v_{j} where OP is defined as in ssaupd
c For shift-invert mode p_{j} = B*v_{j} is already available.
c wnorm = || OP*v_{j} ||
c 4) Compute the j-th step residual vector.
c w_{j} = V_{j}^T * B * OP * v_{j}
c r_{j} = OP*v_{j} - V_{j} * w_{j}
c alphaj <- j-th component of w_{j}
c rnorm = || r_{j} ||
c betaj+1 = rnorm
c If (rnorm > 0.717*wnorm) accept step and go back to 1)
c 5) Re-orthogonalization step:
c s = V_{j}'*B*r_{j}
c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} ||
c alphaj = alphaj + s_{j};
c 6) Iterative refinement step:
c If (rnorm1 > 0.717*rnorm) then
c rnorm = rnorm1
c accept step and go back to 1)
c Else
c rnorm = rnorm1
c If this is the first time in step 6), go to 5)
c Else r_{j} lies in the span of V_{j} numerically.
c Set r_{j} = 0 and rnorm = 0; go to 1)
c EndIf
c End Do
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine ssaitr
& (ido, bmat, n, k, np, mode, resid, rnorm, v, ldv, h, ldh,
& ipntr, workd, info)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1
integer ido, info, k, ldh, ldv, n, mode, np
Real
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Real
& h(ldh,2), resid(n), v(ldv,k+np), workd(3*n)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0, zero = 0.0E+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
logical first, orth1, orth2, rstart, step3, step4
integer i, ierr, ipj, irj, ivj, iter, itry, j, msglvl,
& infol, jj
Real
& rnorm1, wnorm, safmin, temp1
save orth1, orth2, rstart, step3, step4,
& ierr, ipj, irj, ivj, iter, itry, j, msglvl,
& rnorm1, safmin, wnorm
c
c %-----------------------%
c | Local Array Arguments |
c %-----------------------%
c
Real
& xtemp(2)
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external saxpy, scopy, sscal, sgemv, sgetv0, svout, smout,
& slascl, ivout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& sdot, snrm2, slamch
external sdot, snrm2, slamch
c
c %-----------------%
c | Data statements |
c %-----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
first = .false.
c
c %--------------------------------%
c | safmin = safe minimum is such |
c | that 1/sfmin does not overflow |
c %--------------------------------%
c
safmin = slamch('safmin')
end if
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = msaitr
c
c %------------------------------%
c | Initial call to this routine |
c %------------------------------%
c
info = 0
step3 = .false.
step4 = .false.
rstart = .false.
orth1 = .false.
orth2 = .false.
c
c %--------------------------------%
c | Pointer to the current step of |
c | the factorization to build |
c %--------------------------------%
c
j = k + 1
c
c %------------------------------------------%
c | Pointers used for reverse communication |
c | when using WORKD. |
c %------------------------------------------%
c
ipj = 1
irj = ipj + n
ivj = irj + n
end if
c
c %-------------------------------------------------%
c | When in reverse communication mode one of: |
c | STEP3, STEP4, ORTH1, ORTH2, RSTART |
c | will be .true. |
c | STEP3: return from computing OP*v_{j}. |
c | STEP4: return from computing B-norm of OP*v_{j} |
c | ORTH1: return from computing B-norm of r_{j+1} |
c | ORTH2: return from computing B-norm of |
c | correction to the residual vector. |
c | RSTART: return from OP computations needed by |
c | sgetv0. |
c %-------------------------------------------------%
c
if (step3) go to 50
if (step4) go to 60
if (orth1) go to 70
if (orth2) go to 90
if (rstart) go to 30
c
c %------------------------------%
c | Else this is the first step. |
c %------------------------------%
c
c %--------------------------------------------------------------%
c | |
c | A R N O L D I I T E R A T I O N L O O P |
c | |
c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) |
c %--------------------------------------------------------------%
c
1000 continue
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, j, ndigit,
& '_saitr: generating Arnoldi vector no.')
call svout (logfil, 1, rnorm, ndigit,
& '_saitr: B-norm of the current residual =')
end if
c
c %---------------------------------------------------------%
c | Check for exact zero. Equivalent to determing whether a |
c | j-step Arnoldi factorization is present. |
c %---------------------------------------------------------%
c
if (rnorm .gt. zero) go to 40
c
c %---------------------------------------------------%
c | Invariant subspace found, generate a new starting |
c | vector which is orthogonal to the current Arnoldi |
c | basis and continue the iteration. |
c %---------------------------------------------------%
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, j, ndigit,
& '_saitr: ****** restart at step ******')
end if
c
c %---------------------------------------------%
c | ITRY is the loop variable that controls the |
c | maximum amount of times that a restart is |
c | attempted. NRSTRT is used by stat.h |
c %---------------------------------------------%
c
nrstrt = nrstrt + 1
itry = 1
20 continue
rstart = .true.
ido = 0
30 continue
c
c %--------------------------------------%
c | If in reverse communication mode and |
c | RSTART = .true. flow returns here. |
c %--------------------------------------%
c
call sgetv0 (ido, bmat, itry, .false., n, j, v, ldv,
& resid, rnorm, ipntr, workd, ierr)
if (ido .ne. 99) go to 9000
if (ierr .lt. 0) then
itry = itry + 1
if (itry .le. 3) go to 20
c
c %------------------------------------------------%
c | Give up after several restart attempts. |
c | Set INFO to the size of the invariant subspace |
c | which spans OP and exit. |
c %------------------------------------------------%
c
info = j - 1
call second (t1)
tsaitr = tsaitr + (t1 - t0)
ido = 99
go to 9000
end if
c
40 continue
c
c %---------------------------------------------------------%
c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm |
c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow |
c | when reciprocating a small RNORM, test against lower |
c | machine bound. |
c %---------------------------------------------------------%
c
call scopy (n, resid, 1, v(1,j), 1)
if (rnorm .ge. safmin) then
temp1 = one / rnorm
call sscal (n, temp1, v(1,j), 1)
call sscal (n, temp1, workd(ipj), 1)
else
c
c %-----------------------------------------%
c | To scale both v_{j} and p_{j} carefully |
c | use LAPACK routine SLASCL |
c %-----------------------------------------%
c
call slascl ('General', i, i, rnorm, one, n, 1,
& v(1,j), n, infol)
call slascl ('General', i, i, rnorm, one, n, 1,
& workd(ipj), n, infol)
end if
c
c %------------------------------------------------------%
c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} |
c | Note that this is not quite yet r_{j}. See STEP 4 |
c %------------------------------------------------------%
c
step3 = .true.
nopx = nopx + 1
call second (t2)
call scopy (n, v(1,j), 1, workd(ivj), 1)
ipntr(1) = ivj
ipntr(2) = irj
ipntr(3) = ipj
ido = 1
c
c %-----------------------------------%
c | Exit in order to compute OP*v_{j} |
c %-----------------------------------%
c
go to 9000
50 continue
c
c %-----------------------------------%
c | Back from reverse communication; |
c | WORKD(IRJ:IRJ+N-1) := OP*v_{j}. |
c %-----------------------------------%
c
call second (t3)
tmvopx = tmvopx + (t3 - t2)
c
step3 = .false.
c
c %------------------------------------------%
c | Put another copy of OP*v_{j} into RESID. |
c %------------------------------------------%
c
call scopy (n, workd(irj), 1, resid, 1)
c
c %-------------------------------------------%
c | STEP 4: Finish extending the symmetric |
c | Arnoldi to length j. If MODE = 2 |
c | then B*OP = B*inv(B)*A = A and |
c | we don't need to compute B*OP. |
c | NOTE: If MODE = 2 WORKD(IVJ:IVJ+N-1) is |
c | assumed to have A*v_{j}. |
c %-------------------------------------------%
c
if (mode .eq. 2) go to 65
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
step4 = .true.
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-------------------------------------%
c | Exit in order to compute B*OP*v_{j} |
c %-------------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call scopy(n, resid, 1 , workd(ipj), 1)
end if
60 continue
c
c %-----------------------------------%
c | Back from reverse communication; |
c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j}. |
c %-----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
step4 = .false.
c
c %-------------------------------------%
c | The following is needed for STEP 5. |
c | Compute the B-norm of OP*v_{j}. |
c %-------------------------------------%
c
65 continue
if (mode .eq. 2) then
c
c %----------------------------------%
c | Note that the B-norm of OP*v_{j} |
c | is the inv(B)-norm of A*v_{j}. |
c %----------------------------------%
c
wnorm = sdot (n, resid, 1, workd(ivj), 1)
wnorm = sqrt(abs(wnorm))
else if (bmat .eq. 'G') then
wnorm = sdot (n, resid, 1, workd(ipj), 1)
wnorm = sqrt(abs(wnorm))
else if (bmat .eq. 'I') then
wnorm = snrm2(n, resid, 1)
end if
c
c %-----------------------------------------%
c | Compute the j-th residual corresponding |
c | to the j step factorization. |
c | Use Classical Gram Schmidt and compute: |
c | w_{j} <- V_{j}^T * B * OP * v_{j} |
c | r_{j} <- OP*v_{j} - V_{j} * w_{j} |
c %-----------------------------------------%
c
c
c %------------------------------------------%
c | Compute the j Fourier coefficients w_{j} |
c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. |
c %------------------------------------------%
c
if (mode .ne. 2 ) then
call sgemv('T', n, j, one, v, ldv, workd(ipj), 1, zero,
& workd(irj), 1)
else if (mode .eq. 2) then
call sgemv('T', n, j, one, v, ldv, workd(ivj), 1, zero,
& workd(irj), 1)
end if
c
c %--------------------------------------%
c | Orthgonalize r_{j} against V_{j}. |
c | RESID contains OP*v_{j}. See STEP 3. |
c %--------------------------------------%
c
call sgemv('N', n, j, -one, v, ldv, workd(irj), 1, one,
& resid, 1)
c
c %--------------------------------------%
c | Extend H to have j rows and columns. |
c %--------------------------------------%
c
h(j,2) = workd(irj + j - 1)
if (j .eq. 1 .or. rstart) then
h(j,1) = zero
else
h(j,1) = rnorm
end if
call second (t4)
c
orth1 = .true.
iter = 0
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call scopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*r_{j} |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call scopy (n, resid, 1, workd(ipj), 1)
end if
70 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH1 = .true. |
c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
orth1 = .false.
c
c %------------------------------%
c | Compute the B-norm of r_{j}. |
c %------------------------------%
c
if (bmat .eq. 'G') then
rnorm = sdot (n, resid, 1, workd(ipj), 1)
rnorm = sqrt(abs(rnorm))
else if (bmat .eq. 'I') then
rnorm = snrm2(n, resid, 1)
end if
c
c %-----------------------------------------------------------%
c | STEP 5: Re-orthogonalization / Iterative refinement phase |
c | Maximum NITER_ITREF tries. |
c | |
c | s = V_{j}^T * B * r_{j} |
c | r_{j} = r_{j} - V_{j}*s |
c | alphaj = alphaj + s_{j} |
c | |
c | The stopping criteria used for iterative refinement is |
c | discussed in Parlett's book SEP, page 107 and in Gragg & |
c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. |
c | Determine if we need to correct the residual. The goal is |
c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || |
c %-----------------------------------------------------------%
c
if (rnorm .gt. 0.717*wnorm) go to 100
nrorth = nrorth + 1
c
c %---------------------------------------------------%
c | Enter the Iterative refinement phase. If further |
c | refinement is necessary, loop back here. The loop |
c | variable is ITER. Perform a step of Classical |
c | Gram-Schmidt using all the Arnoldi vectors V_{j} |
c %---------------------------------------------------%
c
80 continue
c
if (msglvl .gt. 2) then
xtemp(1) = wnorm
xtemp(2) = rnorm
call svout (logfil, 2, xtemp, ndigit,
& '_saitr: re-orthonalization ; wnorm and rnorm are')
end if
c
c %----------------------------------------------------%
c | Compute V_{j}^T * B * r_{j}. |
c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). |
c %----------------------------------------------------%
c
call sgemv ('T', n, j, one, v, ldv, workd(ipj), 1,
& zero, workd(irj), 1)
c
c %----------------------------------------------%
c | Compute the correction to the residual: |
c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). |
c | The correction to H is v(:,1:J)*H(1:J,1:J) + |
c | v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j, but only |
c | H(j,j) is updated. |
c %----------------------------------------------%
c
call sgemv ('N', n, j, -one, v, ldv, workd(irj), 1,
& one, resid, 1)
c
if (j .eq. 1 .or. rstart) h(j,1) = zero
h(j,2) = h(j,2) + workd(irj + j - 1)
c
orth2 = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call scopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-----------------------------------%
c | Exit in order to compute B*r_{j}. |
c | r_{j} is the corrected residual. |
c %-----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call scopy (n, resid, 1, workd(ipj), 1)
end if
90 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH2 = .true. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
c %-----------------------------------------------------%
c | Compute the B-norm of the corrected residual r_{j}. |
c %-----------------------------------------------------%
c
if (bmat .eq. 'G') then
rnorm1 = sdot (n, resid, 1, workd(ipj), 1)
rnorm1 = sqrt(abs(rnorm1))
else if (bmat .eq. 'I') then
rnorm1 = snrm2(n, resid, 1)
end if
c
if (msglvl .gt. 0 .and. iter .gt. 0) then
call ivout (logfil, 1, j, ndigit,
& '_saitr: Iterative refinement for Arnoldi residual')
if (msglvl .gt. 2) then
xtemp(1) = rnorm
xtemp(2) = rnorm1
call svout (logfil, 2, xtemp, ndigit,
& '_saitr: iterative refinement ; rnorm and rnorm1 are')
end if
end if
c
c %-----------------------------------------%
c | Determine if we need to perform another |
c | step of re-orthogonalization. |
c %-----------------------------------------%
c
if (rnorm1 .gt. 0.717*rnorm) then
c
c %--------------------------------%
c | No need for further refinement |
c %--------------------------------%
c
rnorm = rnorm1
c
else
c
c %-------------------------------------------%
c | Another step of iterative refinement step |
c | is required. NITREF is used by stat.h |
c %-------------------------------------------%
c
nitref = nitref + 1
rnorm = rnorm1
iter = iter + 1
if (iter .le. 1) go to 80
c
c %-------------------------------------------------%
c | Otherwise RESID is numerically in the span of V |
c %-------------------------------------------------%
c
do 95 jj = 1, n
resid(jj) = zero
95 continue
rnorm = zero
end if
c
c %----------------------------------------------%
c | Branch here directly if iterative refinement |
c | wasn't necessary or after at most NITER_REF |
c | steps of iterative refinement. |
c %----------------------------------------------%
c
100 continue
c
rstart = .false.
orth2 = .false.
c
call second (t5)
titref = titref + (t5 - t4)
c
c %----------------------------------------------------------%
c | Make sure the last off-diagonal element is non negative |
c | If not perform a similarity transformation on H(1:j,1:j) |
c | and scale v(:,j) by -1. |
c %----------------------------------------------------------%
c
if (h(j,1) .lt. zero) then
h(j,1) = -h(j,1)
if ( j .lt. k+np) then
call sscal(n, -one, v(1,j+1), 1)
else
call sscal(n, -one, resid, 1)
end if
end if
c
c %------------------------------------%
c | STEP 6: Update j = j+1; Continue |
c %------------------------------------%
c
j = j + 1
if (j .gt. k+np) then
call second (t1)
tsaitr = tsaitr + (t1 - t0)
ido = 99
c
if (msglvl .gt. 1) then
call svout (logfil, k+np, h(1,2), ndigit,
& '_saitr: main diagonal of matrix H of step K+NP.')
if (k+np .gt. 1) then
call svout (logfil, k+np-1, h(2,1), ndigit,
& '_saitr: sub diagonal of matrix H of step K+NP.')
end if
end if
c
go to 9000
end if
c
c %--------------------------------------------------------%
c | Loop back to extend the factorization by another step. |
c %--------------------------------------------------------%
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
9000 continue
return
c
c %---------------%
c | End of ssaitr |
c %---------------%
c
end

516
arpack/ARPACK/SRC/ssapps.f Normal file
View File

@@ -0,0 +1,516 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: ssapps
c
c\Description:
c Given the Arnoldi factorization
c
c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T,
c
c apply NP shifts implicitly resulting in
c
c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q
c
c where Q is an orthogonal matrix of order KEV+NP. Q is the product of
c rotations resulting from the NP bulge chasing sweeps. The updated Arnoldi
c factorization becomes:
c
c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T.
c
c\Usage:
c call ssapps
c ( N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ, WORKD )
c
c\Arguments
c N Integer. (INPUT)
c Problem size, i.e. dimension of matrix A.
c
c KEV Integer. (INPUT)
c INPUT: KEV+NP is the size of the input matrix H.
c OUTPUT: KEV is the size of the updated matrix HNEW.
c
c NP Integer. (INPUT)
c Number of implicit shifts to be applied.
c
c SHIFT Real array of length NP. (INPUT)
c The shifts to be applied.
c
c V Real N by (KEV+NP) array. (INPUT/OUTPUT)
c INPUT: V contains the current KEV+NP Arnoldi vectors.
c OUTPUT: VNEW = V(1:n,1:KEV); the updated Arnoldi vectors
c are in the first KEV columns of V.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Real (KEV+NP) by 2 array. (INPUT/OUTPUT)
c INPUT: H contains the symmetric tridiagonal matrix of the
c Arnoldi factorization with the subdiagonal in the 1st column
c starting at H(2,1) and the main diagonal in the 2nd column.
c OUTPUT: H contains the updated tridiagonal matrix in the
c KEV leading submatrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RESID Real array of length (N). (INPUT/OUTPUT)
c INPUT: RESID contains the the residual vector r_{k+p}.
c OUTPUT: RESID is the updated residual vector rnew_{k}.
c
c Q Real KEV+NP by KEV+NP work array. (WORKSPACE)
c Work array used to accumulate the rotations during the bulge
c chase sweep.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKD Real work array of length 2*N. (WORKSPACE)
c Distributed array used in the application of the accumulated
c orthogonal matrix Q.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c svout ARPACK utility routine that prints vectors.
c slamch LAPACK routine that determines machine constants.
c slartg LAPACK Givens rotation construction routine.
c slacpy LAPACK matrix copy routine.
c slaset LAPACK matrix initialization routine.
c sgemv Level 2 BLAS routine for matrix vector multiplication.
c saxpy Level 1 BLAS that computes a vector triad.
c scopy Level 1 BLAS that copies one vector to another.
c sscal Level 1 BLAS that scales a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/16/93: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: sapps.F SID: 2.6 DATE OF SID: 3/28/97 RELEASE: 2
c
c\Remarks
c 1. In this version, each shift is applied to all the subblocks of
c the tridiagonal matrix H and not just to the submatrix that it
c comes from. This routine assumes that the subdiagonal elements
c of H that are stored in h(1:kev+np,1) are nonegative upon input
c and enforce this condition upon output. This version incorporates
c deflation. See code for documentation.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine ssapps
& ( n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq, workd )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer kev, ldh, ldq, ldv, n, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& h(ldh,2), q(ldq,kev+np), resid(n), shift(np),
& v(ldv,kev+np), workd(2*n)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0, zero = 0.0E+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, iend, istart, itop, j, jj, kplusp, msglvl
logical first
Real
& a1, a2, a3, a4, big, c, epsmch, f, g, r, s
save epsmch, first
c
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external saxpy, scopy, sscal, slacpy, slartg, slaset, svout,
& ivout, second, sgemv
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& slamch
external slamch
c
c %----------------------%
c | Intrinsics Functions |
c %----------------------%
c
intrinsic abs
c
c %----------------%
c | Data statments |
c %----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
epsmch = slamch('Epsilon-Machine')
first = .false.
end if
itop = 1
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = msapps
c
kplusp = kev + np
c
c %----------------------------------------------%
c | Initialize Q to the identity matrix of order |
c | kplusp used to accumulate the rotations. |
c %----------------------------------------------%
c
call slaset ('All', kplusp, kplusp, zero, one, q, ldq)
c
c %----------------------------------------------%
c | Quick return if there are no shifts to apply |
c %----------------------------------------------%
c
if (np .eq. 0) go to 9000
c
c %----------------------------------------------------------%
c | Apply the np shifts implicitly. Apply each shift to the |
c | whole matrix and not just to the submatrix from which it |
c | comes. |
c %----------------------------------------------------------%
c
do 90 jj = 1, np
c
istart = itop
c
c %----------------------------------------------------------%
c | Check for splitting and deflation. Currently we consider |
c | an off-diagonal element h(i+1,1) negligible if |
c | h(i+1,1) .le. epsmch*( |h(i,2)| + |h(i+1,2)| ) |
c | for i=1:KEV+NP-1. |
c | If above condition tests true then we set h(i+1,1) = 0. |
c | Note that h(1:KEV+NP,1) are assumed to be non negative. |
c %----------------------------------------------------------%
c
20 continue
c
c %------------------------------------------------%
c | The following loop exits early if we encounter |
c | a negligible off diagonal element. |
c %------------------------------------------------%
c
do 30 i = istart, kplusp-1
big = abs(h(i,2)) + abs(h(i+1,2))
if (h(i+1,1) .le. epsmch*big) then
if (msglvl .gt. 0) then
call ivout (logfil, 1, i, ndigit,
& '_sapps: deflation at row/column no.')
call ivout (logfil, 1, jj, ndigit,
& '_sapps: occured before shift number.')
call svout (logfil, 1, h(i+1,1), ndigit,
& '_sapps: the corresponding off diagonal element')
end if
h(i+1,1) = zero
iend = i
go to 40
end if
30 continue
iend = kplusp
40 continue
c
if (istart .lt. iend) then
c
c %--------------------------------------------------------%
c | Construct the plane rotation G'(istart,istart+1,theta) |
c | that attempts to drive h(istart+1,1) to zero. |
c %--------------------------------------------------------%
c
f = h(istart,2) - shift(jj)
g = h(istart+1,1)
call slartg (f, g, c, s, r)
c
c %-------------------------------------------------------%
c | Apply rotation to the left and right of H; |
c | H <- G' * H * G, where G = G(istart,istart+1,theta). |
c | This will create a "bulge". |
c %-------------------------------------------------------%
c
a1 = c*h(istart,2) + s*h(istart+1,1)
a2 = c*h(istart+1,1) + s*h(istart+1,2)
a4 = c*h(istart+1,2) - s*h(istart+1,1)
a3 = c*h(istart+1,1) - s*h(istart,2)
h(istart,2) = c*a1 + s*a2
h(istart+1,2) = c*a4 - s*a3
h(istart+1,1) = c*a3 + s*a4
c
c %----------------------------------------------------%
c | Accumulate the rotation in the matrix Q; Q <- Q*G |
c %----------------------------------------------------%
c
do 60 j = 1, min(istart+jj,kplusp)
a1 = c*q(j,istart) + s*q(j,istart+1)
q(j,istart+1) = - s*q(j,istart) + c*q(j,istart+1)
q(j,istart) = a1
60 continue
c
c
c %----------------------------------------------%
c | The following loop chases the bulge created. |
c | Note that the previous rotation may also be |
c | done within the following loop. But it is |
c | kept separate to make the distinction among |
c | the bulge chasing sweeps and the first plane |
c | rotation designed to drive h(istart+1,1) to |
c | zero. |
c %----------------------------------------------%
c
do 70 i = istart+1, iend-1
c
c %----------------------------------------------%
c | Construct the plane rotation G'(i,i+1,theta) |
c | that zeros the i-th bulge that was created |
c | by G(i-1,i,theta). g represents the bulge. |
c %----------------------------------------------%
c
f = h(i,1)
g = s*h(i+1,1)
c
c %----------------------------------%
c | Final update with G(i-1,i,theta) |
c %----------------------------------%
c
h(i+1,1) = c*h(i+1,1)
call slartg (f, g, c, s, r)
c
c %-------------------------------------------%
c | The following ensures that h(1:iend-1,1), |
c | the first iend-2 off diagonal of elements |
c | H, remain non negative. |
c %-------------------------------------------%
c
if (r .lt. zero) then
r = -r
c = -c
s = -s
end if
c
c %--------------------------------------------%
c | Apply rotation to the left and right of H; |
c | H <- G * H * G', where G = G(i,i+1,theta) |
c %--------------------------------------------%
c
h(i,1) = r
c
a1 = c*h(i,2) + s*h(i+1,1)
a2 = c*h(i+1,1) + s*h(i+1,2)
a3 = c*h(i+1,1) - s*h(i,2)
a4 = c*h(i+1,2) - s*h(i+1,1)
c
h(i,2) = c*a1 + s*a2
h(i+1,2) = c*a4 - s*a3
h(i+1,1) = c*a3 + s*a4
c
c %----------------------------------------------------%
c | Accumulate the rotation in the matrix Q; Q <- Q*G |
c %----------------------------------------------------%
c
do 50 j = 1, min( i+jj, kplusp )
a1 = c*q(j,i) + s*q(j,i+1)
q(j,i+1) = - s*q(j,i) + c*q(j,i+1)
q(j,i) = a1
50 continue
c
70 continue
c
end if
c
c %--------------------------%
c | Update the block pointer |
c %--------------------------%
c
istart = iend + 1
c
c %------------------------------------------%
c | Make sure that h(iend,1) is non-negative |
c | If not then set h(iend,1) <-- -h(iend,1) |
c | and negate the last column of Q. |
c | We have effectively carried out a |
c | similarity on transformation H |
c %------------------------------------------%
c
if (h(iend,1) .lt. zero) then
h(iend,1) = -h(iend,1)
call sscal(kplusp, -one, q(1,iend), 1)
end if
c
c %--------------------------------------------------------%
c | Apply the same shift to the next block if there is any |
c %--------------------------------------------------------%
c
if (iend .lt. kplusp) go to 20
c
c %-----------------------------------------------------%
c | Check if we can increase the the start of the block |
c %-----------------------------------------------------%
c
do 80 i = itop, kplusp-1
if (h(i+1,1) .gt. zero) go to 90
itop = itop + 1
80 continue
c
c %-----------------------------------%
c | Finished applying the jj-th shift |
c %-----------------------------------%
c
90 continue
c
c %------------------------------------------%
c | All shifts have been applied. Check for |
c | more possible deflation that might occur |
c | after the last shift is applied. |
c %------------------------------------------%
c
do 100 i = itop, kplusp-1
big = abs(h(i,2)) + abs(h(i+1,2))
if (h(i+1,1) .le. epsmch*big) then
if (msglvl .gt. 0) then
call ivout (logfil, 1, i, ndigit,
& '_sapps: deflation at row/column no.')
call svout (logfil, 1, h(i+1,1), ndigit,
& '_sapps: the corresponding off diagonal element')
end if
h(i+1,1) = zero
end if
100 continue
c
c %-------------------------------------------------%
c | Compute the (kev+1)-st column of (V*Q) and |
c | temporarily store the result in WORKD(N+1:2*N). |
c | This is not necessary if h(kev+1,1) = 0. |
c %-------------------------------------------------%
c
if ( h(kev+1,1) .gt. zero )
& call sgemv ('N', n, kplusp, one, v, ldv,
& q(1,kev+1), 1, zero, workd(n+1), 1)
c
c %-------------------------------------------------------%
c | Compute column 1 to kev of (V*Q) in backward order |
c | taking advantage that Q is an upper triangular matrix |
c | with lower bandwidth np. |
c | Place results in v(:,kplusp-kev:kplusp) temporarily. |
c %-------------------------------------------------------%
c
do 130 i = 1, kev
call sgemv ('N', n, kplusp-i+1, one, v, ldv,
& q(1,kev-i+1), 1, zero, workd, 1)
call scopy (n, workd, 1, v(1,kplusp-i+1), 1)
130 continue
c
c %-------------------------------------------------%
c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). |
c %-------------------------------------------------%
c
call slacpy ('All', n, kev, v(1,np+1), ldv, v, ldv)
c
c %--------------------------------------------%
c | Copy the (kev+1)-st column of (V*Q) in the |
c | appropriate place if h(kev+1,1) .ne. zero. |
c %--------------------------------------------%
c
if ( h(kev+1,1) .gt. zero )
& call scopy (n, workd(n+1), 1, v(1,kev+1), 1)
c
c %-------------------------------------%
c | Update the residual vector: |
c | r <- sigmak*r + betak*v(:,kev+1) |
c | where |
c | sigmak = (e_{kev+p}'*Q)*e_{kev} |
c | betak = e_{kev+1}'*H*e_{kev} |
c %-------------------------------------%
c
call sscal (n, q(kplusp,kev), resid, 1)
if (h(kev+1,1) .gt. zero)
& call saxpy (n, h(kev+1,1), v(1,kev+1), 1, resid, 1)
c
if (msglvl .gt. 1) then
call svout (logfil, 1, q(kplusp,kev), ndigit,
& '_sapps: sigmak of the updated residual vector')
call svout (logfil, 1, h(kev+1,1), ndigit,
& '_sapps: betak of the updated residual vector')
call svout (logfil, kev, h(1,2), ndigit,
& '_sapps: updated main diagonal of H for next iteration')
if (kev .gt. 1) then
call svout (logfil, kev-1, h(2,1), ndigit,
& '_sapps: updated sub diagonal of H for next iteration')
end if
end if
c
call second (t1)
tsapps = tsapps + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of ssapps |
c %---------------%
c
end

850
arpack/ARPACK/SRC/ssaup2.f Normal file
View File

@@ -0,0 +1,850 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: ssaup2
c
c\Description:
c Intermediate level interface called by ssaupd.
c
c\Usage:
c call ssaup2
c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD,
c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL,
c IPNTR, WORKD, INFO )
c
c\Arguments
c
c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in ssaupd.
c MODE, ISHIFT, MXITER: see the definition of IPARAM in ssaupd.
c
c NP Integer. (INPUT/OUTPUT)
c Contains the number of implicit shifts to apply during
c each Arnoldi/Lanczos iteration.
c If ISHIFT=1, NP is adjusted dynamically at each iteration
c to accelerate convergence and prevent stagnation.
c This is also roughly equal to the number of matrix-vector
c products (involving the operator OP) per Arnoldi iteration.
c The logic for adjusting is contained within the current
c subroutine.
c If ISHIFT=0, NP is the number of shifts the user needs
c to provide via reverse comunication. 0 < NP < NCV-NEV.
c NP may be less than NCV-NEV since a leading block of the current
c upper Tridiagonal matrix has split off and contains "unwanted"
c Ritz values.
c Upon termination of the IRA iteration, NP contains the number
c of "converged" wanted Ritz values.
c
c IUPD Integer. (INPUT)
c IUPD .EQ. 0: use explicit restart instead implicit update.
c IUPD .NE. 0: use implicit update.
c
c V Real N by (NEV+NP) array. (INPUT/OUTPUT)
c The Lanczos basis vectors.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Real (NEV+NP) by 2 array. (OUTPUT)
c H is used to store the generated symmetric tridiagonal matrix
c The subdiagonal is stored in the first column of H starting
c at H(2,1). The main diagonal is stored in the second column
c of H starting at H(1,2). If ssaup2 converges store the
c B-norm of the final residual vector in H(1,1).
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RITZ Real array of length NEV+NP. (OUTPUT)
c RITZ(1:NEV) contains the computed Ritz values of OP.
c
c BOUNDS Real array of length NEV+NP. (OUTPUT)
c BOUNDS(1:NEV) contain the error bounds corresponding to RITZ.
c
c Q Real (NEV+NP) by (NEV+NP) array. (WORKSPACE)
c Private (replicated) work array used to accumulate the
c rotation in the shift application step.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Real array of length at least 3*(NEV+NP). (INPUT/WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. It is used in the computation of the
c tridiagonal eigenvalue problem, the calculation and
c application of the shifts and convergence checking.
c If ISHIFT .EQ. O and IDO .EQ. 3, the first NP locations
c of WORKL are used in reverse communication to hold the user
c supplied shifts.
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORKD for
c vectors used by the Lanczos iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in one of
c the spectral transformation modes. X is the current
c operand.
c -------------------------------------------------------------
c
c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Lanczos iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration !!!!!!!!!!
c See Data Distribution Note in ssaupd.
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal return.
c = 1: All possible eigenvalues of OP has been found.
c NP returns the size of the invariant subspace
c spanning the operator OP.
c = 2: No shifts could be applied.
c = -8: Error return from trid. eigenvalue calculation;
c This should never happen.
c = -9: Starting vector is zero.
c = -9999: Could not build an Lanczos factorization.
c Size that was built in returned in NP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall,
c 1980.
c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program",
c Computer Physics Communications, 53 (1989), pp 169-179.
c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to
c Implement the Spectral Transformation", Math. Comp., 48 (1987),
c pp 663-673.
c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos
c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems",
c SIAM J. Matr. Anal. Apps., January (1993).
c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines
c for Updating the QR decomposition", ACM TOMS, December 1990,
c Volume 16 Number 4, pp 369-377.
c
c\Routines called:
c sgetv0 ARPACK initial vector generation routine.
c ssaitr ARPACK Lanczos factorization routine.
c ssapps ARPACK application of implicit shifts routine.
c ssconv ARPACK convergence of Ritz values routine.
c sseigt ARPACK compute Ritz values and error bounds routine.
c ssgets ARPACK reorder Ritz values and error bounds routine.
c ssortr ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c svout ARPACK utility routine that prints vectors.
c slamch LAPACK routine that determines machine constants.
c scopy Level 1 BLAS that copies one vector to another.
c sdot Level 1 BLAS that computes the scalar product of two vectors.
c snrm2 Level 1 BLAS that computes the norm of a vector.
c sscal Level 1 BLAS that scales a vector.
c sswap Level 1 BLAS that swaps two vectors.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/15/93: Version ' 2.4'
c xx/xx/95: Version ' 2.4'. (R.B. Lehoucq)
c
c\SCCS Information: @(#)
c FILE: saup2.F SID: 2.7 DATE OF SID: 5/19/98 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine ssaup2
& ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, h, ldh, ritz, bounds,
& q, ldq, workl, ipntr, workd, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ishift, iupd, ldh, ldq, ldv, mxiter,
& n, mode, nev, np
Real
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Real
& bounds(nev+np), h(ldh,2), q(ldq,nev+np), resid(n),
& ritz(nev+np), v(ldv,nev+np), workd(3*n),
& workl(3*(nev+np))
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0, zero = 0.0E+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
character wprime*2
logical cnorm, getv0, initv, update, ushift
integer ierr, iter, j, kplusp, msglvl, nconv, nevbef, nev0,
& np0, nptemp, nevd2, nevm2, kp(3)
Real
& rnorm, temp, eps23
save cnorm, getv0, initv, update, ushift,
& iter, kplusp, msglvl, nconv, nev0, np0,
& rnorm, eps23
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external scopy, sgetv0, ssaitr, sscal, ssconv, sseigt, ssgets,
& ssapps, ssortr, svout, ivout, second, sswap
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& sdot, snrm2, slamch
external sdot, snrm2, slamch
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic min
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = msaup2
c
c %---------------------------------%
c | Set machine dependent constant. |
c %---------------------------------%
c
eps23 = slamch('Epsilon-Machine')
eps23 = eps23**(2.0E+0/3.0E+0)
c
c %-------------------------------------%
c | nev0 and np0 are integer variables |
c | hold the initial values of NEV & NP |
c %-------------------------------------%
c
nev0 = nev
np0 = np
c
c %-------------------------------------%
c | kplusp is the bound on the largest |
c | Lanczos factorization built. |
c | nconv is the current number of |
c | "converged" eigenvlues. |
c | iter is the counter on the current |
c | iteration step. |
c %-------------------------------------%
c
kplusp = nev0 + np0
nconv = 0
iter = 0
c
c %--------------------------------------------%
c | Set flags for computing the first NEV steps |
c | of the Lanczos factorization. |
c %--------------------------------------------%
c
getv0 = .true.
update = .false.
ushift = .false.
cnorm = .false.
c
if (info .ne. 0) then
c
c %--------------------------------------------%
c | User provides the initial residual vector. |
c %--------------------------------------------%
c
initv = .true.
info = 0
else
initv = .false.
end if
end if
c
c %---------------------------------------------%
c | Get a possibly random starting vector and |
c | force it into the range of the operator OP. |
c %---------------------------------------------%
c
10 continue
c
if (getv0) then
call sgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm,
& ipntr, workd, info)
c
if (ido .ne. 99) go to 9000
c
if (rnorm .eq. zero) then
c
c %-----------------------------------------%
c | The initial vector is zero. Error exit. |
c %-----------------------------------------%
c
info = -9
go to 1200
end if
getv0 = .false.
ido = 0
end if
c
c %------------------------------------------------------------%
c | Back from reverse communication: continue with update step |
c %------------------------------------------------------------%
c
if (update) go to 20
c
c %-------------------------------------------%
c | Back from computing user specified shifts |
c %-------------------------------------------%
c
if (ushift) go to 50
c
c %-------------------------------------%
c | Back from computing residual norm |
c | at the end of the current iteration |
c %-------------------------------------%
c
if (cnorm) go to 100
c
c %----------------------------------------------------------%
c | Compute the first NEV steps of the Lanczos factorization |
c %----------------------------------------------------------%
c
call ssaitr (ido, bmat, n, 0, nev0, mode, resid, rnorm, v, ldv,
& h, ldh, ipntr, workd, info)
c
c %---------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP and possibly B |
c %---------------------------------------------------%
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
c
c %-----------------------------------------------------%
c | ssaitr was unable to build an Lanczos factorization |
c | of length NEV0. INFO is returned with the size of |
c | the factorization built. Exit main loop. |
c %-----------------------------------------------------%
c
np = info
mxiter = iter
info = -9999
go to 1200
end if
c
c %--------------------------------------------------------------%
c | |
c | M A I N LANCZOS I T E R A T I O N L O O P |
c | Each iteration implicitly restarts the Lanczos |
c | factorization in place. |
c | |
c %--------------------------------------------------------------%
c
1000 continue
c
iter = iter + 1
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, iter, ndigit,
& '_saup2: **** Start of major iteration number ****')
end if
if (msglvl .gt. 1) then
call ivout (logfil, 1, nev, ndigit,
& '_saup2: The length of the current Lanczos factorization')
call ivout (logfil, 1, np, ndigit,
& '_saup2: Extend the Lanczos factorization by')
end if
c
c %------------------------------------------------------------%
c | Compute NP additional steps of the Lanczos factorization. |
c %------------------------------------------------------------%
c
ido = 0
20 continue
update = .true.
c
call ssaitr (ido, bmat, n, nev, np, mode, resid, rnorm, v,
& ldv, h, ldh, ipntr, workd, info)
c
c %---------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP and possibly B |
c %---------------------------------------------------%
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
c
c %-----------------------------------------------------%
c | ssaitr was unable to build an Lanczos factorization |
c | of length NEV0+NP0. INFO is returned with the size |
c | of the factorization built. Exit main loop. |
c %-----------------------------------------------------%
c
np = info
mxiter = iter
info = -9999
go to 1200
end if
update = .false.
c
if (msglvl .gt. 1) then
call svout (logfil, 1, rnorm, ndigit,
& '_saup2: Current B-norm of residual for factorization')
end if
c
c %--------------------------------------------------------%
c | Compute the eigenvalues and corresponding error bounds |
c | of the current symmetric tridiagonal matrix. |
c %--------------------------------------------------------%
c
call sseigt (rnorm, kplusp, h, ldh, ritz, bounds, workl, ierr)
c
if (ierr .ne. 0) then
info = -8
go to 1200
end if
c
c %----------------------------------------------------%
c | Make a copy of eigenvalues and corresponding error |
c | bounds obtained from _seigt. |
c %----------------------------------------------------%
c
call scopy(kplusp, ritz, 1, workl(kplusp+1), 1)
call scopy(kplusp, bounds, 1, workl(2*kplusp+1), 1)
c
c %---------------------------------------------------%
c | Select the wanted Ritz values and their bounds |
c | to be used in the convergence test. |
c | The selection is based on the requested number of |
c | eigenvalues instead of the current NEV and NP to |
c | prevent possible misconvergence. |
c | * Wanted Ritz values := RITZ(NP+1:NEV+NP) |
c | * Shifts := RITZ(1:NP) := WORKL(1:NP) |
c %---------------------------------------------------%
c
nev = nev0
np = np0
call ssgets (ishift, which, nev, np, ritz, bounds, workl)
c
c %-------------------%
c | Convergence test. |
c %-------------------%
c
call scopy (nev, bounds(np+1), 1, workl(np+1), 1)
call ssconv (nev, ritz(np+1), workl(np+1), tol, nconv)
c
if (msglvl .gt. 2) then
kp(1) = nev
kp(2) = np
kp(3) = nconv
call ivout (logfil, 3, kp, ndigit,
& '_saup2: NEV, NP, NCONV are')
call svout (logfil, kplusp, ritz, ndigit,
& '_saup2: The eigenvalues of H')
call svout (logfil, kplusp, bounds, ndigit,
& '_saup2: Ritz estimates of the current NCV Ritz values')
end if
c
c %---------------------------------------------------------%
c | Count the number of unwanted Ritz values that have zero |
c | Ritz estimates. If any Ritz estimates are equal to zero |
c | then a leading block of H of order equal to at least |
c | the number of Ritz values with zero Ritz estimates has |
c | split off. None of these Ritz values may be removed by |
c | shifting. Decrease NP the number of shifts to apply. If |
c | no shifts may be applied, then prepare to exit |
c %---------------------------------------------------------%
c
nptemp = np
do 30 j=1, nptemp
if (bounds(j) .eq. zero) then
np = np - 1
nev = nev + 1
end if
30 continue
c
if ( (nconv .ge. nev0) .or.
& (iter .gt. mxiter) .or.
& (np .eq. 0) ) then
c
c %------------------------------------------------%
c | Prepare to exit. Put the converged Ritz values |
c | and corresponding bounds in RITZ(1:NCONV) and |
c | BOUNDS(1:NCONV) respectively. Then sort. Be |
c | careful when NCONV > NP since we don't want to |
c | swap overlapping locations. |
c %------------------------------------------------%
c
if (which .eq. 'BE') then
c
c %-----------------------------------------------------%
c | Both ends of the spectrum are requested. |
c | Sort the eigenvalues into algebraically decreasing |
c | order first then swap low end of the spectrum next |
c | to high end in appropriate locations. |
c | NOTE: when np < floor(nev/2) be careful not to swap |
c | overlapping locations. |
c %-----------------------------------------------------%
c
wprime = 'SA'
call ssortr (wprime, .true., kplusp, ritz, bounds)
nevd2 = nev0 / 2
nevm2 = nev0 - nevd2
if ( nev .gt. 1 ) then
call sswap ( min(nevd2,np), ritz(nevm2+1), 1,
& ritz( max(kplusp-nevd2+1,kplusp-np+1) ), 1)
call sswap ( min(nevd2,np), bounds(nevm2+1), 1,
& bounds( max(kplusp-nevd2+1,kplusp-np+1)), 1)
end if
c
else
c
c %--------------------------------------------------%
c | LM, SM, LA, SA case. |
c | Sort the eigenvalues of H into the an order that |
c | is opposite to WHICH, and apply the resulting |
c | order to BOUNDS. The eigenvalues are sorted so |
c | that the wanted part are always within the first |
c | NEV locations. |
c %--------------------------------------------------%
c
if (which .eq. 'LM') wprime = 'SM'
if (which .eq. 'SM') wprime = 'LM'
if (which .eq. 'LA') wprime = 'SA'
if (which .eq. 'SA') wprime = 'LA'
c
call ssortr (wprime, .true., kplusp, ritz, bounds)
c
end if
c
c %--------------------------------------------------%
c | Scale the Ritz estimate of each Ritz value |
c | by 1 / max(eps23,magnitude of the Ritz value). |
c %--------------------------------------------------%
c
do 35 j = 1, nev0
temp = max( eps23, abs(ritz(j)) )
bounds(j) = bounds(j)/temp
35 continue
c
c %----------------------------------------------------%
c | Sort the Ritz values according to the scaled Ritz |
c | esitmates. This will push all the converged ones |
c | towards the front of ritzr, ritzi, bounds |
c | (in the case when NCONV < NEV.) |
c %----------------------------------------------------%
c
wprime = 'LA'
call ssortr(wprime, .true., nev0, bounds, ritz)
c
c %----------------------------------------------%
c | Scale the Ritz estimate back to its original |
c | value. |
c %----------------------------------------------%
c
do 40 j = 1, nev0
temp = max( eps23, abs(ritz(j)) )
bounds(j) = bounds(j)*temp
40 continue
c
c %--------------------------------------------------%
c | Sort the "converged" Ritz values again so that |
c | the "threshold" values and their associated Ritz |
c | estimates appear at the appropriate position in |
c | ritz and bound. |
c %--------------------------------------------------%
c
if (which .eq. 'BE') then
c
c %------------------------------------------------%
c | Sort the "converged" Ritz values in increasing |
c | order. The "threshold" values are in the |
c | middle. |
c %------------------------------------------------%
c
wprime = 'LA'
call ssortr(wprime, .true., nconv, ritz, bounds)
c
else
c
c %----------------------------------------------%
c | In LM, SM, LA, SA case, sort the "converged" |
c | Ritz values according to WHICH so that the |
c | "threshold" value appears at the front of |
c | ritz. |
c %----------------------------------------------%
call ssortr(which, .true., nconv, ritz, bounds)
c
end if
c
c %------------------------------------------%
c | Use h( 1,1 ) as storage to communicate |
c | rnorm to _seupd if needed |
c %------------------------------------------%
c
h(1,1) = rnorm
c
if (msglvl .gt. 1) then
call svout (logfil, kplusp, ritz, ndigit,
& '_saup2: Sorted Ritz values.')
call svout (logfil, kplusp, bounds, ndigit,
& '_saup2: Sorted ritz estimates.')
end if
c
c %------------------------------------%
c | Max iterations have been exceeded. |
c %------------------------------------%
c
if (iter .gt. mxiter .and. nconv .lt. nev) info = 1
c
c %---------------------%
c | No shifts to apply. |
c %---------------------%
c
if (np .eq. 0 .and. nconv .lt. nev0) info = 2
c
np = nconv
go to 1100
c
else if (nconv .lt. nev .and. ishift .eq. 1) then
c
c %---------------------------------------------------%
c | Do not have all the requested eigenvalues yet. |
c | To prevent possible stagnation, adjust the number |
c | of Ritz values and the shifts. |
c %---------------------------------------------------%
c
nevbef = nev
nev = nev + min (nconv, np/2)
if (nev .eq. 1 .and. kplusp .ge. 6) then
nev = kplusp / 2
else if (nev .eq. 1 .and. kplusp .gt. 2) then
nev = 2
end if
np = kplusp - nev
c
c %---------------------------------------%
c | If the size of NEV was just increased |
c | resort the eigenvalues. |
c %---------------------------------------%
c
if (nevbef .lt. nev)
& call ssgets (ishift, which, nev, np, ritz, bounds,
& workl)
c
end if
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, nconv, ndigit,
& '_saup2: no. of "converged" Ritz values at this iter.')
if (msglvl .gt. 1) then
kp(1) = nev
kp(2) = np
call ivout (logfil, 2, kp, ndigit,
& '_saup2: NEV and NP are')
call svout (logfil, nev, ritz(np+1), ndigit,
& '_saup2: "wanted" Ritz values.')
call svout (logfil, nev, bounds(np+1), ndigit,
& '_saup2: Ritz estimates of the "wanted" values ')
end if
end if
c
if (ishift .eq. 0) then
c
c %-----------------------------------------------------%
c | User specified shifts: reverse communication to |
c | compute the shifts. They are returned in the first |
c | NP locations of WORKL. |
c %-----------------------------------------------------%
c
ushift = .true.
ido = 3
go to 9000
end if
c
50 continue
c
c %------------------------------------%
c | Back from reverse communication; |
c | User specified shifts are returned |
c | in WORKL(1:*NP) |
c %------------------------------------%
c
ushift = .false.
c
c
c %---------------------------------------------------------%
c | Move the NP shifts to the first NP locations of RITZ to |
c | free up WORKL. This is for the non-exact shift case; |
c | in the exact shift case, ssgets already handles this. |
c %---------------------------------------------------------%
c
if (ishift .eq. 0) call scopy (np, workl, 1, ritz, 1)
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, np, ndigit,
& '_saup2: The number of shifts to apply ')
call svout (logfil, np, workl, ndigit,
& '_saup2: shifts selected')
if (ishift .eq. 1) then
call svout (logfil, np, bounds, ndigit,
& '_saup2: corresponding Ritz estimates')
end if
end if
c
c %---------------------------------------------------------%
c | Apply the NP0 implicit shifts by QR bulge chasing. |
c | Each shift is applied to the entire tridiagonal matrix. |
c | The first 2*N locations of WORKD are used as workspace. |
c | After ssapps is done, we have a Lanczos |
c | factorization of length NEV. |
c %---------------------------------------------------------%
c
call ssapps (n, nev, np, ritz, v, ldv, h, ldh, resid, q, ldq,
& workd)
c
c %---------------------------------------------%
c | Compute the B-norm of the updated residual. |
c | Keep B*RESID in WORKD(1:N) to be used in |
c | the first step of the next call to ssaitr. |
c %---------------------------------------------%
c
cnorm = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call scopy (n, resid, 1, workd(n+1), 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*RESID |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call scopy (n, resid, 1, workd, 1)
end if
c
100 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(1:N) := B*RESID |
c %----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
if (bmat .eq. 'G') then
rnorm = sdot (n, resid, 1, workd, 1)
rnorm = sqrt(abs(rnorm))
else if (bmat .eq. 'I') then
rnorm = snrm2(n, resid, 1)
end if
cnorm = .false.
130 continue
c
if (msglvl .gt. 2) then
call svout (logfil, 1, rnorm, ndigit,
& '_saup2: B-norm of residual for NEV factorization')
call svout (logfil, nev, h(1,2), ndigit,
& '_saup2: main diagonal of compressed H matrix')
call svout (logfil, nev-1, h(2,1), ndigit,
& '_saup2: subdiagonal of compressed H matrix')
end if
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
1100 continue
c
mxiter = iter
nev = nconv
c
1200 continue
ido = 99
c
c %------------%
c | Error exit |
c %------------%
c
call second (t1)
tsaup2 = t1 - t0
c
9000 continue
return
c
c %---------------%
c | End of ssaup2 |
c %---------------%
c
end

690
arpack/ARPACK/SRC/ssaupd.f Normal file
View File

@@ -0,0 +1,690 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: ssaupd
c
c\Description:
c
c Reverse communication interface for the Implicitly Restarted Arnoldi
c Iteration. For symmetric problems this reduces to a variant of the Lanczos
c method. This method has been designed to compute approximations to a
c few eigenpairs of a linear operator OP that is real and symmetric
c with respect to a real positive semi-definite symmetric matrix B,
c i.e.
c
c B*OP = (OP`)*B.
c
c Another way to express this condition is
c
c < x,OPy > = < OPx,y > where < z,w > = z`Bw .
c
c In the standard eigenproblem B is the identity matrix.
c ( A` denotes transpose of A)
c
c The computed approximate eigenvalues are called Ritz values and
c the corresponding approximate eigenvectors are called Ritz vectors.
c
c ssaupd is usually called iteratively to solve one of the
c following problems:
c
c Mode 1: A*x = lambda*x, A symmetric
c ===> OP = A and B = I.
c
c Mode 2: A*x = lambda*M*x, A symmetric, M symmetric positive definite
c ===> OP = inv[M]*A and B = M.
c ===> (If M can be factored see remark 3 below)
c
c Mode 3: K*x = lambda*M*x, K symmetric, M symmetric positive semi-definite
c ===> OP = (inv[K - sigma*M])*M and B = M.
c ===> Shift-and-Invert mode
c
c Mode 4: K*x = lambda*KG*x, K symmetric positive semi-definite,
c KG symmetric indefinite
c ===> OP = (inv[K - sigma*KG])*K and B = K.
c ===> Buckling mode
c
c Mode 5: A*x = lambda*M*x, A symmetric, M symmetric positive semi-definite
c ===> OP = inv[A - sigma*M]*[A + sigma*M] and B = M.
c ===> Cayley transformed mode
c
c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v
c should be accomplished either by a direct method
c using a sparse matrix factorization and solving
c
c [A - sigma*M]*w = v or M*w = v,
c
c or through an iterative method for solving these
c systems. If an iterative method is used, the
c convergence test must be more stringent than
c the accuracy requirements for the eigenvalue
c approximations.
c
c\Usage:
c call ssaupd
c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM,
c IPNTR, WORKD, WORKL, LWORKL, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag. IDO must be zero on the first
c call to ssaupd. IDO will be set internally to
c indicate the type of operation to be performed. Control is
c then given back to the calling routine which has the
c responsibility to carry out the requested operation and call
c ssaupd with the result. The operand is given in
c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)).
c (If Mode = 2 see remark 5 below)
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c This is for the initialization phase to force the
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c In mode 3,4 and 5, the vector B * X is already
c available in WORKD(ipntr(3)). It does not
c need to be recomputed in forming OP * X.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c IDO = 3: compute the IPARAM(8) shifts where
c IPNTR(11) is the pointer into WORKL for
c placing the shifts. See remark 6 below.
c IDO = 99: done
c -------------------------------------------------------------
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B that defines the
c semi-inner product for the operator OP.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c WHICH Character*2. (INPUT)
c Specify which of the Ritz values of OP to compute.
c
c 'LA' - compute the NEV largest (algebraic) eigenvalues.
c 'SA' - compute the NEV smallest (algebraic) eigenvalues.
c 'LM' - compute the NEV largest (in magnitude) eigenvalues.
c 'SM' - compute the NEV smallest (in magnitude) eigenvalues.
c 'BE' - compute NEV eigenvalues, half from each end of the
c spectrum. When NEV is odd, compute one more from the
c high end than from the low end.
c (see remark 1 below)
c
c NEV Integer. (INPUT)
c Number of eigenvalues of OP to be computed. 0 < NEV < N.
c
c TOL Real scalar. (INPUT)
c Stopping criterion: the relative accuracy of the Ritz value
c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I)).
c If TOL .LE. 0. is passed a default is set:
c DEFAULT = SLAMCH('EPS') (machine precision as computed
c by the LAPACK auxiliary subroutine SLAMCH).
c
c RESID Real array of length N. (INPUT/OUTPUT)
c On INPUT:
c If INFO .EQ. 0, a random initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c On OUTPUT:
c RESID contains the final residual vector.
c
c NCV Integer. (INPUT)
c Number of columns of the matrix V (less than or equal to N).
c This will indicate how many Lanczos vectors are generated
c at each iteration. After the startup phase in which NEV
c Lanczos vectors are generated, the algorithm generates
c NCV-NEV Lanczos vectors at each subsequent update iteration.
c Most of the cost in generating each Lanczos vector is in the
c matrix-vector product OP*x. (See remark 4 below).
c
c V Real N by NCV array. (OUTPUT)
c The NCV columns of V contain the Lanczos basis vectors.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c IPARAM Integer array of length 11. (INPUT/OUTPUT)
c IPARAM(1) = ISHIFT: method for selecting the implicit shifts.
c The shifts selected at each iteration are used to restart
c the Arnoldi iteration in an implicit fashion.
c -------------------------------------------------------------
c ISHIFT = 0: the shifts are provided by the user via
c reverse communication. The NCV eigenvalues of
c the current tridiagonal matrix T are returned in
c the part of WORKL array corresponding to RITZ.
c See remark 6 below.
c ISHIFT = 1: exact shifts with respect to the reduced
c tridiagonal matrix T. This is equivalent to
c restarting the iteration with a starting vector
c that is a linear combination of Ritz vectors
c associated with the "wanted" Ritz values.
c -------------------------------------------------------------
c
c IPARAM(2) = LEVEC
c No longer referenced. See remark 2 below.
c
c IPARAM(3) = MXITER
c On INPUT: maximum number of Arnoldi update iterations allowed.
c On OUTPUT: actual number of Arnoldi update iterations taken.
c
c IPARAM(4) = NB: blocksize to be used in the recurrence.
c The code currently works only for NB = 1.
c
c IPARAM(5) = NCONV: number of "converged" Ritz values.
c This represents the number of Ritz values that satisfy
c the convergence criterion.
c
c IPARAM(6) = IUPD
c No longer referenced. Implicit restarting is ALWAYS used.
c
c IPARAM(7) = MODE
c On INPUT determines what type of eigenproblem is being solved.
c Must be 1,2,3,4,5; See under \Description of ssaupd for the
c five modes available.
c
c IPARAM(8) = NP
c When ido = 3 and the user provides shifts through reverse
c communication (IPARAM(1)=0), ssaupd returns NP, the number
c of shifts the user is to provide. 0 < NP <=NCV-NEV. See Remark
c 6 below.
c
c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO,
c OUTPUT: NUMOP = total number of OP*x operations,
c NUMOPB = total number of B*x operations if BMAT='G',
c NUMREO = total number of steps of re-orthogonalization.
c
c IPNTR Integer array of length 11. (OUTPUT)
c Pointer to mark the starting locations in the WORKD and WORKL
c arrays for matrices/vectors used by the Lanczos iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X in WORKD.
c IPNTR(2): pointer to the current result vector Y in WORKD.
c IPNTR(3): pointer to the vector B * X in WORKD when used in
c the shift-and-invert mode.
c IPNTR(4): pointer to the next available location in WORKL
c that is untouched by the program.
c IPNTR(5): pointer to the NCV by 2 tridiagonal matrix T in WORKL.
c IPNTR(6): pointer to the NCV RITZ values array in WORKL.
c IPNTR(7): pointer to the Ritz estimates in array WORKL associated
c with the Ritz values located in RITZ in WORKL.
c IPNTR(11): pointer to the NP shifts in WORKL. See Remark 6 below.
c
c Note: IPNTR(8:10) is only referenced by sseupd. See Remark 2.
c IPNTR(8): pointer to the NCV RITZ values of the original system.
c IPNTR(9): pointer to the NCV corresponding error bounds.
c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors
c of the tridiagonal matrix T. Only referenced by
c sseupd if RVEC = .TRUE. See Remarks.
c -------------------------------------------------------------
c
c WORKD Real work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration. Upon termination
c WORKD(1:N) contains B*RESID(1:N). If the Ritz vectors are desired
c subroutine sseupd uses this output.
c See Data Distribution Note below.
c
c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. See Data Distribution Note below.
c
c LWORKL Integer. (INPUT)
c LWORKL must be at least NCV**2 + 8*NCV .
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal exit.
c = 1: Maximum number of iterations taken.
c All possible eigenvalues of OP has been found. IPARAM(5)
c returns the number of wanted converged Ritz values.
c = 2: No longer an informational error. Deprecated starting
c with release 2 of ARPACK.
c = 3: No shifts could be applied during a cycle of the
c Implicitly restarted Arnoldi iteration. One possibility
c is to increase the size of NCV relative to NEV.
c See remark 4 below.
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV must be greater than NEV and less than or equal to N.
c = -4: The maximum number of Arnoldi update iterations allowed
c must be greater than zero.
c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'.
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work array WORKL is not sufficient.
c = -8: Error return from trid. eigenvalue calculation;
c Informatinal error from LAPACK routine ssteqr.
c = -9: Starting vector is zero.
c = -10: IPARAM(7) must be 1,2,3,4,5.
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatable.
c = -12: IPARAM(1) must be equal to 0 or 1.
c = -13: NEV and WHICH = 'BE' are incompatable.
c = -9999: Could not build an Arnoldi factorization.
c IPARAM(5) returns the size of the current Arnoldi
c factorization. The user is advised to check that
c enough workspace and array storage has been allocated.
c
c
c\Remarks
c 1. The converged Ritz values are always returned in ascending
c algebraic order. The computed Ritz values are approximate
c eigenvalues of OP. The selection of WHICH should be made
c with this in mind when Mode = 3,4,5. After convergence,
c approximate eigenvalues of the original problem may be obtained
c with the ARPACK subroutine sseupd.
c
c 2. If the Ritz vectors corresponding to the converged Ritz values
c are needed, the user must call sseupd immediately following completion
c of ssaupd. This is new starting with version 2.1 of ARPACK.
c
c 3. If M can be factored into a Cholesky factorization M = LL`
c then Mode = 2 should not be selected. Instead one should use
c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular
c linear systems should be solved with L and L` rather
c than computing inverses. After convergence, an approximate
c eigenvector z of the original problem is recovered by solving
c L`z = x where x is a Ritz vector of OP.
c
c 4. At present there is no a-priori analysis to guide the selection
c of NCV relative to NEV. The only formal requrement is that NCV > NEV.
c However, it is recommended that NCV .ge. 2*NEV. If many problems of
c the same type are to be solved, one should experiment with increasing
c NCV while keeping NEV fixed for a given test problem. This will
c usually decrease the required number of OP*x operations but it
c also increases the work and storage required to maintain the orthogonal
c basis vectors. The optimal "cross-over" with respect to CPU time
c is problem dependent and must be determined empirically.
c
c 5. If IPARAM(7) = 2 then in the Reverse commuication interface the user
c must do the following. When IDO = 1, Y = OP * X is to be computed.
c When IPARAM(7) = 2 OP = inv(B)*A. After computing A*X the user
c must overwrite X with A*X. Y is then the solution to the linear set
c of equations B*Y = A*X.
c
c 6. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the
c NP = IPARAM(8) shifts in locations:
c 1 WORKL(IPNTR(11))
c 2 WORKL(IPNTR(11)+1)
c .
c .
c .
c NP WORKL(IPNTR(11)+NP-1).
c
c The eigenvalues of the current tridiagonal matrix are located in
c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are in the
c order defined by WHICH. The associated Ritz estimates are located in
c WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... , WORKL(IPNTR(8)+NCV-1).
c
c-----------------------------------------------------------------------
c
c\Data Distribution Note:
c
c Fortran-D syntax:
c ================
c REAL RESID(N), V(LDV,NCV), WORKD(3*N), WORKL(LWORKL)
c DECOMPOSE D1(N), D2(N,NCV)
c ALIGN RESID(I) with D1(I)
c ALIGN V(I,J) with D2(I,J)
c ALIGN WORKD(I) with D1(I) range (1:N)
c ALIGN WORKD(I) with D1(I-N) range (N+1:2*N)
c ALIGN WORKD(I) with D1(I-2*N) range (2*N+1:3*N)
c DISTRIBUTE D1(BLOCK), D2(BLOCK,:)
c REPLICATED WORKL(LWORKL)
c
c Cray MPP syntax:
c ===============
c REAL RESID(N), V(LDV,NCV), WORKD(N,3), WORKL(LWORKL)
c SHARED RESID(BLOCK), V(BLOCK,:), WORKD(BLOCK,:)
c REPLICATED WORKL(LWORKL)
c
c
c\BeginLib
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall,
c 1980.
c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program",
c Computer Physics Communications, 53 (1989), pp 169-179.
c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to
c Implement the Spectral Transformation", Math. Comp., 48 (1987),
c pp 663-673.
c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos
c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems",
c SIAM J. Matr. Anal. Apps., January (1993).
c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines
c for Updating the QR decomposition", ACM TOMS, December 1990,
c Volume 16 Number 4, pp 369-377.
c 8. R.B. Lehoucq, D.C. Sorensen, "Implementation of Some Spectral
c Transformations in a k-Step Arnoldi Method". In Preparation.
c
c\Routines called:
c ssaup2 ARPACK routine that implements the Implicitly Restarted
c Arnoldi Iteration.
c sstats ARPACK routine that initialize timing and other statistics
c variables.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c svout ARPACK utility routine that prints vectors.
c slamch LAPACK routine that determines machine constants.
c
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/15/93: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: saupd.F SID: 2.8 DATE OF SID: 04/10/01 RELEASE: 2
c
c\Remarks
c 1. None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine ssaupd
& ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam,
& ipntr, workd, workl, lworkl, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ldv, lworkl, n, ncv, nev
Real
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(11), ipntr(11)
Real
& resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0 , zero = 0.0E+0 )
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer bounds, ierr, ih, iq, ishift, iupd, iw,
& ldh, ldq, msglvl, mxiter, mode, nb,
& nev0, next, np, ritz, j
save bounds, ierr, ih, iq, ishift, iupd, iw,
& ldh, ldq, msglvl, mxiter, mode, nb,
& nev0, next, np, ritz
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external ssaup2, svout, ivout, second, sstats
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& slamch
external slamch
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call sstats
call second (t0)
msglvl = msaupd
c
ierr = 0
ishift = iparam(1)
mxiter = iparam(3)
c nb = iparam(4)
nb = 1
c
c %--------------------------------------------%
c | Revision 2 performs only implicit restart. |
c %--------------------------------------------%
c
iupd = 1
mode = iparam(7)
c
c %----------------%
c | Error checking |
c %----------------%
c
if (n .le. 0) then
ierr = -1
else if (nev .le. 0) then
ierr = -2
else if (ncv .le. nev .or. ncv .gt. n) then
ierr = -3
end if
c
c %----------------------------------------------%
c | NP is the number of additional steps to |
c | extend the length NEV Lanczos factorization. |
c %----------------------------------------------%
c
np = ncv - nev
c
if (mxiter .le. 0) ierr = -4
if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LA' .and.
& which .ne. 'SA' .and.
& which .ne. 'BE') ierr = -5
if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6
c
if (lworkl .lt. ncv**2 + 8*ncv) ierr = -7
if (mode .lt. 1 .or. mode .gt. 5) then
ierr = -10
else if (mode .eq. 1 .and. bmat .eq. 'G') then
ierr = -11
else if (ishift .lt. 0 .or. ishift .gt. 1) then
ierr = -12
else if (nev .eq. 1 .and. which .eq. 'BE') then
ierr = -13
end if
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
ido = 99
go to 9000
end if
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
if (nb .le. 0) nb = 1
if (tol .le. zero) tol = slamch('EpsMach')
c
c %----------------------------------------------%
c | NP is the number of additional steps to |
c | extend the length NEV Lanczos factorization. |
c | NEV0 is the local variable designating the |
c | size of the invariant subspace desired. |
c %----------------------------------------------%
c
np = ncv - nev
nev0 = nev
c
c %-----------------------------%
c | Zero out internal workspace |
c %-----------------------------%
c
do 10 j = 1, ncv**2 + 8*ncv
workl(j) = zero
10 continue
c
c %-------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:2*ncv) := generated tridiagonal matrix |
c | workl(2*ncv+1:2*ncv+ncv) := ritz values |
c | workl(3*ncv+1:3*ncv+ncv) := computed error bounds |
c | workl(4*ncv+1:4*ncv+ncv*ncv) := rotation matrix Q |
c | workl(4*ncv+ncv*ncv+1:7*ncv+ncv*ncv) := workspace |
c %-------------------------------------------------------%
c
ldh = ncv
ldq = ncv
ih = 1
ritz = ih + 2*ldh
bounds = ritz + ncv
iq = bounds + ncv
iw = iq + ncv**2
next = iw + 3*ncv
c
ipntr(4) = next
ipntr(5) = ih
ipntr(6) = ritz
ipntr(7) = bounds
ipntr(11) = iw
end if
c
c %-------------------------------------------------------%
c | Carry out the Implicitly restarted Lanczos Iteration. |
c %-------------------------------------------------------%
c
call ssaup2
& ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz),
& workl(bounds), workl(iq), ldq, workl(iw), ipntr, workd,
& info )
c
c %--------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP or shifts. |
c %--------------------------------------------------%
c
if (ido .eq. 3) iparam(8) = np
if (ido .ne. 99) go to 9000
c
iparam(3) = mxiter
iparam(5) = np
iparam(9) = nopx
iparam(10) = nbx
iparam(11) = nrorth
c
c %------------------------------------%
c | Exit if there was an informational |
c | error within ssaup2. |
c %------------------------------------%
c
if (info .lt. 0) go to 9000
if (info .eq. 2) info = 3
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, mxiter, ndigit,
& '_saupd: number of update iterations taken')
call ivout (logfil, 1, np, ndigit,
& '_saupd: number of "converged" Ritz values')
call svout (logfil, np, workl(Ritz), ndigit,
& '_saupd: final Ritz values')
call svout (logfil, np, workl(Bounds), ndigit,
& '_saupd: corresponding error bounds')
end if
c
call second (t1)
tsaupd = t1 - t0
c
if (msglvl .gt. 0) then
c
c %--------------------------------------------------------%
c | Version Number & Version Date are defined in version.h |
c %--------------------------------------------------------%
c
write (6,1000)
write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt,
& tmvopx, tmvbx, tsaupd, tsaup2, tsaitr, titref,
& tgetv0, tseigt, tsgets, tsapps, tsconv
1000 format (//,
& 5x, '==========================================',/
& 5x, '= Symmetric implicit Arnoldi update code =',/
& 5x, '= Version Number:', ' 2.4' , 19x, ' =',/
& 5x, '= Version Date: ', ' 07/31/96' , 14x, ' =',/
& 5x, '==========================================',/
& 5x, '= Summary of timing statistics =',/
& 5x, '==========================================',//)
1100 format (
& 5x, 'Total number update iterations = ', i5,/
& 5x, 'Total number of OP*x operations = ', i5,/
& 5x, 'Total number of B*x operations = ', i5,/
& 5x, 'Total number of reorthogonalization steps = ', i5,/
& 5x, 'Total number of iterative refinement steps = ', i5,/
& 5x, 'Total number of restart steps = ', i5,/
& 5x, 'Total time in user OP*x operation = ', f12.6,/
& 5x, 'Total time in user B*x operation = ', f12.6,/
& 5x, 'Total time in Arnoldi update routine = ', f12.6,/
& 5x, 'Total time in saup2 routine = ', f12.6,/
& 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/
& 5x, 'Total time in reorthogonalization phase = ', f12.6,/
& 5x, 'Total time in (re)start vector generation = ', f12.6,/
& 5x, 'Total time in trid eigenvalue subproblem = ', f12.6,/
& 5x, 'Total time in getting the shifts = ', f12.6,/
& 5x, 'Total time in applying the shifts = ', f12.6,/
& 5x, 'Total time in convergence testing = ', f12.6)
end if
c
9000 continue
c
return
c
c %---------------%
c | End of ssaupd |
c %---------------%
c
end

138
arpack/ARPACK/SRC/ssconv.f Normal file
View File

@@ -0,0 +1,138 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: ssconv
c
c\Description:
c Convergence testing for the symmetric Arnoldi eigenvalue routine.
c
c\Usage:
c call ssconv
c ( N, RITZ, BOUNDS, TOL, NCONV )
c
c\Arguments
c N Integer. (INPUT)
c Number of Ritz values to check for convergence.
c
c RITZ Real array of length N. (INPUT)
c The Ritz values to be checked for convergence.
c
c BOUNDS Real array of length N. (INPUT)
c Ritz estimates associated with the Ritz values in RITZ.
c
c TOL Real scalar. (INPUT)
c Desired relative accuracy for a Ritz value to be considered
c "converged".
c
c NCONV Integer scalar. (OUTPUT)
c Number of "converged" Ritz values.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Routines called:
c second ARPACK utility routine for timing.
c slamch LAPACK routine that determines machine constants.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: sconv.F SID: 2.4 DATE OF SID: 4/19/96 RELEASE: 2
c
c\Remarks
c 1. Starting with version 2.4, this routine no longer uses the
c Parlett strategy using the gap conditions.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine ssconv (n, ritz, bounds, tol, nconv)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer n, nconv
Real
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& ritz(n), bounds(n)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i
Real
& temp, eps23
c
c %-------------------%
c | External routines |
c %-------------------%
c
Real
& slamch
external slamch
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic abs
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
call second (t0)
c
eps23 = slamch('Epsilon-Machine')
eps23 = eps23**(2.0E+0 / 3.0E+0)
c
nconv = 0
do 10 i = 1, n
c
c %-----------------------------------------------------%
c | The i-th Ritz value is considered "converged" |
c | when: bounds(i) .le. TOL*max(eps23, abs(ritz(i))) |
c %-----------------------------------------------------%
c
temp = max( eps23, abs(ritz(i)) )
if ( bounds(i) .le. tol*temp ) then
nconv = nconv + 1
end if
c
10 continue
c
call second (t1)
tsconv = tsconv + (t1 - t0)
c
return
c
c %---------------%
c | End of ssconv |
c %---------------%
c
end

181
arpack/ARPACK/SRC/sseigt.f Normal file
View File

@@ -0,0 +1,181 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: sseigt
c
c\Description:
c Compute the eigenvalues of the current symmetric tridiagonal matrix
c and the corresponding error bounds given the current residual norm.
c
c\Usage:
c call sseigt
c ( RNORM, N, H, LDH, EIG, BOUNDS, WORKL, IERR )
c
c\Arguments
c RNORM Real scalar. (INPUT)
c RNORM contains the residual norm corresponding to the current
c symmetric tridiagonal matrix H.
c
c N Integer. (INPUT)
c Size of the symmetric tridiagonal matrix H.
c
c H Real N by 2 array. (INPUT)
c H contains the symmetric tridiagonal matrix with the
c subdiagonal in the first column starting at H(2,1) and the
c main diagonal in second column.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c EIG Real array of length N. (OUTPUT)
c On output, EIG contains the N eigenvalues of H possibly
c unsorted. The BOUNDS arrays are returned in the
c same sorted order as EIG.
c
c BOUNDS Real array of length N. (OUTPUT)
c On output, BOUNDS contains the error estimates corresponding
c to the eigenvalues EIG. This is equal to RNORM times the
c last components of the eigenvectors corresponding to the
c eigenvalues in EIG.
c
c WORKL Real work array of length 3*N. (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c IERR Integer. (OUTPUT)
c Error exit flag from sstqrb.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c sstqrb ARPACK routine that computes the eigenvalues and the
c last components of the eigenvectors of a symmetric
c and tridiagonal matrix.
c second ARPACK utility routine for timing.
c svout ARPACK utility routine that prints vectors.
c scopy Level 1 BLAS that copies one vector to another.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.4'
c
c\SCCS Information: @(#)
c FILE: seigt.F SID: 2.4 DATE OF SID: 8/27/96 RELEASE: 2
c
c\Remarks
c None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine sseigt
& ( rnorm, n, h, ldh, eig, bounds, workl, ierr )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer ierr, ldh, n
Real
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& eig(n), bounds(n), h(ldh,2), workl(3*n)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& zero
parameter (zero = 0.0E+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, k, msglvl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external scopy, sstqrb, svout, second
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mseigt
c
if (msglvl .gt. 0) then
call svout (logfil, n, h(1,2), ndigit,
& '_seigt: main diagonal of matrix H')
if (n .gt. 1) then
call svout (logfil, n-1, h(2,1), ndigit,
& '_seigt: sub diagonal of matrix H')
end if
end if
c
call scopy (n, h(1,2), 1, eig, 1)
call scopy (n-1, h(2,1), 1, workl, 1)
call sstqrb (n, eig, workl, bounds, workl(n+1), ierr)
if (ierr .ne. 0) go to 9000
if (msglvl .gt. 1) then
call svout (logfil, n, bounds, ndigit,
& '_seigt: last row of the eigenvector matrix for H')
end if
c
c %-----------------------------------------------%
c | Finally determine the error bounds associated |
c | with the n Ritz values of H. |
c %-----------------------------------------------%
c
do 30 k = 1, n
bounds(k) = rnorm*abs(bounds(k))
30 continue
c
call second (t1)
tseigt = tseigt + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of sseigt |
c %---------------%
c
end

217
arpack/ARPACK/SRC/ssesrt.f Normal file
View File

@@ -0,0 +1,217 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: ssesrt
c
c\Description:
c Sort the array X in the order specified by WHICH and optionally
c apply the permutation to the columns of the matrix A.
c
c\Usage:
c call ssesrt
c ( WHICH, APPLY, N, X, NA, A, LDA)
c
c\Arguments
c WHICH Character*2. (Input)
c 'LM' -> X is sorted into increasing order of magnitude.
c 'SM' -> X is sorted into decreasing order of magnitude.
c 'LA' -> X is sorted into increasing order of algebraic.
c 'SA' -> X is sorted into decreasing order of algebraic.
c
c APPLY Logical. (Input)
c APPLY = .TRUE. -> apply the sorted order to A.
c APPLY = .FALSE. -> do not apply the sorted order to A.
c
c N Integer. (INPUT)
c Dimension of the array X.
c
c X Real array of length N. (INPUT/OUTPUT)
c The array to be sorted.
c
c NA Integer. (INPUT)
c Number of rows of the matrix A.
c
c A Real array of length NA by N. (INPUT/OUTPUT)
c
c LDA Integer. (INPUT)
c Leading dimension of A.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Routines
c sswap Level 1 BLAS that swaps the contents of two vectors.
c
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/15/93: Version ' 2.1'.
c Adapted from the sort routine in LANSO and
c the ARPACK code ssortr
c
c\SCCS Information: @(#)
c FILE: sesrt.F SID: 2.3 DATE OF SID: 4/19/96 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine ssesrt (which, apply, n, x, na, a, lda)
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
logical apply
integer lda, n, na
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& x(0:n-1), a(lda, 0:n-1)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, igap, j
Real
& temp
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external sswap
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
igap = n / 2
c
if (which .eq. 'SA') then
c
c X is sorted into decreasing order of algebraic.
c
10 continue
if (igap .eq. 0) go to 9000
do 30 i = igap, n-1
j = i-igap
20 continue
c
if (j.lt.0) go to 30
c
if (x(j).lt.x(j+igap)) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
if (apply) call sswap( na, a(1, j), 1, a(1,j+igap), 1)
else
go to 30
endif
j = j-igap
go to 20
30 continue
igap = igap / 2
go to 10
c
else if (which .eq. 'SM') then
c
c X is sorted into decreasing order of magnitude.
c
40 continue
if (igap .eq. 0) go to 9000
do 60 i = igap, n-1
j = i-igap
50 continue
c
if (j.lt.0) go to 60
c
if (abs(x(j)).lt.abs(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
if (apply) call sswap( na, a(1, j), 1, a(1,j+igap), 1)
else
go to 60
endif
j = j-igap
go to 50
60 continue
igap = igap / 2
go to 40
c
else if (which .eq. 'LA') then
c
c X is sorted into increasing order of algebraic.
c
70 continue
if (igap .eq. 0) go to 9000
do 90 i = igap, n-1
j = i-igap
80 continue
c
if (j.lt.0) go to 90
c
if (x(j).gt.x(j+igap)) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
if (apply) call sswap( na, a(1, j), 1, a(1,j+igap), 1)
else
go to 90
endif
j = j-igap
go to 80
90 continue
igap = igap / 2
go to 70
c
else if (which .eq. 'LM') then
c
c X is sorted into increasing order of magnitude.
c
100 continue
if (igap .eq. 0) go to 9000
do 120 i = igap, n-1
j = i-igap
110 continue
c
if (j.lt.0) go to 120
c
if (abs(x(j)).gt.abs(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
if (apply) call sswap( na, a(1, j), 1, a(1,j+igap), 1)
else
go to 120
endif
j = j-igap
go to 110
120 continue
igap = igap / 2
go to 100
end if
c
9000 continue
return
c
c %---------------%
c | End of ssesrt |
c %---------------%
c
end

857
arpack/ARPACK/SRC/sseupd.f Normal file
View File

@@ -0,0 +1,857 @@
c\BeginDoc
c
c\Name: sseupd
c
c\Description:
c
c This subroutine returns the converged approximations to eigenvalues
c of A*z = lambda*B*z and (optionally):
c
c (1) the corresponding approximate eigenvectors,
c
c (2) an orthonormal (Lanczos) basis for the associated approximate
c invariant subspace,
c
c (3) Both.
c
c There is negligible additional cost to obtain eigenvectors. An orthonormal
c (Lanczos) basis is always computed. There is an additional storage cost
c of n*nev if both are requested (in this case a separate array Z must be
c supplied).
c
c These quantities are obtained from the Lanczos factorization computed
c by SSAUPD for the linear operator OP prescribed by the MODE selection
c (see IPARAM(7) in SSAUPD documentation.) SSAUPD must be called before
c this routine is called. These approximate eigenvalues and vectors are
c commonly called Ritz values and Ritz vectors respectively. They are
c referred to as such in the comments that follow. The computed orthonormal
c basis for the invariant subspace corresponding to these Ritz values is
c referred to as a Lanczos basis.
c
c See documentation in the header of the subroutine SSAUPD for a definition
c of OP as well as other terms and the relation of computed Ritz values
c and vectors of OP with respect to the given problem A*z = lambda*B*z.
c
c The approximate eigenvalues of the original problem are returned in
c ascending algebraic order. The user may elect to call this routine
c once for each desired Ritz vector and store it peripherally if desired.
c There is also the option of computing a selected set of these vectors
c with a single call.
c
c\Usage:
c call sseupd
c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, BMAT, N, WHICH, NEV, TOL,
c RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, LWORKL, INFO )
c
c RVEC LOGICAL (INPUT)
c Specifies whether Ritz vectors corresponding to the Ritz value
c approximations to the eigenproblem A*z = lambda*B*z are computed.
c
c RVEC = .FALSE. Compute Ritz values only.
c
c RVEC = .TRUE. Compute Ritz vectors.
c
c HOWMNY Character*1 (INPUT)
c Specifies how many Ritz vectors are wanted and the form of Z
c the matrix of Ritz vectors. See remark 1 below.
c = 'A': compute NEV Ritz vectors;
c = 'S': compute some of the Ritz vectors, specified
c by the logical array SELECT.
c
c SELECT Logical array of dimension NCV. (INPUT/WORKSPACE)
c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be
c computed. To select the Ritz vector corresponding to a
c Ritz value D(j), SELECT(j) must be set to .TRUE..
c If HOWMNY = 'A' , SELECT is used as a workspace for
c reordering the Ritz values.
c
c D Real array of dimension NEV. (OUTPUT)
c On exit, D contains the Ritz value approximations to the
c eigenvalues of A*z = lambda*B*z. The values are returned
c in ascending order. If IPARAM(7) = 3,4,5 then D represents
c the Ritz values of OP computed by ssaupd transformed to
c those of the original eigensystem A*z = lambda*B*z. If
c IPARAM(7) = 1,2 then the Ritz values of OP are the same
c as the those of A*z = lambda*B*z.
c
c Z Real N by NEV array if HOWMNY = 'A'. (OUTPUT)
c On exit, Z contains the B-orthonormal Ritz vectors of the
c eigensystem A*z = lambda*B*z corresponding to the Ritz
c value approximations.
c If RVEC = .FALSE. then Z is not referenced.
c NOTE: The array Z may be set equal to first NEV columns of the
c Arnoldi/Lanczos basis array V computed by SSAUPD.
c
c LDZ Integer. (INPUT)
c The leading dimension of the array Z. If Ritz vectors are
c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1.
c
c SIGMA Real (INPUT)
c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if
c IPARAM(7) = 1 or 2.
c
c
c **** The remaining arguments MUST be the same as for the ****
c **** call to SSAUPD that was just completed. ****
c
c NOTE: The remaining arguments
c
c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR,
c WORKD, WORKL, LWORKL, INFO
c
c must be passed directly to SSEUPD following the last call
c to SSAUPD. These arguments MUST NOT BE MODIFIED between
c the the last call to SSAUPD and the call to SSEUPD.
c
c Two of these parameters (WORKL, INFO) are also output parameters:
c
c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE)
c WORKL(1:4*ncv) contains information obtained in
c ssaupd. They are not changed by sseupd.
c WORKL(4*ncv+1:ncv*ncv+8*ncv) holds the
c untransformed Ritz values, the computed error estimates,
c and the associated eigenvector matrix of H.
c
c Note: IPNTR(8:10) contains the pointer into WORKL for addresses
c of the above information computed by sseupd.
c -------------------------------------------------------------
c IPNTR(8): pointer to the NCV RITZ values of the original system.
c IPNTR(9): pointer to the NCV corresponding error bounds.
c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors
c of the tridiagonal matrix T. Only referenced by
c sseupd if RVEC = .TRUE. See Remarks.
c -------------------------------------------------------------
c
c INFO Integer. (OUTPUT)
c Error flag on output.
c = 0: Normal exit.
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV must be greater than NEV and less than or equal to N.
c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'.
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work WORKL array is not sufficient.
c = -8: Error return from trid. eigenvalue calculation;
c Information error from LAPACK routine ssteqr.
c = -9: Starting vector is zero.
c = -10: IPARAM(7) must be 1,2,3,4,5.
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.
c = -12: NEV and WHICH = 'BE' are incompatible.
c = -14: SSAUPD did not find any eigenvalues to sufficient
c accuracy.
c = -15: HOWMNY must be one of 'A' or 'S' if RVEC = .true.
c = -16: HOWMNY = 'S' not yet implemented
c = -17: SSEUPD got a different count of the number of converged
c Ritz values than SSAUPD got. This indicates the user
c probably made an error in passing data from SSAUPD to
c SSEUPD or that the data was modified before entering
c SSEUPD.
c
c\BeginLib
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall,
c 1980.
c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program",
c Computer Physics Communications, 53 (1989), pp 169-179.
c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to
c Implement the Spectral Transformation", Math. Comp., 48 (1987),
c pp 663-673.
c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos
c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems",
c SIAM J. Matr. Anal. Apps., January (1993).
c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines
c for Updating the QR decomposition", ACM TOMS, December 1990,
c Volume 16 Number 4, pp 369-377.
c
c\Remarks
c 1. The converged Ritz values are always returned in increasing
c (algebraic) order.
c
c 2. Currently only HOWMNY = 'A' is implemented. It is included at this
c stage for the user who wants to incorporate it.
c
c\Routines called:
c ssesrt ARPACK routine that sorts an array X, and applies the
c corresponding permutation to a matrix A.
c ssortr ssortr ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c svout ARPACK utility routine that prints vectors.
c sgeqr2 LAPACK routine that computes the QR factorization of
c a matrix.
c slacpy LAPACK matrix copy routine.
c slamch LAPACK routine that determines machine constants.
c sorm2r LAPACK routine that applies an orthogonal matrix in
c factored form.
c ssteqr LAPACK routine that computes eigenvalues and eigenvectors
c of a tridiagonal matrix.
c sger Level 2 BLAS rank one update to a matrix.
c scopy Level 1 BLAS that copies one vector to another .
c snrm2 Level 1 BLAS that computes the norm of a vector.
c sscal Level 1 BLAS that scales a vector.
c sswap Level 1 BLAS that swaps the contents of two vectors.
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Chao Yang Houston, Texas
c Dept. of Computational &
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/15/93: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: seupd.F SID: 2.11 DATE OF SID: 04/10/01 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
subroutine sseupd(rvec , howmny, select, d ,
& z , ldz , sigma , bmat ,
& n , which , nev , tol ,
& resid , ncv , v , ldv ,
& iparam, ipntr , workd , workl,
& lworkl, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat, howmny, which*2
logical rvec
integer info, ldz, ldv, lworkl, n, ncv, nev
Real
& sigma, tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(7), ipntr(11)
logical select(ncv)
Real
& d(nev) , resid(n) , v(ldv,ncv),
& z(ldz, nev), workd(2*n), workl(lworkl)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0 , zero = 0.0E+0 )
c
c %---------------%
c | Local Scalars |
c %---------------%
c
character type*6
integer bounds , ierr , ih , ihb , ihd ,
& iq , iw , j , k , ldh ,
& ldq , mode , msglvl, nconv , next ,
& ritz , irz , ibd , np , ishift,
& leftptr, rghtptr, numcnv, jj
Real
& bnorm2 , rnorm, temp, temp1, eps23
logical reord
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external scopy , sger , sgeqr2, slacpy, sorm2r, sscal,
& ssesrt, ssteqr, sswap , svout , ivout , ssortr
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& snrm2, slamch
external snrm2, slamch
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic min
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
msglvl = mseupd
mode = iparam(7)
nconv = iparam(5)
info = 0
c
c %--------------%
c | Quick return |
c %--------------%
c
if (nconv .eq. 0) go to 9000
ierr = 0
c
if (nconv .le. 0) ierr = -14
if (n .le. 0) ierr = -1
if (nev .le. 0) ierr = -2
if (ncv .le. nev .or. ncv .gt. n) ierr = -3
if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LA' .and.
& which .ne. 'SA' .and.
& which .ne. 'BE') ierr = -5
if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6
if ( (howmny .ne. 'A' .and.
& howmny .ne. 'P' .and.
& howmny .ne. 'S') .and. rvec )
& ierr = -15
if (rvec .and. howmny .eq. 'S') ierr = -16
c
if (rvec .and. lworkl .lt. ncv**2+8*ncv) ierr = -7
c
if (mode .eq. 1 .or. mode .eq. 2) then
type = 'REGULR'
else if (mode .eq. 3 ) then
type = 'SHIFTI'
else if (mode .eq. 4 ) then
type = 'BUCKLE'
else if (mode .eq. 5 ) then
type = 'CAYLEY'
else
ierr = -10
end if
if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11
if (nev .eq. 1 .and. which .eq. 'BE') ierr = -12
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
go to 9000
end if
c
c %-------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:2*ncv) := generated tridiagonal matrix H |
c | The subdiagonal is stored in workl(2:ncv). |
c | The dead spot is workl(1) but upon exiting |
c | ssaupd stores the B-norm of the last residual |
c | vector in workl(1). We use this !!! |
c | workl(2*ncv+1:2*ncv+ncv) := ritz values |
c | The wanted values are in the first NCONV spots. |
c | workl(3*ncv+1:3*ncv+ncv) := computed Ritz estimates |
c | The wanted values are in the first NCONV spots. |
c | NOTE: workl(1:4*ncv) is set by ssaupd and is not |
c | modified by sseupd. |
c %-------------------------------------------------------%
c
c %-------------------------------------------------------%
c | The following is used and set by sseupd. |
c | workl(4*ncv+1:4*ncv+ncv) := used as workspace during |
c | computation of the eigenvectors of H. Stores |
c | the diagonal of H. Upon EXIT contains the NCV |
c | Ritz values of the original system. The first |
c | NCONV spots have the wanted values. If MODE = |
c | 1 or 2 then will equal workl(2*ncv+1:3*ncv). |
c | workl(5*ncv+1:5*ncv+ncv) := used as workspace during |
c | computation of the eigenvectors of H. Stores |
c | the subdiagonal of H. Upon EXIT contains the |
c | NCV corresponding Ritz estimates of the |
c | original system. The first NCONV spots have the |
c | wanted values. If MODE = 1,2 then will equal |
c | workl(3*ncv+1:4*ncv). |
c | workl(6*ncv+1:6*ncv+ncv*ncv) := orthogonal Q that is |
c | the eigenvector matrix for H as returned by |
c | ssteqr. Not referenced if RVEC = .False. |
c | Ordering follows that of workl(4*ncv+1:5*ncv) |
c | workl(6*ncv+ncv*ncv+1:6*ncv+ncv*ncv+2*ncv) := |
c | Workspace. Needed by ssteqr and by sseupd. |
c | GRAND total of NCV*(NCV+8) locations. |
c %-------------------------------------------------------%
c
c
ih = ipntr(5)
ritz = ipntr(6)
bounds = ipntr(7)
ldh = ncv
ldq = ncv
ihd = bounds + ldh
ihb = ihd + ldh
iq = ihb + ldh
iw = iq + ldh*ncv
next = iw + 2*ncv
ipntr(4) = next
ipntr(8) = ihd
ipntr(9) = ihb
ipntr(10) = iq
c
c %----------------------------------------%
c | irz points to the Ritz values computed |
c | by _seigt before exiting _saup2. |
c | ibd points to the Ritz estimates |
c | computed by _seigt before exiting |
c | _saup2. |
c %----------------------------------------%
c
irz = ipntr(11)+ncv
ibd = irz+ncv
c
c
c %---------------------------------%
c | Set machine dependent constant. |
c %---------------------------------%
c
eps23 = slamch('Epsilon-Machine')
eps23 = eps23**(2.0E+0 / 3.0E+0 )
c
c %---------------------------------------%
c | RNORM is B-norm of the RESID(1:N). |
c | BNORM2 is the 2 norm of B*RESID(1:N). |
c | Upon exit of ssaupd WORKD(1:N) has |
c | B*RESID(1:N). |
c %---------------------------------------%
c
rnorm = workl(ih)
if (bmat .eq. 'I') then
bnorm2 = rnorm
else if (bmat .eq. 'G') then
bnorm2 = snrm2(n, workd, 1)
end if
c
if (msglvl .gt. 2) then
call svout(logfil, ncv, workl(irz), ndigit,
& '_seupd: Ritz values passed in from _SAUPD.')
call svout(logfil, ncv, workl(ibd), ndigit,
& '_seupd: Ritz estimates passed in from _SAUPD.')
end if
c
if (rvec) then
c
reord = .false.
c
c %---------------------------------------------------%
c | Use the temporary bounds array to store indices |
c | These will be used to mark the select array later |
c %---------------------------------------------------%
c
do 10 j = 1,ncv
workl(bounds+j-1) = j
select(j) = .false.
10 continue
c
c %-------------------------------------%
c | Select the wanted Ritz values. |
c | Sort the Ritz values so that the |
c | wanted ones appear at the tailing |
c | NEV positions of workl(irr) and |
c | workl(iri). Move the corresponding |
c | error estimates in workl(bound) |
c | accordingly. |
c %-------------------------------------%
c
np = ncv - nev
ishift = 0
call ssgets(ishift, which , nev ,
& np , workl(irz) , workl(bounds),
& workl)
c
if (msglvl .gt. 2) then
call svout(logfil, ncv, workl(irz), ndigit,
& '_seupd: Ritz values after calling _SGETS.')
call svout(logfil, ncv, workl(bounds), ndigit,
& '_seupd: Ritz value indices after calling _SGETS.')
end if
c
c %-----------------------------------------------------%
c | Record indices of the converged wanted Ritz values |
c | Mark the select array for possible reordering |
c %-----------------------------------------------------%
c
numcnv = 0
do 11 j = 1,ncv
temp1 = max(eps23, abs(workl(irz+ncv-j)) )
jj = workl(bounds + ncv - j)
if (numcnv .lt. nconv .and.
& workl(ibd+jj-1) .le. tol*temp1) then
select(jj) = .true.
numcnv = numcnv + 1
if (jj .gt. nev) reord = .true.
endif
11 continue
c
c %-----------------------------------------------------------%
c | Check the count (numcnv) of converged Ritz values with |
c | the number (nconv) reported by _saupd. If these two |
c | are different then there has probably been an error |
c | caused by incorrect passing of the _saupd data. |
c %-----------------------------------------------------------%
c
if (msglvl .gt. 2) then
call ivout(logfil, 1, numcnv, ndigit,
& '_seupd: Number of specified eigenvalues')
call ivout(logfil, 1, nconv, ndigit,
& '_seupd: Number of "converged" eigenvalues')
end if
c
if (numcnv .ne. nconv) then
info = -17
go to 9000
end if
c
c %-----------------------------------------------------------%
c | Call LAPACK routine _steqr to compute the eigenvalues and |
c | eigenvectors of the final symmetric tridiagonal matrix H. |
c | Initialize the eigenvector matrix Q to the identity. |
c %-----------------------------------------------------------%
c
call scopy(ncv-1, workl(ih+1), 1, workl(ihb), 1)
call scopy(ncv, workl(ih+ldh), 1, workl(ihd), 1)
c
call ssteqr('Identity', ncv, workl(ihd), workl(ihb),
& workl(iq) , ldq, workl(iw), ierr)
c
if (ierr .ne. 0) then
info = -8
go to 9000
end if
c
if (msglvl .gt. 1) then
call scopy(ncv, workl(iq+ncv-1), ldq, workl(iw), 1)
call svout(logfil, ncv, workl(ihd), ndigit,
& '_seupd: NCV Ritz values of the final H matrix')
call svout(logfil, ncv, workl(iw), ndigit,
& '_seupd: last row of the eigenvector matrix for H')
end if
c
if (reord) then
c
c %---------------------------------------------%
c | Reordered the eigenvalues and eigenvectors |
c | computed by _steqr so that the "converged" |
c | eigenvalues appear in the first NCONV |
c | positions of workl(ihd), and the associated |
c | eigenvectors appear in the first NCONV |
c | columns. |
c %---------------------------------------------%
c
leftptr = 1
rghtptr = ncv
c
if (ncv .eq. 1) go to 30
c
20 if (select(leftptr)) then
c
c %-------------------------------------------%
c | Search, from the left, for the first Ritz |
c | value that has not converged. |
c %-------------------------------------------%
c
leftptr = leftptr + 1
c
else if ( .not. select(rghtptr)) then
c
c %----------------------------------------------%
c | Search, from the right, the first Ritz value |
c | that has converged. |
c %----------------------------------------------%
c
rghtptr = rghtptr - 1
c
else
c
c %----------------------------------------------%
c | Swap the Ritz value on the left that has not |
c | converged with the Ritz value on the right |
c | that has converged. Swap the associated |
c | eigenvector of the tridiagonal matrix H as |
c | well. |
c %----------------------------------------------%
c
temp = workl(ihd+leftptr-1)
workl(ihd+leftptr-1) = workl(ihd+rghtptr-1)
workl(ihd+rghtptr-1) = temp
call scopy(ncv, workl(iq+ncv*(leftptr-1)), 1,
& workl(iw), 1)
call scopy(ncv, workl(iq+ncv*(rghtptr-1)), 1,
& workl(iq+ncv*(leftptr-1)), 1)
call scopy(ncv, workl(iw), 1,
& workl(iq+ncv*(rghtptr-1)), 1)
leftptr = leftptr + 1
rghtptr = rghtptr - 1
c
end if
c
if (leftptr .lt. rghtptr) go to 20
c
30 end if
c
if (msglvl .gt. 2) then
call svout (logfil, ncv, workl(ihd), ndigit,
& '_seupd: The eigenvalues of H--reordered')
end if
c
c %----------------------------------------%
c | Load the converged Ritz values into D. |
c %----------------------------------------%
c
call scopy(nconv, workl(ihd), 1, d, 1)
c
else
c
c %-----------------------------------------------------%
c | Ritz vectors not required. Load Ritz values into D. |
c %-----------------------------------------------------%
c
call scopy(nconv, workl(ritz), 1, d, 1)
call scopy(ncv, workl(ritz), 1, workl(ihd), 1)
c
end if
c
c %------------------------------------------------------------------%
c | Transform the Ritz values and possibly vectors and corresponding |
c | Ritz estimates of OP to those of A*x=lambda*B*x. The Ritz values |
c | (and corresponding data) are returned in ascending order. |
c %------------------------------------------------------------------%
c
if (type .eq. 'REGULR') then
c
c %---------------------------------------------------------%
c | Ascending sort of wanted Ritz values, vectors and error |
c | bounds. Not necessary if only Ritz values are desired. |
c %---------------------------------------------------------%
c
if (rvec) then
call ssesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq)
else
call scopy(ncv, workl(bounds), 1, workl(ihb), 1)
end if
c
else
c
c %-------------------------------------------------------------%
c | * Make a copy of all the Ritz values. |
c | * Transform the Ritz values back to the original system. |
c | For TYPE = 'SHIFTI' the transformation is |
c | lambda = 1/theta + sigma |
c | For TYPE = 'BUCKLE' the transformation is |
c | lambda = sigma * theta / ( theta - 1 ) |
c | For TYPE = 'CAYLEY' the transformation is |
c | lambda = sigma * (theta + 1) / (theta - 1 ) |
c | where the theta are the Ritz values returned by ssaupd. |
c | NOTES: |
c | *The Ritz vectors are not affected by the transformation. |
c | They are only reordered. |
c %-------------------------------------------------------------%
c
call scopy (ncv, workl(ihd), 1, workl(iw), 1)
if (type .eq. 'SHIFTI') then
do 40 k=1, ncv
workl(ihd+k-1) = one / workl(ihd+k-1) + sigma
40 continue
else if (type .eq. 'BUCKLE') then
do 50 k=1, ncv
workl(ihd+k-1) = sigma * workl(ihd+k-1) /
& (workl(ihd+k-1) - one)
50 continue
else if (type .eq. 'CAYLEY') then
do 60 k=1, ncv
workl(ihd+k-1) = sigma * (workl(ihd+k-1) + one) /
& (workl(ihd+k-1) - one)
60 continue
end if
c
c %-------------------------------------------------------------%
c | * Store the wanted NCONV lambda values into D. |
c | * Sort the NCONV wanted lambda in WORKL(IHD:IHD+NCONV-1) |
c | into ascending order and apply sort to the NCONV theta |
c | values in the transformed system. We will need this to |
c | compute Ritz estimates in the original system. |
c | * Finally sort the lambda`s into ascending order and apply |
c | to Ritz vectors if wanted. Else just sort lambda`s into |
c | ascending order. |
c | NOTES: |
c | *workl(iw:iw+ncv-1) contain the theta ordered so that they |
c | match the ordering of the lambda. We`ll use them again for |
c | Ritz vector purification. |
c %-------------------------------------------------------------%
c
call scopy(nconv, workl(ihd), 1, d, 1)
call ssortr('LA', .true., nconv, workl(ihd), workl(iw))
if (rvec) then
call ssesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq)
else
call scopy(ncv, workl(bounds), 1, workl(ihb), 1)
call sscal(ncv, bnorm2/rnorm, workl(ihb), 1)
call ssortr('LA', .true., nconv, d, workl(ihb))
end if
c
end if
c
c %------------------------------------------------%
c | Compute the Ritz vectors. Transform the wanted |
c | eigenvectors of the symmetric tridiagonal H by |
c | the Lanczos basis matrix V. |
c %------------------------------------------------%
c
if (rvec .and. howmny .eq. 'A') then
c
c %----------------------------------------------------------%
c | Compute the QR factorization of the matrix representing |
c | the wanted invariant subspace located in the first NCONV |
c | columns of workl(iq,ldq). |
c %----------------------------------------------------------%
c
call sgeqr2(ncv, nconv , workl(iq) ,
& ldq, workl(iw+ncv), workl(ihb),
& ierr)
c
c %--------------------------------------------------------%
c | * Postmultiply V by Q. |
c | * Copy the first NCONV columns of VQ into Z. |
c | The N by NCONV matrix Z is now a matrix representation |
c | of the approximate invariant subspace associated with |
c | the Ritz values in workl(ihd). |
c %--------------------------------------------------------%
c
call sorm2r('Right', 'Notranspose', n ,
& ncv , nconv , workl(iq),
& ldq , workl(iw+ncv), v ,
& ldv , workd(n+1) , ierr)
call slacpy('All', n, nconv, v, ldv, z, ldz)
c
c %-----------------------------------------------------%
c | In order to compute the Ritz estimates for the Ritz |
c | values in both systems, need the last row of the |
c | eigenvector matrix. Remember, it`s in factored form |
c %-----------------------------------------------------%
c
do 65 j = 1, ncv-1
workl(ihb+j-1) = zero
65 continue
workl(ihb+ncv-1) = one
call sorm2r('Left', 'Transpose' , ncv ,
& 1 , nconv , workl(iq) ,
& ldq , workl(iw+ncv), workl(ihb),
& ncv , temp , ierr)
c
else if (rvec .and. howmny .eq. 'S') then
c
c Not yet implemented. See remark 2 above.
c
end if
c
if (type .eq. 'REGULR' .and. rvec) then
c
do 70 j=1, ncv
workl(ihb+j-1) = rnorm * abs( workl(ihb+j-1) )
70 continue
c
else if (type .ne. 'REGULR' .and. rvec) then
c
c %-------------------------------------------------%
c | * Determine Ritz estimates of the theta. |
c | If RVEC = .true. then compute Ritz estimates |
c | of the theta. |
c | If RVEC = .false. then copy Ritz estimates |
c | as computed by ssaupd. |
c | * Determine Ritz estimates of the lambda. |
c %-------------------------------------------------%
c
call sscal (ncv, bnorm2, workl(ihb), 1)
if (type .eq. 'SHIFTI') then
c
do 80 k=1, ncv
workl(ihb+k-1) = abs( workl(ihb+k-1) )
& / workl(iw+k-1)**2
80 continue
c
else if (type .eq. 'BUCKLE') then
c
do 90 k=1, ncv
workl(ihb+k-1) = sigma * abs( workl(ihb+k-1) )
& / (workl(iw+k-1)-one )**2
90 continue
c
else if (type .eq. 'CAYLEY') then
c
do 100 k=1, ncv
workl(ihb+k-1) = abs( workl(ihb+k-1)
& / workl(iw+k-1)*(workl(iw+k-1)-one) )
100 continue
c
end if
c
end if
c
if (type .ne. 'REGULR' .and. msglvl .gt. 1) then
call svout(logfil, nconv, d, ndigit,
& '_seupd: Untransformed converged Ritz values')
call svout(logfil, nconv, workl(ihb), ndigit,
& '_seupd: Ritz estimates of the untransformed Ritz values')
else if (msglvl .gt. 1) then
call svout(logfil, nconv, d, ndigit,
& '_seupd: Converged Ritz values')
call svout(logfil, nconv, workl(ihb), ndigit,
& '_seupd: Associated Ritz estimates')
end if
c
c %-------------------------------------------------%
c | Ritz vector purification step. Formally perform |
c | one of inverse subspace iteration. Only used |
c | for MODE = 3,4,5. See reference 7 |
c %-------------------------------------------------%
c
if (rvec .and. (type .eq. 'SHIFTI' .or. type .eq. 'CAYLEY')) then
c
do 110 k=0, nconv-1
workl(iw+k) = workl(iq+k*ldq+ncv-1)
& / workl(iw+k)
110 continue
c
else if (rvec .and. type .eq. 'BUCKLE') then
c
do 120 k=0, nconv-1
workl(iw+k) = workl(iq+k*ldq+ncv-1)
& / (workl(iw+k)-one)
120 continue
c
end if
c
if (type .ne. 'REGULR')
& call sger (n, nconv, one, resid, 1, workl(iw), 1, z, ldz)
c
9000 continue
c
return
c
c %---------------%
c | End of sseupd|
c %---------------%
c
end

219
arpack/ARPACK/SRC/ssgets.f Normal file
View File

@@ -0,0 +1,219 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: ssgets
c
c\Description:
c Given the eigenvalues of the symmetric tridiagonal matrix H,
c computes the NP shifts AMU that are zeros of the polynomial of
c degree NP which filters out components of the unwanted eigenvectors
c corresponding to the AMU's based on some given criteria.
c
c NOTE: This is called even in the case of user specified shifts in
c order to sort the eigenvalues, and error bounds of H for later use.
c
c\Usage:
c call ssgets
c ( ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS, SHIFTS )
c
c\Arguments
c ISHIFT Integer. (INPUT)
c Method for selecting the implicit shifts at each iteration.
c ISHIFT = 0: user specified shifts
c ISHIFT = 1: exact shift with respect to the matrix H.
c
c WHICH Character*2. (INPUT)
c Shift selection criteria.
c 'LM' -> KEV eigenvalues of largest magnitude are retained.
c 'SM' -> KEV eigenvalues of smallest magnitude are retained.
c 'LA' -> KEV eigenvalues of largest value are retained.
c 'SA' -> KEV eigenvalues of smallest value are retained.
c 'BE' -> KEV eigenvalues, half from each end of the spectrum.
c If KEV is odd, compute one more from the high end.
c
c KEV Integer. (INPUT)
c KEV+NP is the size of the matrix H.
c
c NP Integer. (INPUT)
c Number of implicit shifts to be computed.
c
c RITZ Real array of length KEV+NP. (INPUT/OUTPUT)
c On INPUT, RITZ contains the eigenvalues of H.
c On OUTPUT, RITZ are sorted so that the unwanted eigenvalues
c are in the first NP locations and the wanted part is in
c the last KEV locations. When exact shifts are selected, the
c unwanted part corresponds to the shifts to be applied.
c
c BOUNDS Real array of length KEV+NP. (INPUT/OUTPUT)
c Error bounds corresponding to the ordering in RITZ.
c
c SHIFTS Real array of length NP. (INPUT/OUTPUT)
c On INPUT: contains the user specified shifts if ISHIFT = 0.
c On OUTPUT: contains the shifts sorted into decreasing order
c of magnitude with respect to the Ritz estimates contained in
c BOUNDS. If ISHIFT = 0, SHIFTS is not modified on exit.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c ssortr ARPACK utility sorting routine.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c svout ARPACK utility routine that prints vectors.
c scopy Level 1 BLAS that copies one vector to another.
c sswap Level 1 BLAS that swaps the contents of two vectors.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/93: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: sgets.F SID: 2.4 DATE OF SID: 4/19/96 RELEASE: 2
c
c\Remarks
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine ssgets ( ishift, which, kev, np, ritz, bounds, shifts )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
integer ishift, kev, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& bounds(kev+np), ritz(kev+np), shifts(np)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0, zero = 0.0E+0)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer kevd2, msglvl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external sswap, scopy, ssortr, second
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic max, min
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = msgets
c
if (which .eq. 'BE') then
c
c %-----------------------------------------------------%
c | Both ends of the spectrum are requested. |
c | Sort the eigenvalues into algebraically increasing |
c | order first then swap high end of the spectrum next |
c | to low end in appropriate locations. |
c | NOTE: when np < floor(kev/2) be careful not to swap |
c | overlapping locations. |
c %-----------------------------------------------------%
c
call ssortr ('LA', .true., kev+np, ritz, bounds)
kevd2 = kev / 2
if ( kev .gt. 1 ) then
call sswap ( min(kevd2,np), ritz, 1,
& ritz( max(kevd2,np)+1 ), 1)
call sswap ( min(kevd2,np), bounds, 1,
& bounds( max(kevd2,np)+1 ), 1)
end if
c
else
c
c %----------------------------------------------------%
c | LM, SM, LA, SA case. |
c | Sort the eigenvalues of H into the desired order |
c | and apply the resulting order to BOUNDS. |
c | The eigenvalues are sorted so that the wanted part |
c | are always in the last KEV locations. |
c %----------------------------------------------------%
c
call ssortr (which, .true., kev+np, ritz, bounds)
end if
c
if (ishift .eq. 1 .and. np .gt. 0) then
c
c %-------------------------------------------------------%
c | Sort the unwanted Ritz values used as shifts so that |
c | the ones with largest Ritz estimates are first. |
c | This will tend to minimize the effects of the |
c | forward instability of the iteration when the shifts |
c | are applied in subroutine ssapps. |
c %-------------------------------------------------------%
c
call ssortr ('SM', .true., np, bounds, ritz)
call scopy (np, ritz, 1, shifts, 1)
end if
c
call second (t1)
tsgets = tsgets + (t1 - t0)
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, kev, ndigit, '_sgets: KEV is')
call ivout (logfil, 1, np, ndigit, '_sgets: NP is')
call svout (logfil, kev+np, ritz, ndigit,
& '_sgets: Eigenvalues of current H matrix')
call svout (logfil, kev+np, bounds, ndigit,
& '_sgets: Associated Ritz estimates')
end if
c
return
c
c %---------------%
c | End of ssgets |
c %---------------%
c
end

344
arpack/ARPACK/SRC/ssortc.f Normal file
View File

@@ -0,0 +1,344 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: ssortc
c
c\Description:
c Sorts the complex array in XREAL and XIMAG into the order
c specified by WHICH and optionally applies the permutation to the
c real array Y. It is assumed that if an element of XIMAG is
c nonzero, then its negative is also an element. In other words,
c both members of a complex conjugate pair are to be sorted and the
c pairs are kept adjacent to each other.
c
c\Usage:
c call ssortc
c ( WHICH, APPLY, N, XREAL, XIMAG, Y )
c
c\Arguments
c WHICH Character*2. (Input)
c 'LM' -> sort XREAL,XIMAG into increasing order of magnitude.
c 'SM' -> sort XREAL,XIMAG into decreasing order of magnitude.
c 'LR' -> sort XREAL into increasing order of algebraic.
c 'SR' -> sort XREAL into decreasing order of algebraic.
c 'LI' -> sort XIMAG into increasing order of magnitude.
c 'SI' -> sort XIMAG into decreasing order of magnitude.
c NOTE: If an element of XIMAG is non-zero, then its negative
c is also an element.
c
c APPLY Logical. (Input)
c APPLY = .TRUE. -> apply the sorted order to array Y.
c APPLY = .FALSE. -> do not apply the sorted order to array Y.
c
c N Integer. (INPUT)
c Size of the arrays.
c
c XREAL, Real array of length N. (INPUT/OUTPUT)
c XIMAG Real and imaginary part of the array to be sorted.
c
c Y Real array of length N. (INPUT/OUTPUT)
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c xx/xx/92: Version ' 2.1'
c Adapted from the sort routine in LANSO.
c
c\SCCS Information: @(#)
c FILE: sortc.F SID: 2.3 DATE OF SID: 4/20/96 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine ssortc (which, apply, n, xreal, ximag, y)
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
logical apply
integer n
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& xreal(0:n-1), ximag(0:n-1), y(0:n-1)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, igap, j
Real
& temp, temp1, temp2
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& slapy2
external slapy2
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
igap = n / 2
c
if (which .eq. 'LM') then
c
c %------------------------------------------------------%
c | Sort XREAL,XIMAG into increasing order of magnitude. |
c %------------------------------------------------------%
c
10 continue
if (igap .eq. 0) go to 9000
c
do 30 i = igap, n-1
j = i-igap
20 continue
c
if (j.lt.0) go to 30
c
temp1 = slapy2(xreal(j),ximag(j))
temp2 = slapy2(xreal(j+igap),ximag(j+igap))
c
if (temp1.gt.temp2) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 30
end if
j = j-igap
go to 20
30 continue
igap = igap / 2
go to 10
c
else if (which .eq. 'SM') then
c
c %------------------------------------------------------%
c | Sort XREAL,XIMAG into decreasing order of magnitude. |
c %------------------------------------------------------%
c
40 continue
if (igap .eq. 0) go to 9000
c
do 60 i = igap, n-1
j = i-igap
50 continue
c
if (j .lt. 0) go to 60
c
temp1 = slapy2(xreal(j),ximag(j))
temp2 = slapy2(xreal(j+igap),ximag(j+igap))
c
if (temp1.lt.temp2) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 60
endif
j = j-igap
go to 50
60 continue
igap = igap / 2
go to 40
c
else if (which .eq. 'LR') then
c
c %------------------------------------------------%
c | Sort XREAL into increasing order of algebraic. |
c %------------------------------------------------%
c
70 continue
if (igap .eq. 0) go to 9000
c
do 90 i = igap, n-1
j = i-igap
80 continue
c
if (j.lt.0) go to 90
c
if (xreal(j).gt.xreal(j+igap)) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 90
endif
j = j-igap
go to 80
90 continue
igap = igap / 2
go to 70
c
else if (which .eq. 'SR') then
c
c %------------------------------------------------%
c | Sort XREAL into decreasing order of algebraic. |
c %------------------------------------------------%
c
100 continue
if (igap .eq. 0) go to 9000
do 120 i = igap, n-1
j = i-igap
110 continue
c
if (j.lt.0) go to 120
c
if (xreal(j).lt.xreal(j+igap)) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 120
endif
j = j-igap
go to 110
120 continue
igap = igap / 2
go to 100
c
else if (which .eq. 'LI') then
c
c %------------------------------------------------%
c | Sort XIMAG into increasing order of magnitude. |
c %------------------------------------------------%
c
130 continue
if (igap .eq. 0) go to 9000
do 150 i = igap, n-1
j = i-igap
140 continue
c
if (j.lt.0) go to 150
c
if (abs(ximag(j)).gt.abs(ximag(j+igap))) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 150
endif
j = j-igap
go to 140
150 continue
igap = igap / 2
go to 130
c
else if (which .eq. 'SI') then
c
c %------------------------------------------------%
c | Sort XIMAG into decreasing order of magnitude. |
c %------------------------------------------------%
c
160 continue
if (igap .eq. 0) go to 9000
do 180 i = igap, n-1
j = i-igap
170 continue
c
if (j.lt.0) go to 180
c
if (abs(ximag(j)).lt.abs(ximag(j+igap))) then
temp = xreal(j)
xreal(j) = xreal(j+igap)
xreal(j+igap) = temp
c
temp = ximag(j)
ximag(j) = ximag(j+igap)
ximag(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 180
endif
j = j-igap
go to 170
180 continue
igap = igap / 2
go to 160
end if
c
9000 continue
return
c
c %---------------%
c | End of ssortc |
c %---------------%
c
end

218
arpack/ARPACK/SRC/ssortr.f Normal file
View File

@@ -0,0 +1,218 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: ssortr
c
c\Description:
c Sort the array X1 in the order specified by WHICH and optionally
c applies the permutation to the array X2.
c
c\Usage:
c call ssortr
c ( WHICH, APPLY, N, X1, X2 )
c
c\Arguments
c WHICH Character*2. (Input)
c 'LM' -> X1 is sorted into increasing order of magnitude.
c 'SM' -> X1 is sorted into decreasing order of magnitude.
c 'LA' -> X1 is sorted into increasing order of algebraic.
c 'SA' -> X1 is sorted into decreasing order of algebraic.
c
c APPLY Logical. (Input)
c APPLY = .TRUE. -> apply the sorted order to X2.
c APPLY = .FALSE. -> do not apply the sorted order to X2.
c
c N Integer. (INPUT)
c Size of the arrays.
c
c X1 Real array of length N. (INPUT/OUTPUT)
c The array to be sorted.
c
c X2 Real array of length N. (INPUT/OUTPUT)
c Only referenced if APPLY = .TRUE.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/16/93: Version ' 2.1'.
c Adapted from the sort routine in LANSO.
c
c\SCCS Information: @(#)
c FILE: sortr.F SID: 2.3 DATE OF SID: 4/19/96 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine ssortr (which, apply, n, x1, x2)
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
logical apply
integer n
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& x1(0:n-1), x2(0:n-1)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, igap, j
Real
& temp
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
igap = n / 2
c
if (which .eq. 'SA') then
c
c X1 is sorted into decreasing order of algebraic.
c
10 continue
if (igap .eq. 0) go to 9000
do 30 i = igap, n-1
j = i-igap
20 continue
c
if (j.lt.0) go to 30
c
if (x1(j).lt.x1(j+igap)) then
temp = x1(j)
x1(j) = x1(j+igap)
x1(j+igap) = temp
if (apply) then
temp = x2(j)
x2(j) = x2(j+igap)
x2(j+igap) = temp
end if
else
go to 30
endif
j = j-igap
go to 20
30 continue
igap = igap / 2
go to 10
c
else if (which .eq. 'SM') then
c
c X1 is sorted into decreasing order of magnitude.
c
40 continue
if (igap .eq. 0) go to 9000
do 60 i = igap, n-1
j = i-igap
50 continue
c
if (j.lt.0) go to 60
c
if (abs(x1(j)).lt.abs(x1(j+igap))) then
temp = x1(j)
x1(j) = x1(j+igap)
x1(j+igap) = temp
if (apply) then
temp = x2(j)
x2(j) = x2(j+igap)
x2(j+igap) = temp
end if
else
go to 60
endif
j = j-igap
go to 50
60 continue
igap = igap / 2
go to 40
c
else if (which .eq. 'LA') then
c
c X1 is sorted into increasing order of algebraic.
c
70 continue
if (igap .eq. 0) go to 9000
do 90 i = igap, n-1
j = i-igap
80 continue
c
if (j.lt.0) go to 90
c
if (x1(j).gt.x1(j+igap)) then
temp = x1(j)
x1(j) = x1(j+igap)
x1(j+igap) = temp
if (apply) then
temp = x2(j)
x2(j) = x2(j+igap)
x2(j+igap) = temp
end if
else
go to 90
endif
j = j-igap
go to 80
90 continue
igap = igap / 2
go to 70
c
else if (which .eq. 'LM') then
c
c X1 is sorted into increasing order of magnitude.
c
100 continue
if (igap .eq. 0) go to 9000
do 120 i = igap, n-1
j = i-igap
110 continue
c
if (j.lt.0) go to 120
c
if (abs(x1(j)).gt.abs(x1(j+igap))) then
temp = x1(j)
x1(j) = x1(j+igap)
x1(j+igap) = temp
if (apply) then
temp = x2(j)
x2(j) = x2(j+igap)
x2(j+igap) = temp
end if
else
go to 120
endif
j = j-igap
go to 110
120 continue
igap = igap / 2
go to 100
end if
c
9000 continue
return
c
c %---------------%
c | End of ssortr |
c %---------------%
c
end

View File

@@ -0,0 +1,61 @@
c
c %---------------------------------------------%
c | Initialize statistic and timing information |
c | for nonsymmetric Arnoldi code. |
c %---------------------------------------------%
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: statn.F SID: 2.4 DATE OF SID: 4/20/96 RELEASE: 2
c
subroutine sstatn
c
c %--------------------------------%
c | See stat.doc for documentation |
c %--------------------------------%
c
include 'stat.h'
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
nopx = 0
nbx = 0
nrorth = 0
nitref = 0
nrstrt = 0
c
tnaupd = 0.0E+0
tnaup2 = 0.0E+0
tnaitr = 0.0E+0
tneigh = 0.0E+0
tngets = 0.0E+0
tnapps = 0.0E+0
tnconv = 0.0E+0
titref = 0.0E+0
tgetv0 = 0.0E+0
trvec = 0.0E+0
c
c %----------------------------------------------------%
c | User time including reverse communication overhead |
c %----------------------------------------------------%
c
tmvopx = 0.0E+0
tmvbx = 0.0E+0
c
return
c
c
c %---------------%
c | End of sstatn |
c %---------------%
c
end

View File

@@ -0,0 +1,47 @@
c
c\SCCS Information: @(#)
c FILE: stats.F SID: 2.1 DATE OF SID: 4/19/96 RELEASE: 2
c %---------------------------------------------%
c | Initialize statistic and timing information |
c | for symmetric Arnoldi code. |
c %---------------------------------------------%
subroutine sstats
c %--------------------------------%
c | See stat.doc for documentation |
c %--------------------------------%
include 'stat.h'
c %-----------------------%
c | Executable Statements |
c %-----------------------%
nopx = 0
nbx = 0
nrorth = 0
nitref = 0
nrstrt = 0
tsaupd = 0.0E+0
tsaup2 = 0.0E+0
tsaitr = 0.0E+0
tseigt = 0.0E+0
tsgets = 0.0E+0
tsapps = 0.0E+0
tsconv = 0.0E+0
titref = 0.0E+0
tgetv0 = 0.0E+0
trvec = 0.0E+0
c %----------------------------------------------------%
c | User time including reverse communication overhead |
c %----------------------------------------------------%
tmvopx = 0.0E+0
tmvbx = 0.0E+0
return
c
c End of sstats
c
end

594
arpack/ARPACK/SRC/sstqrb.f Normal file
View File

@@ -0,0 +1,594 @@
c-----------------------------------------------------------------------
c\BeginDoc
c
c\Name: sstqrb
c
c\Description:
c Computes all eigenvalues and the last component of the eigenvectors
c of a symmetric tridiagonal matrix using the implicit QL or QR method.
c
c This is mostly a modification of the LAPACK routine ssteqr.
c See Remarks.
c
c\Usage:
c call sstqrb
c ( N, D, E, Z, WORK, INFO )
c
c\Arguments
c N Integer. (INPUT)
c The number of rows and columns in the matrix. N >= 0.
c
c D Real array, dimension (N). (INPUT/OUTPUT)
c On entry, D contains the diagonal elements of the
c tridiagonal matrix.
c On exit, D contains the eigenvalues, in ascending order.
c If an error exit is made, the eigenvalues are correct
c for indices 1,2,...,INFO-1, but they are unordered and
c may not be the smallest eigenvalues of the matrix.
c
c E Real array, dimension (N-1). (INPUT/OUTPUT)
c On entry, E contains the subdiagonal elements of the
c tridiagonal matrix in positions 1 through N-1.
c On exit, E has been destroyed.
c
c Z Real array, dimension (N). (OUTPUT)
c On exit, Z contains the last row of the orthonormal
c eigenvector matrix of the symmetric tridiagonal matrix.
c If an error exit is made, Z contains the last row of the
c eigenvector matrix associated with the stored eigenvalues.
c
c WORK Real array, dimension (max(1,2*N-2)). (WORKSPACE)
c Workspace used in accumulating the transformation for
c computing the last components of the eigenvectors.
c
c INFO Integer. (OUTPUT)
c = 0: normal return.
c < 0: if INFO = -i, the i-th argument had an illegal value.
c > 0: if INFO = +i, the i-th eigenvalue has not converged
c after a total of 30*N iterations.
c
c\Remarks
c 1. None.
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx real
c
c\Routines called:
c saxpy Level 1 BLAS that computes a vector triad.
c scopy Level 1 BLAS that copies one vector to another.
c sswap Level 1 BLAS that swaps the contents of two vectors.
c lsame LAPACK character comparison routine.
c slae2 LAPACK routine that computes the eigenvalues of a 2-by-2
c symmetric matrix.
c slaev2 LAPACK routine that eigendecomposition of a 2-by-2 symmetric
c matrix.
c slamch LAPACK routine that determines machine constants.
c slanst LAPACK routine that computes the norm of a matrix.
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c slartg LAPACK Givens rotation construction routine.
c slascl LAPACK routine for careful scaling of a matrix.
c slaset LAPACK matrix initialization routine.
c slasr LAPACK routine that applies an orthogonal transformation to
c a matrix.
c slasrt LAPACK sorting routine.
c ssteqr LAPACK routine that computes eigenvalues and eigenvectors
c of a symmetric tridiagonal matrix.
c xerbla LAPACK error handler routine.
c
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: stqrb.F SID: 2.5 DATE OF SID: 8/27/96 RELEASE: 2
c
c\Remarks
c 1. Starting with version 2.5, this routine is a modified version
c of LAPACK version 2.0 subroutine SSTEQR. No lines are deleted,
c only commeted out and new lines inserted.
c All lines commented out have "c$$$" at the beginning.
c Note that the LAPACK version 1.0 subroutine SSTEQR contained
c bugs.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine sstqrb ( n, d, e, z, work, info )
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer info, n
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Real
& d( n ), e( n-1 ), z( n ), work( 2*n-2 )
c
c .. parameters ..
Real
& zero, one, two, three
parameter ( zero = 0.0E+0, one = 1.0E+0,
& two = 2.0E+0, three = 3.0E+0 )
integer maxit
parameter ( maxit = 30 )
c ..
c .. local scalars ..
integer i, icompz, ii, iscale, j, jtot, k, l, l1, lend,
& lendm1, lendp1, lendsv, lm1, lsv, m, mm, mm1,
& nm1, nmaxit
Real
& anorm, b, c, eps, eps2, f, g, p, r, rt1, rt2,
& s, safmax, safmin, ssfmax, ssfmin, tst
c ..
c .. external functions ..
logical lsame
Real
& slamch, slanst, slapy2
external lsame, slamch, slanst, slapy2
c ..
c .. external subroutines ..
external slae2, slaev2, slartg, slascl, slaset, slasr,
& slasrt, sswap, xerbla
c ..
c .. intrinsic functions ..
intrinsic abs, max, sign, sqrt
c ..
c .. executable statements ..
c
c test the input parameters.
c
info = 0
c
c$$$ IF( LSAME( COMPZ, 'N' ) ) THEN
c$$$ ICOMPZ = 0
c$$$ ELSE IF( LSAME( COMPZ, 'V' ) ) THEN
c$$$ ICOMPZ = 1
c$$$ ELSE IF( LSAME( COMPZ, 'I' ) ) THEN
c$$$ ICOMPZ = 2
c$$$ ELSE
c$$$ ICOMPZ = -1
c$$$ END IF
c$$$ IF( ICOMPZ.LT.0 ) THEN
c$$$ INFO = -1
c$$$ ELSE IF( N.LT.0 ) THEN
c$$$ INFO = -2
c$$$ ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1,
c$$$ $ N ) ) ) THEN
c$$$ INFO = -6
c$$$ END IF
c$$$ IF( INFO.NE.0 ) THEN
c$$$ CALL XERBLA( 'SSTEQR', -INFO )
c$$$ RETURN
c$$$ END IF
c
c *** New starting with version 2.5 ***
c
icompz = 2
c *************************************
c
c quick return if possible
c
if( n.eq.0 )
$ return
c
if( n.eq.1 ) then
if( icompz.eq.2 ) z( 1 ) = one
return
end if
c
c determine the unit roundoff and over/underflow thresholds.
c
eps = slamch( 'e' )
eps2 = eps**2
safmin = slamch( 's' )
safmax = one / safmin
ssfmax = sqrt( safmax ) / three
ssfmin = sqrt( safmin ) / eps2
c
c compute the eigenvalues and eigenvectors of the tridiagonal
c matrix.
c
c$$ if( icompz.eq.2 )
c$$$ $ call slaset( 'full', n, n, zero, one, z, ldz )
c
c *** New starting with version 2.5 ***
c
if ( icompz .eq. 2 ) then
do 5 j = 1, n-1
z(j) = zero
5 continue
z( n ) = one
end if
c *************************************
c
nmaxit = n*maxit
jtot = 0
c
c determine where the matrix splits and choose ql or qr iteration
c for each block, according to whether top or bottom diagonal
c element is smaller.
c
l1 = 1
nm1 = n - 1
c
10 continue
if( l1.gt.n )
$ go to 160
if( l1.gt.1 )
$ e( l1-1 ) = zero
if( l1.le.nm1 ) then
do 20 m = l1, nm1
tst = abs( e( m ) )
if( tst.eq.zero )
$ go to 30
if( tst.le.( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+
$ 1 ) ) ) )*eps ) then
e( m ) = zero
go to 30
end if
20 continue
end if
m = n
c
30 continue
l = l1
lsv = l
lend = m
lendsv = lend
l1 = m + 1
if( lend.eq.l )
$ go to 10
c
c scale submatrix in rows and columns l to lend
c
anorm = slanst( 'i', lend-l+1, d( l ), e( l ) )
iscale = 0
if( anorm.eq.zero )
$ go to 10
if( anorm.gt.ssfmax ) then
iscale = 1
call slascl( 'g', 0, 0, anorm, ssfmax, lend-l+1, 1, d( l ), n,
$ info )
call slascl( 'g', 0, 0, anorm, ssfmax, lend-l, 1, e( l ), n,
$ info )
else if( anorm.lt.ssfmin ) then
iscale = 2
call slascl( 'g', 0, 0, anorm, ssfmin, lend-l+1, 1, d( l ), n,
$ info )
call slascl( 'g', 0, 0, anorm, ssfmin, lend-l, 1, e( l ), n,
$ info )
end if
c
c choose between ql and qr iteration
c
if( abs( d( lend ) ).lt.abs( d( l ) ) ) then
lend = lsv
l = lendsv
end if
c
if( lend.gt.l ) then
c
c ql iteration
c
c look for small subdiagonal element.
c
40 continue
if( l.ne.lend ) then
lendm1 = lend - 1
do 50 m = l, lendm1
tst = abs( e( m ) )**2
if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+
$ safmin )go to 60
50 continue
end if
c
m = lend
c
60 continue
if( m.lt.lend )
$ e( m ) = zero
p = d( l )
if( m.eq.l )
$ go to 80
c
c if remaining matrix is 2-by-2, use slae2 or slaev2
c to compute its eigensystem.
c
if( m.eq.l+1 ) then
if( icompz.gt.0 ) then
call slaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s )
work( l ) = c
work( n-1+l ) = s
c$$$ call slasr( 'r', 'v', 'b', n, 2, work( l ),
c$$$ $ work( n-1+l ), z( 1, l ), ldz )
c
c *** New starting with version 2.5 ***
c
tst = z(l+1)
z(l+1) = c*tst - s*z(l)
z(l) = s*tst + c*z(l)
c *************************************
else
call slae2( d( l ), e( l ), d( l+1 ), rt1, rt2 )
end if
d( l ) = rt1
d( l+1 ) = rt2
e( l ) = zero
l = l + 2
if( l.le.lend )
$ go to 40
go to 140
end if
c
if( jtot.eq.nmaxit )
$ go to 140
jtot = jtot + 1
c
c form shift.
c
g = ( d( l+1 )-p ) / ( two*e( l ) )
r = slapy2( g, one )
g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) )
c
s = one
c = one
p = zero
c
c inner loop
c
mm1 = m - 1
do 70 i = mm1, l, -1
f = s*e( i )
b = c*e( i )
call slartg( g, f, c, s, r )
if( i.ne.m-1 )
$ e( i+1 ) = r
g = d( i+1 ) - p
r = ( d( i )-g )*s + two*c*b
p = s*r
d( i+1 ) = g + p
g = c*r - b
c
c if eigenvectors are desired, then save rotations.
c
if( icompz.gt.0 ) then
work( i ) = c
work( n-1+i ) = -s
end if
c
70 continue
c
c if eigenvectors are desired, then apply saved rotations.
c
if( icompz.gt.0 ) then
mm = m - l + 1
c$$$ call slasr( 'r', 'v', 'b', n, mm, work( l ), work( n-1+l ),
c$$$ $ z( 1, l ), ldz )
c
c *** New starting with version 2.5 ***
c
call slasr( 'r', 'v', 'b', 1, mm, work( l ),
& work( n-1+l ), z( l ), 1 )
c *************************************
end if
c
d( l ) = d( l ) - p
e( l ) = g
go to 40
c
c eigenvalue found.
c
80 continue
d( l ) = p
c
l = l + 1
if( l.le.lend )
$ go to 40
go to 140
c
else
c
c qr iteration
c
c look for small superdiagonal element.
c
90 continue
if( l.ne.lend ) then
lendp1 = lend + 1
do 100 m = l, lendp1, -1
tst = abs( e( m-1 ) )**2
if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+
$ safmin )go to 110
100 continue
end if
c
m = lend
c
110 continue
if( m.gt.lend )
$ e( m-1 ) = zero
p = d( l )
if( m.eq.l )
$ go to 130
c
c if remaining matrix is 2-by-2, use slae2 or slaev2
c to compute its eigensystem.
c
if( m.eq.l-1 ) then
if( icompz.gt.0 ) then
call slaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s )
c$$$ work( m ) = c
c$$$ work( n-1+m ) = s
c$$$ call slasr( 'r', 'v', 'f', n, 2, work( m ),
c$$$ $ work( n-1+m ), z( 1, l-1 ), ldz )
c
c *** New starting with version 2.5 ***
c
tst = z(l)
z(l) = c*tst - s*z(l-1)
z(l-1) = s*tst + c*z(l-1)
c *************************************
else
call slae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 )
end if
d( l-1 ) = rt1
d( l ) = rt2
e( l-1 ) = zero
l = l - 2
if( l.ge.lend )
$ go to 90
go to 140
end if
c
if( jtot.eq.nmaxit )
$ go to 140
jtot = jtot + 1
c
c form shift.
c
g = ( d( l-1 )-p ) / ( two*e( l-1 ) )
r = slapy2( g, one )
g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) )
c
s = one
c = one
p = zero
c
c inner loop
c
lm1 = l - 1
do 120 i = m, lm1
f = s*e( i )
b = c*e( i )
call slartg( g, f, c, s, r )
if( i.ne.m )
$ e( i-1 ) = r
g = d( i ) - p
r = ( d( i+1 )-g )*s + two*c*b
p = s*r
d( i ) = g + p
g = c*r - b
c
c if eigenvectors are desired, then save rotations.
c
if( icompz.gt.0 ) then
work( i ) = c
work( n-1+i ) = s
end if
c
120 continue
c
c if eigenvectors are desired, then apply saved rotations.
c
if( icompz.gt.0 ) then
mm = l - m + 1
c$$$ call slasr( 'r', 'v', 'f', n, mm, work( m ), work( n-1+m ),
c$$$ $ z( 1, m ), ldz )
c
c *** New starting with version 2.5 ***
c
call slasr( 'r', 'v', 'f', 1, mm, work( m ), work( n-1+m ),
& z( m ), 1 )
c *************************************
end if
c
d( l ) = d( l ) - p
e( lm1 ) = g
go to 90
c
c eigenvalue found.
c
130 continue
d( l ) = p
c
l = l - 1
if( l.ge.lend )
$ go to 90
go to 140
c
end if
c
c undo scaling if necessary
c
140 continue
if( iscale.eq.1 ) then
call slascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv+1, 1,
$ d( lsv ), n, info )
call slascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv, 1, e( lsv ),
$ n, info )
else if( iscale.eq.2 ) then
call slascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv+1, 1,
$ d( lsv ), n, info )
call slascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv, 1, e( lsv ),
$ n, info )
end if
c
c check for no convergence to an eigenvalue after a total
c of n*maxit iterations.
c
if( jtot.lt.nmaxit )
$ go to 10
do 150 i = 1, n - 1
if( e( i ).ne.zero )
$ info = info + 1
150 continue
go to 190
c
c order eigenvalues and eigenvectors.
c
160 continue
if( icompz.eq.0 ) then
c
c use quick sort
c
call slasrt( 'i', n, d, info )
c
else
c
c use selection sort to minimize swaps of eigenvectors
c
do 180 ii = 2, n
i = ii - 1
k = i
p = d( i )
do 170 j = ii, n
if( d( j ).lt.p ) then
k = j
p = d( j )
end if
170 continue
if( k.ne.i ) then
d( k ) = d( i )
d( i ) = p
c$$$ call sswap( n, z( 1, i ), 1, z( 1, k ), 1 )
c *** New starting with version 2.5 ***
c
p = z(k)
z(k) = z(i)
z(i) = p
c *************************************
end if
180 continue
end if
c
190 continue
return
c
c %---------------%
c | End of sstqrb |
c %---------------%
c
end

21
arpack/ARPACK/SRC/stat.h Normal file
View File

@@ -0,0 +1,21 @@
c %--------------------------------%
c | See stat.doc for documentation |
c %--------------------------------%
c
c\SCCS Information: @(#)
c FILE: stat.h SID: 2.2 DATE OF SID: 11/16/95 RELEASE: 2
c
real t0, t1, t2, t3, t4, t5
save t0, t1, t2, t3, t4, t5
c
integer nopx, nbx, nrorth, nitref, nrstrt
real tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv,
& tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv,
& tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv,
& tmvopx, tmvbx, tgetv0, titref, trvec
common /timing/
& nopx, nbx, nrorth, nitref, nrstrt,
& tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv,
& tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv,
& tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv,
& tmvopx, tmvbx, tgetv0, titref, trvec

View File

@@ -0,0 +1,30 @@
/*
In the current version, the parameter KAPPA in the Kahan's test
for orthogonality is set to 0.717, the same as used by Gragg & Reichel.
However computational experience indicates that this is a little too
strict and will frequently force reorthogonalization when it is not
necessary to do so.
Also the "moving boundary" idea is not currently activated in the nonsymmetric
code since it is not conclusive that it's the right thing to do all the time.
Requires further investigation.
As of 02/01/93 Richard Lehoucq assumes software control of the codes from
Phuong Vu. On 03/01/93 all the *.F files were migrated SCCS. The 1.1 version
of codes are those received from Phuong Vu. The frozen version of 07/08/92
is now considered version 1.1.
Version 2.1 contains two new symmetric routines, sesrt and seupd.
Changes as well as bug fixes for version 1.1 codes that were only corrected
for programming bugs are version 1.2. These 1.2 versions will also be in version 2.1.
Subroutine [d,s]saupd now requires slightly more workspace. See [d,s]saupd for the
details.
\SCCS Information: @(#)
FILE: version.h SID: 2.3 DATE OF SID: 11/16/95 RELEASE: 2
*/
#define VERSION_NUMBER ' 2.1'
#define VERSION_DATE ' 11/15/95'

414
arpack/ARPACK/SRC/zgetv0.f Normal file
View File

@@ -0,0 +1,414 @@
c\BeginDoc
c
c\Name: zgetv0
c
c\Description:
c Generate a random initial residual vector for the Arnoldi process.
c Force the residual vector to be in the range of the operator OP.
c
c\Usage:
c call zgetv0
c ( IDO, BMAT, ITRY, INITV, N, J, V, LDV, RESID, RNORM,
c IPNTR, WORKD, IERR )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag. IDO must be zero on the first
c call to zgetv0.
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c This is for the initialization phase to force the
c starting vector into the range of OP.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c IDO = 99: done
c -------------------------------------------------------------
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B in the (generalized)
c eigenvalue problem A*x = lambda*B*x.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*B*x
c
c ITRY Integer. (INPUT)
c ITRY counts the number of times that zgetv0 is called.
c It should be set to 1 on the initial call to zgetv0.
c
c INITV Logical variable. (INPUT)
c .TRUE. => the initial residual vector is given in RESID.
c .FALSE. => generate a random initial residual vector.
c
c N Integer. (INPUT)
c Dimension of the problem.
c
c J Integer. (INPUT)
c Index of the residual vector to be generated, with respect to
c the Arnoldi process. J > 1 in case of a "restart".
c
c V Complex*16 N by J array. (INPUT)
c The first J-1 columns of V contain the current Arnoldi basis
c if this is a "restart".
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c RESID Complex*16 array of length N. (INPUT/OUTPUT)
c Initial residual vector to be generated. If RESID is
c provided, force RESID into the range of the operator OP.
c
c RNORM Double precision scalar. (OUTPUT)
c B-norm of the generated residual.
c
c IPNTR Integer array of length 3. (OUTPUT)
c
c WORKD Complex*16 work array of length 2*N. (REVERSE COMMUNICATION).
c On exit, WORK(1:N) = B*RESID to be used in SSAITR.
c
c IERR Integer. (OUTPUT)
c = 0: Normal exit.
c = -1: Cannot generate a nontrivial restarted residual vector
c in the range of the operator OP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex*16
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c
c\Routines called:
c second ARPACK utility routine for timing.
c zvout ARPACK utility routine that prints vectors.
c zlarnv LAPACK routine for generating a random vector.
c zgemv Level 2 BLAS routine for matrix vector multiplication.
c zcopy Level 1 BLAS that copies one vector to another.
c zdotc Level 1 BLAS that computes the scalar product of two vectors.
c dznrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: getv0.F SID: 2.3 DATE OF SID: 08/27/96 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine zgetv0
& ( ido, bmat, itry, initv, n, j, v, ldv, resid, rnorm,
& ipntr, workd, ierr )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1
logical initv
integer ido, ierr, itry, j, ldv, n
Double precision
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Complex*16
& resid(n), v(ldv,j), workd(2*n)
c
c %------------%
c | Parameters |
c %------------%
c
Complex*16
& one, zero
Double precision
& rzero
parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0),
& rzero = 0.0D+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
logical first, inits, orth
integer idist, iseed(4), iter, msglvl, jj
Double precision
& rnorm0
Complex*16
& cnorm
save first, iseed, inits, iter, msglvl, orth, rnorm0
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external zcopy, zgemv, zlarnv, zvout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dznrm2, dlapy2
Complex*16
& zdotc
external zdotc, dznrm2, dlapy2
c
c %-----------------%
c | Data Statements |
c %-----------------%
c
data inits /.true./
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c
c %-----------------------------------%
c | Initialize the seed of the LAPACK |
c | random number generator |
c %-----------------------------------%
c
if (inits) then
iseed(1) = 1
iseed(2) = 3
iseed(3) = 5
iseed(4) = 7
inits = .false.
end if
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mgetv0
c
ierr = 0
iter = 0
first = .FALSE.
orth = .FALSE.
c
c %-----------------------------------------------------%
c | Possibly generate a random starting vector in RESID |
c | Use a LAPACK random number generator used by the |
c | matrix generation routines. |
c | idist = 1: uniform (0,1) distribution; |
c | idist = 2: uniform (-1,1) distribution; |
c | idist = 3: normal (0,1) distribution; |
c %-----------------------------------------------------%
c
if (.not.initv) then
idist = 2
call zlarnv (idist, iseed, n, resid)
end if
c
c %----------------------------------------------------------%
c | Force the starting vector into the range of OP to handle |
c | the generalized problem when B is possibly (singular). |
c %----------------------------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nopx = nopx + 1
ipntr(1) = 1
ipntr(2) = n + 1
call zcopy (n, resid, 1, workd, 1)
ido = -1
go to 9000
end if
end if
c
c %----------------------------------------%
c | Back from computing B*(initial-vector) |
c %----------------------------------------%
c
if (first) go to 20
c
c %-----------------------------------------------%
c | Back from computing B*(orthogonalized-vector) |
c %-----------------------------------------------%
c
if (orth) go to 40
c
call second (t3)
tmvopx = tmvopx + (t3 - t2)
c
c %------------------------------------------------------%
c | Starting vector is now in the range of OP; r = OP*r; |
c | Compute B-norm of starting vector. |
c %------------------------------------------------------%
c
call second (t2)
first = .TRUE.
if (bmat .eq. 'G') then
nbx = nbx + 1
call zcopy (n, workd(n+1), 1, resid, 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
go to 9000
else if (bmat .eq. 'I') then
call zcopy (n, resid, 1, workd, 1)
end if
c
20 continue
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
first = .FALSE.
if (bmat .eq. 'G') then
cnorm = zdotc (n, resid, 1, workd, 1)
rnorm0 = sqrt(dlapy2(dble(cnorm),dimag(cnorm)))
else if (bmat .eq. 'I') then
rnorm0 = dznrm2(n, resid, 1)
end if
rnorm = rnorm0
c
c %---------------------------------------------%
c | Exit if this is the very first Arnoldi step |
c %---------------------------------------------%
c
if (j .eq. 1) go to 50
c
c %----------------------------------------------------------------
c | Otherwise need to B-orthogonalize the starting vector against |
c | the current Arnoldi basis using Gram-Schmidt with iter. ref. |
c | This is the case where an invariant subspace is encountered |
c | in the middle of the Arnoldi factorization. |
c | |
c | s = V^{T}*B*r; r = r - V*s; |
c | |
c | Stopping criteria used for iter. ref. is discussed in |
c | Parlett's book, page 107 and in Gragg & Reichel TOMS paper. |
c %---------------------------------------------------------------%
c
orth = .TRUE.
30 continue
c
call zgemv ('C', n, j-1, one, v, ldv, workd, 1,
& zero, workd(n+1), 1)
call zgemv ('N', n, j-1, -one, v, ldv, workd(n+1), 1,
& one, resid, 1)
c
c %----------------------------------------------------------%
c | Compute the B-norm of the orthogonalized starting vector |
c %----------------------------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call zcopy (n, resid, 1, workd(n+1), 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
go to 9000
else if (bmat .eq. 'I') then
call zcopy (n, resid, 1, workd, 1)
end if
c
40 continue
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
if (bmat .eq. 'G') then
cnorm = zdotc (n, resid, 1, workd, 1)
rnorm = sqrt(dlapy2(dble(cnorm),dimag(cnorm)))
else if (bmat .eq. 'I') then
rnorm = dznrm2(n, resid, 1)
end if
c
c %--------------------------------------%
c | Check for further orthogonalization. |
c %--------------------------------------%
c
if (msglvl .gt. 2) then
call dvout (logfil, 1, rnorm0, ndigit,
& '_getv0: re-orthonalization ; rnorm0 is')
call dvout (logfil, 1, rnorm, ndigit,
& '_getv0: re-orthonalization ; rnorm is')
end if
c
if (rnorm .gt. 0.717*rnorm0) go to 50
c
iter = iter + 1
if (iter .le. 1) then
c
c %-----------------------------------%
c | Perform iterative refinement step |
c %-----------------------------------%
c
rnorm0 = rnorm
go to 30
else
c
c %------------------------------------%
c | Iterative refinement step "failed" |
c %------------------------------------%
c
do 45 jj = 1, n
resid(jj) = zero
45 continue
rnorm = rzero
ierr = -1
end if
c
50 continue
c
if (msglvl .gt. 0) then
call dvout (logfil, 1, rnorm, ndigit,
& '_getv0: B-norm of initial / restarted starting vector')
end if
if (msglvl .gt. 2) then
call zvout (logfil, n, resid, ndigit,
& '_getv0: initial / restarted starting vector')
end if
ido = 99
c
call second (t1)
tgetv0 = tgetv0 + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of zgetv0 |
c %---------------%
c
end

850
arpack/ARPACK/SRC/znaitr.f Normal file
View File

@@ -0,0 +1,850 @@
c\BeginDoc
c
c\Name: znaitr
c
c\Description:
c Reverse communication interface for applying NP additional steps to
c a K step nonsymmetric Arnoldi factorization.
c
c Input: OP*V_{k} - V_{k}*H = r_{k}*e_{k}^T
c
c with (V_{k}^T)*B*V_{k} = I, (V_{k}^T)*B*r_{k} = 0.
c
c Output: OP*V_{k+p} - V_{k+p}*H = r_{k+p}*e_{k+p}^T
c
c with (V_{k+p}^T)*B*V_{k+p} = I, (V_{k+p}^T)*B*r_{k+p} = 0.
c
c where OP and B are as in znaupd. The B-norm of r_{k+p} is also
c computed and returned.
c
c\Usage:
c call znaitr
c ( IDO, BMAT, N, K, NP, NB, RESID, RNORM, V, LDV, H, LDH,
c IPNTR, WORKD, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag.
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c This is for the restart phase to force the new
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y,
c IPNTR(3) is the pointer into WORK for B * X.
c IDO = 2: compute Y = B * X where
c IPNTR(1) is the pointer into WORK for X,
c IPNTR(2) is the pointer into WORK for Y.
c IDO = 99: done
c -------------------------------------------------------------
c When the routine is used in the "shift-and-invert" mode, the
c vector B * Q is already available and do not need to be
c recomputed in forming OP * Q.
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B that defines the
c semi-inner product for the operator OP. See znaupd.
c B = 'I' -> standard eigenvalue problem A*x = lambda*x
c B = 'G' -> generalized eigenvalue problem A*x = lambda*M**x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c K Integer. (INPUT)
c Current size of V and H.
c
c NP Integer. (INPUT)
c Number of additional Arnoldi steps to take.
c
c NB Integer. (INPUT)
c Blocksize to be used in the recurrence.
c Only work for NB = 1 right now. The goal is to have a
c program that implement both the block and non-block method.
c
c RESID Complex*16 array of length N. (INPUT/OUTPUT)
c On INPUT: RESID contains the residual vector r_{k}.
c On OUTPUT: RESID contains the residual vector r_{k+p}.
c
c RNORM Double precision scalar. (INPUT/OUTPUT)
c B-norm of the starting residual on input.
c B-norm of the updated residual r_{k+p} on output.
c
c V Complex*16 N by K+NP array. (INPUT/OUTPUT)
c On INPUT: V contains the Arnoldi vectors in the first K
c columns.
c On OUTPUT: V contains the new NP Arnoldi vectors in the next
c NP columns. The first K columns are unchanged.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Complex*16 (K+NP) by (K+NP) array. (INPUT/OUTPUT)
c H is used to store the generated upper Hessenberg matrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORK for
c vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in the
c shift-and-invert mode. X is the current operand.
c -------------------------------------------------------------
c
c WORKD Complex*16 work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The calling program should not
c use WORKD as temporary workspace during the iteration !!!!!!
c On input, WORKD(1:N) = B*RESID and is used to save some
c computation at the first step.
c
c INFO Integer. (OUTPUT)
c = 0: Normal exit.
c > 0: Size of the spanning invariant subspace of OP found.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex*16
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c zgetv0 ARPACK routine to generate the initial vector.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c zmout ARPACK utility routine that prints matrices
c zvout ARPACK utility routine that prints vectors.
c zlanhs LAPACK routine that computes various norms of a matrix.
c zlascl LAPACK routine for careful scaling of a matrix.
c dlabad LAPACK routine for defining the underflow and overflow
c limits.
c dlamch LAPACK routine that determines machine constants.
c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c zgemv Level 2 BLAS routine for matrix vector multiplication.
c zaxpy Level 1 BLAS that computes a vector triad.
c zcopy Level 1 BLAS that copies one vector to another .
c zdotc Level 1 BLAS that computes the scalar product of two vectors.
c zscal Level 1 BLAS that scales a vector.
c zdscal Level 1 BLAS that scales a complex vector by a real number.
c dznrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: naitr.F SID: 2.3 DATE OF SID: 8/27/96 RELEASE: 2
c
c\Remarks
c The algorithm implemented is:
c
c restart = .false.
c Given V_{k} = [v_{1}, ..., v_{k}], r_{k};
c r_{k} contains the initial residual vector even for k = 0;
c Also assume that rnorm = || B*r_{k} || and B*r_{k} are already
c computed by the calling program.
c
c betaj = rnorm ; p_{k+1} = B*r_{k} ;
c For j = k+1, ..., k+np Do
c 1) if ( betaj < tol ) stop or restart depending on j.
c ( At present tol is zero )
c if ( restart ) generate a new starting vector.
c 2) v_{j} = r(j-1)/betaj; V_{j} = [V_{j-1}, v_{j}];
c p_{j} = p_{j}/betaj
c 3) r_{j} = OP*v_{j} where OP is defined as in znaupd
c For shift-invert mode p_{j} = B*v_{j} is already available.
c wnorm = || OP*v_{j} ||
c 4) Compute the j-th step residual vector.
c w_{j} = V_{j}^T * B * OP * v_{j}
c r_{j} = OP*v_{j} - V_{j} * w_{j}
c H(:,j) = w_{j};
c H(j,j-1) = rnorm
c rnorm = || r_(j) ||
c If (rnorm > 0.717*wnorm) accept step and go back to 1)
c 5) Re-orthogonalization step:
c s = V_{j}'*B*r_{j}
c r_{j} = r_{j} - V_{j}*s; rnorm1 = || r_{j} ||
c alphaj = alphaj + s_{j};
c 6) Iterative refinement step:
c If (rnorm1 > 0.717*rnorm) then
c rnorm = rnorm1
c accept step and go back to 1)
c Else
c rnorm = rnorm1
c If this is the first time in step 6), go to 5)
c Else r_{j} lies in the span of V_{j} numerically.
c Set r_{j} = 0 and rnorm = 0; go to 1)
c EndIf
c End Do
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine znaitr
& (ido, bmat, n, k, np, nb, resid, rnorm, v, ldv, h, ldh,
& ipntr, workd, info)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1
integer ido, info, k, ldh, ldv, n, nb, np
Double precision
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(3)
Complex*16
& h(ldh,k+np), resid(n), v(ldv,k+np), workd(3*n)
c
c %------------%
c | Parameters |
c %------------%
c
Complex*16
& one, zero
Double precision
& rone, rzero
parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0),
& rone = 1.0D+0, rzero = 0.0D+0)
c
c %--------------%
c | Local Arrays |
c %--------------%
c
Double precision
& rtemp(2)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
logical first, orth1, orth2, rstart, step3, step4
integer ierr, i, infol, ipj, irj, ivj, iter, itry, j, msglvl,
& jj
Double precision
& ovfl, smlnum, tst1, ulp, unfl, betaj,
& temp1, rnorm1, wnorm
Complex*16
& cnorm
c
save first, orth1, orth2, rstart, step3, step4,
& ierr, ipj, irj, ivj, iter, itry, j, msglvl, ovfl,
& betaj, rnorm1, smlnum, ulp, unfl, wnorm
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external zaxpy, zcopy, zscal, zdscal, zgemv, zgetv0,
& dlabad, zvout, zmout, ivout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Complex*16
& zdotc
Double precision
& dlamch, dznrm2, zlanhs, dlapy2
external zdotc, dznrm2, zlanhs, dlamch, dlapy2
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic dimag, dble, max, sqrt
c
c %-----------------%
c | Data statements |
c %-----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
c
c %-----------------------------------------%
c | Set machine-dependent constants for the |
c | the splitting and deflation criterion. |
c | If norm(H) <= sqrt(OVFL), |
c | overflow should not occur. |
c | REFERENCE: LAPACK subroutine zlahqr |
c %-----------------------------------------%
c
unfl = dlamch( 'safe minimum' )
ovfl = dble(one / unfl)
call dlabad( unfl, ovfl )
ulp = dlamch( 'precision' )
smlnum = unfl*( n / ulp )
first = .false.
end if
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mcaitr
c
c %------------------------------%
c | Initial call to this routine |
c %------------------------------%
c
info = 0
step3 = .false.
step4 = .false.
rstart = .false.
orth1 = .false.
orth2 = .false.
j = k + 1
ipj = 1
irj = ipj + n
ivj = irj + n
end if
c
c %-------------------------------------------------%
c | When in reverse communication mode one of: |
c | STEP3, STEP4, ORTH1, ORTH2, RSTART |
c | will be .true. when .... |
c | STEP3: return from computing OP*v_{j}. |
c | STEP4: return from computing B-norm of OP*v_{j} |
c | ORTH1: return from computing B-norm of r_{j+1} |
c | ORTH2: return from computing B-norm of |
c | correction to the residual vector. |
c | RSTART: return from OP computations needed by |
c | zgetv0. |
c %-------------------------------------------------%
c
if (step3) go to 50
if (step4) go to 60
if (orth1) go to 70
if (orth2) go to 90
if (rstart) go to 30
c
c %-----------------------------%
c | Else this is the first step |
c %-----------------------------%
c
c %--------------------------------------------------------------%
c | |
c | A R N O L D I I T E R A T I O N L O O P |
c | |
c | Note: B*r_{j-1} is already in WORKD(1:N)=WORKD(IPJ:IPJ+N-1) |
c %--------------------------------------------------------------%
1000 continue
c
if (msglvl .gt. 1) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: generating Arnoldi vector number')
call dvout (logfil, 1, rnorm, ndigit,
& '_naitr: B-norm of the current residual is')
end if
c
c %---------------------------------------------------%
c | STEP 1: Check if the B norm of j-th residual |
c | vector is zero. Equivalent to determine whether |
c | an exact j-step Arnoldi factorization is present. |
c %---------------------------------------------------%
c
betaj = rnorm
if (rnorm .gt. rzero) go to 40
c
c %---------------------------------------------------%
c | Invariant subspace found, generate a new starting |
c | vector which is orthogonal to the current Arnoldi |
c | basis and continue the iteration. |
c %---------------------------------------------------%
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: ****** RESTART AT STEP ******')
end if
c
c %---------------------------------------------%
c | ITRY is the loop variable that controls the |
c | maximum amount of times that a restart is |
c | attempted. NRSTRT is used by stat.h |
c %---------------------------------------------%
c
betaj = rzero
nrstrt = nrstrt + 1
itry = 1
20 continue
rstart = .true.
ido = 0
30 continue
c
c %--------------------------------------%
c | If in reverse communication mode and |
c | RSTART = .true. flow returns here. |
c %--------------------------------------%
c
call zgetv0 (ido, bmat, itry, .false., n, j, v, ldv,
& resid, rnorm, ipntr, workd, ierr)
if (ido .ne. 99) go to 9000
if (ierr .lt. 0) then
itry = itry + 1
if (itry .le. 3) go to 20
c
c %------------------------------------------------%
c | Give up after several restart attempts. |
c | Set INFO to the size of the invariant subspace |
c | which spans OP and exit. |
c %------------------------------------------------%
c
info = j - 1
call second (t1)
tcaitr = tcaitr + (t1 - t0)
ido = 99
go to 9000
end if
c
40 continue
c
c %---------------------------------------------------------%
c | STEP 2: v_{j} = r_{j-1}/rnorm and p_{j} = p_{j}/rnorm |
c | Note that p_{j} = B*r_{j-1}. In order to avoid overflow |
c | when reciprocating a small RNORM, test against lower |
c | machine bound. |
c %---------------------------------------------------------%
c
call zcopy (n, resid, 1, v(1,j), 1)
if ( rnorm .ge. unfl) then
temp1 = rone / rnorm
call zdscal (n, temp1, v(1,j), 1)
call zdscal (n, temp1, workd(ipj), 1)
else
c
c %-----------------------------------------%
c | To scale both v_{j} and p_{j} carefully |
c | use LAPACK routine zlascl |
c %-----------------------------------------%
c
call zlascl ('General', i, i, rnorm, rone,
& n, 1, v(1,j), n, infol)
call zlascl ('General', i, i, rnorm, rone,
& n, 1, workd(ipj), n, infol)
end if
c
c %------------------------------------------------------%
c | STEP 3: r_{j} = OP*v_{j}; Note that p_{j} = B*v_{j} |
c | Note that this is not quite yet r_{j}. See STEP 4 |
c %------------------------------------------------------%
c
step3 = .true.
nopx = nopx + 1
call second (t2)
call zcopy (n, v(1,j), 1, workd(ivj), 1)
ipntr(1) = ivj
ipntr(2) = irj
ipntr(3) = ipj
ido = 1
c
c %-----------------------------------%
c | Exit in order to compute OP*v_{j} |
c %-----------------------------------%
c
go to 9000
50 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(IRJ:IRJ+N-1) := OP*v_{j} |
c | if step3 = .true. |
c %----------------------------------%
c
call second (t3)
tmvopx = tmvopx + (t3 - t2)
step3 = .false.
c
c %------------------------------------------%
c | Put another copy of OP*v_{j} into RESID. |
c %------------------------------------------%
c
call zcopy (n, workd(irj), 1, resid, 1)
c
c %---------------------------------------%
c | STEP 4: Finish extending the Arnoldi |
c | factorization to length j. |
c %---------------------------------------%
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
step4 = .true.
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-------------------------------------%
c | Exit in order to compute B*OP*v_{j} |
c %-------------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call zcopy (n, resid, 1, workd(ipj), 1)
end if
60 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(IPJ:IPJ+N-1) := B*OP*v_{j} |
c | if step4 = .true. |
c %----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
step4 = .false.
c
c %-------------------------------------%
c | The following is needed for STEP 5. |
c | Compute the B-norm of OP*v_{j}. |
c %-------------------------------------%
c
if (bmat .eq. 'G') then
cnorm = zdotc (n, resid, 1, workd(ipj), 1)
wnorm = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) )
else if (bmat .eq. 'I') then
wnorm = dznrm2(n, resid, 1)
end if
c
c %-----------------------------------------%
c | Compute the j-th residual corresponding |
c | to the j step factorization. |
c | Use Classical Gram Schmidt and compute: |
c | w_{j} <- V_{j}^T * B * OP * v_{j} |
c | r_{j} <- OP*v_{j} - V_{j} * w_{j} |
c %-----------------------------------------%
c
c
c %------------------------------------------%
c | Compute the j Fourier coefficients w_{j} |
c | WORKD(IPJ:IPJ+N-1) contains B*OP*v_{j}. |
c %------------------------------------------%
c
call zgemv ('C', n, j, one, v, ldv, workd(ipj), 1,
& zero, h(1,j), 1)
c
c %--------------------------------------%
c | Orthogonalize r_{j} against V_{j}. |
c | RESID contains OP*v_{j}. See STEP 3. |
c %--------------------------------------%
c
call zgemv ('N', n, j, -one, v, ldv, h(1,j), 1,
& one, resid, 1)
c
if (j .gt. 1) h(j,j-1) = dcmplx(betaj, rzero)
c
call second (t4)
c
orth1 = .true.
c
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call zcopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*r_{j} |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call zcopy (n, resid, 1, workd(ipj), 1)
end if
70 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH1 = .true. |
c | WORKD(IPJ:IPJ+N-1) := B*r_{j}. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
orth1 = .false.
c
c %------------------------------%
c | Compute the B-norm of r_{j}. |
c %------------------------------%
c
if (bmat .eq. 'G') then
cnorm = zdotc (n, resid, 1, workd(ipj), 1)
rnorm = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) )
else if (bmat .eq. 'I') then
rnorm = dznrm2(n, resid, 1)
end if
c
c %-----------------------------------------------------------%
c | STEP 5: Re-orthogonalization / Iterative refinement phase |
c | Maximum NITER_ITREF tries. |
c | |
c | s = V_{j}^T * B * r_{j} |
c | r_{j} = r_{j} - V_{j}*s |
c | alphaj = alphaj + s_{j} |
c | |
c | The stopping criteria used for iterative refinement is |
c | discussed in Parlett's book SEP, page 107 and in Gragg & |
c | Reichel ACM TOMS paper; Algorithm 686, Dec. 1990. |
c | Determine if we need to correct the residual. The goal is |
c | to enforce ||v(:,1:j)^T * r_{j}|| .le. eps * || r_{j} || |
c | The following test determines whether the sine of the |
c | angle between OP*x and the computed residual is less |
c | than or equal to 0.717. |
c %-----------------------------------------------------------%
c
if ( rnorm .gt. 0.717*wnorm ) go to 100
c
iter = 0
nrorth = nrorth + 1
c
c %---------------------------------------------------%
c | Enter the Iterative refinement phase. If further |
c | refinement is necessary, loop back here. The loop |
c | variable is ITER. Perform a step of Classical |
c | Gram-Schmidt using all the Arnoldi vectors V_{j} |
c %---------------------------------------------------%
c
80 continue
c
if (msglvl .gt. 2) then
rtemp(1) = wnorm
rtemp(2) = rnorm
call dvout (logfil, 2, rtemp, ndigit,
& '_naitr: re-orthogonalization; wnorm and rnorm are')
call zvout (logfil, j, h(1,j), ndigit,
& '_naitr: j-th column of H')
end if
c
c %----------------------------------------------------%
c | Compute V_{j}^T * B * r_{j}. |
c | WORKD(IRJ:IRJ+J-1) = v(:,1:J)'*WORKD(IPJ:IPJ+N-1). |
c %----------------------------------------------------%
c
call zgemv ('C', n, j, one, v, ldv, workd(ipj), 1,
& zero, workd(irj), 1)
c
c %---------------------------------------------%
c | Compute the correction to the residual: |
c | r_{j} = r_{j} - V_{j} * WORKD(IRJ:IRJ+J-1). |
c | The correction to H is v(:,1:J)*H(1:J,1:J) |
c | + v(:,1:J)*WORKD(IRJ:IRJ+J-1)*e'_j. |
c %---------------------------------------------%
c
call zgemv ('N', n, j, -one, v, ldv, workd(irj), 1,
& one, resid, 1)
call zaxpy (j, one, workd(irj), 1, h(1,j), 1)
c
orth2 = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call zcopy (n, resid, 1, workd(irj), 1)
ipntr(1) = irj
ipntr(2) = ipj
ido = 2
c
c %-----------------------------------%
c | Exit in order to compute B*r_{j}. |
c | r_{j} is the corrected residual. |
c %-----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call zcopy (n, resid, 1, workd(ipj), 1)
end if
90 continue
c
c %---------------------------------------------------%
c | Back from reverse communication if ORTH2 = .true. |
c %---------------------------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
c %-----------------------------------------------------%
c | Compute the B-norm of the corrected residual r_{j}. |
c %-----------------------------------------------------%
c
if (bmat .eq. 'G') then
cnorm = zdotc (n, resid, 1, workd(ipj), 1)
rnorm1 = sqrt( dlapy2(dble(cnorm),dimag(cnorm)) )
else if (bmat .eq. 'I') then
rnorm1 = dznrm2(n, resid, 1)
end if
c
if (msglvl .gt. 0 .and. iter .gt. 0 ) then
call ivout (logfil, 1, j, ndigit,
& '_naitr: Iterative refinement for Arnoldi residual')
if (msglvl .gt. 2) then
rtemp(1) = rnorm
rtemp(2) = rnorm1
call dvout (logfil, 2, rtemp, ndigit,
& '_naitr: iterative refinement ; rnorm and rnorm1 are')
end if
end if
c
c %-----------------------------------------%
c | Determine if we need to perform another |
c | step of re-orthogonalization. |
c %-----------------------------------------%
c
if ( rnorm1 .gt. 0.717*rnorm ) then
c
c %---------------------------------------%
c | No need for further refinement. |
c | The cosine of the angle between the |
c | corrected residual vector and the old |
c | residual vector is greater than 0.717 |
c | In other words the corrected residual |
c | and the old residual vector share an |
c | angle of less than arcCOS(0.717) |
c %---------------------------------------%
c
rnorm = rnorm1
c
else
c
c %-------------------------------------------%
c | Another step of iterative refinement step |
c | is required. NITREF is used by stat.h |
c %-------------------------------------------%
c
nitref = nitref + 1
rnorm = rnorm1
iter = iter + 1
if (iter .le. 1) go to 80
c
c %-------------------------------------------------%
c | Otherwise RESID is numerically in the span of V |
c %-------------------------------------------------%
c
do 95 jj = 1, n
resid(jj) = zero
95 continue
rnorm = rzero
end if
c
c %----------------------------------------------%
c | Branch here directly if iterative refinement |
c | wasn't necessary or after at most NITER_REF |
c | steps of iterative refinement. |
c %----------------------------------------------%
c
100 continue
c
rstart = .false.
orth2 = .false.
c
call second (t5)
titref = titref + (t5 - t4)
c
c %------------------------------------%
c | STEP 6: Update j = j+1; Continue |
c %------------------------------------%
c
j = j + 1
if (j .gt. k+np) then
call second (t1)
tcaitr = tcaitr + (t1 - t0)
ido = 99
do 110 i = max(1,k), k+np-1
c
c %--------------------------------------------%
c | Check for splitting and deflation. |
c | Use a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine zlahqr |
c %--------------------------------------------%
c
tst1 = dlapy2(dble(h(i,i)),dimag(h(i,i)))
& + dlapy2(dble(h(i+1,i+1)), dimag(h(i+1,i+1)))
if( tst1.eq.dble(zero) )
& tst1 = zlanhs( '1', k+np, h, ldh, workd(n+1) )
if( dlapy2(dble(h(i+1,i)),dimag(h(i+1,i))) .le.
& max( ulp*tst1, smlnum ) )
& h(i+1,i) = zero
110 continue
c
if (msglvl .gt. 2) then
call zmout (logfil, k+np, k+np, h, ldh, ndigit,
& '_naitr: Final upper Hessenberg matrix H of order K+NP')
end if
c
go to 9000
end if
c
c %--------------------------------------------------------%
c | Loop back to extend the factorization by another step. |
c %--------------------------------------------------------%
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
9000 continue
return
c
c %---------------%
c | End of znaitr |
c %---------------%
c
end

507
arpack/ARPACK/SRC/znapps.f Normal file
View File

@@ -0,0 +1,507 @@
c\BeginDoc
c
c\Name: znapps
c
c\Description:
c Given the Arnoldi factorization
c
c A*V_{k} - V_{k}*H_{k} = r_{k+p}*e_{k+p}^T,
c
c apply NP implicit shifts resulting in
c
c A*(V_{k}*Q) - (V_{k}*Q)*(Q^T* H_{k}*Q) = r_{k+p}*e_{k+p}^T * Q
c
c where Q is an orthogonal matrix which is the product of rotations
c and reflections resulting from the NP bulge change sweeps.
c The updated Arnoldi factorization becomes:
c
c A*VNEW_{k} - VNEW_{k}*HNEW_{k} = rnew_{k}*e_{k}^T.
c
c\Usage:
c call znapps
c ( N, KEV, NP, SHIFT, V, LDV, H, LDH, RESID, Q, LDQ,
c WORKL, WORKD )
c
c\Arguments
c N Integer. (INPUT)
c Problem size, i.e. size of matrix A.
c
c KEV Integer. (INPUT/OUTPUT)
c KEV+NP is the size of the input matrix H.
c KEV is the size of the updated matrix HNEW.
c
c NP Integer. (INPUT)
c Number of implicit shifts to be applied.
c
c SHIFT Complex*16 array of length NP. (INPUT)
c The shifts to be applied.
c
c V Complex*16 N by (KEV+NP) array. (INPUT/OUTPUT)
c On INPUT, V contains the current KEV+NP Arnoldi vectors.
c On OUTPUT, V contains the updated KEV Arnoldi vectors
c in the first KEV columns of V.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Complex*16 (KEV+NP) by (KEV+NP) array. (INPUT/OUTPUT)
c On INPUT, H contains the current KEV+NP by KEV+NP upper
c Hessenberg matrix of the Arnoldi factorization.
c On OUTPUT, H contains the updated KEV by KEV upper Hessenberg
c matrix in the KEV leading submatrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RESID Complex*16 array of length N. (INPUT/OUTPUT)
c On INPUT, RESID contains the the residual vector r_{k+p}.
c On OUTPUT, RESID is the update residual vector rnew_{k}
c in the first KEV locations.
c
c Q Complex*16 KEV+NP by KEV+NP work array. (WORKSPACE)
c Work array used to accumulate the rotations and reflections
c during the bulge chase sweep.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Complex*16 work array of length (KEV+NP). (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c WORKD Complex*16 work array of length 2*N. (WORKSPACE)
c Distributed array used in the application of the accumulated
c orthogonal matrix Q.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex*16
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c
c\Routines called:
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c zmout ARPACK utility routine that prints matrices
c zvout ARPACK utility routine that prints vectors.
c zlacpy LAPACK matrix copy routine.
c zlanhs LAPACK routine that computes various norms of a matrix.
c zlartg LAPACK Givens rotation construction routine.
c zlaset LAPACK matrix initialization routine.
c dlabad LAPACK routine for defining the underflow and overflow
c limits.
c dlamch LAPACK routine that determines machine constants.
c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c zgemv Level 2 BLAS routine for matrix vector multiplication.
c zaxpy Level 1 BLAS that computes a vector triad.
c zcopy Level 1 BLAS that copies one vector to another.
c zscal Level 1 BLAS that scales a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: napps.F SID: 2.3 DATE OF SID: 3/28/97 RELEASE: 2
c
c\Remarks
c 1. In this version, each shift is applied to all the sublocks of
c the Hessenberg matrix H and not just to the submatrix that it
c comes from. Deflation as in LAPACK routine zlahqr (QR algorithm
c for upper Hessenberg matrices ) is used.
c Upon output, the subdiagonals of H are enforced to be non-negative
c real numbers.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine znapps
& ( n, kev, np, shift, v, ldv, h, ldh, resid, q, ldq,
& workl, workd )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer kev, ldh, ldq, ldv, n, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Complex*16
& h(ldh,kev+np), resid(n), shift(np),
& v(ldv,kev+np), q(ldq,kev+np), workd(2*n), workl(kev+np)
c
c %------------%
c | Parameters |
c %------------%
c
Complex*16
& one, zero
Double precision
& rzero
parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0),
& rzero = 0.0D+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
integer i, iend, istart, j, jj, kplusp, msglvl
logical first
Complex*16
& cdum, f, g, h11, h21, r, s, sigma, t
Double precision
& c, ovfl, smlnum, ulp, unfl, tst1
save first, ovfl, smlnum, ulp, unfl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external zaxpy, zcopy, zgemv, zscal, zlacpy, zlartg,
& zvout, zlaset, dlabad, zmout, second, ivout
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& zlanhs, dlamch, dlapy2
external zlanhs, dlamch, dlapy2
c
c %----------------------%
c | Intrinsics Functions |
c %----------------------%
c
intrinsic abs, dimag, conjg, dcmplx, max, min, dble
c
c %---------------------%
c | Statement Functions |
c %---------------------%
c
Double precision
& zabs1
zabs1( cdum ) = abs( dble( cdum ) ) + abs( dimag( cdum ) )
c
c %----------------%
c | Data statments |
c %----------------%
c
data first / .true. /
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (first) then
c
c %-----------------------------------------------%
c | Set machine-dependent constants for the |
c | stopping criterion. If norm(H) <= sqrt(OVFL), |
c | overflow should not occur. |
c | REFERENCE: LAPACK subroutine zlahqr |
c %-----------------------------------------------%
c
unfl = dlamch( 'safe minimum' )
ovfl = dble(one / unfl)
call dlabad( unfl, ovfl )
ulp = dlamch( 'precision' )
smlnum = unfl*( n / ulp )
first = .false.
end if
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mcapps
c
kplusp = kev + np
c
c %--------------------------------------------%
c | Initialize Q to the identity to accumulate |
c | the rotations and reflections |
c %--------------------------------------------%
c
call zlaset ('All', kplusp, kplusp, zero, one, q, ldq)
c
c %----------------------------------------------%
c | Quick return if there are no shifts to apply |
c %----------------------------------------------%
c
if (np .eq. 0) go to 9000
c
c %----------------------------------------------%
c | Chase the bulge with the application of each |
c | implicit shift. Each shift is applied to the |
c | whole matrix including each block. |
c %----------------------------------------------%
c
do 110 jj = 1, np
sigma = shift(jj)
c
if (msglvl .gt. 2 ) then
call ivout (logfil, 1, jj, ndigit,
& '_napps: shift number.')
call zvout (logfil, 1, sigma, ndigit,
& '_napps: Value of the shift ')
end if
c
istart = 1
20 continue
c
do 30 i = istart, kplusp-1
c
c %----------------------------------------%
c | Check for splitting and deflation. Use |
c | a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine zlahqr |
c %----------------------------------------%
c
tst1 = zabs1( h( i, i ) ) + zabs1( h( i+1, i+1 ) )
if( tst1.eq.rzero )
& tst1 = zlanhs( '1', kplusp-jj+1, h, ldh, workl )
if ( abs(dble(h(i+1,i)))
& .le. max(ulp*tst1, smlnum) ) then
if (msglvl .gt. 0) then
call ivout (logfil, 1, i, ndigit,
& '_napps: matrix splitting at row/column no.')
call ivout (logfil, 1, jj, ndigit,
& '_napps: matrix splitting with shift number.')
call zvout (logfil, 1, h(i+1,i), ndigit,
& '_napps: off diagonal element.')
end if
iend = i
h(i+1,i) = zero
go to 40
end if
30 continue
iend = kplusp
40 continue
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, istart, ndigit,
& '_napps: Start of current block ')
call ivout (logfil, 1, iend, ndigit,
& '_napps: End of current block ')
end if
c
c %------------------------------------------------%
c | No reason to apply a shift to block of order 1 |
c | or if the current block starts after the point |
c | of compression since we'll discard this stuff |
c %------------------------------------------------%
c
if ( istart .eq. iend .or. istart .gt. kev) go to 100
c
h11 = h(istart,istart)
h21 = h(istart+1,istart)
f = h11 - sigma
g = h21
c
do 80 i = istart, iend-1
c
c %------------------------------------------------------%
c | Construct the plane rotation G to zero out the bulge |
c %------------------------------------------------------%
c
call zlartg (f, g, c, s, r)
if (i .gt. istart) then
h(i,i-1) = r
h(i+1,i-1) = zero
end if
c
c %---------------------------------------------%
c | Apply rotation to the left of H; H <- G'*H |
c %---------------------------------------------%
c
do 50 j = i, kplusp
t = c*h(i,j) + s*h(i+1,j)
h(i+1,j) = -conjg(s)*h(i,j) + c*h(i+1,j)
h(i,j) = t
50 continue
c
c %---------------------------------------------%
c | Apply rotation to the right of H; H <- H*G |
c %---------------------------------------------%
c
do 60 j = 1, min(i+2,iend)
t = c*h(j,i) + conjg(s)*h(j,i+1)
h(j,i+1) = -s*h(j,i) + c*h(j,i+1)
h(j,i) = t
60 continue
c
c %-----------------------------------------------------%
c | Accumulate the rotation in the matrix Q; Q <- Q*G' |
c %-----------------------------------------------------%
c
do 70 j = 1, min(i+jj, kplusp)
t = c*q(j,i) + conjg(s)*q(j,i+1)
q(j,i+1) = - s*q(j,i) + c*q(j,i+1)
q(j,i) = t
70 continue
c
c %---------------------------%
c | Prepare for next rotation |
c %---------------------------%
c
if (i .lt. iend-1) then
f = h(i+1,i)
g = h(i+2,i)
end if
80 continue
c
c %-------------------------------%
c | Finished applying the shift. |
c %-------------------------------%
c
100 continue
c
c %---------------------------------------------------------%
c | Apply the same shift to the next block if there is any. |
c %---------------------------------------------------------%
c
istart = iend + 1
if (iend .lt. kplusp) go to 20
c
c %---------------------------------------------%
c | Loop back to the top to get the next shift. |
c %---------------------------------------------%
c
110 continue
c
c %---------------------------------------------------%
c | Perform a similarity transformation that makes |
c | sure that the compressed H will have non-negative |
c | real subdiagonal elements. |
c %---------------------------------------------------%
c
do 120 j=1,kev
if ( dble( h(j+1,j) ) .lt. rzero .or.
& dimag( h(j+1,j) ) .ne. rzero ) then
t = h(j+1,j) / dlapy2(dble(h(j+1,j)),dimag(h(j+1,j)))
call zscal( kplusp-j+1, conjg(t), h(j+1,j), ldh )
call zscal( min(j+2, kplusp), t, h(1,j+1), 1 )
call zscal( min(j+np+1,kplusp), t, q(1,j+1), 1 )
h(j+1,j) = dcmplx( dble( h(j+1,j) ), rzero )
end if
120 continue
c
do 130 i = 1, kev
c
c %--------------------------------------------%
c | Final check for splitting and deflation. |
c | Use a standard test as in the QR algorithm |
c | REFERENCE: LAPACK subroutine zlahqr. |
c | Note: Since the subdiagonals of the |
c | compressed H are nonnegative real numbers, |
c | we take advantage of this. |
c %--------------------------------------------%
c
tst1 = zabs1( h( i, i ) ) + zabs1( h( i+1, i+1 ) )
if( tst1 .eq. rzero )
& tst1 = zlanhs( '1', kev, h, ldh, workl )
if( dble( h( i+1,i ) ) .le. max( ulp*tst1, smlnum ) )
& h(i+1,i) = zero
130 continue
c
c %-------------------------------------------------%
c | Compute the (kev+1)-st column of (V*Q) and |
c | temporarily store the result in WORKD(N+1:2*N). |
c | This is needed in the residual update since we |
c | cannot GUARANTEE that the corresponding entry |
c | of H would be zero as in exact arithmetic. |
c %-------------------------------------------------%
c
if ( dble( h(kev+1,kev) ) .gt. rzero )
& call zgemv ('N', n, kplusp, one, v, ldv, q(1,kev+1), 1, zero,
& workd(n+1), 1)
c
c %----------------------------------------------------------%
c | Compute column 1 to kev of (V*Q) in backward order |
c | taking advantage of the upper Hessenberg structure of Q. |
c %----------------------------------------------------------%
c
do 140 i = 1, kev
call zgemv ('N', n, kplusp-i+1, one, v, ldv,
& q(1,kev-i+1), 1, zero, workd, 1)
call zcopy (n, workd, 1, v(1,kplusp-i+1), 1)
140 continue
c
c %-------------------------------------------------%
c | Move v(:,kplusp-kev+1:kplusp) into v(:,1:kev). |
c %-------------------------------------------------%
c
call zlacpy ('A', n, kev, v(1,kplusp-kev+1), ldv, v, ldv)
c
c %--------------------------------------------------------------%
c | Copy the (kev+1)-st column of (V*Q) in the appropriate place |
c %--------------------------------------------------------------%
c
if ( dble( h(kev+1,kev) ) .gt. rzero )
& call zcopy (n, workd(n+1), 1, v(1,kev+1), 1)
c
c %-------------------------------------%
c | Update the residual vector: |
c | r <- sigmak*r + betak*v(:,kev+1) |
c | where |
c | sigmak = (e_{kev+p}'*Q)*e_{kev} |
c | betak = e_{kev+1}'*H*e_{kev} |
c %-------------------------------------%
c
call zscal (n, q(kplusp,kev), resid, 1)
if ( dble( h(kev+1,kev) ) .gt. rzero )
& call zaxpy (n, h(kev+1,kev), v(1,kev+1), 1, resid, 1)
c
if (msglvl .gt. 1) then
call zvout (logfil, 1, q(kplusp,kev), ndigit,
& '_napps: sigmak = (e_{kev+p}^T*Q)*e_{kev}')
call zvout (logfil, 1, h(kev+1,kev), ndigit,
& '_napps: betak = e_{kev+1}^T*H*e_{kev}')
call ivout (logfil, 1, kev, ndigit,
& '_napps: Order of the final Hessenberg matrix ')
if (msglvl .gt. 2) then
call zmout (logfil, kev, kev, h, ldh, ndigit,
& '_napps: updated Hessenberg matrix H for next iteration')
end if
c
end if
c
9000 continue
call second (t1)
tcapps = tcapps + (t1 - t0)
c
return
c
c %---------------%
c | End of znapps |
c %---------------%
c
end

801
arpack/ARPACK/SRC/znaup2.f Normal file
View File

@@ -0,0 +1,801 @@
c\BeginDoc
c
c\Name: znaup2
c
c\Description:
c Intermediate level interface called by znaupd .
c
c\Usage:
c call znaup2
c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD,
c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS,
c Q, LDQ, WORKL, IPNTR, WORKD, RWORK, INFO )
c
c\Arguments
c
c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in znaupd .
c MODE, ISHIFT, MXITER: see the definition of IPARAM in znaupd .
c
c NP Integer. (INPUT/OUTPUT)
c Contains the number of implicit shifts to apply during
c each Arnoldi iteration.
c If ISHIFT=1, NP is adjusted dynamically at each iteration
c to accelerate convergence and prevent stagnation.
c This is also roughly equal to the number of matrix-vector
c products (involving the operator OP) per Arnoldi iteration.
c The logic for adjusting is contained within the current
c subroutine.
c If ISHIFT=0, NP is the number of shifts the user needs
c to provide via reverse comunication. 0 < NP < NCV-NEV.
c NP may be less than NCV-NEV since a leading block of the current
c upper Hessenberg matrix has split off and contains "unwanted"
c Ritz values.
c Upon termination of the IRA iteration, NP contains the number
c of "converged" wanted Ritz values.
c
c IUPD Integer. (INPUT)
c IUPD .EQ. 0: use explicit restart instead implicit update.
c IUPD .NE. 0: use implicit update.
c
c V Complex*16 N by (NEV+NP) array. (INPUT/OUTPUT)
c The Arnoldi basis vectors are returned in the first NEV
c columns of V.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling
c program.
c
c H Complex*16 (NEV+NP) by (NEV+NP) array. (OUTPUT)
c H is used to store the generated upper Hessenberg matrix
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RITZ Complex*16 array of length NEV+NP. (OUTPUT)
c RITZ(1:NEV) contains the computed Ritz values of OP.
c
c BOUNDS Complex*16 array of length NEV+NP. (OUTPUT)
c BOUNDS(1:NEV) contain the error bounds corresponding to
c the computed Ritz values.
c
c Q Complex*16 (NEV+NP) by (NEV+NP) array. (WORKSPACE)
c Private (replicated) work array used to accumulate the
c rotation in the shift application step.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Complex*16 work array of length at least
c (NEV+NP)**2 + 3*(NEV+NP). (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. It is used in shifts calculation, shifts
c application and convergence checking.
c
c
c IPNTR Integer array of length 3. (OUTPUT)
c Pointer to mark the starting locations in the WORKD for
c vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X.
c IPNTR(2): pointer to the current result vector Y.
c IPNTR(3): pointer to the vector B * X when used in the
c shift-and-invert mode. X is the current operand.
c -------------------------------------------------------------
c
c WORKD Complex*16 work array of length 3*N. (WORKSPACE)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration !!!!!!!!!!
c See Data Distribution Note in ZNAUPD .
c
c RWORK Double precision work array of length NEV+NP ( WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal return.
c = 1: Maximum number of iterations taken.
c All possible eigenvalues of OP has been found.
c NP returns the number of converged Ritz values.
c = 2: No shifts could be applied.
c = -8: Error return from LAPACK eigenvalue calculation;
c This should never happen.
c = -9: Starting vector is zero.
c = -9999: Could not build an Arnoldi factorization.
c Size that was built in returned in NP.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex*16
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c
c\Routines called:
c zgetv0 ARPACK initial vector generation routine.
c znaitr ARPACK Arnoldi factorization routine.
c znapps ARPACK application of implicit shifts routine.
c zneigh ARPACK compute Ritz values and error bounds routine.
c zngets ARPACK reorder Ritz values and error bounds routine.
c zsortc ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c zmout ARPACK utility routine that prints matrices
c zvout ARPACK utility routine that prints vectors.
c dvout ARPACK utility routine that prints vectors.
c dlamch LAPACK routine that determines machine constants.
c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c zcopy Level 1 BLAS that copies one vector to another .
c zdotc Level 1 BLAS that computes the scalar product of two vectors.
c zswap Level 1 BLAS that swaps two vectors.
c dznrm2 Level 1 BLAS that computes the norm of a vector.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice Universitya
c Chao Yang Houston, Texas
c Dept. of Computational &
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: naup2.F SID: 2.6 DATE OF SID: 06/01/00 RELEASE: 2
c
c\Remarks
c 1. None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine znaup2
& ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, h, ldh, ritz, bounds,
& q, ldq, workl, ipntr, workd, rwork, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter,
& n, nev, np
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer ipntr(13)
Complex*16
& bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np),
& resid(n), ritz(nev+np), v(ldv,nev+np),
& workd(3*n), workl( (nev+np)*(nev+np+3) )
Double precision
& rwork(nev+np)
c
c %------------%
c | Parameters |
c %------------%
c
Complex*16
& one, zero
Double precision
& rzero
parameter (one = (1.0D+0, 0.0D+0) , zero = (0.0D+0, 0.0D+0) ,
& rzero = 0.0D+0 )
c
c %---------------%
c | Local Scalars |
c %---------------%
c
logical cnorm , getv0, initv , update, ushift
integer ierr , iter , kplusp, msglvl, nconv,
& nevbef, nev0 , np0 , nptemp, i ,
& j
Complex*16
& cmpnorm
Double precision
& rnorm , eps23, rtemp
character wprime*2
c
save cnorm, getv0, initv , update, ushift,
& rnorm, iter , kplusp, msglvl, nconv ,
& nevbef, nev0 , np0 , eps23
c
c
c %-----------------------%
c | Local array arguments |
c %-----------------------%
c
integer kp(3)
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external zcopy , zgetv0 , znaitr , zneigh , zngets , znapps ,
& zsortc , zswap , zmout , zvout , ivout, second
c
c %--------------------%
c | External functions |
c %--------------------%
c
Complex*16
& zdotc
Double precision
& dznrm2 , dlamch , dlapy2
external zdotc , dznrm2 , dlamch , dlapy2
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic dimag , dble , min, max
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
call second (t0)
c
msglvl = mcaup2
c
nev0 = nev
np0 = np
c
c %-------------------------------------%
c | kplusp is the bound on the largest |
c | Lanczos factorization built. |
c | nconv is the current number of |
c | "converged" eigenvalues. |
c | iter is the counter on the current |
c | iteration step. |
c %-------------------------------------%
c
kplusp = nev + np
nconv = 0
iter = 0
c
c %---------------------------------%
c | Get machine dependent constant. |
c %---------------------------------%
c
eps23 = dlamch ('Epsilon-Machine')
eps23 = eps23**(2.0D+0 / 3.0D+0 )
c
c %---------------------------------------%
c | Set flags for computing the first NEV |
c | steps of the Arnoldi factorization. |
c %---------------------------------------%
c
getv0 = .true.
update = .false.
ushift = .false.
cnorm = .false.
c
if (info .ne. 0) then
c
c %--------------------------------------------%
c | User provides the initial residual vector. |
c %--------------------------------------------%
c
initv = .true.
info = 0
else
initv = .false.
end if
end if
c
c %---------------------------------------------%
c | Get a possibly random starting vector and |
c | force it into the range of the operator OP. |
c %---------------------------------------------%
c
10 continue
c
if (getv0) then
call zgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm,
& ipntr, workd, info)
c
if (ido .ne. 99) go to 9000
c
if (rnorm .eq. rzero) then
c
c %-----------------------------------------%
c | The initial vector is zero. Error exit. |
c %-----------------------------------------%
c
info = -9
go to 1100
end if
getv0 = .false.
ido = 0
end if
c
c %-----------------------------------%
c | Back from reverse communication : |
c | continue with update step |
c %-----------------------------------%
c
if (update) go to 20
c
c %-------------------------------------------%
c | Back from computing user specified shifts |
c %-------------------------------------------%
c
if (ushift) go to 50
c
c %-------------------------------------%
c | Back from computing residual norm |
c | at the end of the current iteration |
c %-------------------------------------%
c
if (cnorm) go to 100
c
c %----------------------------------------------------------%
c | Compute the first NEV steps of the Arnoldi factorization |
c %----------------------------------------------------------%
c
call znaitr (ido, bmat, n, 0, nev, mode, resid, rnorm, v, ldv,
& h, ldh, ipntr, workd, info)
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
np = info
mxiter = iter
info = -9999
go to 1200
end if
c
c %--------------------------------------------------------------%
c | |
c | M A I N ARNOLDI I T E R A T I O N L O O P |
c | Each iteration implicitly restarts the Arnoldi |
c | factorization in place. |
c | |
c %--------------------------------------------------------------%
c
1000 continue
c
iter = iter + 1
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, iter, ndigit,
& '_naup2: **** Start of major iteration number ****')
end if
c
c %-----------------------------------------------------------%
c | Compute NP additional steps of the Arnoldi factorization. |
c | Adjust NP since NEV might have been updated by last call |
c | to the shift application routine znapps . |
c %-----------------------------------------------------------%
c
np = kplusp - nev
c
if (msglvl .gt. 1) then
call ivout (logfil, 1, nev, ndigit,
& '_naup2: The length of the current Arnoldi factorization')
call ivout (logfil, 1, np, ndigit,
& '_naup2: Extend the Arnoldi factorization by')
end if
c
c %-----------------------------------------------------------%
c | Compute NP additional steps of the Arnoldi factorization. |
c %-----------------------------------------------------------%
c
ido = 0
20 continue
update = .true.
c
call znaitr (ido, bmat, n, nev, np, mode, resid, rnorm,
& v , ldv , h, ldh, ipntr, workd, info)
c
if (ido .ne. 99) go to 9000
c
if (info .gt. 0) then
np = info
mxiter = iter
info = -9999
go to 1200
end if
update = .false.
c
if (msglvl .gt. 1) then
call dvout (logfil, 1, rnorm, ndigit,
& '_naup2: Corresponding B-norm of the residual')
end if
c
c %--------------------------------------------------------%
c | Compute the eigenvalues and corresponding error bounds |
c | of the current upper Hessenberg matrix. |
c %--------------------------------------------------------%
c
call zneigh (rnorm, kplusp, h, ldh, ritz, bounds,
& q, ldq, workl, rwork, ierr)
c
if (ierr .ne. 0) then
info = -8
go to 1200
end if
c
c %---------------------------------------------------%
c | Select the wanted Ritz values and their bounds |
c | to be used in the convergence test. |
c | The wanted part of the spectrum and corresponding |
c | error bounds are in the last NEV loc. of RITZ, |
c | and BOUNDS respectively. |
c %---------------------------------------------------%
c
nev = nev0
np = np0
c
c %--------------------------------------------------%
c | Make a copy of Ritz values and the corresponding |
c | Ritz estimates obtained from zneigh . |
c %--------------------------------------------------%
c
call zcopy (kplusp,ritz,1,workl(kplusp**2+1),1)
call zcopy (kplusp,bounds,1,workl(kplusp**2+kplusp+1),1)
c
c %---------------------------------------------------%
c | Select the wanted Ritz values and their bounds |
c | to be used in the convergence test. |
c | The wanted part of the spectrum and corresponding |
c | bounds are in the last NEV loc. of RITZ |
c | BOUNDS respectively. |
c %---------------------------------------------------%
c
call zngets (ishift, which, nev, np, ritz, bounds)
c
c %------------------------------------------------------------%
c | Convergence test: currently we use the following criteria. |
c | The relative accuracy of a Ritz value is considered |
c | acceptable if: |
c | |
c | error_bounds(i) .le. tol*max(eps23, magnitude_of_ritz(i)). |
c | |
c %------------------------------------------------------------%
c
nconv = 0
c
do 25 i = 1, nev
rtemp = max( eps23, dlapy2 ( dble (ritz(np+i)),
& dimag (ritz(np+i)) ) )
if ( dlapy2 (dble (bounds(np+i)),dimag (bounds(np+i)))
& .le. tol*rtemp ) then
nconv = nconv + 1
end if
25 continue
c
if (msglvl .gt. 2) then
kp(1) = nev
kp(2) = np
kp(3) = nconv
call ivout (logfil, 3, kp, ndigit,
& '_naup2: NEV, NP, NCONV are')
call zvout (logfil, kplusp, ritz, ndigit,
& '_naup2: The eigenvalues of H')
call zvout (logfil, kplusp, bounds, ndigit,
& '_naup2: Ritz estimates of the current NCV Ritz values')
end if
c
c %---------------------------------------------------------%
c | Count the number of unwanted Ritz values that have zero |
c | Ritz estimates. If any Ritz estimates are equal to zero |
c | then a leading block of H of order equal to at least |
c | the number of Ritz values with zero Ritz estimates has |
c | split off. None of these Ritz values may be removed by |
c | shifting. Decrease NP the number of shifts to apply. If |
c | no shifts may be applied, then prepare to exit |
c %---------------------------------------------------------%
c
nptemp = np
do 30 j=1, nptemp
if (bounds(j) .eq. zero) then
np = np - 1
nev = nev + 1
end if
30 continue
c
if ( (nconv .ge. nev0) .or.
& (iter .gt. mxiter) .or.
& (np .eq. 0) ) then
c
if (msglvl .gt. 4) then
call zvout (logfil, kplusp, workl(kplusp**2+1), ndigit,
& '_naup2: Eigenvalues computed by _neigh:')
call zvout (logfil, kplusp, workl(kplusp**2+kplusp+1),
& ndigit,
& '_naup2: Ritz estimates computed by _neigh:')
end if
c
c %------------------------------------------------%
c | Prepare to exit. Put the converged Ritz values |
c | and corresponding bounds in RITZ(1:NCONV) and |
c | BOUNDS(1:NCONV) respectively. Then sort. Be |
c | careful when NCONV > NP |
c %------------------------------------------------%
c
c %------------------------------------------%
c | Use h( 3,1 ) as storage to communicate |
c | rnorm to zneupd if needed |
c %------------------------------------------%
h(3,1) = dcmplx (rnorm,rzero)
c
c %----------------------------------------------%
c | Sort Ritz values so that converged Ritz |
c | values appear within the first NEV locations |
c | of ritz and bounds, and the most desired one |
c | appears at the front. |
c %----------------------------------------------%
c
if (which .eq. 'LM') wprime = 'SM'
if (which .eq. 'SM') wprime = 'LM'
if (which .eq. 'LR') wprime = 'SR'
if (which .eq. 'SR') wprime = 'LR'
if (which .eq. 'LI') wprime = 'SI'
if (which .eq. 'SI') wprime = 'LI'
c
call zsortc (wprime, .true., kplusp, ritz, bounds)
c
c %--------------------------------------------------%
c | Scale the Ritz estimate of each Ritz value |
c | by 1 / max(eps23, magnitude of the Ritz value). |
c %--------------------------------------------------%
c
do 35 j = 1, nev0
rtemp = max( eps23, dlapy2 ( dble (ritz(j)),
& dimag (ritz(j)) ) )
bounds(j) = bounds(j)/rtemp
35 continue
c
c %---------------------------------------------------%
c | Sort the Ritz values according to the scaled Ritz |
c | estimates. This will push all the converged ones |
c | towards the front of ritz, bounds (in the case |
c | when NCONV < NEV.) |
c %---------------------------------------------------%
c
wprime = 'LM'
call zsortc (wprime, .true., nev0, bounds, ritz)
c
c %----------------------------------------------%
c | Scale the Ritz estimate back to its original |
c | value. |
c %----------------------------------------------%
c
do 40 j = 1, nev0
rtemp = max( eps23, dlapy2 ( dble (ritz(j)),
& dimag (ritz(j)) ) )
bounds(j) = bounds(j)*rtemp
40 continue
c
c %-----------------------------------------------%
c | Sort the converged Ritz values again so that |
c | the "threshold" value appears at the front of |
c | ritz and bound. |
c %-----------------------------------------------%
c
call zsortc (which, .true., nconv, ritz, bounds)
c
if (msglvl .gt. 1) then
call zvout (logfil, kplusp, ritz, ndigit,
& '_naup2: Sorted eigenvalues')
call zvout (logfil, kplusp, bounds, ndigit,
& '_naup2: Sorted ritz estimates.')
end if
c
c %------------------------------------%
c | Max iterations have been exceeded. |
c %------------------------------------%
c
if (iter .gt. mxiter .and. nconv .lt. nev0) info = 1
c
c %---------------------%
c | No shifts to apply. |
c %---------------------%
c
if (np .eq. 0 .and. nconv .lt. nev0) info = 2
c
np = nconv
go to 1100
c
else if ( (nconv .lt. nev0) .and. (ishift .eq. 1) ) then
c
c %-------------------------------------------------%
c | Do not have all the requested eigenvalues yet. |
c | To prevent possible stagnation, adjust the size |
c | of NEV. |
c %-------------------------------------------------%
c
nevbef = nev
nev = nev + min(nconv, np/2)
if (nev .eq. 1 .and. kplusp .ge. 6) then
nev = kplusp / 2
else if (nev .eq. 1 .and. kplusp .gt. 3) then
nev = 2
end if
np = kplusp - nev
c
c %---------------------------------------%
c | If the size of NEV was just increased |
c | resort the eigenvalues. |
c %---------------------------------------%
c
if (nevbef .lt. nev)
& call zngets (ishift, which, nev, np, ritz, bounds)
c
end if
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, nconv, ndigit,
& '_naup2: no. of "converged" Ritz values at this iter.')
if (msglvl .gt. 1) then
kp(1) = nev
kp(2) = np
call ivout (logfil, 2, kp, ndigit,
& '_naup2: NEV and NP are')
call zvout (logfil, nev, ritz(np+1), ndigit,
& '_naup2: "wanted" Ritz values ')
call zvout (logfil, nev, bounds(np+1), ndigit,
& '_naup2: Ritz estimates of the "wanted" values ')
end if
end if
c
if (ishift .eq. 0) then
c
c %-------------------------------------------------------%
c | User specified shifts: pop back out to get the shifts |
c | and return them in the first 2*NP locations of WORKL. |
c %-------------------------------------------------------%
c
ushift = .true.
ido = 3
go to 9000
end if
50 continue
ushift = .false.
c
if ( ishift .ne. 1 ) then
c
c %----------------------------------%
c | Move the NP shifts from WORKL to |
c | RITZ, to free up WORKL |
c | for non-exact shift case. |
c %----------------------------------%
c
call zcopy (np, workl, 1, ritz, 1)
end if
c
if (msglvl .gt. 2) then
call ivout (logfil, 1, np, ndigit,
& '_naup2: The number of shifts to apply ')
call zvout (logfil, np, ritz, ndigit,
& '_naup2: values of the shifts')
if ( ishift .eq. 1 )
& call zvout (logfil, np, bounds, ndigit,
& '_naup2: Ritz estimates of the shifts')
end if
c
c %---------------------------------------------------------%
c | Apply the NP implicit shifts by QR bulge chasing. |
c | Each shift is applied to the whole upper Hessenberg |
c | matrix H. |
c | The first 2*N locations of WORKD are used as workspace. |
c %---------------------------------------------------------%
c
call znapps (n, nev, np, ritz, v, ldv,
& h, ldh, resid, q, ldq, workl, workd)
c
c %---------------------------------------------%
c | Compute the B-norm of the updated residual. |
c | Keep B*RESID in WORKD(1:N) to be used in |
c | the first step of the next call to znaitr . |
c %---------------------------------------------%
c
cnorm = .true.
call second (t2)
if (bmat .eq. 'G') then
nbx = nbx + 1
call zcopy (n, resid, 1, workd(n+1), 1)
ipntr(1) = n + 1
ipntr(2) = 1
ido = 2
c
c %----------------------------------%
c | Exit in order to compute B*RESID |
c %----------------------------------%
c
go to 9000
else if (bmat .eq. 'I') then
call zcopy (n, resid, 1, workd, 1)
end if
c
100 continue
c
c %----------------------------------%
c | Back from reverse communication; |
c | WORKD(1:N) := B*RESID |
c %----------------------------------%
c
if (bmat .eq. 'G') then
call second (t3)
tmvbx = tmvbx + (t3 - t2)
end if
c
if (bmat .eq. 'G') then
cmpnorm = zdotc (n, resid, 1, workd, 1)
rnorm = sqrt(dlapy2 (dble (cmpnorm),dimag (cmpnorm)))
else if (bmat .eq. 'I') then
rnorm = dznrm2 (n, resid, 1)
end if
cnorm = .false.
c
if (msglvl .gt. 2) then
call dvout (logfil, 1, rnorm, ndigit,
& '_naup2: B-norm of residual for compressed factorization')
call zmout (logfil, nev, nev, h, ldh, ndigit,
& '_naup2: Compressed upper Hessenberg matrix H')
end if
c
go to 1000
c
c %---------------------------------------------------------------%
c | |
c | E N D O F M A I N I T E R A T I O N L O O P |
c | |
c %---------------------------------------------------------------%
c
1100 continue
c
mxiter = iter
nev = nconv
c
1200 continue
ido = 99
c
c %------------%
c | Error Exit |
c %------------%
c
call second (t1)
tcaup2 = t1 - t0
c
9000 continue
c
c %---------------%
c | End of znaup2 |
c %---------------%
c
return
end

664
arpack/ARPACK/SRC/znaupd.f Normal file
View File

@@ -0,0 +1,664 @@
c\BeginDoc
c
c\Name: znaupd
c
c\Description:
c Reverse communication interface for the Implicitly Restarted Arnoldi
c iteration. This is intended to be used to find a few eigenpairs of a
c complex linear operator OP with respect to a semi-inner product defined
c by a hermitian positive semi-definite real matrix B. B may be the identity
c matrix. NOTE: if both OP and B are real, then dsaupd or dnaupd should
c be used.
c
c
c The computed approximate eigenvalues are called Ritz values and
c the corresponding approximate eigenvectors are called Ritz vectors.
c
c znaupd is usually called iteratively to solve one of the
c following problems:
c
c Mode 1: A*x = lambda*x.
c ===> OP = A and B = I.
c
c Mode 2: A*x = lambda*M*x, M hermitian positive definite
c ===> OP = inv[M]*A and B = M.
c ===> (If M can be factored see remark 3 below)
c
c Mode 3: A*x = lambda*M*x, M hermitian semi-definite
c ===> OP = inv[A - sigma*M]*M and B = M.
c ===> shift-and-invert mode
c If OP*x = amu*x, then lambda = sigma + 1/amu.
c
c
c NOTE: The action of w <- inv[A - sigma*M]*v or w <- inv[M]*v
c should be accomplished either by a direct method
c using a sparse matrix factorization and solving
c
c [A - sigma*M]*w = v or M*w = v,
c
c or through an iterative method for solving these
c systems. If an iterative method is used, the
c convergence test must be more stringent than
c the accuracy requirements for the eigenvalue
c approximations.
c
c\Usage:
c call znaupd
c ( IDO, BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM,
c IPNTR, WORKD, WORKL, LWORKL, RWORK, INFO )
c
c\Arguments
c IDO Integer. (INPUT/OUTPUT)
c Reverse communication flag. IDO must be zero on the first
c call to znaupd. IDO will be set internally to
c indicate the type of operation to be performed. Control is
c then given back to the calling routine which has the
c responsibility to carry out the requested operation and call
c znaupd with the result. The operand is given in
c WORKD(IPNTR(1)), the result must be put in WORKD(IPNTR(2)).
c -------------------------------------------------------------
c IDO = 0: first call to the reverse communication interface
c IDO = -1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c This is for the initialization phase to force the
c starting vector into the range of OP.
c IDO = 1: compute Y = OP * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c In mode 3, the vector B * X is already
c available in WORKD(ipntr(3)). It does not
c need to be recomputed in forming OP * X.
c IDO = 2: compute Y = M * X where
c IPNTR(1) is the pointer into WORKD for X,
c IPNTR(2) is the pointer into WORKD for Y.
c IDO = 3: compute and return the shifts in the first
c NP locations of WORKL.
c IDO = 99: done
c -------------------------------------------------------------
c After the initialization phase, when the routine is used in
c the "shift-and-invert" mode, the vector M * X is already
c available and does not need to be recomputed in forming OP*X.
c
c BMAT Character*1. (INPUT)
c BMAT specifies the type of the matrix B that defines the
c semi-inner product for the operator OP.
c BMAT = 'I' -> standard eigenvalue problem A*x = lambda*x
c BMAT = 'G' -> generalized eigenvalue problem A*x = lambda*M*x
c
c N Integer. (INPUT)
c Dimension of the eigenproblem.
c
c WHICH Character*2. (INPUT)
c 'LM' -> want the NEV eigenvalues of largest magnitude.
c 'SM' -> want the NEV eigenvalues of smallest magnitude.
c 'LR' -> want the NEV eigenvalues of largest real part.
c 'SR' -> want the NEV eigenvalues of smallest real part.
c 'LI' -> want the NEV eigenvalues of largest imaginary part.
c 'SI' -> want the NEV eigenvalues of smallest imaginary part.
c
c NEV Integer. (INPUT)
c Number of eigenvalues of OP to be computed. 0 < NEV < N-1.
c
c TOL Double precision scalar. (INPUT)
c Stopping criteria: the relative accuracy of the Ritz value
c is considered acceptable if BOUNDS(I) .LE. TOL*ABS(RITZ(I))
c where ABS(RITZ(I)) is the magnitude when RITZ(I) is complex.
c DEFAULT = dlamch('EPS') (machine precision as computed
c by the LAPACK auxiliary subroutine dlamch).
c
c RESID Complex*16 array of length N. (INPUT/OUTPUT)
c On INPUT:
c If INFO .EQ. 0, a random initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c On OUTPUT:
c RESID contains the final residual vector.
c
c NCV Integer. (INPUT)
c Number of columns of the matrix V. NCV must satisfy the two
c inequalities 1 <= NCV-NEV and NCV <= N.
c This will indicate how many Arnoldi vectors are generated
c at each iteration. After the startup phase in which NEV
c Arnoldi vectors are generated, the algorithm generates
c approximately NCV-NEV Arnoldi vectors at each subsequent update
c iteration. Most of the cost in generating each Arnoldi vector is
c in the matrix-vector operation OP*x. (See remark 4 below.)
c
c V Complex*16 array N by NCV. (OUTPUT)
c Contains the final set of Arnoldi basis vectors.
c
c LDV Integer. (INPUT)
c Leading dimension of V exactly as declared in the calling program.
c
c IPARAM Integer array of length 11. (INPUT/OUTPUT)
c IPARAM(1) = ISHIFT: method for selecting the implicit shifts.
c The shifts selected at each iteration are used to filter out
c the components of the unwanted eigenvector.
c -------------------------------------------------------------
c ISHIFT = 0: the shifts are to be provided by the user via
c reverse communication. The NCV eigenvalues of
c the Hessenberg matrix H are returned in the part
c of WORKL array corresponding to RITZ.
c ISHIFT = 1: exact shifts with respect to the current
c Hessenberg matrix H. This is equivalent to
c restarting the iteration from the beginning
c after updating the starting vector with a linear
c combination of Ritz vectors associated with the
c "wanted" eigenvalues.
c ISHIFT = 2: other choice of internal shift to be defined.
c -------------------------------------------------------------
c
c IPARAM(2) = No longer referenced
c
c IPARAM(3) = MXITER
c On INPUT: maximum number of Arnoldi update iterations allowed.
c On OUTPUT: actual number of Arnoldi update iterations taken.
c
c IPARAM(4) = NB: blocksize to be used in the recurrence.
c The code currently works only for NB = 1.
c
c IPARAM(5) = NCONV: number of "converged" Ritz values.
c This represents the number of Ritz values that satisfy
c the convergence criterion.
c
c IPARAM(6) = IUPD
c No longer referenced. Implicit restarting is ALWAYS used.
c
c IPARAM(7) = MODE
c On INPUT determines what type of eigenproblem is being solved.
c Must be 1,2,3; See under \Description of znaupd for the
c four modes available.
c
c IPARAM(8) = NP
c When ido = 3 and the user provides shifts through reverse
c communication (IPARAM(1)=0), _naupd returns NP, the number
c of shifts the user is to provide. 0 < NP < NCV-NEV.
c
c IPARAM(9) = NUMOP, IPARAM(10) = NUMOPB, IPARAM(11) = NUMREO,
c OUTPUT: NUMOP = total number of OP*x operations,
c NUMOPB = total number of B*x operations if BMAT='G',
c NUMREO = total number of steps of re-orthogonalization.
c
c IPNTR Integer array of length 14. (OUTPUT)
c Pointer to mark the starting locations in the WORKD and WORKL
c arrays for matrices/vectors used by the Arnoldi iteration.
c -------------------------------------------------------------
c IPNTR(1): pointer to the current operand vector X in WORKD.
c IPNTR(2): pointer to the current result vector Y in WORKD.
c IPNTR(3): pointer to the vector B * X in WORKD when used in
c the shift-and-invert mode.
c IPNTR(4): pointer to the next available location in WORKL
c that is untouched by the program.
c IPNTR(5): pointer to the NCV by NCV upper Hessenberg
c matrix H in WORKL.
c IPNTR(6): pointer to the ritz value array RITZ
c IPNTR(7): pointer to the (projected) ritz vector array Q
c IPNTR(8): pointer to the error BOUNDS array in WORKL.
c IPNTR(14): pointer to the NP shifts in WORKL. See Remark 5 below.
c
c Note: IPNTR(9:13) is only referenced by zneupd. See Remark 2 below.
c
c IPNTR(9): pointer to the NCV RITZ values of the
c original system.
c IPNTR(10): Not Used
c IPNTR(11): pointer to the NCV corresponding error bounds.
c IPNTR(12): pointer to the NCV by NCV upper triangular
c Schur matrix for H.
c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors
c of the upper Hessenberg matrix H. Only referenced by
c zneupd if RVEC = .TRUE. See Remark 2 below.
c
c -------------------------------------------------------------
c
c WORKD Complex*16 work array of length 3*N. (REVERSE COMMUNICATION)
c Distributed array to be used in the basic Arnoldi iteration
c for reverse communication. The user should not use WORKD
c as temporary workspace during the iteration !!!!!!!!!!
c See Data Distribution Note below.
c
c WORKL Complex*16 work array of length LWORKL. (OUTPUT/WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. See Data Distribution Note below.
c
c LWORKL Integer. (INPUT)
c LWORKL must be at least 3*NCV**2 + 5*NCV.
c
c RWORK Double precision work array of length NCV (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c
c INFO Integer. (INPUT/OUTPUT)
c If INFO .EQ. 0, a randomly initial residual vector is used.
c If INFO .NE. 0, RESID contains the initial residual vector,
c possibly from a previous run.
c Error flag on output.
c = 0: Normal exit.
c = 1: Maximum number of iterations taken.
c All possible eigenvalues of OP has been found. IPARAM(5)
c returns the number of wanted converged Ritz values.
c = 2: No longer an informational error. Deprecated starting
c with release 2 of ARPACK.
c = 3: No shifts could be applied during a cycle of the
c Implicitly restarted Arnoldi iteration. One possibility
c is to increase the size of NCV relative to NEV.
c See remark 4 below.
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV-NEV >= 1 and less than or equal to N.
c = -4: The maximum number of Arnoldi update iteration
c must be greater than zero.
c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work array is not sufficient.
c = -8: Error return from LAPACK eigenvalue calculation;
c = -9: Starting vector is zero.
c = -10: IPARAM(7) must be 1,2,3.
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.
c = -12: IPARAM(1) must be equal to 0 or 1.
c = -9999: Could not build an Arnoldi factorization.
c User input error highly likely. Please
c check actual array dimensions and layout.
c IPARAM(5) returns the size of the current Arnoldi
c factorization.
c
c\Remarks
c 1. The computed Ritz values are approximate eigenvalues of OP. The
c selection of WHICH should be made with this in mind when using
c Mode = 3. When operating in Mode = 3 setting WHICH = 'LM' will
c compute the NEV eigenvalues of the original problem that are
c closest to the shift SIGMA . After convergence, approximate eigenvalues
c of the original problem may be obtained with the ARPACK subroutine zneupd.
c
c 2. If a basis for the invariant subspace corresponding to the converged Ritz
c values is needed, the user must call zneupd immediately following
c completion of znaupd. This is new starting with release 2 of ARPACK.
c
c 3. If M can be factored into a Cholesky factorization M = LL`
c then Mode = 2 should not be selected. Instead one should use
c Mode = 1 with OP = inv(L)*A*inv(L`). Appropriate triangular
c linear systems should be solved with L and L` rather
c than computing inverses. After convergence, an approximate
c eigenvector z of the original problem is recovered by solving
c L`z = x where x is a Ritz vector of OP.
c
c 4. At present there is no a-priori analysis to guide the selection
c of NCV relative to NEV. The only formal requirement is that NCV > NEV + 1.
c However, it is recommended that NCV .ge. 2*NEV. If many problems of
c the same type are to be solved, one should experiment with increasing
c NCV while keeping NEV fixed for a given test problem. This will
c usually decrease the required number of OP*x operations but it
c also increases the work and storage required to maintain the orthogonal
c basis vectors. The optimal "cross-over" with respect to CPU time
c is problem dependent and must be determined empirically.
c See Chapter 8 of Reference 2 for further information.
c
c 5. When IPARAM(1) = 0, and IDO = 3, the user needs to provide the
c NP = IPARAM(8) complex shifts in locations
c WORKL(IPNTR(14)), WORKL(IPNTR(14)+1), ... , WORKL(IPNTR(14)+NP).
c Eigenvalues of the current upper Hessenberg matrix are located in
c WORKL(IPNTR(6)) through WORKL(IPNTR(6)+NCV-1). They are ordered
c according to the order defined by WHICH. The associated Ritz estimates
c are located in WORKL(IPNTR(8)), WORKL(IPNTR(8)+1), ... ,
c WORKL(IPNTR(8)+NCV-1).
c
c-----------------------------------------------------------------------
c
c\Data Distribution Note:
c
c Fortran-D syntax:
c ================
c Complex*16 resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
c decompose d1(n), d2(n,ncv)
c align resid(i) with d1(i)
c align v(i,j) with d2(i,j)
c align workd(i) with d1(i) range (1:n)
c align workd(i) with d1(i-n) range (n+1:2*n)
c align workd(i) with d1(i-2*n) range (2*n+1:3*n)
c distribute d1(block), d2(block,:)
c replicated workl(lworkl)
c
c Cray MPP syntax:
c ===============
c Complex*16 resid(n), v(ldv,ncv), workd(n,3), workl(lworkl)
c shared resid(block), v(block,:), workd(block,:)
c replicated workl(lworkl)
c
c CM2/CM5 syntax:
c ==============
c
c-----------------------------------------------------------------------
c
c include 'ex-nonsym.doc'
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex*16
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett & Y. Saad, "_Complex_ Shift and Invert Strategies for
c Double precision Matrices", Linear Algebra and its Applications, vol 88/89,
c pp 575-595, (1987).
c
c\Routines called:
c znaup2 ARPACK routine that implements the Implicitly Restarted
c Arnoldi Iteration.
c zstatn ARPACK routine that initializes the timing variables.
c ivout ARPACK utility routine that prints integers.
c zvout ARPACK utility routine that prints vectors.
c second ARPACK utility routine for timing.
c dlamch LAPACK routine that determines machine constants.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: naupd.F SID: 2.9 DATE OF SID: 07/21/02 RELEASE: 2
c
c\Remarks
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine znaupd
& ( ido, bmat, n, which, nev, tol, resid, ncv, v, ldv, iparam,
& ipntr, workd, workl, lworkl, rwork, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat*1, which*2
integer ido, info, ldv, lworkl, n, ncv, nev
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(11), ipntr(14)
Complex*16
& resid(n), v(ldv,ncv), workd(3*n), workl(lworkl)
Double precision
& rwork(ncv)
c
c %------------%
c | Parameters |
c %------------%
c
Complex*16
& one, zero
parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0))
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer bounds, ierr, ih, iq, ishift, iupd, iw,
& ldh, ldq, levec, mode, msglvl, mxiter, nb,
& nev0, next, np, ritz, j
save bounds, ih, iq, ishift, iupd, iw,
& ldh, ldq, levec, mode, msglvl, mxiter, nb,
& nev0, next, np, ritz
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external znaup2, zvout, ivout, second, zstatn
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dlamch
external dlamch
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
if (ido .eq. 0) then
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call zstatn
call second (t0)
msglvl = mcaupd
c
c %----------------%
c | Error checking |
c %----------------%
c
ierr = 0
ishift = iparam(1)
c levec = iparam(2)
mxiter = iparam(3)
c nb = iparam(4)
nb = 1
c
c %--------------------------------------------%
c | Revision 2 performs only implicit restart. |
c %--------------------------------------------%
c
iupd = 1
mode = iparam(7)
c
if (n .le. 0) then
ierr = -1
else if (nev .le. 0) then
ierr = -2
else if (ncv .le. nev .or. ncv .gt. n) then
ierr = -3
else if (mxiter .le. 0) then
ierr = -4
else if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LR' .and.
& which .ne. 'SR' .and.
& which .ne. 'LI' .and.
& which .ne. 'SI') then
ierr = -5
else if (bmat .ne. 'I' .and. bmat .ne. 'G') then
ierr = -6
else if (lworkl .lt. 3*ncv**2 + 5*ncv) then
ierr = -7
else if (mode .lt. 1 .or. mode .gt. 3) then
ierr = -10
else if (mode .eq. 1 .and. bmat .eq. 'G') then
ierr = -11
end if
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
ido = 99
go to 9000
end if
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
if (nb .le. 0) nb = 1
if (tol .le. 0.0D+0 ) tol = dlamch('EpsMach')
if (ishift .ne. 0 .and.
& ishift .ne. 1 .and.
& ishift .ne. 2) ishift = 1
c
c %----------------------------------------------%
c | NP is the number of additional steps to |
c | extend the length NEV Lanczos factorization. |
c | NEV0 is the local variable designating the |
c | size of the invariant subspace desired. |
c %----------------------------------------------%
c
np = ncv - nev
nev0 = nev
c
c %-----------------------------%
c | Zero out internal workspace |
c %-----------------------------%
c
do 10 j = 1, 3*ncv**2 + 5*ncv
workl(j) = zero
10 continue
c
c %-------------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:ncv*ncv) := generated Hessenberg matrix |
c | workl(ncv*ncv+1:ncv*ncv+ncv) := the ritz values |
c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds |
c | workl(ncv*ncv+2*ncv+1:2*ncv*ncv+2*ncv) := rotation matrix Q |
c | workl(2*ncv*ncv+2*ncv+1:3*ncv*ncv+5*ncv) := workspace |
c | The final workspace is needed by subroutine zneigh called |
c | by znaup2. Subroutine zneigh calls LAPACK routines for |
c | calculating eigenvalues and the last row of the eigenvector |
c | matrix. |
c %-------------------------------------------------------------%
c
ldh = ncv
ldq = ncv
ih = 1
ritz = ih + ldh*ncv
bounds = ritz + ncv
iq = bounds + ncv
iw = iq + ldq*ncv
next = iw + ncv**2 + 3*ncv
c
ipntr(4) = next
ipntr(5) = ih
ipntr(6) = ritz
ipntr(7) = iq
ipntr(8) = bounds
ipntr(14) = iw
end if
c
c %-------------------------------------------------------%
c | Carry out the Implicitly restarted Arnoldi Iteration. |
c %-------------------------------------------------------%
c
call znaup2
& ( ido, bmat, n, which, nev0, np, tol, resid, mode, iupd,
& ishift, mxiter, v, ldv, workl(ih), ldh, workl(ritz),
& workl(bounds), workl(iq), ldq, workl(iw),
& ipntr, workd, rwork, info )
c
c %--------------------------------------------------%
c | ido .ne. 99 implies use of reverse communication |
c | to compute operations involving OP. |
c %--------------------------------------------------%
c
if (ido .eq. 3) iparam(8) = np
if (ido .ne. 99) go to 9000
c
iparam(3) = mxiter
iparam(5) = np
iparam(9) = nopx
iparam(10) = nbx
iparam(11) = nrorth
c
c %------------------------------------%
c | Exit if there was an informational |
c | error within znaup2. |
c %------------------------------------%
c
if (info .lt. 0) go to 9000
if (info .eq. 2) info = 3
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, mxiter, ndigit,
& '_naupd: Number of update iterations taken')
call ivout (logfil, 1, np, ndigit,
& '_naupd: Number of wanted "converged" Ritz values')
call zvout (logfil, np, workl(ritz), ndigit,
& '_naupd: The final Ritz values')
call zvout (logfil, np, workl(bounds), ndigit,
& '_naupd: Associated Ritz estimates')
end if
c
call second (t1)
tcaupd = t1 - t0
c
if (msglvl .gt. 0) then
c
c %--------------------------------------------------------%
c | Version Number & Version Date are defined in version.h |
c %--------------------------------------------------------%
c
write (6,1000)
write (6,1100) mxiter, nopx, nbx, nrorth, nitref, nrstrt,
& tmvopx, tmvbx, tcaupd, tcaup2, tcaitr, titref,
& tgetv0, tceigh, tcgets, tcapps, tcconv, trvec
1000 format (//,
& 5x, '=============================================',/
& 5x, '= Complex implicit Arnoldi update code =',/
& 5x, '= Version Number: ', ' 2.3', 21x, ' =',/
& 5x, '= Version Date: ', ' 07/31/96', 16x, ' =',/
& 5x, '=============================================',/
& 5x, '= Summary of timing statistics =',/
& 5x, '=============================================',//)
1100 format (
& 5x, 'Total number update iterations = ', i5,/
& 5x, 'Total number of OP*x operations = ', i5,/
& 5x, 'Total number of B*x operations = ', i5,/
& 5x, 'Total number of reorthogonalization steps = ', i5,/
& 5x, 'Total number of iterative refinement steps = ', i5,/
& 5x, 'Total number of restart steps = ', i5,/
& 5x, 'Total time in user OP*x operation = ', f12.6,/
& 5x, 'Total time in user B*x operation = ', f12.6,/
& 5x, 'Total time in Arnoldi update routine = ', f12.6,/
& 5x, 'Total time in naup2 routine = ', f12.6,/
& 5x, 'Total time in basic Arnoldi iteration loop = ', f12.6,/
& 5x, 'Total time in reorthogonalization phase = ', f12.6,/
& 5x, 'Total time in (re)start vector generation = ', f12.6,/
& 5x, 'Total time in Hessenberg eig. subproblem = ', f12.6,/
& 5x, 'Total time in getting the shifts = ', f12.6,/
& 5x, 'Total time in applying the shifts = ', f12.6,/
& 5x, 'Total time in convergence testing = ', f12.6,/
& 5x, 'Total time in computing final Ritz vectors = ', f12.6/)
end if
c
9000 continue
c
return
c
c %---------------%
c | End of znaupd |
c %---------------%
c
end

257
arpack/ARPACK/SRC/zneigh.f Normal file
View File

@@ -0,0 +1,257 @@
c\BeginDoc
c
c\Name: zneigh
c
c\Description:
c Compute the eigenvalues of the current upper Hessenberg matrix
c and the corresponding Ritz estimates given the current residual norm.
c
c\Usage:
c call zneigh
c ( RNORM, N, H, LDH, RITZ, BOUNDS, Q, LDQ, WORKL, RWORK, IERR )
c
c\Arguments
c RNORM Double precision scalar. (INPUT)
c Residual norm corresponding to the current upper Hessenberg
c matrix H.
c
c N Integer. (INPUT)
c Size of the matrix H.
c
c H Complex*16 N by N array. (INPUT)
c H contains the current upper Hessenberg matrix.
c
c LDH Integer. (INPUT)
c Leading dimension of H exactly as declared in the calling
c program.
c
c RITZ Complex*16 array of length N. (OUTPUT)
c On output, RITZ(1:N) contains the eigenvalues of H.
c
c BOUNDS Complex*16 array of length N. (OUTPUT)
c On output, BOUNDS contains the Ritz estimates associated with
c the eigenvalues held in RITZ. This is equal to RNORM
c times the last components of the eigenvectors corresponding
c to the eigenvalues in RITZ.
c
c Q Complex*16 N by N array. (WORKSPACE)
c Workspace needed to store the eigenvectors of H.
c
c LDQ Integer. (INPUT)
c Leading dimension of Q exactly as declared in the calling
c program.
c
c WORKL Complex*16 work array of length N**2 + 3*N. (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end. This is needed to keep the full Schur form
c of H and also in the calculation of the eigenvectors of H.
c
c RWORK Double precision work array of length N (WORKSPACE)
c Private (replicated) array on each PE or array allocated on
c the front end.
c
c IERR Integer. (OUTPUT)
c Error exit flag from zlahqr or ztrevc.
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex*16
c
c\Routines called:
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c zmout ARPACK utility routine that prints matrices
c zvout ARPACK utility routine that prints vectors.
c dvout ARPACK utility routine that prints vectors.
c zlacpy LAPACK matrix copy routine.
c zlahqr LAPACK routine to compute the Schur form of an
c upper Hessenberg matrix.
c zlaset LAPACK matrix initialization routine.
c ztrevc LAPACK routine to compute the eigenvectors of a matrix
c in upper triangular form
c zcopy Level 1 BLAS that copies one vector to another.
c zdscal Level 1 BLAS that scales a complex vector by a real number.
c dznrm2 Level 1 BLAS that computes the norm of a vector.
c
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: neigh.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2
c
c\Remarks
c None
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine zneigh (rnorm, n, h, ldh, ritz, bounds,
& q, ldq, workl, rwork, ierr)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
integer ierr, n, ldh, ldq
Double precision
& rnorm
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Complex*16
& bounds(n), h(ldh,n), q(ldq,n), ritz(n),
& workl(n*(n+3))
Double precision
& rwork(n)
c
c %------------%
c | Parameters |
c %------------%
c
Complex*16
& one, zero
Double precision
& rone
parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0),
& rone = 1.0D+0)
c
c %------------------------%
c | Local Scalars & Arrays |
c %------------------------%
c
logical select(1)
integer j, msglvl
Complex*16
& vl(1)
Double precision
& temp
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external zlacpy, zlahqr, ztrevc, zcopy,
& zdscal, zmout, zvout, second
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dznrm2
external dznrm2
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mceigh
c
if (msglvl .gt. 2) then
call zmout (logfil, n, n, h, ldh, ndigit,
& '_neigh: Entering upper Hessenberg matrix H ')
end if
c
c %----------------------------------------------------------%
c | 1. Compute the eigenvalues, the last components of the |
c | corresponding Schur vectors and the full Schur form T |
c | of the current upper Hessenberg matrix H. |
c | zlahqr returns the full Schur form of H |
c | in WORKL(1:N**2), and the Schur vectors in q. |
c %----------------------------------------------------------%
c
call zlacpy ('All', n, n, h, ldh, workl, n)
call zlaset ('All', n, n, zero, one, q, ldq)
call zlahqr (.true., .true., n, 1, n, workl, ldh, ritz,
& 1, n, q, ldq, ierr)
if (ierr .ne. 0) go to 9000
c
call zcopy (n, q(n-1,1), ldq, bounds, 1)
if (msglvl .gt. 1) then
call zvout (logfil, n, bounds, ndigit,
& '_neigh: last row of the Schur matrix for H')
end if
c
c %----------------------------------------------------------%
c | 2. Compute the eigenvectors of the full Schur form T and |
c | apply the Schur vectors to get the corresponding |
c | eigenvectors. |
c %----------------------------------------------------------%
c
call ztrevc ('Right', 'Back', select, n, workl, n, vl, n, q,
& ldq, n, n, workl(n*n+1), rwork, ierr)
c
if (ierr .ne. 0) go to 9000
c
c %------------------------------------------------%
c | Scale the returning eigenvectors so that their |
c | Euclidean norms are all one. LAPACK subroutine |
c | ztrevc returns each eigenvector normalized so |
c | that the element of largest magnitude has |
c | magnitude 1; here the magnitude of a complex |
c | number (x,y) is taken to be |x| + |y|. |
c %------------------------------------------------%
c
do 10 j=1, n
temp = dznrm2( n, q(1,j), 1 )
call zdscal ( n, rone / temp, q(1,j), 1 )
10 continue
c
if (msglvl .gt. 1) then
call zcopy(n, q(n,1), ldq, workl, 1)
call zvout (logfil, n, workl, ndigit,
& '_neigh: Last row of the eigenvector matrix for H')
end if
c
c %----------------------------%
c | Compute the Ritz estimates |
c %----------------------------%
c
call zcopy(n, q(n,1), n, bounds, 1)
call zdscal(n, rnorm, bounds, 1)
c
if (msglvl .gt. 2) then
call zvout (logfil, n, ritz, ndigit,
& '_neigh: The eigenvalues of H')
call zvout (logfil, n, bounds, ndigit,
& '_neigh: Ritz estimates for the eigenvalues of H')
end if
c
call second(t1)
tceigh = tceigh + (t1 - t0)
c
9000 continue
return
c
c %---------------%
c | End of zneigh |
c %---------------%
c
end

872
arpack/ARPACK/SRC/zneupd.f Normal file
View File

@@ -0,0 +1,872 @@
c\BeginDoc
c
c\Name: zneupd
c
c\Description:
c This subroutine returns the converged approximations to eigenvalues
c of A*z = lambda*B*z and (optionally):
c
c (1) The corresponding approximate eigenvectors;
c
c (2) An orthonormal basis for the associated approximate
c invariant subspace;
c
c (3) Both.
c
c There is negligible additional cost to obtain eigenvectors. An orthonormal
c basis is always computed. There is an additional storage cost of n*nev
c if both are requested (in this case a separate array Z must be supplied).
c
c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z
c are derived from approximate eigenvalues and eigenvectors of
c of the linear operator OP prescribed by the MODE selection in the
c call to ZNAUPD. ZNAUPD must be called before this routine is called.
c These approximate eigenvalues and vectors are commonly called Ritz
c values and Ritz vectors respectively. They are referred to as such
c in the comments that follow. The computed orthonormal basis for the
c invariant subspace corresponding to these Ritz values is referred to as a
c Schur basis.
c
c The definition of OP as well as other terms and the relation of computed
c Ritz values and vectors of OP with respect to the given problem
c A*z = lambda*B*z may be found in the header of ZNAUPD. For a brief
c description, see definitions of IPARAM(7), MODE and WHICH in the
c documentation of ZNAUPD.
c
c\Usage:
c call zneupd
c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, WORKEV, BMAT,
c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD,
c WORKL, LWORKL, RWORK, INFO )
c
c\Arguments:
c RVEC LOGICAL (INPUT)
c Specifies whether a basis for the invariant subspace corresponding
c to the converged Ritz value approximations for the eigenproblem
c A*z = lambda*B*z is computed.
c
c RVEC = .FALSE. Compute Ritz values only.
c
c RVEC = .TRUE. Compute Ritz vectors or Schur vectors.
c See Remarks below.
c
c HOWMNY Character*1 (INPUT)
c Specifies the form of the basis for the invariant subspace
c corresponding to the converged Ritz values that is to be computed.
c
c = 'A': Compute NEV Ritz vectors;
c = 'P': Compute NEV Schur vectors;
c = 'S': compute some of the Ritz vectors, specified
c by the logical array SELECT.
c
c SELECT Logical array of dimension NCV. (INPUT)
c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be
c computed. To select the Ritz vector corresponding to a
c Ritz value D(j), SELECT(j) must be set to .TRUE..
c If HOWMNY = 'A' or 'P', SELECT need not be initialized
c but it is used as internal workspace.
c
c D Complex*16 array of dimension NEV+1. (OUTPUT)
c On exit, D contains the Ritz approximations
c to the eigenvalues lambda for A*z = lambda*B*z.
c
c Z Complex*16 N by NEV array (OUTPUT)
c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of
c Z represents approximate eigenvectors (Ritz vectors) corresponding
c to the NCONV=IPARAM(5) Ritz values for eigensystem
c A*z = lambda*B*z.
c
c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED.
c
c NOTE: If if RVEC = .TRUE. and a Schur basis is not required,
c the array Z may be set equal to first NEV+1 columns of the Arnoldi
c basis array V computed by ZNAUPD. In this case the Arnoldi basis
c will be destroyed and overwritten with the eigenvector basis.
c
c LDZ Integer. (INPUT)
c The leading dimension of the array Z. If Ritz vectors are
c desired, then LDZ .ge. max( 1, N ) is required.
c In any case, LDZ .ge. 1 is required.
c
c SIGMA Complex*16 (INPUT)
c If IPARAM(7) = 3 then SIGMA represents the shift.
c Not referenced if IPARAM(7) = 1 or 2.
c
c WORKEV Complex*16 work array of dimension 2*NCV. (WORKSPACE)
c
c **** The remaining arguments MUST be the same as for the ****
c **** call to ZNAUPD that was just completed. ****
c
c NOTE: The remaining arguments
c
c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR,
c WORKD, WORKL, LWORKL, RWORK, INFO
c
c must be passed directly to ZNEUPD following the last call
c to ZNAUPD. These arguments MUST NOT BE MODIFIED between
c the the last call to ZNAUPD and the call to ZNEUPD.
c
c Three of these parameters (V, WORKL and INFO) are also output parameters:
c
c V Complex*16 N by NCV array. (INPUT/OUTPUT)
c
c Upon INPUT: the NCV columns of V contain the Arnoldi basis
c vectors for OP as constructed by ZNAUPD .
c
c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns
c contain approximate Schur vectors that span the
c desired invariant subspace.
c
c NOTE: If the array Z has been set equal to first NEV+1 columns
c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the
c Arnoldi basis held by V has been overwritten by the desired
c Ritz vectors. If a separate array Z has been passed then
c the first NCONV=IPARAM(5) columns of V will contain approximate
c Schur vectors that span the desired invariant subspace.
c
c WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE)
c WORKL(1:ncv*ncv+2*ncv) contains information obtained in
c znaupd. They are not changed by zneupd.
c WORKL(ncv*ncv+2*ncv+1:3*ncv*ncv+4*ncv) holds the
c untransformed Ritz values, the untransformed error estimates of
c the Ritz values, the upper triangular matrix for H, and the
c associated matrix representation of the invariant subspace for H.
c
c Note: IPNTR(9:13) contains the pointer into WORKL for addresses
c of the above information computed by zneupd.
c -------------------------------------------------------------
c IPNTR(9): pointer to the NCV RITZ values of the
c original system.
c IPNTR(10): Not used
c IPNTR(11): pointer to the NCV corresponding error estimates.
c IPNTR(12): pointer to the NCV by NCV upper triangular
c Schur matrix for H.
c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors
c of the upper Hessenberg matrix H. Only referenced by
c zneupd if RVEC = .TRUE. See Remark 2 below.
c -------------------------------------------------------------
c
c INFO Integer. (OUTPUT)
c Error flag on output.
c = 0: Normal exit.
c
c = 1: The Schur form computed by LAPACK routine csheqr
c could not be reordered by LAPACK routine ztrsen.
c Re-enter subroutine zneupd with IPARAM(5)=NCV and
c increase the size of the array D to have
c dimension at least dimension NCV and allocate at least NCV
c columns for Z. NOTE: Not necessary if Z and V share
c the same space. Please notify the authors if this error
c occurs.
c
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV-NEV >= 1 and less than or equal to N.
c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work WORKL array is not sufficient.
c = -8: Error return from LAPACK eigenvalue calculation.
c This should never happened.
c = -9: Error return from calculation of eigenvectors.
c Informational error from LAPACK routine ztrevc.
c = -10: IPARAM(7) must be 1,2,3
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.
c = -12: HOWMNY = 'S' not yet implemented
c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true.
c = -14: ZNAUPD did not find any eigenvalues to sufficient
c accuracy.
c = -15: ZNEUPD got a different count of the number of converged
c Ritz values than ZNAUPD got. This indicates the user
c probably made an error in passing data from ZNAUPD to
c ZNEUPD or that the data was modified before entering
c ZNEUPD
c
c\BeginLib
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B. Nour-Omid, B. N. Parlett, T. Ericsson and P. S. Jensen,
c "How to Implement the Spectral Transformation", Math Comp.,
c Vol. 48, No. 178, April, 1987 pp. 664-673.
c
c\Routines called:
c ivout ARPACK utility routine that prints integers.
c zmout ARPACK utility routine that prints matrices
c zvout ARPACK utility routine that prints vectors.
c zgeqr2 LAPACK routine that computes the QR factorization of
c a matrix.
c zlacpy LAPACK matrix copy routine.
c zlahqr LAPACK routine that computes the Schur form of a
c upper Hessenberg matrix.
c zlaset LAPACK matrix initialization routine.
c ztrevc LAPACK routine to compute the eigenvectors of a matrix
c in upper triangular form.
c ztrsen LAPACK routine that re-orders the Schur form.
c zunm2r LAPACK routine that applies an orthogonal matrix in
c factored form.
c dlamch LAPACK routine that determines machine constants.
c ztrmm Level 3 BLAS matrix times an upper triangular matrix.
c zgeru Level 2 BLAS rank one update to a matrix.
c zcopy Level 1 BLAS that copies one vector to another .
c zscal Level 1 BLAS that scales a vector.
c zdscal Level 1 BLAS that scales a complex vector by a real number.
c dznrm2 Level 1 BLAS that computes the norm of a complex vector.
c
c\Remarks
c
c 1. Currently only HOWMNY = 'A' and 'P' are implemented.
c
c 2. Schur vectors are an orthogonal representation for the basis of
c Ritz vectors. Thus, their numerical properties are often superior.
c If RVEC = .true. then the relationship
c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and
c transpose( V(:,1:IPARAM(5)) ) * V(:,1:IPARAM(5)) = I
c are approximately satisfied.
c Here T is the leading submatrix of order IPARAM(5) of the
c upper triangular matrix stored workl(ipntr(12)).
c
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Chao Yang Houston, Texas
c Dept. of Computational &
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: neupd.F SID: 2.8 DATE OF SID: 07/21/02 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
subroutine zneupd(rvec , howmny, select, d ,
& z , ldz , sigma , workev,
& bmat , n , which , nev ,
& tol , resid , ncv , v ,
& ldv , iparam, ipntr , workd ,
& workl, lworkl, rwork , info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat, howmny, which*2
logical rvec
integer info, ldz, ldv, lworkl, n, ncv, nev
Complex*16
& sigma
Double precision
& tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(11), ipntr(14)
logical select(ncv)
Double precision
& rwork(ncv)
Complex*16
& d(nev) , resid(n) , v(ldv,ncv),
& z(ldz, nev),
& workd(3*n) , workl(lworkl), workev(2*ncv)
c
c %------------%
c | Parameters |
c %------------%
c
Complex*16
& one, zero
parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0))
c
c %---------------%
c | Local Scalars |
c %---------------%
c
character type*6
integer bounds, ierr , ih , ihbds, iheig , nconv ,
& invsub, iuptri, iwev , j , ldh , ldq ,
& mode , msglvl, ritz , wr , k , irz ,
& ibd , outncv, iq , np , numcnv, jj ,
& ishift
Complex*16
& rnorm, temp, vl(1)
Double precision
& conds, sep, rtemp, eps23
logical reord
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external zcopy , zgeru, zgeqr2, zlacpy, zmout,
& zunm2r, ztrmm, zvout, ivout,
& zlahqr
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Double precision
& dznrm2, dlamch, dlapy2
external dznrm2, dlamch, dlapy2
c
Complex*16
& zdotc
external zdotc
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
msglvl = mceupd
mode = iparam(7)
nconv = iparam(5)
info = 0
c
c
c %---------------------------------%
c | Get machine dependent constant. |
c %---------------------------------%
c
eps23 = dlamch('Epsilon-Machine')
eps23 = eps23**(2.0D+0 / 3.0D+0)
c
c %-------------------------------%
c | Quick return |
c | Check for incompatible input |
c %-------------------------------%
c
ierr = 0
c
if (nconv .le. 0) then
ierr = -14
else if (n .le. 0) then
ierr = -1
else if (nev .le. 0) then
ierr = -2
else if (ncv .le. nev .or. ncv .gt. n) then
ierr = -3
else if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LR' .and.
& which .ne. 'SR' .and.
& which .ne. 'LI' .and.
& which .ne. 'SI') then
ierr = -5
else if (bmat .ne. 'I' .and. bmat .ne. 'G') then
ierr = -6
else if (lworkl .lt. 3*ncv**2 + 4*ncv) then
ierr = -7
else if ( (howmny .ne. 'A' .and.
& howmny .ne. 'P' .and.
& howmny .ne. 'S') .and. rvec ) then
ierr = -13
else if (howmny .eq. 'S' ) then
ierr = -12
end if
c
if (mode .eq. 1 .or. mode .eq. 2) then
type = 'REGULR'
else if (mode .eq. 3 ) then
type = 'SHIFTI'
else
ierr = -10
end if
if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
go to 9000
end if
c
c %--------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, WORKEV, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:ncv*ncv) := generated Hessenberg matrix |
c | workl(ncv*ncv+1:ncv*ncv+ncv) := ritz values |
c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds |
c %--------------------------------------------------------%
c
c %-----------------------------------------------------------%
c | The following is used and set by ZNEUPD. |
c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := The untransformed |
c | Ritz values. |
c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed |
c | error bounds of |
c | the Ritz values |
c | workl(ncv*ncv+4*ncv+1:2*ncv*ncv+4*ncv) := Holds the upper |
c | triangular matrix |
c | for H. |
c | workl(2*ncv*ncv+4*ncv+1: 3*ncv*ncv+4*ncv) := Holds the |
c | associated matrix |
c | representation of |
c | the invariant |
c | subspace for H. |
c | GRAND total of NCV * ( 3 * NCV + 4 ) locations. |
c %-----------------------------------------------------------%
c
ih = ipntr(5)
ritz = ipntr(6)
iq = ipntr(7)
bounds = ipntr(8)
ldh = ncv
ldq = ncv
iheig = bounds + ldh
ihbds = iheig + ldh
iuptri = ihbds + ldh
invsub = iuptri + ldh*ncv
ipntr(9) = iheig
ipntr(11) = ihbds
ipntr(12) = iuptri
ipntr(13) = invsub
wr = 1
iwev = wr + ncv
c
c %-----------------------------------------%
c | irz points to the Ritz values computed |
c | by _neigh before exiting _naup2. |
c | ibd points to the Ritz estimates |
c | computed by _neigh before exiting |
c | _naup2. |
c %-----------------------------------------%
c
irz = ipntr(14) + ncv*ncv
ibd = irz + ncv
c
c %------------------------------------%
c | RNORM is B-norm of the RESID(1:N). |
c %------------------------------------%
c
rnorm = workl(ih+2)
workl(ih+2) = zero
c
if (msglvl .gt. 2) then
call zvout(logfil, ncv, workl(irz), ndigit,
& '_neupd: Ritz values passed in from _NAUPD.')
call zvout(logfil, ncv, workl(ibd), ndigit,
& '_neupd: Ritz estimates passed in from _NAUPD.')
end if
c
if (rvec) then
c
reord = .false.
c
c %---------------------------------------------------%
c | Use the temporary bounds array to store indices |
c | These will be used to mark the select array later |
c %---------------------------------------------------%
c
do 10 j = 1,ncv
workl(bounds+j-1) = j
select(j) = .false.
10 continue
c
c %-------------------------------------%
c | Select the wanted Ritz values. |
c | Sort the Ritz values so that the |
c | wanted ones appear at the tailing |
c | NEV positions of workl(irr) and |
c | workl(iri). Move the corresponding |
c | error estimates in workl(ibd) |
c | accordingly. |
c %-------------------------------------%
c
np = ncv - nev
ishift = 0
call zngets(ishift, which , nev ,
& np , workl(irz), workl(bounds))
c
if (msglvl .gt. 2) then
call zvout (logfil, ncv, workl(irz), ndigit,
& '_neupd: Ritz values after calling _NGETS.')
call zvout (logfil, ncv, workl(bounds), ndigit,
& '_neupd: Ritz value indices after calling _NGETS.')
end if
c
c %-----------------------------------------------------%
c | Record indices of the converged wanted Ritz values |
c | Mark the select array for possible reordering |
c %-----------------------------------------------------%
c
numcnv = 0
do 11 j = 1,ncv
rtemp = max(eps23,
& dlapy2 ( dble(workl(irz+ncv-j)),
& dimag(workl(irz+ncv-j)) ))
jj = workl(bounds + ncv - j)
if (numcnv .lt. nconv .and.
& dlapy2( dble(workl(ibd+jj-1)),
& dimag(workl(ibd+jj-1)) )
& .le. tol*rtemp) then
select(jj) = .true.
numcnv = numcnv + 1
if (jj .gt. nev) reord = .true.
endif
11 continue
c
c %-----------------------------------------------------------%
c | Check the count (numcnv) of converged Ritz values with |
c | the number (nconv) reported by dnaupd. If these two |
c | are different then there has probably been an error |
c | caused by incorrect passing of the dnaupd data. |
c %-----------------------------------------------------------%
c
if (msglvl .gt. 2) then
call ivout(logfil, 1, numcnv, ndigit,
& '_neupd: Number of specified eigenvalues')
call ivout(logfil, 1, nconv, ndigit,
& '_neupd: Number of "converged" eigenvalues')
end if
c
if (numcnv .ne. nconv) then
info = -15
go to 9000
end if
c
c %-------------------------------------------------------%
c | Call LAPACK routine zlahqr to compute the Schur form |
c | of the upper Hessenberg matrix returned by ZNAUPD. |
c | Make a copy of the upper Hessenberg matrix. |
c | Initialize the Schur vector matrix Q to the identity. |
c %-------------------------------------------------------%
c
call zcopy(ldh*ncv, workl(ih), 1, workl(iuptri), 1)
call zlaset('All', ncv, ncv ,
& zero , one, workl(invsub),
& ldq)
call zlahqr(.true., .true. , ncv ,
& 1 , ncv , workl(iuptri),
& ldh , workl(iheig) , 1 ,
& ncv , workl(invsub), ldq ,
& ierr)
call zcopy(ncv , workl(invsub+ncv-1), ldq,
& workl(ihbds), 1)
c
if (ierr .ne. 0) then
info = -8
go to 9000
end if
c
if (msglvl .gt. 1) then
call zvout (logfil, ncv, workl(iheig), ndigit,
& '_neupd: Eigenvalues of H')
call zvout (logfil, ncv, workl(ihbds), ndigit,
& '_neupd: Last row of the Schur vector matrix')
if (msglvl .gt. 3) then
call zmout (logfil , ncv, ncv ,
& workl(iuptri), ldh, ndigit,
& '_neupd: The upper triangular matrix ')
end if
end if
c
if (reord) then
c
c %-----------------------------------------------%
c | Reorder the computed upper triangular matrix. |
c %-----------------------------------------------%
c
call ztrsen('None' , 'V' , select ,
& ncv , workl(iuptri), ldh ,
& workl(invsub), ldq , workl(iheig),
& nconv , conds , sep ,
& workev , ncv , ierr)
c
if (ierr .eq. 1) then
info = 1
go to 9000
end if
c
if (msglvl .gt. 2) then
call zvout (logfil, ncv, workl(iheig), ndigit,
& '_neupd: Eigenvalues of H--reordered')
if (msglvl .gt. 3) then
call zmout(logfil , ncv, ncv ,
& workl(iuptri), ldq, ndigit,
& '_neupd: Triangular matrix after re-ordering')
end if
end if
c
end if
c
c %---------------------------------------------%
c | Copy the last row of the Schur basis matrix |
c | to workl(ihbds). This vector will be used |
c | to compute the Ritz estimates of converged |
c | Ritz values. |
c %---------------------------------------------%
c
call zcopy(ncv , workl(invsub+ncv-1), ldq,
& workl(ihbds), 1)
c
c %--------------------------------------------%
c | Place the computed eigenvalues of H into D |
c | if a spectral transformation was not used. |
c %--------------------------------------------%
c
if (type .eq. 'REGULR') then
call zcopy(nconv, workl(iheig), 1, d, 1)
end if
c
c %----------------------------------------------------------%
c | Compute the QR factorization of the matrix representing |
c | the wanted invariant subspace located in the first NCONV |
c | columns of workl(invsub,ldq). |
c %----------------------------------------------------------%
c
call zgeqr2(ncv , nconv , workl(invsub),
& ldq , workev, workev(ncv+1),
& ierr)
c
c %--------------------------------------------------------%
c | * Postmultiply V by Q using zunm2r. |
c | * Copy the first NCONV columns of VQ into Z. |
c | * Postmultiply Z by R. |
c | The N by NCONV matrix Z is now a matrix representation |
c | of the approximate invariant subspace associated with |
c | the Ritz values in workl(iheig). The first NCONV |
c | columns of V are now approximate Schur vectors |
c | associated with the upper triangular matrix of order |
c | NCONV in workl(iuptri). |
c %--------------------------------------------------------%
c
call zunm2r('Right', 'Notranspose', n ,
& ncv , nconv , workl(invsub),
& ldq , workev , v ,
& ldv , workd(n+1) , ierr)
call zlacpy('All', n, nconv, v, ldv, z, ldz)
c
do 20 j=1, nconv
c
c %---------------------------------------------------%
c | Perform both a column and row scaling if the |
c | diagonal element of workl(invsub,ldq) is negative |
c | I'm lazy and don't take advantage of the upper |
c | triangular form of workl(iuptri,ldq). |
c | Note that since Q is orthogonal, R is a diagonal |
c | matrix consisting of plus or minus ones. |
c %---------------------------------------------------%
c
if ( dble( workl(invsub+(j-1)*ldq+j-1) ) .lt.
& dble(zero) ) then
call zscal(nconv, -one, workl(iuptri+j-1), ldq)
call zscal(nconv, -one, workl(iuptri+(j-1)*ldq), 1)
end if
c
20 continue
c
if (howmny .eq. 'A') then
c
c %--------------------------------------------%
c | Compute the NCONV wanted eigenvectors of T |
c | located in workl(iuptri,ldq). |
c %--------------------------------------------%
c
do 30 j=1, ncv
if (j .le. nconv) then
select(j) = .true.
else
select(j) = .false.
end if
30 continue
c
call ztrevc('Right', 'Select' , select ,
& ncv , workl(iuptri), ldq ,
& vl , 1 , workl(invsub),
& ldq , ncv , outncv ,
& workev , rwork , ierr)
c
if (ierr .ne. 0) then
info = -9
go to 9000
end if
c
c %------------------------------------------------%
c | Scale the returning eigenvectors so that their |
c | Euclidean norms are all one. LAPACK subroutine |
c | ztrevc returns each eigenvector normalized so |
c | that the element of largest magnitude has |
c | magnitude 1. |
c %------------------------------------------------%
c
do 40 j=1, nconv
rtemp = dznrm2(ncv, workl(invsub+(j-1)*ldq), 1)
rtemp = dble(one) / rtemp
call zdscal ( ncv, rtemp,
& workl(invsub+(j-1)*ldq), 1 )
c
c %------------------------------------------%
c | Ritz estimates can be obtained by taking |
c | the inner product of the last row of the |
c | Schur basis of H with eigenvectors of T. |
c | Note that the eigenvector matrix of T is |
c | upper triangular, thus the length of the |
c | inner product can be set to j. |
c %------------------------------------------%
c
workev(j) = zdotc(j, workl(ihbds), 1,
& workl(invsub+(j-1)*ldq), 1)
40 continue
c
if (msglvl .gt. 2) then
call zcopy(nconv, workl(invsub+ncv-1), ldq,
& workl(ihbds), 1)
call zvout (logfil, nconv, workl(ihbds), ndigit,
& '_neupd: Last row of the eigenvector matrix for T')
if (msglvl .gt. 3) then
call zmout(logfil , ncv, ncv ,
& workl(invsub), ldq, ndigit,
& '_neupd: The eigenvector matrix for T')
end if
end if
c
c %---------------------------------------%
c | Copy Ritz estimates into workl(ihbds) |
c %---------------------------------------%
c
call zcopy(nconv, workev, 1, workl(ihbds), 1)
c
c %----------------------------------------------%
c | The eigenvector matrix Q of T is triangular. |
c | Form Z*Q. |
c %----------------------------------------------%
c
call ztrmm('Right' , 'Upper' , 'No transpose',
& 'Non-unit', n , nconv ,
& one , workl(invsub), ldq ,
& z , ldz)
end if
c
else
c
c %--------------------------------------------------%
c | An approximate invariant subspace is not needed. |
c | Place the Ritz values computed ZNAUPD into D. |
c %--------------------------------------------------%
c
call zcopy(nconv, workl(ritz), 1, d, 1)
call zcopy(nconv, workl(ritz), 1, workl(iheig), 1)
call zcopy(nconv, workl(bounds), 1, workl(ihbds), 1)
c
end if
c
c %------------------------------------------------%
c | Transform the Ritz values and possibly vectors |
c | and corresponding error bounds of OP to those |
c | of A*x = lambda*B*x. |
c %------------------------------------------------%
c
if (type .eq. 'REGULR') then
c
if (rvec)
& call zscal(ncv, rnorm, workl(ihbds), 1)
c
else
c
c %---------------------------------------%
c | A spectral transformation was used. |
c | * Determine the Ritz estimates of the |
c | Ritz values in the original system. |
c %---------------------------------------%
c
if (rvec)
& call zscal(ncv, rnorm, workl(ihbds), 1)
c
do 50 k=1, ncv
temp = workl(iheig+k-1)
workl(ihbds+k-1) = workl(ihbds+k-1) / temp / temp
50 continue
c
end if
c
c %-----------------------------------------------------------%
c | * Transform the Ritz values back to the original system. |
c | For TYPE = 'SHIFTI' the transformation is |
c | lambda = 1/theta + sigma |
c | NOTES: |
c | *The Ritz vectors are not affected by the transformation. |
c %-----------------------------------------------------------%
c
if (type .eq. 'SHIFTI') then
do 60 k=1, nconv
d(k) = one / workl(iheig+k-1) + sigma
60 continue
end if
c
if (type .ne. 'REGULR' .and. msglvl .gt. 1) then
call zvout (logfil, nconv, d, ndigit,
& '_neupd: Untransformed Ritz values.')
call zvout (logfil, nconv, workl(ihbds), ndigit,
& '_neupd: Ritz estimates of the untransformed Ritz values.')
else if ( msglvl .gt. 1) then
call zvout (logfil, nconv, d, ndigit,
& '_neupd: Converged Ritz values.')
call zvout (logfil, nconv, workl(ihbds), ndigit,
& '_neupd: Associated Ritz estimates.')
end if
c
c %-------------------------------------------------%
c | Eigenvector Purification step. Formally perform |
c | one of inverse subspace iteration. Only used |
c | for MODE = 3. See reference 3. |
c %-------------------------------------------------%
c
if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then
c
c %------------------------------------------------%
c | Purify the computed Ritz vectors by adding a |
c | little bit of the residual vector: |
c | T |
c | resid(:)*( e s ) / theta |
c | NCV |
c | where H s = s theta. |
c %------------------------------------------------%
c
do 100 j=1, nconv
if (workl(iheig+j-1) .ne. zero) then
workev(j) = workl(invsub+(j-1)*ldq+ncv-1) /
& workl(iheig+j-1)
endif
100 continue
c %---------------------------------------%
c | Perform a rank one update to Z and |
c | purify all the Ritz vectors together. |
c %---------------------------------------%
c
call zgeru (n, nconv, one, resid, 1, workev, 1, z, ldz)
c
end if
c
9000 continue
c
return
c
c %---------------%
c | End of zneupd|
c %---------------%
c
end

178
arpack/ARPACK/SRC/zngets.f Normal file
View File

@@ -0,0 +1,178 @@
c\BeginDoc
c
c\Name: zngets
c
c\Description:
c Given the eigenvalues of the upper Hessenberg matrix H,
c computes the NP shifts AMU that are zeros of the polynomial of
c degree NP which filters out components of the unwanted eigenvectors
c corresponding to the AMU's based on some given criteria.
c
c NOTE: call this even in the case of user specified shifts in order
c to sort the eigenvalues, and error bounds of H for later use.
c
c\Usage:
c call zngets
c ( ISHIFT, WHICH, KEV, NP, RITZ, BOUNDS )
c
c\Arguments
c ISHIFT Integer. (INPUT)
c Method for selecting the implicit shifts at each iteration.
c ISHIFT = 0: user specified shifts
c ISHIFT = 1: exact shift with respect to the matrix H.
c
c WHICH Character*2. (INPUT)
c Shift selection criteria.
c 'LM' -> want the KEV eigenvalues of largest magnitude.
c 'SM' -> want the KEV eigenvalues of smallest magnitude.
c 'LR' -> want the KEV eigenvalues of largest REAL part.
c 'SR' -> want the KEV eigenvalues of smallest REAL part.
c 'LI' -> want the KEV eigenvalues of largest imaginary part.
c 'SI' -> want the KEV eigenvalues of smallest imaginary part.
c
c KEV Integer. (INPUT)
c The number of desired eigenvalues.
c
c NP Integer. (INPUT)
c The number of shifts to compute.
c
c RITZ Complex*16 array of length KEV+NP. (INPUT/OUTPUT)
c On INPUT, RITZ contains the the eigenvalues of H.
c On OUTPUT, RITZ are sorted so that the unwanted
c eigenvalues are in the first NP locations and the wanted
c portion is in the last KEV locations. When exact shifts are
c selected, the unwanted part corresponds to the shifts to
c be applied. Also, if ISHIFT .eq. 1, the unwanted eigenvalues
c are further sorted so that the ones with largest Ritz values
c are first.
c
c BOUNDS Complex*16 array of length KEV+NP. (INPUT/OUTPUT)
c Error bounds corresponding to the ordering in RITZ.
c
c
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Local variables:
c xxxxxx Complex*16
c
c\Routines called:
c zsortc ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c second ARPACK utility routine for timing.
c zvout ARPACK utility routine that prints vectors.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\SCCS Information: @(#)
c FILE: ngets.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2
c
c\Remarks
c 1. This routine does not keep complex conjugate pairs of
c eigenvalues together.
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine zngets ( ishift, which, kev, np, ritz, bounds)
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
integer ishift, kev, np
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Complex*16
& bounds(kev+np), ritz(kev+np)
c
c %------------%
c | Parameters |
c %------------%
c
Complex*16
& one, zero
parameter (one = (1.0D+0, 0.0D+0), zero = (0.0D+0, 0.0D+0))
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer msglvl
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external zvout, zsortc, second
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %-------------------------------%
c | Initialize timing statistics |
c | & message level for debugging |
c %-------------------------------%
c
call second (t0)
msglvl = mcgets
c
call zsortc (which, .true., kev+np, ritz, bounds)
c
if ( ishift .eq. 1 ) then
c
c %-------------------------------------------------------%
c | Sort the unwanted Ritz values used as shifts so that |
c | the ones with largest Ritz estimates are first |
c | This will tend to minimize the effects of the |
c | forward instability of the iteration when the shifts |
c | are applied in subroutine znapps. |
c | Be careful and use 'SM' since we want to sort BOUNDS! |
c %-------------------------------------------------------%
c
call zsortc ( 'SM', .true., np, bounds, ritz )
c
end if
c
call second (t1)
tcgets = tcgets + (t1 - t0)
c
if (msglvl .gt. 0) then
call ivout (logfil, 1, kev, ndigit, '_ngets: KEV is')
call ivout (logfil, 1, np, ndigit, '_ngets: NP is')
call zvout (logfil, kev+np, ritz, ndigit,
& '_ngets: Eigenvalues of current H matrix ')
call zvout (logfil, kev+np, bounds, ndigit,
& '_ngets: Ritz estimates of the current KEV+NP Ritz values')
end if
c
return
c
c %---------------%
c | End of zngets |
c %---------------%
c
end

322
arpack/ARPACK/SRC/zsortc.f Normal file
View File

@@ -0,0 +1,322 @@
c\BeginDoc
c
c\Name: zsortc
c
c\Description:
c Sorts the Complex*16 array in X into the order
c specified by WHICH and optionally applies the permutation to the
c Double precision array Y.
c
c\Usage:
c call zsortc
c ( WHICH, APPLY, N, X, Y )
c
c\Arguments
c WHICH Character*2. (Input)
c 'LM' -> sort X into increasing order of magnitude.
c 'SM' -> sort X into decreasing order of magnitude.
c 'LR' -> sort X with real(X) in increasing algebraic order
c 'SR' -> sort X with real(X) in decreasing algebraic order
c 'LI' -> sort X with imag(X) in increasing algebraic order
c 'SI' -> sort X with imag(X) in decreasing algebraic order
c
c APPLY Logical. (Input)
c APPLY = .TRUE. -> apply the sorted order to array Y.
c APPLY = .FALSE. -> do not apply the sorted order to array Y.
c
c N Integer. (INPUT)
c Size of the arrays.
c
c X Complex*16 array of length N. (INPUT/OUTPUT)
c This is the array to be sorted.
c
c Y Complex*16 array of length N. (INPUT/OUTPUT)
c
c\EndDoc
c
c-----------------------------------------------------------------------
c
c\BeginLib
c
c\Routines called:
c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
c
c\Author
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Dept. of Computational & Houston, Texas
c Applied Mathematics
c Rice University
c Houston, Texas
c
c Adapted from the sort routine in LANSO.
c
c\SCCS Information: @(#)
c FILE: sortc.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
c
subroutine zsortc (which, apply, n, x, y)
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character*2 which
logical apply
integer n
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
Complex*16
& x(0:n-1), y(0:n-1)
c
c %---------------%
c | Local Scalars |
c %---------------%
c
integer i, igap, j
Complex*16
& temp
Double precision
& temp1, temp2
c
c %--------------------%
c | External functions |
c %--------------------%
c
Double precision
& dlapy2
c
c %--------------------%
c | Intrinsic Functions |
c %--------------------%
Intrinsic
& dble, dimag
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
igap = n / 2
c
if (which .eq. 'LM') then
c
c %--------------------------------------------%
c | Sort X into increasing order of magnitude. |
c %--------------------------------------------%
c
10 continue
if (igap .eq. 0) go to 9000
c
do 30 i = igap, n-1
j = i-igap
20 continue
c
if (j.lt.0) go to 30
c
temp1 = dlapy2(dble(x(j)),dimag(x(j)))
temp2 = dlapy2(dble(x(j+igap)),dimag(x(j+igap)))
c
if (temp1.gt.temp2) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 30
end if
j = j-igap
go to 20
30 continue
igap = igap / 2
go to 10
c
else if (which .eq. 'SM') then
c
c %--------------------------------------------%
c | Sort X into decreasing order of magnitude. |
c %--------------------------------------------%
c
40 continue
if (igap .eq. 0) go to 9000
c
do 60 i = igap, n-1
j = i-igap
50 continue
c
if (j .lt. 0) go to 60
c
temp1 = dlapy2(dble(x(j)),dimag(x(j)))
temp2 = dlapy2(dble(x(j+igap)),dimag(x(j+igap)))
c
if (temp1.lt.temp2) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 60
endif
j = j-igap
go to 50
60 continue
igap = igap / 2
go to 40
c
else if (which .eq. 'LR') then
c
c %------------------------------------------------%
c | Sort XREAL into increasing order of algebraic. |
c %------------------------------------------------%
c
70 continue
if (igap .eq. 0) go to 9000
c
do 90 i = igap, n-1
j = i-igap
80 continue
c
if (j.lt.0) go to 90
c
if (dble(x(j)).gt.dble(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 90
endif
j = j-igap
go to 80
90 continue
igap = igap / 2
go to 70
c
else if (which .eq. 'SR') then
c
c %------------------------------------------------%
c | Sort XREAL into decreasing order of algebraic. |
c %------------------------------------------------%
c
100 continue
if (igap .eq. 0) go to 9000
do 120 i = igap, n-1
j = i-igap
110 continue
c
if (j.lt.0) go to 120
c
if (dble(x(j)).lt.dble(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 120
endif
j = j-igap
go to 110
120 continue
igap = igap / 2
go to 100
c
else if (which .eq. 'LI') then
c
c %--------------------------------------------%
c | Sort XIMAG into increasing algebraic order |
c %--------------------------------------------%
c
130 continue
if (igap .eq. 0) go to 9000
do 150 i = igap, n-1
j = i-igap
140 continue
c
if (j.lt.0) go to 150
c
if (dimag(x(j)).gt.dimag(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 150
endif
j = j-igap
go to 140
150 continue
igap = igap / 2
go to 130
c
else if (which .eq. 'SI') then
c
c %---------------------------------------------%
c | Sort XIMAG into decreasing algebraic order |
c %---------------------------------------------%
c
160 continue
if (igap .eq. 0) go to 9000
do 180 i = igap, n-1
j = i-igap
170 continue
c
if (j.lt.0) go to 180
c
if (dimag(x(j)).lt.dimag(x(j+igap))) then
temp = x(j)
x(j) = x(j+igap)
x(j+igap) = temp
c
if (apply) then
temp = y(j)
y(j) = y(j+igap)
y(j+igap) = temp
end if
else
go to 180
endif
j = j-igap
go to 170
180 continue
igap = igap / 2
go to 160
end if
c
9000 continue
return
c
c %---------------%
c | End of zsortc |
c %---------------%
c
end

View File

@@ -0,0 +1,51 @@
c
c\SCCS Information: @(#)
c FILE: statn.F SID: 2.2 DATE OF SID: 4/20/96 RELEASE: 2
c
c %---------------------------------------------%
c | Initialize statistic and timing information |
c | for complex nonsymmetric Arnoldi code. |
c %---------------------------------------------%
subroutine zstatn
c
c %--------------------------------%
c | See stat.doc for documentation |
c %--------------------------------%
c
include 'stat.h'
c %-----------------------%
c | Executable Statements |
c %-----------------------%
nopx = 0
nbx = 0
nrorth = 0
nitref = 0
nrstrt = 0
tcaupd = 0.0D+0
tcaup2 = 0.0D+0
tcaitr = 0.0D+0
tceigh = 0.0D+0
tcgets = 0.0D+0
tcapps = 0.0D+0
tcconv = 0.0D+0
titref = 0.0D+0
tgetv0 = 0.0D+0
trvec = 0.0D+0
c %----------------------------------------------------%
c | User time including reverse communication overhead |
c %----------------------------------------------------%
tmvopx = 0.0D+0
tmvbx = 0.0D+0
return
c
c %---------------%
c | End of zstatn |
c %---------------%
c
end

View File

@@ -0,0 +1,82 @@
############################################################################
#
# Program: ARPACK
#
# Module: Makefile
#
# Purpose: Sources Makefile
#
# Creation date: February 22, 1996
#
# Modified: September 6, 1996
#
# Send bug reports, comments or suggestions to arpack.caam.rice.edu
#
############################################################################
#\SCCS Information: @(#)
# FILE: Makefile SID: 2.1 DATE OF SID: 9/9/96 RELEASE: 2
include ../ARmake.inc
############################################################################
# To create or add to the library, enter make followed by one or
# more of the precisions desired. Some examples:
# make single
# make single complex
# make single double complex complex16
# Alternatively, the command
# make
# without any arguments creates a library of all four precisions.
# The name of the library is defined by $(ARPACKLIB) in
# ../ARmake.inc and is created at the next higher directory level.
#
OBJS = icnteq.o icopy.o iset.o iswap.o ivout.o second.o
SOBJ = svout.o smout.o
DOBJ = dvout.o dmout.o
COBJ = cvout.o cmout.o
ZOBJ = zvout.o zmout.o
.SUFFIXES: .o .F .f
.f.o:
$(FC) $(FFLAGS) -c $<
#
# make the library containing both single and double precision
#
all: single double complex complex16
single: $(SOBJ) $(OBJS)
$(AR) $(ARFLAGS) $(ARPACKLIB) $(SOBJ) $(OBJS)
$(RANLIB) $(ARPACKLIB)
double: $(DOBJ) $(OBJS) $(ZOBJ)
$(AR) $(ARFLAGS) $(ARPACKLIB) $(DOBJ) $(OBJS)
$(RANLIB) $(ARPACKLIB)
complex: $(SOBJ) $(OBJS) $(COBJ)
$(AR) $(ARFLAGS) $(ARPACKLIB) $(SOBJ) $(COBJ) $(OBJS)
$(RANLIB) $(ARPACKLIB)
complex16: $(DOBJ) $(OBJS) $(ZOBJ)
$(AR) $(ARFLAGS) $(ARPACKLIB) $(DOBJ) $(ZOBJ) $(OBJS)
$(RANLIB) $(ARPACKLIB)
#
sdrv:
ddrv:
cdrv:
zdrv:
#
# clean - remove all object files
#
clean:
rm -f *.o a.out core

250
arpack/ARPACK/UTIL/cmout.f Normal file
View File

@@ -0,0 +1,250 @@
*
* Routine: CMOUT
*
* Purpose: Complex matrix output routine.
*
* Usage: CALL CMOUT (LOUT, M, N, A, LDA, IDIGIT, IFMT)
*
* Arguments
* M - Number of rows of A. (Input)
* N - Number of columns of A. (Input)
* A - Complex M by N matrix to be printed. (Input)
* LDA - Leading dimension of A exactly as specified in the
* dimension statement of the calling program. (Input)
* IFMT - Format to be used in printing matrix A. (Input)
* IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In)
* If IDIGIT .LT. 0, printing is done with 72 columns.
* If IDIGIT .GT. 0, printing is done with 132 columns.
*
*\SCCS Information: @(#)
* FILE: cmout.f SID: 2.1 DATE OF SID: 11/16/95 RELEASE: 2
*
*-----------------------------------------------------------------------
*
SUBROUTINE CMOUT( LOUT, M, N, A, LDA, IDIGIT, IFMT )
* ...
* ... SPECIFICATIONS FOR ARGUMENTS
INTEGER M, N, IDIGIT, LDA, LOUT
Complex
& A( LDA, * )
CHARACTER IFMT*( * )
* ...
* ... SPECIFICATIONS FOR LOCAL VARIABLES
INTEGER I, J, NDIGIT, K1, K2, LLL
CHARACTER*1 ICOL( 3 )
CHARACTER*80 LINE
* ...
* ... SPECIFICATIONS INTRINSICS
INTRINSIC MIN
*
DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o',
$ 'l' /
* ...
* ... FIRST EXECUTABLE STATEMENT
*
LLL = MIN( LEN( IFMT ), 80 )
DO 10 I = 1, LLL
LINE( I: I ) = '-'
10 CONTINUE
*
DO 20 I = LLL + 1, 80
LINE( I: I ) = ' '
20 CONTINUE
*
WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL )
9999 FORMAT( / 1X, A / 1X, A )
*
IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 )
$ RETURN
NDIGIT = IDIGIT
IF( IDIGIT.EQ.0 )
$ NDIGIT = 4
*
*=======================================================================
* CODE FOR OUTPUT USING 72 COLUMNS FORMAT
*=======================================================================
*
IF( IDIGIT.LT.0 ) THEN
NDIGIT = -IDIGIT
IF( NDIGIT.LE.4 ) THEN
DO 40 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 )
DO 30 I = 1, M
IF (K1.NE.N) THEN
WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 )
ELSE
WRITE( LOUT, 9984 )I, ( A( I, J ), J = K1, K2 )
END IF
30 CONTINUE
40 CONTINUE
*
ELSE IF( NDIGIT.LE.6 ) THEN
DO 60 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 )
DO 50 I = 1, M
IF (K1.NE.N) THEN
WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 )
ELSE
WRITE( LOUT, 9983 )I, ( A( I, J ), J = K1, K2 )
END IF
50 CONTINUE
60 CONTINUE
*
ELSE IF( NDIGIT.LE.8 ) THEN
DO 80 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 )
DO 70 I = 1, M
IF (K1.NE.N) THEN
WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 )
ELSE
WRITE( LOUT, 9982 )I, ( A( I, J ), J = K1, K2 )
END IF
70 CONTINUE
80 CONTINUE
*
ELSE
DO 100 K1 = 1, N
WRITE( LOUT, 9995 ) ICOL, K1
DO 90 I = 1, M
WRITE( LOUT, 9991 )I, A( I, K1 )
90 CONTINUE
100 CONTINUE
END IF
*
*=======================================================================
* CODE FOR OUTPUT USING 132 COLUMNS FORMAT
*=======================================================================
*
ELSE
IF( NDIGIT.LE.4 ) THEN
DO 120 K1 = 1, N, 4
K2 = MIN0( N, K1+3 )
WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 )
DO 110 I = 1, M
IF ((K1+3).LE.N) THEN
WRITE( LOUT, 9974 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+3-N).EQ.1) THEN
WRITE( LOUT, 9964 )I, ( A( I, J ), J = k1, K2 )
ELSE IF ((K1+3-N).EQ.2) THEN
WRITE( LOUT, 9954 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+3-N).EQ.3) THEN
WRITE( LOUT, 9944 )I, ( A( I, J ), J = K1, K2 )
END IF
110 CONTINUE
120 CONTINUE
*
ELSE IF( NDIGIT.LE.6 ) THEN
DO 140 K1 = 1, N, 3
K2 = MIN0( N, K1+ 2)
WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 )
DO 130 I = 1, M
IF ((K1+2).LE.N) THEN
WRITE( LOUT, 9973 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+2-N).EQ.1) THEN
WRITE( LOUT, 9963 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+2-N).EQ.2) THEN
WRITE( LOUT, 9953 )I, ( A( I, J ), J = K1, K2 )
END IF
130 CONTINUE
140 CONTINUE
*
ELSE IF( NDIGIT.LE.8 ) THEN
DO 160 K1 = 1, N, 3
K2 = MIN0( N, K1+2 )
WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 )
DO 150 I = 1, M
IF ((K1+2).LE.N) THEN
WRITE( LOUT, 9972 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+2-N).EQ.1) THEN
WRITE( LOUT, 9962 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+2-N).EQ.2) THEN
WRITE( LOUT, 9952 )I, ( A( I, J ), J = K1, K2 )
END IF
150 CONTINUE
160 CONTINUE
*
ELSE
DO 180 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 )
DO 170 I = 1, M
IF ((K1+1).LE.N) THEN
WRITE( LOUT, 9971 )I, ( A( I, J ), J = K1, K2 )
ELSE
WRITE( LOUT, 9961 )I, ( A( I, J ), J = K1, K2 )
END IF
170 CONTINUE
180 CONTINUE
END IF
END IF
WRITE( LOUT, 9990 )
*
9998 FORMAT( 11X, 4( 9X, 3A1, I4, 9X ) )
9997 FORMAT( 10X, 4( 11X, 3A1, I4, 11X ) )
9996 FORMAT( 10X, 3( 13X, 3A1, I4, 13X ) )
9995 FORMAT( 12X, 2( 18x, 3A1, I4, 18X ) )
*
*========================================================
* FORMAT FOR 72 COLUMN
*========================================================
*
* DISPLAY 4 SIGNIFICANT DIGITS
*
9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E10.3,',',E10.3,') ') )
9984 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E10.3,',',E10.3,') ') )
*
* DISPLAY 6 SIGNIFICANT DIGITS
*
9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E12.5,',',E12.5,') ') )
9983 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E12.5,',',E12.5,') ') )
*
* DISPLAY 8 SIGNIFICANT DIGITS
*
9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E14.7,',',E14.7,') ') )
9982 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E14.7,',',E14.7,') ') )
*
* DISPLAY 13 SIGNIFICANT DIGITS
*
9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E20.13,',',E20.13,')') )
9990 FORMAT( 1X, ' ' )
*
*
*========================================================
* FORMAT FOR 132 COLUMN
*========================================================
*
* DISPLAY 4 SIGNIFICANT DIGIT
*
9974 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,4('(',E10.3,',',E10.3,') ') )
9964 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E10.3,',',E10.3,') ') )
9954 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E10.3,',',E10.3,') ') )
9944 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E10.3,',',E10.3,') ') )
*
* DISPLAY 6 SIGNIFICANT DIGIT
*
9973 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E12.5,',',E12.5,') ') )
9963 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E12.5,',',E12.5,') ') )
9953 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E12.5,',',E12.5,') ') )
*
* DISPLAY 8 SIGNIFICANT DIGIT
*
9972 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',E14.7,',',E14.7,') ') )
9962 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E14.7,',',E14.7,') ') )
9952 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E14.7,',',E14.7,') ') )
*
* DISPLAY 13 SIGNIFICANT DIGIT
*
9971 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',E20.13,',',E20.13,
& ') '))
9961 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',E20.13,',',E20.13,
& ') '))
*
*
*
*
RETURN
END

240
arpack/ARPACK/UTIL/cvout.f Normal file
View File

@@ -0,0 +1,240 @@
c-----------------------------------------------------------------------
c
c\SCCS Information: @(#)
c FILE: cvout.f SID: 2.1 DATE OF SID: 11/16/95 RELEASE: 2
c
*-----------------------------------------------------------------------
* Routine: CVOUT
*
* Purpose: Complex vector output routine.
*
* Usage: CALL CVOUT (LOUT, N, CX, IDIGIT, IFMT)
*
* Arguments
* N - Length of array CX. (Input)
* CX - Complex array to be printed. (Input)
* IFMT - Format to be used in printing array CX. (Input)
* IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In)
* If IDIGIT .LT. 0, printing is done with 72 columns.
* If IDIGIT .GT. 0, printing is done with 132 columns.
*
*-----------------------------------------------------------------------
*
SUBROUTINE CVOUT( LOUT, N, CX, IDIGIT, IFMT )
* ...
* ... SPECIFICATIONS FOR ARGUMENTS
INTEGER N, IDIGIT, LOUT
Complex
& CX( * )
CHARACTER IFMT*( * )
* ...
* ... SPECIFICATIONS FOR LOCAL VARIABLES
INTEGER I, NDIGIT, K1, K2, LLL
CHARACTER*80 LINE
* ...
* ... FIRST EXECUTABLE STATEMENT
*
*
LLL = MIN( LEN( IFMT ), 80 )
DO 10 I = 1, LLL
LINE( I: I ) = '-'
10 CONTINUE
*
DO 20 I = LLL + 1, 80
LINE( I: I ) = ' '
20 CONTINUE
*
WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL )
9999 FORMAT( / 1X, A / 1X, A )
*
IF( N.LE.0 )
$ RETURN
NDIGIT = IDIGIT
IF( IDIGIT.EQ.0 )
$ NDIGIT = 4
*
*=======================================================================
* CODE FOR OUTPUT USING 72 COLUMNS FORMAT
*=======================================================================
*
IF( IDIGIT.LT.0 ) THEN
NDIGIT = -IDIGIT
IF( NDIGIT.LE.4 ) THEN
DO 30 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
IF (K1.NE.N) THEN
WRITE( LOUT, 9998 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE
WRITE( LOUT, 9997 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
30 CONTINUE
ELSE IF( NDIGIT.LE.6 ) THEN
DO 40 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
IF (K1.NE.N) THEN
WRITE( LOUT, 9988 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE
WRITE( LOUT, 9987 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
40 CONTINUE
ELSE IF( NDIGIT.LE.8 ) THEN
DO 50 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
IF (K1.NE.N) THEN
WRITE( LOUT, 9978 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE
WRITE( LOUT, 9977 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
50 CONTINUE
ELSE
DO 60 K1 = 1, N
WRITE( LOUT, 9968 )K1, K1, CX( I )
60 CONTINUE
END IF
*
*=======================================================================
* CODE FOR OUTPUT USING 132 COLUMNS FORMAT
*=======================================================================
*
ELSE
IF( NDIGIT.LE.4 ) THEN
DO 70 K1 = 1, N, 4
K2 = MIN0( N, K1+3 )
IF ((K1+3).LE.N) THEN
WRITE( LOUT, 9958 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+3-N) .EQ. 1) THEN
WRITE( LOUT, 9957 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+3-N) .EQ. 2) THEN
WRITE( LOUT, 9956 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+3-N) .EQ. 1) THEN
WRITE( LOUT, 9955 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
70 CONTINUE
ELSE IF( NDIGIT.LE.6 ) THEN
DO 80 K1 = 1, N, 3
K2 = MIN0( N, K1+2 )
IF ((K1+2).LE.N) THEN
WRITE( LOUT, 9948 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+2-N) .EQ. 1) THEN
WRITE( LOUT, 9947 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+2-N) .EQ. 2) THEN
WRITE( LOUT, 9946 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
80 CONTINUE
ELSE IF( NDIGIT.LE.8 ) THEN
DO 90 K1 = 1, N, 3
K2 = MIN0( N, K1+2 )
IF ((K1+2).LE.N) THEN
WRITE( LOUT, 9938 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+2-N) .EQ. 1) THEN
WRITE( LOUT, 9937 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+2-N) .EQ. 2) THEN
WRITE( LOUT, 9936 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
90 CONTINUE
ELSE
DO 100 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
IF ((K1+2).LE.N) THEN
WRITE( LOUT, 9928 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+2-N) .EQ. 1) THEN
WRITE( LOUT, 9927 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
100 CONTINUE
END IF
END IF
WRITE( LOUT, 9994 )
RETURN
*
*=======================================================================
* FORMAT FOR 72 COLUMNS
*=======================================================================
*
* DISPLAY 4 SIGNIFICANT DIGITS
*
9998 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',E10.3,',',E10.3,') ') )
9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',E10.3,',',E10.3,') ') )
*
* DISPLAY 6 SIGNIFICANT DIGITS
*
9988 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',E12.5,',',E12.5,') ') )
9987 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',E12.5,',',E12.5,') ') )
*
* DISPLAY 8 SIGNIFICANT DIGITS
*
9978 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',E14.7,',',E14.7,') ') )
9977 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',E14.7,',',E14.7,') ') )
*
* DISPLAY 13 SIGNIFICANT DIGITS
*
9968 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',E20.13,',',E20.13,') ') )
*
*=========================================================================
* FORMAT FOR 132 COLUMNS
*=========================================================================
*
* DISPLAY 4 SIGNIFICANT DIGITS
*
9958 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,4('(',E10.3,',',E10.3,') ') )
9957 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,3('(',E10.3,',',E10.3,') ') )
9956 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',E10.3,',',E10.3,') ') )
9955 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',E10.3,',',E10.3,') ') )
*
* DISPLAY 6 SIGNIFICANT DIGITS
*
9948 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,3('(',E12.5,',',E12.5,') ') )
9947 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',E12.5,',',E12.5,') ') )
9946 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',E12.5,',',E12.5,') ') )
*
* DISPLAY 8 SIGNIFICANT DIGITS
*
9938 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,3('(',E14.7,',',E14.7,') ') )
9937 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',E14.7,',',E14.7,') ') )
9936 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',E14.7,',',E14.7,') ') )
*
* DISPLAY 13 SIGNIFICANT DIGITS
*
9928 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',E20.13,',',E20.13,') ') )
9927 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',E20.13,',',E20.13,') ') )
*
*
*
9994 FORMAT( 1X, ' ' )
END

167
arpack/ARPACK/UTIL/dmout.f Normal file
View File

@@ -0,0 +1,167 @@
*-----------------------------------------------------------------------
* Routine: DMOUT
*
* Purpose: Real matrix output routine.
*
* Usage: CALL DMOUT (LOUT, M, N, A, LDA, IDIGIT, IFMT)
*
* Arguments
* M - Number of rows of A. (Input)
* N - Number of columns of A. (Input)
* A - Real M by N matrix to be printed. (Input)
* LDA - Leading dimension of A exactly as specified in the
* dimension statement of the calling program. (Input)
* IFMT - Format to be used in printing matrix A. (Input)
* IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In)
* If IDIGIT .LT. 0, printing is done with 72 columns.
* If IDIGIT .GT. 0, printing is done with 132 columns.
*
*-----------------------------------------------------------------------
*
SUBROUTINE DMOUT( LOUT, M, N, A, LDA, IDIGIT, IFMT )
* ...
* ... SPECIFICATIONS FOR ARGUMENTS
* ...
* ... SPECIFICATIONS FOR LOCAL VARIABLES
* .. Scalar Arguments ..
CHARACTER*( * ) IFMT
INTEGER IDIGIT, LDA, LOUT, M, N
* ..
* .. Array Arguments ..
DOUBLE PRECISION A( LDA, * )
* ..
* .. Local Scalars ..
CHARACTER*80 LINE
INTEGER I, J, K1, K2, LLL, NDIGIT
* ..
* .. Local Arrays ..
CHARACTER ICOL( 3 )
* ..
* .. Intrinsic Functions ..
INTRINSIC LEN, MIN, MIN0
* ..
* .. Data statements ..
DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o',
$ 'l' /
* ..
* .. Executable Statements ..
* ...
* ... FIRST EXECUTABLE STATEMENT
*
LLL = MIN( LEN( IFMT ), 80 )
DO 10 I = 1, LLL
LINE( I: I ) = '-'
10 CONTINUE
*
DO 20 I = LLL + 1, 80
LINE( I: I ) = ' '
20 CONTINUE
*
WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL )
9999 FORMAT( / 1X, A, / 1X, A )
*
IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 )
$ RETURN
NDIGIT = IDIGIT
IF( IDIGIT.EQ.0 )
$ NDIGIT = 4
*
*=======================================================================
* CODE FOR OUTPUT USING 72 COLUMNS FORMAT
*=======================================================================
*
IF( IDIGIT.LT.0 ) THEN
NDIGIT = -IDIGIT
IF( NDIGIT.LE.4 ) THEN
DO 40 K1 = 1, N, 5
K2 = MIN0( N, K1+4 )
WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 )
DO 30 I = 1, M
WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 )
30 CONTINUE
40 CONTINUE
*
ELSE IF( NDIGIT.LE.6 ) THEN
DO 60 K1 = 1, N, 4
K2 = MIN0( N, K1+3 )
WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 )
DO 50 I = 1, M
WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 )
50 CONTINUE
60 CONTINUE
*
ELSE IF( NDIGIT.LE.10 ) THEN
DO 80 K1 = 1, N, 3
K2 = MIN0( N, K1+2 )
WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 )
DO 70 I = 1, M
WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 )
70 CONTINUE
80 CONTINUE
*
ELSE
DO 100 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 )
DO 90 I = 1, M
WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 )
90 CONTINUE
100 CONTINUE
END IF
*
*=======================================================================
* CODE FOR OUTPUT USING 132 COLUMNS FORMAT
*=======================================================================
*
ELSE
IF( NDIGIT.LE.4 ) THEN
DO 120 K1 = 1, N, 10
K2 = MIN0( N, K1+9 )
WRITE( LOUT, FMT = 9998 )( ICOL, I, I = K1, K2 )
DO 110 I = 1, M
WRITE( LOUT, FMT = 9994 )I, ( A( I, J ), J = K1, K2 )
110 CONTINUE
120 CONTINUE
*
ELSE IF( NDIGIT.LE.6 ) THEN
DO 140 K1 = 1, N, 8
K2 = MIN0( N, K1+7 )
WRITE( LOUT, FMT = 9997 )( ICOL, I, I = K1, K2 )
DO 130 I = 1, M
WRITE( LOUT, FMT = 9993 )I, ( A( I, J ), J = K1, K2 )
130 CONTINUE
140 CONTINUE
*
ELSE IF( NDIGIT.LE.10 ) THEN
DO 160 K1 = 1, N, 6
K2 = MIN0( N, K1+5 )
WRITE( LOUT, FMT = 9996 )( ICOL, I, I = K1, K2 )
DO 150 I = 1, M
WRITE( LOUT, FMT = 9992 )I, ( A( I, J ), J = K1, K2 )
150 CONTINUE
160 CONTINUE
*
ELSE
DO 180 K1 = 1, N, 5
K2 = MIN0( N, K1+4 )
WRITE( LOUT, FMT = 9995 )( ICOL, I, I = K1, K2 )
DO 170 I = 1, M
WRITE( LOUT, FMT = 9991 )I, ( A( I, J ), J = K1, K2 )
170 CONTINUE
180 CONTINUE
END IF
END IF
WRITE( LOUT, FMT = 9990 )
*
9998 FORMAT( 10X, 10( 4X, 3A1, I4, 1X ) )
9997 FORMAT( 10X, 8( 5X, 3A1, I4, 2X ) )
9996 FORMAT( 10X, 6( 7X, 3A1, I4, 4X ) )
9995 FORMAT( 10X, 5( 9X, 3A1, I4, 6X ) )
9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 10D12.3 )
9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 8D14.5 )
9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 6D18.9 )
9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P, 5D22.13 )
9990 FORMAT( 1X, ' ' )
*
RETURN
END

122
arpack/ARPACK/UTIL/dvout.f Normal file
View File

@@ -0,0 +1,122 @@
*-----------------------------------------------------------------------
* Routine: DVOUT
*
* Purpose: Real vector output routine.
*
* Usage: CALL DVOUT (LOUT, N, SX, IDIGIT, IFMT)
*
* Arguments
* N - Length of array SX. (Input)
* SX - Real array to be printed. (Input)
* IFMT - Format to be used in printing array SX. (Input)
* IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In)
* If IDIGIT .LT. 0, printing is done with 72 columns.
* If IDIGIT .GT. 0, printing is done with 132 columns.
*
*-----------------------------------------------------------------------
*
SUBROUTINE DVOUT( LOUT, N, SX, IDIGIT, IFMT )
* ...
* ... SPECIFICATIONS FOR ARGUMENTS
* ...
* ... SPECIFICATIONS FOR LOCAL VARIABLES
* .. Scalar Arguments ..
CHARACTER*( * ) IFMT
INTEGER IDIGIT, LOUT, N
* ..
* .. Array Arguments ..
DOUBLE PRECISION SX( * )
* ..
* .. Local Scalars ..
CHARACTER*80 LINE
INTEGER I, K1, K2, LLL, NDIGIT
* ..
* .. Intrinsic Functions ..
INTRINSIC LEN, MIN, MIN0
* ..
* .. Executable Statements ..
* ...
* ... FIRST EXECUTABLE STATEMENT
*
*
LLL = MIN( LEN( IFMT ), 80 )
DO 10 I = 1, LLL
LINE( I: I ) = '-'
10 CONTINUE
*
DO 20 I = LLL + 1, 80
LINE( I: I ) = ' '
20 CONTINUE
*
WRITE( LOUT, FMT = 9999 )IFMT, LINE( 1: LLL )
9999 FORMAT( / 1X, A, / 1X, A )
*
IF( N.LE.0 )
$ RETURN
NDIGIT = IDIGIT
IF( IDIGIT.EQ.0 )
$ NDIGIT = 4
*
*=======================================================================
* CODE FOR OUTPUT USING 72 COLUMNS FORMAT
*=======================================================================
*
IF( IDIGIT.LT.0 ) THEN
NDIGIT = -IDIGIT
IF( NDIGIT.LE.4 ) THEN
DO 30 K1 = 1, N, 5
K2 = MIN0( N, K1+4 )
WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 )
30 CONTINUE
ELSE IF( NDIGIT.LE.6 ) THEN
DO 40 K1 = 1, N, 4
K2 = MIN0( N, K1+3 )
WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 )
40 CONTINUE
ELSE IF( NDIGIT.LE.10 ) THEN
DO 50 K1 = 1, N, 3
K2 = MIN0( N, K1+2 )
WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 )
50 CONTINUE
ELSE
DO 60 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 )
60 CONTINUE
END IF
*
*=======================================================================
* CODE FOR OUTPUT USING 132 COLUMNS FORMAT
*=======================================================================
*
ELSE
IF( NDIGIT.LE.4 ) THEN
DO 70 K1 = 1, N, 10
K2 = MIN0( N, K1+9 )
WRITE( LOUT, FMT = 9998 )K1, K2, ( SX( I ), I = K1, K2 )
70 CONTINUE
ELSE IF( NDIGIT.LE.6 ) THEN
DO 80 K1 = 1, N, 8
K2 = MIN0( N, K1+7 )
WRITE( LOUT, FMT = 9997 )K1, K2, ( SX( I ), I = K1, K2 )
80 CONTINUE
ELSE IF( NDIGIT.LE.10 ) THEN
DO 90 K1 = 1, N, 6
K2 = MIN0( N, K1+5 )
WRITE( LOUT, FMT = 9996 )K1, K2, ( SX( I ), I = K1, K2 )
90 CONTINUE
ELSE
DO 100 K1 = 1, N, 5
K2 = MIN0( N, K1+4 )
WRITE( LOUT, FMT = 9995 )K1, K2, ( SX( I ), I = K1, K2 )
100 CONTINUE
END IF
END IF
WRITE( LOUT, FMT = 9994 )
RETURN
9998 FORMAT( 1X, I4, ' - ', I4, ':', 1P, 10D12.3 )
9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 8D14.5 )
9996 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 6D18.9 )
9995 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P, 5D24.13 )
9994 FORMAT( 1X, ' ' )
END

View File

@@ -0,0 +1,18 @@
c
c-----------------------------------------------------------------------
c
c Count the number of elements equal to a specified integer value.
c
integer function icnteq (n, array, value)
c
integer n, value
integer array(*)
c
k = 0
do 10 i = 1, n
if (array(i) .eq. value) k = k + 1
10 continue
icnteq = k
c
return
end

View File

@@ -0,0 +1,77 @@
*--------------------------------------------------------------------
*\Documentation
*
*\Name: ICOPY
*
*\Description:
* ICOPY copies an integer vector lx to an integer vector ly.
*
*\Usage:
* call icopy ( n, lx, inc, ly, incy )
*
*\Arguments:
* n integer (input)
* On entry, n is the number of elements of lx to be
c copied to ly.
*
* lx integer array (input)
* On entry, lx is the integer vector to be copied.
*
* incx integer (input)
* On entry, incx is the increment between elements of lx.
*
* ly integer array (input)
* On exit, ly is the integer vector that contains the
* copy of lx.
*
* incy integer (input)
* On entry, incy is the increment between elements of ly.
*
*\Enddoc
*
*--------------------------------------------------------------------
*
subroutine icopy( n, lx, incx, ly, incy )
*
* ----------------------------
* Specifications for arguments
* ----------------------------
integer incx, incy, n
integer lx( 1 ), ly( 1 )
*
* ----------------------------------
* Specifications for local variables
* ----------------------------------
integer i, ix, iy
*
* --------------------------
* First executable statement
* --------------------------
if( n.le.0 )
$ return
if( incx.eq.1 .and. incy.eq.1 )
$ go to 20
c
c.....code for unequal increments or equal increments
c not equal to 1
ix = 1
iy = 1
if( incx.lt.0 )
$ ix = ( -n+1 )*incx + 1
if( incy.lt.0 )
$ iy = ( -n+1 )*incy + 1
do 10 i = 1, n
ly( iy ) = lx( ix )
ix = ix + incx
iy = iy + incy
10 continue
return
c
c.....code for both increments equal to 1
c
20 continue
do 30 i = 1, n
ly( i ) = lx( i )
30 continue
return
end

16
arpack/ARPACK/UTIL/iset.f Normal file
View File

@@ -0,0 +1,16 @@
c
c-----------------------------------------------------------------------
c
c Only work with increment equal to 1 right now.
c
subroutine iset (n, value, array, inc)
c
integer n, value, inc
integer array(*)
c
do 10 i = 1, n
array(i) = value
10 continue
c
return
end

View File

@@ -0,0 +1,55 @@
subroutine iswap (n,sx,incx,sy,incy)
c
c interchanges two vectors.
c uses unrolled loops for increments equal to 1.
c jack dongarra, linpack, 3/11/78.
c
integer sx(1),sy(1),stemp
integer i,incx,incy,ix,iy,m,mp1,n
c
if(n.le.0)return
if(incx.eq.1.and.incy.eq.1)go to 20
c
c code for unequal increments or equal increments not equal
c to 1
c
ix = 1
iy = 1
if(incx.lt.0)ix = (-n+1)*incx + 1
if(incy.lt.0)iy = (-n+1)*incy + 1
do 10 i = 1,n
stemp = sx(ix)
sx(ix) = sy(iy)
sy(iy) = stemp
ix = ix + incx
iy = iy + incy
10 continue
return
c
c code for both increments equal to 1
c
c
c clean-up loop
c
20 m = mod(n,3)
if( m .eq. 0 ) go to 40
do 30 i = 1,m
stemp = sx(i)
sx(i) = sy(i)
sy(i) = stemp
30 continue
if( n .lt. 3 ) return
40 mp1 = m + 1
do 50 i = mp1,n,3
stemp = sx(i)
sx(i) = sy(i)
sy(i) = stemp
stemp = sx(i + 1)
sx(i + 1) = sy(i + 1)
sy(i + 1) = stemp
stemp = sx(i + 2)
sx(i + 2) = sy(i + 2)
sy(i + 2) = stemp
50 continue
return
end

120
arpack/ARPACK/UTIL/ivout.f Normal file
View File

@@ -0,0 +1,120 @@
C-----------------------------------------------------------------------
C Routine: IVOUT
C
C Purpose: Integer vector output routine.
C
C Usage: CALL IVOUT (LOUT, N, IX, IDIGIT, IFMT)
C
C Arguments
C N - Length of array IX. (Input)
C IX - Integer array to be printed. (Input)
C IFMT - Format to be used in printing array IX. (Input)
C IDIGIT - Print up to ABS(IDIGIT) decimal digits / number. (Input)
C If IDIGIT .LT. 0, printing is done with 72 columns.
C If IDIGIT .GT. 0, printing is done with 132 columns.
C
C-----------------------------------------------------------------------
C
SUBROUTINE IVOUT (LOUT, N, IX, IDIGIT, IFMT)
C ...
C ... SPECIFICATIONS FOR ARGUMENTS
INTEGER IX(*), N, IDIGIT, LOUT
CHARACTER IFMT*(*)
C ...
C ... SPECIFICATIONS FOR LOCAL VARIABLES
INTEGER I, NDIGIT, K1, K2, LLL
CHARACTER*80 LINE
* ...
* ... SPECIFICATIONS INTRINSICS
INTRINSIC MIN
*
C
LLL = MIN ( LEN ( IFMT ), 80 )
DO 1 I = 1, LLL
LINE(I:I) = '-'
1 CONTINUE
C
DO 2 I = LLL+1, 80
LINE(I:I) = ' '
2 CONTINUE
C
WRITE ( LOUT, 2000 ) IFMT, LINE(1:LLL)
2000 FORMAT ( /1X, A /1X, A )
C
IF (N .LE. 0) RETURN
NDIGIT = IDIGIT
IF (IDIGIT .EQ. 0) NDIGIT = 4
C
C=======================================================================
C CODE FOR OUTPUT USING 72 COLUMNS FORMAT
C=======================================================================
C
IF (IDIGIT .LT. 0) THEN
C
NDIGIT = -IDIGIT
IF (NDIGIT .LE. 4) THEN
DO 10 K1 = 1, N, 10
K2 = MIN0(N,K1+9)
WRITE(LOUT,1000) K1,K2,(IX(I),I=K1,K2)
10 CONTINUE
C
ELSE IF (NDIGIT .LE. 6) THEN
DO 30 K1 = 1, N, 7
K2 = MIN0(N,K1+6)
WRITE(LOUT,1001) K1,K2,(IX(I),I=K1,K2)
30 CONTINUE
C
ELSE IF (NDIGIT .LE. 10) THEN
DO 50 K1 = 1, N, 5
K2 = MIN0(N,K1+4)
WRITE(LOUT,1002) K1,K2,(IX(I),I=K1,K2)
50 CONTINUE
C
ELSE
DO 70 K1 = 1, N, 3
K2 = MIN0(N,K1+2)
WRITE(LOUT,1003) K1,K2,(IX(I),I=K1,K2)
70 CONTINUE
END IF
C
C=======================================================================
C CODE FOR OUTPUT USING 132 COLUMNS FORMAT
C=======================================================================
C
ELSE
C
IF (NDIGIT .LE. 4) THEN
DO 90 K1 = 1, N, 20
K2 = MIN0(N,K1+19)
WRITE(LOUT,1000) K1,K2,(IX(I),I=K1,K2)
90 CONTINUE
C
ELSE IF (NDIGIT .LE. 6) THEN
DO 110 K1 = 1, N, 15
K2 = MIN0(N,K1+14)
WRITE(LOUT,1001) K1,K2,(IX(I),I=K1,K2)
110 CONTINUE
C
ELSE IF (NDIGIT .LE. 10) THEN
DO 130 K1 = 1, N, 10
K2 = MIN0(N,K1+9)
WRITE(LOUT,1002) K1,K2,(IX(I),I=K1,K2)
130 CONTINUE
C
ELSE
DO 150 K1 = 1, N, 7
K2 = MIN0(N,K1+6)
WRITE(LOUT,1003) K1,K2,(IX(I),I=K1,K2)
150 CONTINUE
END IF
END IF
WRITE (LOUT,1004)
C
1000 FORMAT(1X,I4,' - ',I4,':',20(1X,I5))
1001 FORMAT(1X,I4,' - ',I4,':',15(1X,I7))
1002 FORMAT(1X,I4,' - ',I4,':',10(1X,I11))
1003 FORMAT(1X,I4,' - ',I4,':',7(1X,I15))
1004 FORMAT(1X,' ')
C
RETURN
END

View File

@@ -0,0 +1,36 @@
SUBROUTINE SECOND( T )
*
REAL T
*
* -- LAPACK auxiliary routine (preliminary version) --
* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
* Courant Institute, Argonne National Lab, and Rice University
* July 26, 1991
*
* Purpose
* =======
*
* SECOND returns the user time for a process in seconds.
* This version gets the time from the system function ETIME.
*
* .. Local Scalars ..
REAL T1
* ..
* .. Local Arrays ..
REAL TARRAY( 2 )
* ..
* .. External Functions ..
REAL ETIME
* EXTERNAL ETIME
* ..
* .. Executable Statements ..
*
T1 = ETIME( TARRAY )
T = TARRAY( 1 )
RETURN
*
* End of SECOND
*
END

157
arpack/ARPACK/UTIL/smout.f Normal file
View File

@@ -0,0 +1,157 @@
*-----------------------------------------------------------------------
* Routine: SMOUT
*
* Purpose: Real matrix output routine.
*
* Usage: CALL SMOUT (LOUT, M, N, A, LDA, IDIGIT, IFMT)
*
* Arguments
* M - Number of rows of A. (Input)
* N - Number of columns of A. (Input)
* A - Real M by N matrix to be printed. (Input)
* LDA - Leading dimension of A exactly as specified in the
* dimension statement of the calling program. (Input)
* IFMT - Format to be used in printing matrix A. (Input)
* IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In)
* If IDIGIT .LT. 0, printing is done with 72 columns.
* If IDIGIT .GT. 0, printing is done with 132 columns.
*
*-----------------------------------------------------------------------
*
SUBROUTINE SMOUT( LOUT, M, N, A, LDA, IDIGIT, IFMT )
* ...
* ... SPECIFICATIONS FOR ARGUMENTS
INTEGER M, N, IDIGIT, LDA, LOUT
REAL A( LDA, * )
CHARACTER IFMT*( * )
* ...
* ... SPECIFICATIONS FOR LOCAL VARIABLES
INTEGER I, J, NDIGIT, K1, K2, LLL
CHARACTER*1 ICOL( 3 )
CHARACTER*80 LINE
* ...
* ... SPECIFICATIONS INTRINSICS
INTRINSIC MIN
*
DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o',
$ 'l' /
* ...
* ... FIRST EXECUTABLE STATEMENT
*
LLL = MIN( LEN( IFMT ), 80 )
DO 10 I = 1, LLL
LINE( I: I ) = '-'
10 CONTINUE
*
DO 20 I = LLL + 1, 80
LINE( I: I ) = ' '
20 CONTINUE
*
WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL )
9999 FORMAT( / 1X, A / 1X, A )
*
IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 )
$ RETURN
NDIGIT = IDIGIT
IF( IDIGIT.EQ.0 )
$ NDIGIT = 4
*
*=======================================================================
* CODE FOR OUTPUT USING 72 COLUMNS FORMAT
*=======================================================================
*
IF( IDIGIT.LT.0 ) THEN
NDIGIT = -IDIGIT
IF( NDIGIT.LE.4 ) THEN
DO 40 K1 = 1, N, 5
K2 = MIN0( N, K1+4 )
WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 )
DO 30 I = 1, M
WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 )
30 CONTINUE
40 CONTINUE
*
ELSE IF( NDIGIT.LE.6 ) THEN
DO 60 K1 = 1, N, 4
K2 = MIN0( N, K1+3 )
WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 )
DO 50 I = 1, M
WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 )
50 CONTINUE
60 CONTINUE
*
ELSE IF( NDIGIT.LE.10 ) THEN
DO 80 K1 = 1, N, 3
K2 = MIN0( N, K1+2 )
WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 )
DO 70 I = 1, M
WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 )
70 CONTINUE
80 CONTINUE
*
ELSE
DO 100 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 )
DO 90 I = 1, M
WRITE( LOUT, 9991 )I, ( A( I, J ), J = K1, K2 )
90 CONTINUE
100 CONTINUE
END IF
*
*=======================================================================
* CODE FOR OUTPUT USING 132 COLUMNS FORMAT
*=======================================================================
*
ELSE
IF( NDIGIT.LE.4 ) THEN
DO 120 K1 = 1, N, 10
K2 = MIN0( N, K1+9 )
WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 )
DO 110 I = 1, M
WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 )
110 CONTINUE
120 CONTINUE
*
ELSE IF( NDIGIT.LE.6 ) THEN
DO 140 K1 = 1, N, 8
K2 = MIN0( N, K1+7 )
WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 )
DO 130 I = 1, M
WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 )
130 CONTINUE
140 CONTINUE
*
ELSE IF( NDIGIT.LE.10 ) THEN
DO 160 K1 = 1, N, 6
K2 = MIN0( N, K1+5 )
WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 )
DO 150 I = 1, M
WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 )
150 CONTINUE
160 CONTINUE
*
ELSE
DO 180 K1 = 1, N, 5
K2 = MIN0( N, K1+4 )
WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 )
DO 170 I = 1, M
WRITE( LOUT, 9991 )I, ( A( I, J ), J = K1, K2 )
170 CONTINUE
180 CONTINUE
END IF
END IF
WRITE( LOUT, 9990 )
*
9998 FORMAT( 10X, 10( 4X, 3A1, I4, 1X ) )
9997 FORMAT( 10X, 8( 5X, 3A1, I4, 2X ) )
9996 FORMAT( 10X, 6( 7X, 3A1, I4, 4X ) )
9995 FORMAT( 10X, 5( 9X, 3A1, I4, 6X ) )
9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P10E12.3 )
9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P8E14.5 )
9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P6E18.9 )
9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P5E22.13 )
9990 FORMAT( 1X, ' ' )
*
RETURN
END

112
arpack/ARPACK/UTIL/svout.f Normal file
View File

@@ -0,0 +1,112 @@
*-----------------------------------------------------------------------
* Routine: SVOUT
*
* Purpose: Real vector output routine.
*
* Usage: CALL SVOUT (LOUT, N, SX, IDIGIT, IFMT)
*
* Arguments
* N - Length of array SX. (Input)
* SX - Real array to be printed. (Input)
* IFMT - Format to be used in printing array SX. (Input)
* IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In)
* If IDIGIT .LT. 0, printing is done with 72 columns.
* If IDIGIT .GT. 0, printing is done with 132 columns.
*
*-----------------------------------------------------------------------
*
SUBROUTINE SVOUT( LOUT, N, SX, IDIGIT, IFMT )
* ...
* ... SPECIFICATIONS FOR ARGUMENTS
INTEGER N, IDIGIT, LOUT
REAL SX( * )
CHARACTER IFMT*( * )
* ...
* ... SPECIFICATIONS FOR LOCAL VARIABLES
INTEGER I, NDIGIT, K1, K2, LLL
CHARACTER*80 LINE
* ...
* ... FIRST EXECUTABLE STATEMENT
*
*
LLL = MIN( LEN( IFMT ), 80 )
DO 10 I = 1, LLL
LINE( I: I ) = '-'
10 CONTINUE
*
DO 20 I = LLL + 1, 80
LINE( I: I ) = ' '
20 CONTINUE
*
WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL )
9999 FORMAT( / 1X, A / 1X, A )
*
IF( N.LE.0 )
$ RETURN
NDIGIT = IDIGIT
IF( IDIGIT.EQ.0 )
$ NDIGIT = 4
*
*=======================================================================
* CODE FOR OUTPUT USING 72 COLUMNS FORMAT
*=======================================================================
*
IF( IDIGIT.LT.0 ) THEN
NDIGIT = -IDIGIT
IF( NDIGIT.LE.4 ) THEN
DO 30 K1 = 1, N, 5
K2 = MIN0( N, K1+4 )
WRITE( LOUT, 9998 )K1, K2, ( SX( I ), I = K1, K2 )
30 CONTINUE
ELSE IF( NDIGIT.LE.6 ) THEN
DO 40 K1 = 1, N, 4
K2 = MIN0( N, K1+3 )
WRITE( LOUT, 9997 )K1, K2, ( SX( I ), I = K1, K2 )
40 CONTINUE
ELSE IF( NDIGIT.LE.10 ) THEN
DO 50 K1 = 1, N, 3
K2 = MIN0( N, K1+2 )
WRITE( LOUT, 9996 )K1, K2, ( SX( I ), I = K1, K2 )
50 CONTINUE
ELSE
DO 60 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, 9995 )K1, K2, ( SX( I ), I = K1, K2 )
60 CONTINUE
END IF
*
*=======================================================================
* CODE FOR OUTPUT USING 132 COLUMNS FORMAT
*=======================================================================
*
ELSE
IF( NDIGIT.LE.4 ) THEN
DO 70 K1 = 1, N, 10
K2 = MIN0( N, K1+9 )
WRITE( LOUT, 9998 )K1, K2, ( SX( I ), I = K1, K2 )
70 CONTINUE
ELSE IF( NDIGIT.LE.6 ) THEN
DO 80 K1 = 1, N, 8
K2 = MIN0( N, K1+7 )
WRITE( LOUT, 9997 )K1, K2, ( SX( I ), I = K1, K2 )
80 CONTINUE
ELSE IF( NDIGIT.LE.10 ) THEN
DO 90 K1 = 1, N, 6
K2 = MIN0( N, K1+5 )
WRITE( LOUT, 9996 )K1, K2, ( SX( I ), I = K1, K2 )
90 CONTINUE
ELSE
DO 100 K1 = 1, N, 5
K2 = MIN0( N, K1+4 )
WRITE( LOUT, 9995 )K1, K2, ( SX( I ), I = K1, K2 )
100 CONTINUE
END IF
END IF
WRITE( LOUT, 9994 )
RETURN
9998 FORMAT( 1X, I4, ' - ', I4, ':', 1P10E12.3 )
9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P8E14.5 )
9996 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P6E18.9 )
9995 FORMAT( 1X, I4, ' - ', I4, ':', 1X, 1P5E24.13 )
9994 FORMAT( 1X, ' ' )
END

250
arpack/ARPACK/UTIL/zmout.f Normal file
View File

@@ -0,0 +1,250 @@
*
* Routine: ZMOUT
*
* Purpose: Complex*16 matrix output routine.
*
* Usage: CALL ZMOUT (LOUT, M, N, A, LDA, IDIGIT, IFMT)
*
* Arguments
* M - Number of rows of A. (Input)
* N - Number of columns of A. (Input)
* A - Complex*16 M by N matrix to be printed. (Input)
* LDA - Leading dimension of A exactly as specified in the
* dimension statement of the calling program. (Input)
* IFMT - Format to be used in printing matrix A. (Input)
* IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In)
* If IDIGIT .LT. 0, printing is done with 72 columns.
* If IDIGIT .GT. 0, printing is done with 132 columns.
*
*\SCCS Information: @(#)
* FILE: zmout.f SID: 2.1 DATE OF SID: 11/16/95 RELEASE: 2
*
*-----------------------------------------------------------------------
*
SUBROUTINE ZMOUT( LOUT, M, N, A, LDA, IDIGIT, IFMT )
* ...
* ... SPECIFICATIONS FOR ARGUMENTS
INTEGER M, N, IDIGIT, LDA, LOUT
Complex*16
& A( LDA, * )
CHARACTER IFMT*( * )
* ...
* ... SPECIFICATIONS FOR LOCAL VARIABLES
INTEGER I, J, NDIGIT, K1, K2, LLL
CHARACTER*1 ICOL( 3 )
CHARACTER*80 LINE
* ...
* ... SPECIFICATIONS INTRINSICS
INTRINSIC MIN
*
DATA ICOL( 1 ), ICOL( 2 ), ICOL( 3 ) / 'C', 'o',
$ 'l' /
* ...
* ... FIRST EXECUTABLE STATEMENT
*
LLL = MIN( LEN( IFMT ), 80 )
DO 10 I = 1, LLL
LINE( I: I ) = '-'
10 CONTINUE
*
DO 20 I = LLL + 1, 80
LINE( I: I ) = ' '
20 CONTINUE
*
WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL )
9999 FORMAT( / 1X, A / 1X, A )
*
IF( M.LE.0 .OR. N.LE.0 .OR. LDA.LE.0 )
$ RETURN
NDIGIT = IDIGIT
IF( IDIGIT.EQ.0 )
$ NDIGIT = 4
*
*=======================================================================
* CODE FOR OUTPUT USING 72 COLUMNS FORMAT
*=======================================================================
*
IF( IDIGIT.LT.0 ) THEN
NDIGIT = -IDIGIT
IF( NDIGIT.LE.4 ) THEN
DO 40 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 )
DO 30 I = 1, M
IF (K1.NE.N) THEN
WRITE( LOUT, 9994 )I, ( A( I, J ), J = K1, K2 )
ELSE
WRITE( LOUT, 9984 )I, ( A( I, J ), J = K1, K2 )
END IF
30 CONTINUE
40 CONTINUE
*
ELSE IF( NDIGIT.LE.6 ) THEN
DO 60 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 )
DO 50 I = 1, M
IF (K1.NE.N) THEN
WRITE( LOUT, 9993 )I, ( A( I, J ), J = K1, K2 )
ELSE
WRITE( LOUT, 9983 )I, ( A( I, J ), J = K1, K2 )
END IF
50 CONTINUE
60 CONTINUE
*
ELSE IF( NDIGIT.LE.8 ) THEN
DO 80 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 )
DO 70 I = 1, M
IF (K1.NE.N) THEN
WRITE( LOUT, 9992 )I, ( A( I, J ), J = K1, K2 )
ELSE
WRITE( LOUT, 9982 )I, ( A( I, J ), J = K1, K2 )
END IF
70 CONTINUE
80 CONTINUE
*
ELSE
DO 100 K1 = 1, N
WRITE( LOUT, 9995 ) ICOL, K1
DO 90 I = 1, M
WRITE( LOUT, 9991 )I, A( I, K1 )
90 CONTINUE
100 CONTINUE
END IF
*
*=======================================================================
* CODE FOR OUTPUT USING 132 COLUMNS FORMAT
*=======================================================================
*
ELSE
IF( NDIGIT.LE.4 ) THEN
DO 120 K1 = 1, N, 4
K2 = MIN0( N, K1+3 )
WRITE( LOUT, 9998 )( ICOL, I, I = K1, K2 )
DO 110 I = 1, M
IF ((K1+3).LE.N) THEN
WRITE( LOUT, 9974 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+3-N).EQ.1) THEN
WRITE( LOUT, 9964 )I, ( A( I, J ), J = k1, K2 )
ELSE IF ((K1+3-N).EQ.2) THEN
WRITE( LOUT, 9954 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+3-N).EQ.3) THEN
WRITE( LOUT, 9944 )I, ( A( I, J ), J = K1, K2 )
END IF
110 CONTINUE
120 CONTINUE
*
ELSE IF( NDIGIT.LE.6 ) THEN
DO 140 K1 = 1, N, 3
K2 = MIN0( N, K1+ 2)
WRITE( LOUT, 9997 )( ICOL, I, I = K1, K2 )
DO 130 I = 1, M
IF ((K1+2).LE.N) THEN
WRITE( LOUT, 9973 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+2-N).EQ.1) THEN
WRITE( LOUT, 9963 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+2-N).EQ.2) THEN
WRITE( LOUT, 9953 )I, ( A( I, J ), J = K1, K2 )
END IF
130 CONTINUE
140 CONTINUE
*
ELSE IF( NDIGIT.LE.8 ) THEN
DO 160 K1 = 1, N, 3
K2 = MIN0( N, K1+2 )
WRITE( LOUT, 9996 )( ICOL, I, I = K1, K2 )
DO 150 I = 1, M
IF ((K1+2).LE.N) THEN
WRITE( LOUT, 9972 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+2-N).EQ.1) THEN
WRITE( LOUT, 9962 )I, ( A( I, J ), J = K1, K2 )
ELSE IF ((K1+2-N).EQ.2) THEN
WRITE( LOUT, 9952 )I, ( A( I, J ), J = K1, K2 )
END IF
150 CONTINUE
160 CONTINUE
*
ELSE
DO 180 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
WRITE( LOUT, 9995 )( ICOL, I, I = K1, K2 )
DO 170 I = 1, M
IF ((K1+1).LE.N) THEN
WRITE( LOUT, 9971 )I, ( A( I, J ), J = K1, K2 )
ELSE
WRITE( LOUT, 9961 )I, ( A( I, J ), J = K1, K2 )
END IF
170 CONTINUE
180 CONTINUE
END IF
END IF
WRITE( LOUT, 9990 )
*
9998 FORMAT( 11X, 4( 9X, 3A1, I4, 9X ) )
9997 FORMAT( 10X, 4( 11X, 3A1, I4, 11X ) )
9996 FORMAT( 10X, 3( 13X, 3A1, I4, 13X ) )
9995 FORMAT( 12X, 2( 18x, 3A1, I4, 18X ) )
*
*========================================================
* FORMAT FOR 72 COLUMN
*========================================================
*
* DISPLAY 4 SIGNIFICANT DIGITS
*
9994 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D10.3,',',D10.3,') ') )
9984 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D10.3,',',D10.3,') ') )
*
* DISPLAY 6 SIGNIFICANT DIGITS
*
9993 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D12.5,',',D12.5,') ') )
9983 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D12.5,',',D12.5,') ') )
*
* DISPLAY 8 SIGNIFICANT DIGITS
*
9992 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D14.7,',',D14.7,') ') )
9982 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D14.7,',',D14.7,') ') )
*
* DISPLAY 13 SIGNIFICANT DIGITS
*
9991 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D20.13,',',D20.13,')') )
9990 FORMAT( 1X, ' ' )
*
*
*========================================================
* FORMAT FOR 132 COLUMN
*========================================================
*
* DISPLAY 4 SIGNIFICANT DIGIT
*
9974 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,4('(',D10.3,',',D10.3,') ') )
9964 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D10.3,',',D10.3,') ') )
9954 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D10.3,',',D10.3,') ') )
9944 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D10.3,',',D10.3,') ') )
*
* DISPLAY 6 SIGNIFICANT DIGIT
*
9973 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D12.5,',',D12.5,') ') )
9963 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D12.5,',',D12.5,') ') )
9953 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D12.5,',',D12.5,') ') )
*
* DISPLAY 8 SIGNIFICANT DIGIT
*
9972 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,3('(',D14.7,',',D14.7,') ') )
9962 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D14.7,',',D14.7,') ') )
9952 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D14.7,',',D14.7,') ') )
*
* DISPLAY 13 SIGNIFICANT DIGIT
*
9971 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,2('(',D20.13,',',D20.13,
& ') '))
9961 FORMAT( 1X, ' Row', I4, ':', 1X, 1P,1('(',D20.13,',',D20.13,
& ') '))
*
*
*
*
RETURN
END

240
arpack/ARPACK/UTIL/zvout.f Normal file
View File

@@ -0,0 +1,240 @@
c-----------------------------------------------------------------------
c
c\SCCS Information: @(#)
c FILE: zvout.f SID: 2.1 DATE OF SID: 11/16/95 RELEASE: 2
c
*-----------------------------------------------------------------------
* Routine: ZVOUT
*
* Purpose: Complex*16 vector output routine.
*
* Usage: CALL ZVOUT (LOUT, N, CX, IDIGIT, IFMT)
*
* Arguments
* N - Length of array CX. (Input)
* CX - Complex*16 array to be printed. (Input)
* IFMT - Format to be used in printing array CX. (Input)
* IDIGIT - Print up to IABS(IDIGIT) decimal digits per number. (In)
* If IDIGIT .LT. 0, printing is done with 72 columns.
* If IDIGIT .GT. 0, printing is done with 132 columns.
*
*-----------------------------------------------------------------------
*
SUBROUTINE ZVOUT( LOUT, N, CX, IDIGIT, IFMT )
* ...
* ... SPECIFICATIONS FOR ARGUMENTS
INTEGER N, IDIGIT, LOUT
Complex*16
& CX( * )
CHARACTER IFMT*( * )
* ...
* ... SPECIFICATIONS FOR LOCAL VARIABLES
INTEGER I, NDIGIT, K1, K2, LLL
CHARACTER*80 LINE
* ...
* ... FIRST EXECUTABLE STATEMENT
*
*
LLL = MIN( LEN( IFMT ), 80 )
DO 10 I = 1, LLL
LINE( I: I ) = '-'
10 CONTINUE
*
DO 20 I = LLL + 1, 80
LINE( I: I ) = ' '
20 CONTINUE
*
WRITE( LOUT, 9999 )IFMT, LINE( 1: LLL )
9999 FORMAT( / 1X, A / 1X, A )
*
IF( N.LE.0 )
$ RETURN
NDIGIT = IDIGIT
IF( IDIGIT.EQ.0 )
$ NDIGIT = 4
*
*=======================================================================
* CODE FOR OUTPUT USING 72 COLUMNS FORMAT
*=======================================================================
*
IF( IDIGIT.LT.0 ) THEN
NDIGIT = -IDIGIT
IF( NDIGIT.LE.4 ) THEN
DO 30 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
IF (K1.NE.N) THEN
WRITE( LOUT, 9998 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE
WRITE( LOUT, 9997 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
30 CONTINUE
ELSE IF( NDIGIT.LE.6 ) THEN
DO 40 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
IF (K1.NE.N) THEN
WRITE( LOUT, 9988 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE
WRITE( LOUT, 9987 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
40 CONTINUE
ELSE IF( NDIGIT.LE.8 ) THEN
DO 50 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
IF (K1.NE.N) THEN
WRITE( LOUT, 9978 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE
WRITE( LOUT, 9977 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
50 CONTINUE
ELSE
DO 60 K1 = 1, N
WRITE( LOUT, 9968 )K1, K1, CX( I )
60 CONTINUE
END IF
*
*=======================================================================
* CODE FOR OUTPUT USING 132 COLUMNS FORMAT
*=======================================================================
*
ELSE
IF( NDIGIT.LE.4 ) THEN
DO 70 K1 = 1, N, 4
K2 = MIN0( N, K1+3 )
IF ((K1+3).LE.N) THEN
WRITE( LOUT, 9958 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+3-N) .EQ. 1) THEN
WRITE( LOUT, 9957 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+3-N) .EQ. 2) THEN
WRITE( LOUT, 9956 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+3-N) .EQ. 1) THEN
WRITE( LOUT, 9955 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
70 CONTINUE
ELSE IF( NDIGIT.LE.6 ) THEN
DO 80 K1 = 1, N, 3
K2 = MIN0( N, K1+2 )
IF ((K1+2).LE.N) THEN
WRITE( LOUT, 9948 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+2-N) .EQ. 1) THEN
WRITE( LOUT, 9947 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+2-N) .EQ. 2) THEN
WRITE( LOUT, 9946 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
80 CONTINUE
ELSE IF( NDIGIT.LE.8 ) THEN
DO 90 K1 = 1, N, 3
K2 = MIN0( N, K1+2 )
IF ((K1+2).LE.N) THEN
WRITE( LOUT, 9938 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+2-N) .EQ. 1) THEN
WRITE( LOUT, 9937 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+2-N) .EQ. 2) THEN
WRITE( LOUT, 9936 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
90 CONTINUE
ELSE
DO 100 K1 = 1, N, 2
K2 = MIN0( N, K1+1 )
IF ((K1+2).LE.N) THEN
WRITE( LOUT, 9928 )K1, K2, ( CX( I ),
$ I = K1, K2 )
ELSE IF ((K1+2-N) .EQ. 1) THEN
WRITE( LOUT, 9927 )K1, K2, ( CX( I ),
$ I = K1, K2 )
END IF
100 CONTINUE
END IF
END IF
WRITE( LOUT, 9994 )
RETURN
*
*=======================================================================
* FORMAT FOR 72 COLUMNS
*=======================================================================
*
* DISPLAY 4 SIGNIFICANT DIGITS
*
9998 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',D10.3,',',D10.3,') ') )
9997 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',D10.3,',',D10.3,') ') )
*
* DISPLAY 6 SIGNIFICANT DIGITS
*
9988 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',D12.5,',',D12.5,') ') )
9987 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',D12.5,',',D12.5,') ') )
*
* DISPLAY 8 SIGNIFICANT DIGITS
*
9978 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',D14.7,',',D14.7,') ') )
9977 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',D14.7,',',D14.7,') ') )
*
* DISPLAY 13 SIGNIFICANT DIGITS
*
9968 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',D20.13,',',D20.13,') ') )
*
*=========================================================================
* FORMAT FOR 132 COLUMNS
*=========================================================================
*
* DISPLAY 4 SIGNIFICANT DIGITS
*
9958 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,4('(',D10.3,',',D10.3,') ') )
9957 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,3('(',D10.3,',',D10.3,') ') )
9956 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',D10.3,',',D10.3,') ') )
9955 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',D10.3,',',D10.3,') ') )
*
* DISPLAY 6 SIGNIFICANT DIGITS
*
9948 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,3('(',D12.5,',',D12.5,') ') )
9947 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',D12.5,',',D12.5,') ') )
9946 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',D12.5,',',D12.5,') ') )
*
* DISPLAY 8 SIGNIFICANT DIGITS
*
9938 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,3('(',D14.7,',',D14.7,') ') )
9937 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',D14.7,',',D14.7,') ') )
9936 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',D14.7,',',D14.7,') ') )
*
* DISPLAY 13 SIGNIFICANT DIGITS
*
9928 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,2('(',D20.13,',',D20.13,') ') )
9927 FORMAT( 1X, I4, ' - ', I4, ':', 1X,
$ 1P,1('(',D20.13,',',D20.13,') ') )
*
*
*
9994 FORMAT( 1X, ' ' )
END

98
arpack/README Normal file
View File

@@ -0,0 +1,98 @@
This is the ARPACK package from
http://www.caam.rice.edu/software/ARPACK/
Specifically the files are from
http://www.caam.rice.edu/software/ARPACK/SRC/arpack96.tar.gz
with the patch
http://www.caam.rice.edu/software/ARPACK/SRC/patch.tar.gz
The ARPACK README is at
http://www.caam.rice.edu/software/ARPACK/SRC/readme.arpack
---
ARPACK is a collection of Fortran77 subroutines designed to solve large
scale eigenvalue problems.
The package is designed to compute a few eigenvalues and corresponding
eigenvectors of a general n by n matrix A. It is most appropriate for large
sparse or structured matrices A where structured means that a matrix-vector
product w <- Av requires order n rather than the usual order n**2 floating
point operations. This software is based upon an algorithmic variant of the
Arnoldi process called the Implicitly Restarted Arnoldi Method (IRAM). When
the matrix A is symmetric it reduces to a variant of the Lanczos process
called the Implicitly Restarted Lanczos Method (IRLM). These variants may be
viewed as a synthesis of the Arnoldi/Lanczos process with the Implicitly
Shifted QR technique that is suitable for large scale problems. For many
standard problems, a matrix factorization is not required. Only the action
of the matrix on a vector is needed. ARPACK software is capable of solving
large scale symmetric, nonsymmetric, and generalized eigenproblems from
significant application areas. The software is designed to compute a few (k)
eigenvalues with user specified features such as those of largest real part
or largest magnitude. Storage requirements are on the order of n*k locations.
No auxiliary storage is required. A set of Schur basis vectors for the desired
k-dimensional eigen-space is computed which is numerically orthogonal to working
precision. Numerically accurate eigenvectors are available on request.
Important Features:
o Reverse Communication Interface.
o Single and Double Precision Real Arithmetic Versions for Symmetric,
Non-symmetric, Standard or Generalized Problems.
o Single and Double Precision Complex Arithmetic Versions for Standard
or Generalized Problems.
o Routines for Banded Matrices - Standard or Generalized Problems.
o Routines for The Singular Value Decomposition.
o Example driver routines that may be used as templates to implement
numerous Shift-Invert strategies for all problem types, data types
and precision.
---
The ARPACK license is BSD-like.
http://www.caam.rice.edu/software/ARPACK/RiceBSD.doc
---
Rice BSD Software License
Permits source and binary redistribution of the software ARPACK and
P_ARPACK for both non-commercial and commercial use.
Copyright (©) 2001, Rice University
Developed by D.C. Sorensen, R.B. Lehoucq, C. Yang, and K. Maschhoff.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
. If you modify the source for these routines we ask that you change the
name of the routine and comment the changes made to the original.
. Written notification is provided to the developers of intent to use
this software. Also, we ask that use of ARPACK is properly cited in
any resulting publications or software documentation.
. Neither the name of Rice University (RICE) nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY RICE AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL RICE OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.

4
arpack/__init__.py Normal file
View File

@@ -0,0 +1,4 @@
from info import __doc__
from arpack import *
import speigs

381
arpack/arpack.py Normal file
View File

@@ -0,0 +1,381 @@
"""
arpack - Scipy module to find a few eigenvectors and eigenvalues of a matrix
Uses ARPACK: http://www.caam.rice.edu/software/ARPACK/
"""
__all___=['eigen','eigen_symmetric']
import _arpack
import numpy as sb
import warnings
# inspired by iterative.py
# so inspired, in fact, that some of it was copied directly
try:
False, True
except NameError:
False, True = 0, 1
_type_conv = {'f':'s', 'd':'d', 'F':'c', 'D':'z'}
class get_matvec:
methname = 'matvec'
def __init__(self, obj, *args):
self.obj = obj
self.args = args
if isinstance(obj, sb.matrix):
self.callfunc = self.type1m
return
if isinstance(obj, sb.ndarray):
self.callfunc = self.type1
return
meth = getattr(obj,self.methname,None)
if not callable(meth):
raise ValueError, "Object must be an array "\
"or have a callable %s attribute." % (self.methname,)
self.obj = meth
self.callfunc = self.type2
def __call__(self, x):
return self.callfunc(x)
def type1(self, x):
return sb.dot(self.obj, x)
def type1m(self, x):
return sb.dot(self.obj.A, x)
def type2(self, x):
return self.obj(x,*self.args)
def eigen(A,k=6,M=None,ncv=None,which='LM',
maxiter=None,tol=0, return_eigenvectors=True):
""" Return k eigenvalues and eigenvectors of the matrix A.
Solves A * x[i] = w[i] * x[i], the standard eigenvalue problem for
w[i] eigenvalues with corresponding eigenvectors x[i].
Inputs:
A -- A matrix, array or an object with matvec(x) method to perform
the matrix vector product A * x. The sparse matrix formats
in scipy.sparse are appropriate for A.
k -- The number of eigenvalue/eigenvectors desired
M -- (Not implemented)
A symmetric positive-definite matrix for the generalized
eigenvalue problem A * x = w * M * x
Outputs:
w -- An array of k eigenvalues
v -- An array of k eigenvectors, k[i] is the eigenvector corresponding
to the eigenvector w[i]
Optional Inputs:
ncv -- Number of Lanczos vectors generated, ncv must be greater than k
and is recommended to be ncv > 2*k
which -- String specifying which eigenvectors to compute.
Compute the k eigenvalues of:
'LM' - largest magnitude.
'SM' - smallest magnitude.
'LR' - largest real part.
'SR' - smallest real part.
'LI' - largest imaginary part.
'SI' - smallest imaginary part.
maxiter -- Maximum number of Arnoldi update iterations allowed
tol -- Relative accuracy for eigenvalues (stopping criterion)
return_eigenvectors -- True|False, return eigenvectors
"""
try:
n,ny=A.shape
n==ny
except:
raise AttributeError("matrix is not square")
if M is not None:
raise NotImplementedError("generalized eigenproblem not supported yet")
# some defaults
if ncv is None:
ncv=2*k+1
ncv=min(ncv,n)
if maxiter==None:
maxiter=n*10
# guess type
resid = sb.zeros(n,'f')
try:
typ = A.dtype.char
except AttributeError:
typ = A.matvec(resid).dtype.char
if typ not in 'fdFD':
raise ValueError("matrix type must be 'f', 'd', 'F', or 'D'")
# some sanity checks
if k <= 0:
raise ValueError("k must be positive, k=%d"%k)
if k == n:
raise ValueError("k must be less than rank(A), k=%d"%k)
if maxiter <= 0:
raise ValueError("maxiter must be positive, maxiter=%d"%maxiter)
whiches=['LM','SM','LR','SR','LI','SI']
if which not in whiches:
raise ValueError("which must be one of %s"%' '.join(whiches))
if ncv > n or ncv < k:
raise ValueError("ncv must be k<=ncv<=n, ncv=%s"%ncv)
# assign solver and postprocessor
ltr = _type_conv[typ]
eigsolver = _arpack.__dict__[ltr+'naupd']
eigextract = _arpack.__dict__[ltr+'neupd']
matvec = get_matvec(A)
v = sb.zeros((n,ncv),typ) # holds Ritz vectors
resid = sb.zeros(n,typ) # residual
workd = sb.zeros(3*n,typ) # workspace
workl = sb.zeros(3*ncv*ncv+6*ncv,typ) # workspace
iparam = sb.zeros(11,'int') # problem parameters
ipntr = sb.zeros(14,'int') # pointers into workspaces
info = 0
ido = 0
if typ in 'FD':
rwork = sb.zeros(ncv,typ.lower())
# only supported mode is 1: Ax=lx
ishfts = 1
mode1 = 1
bmat = 'I'
iparam[0] = ishfts
iparam[2] = maxiter
iparam[6] = mode1
while True:
if typ in 'fd':
ido,resid,v,iparam,ipntr,info =\
eigsolver(ido,bmat,which,k,tol,resid,v,iparam,ipntr,
workd,workl,info)
else:
ido,resid,v,iparam,ipntr,info =\
eigsolver(ido,bmat,which,k,tol,resid,v,iparam,ipntr,
workd,workl,rwork,info)
if (ido == -1 or ido == 1):
# compute y = A * x
xslice = slice(ipntr[0]-1, ipntr[0]-1+n)
yslice = slice(ipntr[1]-1, ipntr[1]-1+n)
workd[yslice]=matvec(workd[xslice])
else: # done
break
if info < -1 :
raise RuntimeError("Error info=%d in arpack"%info)
return None
if info == -1:
warnings.warn("Maximum number of iterations taken: %s"%iparam[2])
# if iparam[3] != k:
# warnings.warn("Only %s eigenvalues converged"%iparam[3])
# now extract eigenvalues and (optionally) eigenvectors
rvec = return_eigenvectors
ierr = 0
howmny = 'A' # return all eigenvectors
sselect = sb.zeros(ncv,'int') # unused
sigmai = 0.0 # no shifts, not implemented
sigmar = 0.0 # no shifts, not implemented
workev = sb.zeros(3*ncv,typ)
if typ in 'fd':
dr=sb.zeros(k+1,typ)
di=sb.zeros(k+1,typ)
zr=sb.zeros((n,k+1),typ)
dr,di,z,info=\
eigextract(rvec,howmny,sselect,sigmar,sigmai,workev,
bmat,which,k,tol,resid,v,iparam,ipntr,
workd,workl,info)
# make eigenvalues complex
d=dr+1.0j*di
# futz with the eigenvectors:
# complex are stored as real,imaginary in consecutive columns
z=zr.astype(typ.upper())
for i in range(k): # fix c.c. pairs
if di[i] > 0 :
z[:,i]=zr[:,i]+1.0j*zr[:,i+1]
z[:,i+1]=z[:,i].conjugate()
else:
d,z,info =\
eigextract(rvec,howmny,sselect,sigmar,workev,
bmat,which,k,tol,resid,v,iparam,ipntr,
workd,workl,rwork,ierr)
if ierr != 0:
raise RuntimeError("Error info=%d in arpack"%info)
return None
if return_eigenvectors:
return d,z
return d
def eigen_symmetric(A,k=6,M=None,ncv=None,which='LM',
maxiter=None,tol=0, return_eigenvectors=True):
""" Return k eigenvalues and eigenvectors of the real symmetric matrix A.
Solves A * x[i] = w[i] * x[i], the standard eigenvalue problem for
w[i] eigenvalues with corresponding eigenvectors x[i].
A must be real and symmetric.
See eigen() for nonsymmetric or complex symmetric (Hermetian) matrices.
Inputs:
A -- A symmetric matrix, array or an object with matvec(x) method
to perform the matrix vector product A * x.
The sparse matrix formats in scipy.sparse are appropriate for A.
k -- The number of eigenvalue/eigenvectors desired
M -- (Not implemented)
A symmetric positive-definite matrix for the generalized
eigenvalue problem A * x = w * M * x
Outputs:
w -- An real array of k eigenvalues
v -- An array of k real eigenvectors, k[i] is the eigenvector corresponding
to the eigenvector w[i]
Optional Inputs:
ncv -- Number of Lanczos vectors generated, ncv must be greater than k
and is recommended to be ncv > 2*k
which -- String specifying which eigenvectors to compute.
Compute the k
'LA' - largest (algebraic) eigenvalues.
'SA' - smallest (algebraic) eigenvalues.
'LM' - largest (in magnitude) eigenvalues.
'SM' - smallest (in magnitude) eigenvalues.
'BE' - eigenvalues, half from each end of the
spectrum. When NEV is odd, compute one more from the
high end than from the low end.
maxiter -- Maximum number of Arnoldi update iterations allowed
tol -- Relative accuracy for eigenvalues (stopping criterion)
return_eigenvectors -- True|False, return eigenvectors
"""
try:
n,ny=A.shape
n==ny
except:
raise AttributeError("matrix is not square")
if M is not None:
raise NotImplementedError("generalized eigenproblem not supported yet")
if ncv is None:
ncv=2*k+1
ncv=min(ncv,n)
if maxiter==None:
maxiter=n*10
# guess type
resid = sb.zeros(n,'f')
try:
typ = A.dtype.char
except AttributeError:
typ = A.matvec(resid).dtype.char
if typ not in 'fd':
raise ValueError("matrix type must be 'f' or 'd'")
# some sanity checks
if k <= 0:
raise ValueError("k must be positive, k=%d"%k)
if k == n:
raise ValueError("k must be less than rank(A), k=%d"%k)
if maxiter <= 0:
raise ValueError("maxiter must be positive, maxiter=%d"%maxiter)
whiches=['LM','SM','LA','SA','BE']
if which not in whiches:
raise ValueError("which must be one of %s"%' '.join(whiches))
if ncv > n or ncv < k:
raise ValueError("ncv must be k<=ncv<=n, ncv=%s"%ncv)
# assign solver and postprocessor
ltr = _type_conv[typ]
eigsolver = _arpack.__dict__[ltr+'saupd']
eigextract = _arpack.__dict__[ltr+'seupd']
matvec = get_matvec(A)
v = sb.zeros((n,ncv),typ)
resid = sb.zeros(n,typ)
workd = sb.zeros(3*n,typ)
workl = sb.zeros(ncv*(ncv+8),typ)
iparam = sb.zeros(11,'int')
ipntr = sb.zeros(11,'int')
info = 0
ido = 0
# only supported mode is 1: Ax=lx
ishfts = 1
mode1 = 1
bmat='I'
iparam[0] = ishfts
iparam[2] = maxiter
iparam[6] = mode1
while True:
ido,resid,v,iparam,ipntr,info =\
eigsolver(ido,bmat,which,k,tol,resid,v,iparam,ipntr,
workd,workl,info)
if (ido == -1 or ido == 1):
xslice = slice(ipntr[0]-1, ipntr[0]-1+n)
yslice = slice(ipntr[1]-1, ipntr[1]-1+n)
workd[yslice]=matvec(workd[xslice])
else:
break
if info < -1 :
raise RuntimeError("Error info=%d in arpack"%info)
return None
if info == -1:
warnings.warn("Maximum number of iterations taken: %s"%iparam[2])
# now extract eigenvalues and (optionally) eigenvectors
rvec = return_eigenvectors
ierr = 0
howmny = 'A' # return all eigenvectors
sselect = sb.zeros(ncv,'int') # unused
sigma = 0.0 # no shifts, not implemented
d,z,info =\
eigextract(rvec,howmny,sselect,sigma,
bmat,which, k,tol,resid,v,iparam[0:7],ipntr,
workd[0:2*n],workl,ierr)
if ierr != 0:
raise RuntimeError("Error info=%d in arpack"%info)
return None
if return_eigenvectors:
return d,z
return d

207
arpack/arpack.pyf.src Normal file
View File

@@ -0,0 +1,207 @@
! -*- f90 -*-
! Note: the context of this file is case sensitive.
python module _arpack ! in
<_rd=real,double precision>
<_cd=complex,double complex>
interface ! in :_arpack
subroutine <s,d>saupd(ido,bmat,n,which,nev,tol,resid,ncv,v,ldv,iparam,ipntr,workd,workl,lworkl,info) ! in :_arpack:src/ssaupd.f
integer intent(in,out):: ido
character*1 :: bmat
integer optional,check(len(resid)>=n),depend(resid) :: n=len(resid)
character*2 :: which
integer :: nev
<_rd> :: tol
<_rd> dimension(n),intent(in,out) :: resid
integer optional,check(shape(v,1)==ncv),depend(v) :: ncv=shape(v,1)
<_rd> dimension(ldv,ncv),intent(in,out) :: v
integer optional,check(shape(v,0)==ldv),depend(v) :: ldv=shape(v,0)
integer dimension(11),intent(in,out) :: iparam
integer dimension(11),intent(in,out) :: ipntr
<_rd> dimension(3 * n),depend(n),intent(inout) :: workd
<_rd> dimension(lworkl),intent(inout) :: workl
integer optional,check(len(workl)>=lworkl),depend(workl) :: lworkl=len(workl)
integer intent(in,out):: info
end subroutine <s,d>saupd
subroutine <s,d>seupd(rvec,howmny,select,d,z,ldz,sigma,bmat,n,which,nev,tol,resid,ncv,v,ldv,iparam,ipntr,workd,workl,lworkl,info) ! in :_arpack:src/sseupd.f
logical :: rvec
character :: howmny
logical dimension(ncv) :: select
<_rd> dimension(nev),intent(out),depend(nev) :: d
<_rd> dimension(n,nev),intent(out),depend(nev) :: z
integer optional,check(shape(z,0)==ldz),depend(z) :: ldz=shape(z,0)
<_rd> :: sigma
character :: bmat
integer optional,check(len(resid)>=n),depend(resid) :: n=len(resid)
character*2 :: which
integer :: nev
<_rd> :: tol
<_rd> dimension(n) :: resid
integer optional,check(len(select)>=ncv),depend(select) :: ncv=len(select)
<_rd> dimension(ldv,ncv),depend(ncv) :: v
integer optional,check(shape(v,0)==ldv),depend(v) :: ldv=shape(v,0)
integer dimension(7) :: iparam
integer dimension(11) :: ipntr
<_rd> dimension(2 * n),depend(n) :: workd
<_rd> dimension(lworkl) :: workl
integer optional,check(len(workl)>=lworkl),depend(workl) :: lworkl=len(workl)
integer intent(in,out):: info
end subroutine <s,d>seupd
subroutine <s,d>naupd(ido,bmat,n,which,nev,tol,resid,ncv,v,ldv,iparam,ipntr,workd,workl,lworkl,info) ! in :_arpack:src/snaupd.f
integer intent(in,out):: ido
character*1 :: bmat
integer optional,check(len(resid)>=n),depend(resid) :: n=len(resid)
character*2 :: which
integer :: nev
<_rd> :: tol
<_rd> dimension(n),intent(in,out) :: resid
integer optional,check(shape(v,1)==ncv),depend(v) :: ncv=shape(v,1)
<_rd> dimension(ldv,ncv),intent(in,out) :: v
integer optional,check(shape(v,0)==ldv),depend(v) :: ldv=shape(v,0)
integer dimension(11),intent(in,out) :: iparam
integer dimension(14),intent(in,out) :: ipntr
<_rd> dimension(3 * n),depend(n),intent(inout) :: workd
<_rd> dimension(lworkl),intent(inout) :: workl
integer optional,check(len(workl)>=lworkl),depend(workl) :: lworkl=len(workl)
integer intent(in,out):: info
end subroutine <s,d>naupd
subroutine <s,d>neupd(rvec,howmny,select,dr,di,z,ldz,sigmar,sigmai,workev,bmat,n,which,nev,tol,resid,ncv,v,ldv,iparam,ipntr,workd,workl,lworkl,info) ! in ARPACK/SRC/sneupd.f
logical :: rvec
character :: howmny
logical dimension(ncv) :: select
<_rd> dimension(nev + 1),depend(nev),intent(out) :: dr
<_rd> dimension(nev + 1),depend(nev),intent(out) :: di
<_rd> dimension(n,nev+1),depend(n,nev),intent(out) :: z
integer optional,check(shape(z,0)==ldz),depend(z) :: ldz=shape(z,0)
<_rd> :: sigmar
<_rd> :: sigmai
<_rd> dimension(3 * ncv),depend(ncv) :: workev
character :: bmat
integer optional,check(len(resid)>=n),depend(resid) :: n=len(resid)
character*2 :: which
integer :: nev
<_rd> :: tol
<_rd> dimension(n) :: resid
integer optional,check(len(select)>=ncv),depend(select) :: ncv=len(select)
<_rd> dimension(n,ncv),depend(n,ncv) :: v
integer optional,check(shape(v,0)==ldv),depend(v) :: ldv=shape(v,0)
integer dimension(11) :: iparam
integer dimension(14) :: ipntr
<_rd> dimension(3 * n),depend(n):: workd
<_rd> dimension(lworkl) :: workl
integer optional,check(len(workl)>=lworkl),depend(workl) :: lworkl=len(workl)
integer intent(in,out):: info
end subroutine <s,d>neupd
subroutine <c,z>naupd(ido,bmat,n,which,nev,tol,resid,ncv,v,ldv,iparam,ipntr,workd,workl,lworkl,rwork,info) ! in :_arpack:src/snaupd.f
integer intent(in,out):: ido
character*1 :: bmat
integer optional,check(len(resid)>=n),depend(resid) :: n=len(resid)
character*2 :: which
integer :: nev
<_rd> :: tol
<_cd> dimension(n),intent(in,out) :: resid
integer optional,check(shape(v,1)==ncv),depend(v) :: ncv=shape(v,1)
<_cd> dimension(ldv,ncv),intent(in,out) :: v
integer optional,check(shape(v,0)==ldv),depend(v) :: ldv=shape(v,0)
integer dimension(11),intent(in,out) :: iparam
integer dimension(14),intent(in,out) :: ipntr
<_cd> dimension(3 * n),depend(n),intent(inout) :: workd
<_cd> dimension(lworkl),intent(inout) :: workl
integer optional,check(len(workl)>=lworkl),depend(workl) :: lworkl=len(workl)
<_rd> dimension(ncv),depend(ncv),intent(inout) :: rwork
integer intent(in,out):: info
end subroutine <c,z>naupd
subroutine <c,z>neupd(rvec,howmny,select,d,z,ldz,sigma,workev,bmat,n,which,nev,tol,resid,ncv,v,ldv,iparam,ipntr,workd,workl,lworkl,rwork,info) ! in :_arpack:src/sneupd.f
logical :: rvec
character :: howmny
logical dimension(ncv) :: select
<_cd> dimension(nev),depend(nev),intent(out) :: d
<_cd> dimension(n,nev), depend(nev),intent(out) :: z
integer optional,check(shape(z,0)==ldz),depend(z) :: ldz=shape(z,0)
<_cd> :: sigma
<_cd> dimension(3 * ncv),depend(ncv) :: workev
character :: bmat
integer optional,check(len(resid)>=n),depend(resid) :: n=len(resid)
character*2 :: which
integer :: nev
<_rd> :: tol
<_cd> dimension(n) :: resid
integer optional,check(len(select)>=ncv),depend(select) :: ncv=len(select)
<_cd> dimension(ldv,ncv),depend(ncv) :: v
integer optional,check(shape(v,0)==ldv),depend(v) :: ldv=shape(v,0)
integer dimension(11) :: iparam
integer dimension(14) :: ipntr
<_cd> dimension(3 * n),depend(n) :: workd
<_cd> dimension(lworkl) :: workl
integer optional,check(len(workl)>=lworkl),depend(workl) :: lworkl=len(workl)
<_rd> dimension(ncv),depend(ncv) :: rwork
integer intent(in,out):: info
end subroutine <c,z>neupd
integer :: logfil
integer :: ndigit
integer :: mgetv0
integer :: msaupd
integer :: msaup2
integer :: msaitr
integer :: mseigt
integer :: msapps
integer :: msgets
integer :: mseupd
integer :: mnaupd
integer :: mnaup2
integer :: mnaitr
integer :: mneigh
integer :: mnapps
integer :: mngets
integer :: mneupd
integer :: mcaupd
integer :: mcaup2
integer :: mcaitr
integer :: mceigh
integer :: mcapps
integer :: mcgets
integer :: mceupd
integer :: nopx
integer :: nbx
integer :: nrorth
integer :: nitref
integer :: nrstrt
real :: tsaupd
real :: tsaup2
real :: tsaitr
real :: tseigt
real :: tsgets
real :: tsapps
real :: tsconv
real :: tnaupd
real :: tnaup2
real :: tnaitr
real :: tneigh
real :: tngets
real :: tnapps
real :: tnconv
real :: tcaupd
real :: tcaup2
real :: tcaitr
real :: tceigh
real :: tcgets
real :: tcapps
real :: tcconv
real :: tmvopx
real :: tmvbx
real :: tgetv0
real :: titref
real :: trvec
common /debug/ logfil,ndigit,mgetv0,msaupd,msaup2,msaitr,mseigt,msapps,msgets,mseupd,mnaupd,mnaup2,mnaitr,mneigh,mnapps,mngets,mneupd,mcaupd,mcaup2,mcaitr,mceigh,mcapps,mcgets,mceupd
common /timing/ nopx,nbx,nrorth,nitref,nrstrt,tsaupd,tsaup2,tsaitr,tseigt,tsgets,tsapps,tsconv,tnaupd,tnaup2,tnaitr,tneigh,tngets,tnapps,tnconv,tcaupd,tcaup2,tcaitr,tceigh,tcgets,tcapps,tcconv,tmvopx,tmvbx,tgetv0,titref,trvec
end interface
end python module _arpack
! This file was auto-generated with f2py (version:2_3198).
! See http://cens.ioc.ee/projects/f2py2e/

14
arpack/info.py Normal file
View File

@@ -0,0 +1,14 @@
"""
Eigenvalue solver using iterative methods.
Find k eigenvectors and eigenvalues of a matrix A using the
Arnoldi/Lanczos iterative methods from ARPACK.
These methods are most useful for large sparse matrices.
- eigen(A,k)
- eigen_symmetric(A,k)
"""
global_symbols = []
postpone_import = 1

36
arpack/setup.py Executable file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env python
from os.path import join
def configuration(parent_package='',top_path=None):
from numpy.distutils.system_info import get_info, NotFoundError
from numpy.distutils.misc_util import Configuration
lapack_opt = get_info('lapack_opt')
if not lapack_opt:
raise NotFoundError,'no lapack/blas resources found'
config = Configuration('arpack', parent_package, top_path)
arpack_sources=[join('ARPACK','SRC', '*.f')]
arpack_sources.extend([join('ARPACK','UTIL', '*.f')])
# arpack_sources.extend([join('ARPACK','BLAS', '*.f')])
arpack_sources.extend([join('ARPACK','LAPACK', '*.f')])
config.add_library('arpack', sources=arpack_sources,
include_dirs=[join('ARPACK', 'SRC')])
config.add_extension('_arpack',
sources='arpack.pyf.src',
libraries=['arpack'],
extra_info = lapack_opt
)
config.add_data_dir('tests')
return config
if __name__ == '__main__':
from numpy.distutils.core import setup
setup(**configuration(top_path='').todict())

Some files were not shown because too many files have changed in this diff Show More