forked from opencollab/arpack-ng
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsseupd.f
867 lines (865 loc) · 33.7 KB
/
sseupd.f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
c\BeginDoc
c
c\Name: sseupd
c
c\Description:
c
c This subroutine returns the converged approximations to eigenvalues
c of A*z = lambda*B*z and (optionally):
c
c (1) the corresponding approximate eigenvectors,
c
c (2) an orthonormal (Lanczos) basis for the associated approximate
c invariant subspace,
c
c (3) Both.
c
c There is negligible additional cost to obtain eigenvectors. An orthonormal
c (Lanczos) basis is always computed. There is an additional storage cost
c of n*nev if both are requested (in this case a separate array Z must be
c supplied).
c
c These quantities are obtained from the Lanczos factorization computed
c by SSAUPD for the linear operator OP prescribed by the MODE selection
c (see IPARAM(7) in SSAUPD documentation.) SSAUPD must be called before
c this routine is called. These approximate eigenvalues and vectors are
c commonly called Ritz values and Ritz vectors respectively. They are
c referred to as such in the comments that follow. The computed orthonormal
c basis for the invariant subspace corresponding to these Ritz values is
c referred to as a Lanczos basis.
c
c See documentation in the header of the subroutine SSAUPD for a definition
c of OP as well as other terms and the relation of computed Ritz values
c and vectors of OP with respect to the given problem A*z = lambda*B*z.
c
c The approximate eigenvalues of the original problem are returned in
c ascending algebraic order. The user may elect to call this routine
c once for each desired Ritz vector and store it peripherally if desired.
c There is also the option of computing a selected set of these vectors
c with a single call.
c
c\Usage:
c call sseupd
c ( RVEC, HOWMNY, SELECT, D, Z, LDZ, SIGMA, BMAT, N, WHICH, NEV, TOL,
c RESID, NCV, V, LDV, IPARAM, IPNTR, WORKD, WORKL, LWORKL, INFO )
c
c RVEC LOGICAL (INPUT)
c Specifies whether Ritz vectors corresponding to the Ritz value
c approximations to the eigenproblem A*z = lambda*B*z are computed.
c
c RVEC = .FALSE. Compute Ritz values only.
c
c RVEC = .TRUE. Compute Ritz vectors.
c
c HOWMNY Character*1 (INPUT)
c Specifies how many Ritz vectors are wanted and the form of Z
c the matrix of Ritz vectors. See remark 1 below.
c = 'A': compute NEV Ritz vectors;
c = 'S': compute some of the Ritz vectors, specified
c by the logical array SELECT.
c
c SELECT Logical array of dimension NCV. (INPUT/WORKSPACE)
c If HOWMNY = 'S', SELECT specifies the Ritz vectors to be
c computed. To select the Ritz vector corresponding to a
c Ritz value D(j), SELECT(j) must be set to .TRUE..
c If HOWMNY = 'A' , SELECT is used as a workspace for
c reordering the Ritz values.
c
c D Real array of dimension NEV. (OUTPUT)
c On exit, D contains the Ritz value approximations to the
c eigenvalues of A*z = lambda*B*z. The values are returned
c in ascending order. If IPARAM(7) = 3,4,5 then D represents
c the Ritz values of OP computed by ssaupd transformed to
c those of the original eigensystem A*z = lambda*B*z. If
c IPARAM(7) = 1,2 then the Ritz values of OP are the same
c as the those of A*z = lambda*B*z.
c
c Z Real N by NEV array if HOWMNY = 'A'. (OUTPUT)
c On exit, Z contains the B-orthonormal Ritz vectors of the
c eigensystem A*z = lambda*B*z corresponding to the Ritz
c value approximations.
c If RVEC = .FALSE. then Z is not referenced.
c NOTE: The array Z may be set equal to first NEV columns of the
c Arnoldi/Lanczos basis array V computed by SSAUPD.
c
c LDZ Integer. (INPUT)
c The leading dimension of the array Z. If Ritz vectors are
c desired, then LDZ .ge. max( 1, N ). In any case, LDZ .ge. 1.
c
c SIGMA Real (INPUT)
c If IPARAM(7) = 3,4,5 represents the shift. Not referenced if
c IPARAM(7) = 1 or 2.
c
c
c **** The remaining arguments MUST be the same as for the ****
c **** call to SSAUPD that was just completed. ****
c
c NOTE: The remaining arguments
c
c BMAT, N, WHICH, NEV, TOL, RESID, NCV, V, LDV, IPARAM, IPNTR,
c WORKD, WORKL, LWORKL, INFO
c
c must be passed directly to SSEUPD following the last call
c to SSAUPD. These arguments MUST NOT BE MODIFIED between
c the the last call to SSAUPD and the call to SSEUPD.
c
c Two of these parameters (WORKL, INFO) are also output parameters:
c
c WORKL Real work array of length LWORKL. (OUTPUT/WORKSPACE)
c WORKL(1:4*ncv) contains information obtained in
c ssaupd. They are not changed by sseupd.
c WORKL(4*ncv+1:ncv*ncv+8*ncv) holds the
c untransformed Ritz values, the computed error estimates,
c and the associated eigenvector matrix of H.
c
c Note: IPNTR(8:10) contains the pointer into WORKL for addresses
c of the above information computed by sseupd.
c -------------------------------------------------------------
c IPNTR(8): pointer to the NCV RITZ values of the original system.
c IPNTR(9): pointer to the NCV corresponding error bounds.
c IPNTR(10): pointer to the NCV by NCV matrix of eigenvectors
c of the tridiagonal matrix T. Only referenced by
c sseupd if RVEC = .TRUE. See Remarks.
c -------------------------------------------------------------
c
c INFO Integer. (OUTPUT)
c Error flag on output.
c = 0: Normal exit.
c = -1: N must be positive.
c = -2: NEV must be positive.
c = -3: NCV must be greater than NEV and less than or equal to N.
c = -5: WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'.
c = -6: BMAT must be one of 'I' or 'G'.
c = -7: Length of private work WORKL array is not sufficient.
c = -8: Error return from trid. eigenvalue calculation;
c Information error from LAPACK routine ssteqr.
c = -9: Starting vector is zero.
c = -10: IPARAM(7) must be 1,2,3,4,5.
c = -11: IPARAM(7) = 1 and BMAT = 'G' are incompatible.
c = -12: NEV and WHICH = 'BE' are incompatible.
c = -14: SSAUPD did not find any eigenvalues to sufficient
c accuracy.
c = -15: HOWMNY must be one of 'A' or 'S' if RVEC = .true.
c = -16: HOWMNY = 'S' not yet implemented
c = -17: SSEUPD got a different count of the number of converged
c Ritz values than SSAUPD got. This indicates the user
c probably made an error in passing data from SSAUPD to
c SSEUPD or that the data was modified before entering
c SSEUPD.
c
c\BeginLib
c
c\References:
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
c pp 357-385.
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
c Restarted Arnoldi Iteration", Rice University Technical Report
c TR95-13, Department of Computational and Applied Mathematics.
c 3. B.N. Parlett, "The Symmetric Eigenvalue Problem". Prentice-Hall,
c 1980.
c 4. B.N. Parlett, B. Nour-Omid, "Towards a Black Box Lanczos Program",
c Computer Physics Communications, 53 (1989), pp 169-179.
c 5. B. Nour-Omid, B.N. Parlett, T. Ericson, P.S. Jensen, "How to
c Implement the Spectral Transformation", Math. Comp., 48 (1987),
c pp 663-673.
c 6. R.G. Grimes, J.G. Lewis and H.D. Simon, "A Shifted Block Lanczos
c Algorithm for Solving Sparse Symmetric Generalized Eigenproblems",
c SIAM J. Matr. Anal. Apps., January (1993).
c 7. L. Reichel, W.B. Gragg, "Algorithm 686: FORTRAN Subroutines
c for Updating the QR decomposition", ACM TOMS, December 1990,
c Volume 16 Number 4, pp 369-377.
c
c\Remarks
c 1. The converged Ritz values are always returned in increasing
c (algebraic) order.
c
c 2. Currently only HOWMNY = 'A' is implemented. It is included at this
c stage for the user who wants to incorporate it.
c
c\Routines called:
c ssesrt ARPACK routine that sorts an array X, and applies the
c corresponding permutation to a matrix A.
c ssortr ssortr ARPACK sorting routine.
c ivout ARPACK utility routine that prints integers.
c svout ARPACK utility routine that prints vectors.
c sgeqr2 LAPACK routine that computes the QR factorization of
c a matrix.
c slacpy LAPACK matrix copy routine.
c slamch LAPACK routine that determines machine constants.
c sorm2r LAPACK routine that applies an orthogonal matrix in
c factored form.
c ssteqr LAPACK routine that computes eigenvalues and eigenvectors
c of a tridiagonal matrix.
c sger Level 2 BLAS rank one update to a matrix.
c scopy Level 1 BLAS that copies one vector to another .
c snrm2 Level 1 BLAS that computes the norm of a vector.
c sscal Level 1 BLAS that scales a vector.
c sswap Level 1 BLAS that swaps the contents of two vectors.
c\Authors
c Danny Sorensen Phuong Vu
c Richard Lehoucq CRPC / Rice University
c Chao Yang Houston, Texas
c Dept. of Computational &
c Applied Mathematics
c Rice University
c Houston, Texas
c
c\Revision history:
c 12/15/93: Version ' 2.1'
c
c\SCCS Information: @(#)
c FILE: seupd.F SID: 2.11 DATE OF SID: 04/10/01 RELEASE: 2
c
c\EndLib
c
c-----------------------------------------------------------------------
subroutine sseupd(rvec , howmny, select, d ,
& z , ldz , sigma , bmat ,
& n , which , nev , tol ,
& resid , ncv , v , ldv ,
& iparam, ipntr , workd , workl,
& lworkl, info )
c
c %----------------------------------------------------%
c | Include files for debugging and timing information |
c %----------------------------------------------------%
c
include 'debug.h'
include 'stat.h'
c
c %------------------%
c | Scalar Arguments |
c %------------------%
c
character bmat, howmny, which*2
logical rvec
integer info, ldz, ldv, lworkl, n, ncv, nev
Real
& sigma, tol
c
c %-----------------%
c | Array Arguments |
c %-----------------%
c
integer iparam(7), ipntr(11)
logical select(ncv)
Real
& d(nev) , resid(n) , v(ldv,ncv),
& z(ldz, nev), workd(2*n), workl(lworkl)
c
c %------------%
c | Parameters |
c %------------%
c
Real
& one, zero
parameter (one = 1.0E+0 , zero = 0.0E+0 )
c
c %---------------%
c | Local Scalars |
c %---------------%
c
character type*6
integer bounds , ierr , ih , ihb , ihd ,
& iq , iw , j , k , ldh ,
& ldq , mode , msglvl, nconv , next ,
& ritz , irz , ibd , np , ishift,
& leftptr, rghtptr, numcnv, jj
Real
& bnorm2 , rnorm, temp, temp1, eps23
logical reord
c
c %----------------------%
c | External Subroutines |
c %----------------------%
c
external scopy , sger , sgeqr2, slacpy, sorm2r, sscal,
& ssesrt, ssteqr, sswap , svout , ivout , ssortr
c
c %--------------------%
c | External Functions |
c %--------------------%
c
Real
& snrm2, slamch
external snrm2, slamch
c
c %---------------------%
c | Intrinsic Functions |
c %---------------------%
c
intrinsic min
c
c %-----------------------%
c | Executable Statements |
c %-----------------------%
c
c %------------------------%
c | Set default parameters |
c %------------------------%
c
msglvl = mseupd
mode = iparam(7)
nconv = iparam(5)
info = 0
c
c %--------------%
c | Quick return |
c %--------------%
c
if (nconv .eq. 0) go to 9000
ierr = 0
c
if (nconv .le. 0) ierr = -14
if (n .le. 0) ierr = -1
if (nev .le. 0) ierr = -2
if (ncv .le. nev .or. ncv .gt. n) ierr = -3
if (which .ne. 'LM' .and.
& which .ne. 'SM' .and.
& which .ne. 'LA' .and.
& which .ne. 'SA' .and.
& which .ne. 'BE') ierr = -5
if (bmat .ne. 'I' .and. bmat .ne. 'G') ierr = -6
if ( (howmny .ne. 'A' .and.
& howmny .ne. 'P' .and.
& howmny .ne. 'S') .and. rvec )
& ierr = -15
if (rvec .and. howmny .eq. 'S') ierr = -16
c
if (rvec .and. lworkl .lt. ncv**2+8*ncv) ierr = -7
c
if (mode .eq. 1 .or. mode .eq. 2) then
type = 'REGULR'
else if (mode .eq. 3 ) then
type = 'SHIFTI'
else if (mode .eq. 4 ) then
type = 'BUCKLE'
else if (mode .eq. 5 ) then
type = 'CAYLEY'
else
ierr = -10
end if
if (mode .eq. 1 .and. bmat .eq. 'G') ierr = -11
if (nev .eq. 1 .and. which .eq. 'BE') ierr = -12
c
c %------------%
c | Error Exit |
c %------------%
c
if (ierr .ne. 0) then
info = ierr
go to 9000
end if
c
c %-------------------------------------------------------%
c | Pointer into WORKL for address of H, RITZ, BOUNDS, Q |
c | etc... and the remaining workspace. |
c | Also update pointer to be used on output. |
c | Memory is laid out as follows: |
c | workl(1:2*ncv) := generated tridiagonal matrix H |
c | The subdiagonal is stored in workl(2:ncv). |
c | The dead spot is workl(1) but upon exiting |
c | ssaupd stores the B-norm of the last residual |
c | vector in workl(1). We use this !!! |
c | workl(2*ncv+1:2*ncv+ncv) := ritz values |
c | The wanted values are in the first NCONV spots. |
c | workl(3*ncv+1:3*ncv+ncv) := computed Ritz estimates |
c | The wanted values are in the first NCONV spots. |
c | NOTE: workl(1:4*ncv) is set by ssaupd and is not |
c | modified by sseupd. |
c %-------------------------------------------------------%
c
c %-------------------------------------------------------%
c | The following is used and set by sseupd. |
c | workl(4*ncv+1:4*ncv+ncv) := used as workspace during |
c | computation of the eigenvectors of H. Stores |
c | the diagonal of H. Upon EXIT contains the NCV |
c | Ritz values of the original system. The first |
c | NCONV spots have the wanted values. If MODE = |
c | 1 or 2 then will equal workl(2*ncv+1:3*ncv). |
c | workl(5*ncv+1:5*ncv+ncv) := used as workspace during |
c | computation of the eigenvectors of H. Stores |
c | the subdiagonal of H. Upon EXIT contains the |
c | NCV corresponding Ritz estimates of the |
c | original system. The first NCONV spots have the |
c | wanted values. If MODE = 1,2 then will equal |
c | workl(3*ncv+1:4*ncv). |
c | workl(6*ncv+1:6*ncv+ncv*ncv) := orthogonal Q that is |
c | the eigenvector matrix for H as returned by |
c | ssteqr. Not referenced if RVEC = .False. |
c | Ordering follows that of workl(4*ncv+1:5*ncv) |
c | workl(6*ncv+ncv*ncv+1:6*ncv+ncv*ncv+2*ncv) := |
c | Workspace. Needed by ssteqr and by sseupd. |
c | GRAND total of NCV*(NCV+8) locations. |
c %-------------------------------------------------------%
c
c
ih = ipntr(5)
ritz = ipntr(6)
bounds = ipntr(7)
ldh = ncv
ldq = ncv
ihd = bounds + ldh
ihb = ihd + ldh
iq = ihb + ldh
iw = iq + ldh*ncv
next = iw + 2*ncv
ipntr(4) = next
ipntr(8) = ihd
ipntr(9) = ihb
ipntr(10) = iq
c
c %----------------------------------------%
c | irz points to the Ritz values computed |
c | by _seigt before exiting _saup2. |
c | ibd points to the Ritz estimates |
c | computed by _seigt before exiting |
c | _saup2. |
c %----------------------------------------%
c
irz = ipntr(11)+ncv
ibd = irz+ncv
c
c
c %---------------------------------%
c | Set machine dependent constant. |
c %---------------------------------%
c
eps23 = slamch('Epsilon-Machine')
eps23 = eps23**(2.0E+0 / 3.0E+0 )
c
c %---------------------------------------%
c | RNORM is B-norm of the RESID(1:N). |
c | BNORM2 is the 2 norm of B*RESID(1:N). |
c | Upon exit of ssaupd WORKD(1:N) has |
c | B*RESID(1:N). |
c %---------------------------------------%
c
rnorm = workl(ih)
if (bmat .eq. 'I') then
bnorm2 = rnorm
else if (bmat .eq. 'G') then
bnorm2 = snrm2(n, workd, 1)
end if
c
if (msglvl .gt. 2) then
call svout(logfil, ncv, workl(irz), ndigit,
& '_seupd: Ritz values passed in from _SAUPD.')
call svout(logfil, ncv, workl(ibd), ndigit,
& '_seupd: Ritz estimates passed in from _SAUPD.')
end if
c
if (rvec) then
c
reord = .false.
c
c %---------------------------------------------------%
c | Use the temporary bounds array to store indices |
c | These will be used to mark the select array later |
c %---------------------------------------------------%
c
do 10 j = 1,ncv
workl(bounds+j-1) = j
select(j) = .false.
10 continue
c
c %-------------------------------------%
c | Select the wanted Ritz values. |
c | Sort the Ritz values so that the |
c | wanted ones appear at the tailing |
c | NEV positions of workl(irr) and |
c | workl(iri). Move the corresponding |
c | error estimates in workl(bound) |
c | accordingly. |
c %-------------------------------------%
c
np = ncv - nev
ishift = 0
call ssgets(ishift, which , nev ,
& np , workl(irz) , workl(bounds),
& workl)
c
if (msglvl .gt. 2) then
call svout(logfil, ncv, workl(irz), ndigit,
& '_seupd: Ritz values after calling _SGETS.')
call svout(logfil, ncv, workl(bounds), ndigit,
& '_seupd: Ritz value indices after calling _SGETS.')
end if
c
c %-----------------------------------------------------%
c | Record indices of the converged wanted Ritz values |
c | Mark the select array for possible reordering |
c %-----------------------------------------------------%
c
numcnv = 0
do 11 j = 1,ncv
temp1 = max(eps23, abs(workl(irz+ncv-j)) )
jj = workl(bounds + ncv - j)
if (numcnv .lt. nconv .and.
& workl(ibd+jj-1) .le. tol*temp1) then
select(jj) = .true.
numcnv = numcnv + 1
if (jj .gt. nconv) reord = .true.
endif
11 continue
c
c %-----------------------------------------------------------%
c | Check the count (numcnv) of converged Ritz values with |
c | the number (nconv) reported by _saupd. If these two |
c | are different then there has probably been an error |
c | caused by incorrect passing of the _saupd data. |
c %-----------------------------------------------------------%
c
if (msglvl .gt. 2) then
call ivout(logfil, 1, [numcnv], ndigit,
& '_seupd: Number of specified eigenvalues')
call ivout(logfil, 1, [nconv], ndigit,
& '_seupd: Number of "converged" eigenvalues')
end if
c
if (numcnv .ne. nconv) then
info = -17
go to 9000
end if
c
c %-----------------------------------------------------------%
c | Call LAPACK routine _steqr to compute the eigenvalues and |
c | eigenvectors of the final symmetric tridiagonal matrix H. |
c | Initialize the eigenvector matrix Q to the identity. |
c %-----------------------------------------------------------%
c
call scopy(ncv-1, workl(ih+1), 1, workl(ihb), 1)
call scopy(ncv, workl(ih+ldh), 1, workl(ihd), 1)
c
call ssteqr('Identity', ncv, workl(ihd), workl(ihb),
& workl(iq) , ldq, workl(iw), ierr)
c
if (ierr .ne. 0) then
info = -8
go to 9000
end if
c
if (msglvl .gt. 1) then
call scopy(ncv, workl(iq+ncv-1), ldq, workl(iw), 1)
call svout(logfil, ncv, workl(ihd), ndigit,
& '_seupd: NCV Ritz values of the final H matrix')
call svout(logfil, ncv, workl(iw), ndigit,
& '_seupd: last row of the eigenvector matrix for H')
end if
c
if (reord) then
c
c %---------------------------------------------%
c | Reordered the eigenvalues and eigenvectors |
c | computed by _steqr so that the "converged" |
c | eigenvalues appear in the first NCONV |
c | positions of workl(ihd), and the associated |
c | eigenvectors appear in the first NCONV |
c | columns. |
c %---------------------------------------------%
c
leftptr = 1
rghtptr = ncv
c
if (ncv .eq. 1) go to 30
c
20 if (select(leftptr)) then
c
c %-------------------------------------------%
c | Search, from the left, for the first Ritz |
c | value that has not converged. |
c %-------------------------------------------%
c
leftptr = leftptr + 1
c
else if ( .not. select(rghtptr)) then
c
c %----------------------------------------------%
c | Search, from the right, the first Ritz value |
c | that has converged. |
c %----------------------------------------------%
c
rghtptr = rghtptr - 1
c
else
c
c %----------------------------------------------%
c | Swap the Ritz value on the left that has not |
c | converged with the Ritz value on the right |
c | that has converged. Swap the associated |
c | eigenvector of the tridiagonal matrix H as |
c | well. |
c %----------------------------------------------%
c
temp = workl(ihd+leftptr-1)
workl(ihd+leftptr-1) = workl(ihd+rghtptr-1)
workl(ihd+rghtptr-1) = temp
call scopy(ncv, workl(iq+ncv*(leftptr-1)), 1,
& workl(iw), 1)
call scopy(ncv, workl(iq+ncv*(rghtptr-1)), 1,
& workl(iq+ncv*(leftptr-1)), 1)
call scopy(ncv, workl(iw), 1,
& workl(iq+ncv*(rghtptr-1)), 1)
leftptr = leftptr + 1
rghtptr = rghtptr - 1
c
end if
c
if (leftptr .lt. rghtptr) go to 20
c
end if
c
30 if (msglvl .gt. 2) then
call svout (logfil, ncv, workl(ihd), ndigit,
& '_seupd: The eigenvalues of H--reordered')
end if
c
c %----------------------------------------%
c | Load the converged Ritz values into D. |
c %----------------------------------------%
c
call scopy(nconv, workl(ihd), 1, d, 1)
c
else
c
c %-----------------------------------------------------%
c | Ritz vectors not required. Load Ritz values into D. |
c %-----------------------------------------------------%
c
call scopy(nconv, workl(ritz), 1, d, 1)
call scopy(ncv, workl(ritz), 1, workl(ihd), 1)
c
end if
c
c %------------------------------------------------------------------%
c | Transform the Ritz values and possibly vectors and corresponding |
c | Ritz estimates of OP to those of A*x=lambda*B*x. The Ritz values |
c | (and corresponding data) are returned in ascending order. |
c %------------------------------------------------------------------%
c
if (type .eq. 'REGULR') then
c
c %---------------------------------------------------------%
c | Ascending sort of wanted Ritz values, vectors and error |
c | bounds. Not necessary if only Ritz values are desired. |
c %---------------------------------------------------------%
c
if (rvec) then
call ssesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq)
else
call scopy(ncv, workl(bounds), 1, workl(ihb), 1)
end if
c
else
c
c %-------------------------------------------------------------%
c | * Make a copy of all the Ritz values. |
c | * Transform the Ritz values back to the original system. |
c | For TYPE = 'SHIFTI' the transformation is |
c | lambda = 1/theta + sigma |
c | For TYPE = 'BUCKLE' the transformation is |
c | lambda = sigma * theta / ( theta - 1 ) |
c | For TYPE = 'CAYLEY' the transformation is |
c | lambda = sigma * (theta + 1) / (theta - 1 ) |
c | where the theta are the Ritz values returned by ssaupd. |
c | NOTES: |
c | *The Ritz vectors are not affected by the transformation. |
c | They are only reordered. |
c %-------------------------------------------------------------%
c
call scopy (ncv, workl(ihd), 1, workl(iw), 1)
if (type .eq. 'SHIFTI') then
do 40 k=1, ncv
workl(ihd+k-1) = one / workl(ihd+k-1) + sigma
40 continue
else if (type .eq. 'BUCKLE') then
do 50 k=1, ncv
workl(ihd+k-1) = sigma * workl(ihd+k-1) /
& (workl(ihd+k-1) - one)
50 continue
else if (type .eq. 'CAYLEY') then
do 60 k=1, ncv
workl(ihd+k-1) = sigma * (workl(ihd+k-1) + one) /
& (workl(ihd+k-1) - one)
60 continue
end if
c
c %-------------------------------------------------------------%
c | * Store the wanted NCONV lambda values into D. |
c | * Sort the NCONV wanted lambda in WORKL(IHD:IHD+NCONV-1) |
c | into ascending order and apply sort to the NCONV theta |
c | values in the transformed system. We will need this to |
c | compute Ritz estimates in the original system. |
c | * Finally sort the lambda`s into ascending order and apply |
c | to Ritz vectors if wanted. Else just sort lambda`s into |
c | ascending order. |
c | NOTES: |
c | *workl(iw:iw+ncv-1) contain the theta ordered so that they |
c | match the ordering of the lambda. We`ll use them again for |
c | Ritz vector purification. |
c %-------------------------------------------------------------%
c
call scopy(nconv, workl(ihd), 1, d, 1)
call ssortr('LA', .true., nconv, workl(ihd), workl(iw))
if (rvec) then
call ssesrt('LA', rvec , nconv, d, ncv, workl(iq), ldq)
else
call scopy(ncv, workl(bounds), 1, workl(ihb), 1)
call sscal(ncv, bnorm2/rnorm, workl(ihb), 1)
call ssortr('LA', .true., nconv, d, workl(ihb))
end if
c
end if
c
c %------------------------------------------------%
c | Compute the Ritz vectors. Transform the wanted |
c | eigenvectors of the symmetric tridiagonal H by |
c | the Lanczos basis matrix V. |
c %------------------------------------------------%
c
if (rvec .and. howmny .eq. 'A') then
c
c %----------------------------------------------------------%
c | Compute the QR factorization of the matrix representing |
c | the wanted invariant subspace located in the first NCONV |
c | columns of workl(iq,ldq). |
c %----------------------------------------------------------%
c
call sgeqr2(ncv, nconv , workl(iq) ,
& ldq, workl(iw+ncv), workl(ihb),
& ierr)
c
c %--------------------------------------------------------%
c | * Postmultiply V by Q. |
c | * Copy the first NCONV columns of VQ into Z. |
c | The N by NCONV matrix Z is now a matrix representation |
c | of the approximate invariant subspace associated with |
c | the Ritz values in workl(ihd). |
c %--------------------------------------------------------%
c
call sorm2r('Right', 'Notranspose', n ,
& ncv , nconv , workl(iq),
& ldq , workl(iw+ncv), v ,
& ldv , workd(n+1) , ierr)
call slacpy('All', n, nconv, v, ldv, z, ldz)
c
c %-----------------------------------------------------%
c | In order to compute the Ritz estimates for the Ritz |
c | values in both systems, need the last row of the |
c | eigenvector matrix. Remember, it`s in factored form |
c %-----------------------------------------------------%
c
do 65 j = 1, ncv-1
workl(ihb+j-1) = zero
65 continue
workl(ihb+ncv-1) = one
call sorm2r('Left', 'Transpose' , ncv ,
& 1 , nconv , workl(iq) ,
& ldq , workl(iw+ncv), workl(ihb),
& ncv , temp , ierr)
c
c %-----------------------------------------------------%
c | Make a copy of the last row into |
c | workl(iw+ncv:iw+2*ncv), as it is needed again in |
c | the Ritz vector purification step below |
c %-----------------------------------------------------%
c
do 67 j = 1, nconv
workl(iw+ncv+j-1) = workl(ihb+j-1)
67 continue
else if (rvec .and. howmny .eq. 'S') then
c
c Not yet implemented. See remark 2 above.
c
end if
c
if (type .eq. 'REGULR' .and. rvec) then
c
do 70 j=1, ncv
workl(ihb+j-1) = rnorm * abs( workl(ihb+j-1) )
70 continue
c
else if (type .ne. 'REGULR' .and. rvec) then
c
c %-------------------------------------------------%
c | * Determine Ritz estimates of the theta. |
c | If RVEC = .true. then compute Ritz estimates |
c | of the theta. |
c | If RVEC = .false. then copy Ritz estimates |
c | as computed by ssaupd. |
c | * Determine Ritz estimates of the lambda. |
c %-------------------------------------------------%
c
call sscal (ncv, bnorm2, workl(ihb), 1)
if (type .eq. 'SHIFTI') then
c
do 80 k=1, ncv
workl(ihb+k-1) = abs( workl(ihb+k-1) )
& / workl(iw+k-1)**2
80 continue
c
else if (type .eq. 'BUCKLE') then
c
do 90 k=1, ncv
workl(ihb+k-1) = sigma * abs( workl(ihb+k-1) )
& / (workl(iw+k-1)-one )**2
90 continue
c
else if (type .eq. 'CAYLEY') then
c
do 100 k=1, ncv
workl(ihb+k-1) = abs( workl(ihb+k-1)
& / workl(iw+k-1)*(workl(iw+k-1)-one) )
100 continue
c
end if
c
end if
c
if (type .ne. 'REGULR' .and. msglvl .gt. 1) then
call svout(logfil, nconv, d, ndigit,
& '_seupd: Untransformed converged Ritz values')
call svout(logfil, nconv, workl(ihb), ndigit,
& '_seupd: Ritz estimates of the untransformed Ritz values')
else if (msglvl .gt. 1) then
call svout(logfil, nconv, d, ndigit,
& '_seupd: Converged Ritz values')
call svout(logfil, nconv, workl(ihb), ndigit,
& '_seupd: Associated Ritz estimates')
end if
c
c %-------------------------------------------------%
c | Ritz vector purification step. Formally perform |
c | one of inverse subspace iteration. Only used |
c | for MODE = 3,4,5. See reference 7 |
c %-------------------------------------------------%
c
if (rvec .and. (type .eq. 'SHIFTI' .or. type .eq. 'CAYLEY')) then
c
do 110 k=0, nconv-1
workl(iw+k) = workl(iw+ncv+k)
& / 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(iw+ncv+k)
& / (workl(iw+k)-one)
120 continue
c
end if
c
if (type .ne. 'REGULR')
& call sger (n, nconv, one, resid, 1, workl(iw), 1, z, ldz)
c
9000 continue
c
return
c
c %---------------%
c | End of sseupd|
c %---------------%
c
end