Mercurial > octave-nkf
diff libcruft/arpack/src/dseupd.f @ 12194:470857149e61
import ARPACK sources to libcruft from Debian package libarpack2 2.1+parpack96.dfsg-3+b1
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 28 Jan 2011 14:04:33 -0500 |
parents | |
children | 126d8fe48a12 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcruft/arpack/src/dseupd.f Fri Jan 28 14:04:33 2011 -0500 @@ -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