6
c Intermediate level interface called by snaupd.
10
c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD,
11
c ISHIFT, MXITER, V, LDV, H, LDH, RITZR, RITZI, BOUNDS,
12
c Q, LDQ, WORKL, IPNTR, WORKD, INFO )
16
c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in snaupd.
17
c MODE, ISHIFT, MXITER: see the definition of IPARAM in snaupd.
19
c NP Integer. (INPUT/OUTPUT)
20
c Contains the number of implicit shifts to apply during
21
c each Arnoldi iteration.
22
c If ISHIFT=1, NP is adjusted dynamically at each iteration
23
c to accelerate convergence and prevent stagnation.
24
c This is also roughly equal to the number of matrix-vector
25
c products (involving the operator OP) per Arnoldi iteration.
26
c The logic for adjusting is contained within the current
28
c If ISHIFT=0, NP is the number of shifts the user needs
29
c to provide via reverse comunication. 0 < NP < NCV-NEV.
30
c NP may be less than NCV-NEV for two reasons. The first, is
31
c to keep complex conjugate pairs of "wanted" Ritz values
32
c together. The second, is that a leading block of the current
33
c upper Hessenberg matrix has split off and contains "unwanted"
35
c Upon termination of the IRA iteration, NP contains the number
36
c of "converged" wanted Ritz values.
38
c IUPD Integer. (INPUT)
39
c IUPD .EQ. 0: use explicit restart instead implicit update.
40
c IUPD .NE. 0: use implicit update.
42
c V Real N by (NEV+NP) array. (INPUT/OUTPUT)
43
c The Arnoldi basis vectors are returned in the first NEV
46
c LDV Integer. (INPUT)
47
c Leading dimension of V exactly as declared in the calling
50
c H Real (NEV+NP) by (NEV+NP) array. (OUTPUT)
51
c H is used to store the generated upper Hessenberg matrix
53
c LDH Integer. (INPUT)
54
c Leading dimension of H exactly as declared in the calling
57
c RITZR, Real arrays of length NEV+NP. (OUTPUT)
58
c RITZI RITZR(1:NEV) (resp. RITZI(1:NEV)) contains the real (resp.
59
c imaginary) part of the computed Ritz values of OP.
61
c BOUNDS Real array of length NEV+NP. (OUTPUT)
62
c BOUNDS(1:NEV) contain the error bounds corresponding to
63
c the computed Ritz values.
65
c Q Real (NEV+NP) by (NEV+NP) array. (WORKSPACE)
66
c Private (replicated) work array used to accumulate the
67
c rotation in the shift application step.
69
c LDQ Integer. (INPUT)
70
c Leading dimension of Q exactly as declared in the calling
73
c WORKL Real work array of length at least
74
c (NEV+NP)**2 + 3*(NEV+NP). (INPUT/WORKSPACE)
75
c Private (replicated) array on each PE or array allocated on
76
c the front end. It is used in shifts calculation, shifts
77
c application and convergence checking.
79
c On exit, the last 3*(NEV+NP) locations of WORKL contain
80
c the Ritz values (real,imaginary) and associated Ritz
81
c estimates of the current Hessenberg matrix. They are
82
c listed in the same order as returned from sneigh.
84
c If ISHIFT .EQ. O and IDO .EQ. 3, the first 2*NP locations
85
c of WORKL are used in reverse communication to hold the user
88
c IPNTR Integer array of length 3. (OUTPUT)
89
c Pointer to mark the starting locations in the WORKD for
90
c vectors used by the Arnoldi iteration.
91
c -------------------------------------------------------------
92
c IPNTR(1): pointer to the current operand vector X.
93
c IPNTR(2): pointer to the current result vector Y.
94
c IPNTR(3): pointer to the vector B * X when used in the
95
c shift-and-invert mode. X is the current operand.
96
c -------------------------------------------------------------
98
c WORKD Real work array of length 3*N. (WORKSPACE)
99
c Distributed array to be used in the basic Arnoldi iteration
100
c for reverse communication. The user should not use WORKD
101
c as temporary workspace during the iteration !!!!!!!!!!
102
c See Data Distribution Note in DNAUPD.
104
c INFO Integer. (INPUT/OUTPUT)
105
c If INFO .EQ. 0, a randomly initial residual vector is used.
106
c If INFO .NE. 0, RESID contains the initial residual vector,
107
c possibly from a previous run.
108
c Error flag on output.
109
c = 0: Normal return.
110
c = 1: Maximum number of iterations taken.
111
c All possible eigenvalues of OP has been found.
112
c NP returns the number of converged Ritz values.
113
c = 2: No shifts could be applied.
114
c = -8: Error return from LAPACK eigenvalue calculation;
115
c This should never happen.
116
c = -9: Starting vector is zero.
117
c = -9999: Could not build an Arnoldi factorization.
118
c Size that was built in returned in NP.
122
c-----------------------------------------------------------------------
130
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
131
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
133
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
134
c Restarted Arnoldi Iteration", Rice University Technical Report
135
c TR95-13, Department of Computational and Applied Mathematics.
138
c sgetv0 ARPACK initial vector generation routine.
139
c snaitr ARPACK Arnoldi factorization routine.
140
c snapps ARPACK application of implicit shifts routine.
141
c snconv ARPACK convergence of Ritz values routine.
142
c sneigh ARPACK compute Ritz values and error bounds routine.
143
c sngets ARPACK reorder Ritz values and error bounds routine.
144
c ssortc ARPACK sorting routine.
145
c ivout ARPACK utility routine that prints integers.
146
c second ARPACK utility routine for timing.
147
c smout ARPACK utility routine that prints matrices
148
c svout ARPACK utility routine that prints vectors.
149
c slamch LAPACK routine that determines machine constants.
150
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
151
c scopy Level 1 BLAS that copies one vector to another .
152
c sdot Level 1 BLAS that computes the scalar product of two vectors.
153
c snrm2 Level 1 BLAS that computes the norm of a vector.
154
c sswap Level 1 BLAS that swaps two vectors.
157
c Danny Sorensen Phuong Vu
158
c Richard Lehoucq CRPC / Rice University
159
c Dept. of Computational & Houston, Texas
160
c Applied Mathematics
164
c\SCCS Information: @(#)
165
c FILE: naup2.F SID: 2.8 DATE OF SID: 10/17/00 RELEASE: 2
172
c-----------------------------------------------------------------------
175
& ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd,
176
& ishift, mxiter, v, ldv, h, ldh, ritzr, ritzi, bounds,
177
& q, ldq, workl, ipntr, workd, info )
179
c %----------------------------------------------------%
180
c | Include files for debugging and timing information |
181
c %----------------------------------------------------%
186
c %------------------%
187
c | Scalar Arguments |
188
c %------------------%
190
character bmat*1, which*2
191
integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter,
196
c %-----------------%
197
c | Array Arguments |
198
c %-----------------%
202
& bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np), resid(n),
203
& ritzi(nev+np), ritzr(nev+np), v(ldv,nev+np),
204
& workd(3*n), workl( (nev+np)*(nev+np+3) )
212
parameter (one = 1.0E+0, zero = 0.0E+0)
219
logical cnorm , getv0, initv, update, ushift
220
integer ierr , iter , j , kplusp, msglvl, nconv,
221
& nevbef, nev0 , np0 , nptemp, numcnv
223
& rnorm , temp , eps23
224
save cnorm , getv0, initv, update, ushift,
225
& rnorm , iter , eps23, kplusp, msglvl, nconv ,
226
& nevbef, nev0 , np0 , numcnv
228
c %-----------------------%
229
c | Local array arguments |
230
c %-----------------------%
234
c %----------------------%
235
c | External Subroutines |
236
c %----------------------%
238
external scopy , sgetv0, snaitr, snconv, sneigh,
239
& sngets, snapps, svout , ivout , second
241
c %--------------------%
242
c | External Functions |
243
c %--------------------%
246
& sdot, snrm2, slapy2, slamch
247
external sdot, snrm2, slapy2, slamch
249
c %---------------------%
250
c | Intrinsic Functions |
251
c %---------------------%
253
intrinsic min, max, abs, sqrt
255
c %-----------------------%
256
c | Executable Statements |
257
c %-----------------------%
265
c %-------------------------------------%
266
c | Get the machine dependent constant. |
267
c %-------------------------------------%
269
eps23 = slamch('Epsilon-Machine')
270
eps23 = eps23**(2.0E+0 / 3.0E+0)
275
c %-------------------------------------%
276
c | kplusp is the bound on the largest |
277
c | Lanczos factorization built. |
278
c | nconv is the current number of |
279
c | "converged" eigenvlues. |
280
c | iter is the counter on the current |
281
c | iteration step. |
282
c %-------------------------------------%
288
c %---------------------------------------%
289
c | Set flags for computing the first NEV |
290
c | steps of the Arnoldi factorization. |
291
c %---------------------------------------%
298
if (info .ne. 0) then
300
c %--------------------------------------------%
301
c | User provides the initial residual vector. |
302
c %--------------------------------------------%
311
c %---------------------------------------------%
312
c | Get a possibly random starting vector and |
313
c | force it into the range of the operator OP. |
314
c %---------------------------------------------%
319
call sgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm,
320
& ipntr, workd, info)
322
if (ido .ne. 99) go to 9000
324
if (rnorm .eq. zero) then
326
c %-----------------------------------------%
327
c | The initial vector is zero. Error exit. |
328
c %-----------------------------------------%
337
c %-----------------------------------%
338
c | Back from reverse communication : |
339
c | continue with update step |
340
c %-----------------------------------%
344
c %-------------------------------------------%
345
c | Back from computing user specified shifts |
346
c %-------------------------------------------%
350
c %-------------------------------------%
351
c | Back from computing residual norm |
352
c | at the end of the current iteration |
353
c %-------------------------------------%
357
c %----------------------------------------------------------%
358
c | Compute the first NEV steps of the Arnoldi factorization |
359
c %----------------------------------------------------------%
361
call snaitr (ido, bmat, n, 0, nev, mode, resid, rnorm, v, ldv,
362
& h, ldh, ipntr, workd, info)
364
c %---------------------------------------------------%
365
c | ido .ne. 99 implies use of reverse communication |
366
c | to compute operations involving OP and possibly B |
367
c %---------------------------------------------------%
369
if (ido .ne. 99) go to 9000
371
if (info .gt. 0) then
378
c %--------------------------------------------------------------%
380
c | M A I N ARNOLDI I T E R A T I O N L O O P |
381
c | Each iteration implicitly restarts the Arnoldi |
382
c | factorization in place. |
384
c %--------------------------------------------------------------%
390
if (msglvl .gt. 0) then
391
call ivout (logfil, 1, iter, ndigit,
392
& '_naup2: **** Start of major iteration number ****')
395
c %-----------------------------------------------------------%
396
c | Compute NP additional steps of the Arnoldi factorization. |
397
c | Adjust NP since NEV might have been updated by last call |
398
c | to the shift application routine snapps. |
399
c %-----------------------------------------------------------%
403
if (msglvl .gt. 1) then
404
call ivout (logfil, 1, nev, ndigit,
405
& '_naup2: The length of the current Arnoldi factorization')
406
call ivout (logfil, 1, np, ndigit,
407
& '_naup2: Extend the Arnoldi factorization by')
410
c %-----------------------------------------------------------%
411
c | Compute NP additional steps of the Arnoldi factorization. |
412
c %-----------------------------------------------------------%
418
call snaitr (ido , bmat, n , nev, np , mode , resid,
419
& rnorm, v , ldv, h , ldh, ipntr, workd,
422
c %---------------------------------------------------%
423
c | ido .ne. 99 implies use of reverse communication |
424
c | to compute operations involving OP and possibly B |
425
c %---------------------------------------------------%
427
if (ido .ne. 99) go to 9000
429
if (info .gt. 0) then
437
if (msglvl .gt. 1) then
438
call svout (logfil, 1, rnorm, ndigit,
439
& '_naup2: Corresponding B-norm of the residual')
442
c %--------------------------------------------------------%
443
c | Compute the eigenvalues and corresponding error bounds |
444
c | of the current upper Hessenberg matrix. |
445
c %--------------------------------------------------------%
447
call sneigh (rnorm, kplusp, h, ldh, ritzr, ritzi, bounds,
448
& q, ldq, workl, ierr)
450
if (ierr .ne. 0) then
455
c %----------------------------------------------------%
456
c | Make a copy of eigenvalues and corresponding error |
457
c | bounds obtained from sneigh. |
458
c %----------------------------------------------------%
460
call scopy(kplusp, ritzr, 1, workl(kplusp**2+1), 1)
461
call scopy(kplusp, ritzi, 1, workl(kplusp**2+kplusp+1), 1)
462
call scopy(kplusp, bounds, 1, workl(kplusp**2+2*kplusp+1), 1)
464
c %---------------------------------------------------%
465
c | Select the wanted Ritz values and their bounds |
466
c | to be used in the convergence test. |
467
c | The wanted part of the spectrum and corresponding |
468
c | error bounds are in the last NEV loc. of RITZR, |
469
c | RITZI and BOUNDS respectively. The variables NEV |
470
c | and NP may be updated if the NEV-th wanted Ritz |
471
c | value has a non zero imaginary part. In this case |
472
c | NEV is increased by one and NP decreased by one. |
473
c | NOTE: The last two arguments of sngets are no |
474
c | longer used as of version 2.1. |
475
c %---------------------------------------------------%
480
call sngets (ishift, which, nev, np, ritzr, ritzi,
481
& bounds, workl, workl(np+1))
482
if (nev .eq. nev0+1) numcnv = nev0+1
484
c %-------------------%
485
c | Convergence test. |
486
c %-------------------%
488
call scopy (nev, bounds(np+1), 1, workl(2*np+1), 1)
489
call snconv (nev, ritzr(np+1), ritzi(np+1), workl(2*np+1),
492
if (msglvl .gt. 2) then
497
call ivout (logfil, 4, kp, ndigit,
498
& '_naup2: NEV, NP, NUMCNV, NCONV are')
499
call svout (logfil, kplusp, ritzr, ndigit,
500
& '_naup2: Real part of the eigenvalues of H')
501
call svout (logfil, kplusp, ritzi, ndigit,
502
& '_naup2: Imaginary part of the eigenvalues of H')
503
call svout (logfil, kplusp, bounds, ndigit,
504
& '_naup2: Ritz estimates of the current NCV Ritz values')
507
c %---------------------------------------------------------%
508
c | Count the number of unwanted Ritz values that have zero |
509
c | Ritz estimates. If any Ritz estimates are equal to zero |
510
c | then a leading block of H of order equal to at least |
511
c | the number of Ritz values with zero Ritz estimates has |
512
c | split off. None of these Ritz values may be removed by |
513
c | shifting. Decrease NP the number of shifts to apply. If |
514
c | no shifts may be applied, then prepare to exit |
515
c %---------------------------------------------------------%
519
if (bounds(j) .eq. zero) then
525
if ( (nconv .ge. numcnv) .or.
526
& (iter .gt. mxiter) .or.
529
if (msglvl .gt. 4) then
530
call svout(logfil, kplusp, workl(kplusp**2+1), ndigit,
531
& '_naup2: Real part of the eig computed by _neigh:')
532
call svout(logfil, kplusp, workl(kplusp**2+kplusp+1),
534
& '_naup2: Imag part of the eig computed by _neigh:')
535
call svout(logfil, kplusp, workl(kplusp**2+kplusp*2+1),
537
& '_naup2: Ritz eistmates computed by _neigh:')
540
c %------------------------------------------------%
541
c | Prepare to exit. Put the converged Ritz values |
542
c | and corresponding bounds in RITZ(1:NCONV) and |
543
c | BOUNDS(1:NCONV) respectively. Then sort. Be |
544
c | careful when NCONV > NP |
545
c %------------------------------------------------%
547
c %------------------------------------------%
548
c | Use h( 3,1 ) as storage to communicate |
549
c | rnorm to _neupd if needed |
550
c %------------------------------------------%
554
c %----------------------------------------------%
555
c | To be consistent with sngets, we first do a |
556
c | pre-processing sort in order to keep complex |
557
c | conjugate pairs together. This is similar |
558
c | to the pre-processing sort used in sngets |
559
c | except that the sort is done in the opposite |
561
c %----------------------------------------------%
563
if (which .eq. 'LM') wprime = 'SR'
564
if (which .eq. 'SM') wprime = 'LR'
565
if (which .eq. 'LR') wprime = 'SM'
566
if (which .eq. 'SR') wprime = 'LM'
567
if (which .eq. 'LI') wprime = 'SM'
568
if (which .eq. 'SI') wprime = 'LM'
570
call ssortc (wprime, .true., kplusp, ritzr, ritzi, bounds)
572
c %----------------------------------------------%
573
c | Now sort Ritz values so that converged Ritz |
574
c | values appear within the first NEV locations |
575
c | of ritzr, ritzi and bounds, and the most |
576
c | desired one appears at the front. |
577
c %----------------------------------------------%
579
if (which .eq. 'LM') wprime = 'SM'
580
if (which .eq. 'SM') wprime = 'LM'
581
if (which .eq. 'LR') wprime = 'SR'
582
if (which .eq. 'SR') wprime = 'LR'
583
if (which .eq. 'LI') wprime = 'SI'
584
if (which .eq. 'SI') wprime = 'LI'
586
call ssortc(wprime, .true., kplusp, ritzr, ritzi, bounds)
588
c %--------------------------------------------------%
589
c | Scale the Ritz estimate of each Ritz value |
590
c | by 1 / max(eps23,magnitude of the Ritz value). |
591
c %--------------------------------------------------%
594
temp = max(eps23,slapy2(ritzr(j),
596
bounds(j) = bounds(j)/temp
599
c %----------------------------------------------------%
600
c | Sort the Ritz values according to the scaled Ritz |
601
c | esitmates. This will push all the converged ones |
602
c | towards the front of ritzr, ritzi, bounds |
603
c | (in the case when NCONV < NEV.) |
604
c %----------------------------------------------------%
607
call ssortc(wprime, .true., numcnv, bounds, ritzr, ritzi)
609
c %----------------------------------------------%
610
c | Scale the Ritz estimate back to its original |
612
c %----------------------------------------------%
615
temp = max(eps23, slapy2(ritzr(j),
617
bounds(j) = bounds(j)*temp
620
c %------------------------------------------------%
621
c | Sort the converged Ritz values again so that |
622
c | the "threshold" value appears at the front of |
623
c | ritzr, ritzi and bound. |
624
c %------------------------------------------------%
626
call ssortc(which, .true., nconv, ritzr, ritzi, bounds)
628
if (msglvl .gt. 1) then
629
call svout (logfil, kplusp, ritzr, ndigit,
630
& '_naup2: Sorted real part of the eigenvalues')
631
call svout (logfil, kplusp, ritzi, ndigit,
632
& '_naup2: Sorted imaginary part of the eigenvalues')
633
call svout (logfil, kplusp, bounds, ndigit,
634
& '_naup2: Sorted ritz estimates.')
637
c %------------------------------------%
638
c | Max iterations have been exceeded. |
639
c %------------------------------------%
641
if (iter .gt. mxiter .and. nconv .lt. numcnv) info = 1
643
c %---------------------%
644
c | No shifts to apply. |
645
c %---------------------%
647
if (np .eq. 0 .and. nconv .lt. numcnv) info = 2
652
else if ( (nconv .lt. numcnv) .and. (ishift .eq. 1) ) then
654
c %-------------------------------------------------%
655
c | Do not have all the requested eigenvalues yet. |
656
c | To prevent possible stagnation, adjust the size |
658
c %-------------------------------------------------%
661
nev = nev + min(nconv, np/2)
662
if (nev .eq. 1 .and. kplusp .ge. 6) then
664
else if (nev .eq. 1 .and. kplusp .gt. 3) then
669
c %---------------------------------------%
670
c | If the size of NEV was just increased |
671
c | resort the eigenvalues. |
672
c %---------------------------------------%
675
& call sngets (ishift, which, nev, np, ritzr, ritzi,
676
& bounds, workl, workl(np+1))
680
if (msglvl .gt. 0) then
681
call ivout (logfil, 1, nconv, ndigit,
682
& '_naup2: no. of "converged" Ritz values at this iter.')
683
if (msglvl .gt. 1) then
686
call ivout (logfil, 2, kp, ndigit,
687
& '_naup2: NEV and NP are')
688
call svout (logfil, nev, ritzr(np+1), ndigit,
689
& '_naup2: "wanted" Ritz values -- real part')
690
call svout (logfil, nev, ritzi(np+1), ndigit,
691
& '_naup2: "wanted" Ritz values -- imag part')
692
call svout (logfil, nev, bounds(np+1), ndigit,
693
& '_naup2: Ritz estimates of the "wanted" values ')
697
if (ishift .eq. 0) then
699
c %-------------------------------------------------------%
700
c | User specified shifts: reverse comminucation to |
701
c | compute the shifts. They are returned in the first |
702
c | 2*NP locations of WORKL. |
703
c %-------------------------------------------------------%
712
c %------------------------------------%
713
c | Back from reverse communication; |
714
c | User specified shifts are returned |
715
c | in WORKL(1:2*NP) |
716
c %------------------------------------%
720
if ( ishift .eq. 0 ) then
722
c %----------------------------------%
723
c | Move the NP shifts from WORKL to |
724
c | RITZR, RITZI to free up WORKL |
725
c | for non-exact shift case. |
726
c %----------------------------------%
728
call scopy (np, workl, 1, ritzr, 1)
729
call scopy (np, workl(np+1), 1, ritzi, 1)
732
if (msglvl .gt. 2) then
733
call ivout (logfil, 1, np, ndigit,
734
& '_naup2: The number of shifts to apply ')
735
call svout (logfil, np, ritzr, ndigit,
736
& '_naup2: Real part of the shifts')
737
call svout (logfil, np, ritzi, ndigit,
738
& '_naup2: Imaginary part of the shifts')
740
& call svout (logfil, np, bounds, ndigit,
741
& '_naup2: Ritz estimates of the shifts')
744
c %---------------------------------------------------------%
745
c | Apply the NP implicit shifts by QR bulge chasing. |
746
c | Each shift is applied to the whole upper Hessenberg |
748
c | The first 2*N locations of WORKD are used as workspace. |
749
c %---------------------------------------------------------%
751
call snapps (n, nev, np, ritzr, ritzi, v, ldv,
752
& h, ldh, resid, q, ldq, workl, workd)
754
c %---------------------------------------------%
755
c | Compute the B-norm of the updated residual. |
756
c | Keep B*RESID in WORKD(1:N) to be used in |
757
c | the first step of the next call to snaitr. |
758
c %---------------------------------------------%
762
if (bmat .eq. 'G') then
764
call scopy (n, resid, 1, workd(n+1), 1)
769
c %----------------------------------%
770
c | Exit in order to compute B*RESID |
771
c %----------------------------------%
774
else if (bmat .eq. 'I') then
775
call scopy (n, resid, 1, workd, 1)
780
c %----------------------------------%
781
c | Back from reverse communication; |
782
c | WORKD(1:N) := B*RESID |
783
c %----------------------------------%
785
if (bmat .eq. 'G') then
787
tmvbx = tmvbx + (t3 - t2)
790
if (bmat .eq. 'G') then
791
rnorm = sdot (n, resid, 1, workd, 1)
792
rnorm = sqrt(abs(rnorm))
793
else if (bmat .eq. 'I') then
794
rnorm = snrm2(n, resid, 1)
798
if (msglvl .gt. 2) then
799
call svout (logfil, 1, rnorm, ndigit,
800
& '_naup2: B-norm of residual for compressed factorization')
801
call smout (logfil, nev, nev, h, ldh, ndigit,
802
& '_naup2: Compressed upper Hessenberg matrix H')
807
c %---------------------------------------------------------------%
809
c | E N D O F M A I N I T E R A T I O N L O O P |
811
c %---------------------------------------------------------------%