Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/mathlibs/src/arpack/cneupd.f
5213 views
1
c\BeginDoc
2
c
3
c\Name: cneupd
4
c
5
c\Description:
6
c This subroutine returns the converged approximations to eigenvalues
7
c of A*z = lambda*B*z and (optionally):
8
c
9
c (1) The corresponding approximate eigenvectors;
10
c
11
c (2) An orthonormal basis for the associated approximate
12
c invariant subspace;
13
c
14
c (3) Both.
15
c
16
c There is negligible additional cost to obtain eigenvectors. An orthonormal
17
c basis is always computed. There is an additional storage cost of n*nev
18
c if both are requested (in this case a separate array Z must be supplied).
19
c
20
c The approximate eigenvalues and eigenvectors of A*z = lambda*B*z
21
c are derived from approximate eigenvalues and eigenvectors of
22
c of the linear operator OP prescribed by the MODE selection in the
23
c call to CNAUPD. CNAUPD must be called before this routine is called.
24
c These approximate eigenvalues and vectors are commonly called Ritz
25
c values and Ritz vectors respectively. They are referred to as such
26
c in the comments that follow. The computed orthonormal basis for the
27
c invariant subspace corresponding to these Ritz values is referred to as a
28
c Schur basis.
29
c
30
c The definition of OP as well as other terms and the relation of computed
31
c Ritz values and vectors of OP with respect to the given problem
32
c A*z = lambda*B*z may be found in the header of CNAUPD. For a brief
33
c description, see definitions of IPARAM(7), MODE and WHICH in the
34
c documentation of CNAUPD.
35
c
36
c\Usage:
37
c call cneupd
38
c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, WORKEV, BMAT,
39
c N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD,
40
c WORKL, LWORKL, RWORK, INFO )
41
c
42
c\Arguments:
43
c RVEC LOGICAL (INPUT)
44
c Specifies whether a basis for the invariant subspace corresponding
45
c to the converged Ritz value approximations for the eigenproblem
46
c A*z = lambda*B*z is computed.
47
c
48
c RVEC = .FALSE. Compute Ritz values only.
49
c
50
c RVEC = .TRUE. Compute Ritz vectors or Schur vectors.
51
c See Remarks below.
52
c
53
c HOWMNY Character*1 (INPUT)
54
c Specifies the form of the basis for the invariant subspace
55
c corresponding to the converged Ritz values that is to be computed.
56
c
57
c = 'A': Compute NEV Ritz vectors;
58
c = 'P': Compute NEV Schur vectors;
59
c = 'S': compute some of the Ritz vectors, specified
60
c by the logical array SELECT.
61
c
62
c SELECT Logical array of dimension NCV. (INPUT)
63
c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be
64
c computed. To select the Ritz vector corresponding to a
65
c Ritz value D(j), SELECT(j) must be set to .TRUE..
66
c If HOWMNY = 'A' or 'P', SELECT need not be initialized
67
c but it is used as internal workspace.
68
c
69
c D Complex array of dimension NEV+1. (OUTPUT)
70
c On exit, D contains the Ritz approximations
71
c to the eigenvalues lambda for A*z = lambda*B*z.
72
c
73
c Z Complex N by NEV array (OUTPUT)
74
c On exit, if RVEC = .TRUE. and HOWMNY = 'A', then the columns of
75
c Z represents approximate eigenvectors (Ritz vectors) corresponding
76
c to the NCONV=IPARAM(5) Ritz values for eigensystem
77
c A*z = lambda*B*z.
78
c
79
c If RVEC = .FALSE. or HOWMNY = 'P', then Z is NOT REFERENCED.
80
c
81
c NOTE: If if RVEC = .TRUE. and a Schur basis is not required,
82
c the array Z may be set equal to first NEV+1 columns of the Arnoldi
83
c basis array V computed by CNAUPD. In this case the Arnoldi basis
84
c will be destroyed and overwritten with the eigenvector basis.
85
c
86
c LDZ Integer. (INPUT)
87
c The leading dimension of the array Z. If Ritz vectors are
88
c desired, then LDZ .ge. max( 1, N ) is required.
89
c In any case, LDZ .ge. 1 is required.
90
c
91
c SIGMA Complex (INPUT)
92
c If IPARAM(7) = 3 then SIGMA represents the shift.
93
c Not referenced if IPARAM(7) = 1 or 2.
94
c
95
c WORKEV Complex work array of dimension 2*NCV. (WORKSPACE)
96
c
97
c **** The remaining arguments MUST be the same as for the ****
98
c **** call to CNAUPD that was just completed. ****
99
c
100
c NOTE: The remaining arguments
101
c
102
c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR,
103
c WORKD, WORKL, LWORKL, RWORK, INFO
104
c
105
c must be passed directly to CNEUPD following the last call
106
c to CNAUPD. These arguments MUST NOT BE MODIFIED between
107
c the the last call to CNAUPD and the call to CNEUPD.
108
c
109
c Three of these parameters (V, WORKL and INFO) are also output parameters:
110
c
111
c V Complex N by NCV array. (INPUT/OUTPUT)
112
c
113
c Upon INPUT: the NCV columns of V contain the Arnoldi basis
114
c vectors for OP as constructed by CNAUPD .
115
c
116
c Upon OUTPUT: If RVEC = .TRUE. the first NCONV=IPARAM(5) columns
117
c contain approximate Schur vectors that span the
118
c desired invariant subspace.
119
c
120
c NOTE: If the array Z has been set equal to first NEV+1 columns
121
c of the array V and RVEC=.TRUE. and HOWMNY= 'A', then the
122
c Arnoldi basis held by V has been overwritten by the desired
123
c Ritz vectors. If a separate array Z has been passed then
124
c the first NCONV=IPARAM(5) columns of V will contain approximate
125
c Schur vectors that span the desired invariant subspace.
126
c
127
c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE)
128
c WORKL(1:ncv*ncv+2*ncv) contains information obtained in
129
c cnaupd. They are not changed by cneupd.
130
c WORKL(ncv*ncv+2*ncv+1:3*ncv*ncv+4*ncv) holds the
131
c untransformed Ritz values, the untransformed error estimates of
132
c the Ritz values, the upper triangular matrix for H, and the
133
c associated matrix representation of the invariant subspace for H.
134
c
135
c Note: IPNTR(9:13) contains the pointer into WORKL for addresses
136
c of the above information computed by cneupd.
137
c -------------------------------------------------------------
138
c IPNTR(9): pointer to the NCV RITZ values of the
139
c original system.
140
c IPNTR(10): Not used
141
c IPNTR(11): pointer to the NCV corresponding error estimates.
142
c IPNTR(12): pointer to the NCV by NCV upper triangular
143
c Schur matrix for H.
144
c IPNTR(13): pointer to the NCV by NCV matrix of eigenvectors
145
c of the upper Hessenberg matrix H. Only referenced by
146
c cneupd if RVEC = .TRUE. See Remark 2 below.
147
c -------------------------------------------------------------
148
c
149
c INFO Integer. (OUTPUT)
150
c Error flag on output.
151
c = 0: Normal exit.
152
c
153
c = 1: The Schur form computed by LAPACK routine csheqr
154
c could not be reordered by LAPACK routine ctrsen.
155
c Re-enter subroutine cneupd with IPARAM(5)=NCV and
156
c increase the size of the array D to have
157
c dimension at least dimension NCV and allocate at least NCV
158
c columns for Z. NOTE: Not necessary if Z and V share
159
c the same space. Please notify the authors if this error
160
c occurs.
161
c
162
c = -1: N must be positive.
163
c = -2: NEV must be positive.
164
c = -3: NCV-NEV >= 2 and less than or equal to N.
165
c = -5: WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'
166
c = -6: BMAT must be one of 'I' or 'G'.
167
c = -7: Length of private work WORKL array is not sufficient.
168
c = -8: Error return from LAPACK eigenvalue calculation.
169
c This should never happened.
170
c = -9: Error return from calculation of eigenvectors.
171
c Informational error from LAPACK routine ctrevc.
172
c = -10: IPARAM(7) must be 1,2,3
173
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.
174
c = -12: HOWMNY = 'S' not yet implemented
175
c = -13: HOWMNY must be one of 'A' or 'P' if RVEC = .true.
176
c = -14: CNAUPD did not find any eigenvalues to sufficient
177
c accuracy.
178
c
179
c\BeginLib
180
c
181
c\References:
182
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
183
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
184
c pp 357-385.
185
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
186
c Restarted Arnoldi Iteration", Rice University Technical Report
187
c TR95-13, Department of Computational and Applied Mathematics.
188
c 3. B. Nour-Omid, B. N. Parlett, T. Ericsson and P. S. Jensen,
189
c "How to Implement the Spectral Transformation", Math Comp.,
190
c Vol. 48, No. 178, April, 1987 pp. 664-673.
191
c
192
c\Routines called:
193
c ivout ARPACK utility routine that prints integers.
194
c cmout ARPACK utility routine that prints matrices
195
c cvout ARPACK utility routine that prints vectors.
196
c cgeqr2 LAPACK routine that computes the QR factorization of
197
c a matrix.
198
c clacpy LAPACK matrix copy routine.
199
c clahqr LAPACK routine that computes the Schur form of a
200
c upper Hessenberg matrix.
201
c claset LAPACK matrix initialization routine.
202
c ctrevc LAPACK routine to compute the eigenvectors of a matrix
203
c in upper triangular form.
204
c ctrsen LAPACK routine that re-orders the Schur form.
205
c cunm2r LAPACK routine that applies an orthogonal matrix in
206
c factored form.
207
c slamch LAPACK routine that determines machine constants.
208
c ctrmm Level 3 BLAS matrix times an upper triangular matrix.
209
c cgeru Level 2 BLAS rank one update to a matrix.
210
c ccopy Level 1 BLAS that copies one vector to another .
211
c cscal Level 1 BLAS that scales a vector.
212
c csscal Level 1 BLAS that scales a complex vector by a real number.
213
c scnrm2 Level 1 BLAS that computes the norm of a complex vector.
214
c
215
c\Remarks
216
c
217
c 1. Currently only HOWMNY = 'A' and 'P' are implemented.
218
c
219
c 2. Schur vectors are an orthogonal representation for the basis of
220
c Ritz vectors. Thus, their numerical properties are often superior.
221
c If RVEC = .true. then the relationship
222
c A * V(:,1:IPARAM(5)) = V(:,1:IPARAM(5)) * T, and
223
c V(:,1:IPARAM(5))' * V(:,1:IPARAM(5)) = I are approximately satisfied.
224
c Here T is the leading submatrix of order IPARAM(5) of the
225
c upper triangular matrix stored workl(ipntr(12)).
226
c
227
c\Authors
228
c Danny Sorensen Phuong Vu
229
c Richard Lehoucq CRPC / Rice University
230
c Chao Yang Houston, Texas
231
c Dept. of Computational &
232
c Applied Mathematics
233
c Rice University
234
c Houston, Texas
235
c
236
c\SCCS Information: @(#)
237
c FILE: neupd.F SID: 2.4 DATE OF SID: 7/31/96 RELEASE: 2
238
c
239
c\EndLib
240
c
241
c-----------------------------------------------------------------------
242
subroutine cneupd (rvec, howmny, select, d, z, ldz, sigma,
243
& workev, bmat, n, which, nev, tol,
244
& resid, ncv, v, ldv, iparam, ipntr, workd,
245
& workl, lworkl, rwork, info)
246
c
247
c %----------------------------------------------------%
248
c | Include files for debugging and timing information |
249
c %----------------------------------------------------%
250
c
251
include 'debug.h'
252
include 'stat.h'
253
c
254
c %------------------%
255
c | Scalar Arguments |
256
c %------------------%
257
c
258
character bmat, howmny, which*2
259
logical rvec
260
integer info, ldz, ldv, lworkl, n, ncv, nev
261
Complex
262
& sigma
263
Real
264
& tol
265
c
266
c %-----------------%
267
c | Array Arguments |
268
c %-----------------%
269
c
270
integer iparam(11), ipntr(14)
271
logical select(ncv)
272
Real
273
& rwork(ncv)
274
Complex
275
& d(nev), resid(n), v(ldv,ncv), z(ldz, nev),
276
& workd(3*n), workl(lworkl), workev(2*ncv)
277
c
278
c %------------%
279
c | Parameters |
280
c %------------%
281
c
282
Complex
283
& one, zero
284
parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0))
285
c
286
c %---------------%
287
c | Local Scalars |
288
c %---------------%
289
c
290
character type*6
291
integer bounds, ierr, ih, ihbds, iheig, nconv,
292
& invsub, iuptri, iwev, j,
293
& ldh, ldq, mode, msglvl, ritz, wr, k,
294
& irz, ibd, ktrord, outncv, iq
295
Complex
296
& rnorm, temp, vl(1)
297
Real
298
& thres, conds, sep, rtemp, eps23
299
logical reord
300
c
301
c %----------------------%
302
c | External Subroutines |
303
c %----------------------%
304
c
305
external ccopy, cgeru, cgeqr2, clacpy, cmout,
306
& cunm2r, ctrmm, cvout, ivout,
307
& clahqr
308
c
309
c %--------------------%
310
c | External Functions |
311
c %--------------------%
312
c
313
Real
314
& scnrm2, slamch, slapy2
315
external scnrm2, slamch, slapy2
316
c
317
Complex
318
& cdotc
319
external cdotc
320
c
321
c %-----------------------%
322
c | Executable Statements |
323
c %-----------------------%
324
c
325
c %------------------------%
326
c | Set default parameters |
327
c %------------------------%
328
c
329
msglvl = mceupd
330
mode = iparam(7)
331
nconv = iparam(5)
332
info = 0
333
c
334
c
335
c %---------------------------------%
336
c | Get machine dependent constant. |
337
c %---------------------------------%
338
c
339
eps23 = slamch('Epsilon-Machine')
340
eps23 = eps23**(2.0E+0 / 3.0E+0)
341
c
342
c %-------------------------------%
343
c | Quick return |
344
c | Check for incompatible input |
345
c %-------------------------------%
346
c
347
ierr = 0
348
c
349
if (nconv .le. 0) then
350
ierr = -14
351
else if (n .le. 0) then
352
ierr = -1
353
else if (nev .le. 0) then
354
ierr = -2
355
else if (ncv .le. nev+1 .or. ncv .gt. n) then
356
ierr = -3
357
else if (which .ne. 'LM' .and.
358
& which .ne. 'SM' .and.
359
& which .ne. 'LR' .and.
360
& which .ne. 'SR' .and.
361
& which .ne. 'LI' .and.
362
& which .ne. 'SI') then
363
ierr = -5
364
else if (bmat .ne. 'I' .and. bmat .ne. 'G') then
365
ierr = -6
366
else if (lworkl .lt. 3*ncv**2 + 4*ncv) then
367
ierr = -7
368
else if ( (howmny .ne. 'A' .and.
369
& howmny .ne. 'P' .and.
370
& howmny .ne. 'S') .and. rvec ) then
371
ierr = -13
372
else if (howmny .eq. 'S' ) then
373
ierr = -12
374
end if
375
c
376
if (mode .eq. 1 .or. mode .eq. 2) then
377
type = 'REGULR'
378
else if (mode .eq. 3 ) then
379
type = 'SHIFTI'
380
else
381
ierr = -10
382
end if
383
if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11
384
c
385
c %------------%
386
c | Error Exit |
387
c %------------%
388
c
389
if (ierr .ne. 0) then
390
info = ierr
391
go to 9000
392
end if
393
c
394
c %--------------------------------------------------------%
395
c | Pointer into WORKL for address of H, RITZ, WORKEV, Q |
396
c | etc... and the remaining workspace. |
397
c | Also update pointer to be used on output. |
398
c | Memory is laid out as follows: |
399
c | workl(1:ncv*ncv) := generated Hessenberg matrix |
400
c | workl(ncv*ncv+1:ncv*ncv+ncv) := ritz values |
401
c | workl(ncv*ncv+ncv+1:ncv*ncv+2*ncv) := error bounds |
402
c %--------------------------------------------------------%
403
c
404
c %-----------------------------------------------------------%
405
c | The following is used and set by CNEUPD. |
406
c | workl(ncv*ncv+2*ncv+1:ncv*ncv+3*ncv) := The untransformed |
407
c | Ritz values. |
408
c | workl(ncv*ncv+3*ncv+1:ncv*ncv+4*ncv) := The untransformed |
409
c | error bounds of |
410
c | the Ritz values |
411
c | workl(ncv*ncv+4*ncv+1:2*ncv*ncv+4*ncv) := Holds the upper |
412
c | triangular matrix |
413
c | for H. |
414
c | workl(2*ncv*ncv+4*ncv+1: 3*ncv*ncv+4*ncv) := Holds the |
415
c | associated matrix |
416
c | representation of |
417
c | the invariant |
418
c | subspace for H. |
419
c | GRAND total of NCV * ( 3 * NCV + 4 ) locations. |
420
c %-----------------------------------------------------------%
421
c
422
ih = ipntr(5)
423
ritz = ipntr(6)
424
iq = ipntr(7)
425
bounds = ipntr(8)
426
ldh = ncv
427
ldq = ncv
428
iheig = bounds + ldh
429
ihbds = iheig + ldh
430
iuptri = ihbds + ldh
431
invsub = iuptri + ldh*ncv
432
ipntr(9) = iheig
433
ipntr(11) = ihbds
434
ipntr(12) = iuptri
435
ipntr(13) = invsub
436
wr = 1
437
iwev = wr + ncv
438
c
439
c %-----------------------------------------%
440
c | irz points to the Ritz values computed |
441
c | by _neigh before exiting _naup2. |
442
c | ibd points to the Ritz estimates |
443
c | computed by _neigh before exiting |
444
c | _naup2. |
445
c %-----------------------------------------%
446
c
447
irz = ipntr(14) + ncv*ncv
448
ibd = irz + ncv
449
c
450
c %------------------------------------%
451
c | RNORM is B-norm of the RESID(1:N). |
452
c %------------------------------------%
453
c
454
rnorm = workl(ih+2)
455
workl(ih+2) = zero
456
c
457
if (rvec) then
458
c
459
c %-------------------------------------------%
460
c | Get converged Ritz value on the boundary. |
461
c | Note: converged Ritz values have been |
462
c | placed in the first NCONV locations in |
463
c | workl(ritz). They have been sorted |
464
c | (in _naup2) according to the WHICH |
465
c | selection criterion |
466
c %-------------------------------------------%
467
c
468
if (which .eq. 'LM' .or. which .eq. 'SM') then
469
thres = slapy2(real(workl(ritz)),aimag(workl(ritz)))
470
else if (which .eq. 'LR' .or. which .eq. 'SR') then
471
thres = real(workl(ritz))
472
else if (which .eq. 'LI' .or. which .eq. 'SI') then
473
thres = aimag(workl(ritz))
474
end if
475
if (msglvl .gt. 2) then
476
call svout(logfil, 1, [thres], ndigit,
477
& '_neupd: Threshold eigenvalue used for re-ordering')
478
end if
479
c
480
c %---------------------------------------------------------%
481
c | Check to see if all converged Ritz values appear at the |
482
c | at the top of the upper triangular matrix computed by |
483
c | _neigh in _naup2. This is done in the following way: |
484
c | |
485
c | 1) For each Ritz value from _neigh, compare it with the |
486
c | threshold Ritz value computed above to determine |
487
c | whether it is a wanted one. |
488
c | |
489
c | 2) If it is wanted, then check the corresponding Ritz |
490
c | estimate to see if it has converged. If it has, set |
491
c | correponding entry in the logical array SELECT to |
492
c | .TRUE.. |
493
c | |
494
c | If SELECT(j) = .TRUE. and j > NCONV, then there is a |
495
c | converged Ritz value that does not appear at the top of |
496
c | the upper triangular matrix computed by _neigh in |
497
c | _naup2. Reordering is needed. |
498
c %---------------------------------------------------------%
499
c
500
reord = .false.
501
ktrord = 0
502
do 10 j = 0, ncv-1
503
select(j+1) = .false.
504
if (which .eq. 'LM') then
505
if ( slapy2(real(workl(irz+j)),
506
& aimag(workl(irz+j))) .ge. thres ) then
507
rtemp = max( eps23, slapy2(real(workl(irz+j-1)),
508
& aimag(workl(irz+j-1))) )
509
if ( slapy2(real(workl(ibd+j)),
510
& aimag(workl(ibd+j))) .le. tol*rtemp )
511
& select(j+1) = .true.
512
end if
513
else if (which .eq. 'SM') then
514
if ( slapy2(real(workl(irz+j)),
515
& aimag(workl(irz+j))) .le. thres ) then
516
rtemp = max( eps23, slapy2(real(workl(irz+j-1)),
517
& aimag(workl(irz+j-1))) )
518
if ( slapy2(real(workl(ibd+j)),
519
& aimag(workl(ibd+j))) .le. tol*rtemp )
520
& select(j+1) = .true.
521
end if
522
else if (which .eq. 'LR') then
523
if ( real(workl(irz+j)) .ge. thres ) then
524
rtemp = max( eps23, slapy2(real(workl(irz+j-1)),
525
& aimag(workl(irz+j-1))) )
526
if ( slapy2(real(workl(ibd+j)),
527
& aimag(workl(ibd+j))) .le. tol*rtemp )
528
& select(j+1) = .true.
529
end if
530
else if (which .eq. 'SR') then
531
if ( real(workl(irz+j)) .le. thres ) then
532
rtemp = max( eps23, slapy2(real(workl(irz+j-1)),
533
& aimag(workl(irz+j-1))) )
534
if ( slapy2(real(workl(ibd+j)),
535
& aimag(workl(ibd+j))) .le. tol*rtemp )
536
& select(j+1) = .true.
537
end if
538
else if (which .eq. 'LI') then
539
if ( aimag(workl(irz+j)) .ge. thres ) then
540
rtemp = max( eps23, slapy2(real(workl(irz+j-1)),
541
& aimag(workl(irz+j-1))) )
542
if ( slapy2(real(workl(ibd+j)),
543
& aimag(workl(ibd+j))) .le. tol*rtemp )
544
& select(j+1) = .true.
545
end if
546
else if (which .eq. 'SI') then
547
if ( aimag(workl(irz+j)) .le. thres ) then
548
rtemp = max( eps23, slapy2(real(workl(irz+j-1)),
549
& aimag(workl(irz+j-1))) )
550
if ( slapy2(real(workl(ibd+j)),
551
& aimag(workl(ibd+j))) .le. tol*rtemp )
552
& select(j+1) = .true.
553
end if
554
end if
555
if (j+1 .gt. nconv ) reord = ( select(j+1) .or. reord )
556
if (select(j+1)) ktrord = ktrord + 1
557
10 continue
558
c
559
if (msglvl .gt. 2) then
560
call ivout(logfil, 1, [ktrord], ndigit,
561
& '_neupd: Number of specified eigenvalues')
562
call ivout(logfil, 1, [nconv], ndigit,
563
& '_neupd: Number of "converged" eigenvalues')
564
end if
565
c
566
c if (ktrord .gt. nconv) then
567
c
568
c %-----------------------------------%
569
c | More than NCONV Ritz values have |
570
c | "converged", and they all satisfy |
571
c | the WHICH selection criterion. |
572
c %-----------------------------------%
573
c
574
c iparam(6) = ktrord
575
c
576
c end if
577
c
578
c %-------------------------------------------------------%
579
c | Call LAPACK routine clahqr to compute the Schur form |
580
c | of the upper Hessenberg matrix returned by CNAUPD. |
581
c | Make a copy of the upper Hessenberg matrix. |
582
c | Initialize the Schur vector matrix Q to the identity. |
583
c %-------------------------------------------------------%
584
c
585
call ccopy (ldh*ncv, workl(ih), 1, workl(iuptri), 1)
586
call claset ('All', ncv, ncv, zero, one, workl(invsub), ldq)
587
call clahqr (.true., .true., ncv, 1, ncv, workl(iuptri),
588
& ldh, workl(iheig), 1, ncv, workl(invsub), ldq, ierr)
589
call ccopy (ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1)
590
c
591
if (ierr .ne. 0) then
592
info = -8
593
go to 9000
594
end if
595
c
596
if (msglvl .gt. 1) then
597
call cvout (logfil, ncv, workl(iheig), ndigit,
598
& '_neupd: Eigenvalues of H')
599
call cvout (logfil, ncv, workl(ihbds), ndigit,
600
& '_neupd: Last row of the Schur vector matrix')
601
if (msglvl .gt. 3) then
602
call cmout (logfil, ncv, ncv, workl(iuptri), ldh, ndigit,
603
& '_neupd: The upper triangular matrix ')
604
end if
605
end if
606
c
607
if (reord) then
608
c
609
c %-----------------------------------------------%
610
c | Reorder the computed upper triangular matrix. |
611
c %-----------------------------------------------%
612
c
613
call ctrsen ('None', 'V', select, ncv, workl(iuptri), ldh,
614
& workl(invsub), ldq, workl(iheig), nconv, conds, sep,
615
& workev, ncv, ierr)
616
c
617
if (ierr .eq. 1) then
618
info = 1
619
go to 9000
620
end if
621
c
622
if (msglvl .gt. 2) then
623
call cvout (logfil, ncv, workl(iheig), ndigit,
624
& '_neupd: Eigenvalues of H--reordered')
625
if (msglvl .gt. 3) then
626
call cmout (logfil, ncv, ncv, workl(iuptri), ldq,
627
& ndigit,
628
& '_neupd: Triangular matrix after re-ordering')
629
end if
630
end if
631
c
632
end if
633
c
634
c %---------------------------------------------%
635
c | Copy the last row of the Schur basis matrix |
636
c | to workl(ihbds). This vector will be used |
637
c | to compute the Ritz estimates of converged |
638
c | Ritz values. |
639
c %---------------------------------------------%
640
c
641
call ccopy (ncv, workl(invsub+ncv-1), ldq, workl(ihbds), 1)
642
c
643
c %--------------------------------------------%
644
c | Place the computed eigenvalues of H into D |
645
c | if a spectral transformation was not used. |
646
c %--------------------------------------------%
647
c
648
if (type .eq. 'REGULR') then
649
call ccopy (nconv, workl(iheig), 1, d, 1)
650
end if
651
c
652
c %----------------------------------------------------------%
653
c | Compute the QR factorization of the matrix representing |
654
c | the wanted invariant subspace located in the first NCONV |
655
c | columns of workl(invsub,ldq). |
656
c %----------------------------------------------------------%
657
c
658
call cgeqr2 (ncv, nconv, workl(invsub), ldq, workev,
659
& workev(ncv+1), ierr)
660
c
661
c %--------------------------------------------------------%
662
c | * Postmultiply V by Q using cunm2r. |
663
c | * Copy the first NCONV columns of VQ into Z. |
664
c | * Postmultiply Z by R. |
665
c | The N by NCONV matrix Z is now a matrix representation |
666
c | of the approximate invariant subspace associated with |
667
c | the Ritz values in workl(iheig). The first NCONV |
668
c | columns of V are now approximate Schur vectors |
669
c | associated with the upper triangular matrix of order |
670
c | NCONV in workl(iuptri). |
671
c %--------------------------------------------------------%
672
c
673
call cunm2r ('Right', 'Notranspose', n, ncv, nconv,
674
& workl(invsub), ldq, workev, v, ldv, workd(n+1),
675
& ierr)
676
call clacpy ('All', n, nconv, v, ldv, z, ldz)
677
c
678
do 20 j=1, nconv
679
c
680
c %---------------------------------------------------%
681
c | Perform both a column and row scaling if the |
682
c | diagonal element of workl(invsub,ldq) is negative |
683
c | I'm lazy and don't take advantage of the upper |
684
c | triangular form of workl(iuptri,ldq). |
685
c | Note that since Q is orthogonal, R is a diagonal |
686
c | matrix consisting of plus or minus ones. |
687
c %---------------------------------------------------%
688
c
689
if ( real( workl(invsub+(j-1)*ldq+j-1) ) .lt.
690
& real(zero) ) then
691
call cscal (nconv, -one, workl(iuptri+j-1), ldq)
692
call cscal (nconv, -one, workl(iuptri+(j-1)*ldq), 1)
693
end if
694
c
695
20 continue
696
c
697
if (howmny .eq. 'A') then
698
c
699
c %--------------------------------------------%
700
c | Compute the NCONV wanted eigenvectors of T |
701
c | located in workl(iuptri,ldq). |
702
c %--------------------------------------------%
703
c
704
do 30 j=1, ncv
705
if (j .le. nconv) then
706
select(j) = .true.
707
else
708
select(j) = .false.
709
end if
710
30 continue
711
c
712
call ctrevc ('Right', 'Select', select, ncv, workl(iuptri),
713
& ldq, vl, 1, workl(invsub), ldq, ncv, outncv, workev,
714
& rwork, ierr)
715
c
716
if (ierr .ne. 0) then
717
info = -9
718
go to 9000
719
end if
720
c
721
c %------------------------------------------------%
722
c | Scale the returning eigenvectors so that their |
723
c | Euclidean norms are all one. LAPACK subroutine |
724
c | ctrevc returns each eigenvector normalized so |
725
c | that the element of largest magnitude has |
726
c | magnitude 1. |
727
c %------------------------------------------------%
728
c
729
do 40 j=1, nconv
730
rtemp = scnrm2(ncv, workl(invsub+(j-1)*ldq), 1)
731
rtemp = real(one) / rtemp
732
call csscal ( ncv, rtemp,
733
& workl(invsub+(j-1)*ldq), 1 )
734
c
735
c %------------------------------------------%
736
c | Ritz estimates can be obtained by taking |
737
c | the inner product of the last row of the |
738
c | Schur basis of H with eigenvectors of T. |
739
c | Note that the eigenvector matrix of T is |
740
c | upper triangular, thus the length of the |
741
c | inner product can be set to j. |
742
c %------------------------------------------%
743
c
744
workev(j) = cdotc(j, workl(ihbds), 1,
745
& workl(invsub+(j-1)*ldq), 1)
746
40 continue
747
c
748
if (msglvl .gt. 2) then
749
call ccopy(nconv, workl(invsub+ncv-1), ldq,
750
& workl(ihbds), 1)
751
call cvout (logfil, nconv, workl(ihbds), ndigit,
752
& '_neupd: Last row of the eigenvector matrix for T')
753
if (msglvl .gt. 3) then
754
call cmout (logfil, ncv, ncv, workl(invsub), ldq,
755
& ndigit, '_neupd: The eigenvector matrix for T')
756
end if
757
end if
758
c
759
c %---------------------------------------%
760
c | Copy Ritz estimates into workl(ihbds) |
761
c %---------------------------------------%
762
c
763
call ccopy(nconv, workev, 1, workl(ihbds), 1)
764
c
765
c %----------------------------------------------%
766
c | The eigenvector matrix Q of T is triangular. |
767
c | Form Z*Q. |
768
c %----------------------------------------------%
769
c
770
call ctrmm ('Right', 'Upper', 'No transpose', 'Non-unit',
771
& n, nconv, one, workl(invsub), ldq, z, ldz)
772
c
773
end if
774
c
775
else
776
c
777
c %--------------------------------------------------%
778
c | An approximate invariant subspace is not needed. |
779
c | Place the Ritz values computed CNAUPD into D. |
780
c %--------------------------------------------------%
781
c
782
call ccopy (nconv, workl(ritz), 1, d, 1)
783
call ccopy (nconv, workl(ritz), 1, workl(iheig), 1)
784
call ccopy (nconv, workl(bounds), 1, workl(ihbds), 1)
785
c
786
end if
787
c
788
c %------------------------------------------------%
789
c | Transform the Ritz values and possibly vectors |
790
c | and corresponding error bounds of OP to those |
791
c | of A*x = lambda*B*x. |
792
c %------------------------------------------------%
793
c
794
if (type .eq. 'REGULR') then
795
c
796
if (rvec)
797
& call cscal(ncv, rnorm, workl(ihbds), 1)
798
c
799
else
800
c
801
c %---------------------------------------%
802
c | A spectral transformation was used. |
803
c | * Determine the Ritz estimates of the |
804
c | Ritz values in the original system. |
805
c %---------------------------------------%
806
c
807
if (rvec)
808
& call cscal(ncv, rnorm, workl(ihbds), 1)
809
c
810
do 50 k=1, ncv
811
temp = workl(iheig+k-1)
812
workl(ihbds+k-1) = workl(ihbds+k-1) / temp / temp
813
50 continue
814
c
815
end if
816
c
817
c %-----------------------------------------------------------%
818
c | * Transform the Ritz values back to the original system. |
819
c | For TYPE = 'SHIFTI' the transformation is |
820
c | lambda = 1/theta + sigma |
821
c | NOTES: |
822
c | *The Ritz vectors are not affected by the transformation. |
823
c %-----------------------------------------------------------%
824
c
825
if (type .eq. 'SHIFTI') then
826
do 60 k=1, nconv
827
d(k) = one / workl(iheig+k-1) + sigma
828
60 continue
829
end if
830
c
831
if (type .ne. 'REGULR' .and. msglvl .gt. 1) then
832
call cvout (logfil, nconv, d, ndigit,
833
& '_neupd: Untransformed Ritz values.')
834
call cvout (logfil, nconv, workl(ihbds), ndigit,
835
& '_neupd: Ritz estimates of the untransformed Ritz values.')
836
else if ( msglvl .gt. 1) then
837
call cvout (logfil, nconv, d, ndigit,
838
& '_neupd: Converged Ritz values.')
839
call cvout (logfil, nconv, workl(ihbds), ndigit,
840
& '_neupd: Associated Ritz estimates.')
841
end if
842
c
843
c %-------------------------------------------------%
844
c | Eigenvector Purification step. Formally perform |
845
c | one of inverse subspace iteration. Only used |
846
c | for MODE = 3. See reference 3. |
847
c %-------------------------------------------------%
848
c
849
if (rvec .and. howmny .eq. 'A' .and. type .eq. 'SHIFTI') then
850
c
851
c %------------------------------------------------%
852
c | Purify the computed Ritz vectors by adding a |
853
c | little bit of the residual vector: |
854
c | T |
855
c | resid(:)*( e s ) / theta |
856
c | NCV |
857
c | where H s = s theta. |
858
c %------------------------------------------------%
859
c
860
do 100 j=1, nconv
861
if (workl(iheig+j-1) .ne. zero) then
862
workev(j) = workl(invsub+(j-1)*ldq+ncv-1) /
863
& workl(iheig+j-1)
864
endif
865
100 continue
866
867
c %---------------------------------------%
868
c | Perform a rank one update to Z and |
869
c | purify all the Ritz vectors together. |
870
c %---------------------------------------%
871
c
872
call cgeru (n, nconv, one, resid, 1, workev, 1, z, ldz)
873
c
874
end if
875
c
876
9000 continue
877
c
878
return
879
c
880
c %---------------%
881
c | End of cneupd |
882
c %---------------%
883
c
884
end
885
886