Add graph references
This commit is contained in:
+989
@@ -0,0 +1,989 @@
|
||||
/* -- translated by f2c (version 20240504).
|
||||
You must link the resulting object file with libf2c:
|
||||
on Microsoft Windows system, link with libf2c.lib;
|
||||
on Linux or Unix systems, link with .../path/to/libf2c.a -lm
|
||||
or, if you install libf2c.a in a standard place, with -lf2c -lm
|
||||
-- in that order, at the end of the command line, as in
|
||||
cc *.o -lf2c -lm
|
||||
Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
|
||||
|
||||
http://www.netlib.org/f2c/libf2c.zip
|
||||
*/
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
/* Table of constant values */
|
||||
|
||||
static doublereal c_b21 = .66666666666666663;
|
||||
static integer c__1 = 1;
|
||||
static logical c_true = TRUE_;
|
||||
static doublereal c_b111 = 1.;
|
||||
|
||||
/* \BeginDoc
|
||||
|
||||
\Name: dseupd
|
||||
|
||||
\Description:
|
||||
|
||||
This subroutine returns the converged approximations to eigenvalues
|
||||
of A*z = lambda*B*z and (optionally):
|
||||
|
||||
(1) the corresponding approximate eigenvectors,
|
||||
|
||||
(2) an orthonormal (Lanczos) basis for the associated approximate
|
||||
invariant subspace,
|
||||
|
||||
(3) Both.
|
||||
|
||||
There is negligible additional cost to obtain eigenvectors. An orthonormal
|
||||
(Lanczos) basis is always computed. There is an additional storage cost
|
||||
of n*nev if both are requested (in this case a separate array Z must be
|
||||
supplied).
|
||||
|
||||
These quantities are obtained from the Lanczos factorization computed
|
||||
by DSAUPD for the linear operator OP prescribed by the MODE selection
|
||||
(see IPARAM(7) in DSAUPD documentation.) DSAUPD must be called before
|
||||
this routine is called. These approximate eigenvalues and vectors are
|
||||
commonly called Ritz values and Ritz vectors respectively. They are
|
||||
referred to as such in the comments that follow. The computed orthonormal
|
||||
basis for the invariant subspace corresponding to these Ritz values is
|
||||
referred to as a Lanczos basis.
|
||||
|
||||
See documentation in the header of the subroutine DSAUPD for a definition
|
||||
of OP as well as other terms and the relation of computed Ritz values
|
||||
and vectors of OP with respect to the given problem A*z = lambda*B*z.
|
||||
|
||||
The approximate eigenvalues of the original problem are returned in
|
||||
ascending algebraic order. The user may elect to call this routine
|
||||
once for each desired Ritz vector and store it peripherally if desired.
|
||||
There is also the option of computing a selected set of these vectors
|
||||
with a single call.
|
||||
|
||||
\Usage:
|
||||
call dseupd
|
||||
( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, BMAT, N, WHICH, NEV, TOL,
|
||||
RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, LWORKL, INFO )
|
||||
|
||||
RVEC LOGICAL (INPUT)
|
||||
Specifies whether Ritz vectors corresponding to the Ritz value
|
||||
approximations to the eigenproblem A*z = lambda*B*z are computed.
|
||||
|
||||
RVEC = .FALSE. Compute Ritz values only.
|
||||
|
||||
RVEC = .TRUE. Compute Ritz vectors.
|
||||
|
||||
HOWMNY Character*1 (INPUT)
|
||||
Specifies how many Ritz vectors are wanted and the form of Z
|
||||
the matrix of Ritz vectors. See remark 1 below.
|
||||
= 'A': compute NEV Ritz vectors;
|
||||
= 'S': compute some of the Ritz vectors, specified
|
||||
by the logical array SELECT.
|
||||
|
||||
SELECT Logical array of dimension NCV. (INPUT/WORKSPACE)
|
||||
If HOWMNY = 'S', SELECT specifies the Ritz vectors to be
|
||||
computed. To select the Ritz vector corresponding to a
|
||||
Ritz value D(j), SELECT(j) must be set to .TRUE..
|
||||
If HOWMNY = 'A' , SELECT is used as a workspace for
|
||||
reordering the Ritz values.
|
||||
|
||||
D Double precision array of dimension NEV. (OUTPUT)
|
||||
On exit, D contains the Ritz value approximations to the
|
||||
eigenvalues of A*z = lambda*B*z. The values are returned
|
||||
in ascending order. If IPARAM(7) = 3,4,5 then D represents
|
||||
the Ritz values of OP computed by dsaupd transformed to
|
||||
those of the original eigensystem A*z = lambda*B*z. If
|
||||
IPARAM(7) = 1,2 then the Ritz values of OP are the same
|
||||
as the those of A*z = lambda*B*z.
|
||||
|
||||
Z Double precision N by NEV array if HOWMNY = 'A'. (OUTPUT)
|
||||
On exit, Z contains the B-orthonormal Ritz vectors of the
|
||||
eigensystem A*z = lambda*B*z corresponding to the Ritz
|
||||
value approximations.
|
||||
If RVEC = .FALSE. then Z is not referenced.
|
||||
NOTE: The array Z may be set equal to first NEV columns of the
|
||||
Arnoldi/Lanczos basis array V computed by DSAUPD .
|
||||
|
||||
LDZ Integer. (INPUT)
|
||||
The leading dimension of the array Z. If Ritz vectors are
|
||||
desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1.
|
||||
|
||||
SIGMA Double precision (INPUT)
|
||||
If IPARAM(7) = 3,4,5 represents the shift. Not referenced if
|
||||
IPARAM(7) = 1 or 2.
|
||||
|
||||
|
||||
**** The remaining arguments MUST be the same as for the ****
|
||||
**** call to DSAUPD that was just completed. ****
|
||||
|
||||
NOTE: The remaining arguments
|
||||
|
||||
BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR,
|
||||
WORKD, WORKL, LWORKL, INFO
|
||||
|
||||
must be passed directly to DSEUPD following the last call
|
||||
to DSAUPD . These arguments MUST NOT BE MODIFIED between
|
||||
the the last call to DSAUPD and the call to DSEUPD .
|
||||
|
||||
Two of these parameters (WORKL, INFO) are also output parameters:
|
||||
|
||||
WORKL Double precision work array of length LWORKL. (OUTPUT/WORKSPACE)
|
||||
WORKL(1:4*ncv) contains information obtained in
|
||||
dsaupd . They are not changed by dseupd .
|
||||
WORKL(4*ncv+1:ncv*ncv+8*ncv) holds the
|
||||
untransformed Ritz values, the computed error estimates,
|
||||
and the associated eigenvector matrix of H.
|
||||
|
||||
Note: IPNTR(8:10) contains the pointer into WORKL for addresses
|
||||
of the above information computed by dseupd .
|
||||
-------------------------------------------------------------
|
||||
IPNTR(8): pointer to the NCV RITZ values of the original system.
|
||||
IPNTR(9): pointer to the NCV corresponding error bounds.
|
||||
IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors
|
||||
of the tridiagonal matrix T. Only referenced by
|
||||
dseupd if RVEC = .TRUE. See Remarks.
|
||||
-------------------------------------------------------------
|
||||
|
||||
INFO Integer. (OUTPUT)
|
||||
Error flag on output.
|
||||
= 0: Normal exit.
|
||||
= -1: N must be positive.
|
||||
= -2: NEV must be positive.
|
||||
= -3: NCV must be greater than NEV and less than or equal to N.
|
||||
= -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'.
|
||||
= -6: BMAT must be one of 'I' or 'G'.
|
||||
= -7: Length of private work WORKL array is not sufficient.
|
||||
= -8: Error return from trid. eigenvalue calculation;
|
||||
Information error from LAPACK routine dsteqr .
|
||||
= -9: Starting vector is zero.
|
||||
= -10: IPARAM(7) must be 1,2,3,4,5.
|
||||
= -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.
|
||||
= -12: NEV and WHICH = 'BE' are incompatible.
|
||||
= -14: DSAUPD did not find any eigenvalues to sufficient
|
||||
accuracy.
|
||||
= -15: HOWMNY must be one of 'A' or 'S' if RVEC = .true.
|
||||
= -16: HOWMNY = 'S' not yet implemented
|
||||
= -17: DSEUPD got a different count of the number of converged
|
||||
Ritz values than DSAUPD got. This indicates the user
|
||||
probably made an error in passing data from DSAUPD to
|
||||
DSEUPD or that the data was modified before entering
|
||||
DSEUPD .
|
||||
|
||||
\BeginLib
|
||||
|
||||
\References:
|
||||
1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
|
||||
a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
|
||||
pp 357-385.
|
||||
2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
|
||||
Restarted Arnoldi Iteration", Rice University Technical Report
|
||||
TR95-13, Department of Computational and Applied Mathematics.
|
||||
3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall,
|
||||
1980.
|
||||
4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program",
|
||||
Computer Physics Communications, 53 (1989), pp 169-179.
|
||||
5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to
|
||||
Implement the Spectral Transformation", Math. Comp., 48 (1987),
|
||||
pp 663-673.
|
||||
6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos
|
||||
Algorithm for Solving Sparse Symmetric Generalized Eigenproblems",
|
||||
SIAM J. Matr. Anal. Apps., January (1993).
|
||||
7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines
|
||||
for Updating the QR decomposition", ACM TOMS, December 1990,
|
||||
Volume 16 Number 4, pp 369-377.
|
||||
|
||||
\Remarks
|
||||
1. The converged Ritz values are always returned in increasing
|
||||
(algebraic) order.
|
||||
|
||||
2. Currently only HOWMNY = 'A' is implemented. It is included at this
|
||||
stage for the user who wants to incorporate it.
|
||||
|
||||
\Routines called:
|
||||
dsesrt ARPACK routine that sorts an array X, and applies the
|
||||
corresponding permutation to a matrix A.
|
||||
dsortr dsortr ARPACK sorting routine.
|
||||
ivout ARPACK utility routine that prints integers.
|
||||
dvout ARPACK utility routine that prints vectors.
|
||||
dgeqr2 LAPACK routine that computes the QR factorization of
|
||||
a matrix.
|
||||
dlacpy LAPACK matrix copy routine.
|
||||
dlamch LAPACK routine that determines machine constants.
|
||||
dorm2r LAPACK routine that applies an orthogonal matrix in
|
||||
factored form.
|
||||
dsteqr LAPACK routine that computes eigenvalues and eigenvectors
|
||||
of a tridiagonal matrix.
|
||||
dger Level 2 BLAS rank one update to a matrix.
|
||||
dcopy Level 1 BLAS that copies one vector to another .
|
||||
dnrm2 Level 1 BLAS that computes the norm of a vector.
|
||||
dscal Level 1 BLAS that scales a vector.
|
||||
dswap Level 1 BLAS that swaps the contents of two vectors.
|
||||
\Authors
|
||||
Danny Sorensen Phuong Vu
|
||||
Richard Lehoucq CRPC / Rice University
|
||||
Chao Yang Houston, Texas
|
||||
Dept. of Computational &
|
||||
Applied Mathematics
|
||||
Rice University
|
||||
Houston, Texas
|
||||
|
||||
\Revision history:
|
||||
12/15/93: Version ' 2.1'
|
||||
|
||||
\SCCS Information: @(#)
|
||||
FILE: seupd.F SID: 2.11 DATE OF SID: 04/10/01 RELEASE: 2
|
||||
|
||||
\EndLib
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Subroutine */ int igraphdseupd_(logical *rvec, char *howmny, logical *select,
|
||||
doublereal *d__, doublereal *z__, integer *ldz, doublereal *sigma,
|
||||
char *bmat, integer *n, char *which, integer *nev, doublereal *tol,
|
||||
doublereal *resid, integer *ncv, doublereal *v, integer *ldv, integer
|
||||
*iparam, integer *ipntr, doublereal *workd, doublereal *workl,
|
||||
integer *lworkl, integer *info)
|
||||
{
|
||||
/* System generated locals */
|
||||
integer v_dim1, v_offset, z_dim1, z_offset, i__1;
|
||||
doublereal d__1, d__2, d__3;
|
||||
|
||||
/* Builtin functions */
|
||||
integer s_cmp(char *, char *, ftnlen, ftnlen);
|
||||
/* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen);
|
||||
double pow_dd(doublereal *, doublereal *);
|
||||
|
||||
/* Local variables */
|
||||
integer j, k, ih, jj, iq, np, iw, ibd, ihb, ihd, ldh, ldq, irz;
|
||||
extern /* Subroutine */ int igraphdger_(integer *, integer *, doublereal *,
|
||||
doublereal *, integer *, doublereal *, integer *, doublereal *,
|
||||
integer *);
|
||||
integer mode;
|
||||
doublereal eps23;
|
||||
integer ierr;
|
||||
doublereal temp;
|
||||
integer next;
|
||||
char type__[6];
|
||||
integer ritz;
|
||||
extern doublereal igraphdnrm2_(integer *, doublereal *, integer *);
|
||||
doublereal temp1;
|
||||
extern /* Subroutine */ int igraphdscal_(integer *, doublereal *, doublereal *,
|
||||
integer *);
|
||||
logical reord;
|
||||
extern /* Subroutine */ int igraphdcopy_(integer *, doublereal *, integer *,
|
||||
doublereal *, integer *);
|
||||
integer nconv;
|
||||
doublereal rnorm;
|
||||
extern /* Subroutine */ int igraphdvout_(integer *, integer *, doublereal *,
|
||||
integer *, char *, ftnlen), igraphivout_(integer *, integer *, integer *
|
||||
, integer *, char *, ftnlen), igraphdgeqr2_(integer *, integer *,
|
||||
doublereal *, integer *, doublereal *, doublereal *, integer *);
|
||||
doublereal bnorm2;
|
||||
extern /* Subroutine */ int igraphdorm2r_(char *, char *, integer *, integer *,
|
||||
integer *, doublereal *, integer *, doublereal *, doublereal *,
|
||||
integer *, doublereal *, integer *);
|
||||
extern doublereal igraphdlamch_(char *);
|
||||
extern /* Subroutine */ int igraphdlacpy_(char *, integer *, integer *,
|
||||
doublereal *, integer *, doublereal *, integer *);
|
||||
integer logfil=6, ndigit=-3, ishift;
|
||||
extern /* Subroutine */ int igraphdsgets_(integer *, char *, integer *, integer
|
||||
*, doublereal *, doublereal *, doublereal *);
|
||||
integer bounds, mseupd=0;
|
||||
extern /* Subroutine */ int igraphdsteqr_(char *, integer *, doublereal *,
|
||||
doublereal *, doublereal *, integer *, doublereal *, integer *);
|
||||
integer msglvl;
|
||||
extern /* Subroutine */ int igraphdsesrt_(char *, logical *, integer *,
|
||||
doublereal *, integer *, doublereal *, integer *);
|
||||
integer numcnv;
|
||||
extern /* Subroutine */ int igraphdsortr_(char *, logical *, integer *,
|
||||
doublereal *, doublereal *);
|
||||
integer leftptr, rghtptr;
|
||||
|
||||
|
||||
/* %----------------------------------------------------%
|
||||
| Include files for debugging and timing information |
|
||||
%----------------------------------------------------%
|
||||
|
||||
|
||||
%------------------%
|
||||
| Scalar Arguments |
|
||||
%------------------%
|
||||
|
||||
|
||||
%-----------------%
|
||||
| Array Arguments |
|
||||
%-----------------%
|
||||
|
||||
|
||||
%------------%
|
||||
| Parameters |
|
||||
%------------%
|
||||
|
||||
|
||||
%---------------%
|
||||
| Local Scalars |
|
||||
%---------------%
|
||||
|
||||
|
||||
%----------------------%
|
||||
| External Subroutines |
|
||||
%----------------------%
|
||||
|
||||
|
||||
%--------------------%
|
||||
| External Functions |
|
||||
%--------------------%
|
||||
|
||||
|
||||
%---------------------%
|
||||
| Intrinsic Functions |
|
||||
%---------------------%
|
||||
|
||||
|
||||
%-----------------------%
|
||||
| Executable Statements |
|
||||
%-----------------------%
|
||||
|
||||
%------------------------%
|
||||
| Set default parameters |
|
||||
%------------------------%
|
||||
|
||||
Parameter adjustments */
|
||||
--workd;
|
||||
--resid;
|
||||
z_dim1 = *ldz;
|
||||
z_offset = 1 + z_dim1;
|
||||
z__ -= z_offset;
|
||||
--d__;
|
||||
--select;
|
||||
v_dim1 = *ldv;
|
||||
v_offset = 1 + v_dim1;
|
||||
v -= v_offset;
|
||||
--iparam;
|
||||
--ipntr;
|
||||
--workl;
|
||||
|
||||
/* Function Body */
|
||||
msglvl = mseupd;
|
||||
mode = iparam[7];
|
||||
nconv = iparam[5];
|
||||
*info = 0;
|
||||
|
||||
/* %--------------%
|
||||
| Quick return |
|
||||
%--------------% */
|
||||
|
||||
if (nconv == 0) {
|
||||
goto L9000;
|
||||
}
|
||||
ierr = 0;
|
||||
|
||||
if (nconv <= 0) {
|
||||
ierr = -14;
|
||||
}
|
||||
if (*n <= 0) {
|
||||
ierr = -1;
|
||||
}
|
||||
if (*nev <= 0) {
|
||||
ierr = -2;
|
||||
}
|
||||
if (*ncv <= *nev || *ncv > *n) {
|
||||
ierr = -3;
|
||||
}
|
||||
if (s_cmp(which, "LM", (ftnlen)2, (ftnlen)2) != 0 && s_cmp(which, "SM", (
|
||||
ftnlen)2, (ftnlen)2) != 0 && s_cmp(which, "LA", (ftnlen)2, (
|
||||
ftnlen)2) != 0 && s_cmp(which, "SA", (ftnlen)2, (ftnlen)2) != 0 &&
|
||||
s_cmp(which, "BE", (ftnlen)2, (ftnlen)2) != 0) {
|
||||
ierr = -5;
|
||||
}
|
||||
if (*(unsigned char *)bmat != 'I' && *(unsigned char *)bmat != 'G') {
|
||||
ierr = -6;
|
||||
}
|
||||
if (*(unsigned char *)howmny != 'A' && *(unsigned char *)howmny != 'P' &&
|
||||
*(unsigned char *)howmny != 'S' && *rvec) {
|
||||
ierr = -15;
|
||||
}
|
||||
if (*rvec && *(unsigned char *)howmny == 'S') {
|
||||
ierr = -16;
|
||||
}
|
||||
|
||||
/* Computing 2nd power */
|
||||
i__1 = *ncv;
|
||||
if (*rvec && *lworkl < i__1 * i__1 + (*ncv << 3)) {
|
||||
ierr = -7;
|
||||
}
|
||||
|
||||
if (mode == 1 || mode == 2) {
|
||||
s_copy(type__, "REGULR", (ftnlen)6, (ftnlen)6);
|
||||
} else if (mode == 3) {
|
||||
s_copy(type__, "SHIFTI", (ftnlen)6, (ftnlen)6);
|
||||
} else if (mode == 4) {
|
||||
s_copy(type__, "BUCKLE", (ftnlen)6, (ftnlen)6);
|
||||
} else if (mode == 5) {
|
||||
s_copy(type__, "CAYLEY", (ftnlen)6, (ftnlen)6);
|
||||
} else {
|
||||
ierr = -10;
|
||||
}
|
||||
if (mode == 1 && *(unsigned char *)bmat == 'G') {
|
||||
ierr = -11;
|
||||
}
|
||||
if (*nev == 1 && s_cmp(which, "BE", (ftnlen)2, (ftnlen)2) == 0) {
|
||||
ierr = -12;
|
||||
}
|
||||
|
||||
/* %------------%
|
||||
| Error Exit |
|
||||
%------------% */
|
||||
|
||||
if (ierr != 0) {
|
||||
*info = ierr;
|
||||
goto L9000;
|
||||
}
|
||||
|
||||
/* %-------------------------------------------------------%
|
||||
| Pointer into WORKL for address of H, RITZ, BOUNDS, Q |
|
||||
| etc... and the remaining workspace. |
|
||||
| Also update pointer to be used on output. |
|
||||
| Memory is laid out as follows: |
|
||||
| workl(1:2*ncv) := generated tridiagonal matrix H |
|
||||
| The subdiagonal is stored in workl(2:ncv). |
|
||||
| The dead spot is workl(1) but upon exiting |
|
||||
| dsaupd stores the B-norm of the last residual |
|
||||
| vector in workl(1). We use this !!! |
|
||||
| workl(2*ncv+1:2*ncv+ncv) := ritz values |
|
||||
| The wanted values are in the first NCONV spots. |
|
||||
| workl(3*ncv+1:3*ncv+ncv) := computed Ritz estimates |
|
||||
| The wanted values are in the first NCONV spots. |
|
||||
| NOTE: workl(1:4*ncv) is set by dsaupd and is not |
|
||||
| modified by dseupd . |
|
||||
%-------------------------------------------------------%
|
||||
|
||||
%-------------------------------------------------------%
|
||||
| The following is used and set by dseupd . |
|
||||
| workl(4*ncv+1:4*ncv+ncv) := used as workspace during |
|
||||
| computation of the eigenvectors of H. Stores |
|
||||
| the diagonal of H. Upon EXIT contains the NCV |
|
||||
| Ritz values of the original system. The first |
|
||||
| NCONV spots have the wanted values. If MODE = |
|
||||
| 1 or 2 then will equal workl(2*ncv+1:3*ncv). |
|
||||
| workl(5*ncv+1:5*ncv+ncv) := used as workspace during |
|
||||
| computation of the eigenvectors of H. Stores |
|
||||
| the subdiagonal of H. Upon EXIT contains the |
|
||||
| NCV corresponding Ritz estimates of the |
|
||||
| original system. The first NCONV spots have the |
|
||||
| wanted values. If MODE = 1,2 then will equal |
|
||||
| workl(3*ncv+1:4*ncv). |
|
||||
| workl(6*ncv+1:6*ncv+ncv*ncv) := orthogonal Q that is |
|
||||
| the eigenvector matrix for H as returned by |
|
||||
| dsteqr . Not referenced if RVEC = .False. |
|
||||
| Ordering follows that of workl(4*ncv+1:5*ncv) |
|
||||
| workl(6*ncv+ncv*ncv+1:6*ncv+ncv*ncv+2*ncv) := |
|
||||
| Workspace. Needed by dsteqr and by dseupd . |
|
||||
| GRAND total of NCV*(NCV+8) locations. |
|
||||
%-------------------------------------------------------% */
|
||||
|
||||
|
||||
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 + (*ncv << 1);
|
||||
ipntr[4] = next;
|
||||
ipntr[8] = ihd;
|
||||
ipntr[9] = ihb;
|
||||
ipntr[10] = iq;
|
||||
|
||||
/* %----------------------------------------%
|
||||
| irz points to the Ritz values computed |
|
||||
| by _seigt before exiting _saup2. |
|
||||
| ibd points to the Ritz estimates |
|
||||
| computed by _seigt before exiting |
|
||||
| _saup2. |
|
||||
%----------------------------------------% */
|
||||
|
||||
irz = ipntr[11] + *ncv;
|
||||
ibd = irz + *ncv;
|
||||
|
||||
|
||||
/* %---------------------------------%
|
||||
| Set machine dependent constant. |
|
||||
%---------------------------------% */
|
||||
|
||||
eps23 = igraphdlamch_("Epsilon-Machine");
|
||||
eps23 = pow_dd(&eps23, &c_b21);
|
||||
|
||||
/* %---------------------------------------%
|
||||
| RNORM is B-norm of the RESID(1:N). |
|
||||
| BNORM2 is the 2 norm of B*RESID(1:N). |
|
||||
| Upon exit of dsaupd WORKD(1:N) has |
|
||||
| B*RESID(1:N). |
|
||||
%---------------------------------------% */
|
||||
|
||||
rnorm = workl[ih];
|
||||
if (*(unsigned char *)bmat == 'I') {
|
||||
bnorm2 = rnorm;
|
||||
} else if (*(unsigned char *)bmat == 'G') {
|
||||
bnorm2 = igraphdnrm2_(n, &workd[1], &c__1);
|
||||
}
|
||||
|
||||
if (msglvl > 2) {
|
||||
igraphdvout_(&logfil, ncv, &workl[irz], &ndigit, "_seupd: Ritz values pass"
|
||||
"ed in from _SAUPD.", (ftnlen)42);
|
||||
igraphdvout_(&logfil, ncv, &workl[ibd], &ndigit, "_seupd: Ritz estimates p"
|
||||
"assed in from _SAUPD.", (ftnlen)45);
|
||||
}
|
||||
|
||||
if (*rvec) {
|
||||
|
||||
reord = FALSE_;
|
||||
|
||||
/* %---------------------------------------------------%
|
||||
| Use the temporary bounds array to store indices |
|
||||
| These will be used to mark the select array later |
|
||||
%---------------------------------------------------% */
|
||||
|
||||
i__1 = *ncv;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
workl[bounds + j - 1] = (doublereal) j;
|
||||
select[j] = FALSE_;
|
||||
/* L10: */
|
||||
}
|
||||
|
||||
/* %-------------------------------------%
|
||||
| Select the wanted Ritz values. |
|
||||
| Sort the Ritz values so that the |
|
||||
| wanted ones appear at the tailing |
|
||||
| NEV positions of workl(irr) and |
|
||||
| workl(iri). Move the corresponding |
|
||||
| error estimates in workl(bound) |
|
||||
| accordingly. |
|
||||
%-------------------------------------% */
|
||||
|
||||
np = *ncv - *nev;
|
||||
ishift = 0;
|
||||
igraphdsgets_(&ishift, which, nev, &np, &workl[irz], &workl[bounds], &workl[
|
||||
1]);
|
||||
|
||||
if (msglvl > 2) {
|
||||
igraphdvout_(&logfil, ncv, &workl[irz], &ndigit, "_seupd: Ritz values "
|
||||
"after calling _SGETS.", (ftnlen)41);
|
||||
igraphdvout_(&logfil, ncv, &workl[bounds], &ndigit, "_seupd: Ritz valu"
|
||||
"e indices after calling _SGETS.", (ftnlen)48);
|
||||
}
|
||||
|
||||
/* %-----------------------------------------------------%
|
||||
| Record indices of the converged wanted Ritz values |
|
||||
| Mark the select array for possible reordering |
|
||||
%-----------------------------------------------------% */
|
||||
|
||||
numcnv = 0;
|
||||
i__1 = *ncv;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
/* Computing MAX */
|
||||
d__2 = eps23, d__3 = (d__1 = workl[irz + *ncv - j], abs(d__1));
|
||||
temp1 = max(d__2,d__3);
|
||||
jj = (integer) workl[bounds + *ncv - j];
|
||||
if (numcnv < nconv && workl[ibd + jj - 1] <= *tol * temp1) {
|
||||
select[jj] = TRUE_;
|
||||
++numcnv;
|
||||
if (jj > nconv) {
|
||||
reord = TRUE_;
|
||||
}
|
||||
}
|
||||
/* L11: */
|
||||
}
|
||||
|
||||
/* %-----------------------------------------------------------%
|
||||
| Check the count (numcnv) of converged Ritz values with |
|
||||
| the number (nconv) reported by _saupd. If these two |
|
||||
| are different then there has probably been an error |
|
||||
| caused by incorrect passing of the _saupd data. |
|
||||
%-----------------------------------------------------------% */
|
||||
|
||||
if (msglvl > 2) {
|
||||
igraphivout_(&logfil, &c__1, &numcnv, &ndigit, "_seupd: Number of spec"
|
||||
"ified eigenvalues", (ftnlen)39);
|
||||
igraphivout_(&logfil, &c__1, &nconv, &ndigit, "_seupd: Number of \"con"
|
||||
"verged\" eigenvalues", (ftnlen)41);
|
||||
}
|
||||
|
||||
if (numcnv != nconv) {
|
||||
*info = -17;
|
||||
goto L9000;
|
||||
}
|
||||
|
||||
/* %-----------------------------------------------------------%
|
||||
| Call LAPACK routine _steqr to compute the eigenvalues and |
|
||||
| eigenvectors of the final symmetric tridiagonal matrix H. |
|
||||
| Initialize the eigenvector matrix Q to the identity. |
|
||||
%-----------------------------------------------------------% */
|
||||
|
||||
i__1 = *ncv - 1;
|
||||
igraphdcopy_(&i__1, &workl[ih + 1], &c__1, &workl[ihb], &c__1);
|
||||
igraphdcopy_(ncv, &workl[ih + ldh], &c__1, &workl[ihd], &c__1);
|
||||
|
||||
igraphdsteqr_("Identity", ncv, &workl[ihd], &workl[ihb], &workl[iq], &ldq, &
|
||||
workl[iw], &ierr);
|
||||
|
||||
if (ierr != 0) {
|
||||
*info = -8;
|
||||
goto L9000;
|
||||
}
|
||||
|
||||
if (msglvl > 1) {
|
||||
igraphdcopy_(ncv, &workl[iq + *ncv - 1], &ldq, &workl[iw], &c__1);
|
||||
igraphdvout_(&logfil, ncv, &workl[ihd], &ndigit, "_seupd: NCV Ritz val"
|
||||
"ues of the final H matrix", (ftnlen)45);
|
||||
igraphdvout_(&logfil, ncv, &workl[iw], &ndigit, "_seupd: last row of t"
|
||||
"he eigenvector matrix for H", (ftnlen)48);
|
||||
}
|
||||
|
||||
if (reord) {
|
||||
|
||||
/* %---------------------------------------------%
|
||||
| Reordered the eigenvalues and eigenvectors |
|
||||
| computed by _steqr so that the "converged" |
|
||||
| eigenvalues appear in the first NCONV |
|
||||
| positions of workl(ihd), and the associated |
|
||||
| eigenvectors appear in the first NCONV |
|
||||
| columns. |
|
||||
%---------------------------------------------% */
|
||||
|
||||
leftptr = 1;
|
||||
rghtptr = *ncv;
|
||||
|
||||
if (*ncv == 1) {
|
||||
goto L30;
|
||||
}
|
||||
|
||||
L20:
|
||||
if (select[leftptr]) {
|
||||
|
||||
/* %-------------------------------------------%
|
||||
| Search, from the left, for the first Ritz |
|
||||
| value that has not converged. |
|
||||
%-------------------------------------------% */
|
||||
|
||||
++leftptr;
|
||||
|
||||
} else if (! select[rghtptr]) {
|
||||
|
||||
/* %----------------------------------------------%
|
||||
| Search, from the right, the first Ritz value |
|
||||
| that has converged. |
|
||||
%----------------------------------------------% */
|
||||
|
||||
--rghtptr;
|
||||
|
||||
} else {
|
||||
|
||||
/* %----------------------------------------------%
|
||||
| Swap the Ritz value on the left that has not |
|
||||
| converged with the Ritz value on the right |
|
||||
| that has converged. Swap the associated |
|
||||
| eigenvector of the tridiagonal matrix H as |
|
||||
| well. |
|
||||
%----------------------------------------------% */
|
||||
|
||||
temp = workl[ihd + leftptr - 1];
|
||||
workl[ihd + leftptr - 1] = workl[ihd + rghtptr - 1];
|
||||
workl[ihd + rghtptr - 1] = temp;
|
||||
igraphdcopy_(ncv, &workl[iq + *ncv * (leftptr - 1)], &c__1, &workl[
|
||||
iw], &c__1);
|
||||
igraphdcopy_(ncv, &workl[iq + *ncv * (rghtptr - 1)], &c__1, &workl[
|
||||
iq + *ncv * (leftptr - 1)], &c__1);
|
||||
igraphdcopy_(ncv, &workl[iw], &c__1, &workl[iq + *ncv * (rghtptr -
|
||||
1)], &c__1);
|
||||
++leftptr;
|
||||
--rghtptr;
|
||||
|
||||
}
|
||||
|
||||
if (leftptr < rghtptr) {
|
||||
goto L20;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
L30:
|
||||
if (msglvl > 2) {
|
||||
igraphdvout_(&logfil, ncv, &workl[ihd], &ndigit, "_seupd: The eigenval"
|
||||
"ues of H--reordered", (ftnlen)39);
|
||||
}
|
||||
|
||||
/* %----------------------------------------%
|
||||
| Load the converged Ritz values into D. |
|
||||
%----------------------------------------% */
|
||||
|
||||
igraphdcopy_(&nconv, &workl[ihd], &c__1, &d__[1], &c__1);
|
||||
|
||||
} else {
|
||||
|
||||
/* %-----------------------------------------------------%
|
||||
| Ritz vectors not required. Load Ritz values into D. |
|
||||
%-----------------------------------------------------% */
|
||||
|
||||
igraphdcopy_(&nconv, &workl[ritz], &c__1, &d__[1], &c__1);
|
||||
igraphdcopy_(ncv, &workl[ritz], &c__1, &workl[ihd], &c__1);
|
||||
|
||||
}
|
||||
|
||||
/* %------------------------------------------------------------------%
|
||||
| Transform the Ritz values and possibly vectors and corresponding |
|
||||
| Ritz estimates of OP to those of A*x=lambda*B*x. The Ritz values |
|
||||
| (and corresponding data) are returned in ascending order. |
|
||||
%------------------------------------------------------------------% */
|
||||
|
||||
if (s_cmp(type__, "REGULR", (ftnlen)6, (ftnlen)6) == 0) {
|
||||
|
||||
/* %---------------------------------------------------------%
|
||||
| Ascending sort of wanted Ritz values, vectors and error |
|
||||
| bounds. Not necessary if only Ritz values are desired. |
|
||||
%---------------------------------------------------------% */
|
||||
|
||||
if (*rvec) {
|
||||
igraphdsesrt_("LA", rvec, &nconv, &d__[1], ncv, &workl[iq], &ldq);
|
||||
} else {
|
||||
igraphdcopy_(ncv, &workl[bounds], &c__1, &workl[ihb], &c__1);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* %-------------------------------------------------------------%
|
||||
| * Make a copy of all the Ritz values. |
|
||||
| * Transform the Ritz values back to the original system. |
|
||||
| For TYPE = 'SHIFTI' the transformation is |
|
||||
| lambda = 1/theta + sigma |
|
||||
| For TYPE = 'BUCKLE' the transformation is |
|
||||
| lambda = sigma * theta / ( theta - 1 ) |
|
||||
| For TYPE = 'CAYLEY' the transformation is |
|
||||
| lambda = sigma * (theta + 1) / (theta - 1 ) |
|
||||
| where the theta are the Ritz values returned by dsaupd . |
|
||||
| NOTES: |
|
||||
| *The Ritz vectors are not affected by the transformation. |
|
||||
| They are only reordered. |
|
||||
%-------------------------------------------------------------% */
|
||||
|
||||
igraphdcopy_(ncv, &workl[ihd], &c__1, &workl[iw], &c__1);
|
||||
if (s_cmp(type__, "SHIFTI", (ftnlen)6, (ftnlen)6) == 0) {
|
||||
i__1 = *ncv;
|
||||
for (k = 1; k <= i__1; ++k) {
|
||||
workl[ihd + k - 1] = 1. / workl[ihd + k - 1] + *sigma;
|
||||
/* L40: */
|
||||
}
|
||||
} else if (s_cmp(type__, "BUCKLE", (ftnlen)6, (ftnlen)6) == 0) {
|
||||
i__1 = *ncv;
|
||||
for (k = 1; k <= i__1; ++k) {
|
||||
workl[ihd + k - 1] = *sigma * workl[ihd + k - 1] / (workl[ihd
|
||||
+ k - 1] - 1.);
|
||||
/* L50: */
|
||||
}
|
||||
} else if (s_cmp(type__, "CAYLEY", (ftnlen)6, (ftnlen)6) == 0) {
|
||||
i__1 = *ncv;
|
||||
for (k = 1; k <= i__1; ++k) {
|
||||
workl[ihd + k - 1] = *sigma * (workl[ihd + k - 1] + 1.) / (
|
||||
workl[ihd + k - 1] - 1.);
|
||||
/* L60: */
|
||||
}
|
||||
}
|
||||
|
||||
/* %-------------------------------------------------------------%
|
||||
| * Store the wanted NCONV lambda values into D. |
|
||||
| * Sort the NCONV wanted lambda in WORKL(IHD:IHD+NCONV-1) |
|
||||
| into ascending order and apply sort to the NCONV theta |
|
||||
| values in the transformed system. We will need this to |
|
||||
| compute Ritz estimates in the original system. |
|
||||
| * Finally sort the lambda`s into ascending order and apply |
|
||||
| to Ritz vectors if wanted. Else just sort lambda`s into |
|
||||
| ascending order. |
|
||||
| NOTES: |
|
||||
| *workl(iw:iw+ncv-1) contain the theta ordered so that they |
|
||||
| match the ordering of the lambda. We`ll use them again for |
|
||||
| Ritz vector purification. |
|
||||
%-------------------------------------------------------------% */
|
||||
|
||||
igraphdcopy_(&nconv, &workl[ihd], &c__1, &d__[1], &c__1);
|
||||
igraphdsortr_("LA", &c_true, &nconv, &workl[ihd], &workl[iw]);
|
||||
if (*rvec) {
|
||||
igraphdsesrt_("LA", rvec, &nconv, &d__[1], ncv, &workl[iq], &ldq);
|
||||
} else {
|
||||
igraphdcopy_(ncv, &workl[bounds], &c__1, &workl[ihb], &c__1);
|
||||
d__1 = bnorm2 / rnorm;
|
||||
igraphdscal_(ncv, &d__1, &workl[ihb], &c__1);
|
||||
igraphdsortr_("LA", &c_true, &nconv, &d__[1], &workl[ihb]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* %------------------------------------------------%
|
||||
| Compute the Ritz vectors. Transform the wanted |
|
||||
| eigenvectors of the symmetric tridiagonal H by |
|
||||
| the Lanczos basis matrix V. |
|
||||
%------------------------------------------------% */
|
||||
|
||||
if (*rvec && *(unsigned char *)howmny == 'A') {
|
||||
|
||||
/* %----------------------------------------------------------%
|
||||
| Compute the QR factorization of the matrix representing |
|
||||
| the wanted invariant subspace located in the first NCONV |
|
||||
| columns of workl(iq,ldq). |
|
||||
%----------------------------------------------------------% */
|
||||
|
||||
igraphdgeqr2_(ncv, &nconv, &workl[iq], &ldq, &workl[iw + *ncv], &workl[ihb],
|
||||
&ierr);
|
||||
|
||||
/* %--------------------------------------------------------%
|
||||
| * Postmultiply V by Q. |
|
||||
| * Copy the first NCONV columns of VQ into Z. |
|
||||
| The N by NCONV matrix Z is now a matrix representation |
|
||||
| of the approximate invariant subspace associated with |
|
||||
| the Ritz values in workl(ihd). |
|
||||
%--------------------------------------------------------% */
|
||||
|
||||
igraphdorm2r_("Right", "Notranspose", n, ncv, &nconv, &workl[iq], &ldq, &
|
||||
workl[iw + *ncv], &v[v_offset], ldv, &workd[*n + 1], &ierr);
|
||||
igraphdlacpy_("All", n, &nconv, &v[v_offset], ldv, &z__[z_offset], ldz);
|
||||
|
||||
/* %-----------------------------------------------------%
|
||||
| In order to compute the Ritz estimates for the Ritz |
|
||||
| values in both systems, need the last row of the |
|
||||
| eigenvector matrix. Remember, it`s in factored form |
|
||||
%-----------------------------------------------------% */
|
||||
|
||||
i__1 = *ncv - 1;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
workl[ihb + j - 1] = 0.;
|
||||
/* L65: */
|
||||
}
|
||||
workl[ihb + *ncv - 1] = 1.;
|
||||
igraphdorm2r_("Left", "Transpose", ncv, &c__1, &nconv, &workl[iq], &ldq, &
|
||||
workl[iw + *ncv], &workl[ihb], ncv, &temp, &ierr);
|
||||
|
||||
/* %-----------------------------------------------------%
|
||||
| Make a copy of the last row into |
|
||||
| workl(iw+ncv:iw+2*ncv), as it is needed again in |
|
||||
| the Ritz vector purification step below |
|
||||
%-----------------------------------------------------% */
|
||||
|
||||
i__1 = nconv;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
workl[iw + *ncv + j - 1] = workl[ihb + j - 1];
|
||||
/* L67: */
|
||||
}
|
||||
} else if (*rvec && *(unsigned char *)howmny == 'S') {
|
||||
|
||||
/* Not yet implemented. See remark 2 above. */
|
||||
|
||||
}
|
||||
|
||||
if (s_cmp(type__, "REGULR", (ftnlen)6, (ftnlen)6) == 0 && *rvec) {
|
||||
|
||||
i__1 = *ncv;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
workl[ihb + j - 1] = rnorm * (d__1 = workl[ihb + j - 1], abs(d__1)
|
||||
);
|
||||
/* L70: */
|
||||
}
|
||||
|
||||
} else if (s_cmp(type__, "REGULR", (ftnlen)6, (ftnlen)6) != 0 && *rvec) {
|
||||
|
||||
/* %-------------------------------------------------%
|
||||
| * Determine Ritz estimates of the theta. |
|
||||
| If RVEC = .true. then compute Ritz estimates |
|
||||
| of the theta. |
|
||||
| If RVEC = .false. then copy Ritz estimates |
|
||||
| as computed by dsaupd . |
|
||||
| * Determine Ritz estimates of the lambda. |
|
||||
%-------------------------------------------------% */
|
||||
|
||||
igraphdscal_(ncv, &bnorm2, &workl[ihb], &c__1);
|
||||
if (s_cmp(type__, "SHIFTI", (ftnlen)6, (ftnlen)6) == 0) {
|
||||
|
||||
i__1 = *ncv;
|
||||
for (k = 1; k <= i__1; ++k) {
|
||||
/* Computing 2nd power */
|
||||
d__2 = workl[iw + k - 1];
|
||||
workl[ihb + k - 1] = (d__1 = workl[ihb + k - 1], abs(d__1)) /
|
||||
(d__2 * d__2);
|
||||
/* L80: */
|
||||
}
|
||||
|
||||
} else if (s_cmp(type__, "BUCKLE", (ftnlen)6, (ftnlen)6) == 0) {
|
||||
|
||||
i__1 = *ncv;
|
||||
for (k = 1; k <= i__1; ++k) {
|
||||
/* Computing 2nd power */
|
||||
d__2 = workl[iw + k - 1] - 1.;
|
||||
workl[ihb + k - 1] = *sigma * (d__1 = workl[ihb + k - 1], abs(
|
||||
d__1)) / (d__2 * d__2);
|
||||
/* L90: */
|
||||
}
|
||||
|
||||
} else if (s_cmp(type__, "CAYLEY", (ftnlen)6, (ftnlen)6) == 0) {
|
||||
|
||||
i__1 = *ncv;
|
||||
for (k = 1; k <= i__1; ++k) {
|
||||
workl[ihb + k - 1] = (d__1 = workl[ihb + k - 1] / workl[iw +
|
||||
k - 1] * (workl[iw + k - 1] - 1.), abs(d__1));
|
||||
/* L100: */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (s_cmp(type__, "REGULR", (ftnlen)6, (ftnlen)6) != 0 && msglvl > 1) {
|
||||
igraphdvout_(&logfil, &nconv, &d__[1], &ndigit, "_seupd: Untransformed con"
|
||||
"verged Ritz values", (ftnlen)43);
|
||||
igraphdvout_(&logfil, &nconv, &workl[ihb], &ndigit, "_seupd: Ritz estimate"
|
||||
"s of the untransformed Ritz values", (ftnlen)55);
|
||||
} else if (msglvl > 1) {
|
||||
igraphdvout_(&logfil, &nconv, &d__[1], &ndigit, "_seupd: Converged Ritz va"
|
||||
"lues", (ftnlen)29);
|
||||
igraphdvout_(&logfil, &nconv, &workl[ihb], &ndigit, "_seupd: Associated Ri"
|
||||
"tz estimates", (ftnlen)33);
|
||||
}
|
||||
|
||||
/* %-------------------------------------------------%
|
||||
| Ritz vector purification step. Formally perform |
|
||||
| one of inverse subspace iteration. Only used |
|
||||
| for MODE = 3,4,5. See reference 7 |
|
||||
%-------------------------------------------------% */
|
||||
|
||||
if (*rvec && (s_cmp(type__, "SHIFTI", (ftnlen)6, (ftnlen)6) == 0 || s_cmp(
|
||||
type__, "CAYLEY", (ftnlen)6, (ftnlen)6) == 0)) {
|
||||
|
||||
i__1 = nconv - 1;
|
||||
for (k = 0; k <= i__1; ++k) {
|
||||
workl[iw + k] = workl[iw + *ncv + k] / workl[iw + k];
|
||||
/* L110: */
|
||||
}
|
||||
|
||||
} else if (*rvec && s_cmp(type__, "BUCKLE", (ftnlen)6, (ftnlen)6) == 0) {
|
||||
|
||||
i__1 = nconv - 1;
|
||||
for (k = 0; k <= i__1; ++k) {
|
||||
workl[iw + k] = workl[iw + *ncv + k] / (workl[iw + k] - 1.);
|
||||
/* L120: */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (*rvec && s_cmp(type__, "REGULR", (ftnlen)6, (ftnlen)6) != 0) {
|
||||
igraphdger_(n, &nconv, &c_b111, &resid[1], &c__1, &workl[iw], &c__1, &z__[
|
||||
z_offset], ldz);
|
||||
}
|
||||
|
||||
L9000:
|
||||
|
||||
return 0;
|
||||
|
||||
/* %---------------%
|
||||
| End of dseupd |
|
||||
%---------------% */
|
||||
|
||||
} /* igraphdseupd_ */
|
||||
|
||||
Reference in New Issue
Block a user