Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/mathlibs/src/arpack/cnaup2.f
5218 views
1
c\BeginDoc
2
c
3
c\Name: cnaup2
4
c
5
c\Description:
6
c Intermediate level interface called by cnaupd.
7
c
8
c\Usage:
9
c call cnaup2
10
c ( IDO, BMAT, N, WHICH, NEV, NP, TOL, RESID, MODE, IUPD,
11
c ISHIFT, MXITER, V, LDV, H, LDH, RITZ, BOUNDS,
12
c Q, LDQ, WORKL, IPNTR, WORKD, RWORK, INFO )
13
c
14
c\Arguments
15
c
16
c IDO, BMAT, N, WHICH, NEV, TOL, RESID: same as defined in cnaupd.
17
c MODE, ISHIFT, MXITER: see the definition of IPARAM in cnaupd.
18
c
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
27
c subroutine.
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 since a leading block of the current
31
c upper Hessenberg matrix has split off and contains "unwanted"
32
c Ritz values.
33
c Upon termination of the IRA iteration, NP contains the number
34
c of "converged" wanted Ritz values.
35
c
36
c IUPD Integer. (INPUT)
37
c IUPD .EQ. 0: use explicit restart instead implicit update.
38
c IUPD .NE. 0: use implicit update.
39
c
40
c V Complex N by (NEV+NP) array. (INPUT/OUTPUT)
41
c The Arnoldi basis vectors are returned in the first NEV
42
c columns of V.
43
c
44
c LDV Integer. (INPUT)
45
c Leading dimension of V exactly as declared in the calling
46
c program.
47
c
48
c H Complex (NEV+NP) by (NEV+NP) array. (OUTPUT)
49
c H is used to store the generated upper Hessenberg matrix
50
c
51
c LDH Integer. (INPUT)
52
c Leading dimension of H exactly as declared in the calling
53
c program.
54
c
55
c RITZ Complex array of length NEV+NP. (OUTPUT)
56
c RITZ(1:NEV) contains the computed Ritz values of OP.
57
c
58
c BOUNDS Complex array of length NEV+NP. (OUTPUT)
59
c BOUNDS(1:NEV) contain the error bounds corresponding to
60
c the computed Ritz values.
61
c
62
c Q Complex (NEV+NP) by (NEV+NP) array. (WORKSPACE)
63
c Private (replicated) work array used to accumulate the
64
c rotation in the shift application step.
65
c
66
c LDQ Integer. (INPUT)
67
c Leading dimension of Q exactly as declared in the calling
68
c program.
69
c
70
c WORKL Complex work array of length at least
71
c (NEV+NP)**2 + 3*(NEV+NP). (WORKSPACE)
72
c Private (replicated) array on each PE or array allocated on
73
c the front end. It is used in shifts calculation, shifts
74
c application and convergence checking.
75
c
76
c
77
c IPNTR Integer array of length 3. (OUTPUT)
78
c Pointer to mark the starting locations in the WORKD for
79
c vectors used by the Arnoldi iteration.
80
c -------------------------------------------------------------
81
c IPNTR(1): pointer to the current operand vector X.
82
c IPNTR(2): pointer to the current result vector Y.
83
c IPNTR(3): pointer to the vector B * X when used in the
84
c shift-and-invert mode. X is the current operand.
85
c -------------------------------------------------------------
86
c
87
c WORKD Complex work array of length 3*N. (WORKSPACE)
88
c Distributed array to be used in the basic Arnoldi iteration
89
c for reverse communication. The user should not use WORKD
90
c as temporary workspace during the iteration !!!!!!!!!!
91
c See Data Distribution Note in CNAUPD.
92
c
93
c RWORK Real work array of length NEV+NP ( WORKSPACE)
94
c Private (replicated) array on each PE or array allocated on
95
c the front end.
96
c
97
c INFO Integer. (INPUT/OUTPUT)
98
c If INFO .EQ. 0, a randomly initial residual vector is used.
99
c If INFO .NE. 0, RESID contains the initial residual vector,
100
c possibly from a previous run.
101
c Error flag on output.
102
c = 0: Normal return.
103
c = 1: Maximum number of iterations taken.
104
c All possible eigenvalues of OP has been found.
105
c NP returns the number of converged Ritz values.
106
c = 2: No shifts could be applied.
107
c = -8: Error return from LAPACK eigenvalue calculation;
108
c This should never happen.
109
c = -9: Starting vector is zero.
110
c = -9999: Could not build an Arnoldi factorization.
111
c Size that was built in returned in NP.
112
c
113
c\EndDoc
114
c
115
c-----------------------------------------------------------------------
116
c
117
c\BeginLib
118
c
119
c\Local variables:
120
c xxxxxx Complex
121
c
122
c\References:
123
c 1. D.C. Sorensen, "Implicit Application of Polynomial Filters in
124
c a k-Step Arnoldi Method", SIAM J. Matr. Anal. Apps., 13 (1992),
125
c pp 357-385.
126
c 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly
127
c Restarted Arnoldi Iteration", Rice University Technical Report
128
c TR95-13, Department of Computational and Applied Mathematics.
129
c
130
c\Routines called:
131
c cgetv0 ARPACK initial vector generation routine.
132
c cnaitr ARPACK Arnoldi factorization routine.
133
c cnapps ARPACK application of implicit shifts routine.
134
c cneigh ARPACK compute Ritz values and error bounds routine.
135
c cngets ARPACK reorder Ritz values and error bounds routine.
136
c csortc ARPACK sorting routine.
137
c ivout ARPACK utility routine that prints integers.
138
c second ARPACK utility routine for timing.
139
c cmout ARPACK utility routine that prints matrices
140
c cvout ARPACK utility routine that prints vectors.
141
c svout ARPACK utility routine that prints vectors.
142
c slamch LAPACK routine that determines machine constants.
143
c slapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
144
c ccopy Level 1 BLAS that copies one vector to another .
145
c cdotc Level 1 BLAS that computes the scalar product of two vectors.
146
c cswap Level 1 BLAS that swaps two vectors.
147
c scnrm2 Level 1 BLAS that computes the norm of a vector.
148
c
149
c\Author
150
c Danny Sorensen Phuong Vu
151
c Richard Lehoucq CRPC / Rice Universitya
152
c Chao Yang Houston, Texas
153
c Dept. of Computational &
154
c Applied Mathematics
155
c Rice University
156
c Houston, Texas
157
c
158
c\SCCS Information: @(#)
159
c FILE: naup2.F SID: 2.5 DATE OF SID: 8/16/96 RELEASE: 2
160
c
161
c\Remarks
162
c 1. None
163
c
164
c\EndLib
165
c
166
c-----------------------------------------------------------------------
167
c
168
subroutine cnaup2
169
& ( ido, bmat, n, which, nev, np, tol, resid, mode, iupd,
170
& ishift, mxiter, v, ldv, h, ldh, ritz, bounds,
171
& q, ldq, workl, ipntr, workd, rwork, info )
172
c
173
c %----------------------------------------------------%
174
c | Include files for debugging and timing information |
175
c %----------------------------------------------------%
176
c
177
include 'debug.h'
178
include 'stat.h'
179
c
180
c %------------------%
181
c | Scalar Arguments |
182
c %------------------%
183
c
184
character bmat*1, which*2
185
integer ido, info, ishift, iupd, mode, ldh, ldq, ldv, mxiter,
186
& n, nev, np
187
Real
188
& tol
189
c
190
c %-----------------%
191
c | Array Arguments |
192
c %-----------------%
193
c
194
integer ipntr(13)
195
Complex
196
& bounds(nev+np), h(ldh,nev+np), q(ldq,nev+np),
197
& resid(n), ritz(nev+np), v(ldv,nev+np),
198
& workd(3*n), workl( (nev+np)*(nev+np+3) )
199
Real
200
& rwork(nev+np)
201
c
202
c %------------%
203
c | Parameters |
204
c %------------%
205
c
206
Complex
207
& one, zero
208
Real
209
& rzero
210
parameter (one = (1.0E+0, 0.0E+0), zero = (0.0E+0, 0.0E+0),
211
& rzero = 0.0E+0)
212
c
213
c %---------------%
214
c | Local Scalars |
215
c %---------------%
216
c
217
logical cnorm, getv0, initv, update, ushift
218
integer ierr, iter, i, j, kplusp, msglvl, nconv, nevbef, nev0,
219
& np0, nptemp
220
Complex
221
& cmpnorm
222
Real
223
& rtemp, eps23, rnorm
224
character wprime*2
225
c
226
save cnorm, getv0, initv, update, ushift,
227
& iter, kplusp, msglvl, nconv, nev0, np0,
228
& eps23
229
c
230
c
231
c %-----------------------%
232
c | Local array arguments |
233
c %-----------------------%
234
c
235
integer kp(3)
236
c
237
c %----------------------%
238
c | External Subroutines |
239
c %----------------------%
240
c
241
external ccopy, cgetv0, cnaitr, cneigh, cngets, cnapps,
242
& csortc, cswap, cmout, cvout, ivout, second
243
c
244
c %--------------------%
245
c | External functions |
246
c %--------------------%
247
c
248
Complex
249
& cdotc
250
Real
251
& scnrm2, slamch, slapy2
252
external cdotc, scnrm2, slamch, slapy2
253
c
254
c %---------------------%
255
c | Intrinsic Functions |
256
c %---------------------%
257
c
258
intrinsic aimag, real, min, max
259
c
260
c %-----------------------%
261
c | Executable Statements |
262
c %-----------------------%
263
c
264
if (ido .eq. 0) then
265
c
266
call second (t0)
267
c
268
msglvl = mcaup2
269
c
270
nev0 = nev
271
np0 = np
272
c
273
c %-------------------------------------%
274
c | kplusp is the bound on the largest |
275
c | Lanczos factorization built. |
276
c | nconv is the current number of |
277
c | "converged" eigenvalues. |
278
c | iter is the counter on the current |
279
c | iteration step. |
280
c %-------------------------------------%
281
c
282
kplusp = nev + np
283
nconv = 0
284
iter = 0
285
c
286
c %---------------------------------%
287
c | Get machine dependent constant. |
288
c %---------------------------------%
289
c
290
eps23 = slamch('Epsilon-Machine')
291
eps23 = eps23**(2.0E+0 / 3.0E+0)
292
c
293
c %---------------------------------------%
294
c | Set flags for computing the first NEV |
295
c | steps of the Arnoldi factorization. |
296
c %---------------------------------------%
297
c
298
getv0 = .true.
299
update = .false.
300
ushift = .false.
301
cnorm = .false.
302
c
303
if (info .ne. 0) then
304
c
305
c %--------------------------------------------%
306
c | User provides the initial residual vector. |
307
c %--------------------------------------------%
308
c
309
initv = .true.
310
info = 0
311
else
312
initv = .false.
313
end if
314
end if
315
c
316
c %---------------------------------------------%
317
c | Get a possibly random starting vector and |
318
c | force it into the range of the operator OP. |
319
c %---------------------------------------------%
320
c
321
10 continue
322
c
323
if (getv0) then
324
call cgetv0 (ido, bmat, 1, initv, n, 1, v, ldv, resid, rnorm,
325
& ipntr, workd, info)
326
c
327
if (ido .ne. 99) go to 9000
328
c
329
if (rnorm .eq. rzero) then
330
c
331
c %-----------------------------------------%
332
c | The initial vector is zero. Error exit. |
333
c %-----------------------------------------%
334
c
335
info = -9
336
go to 1100
337
end if
338
getv0 = .false.
339
ido = 0
340
end if
341
c
342
c %-----------------------------------%
343
c | Back from reverse communication : |
344
c | continue with update step |
345
c %-----------------------------------%
346
c
347
if (update) go to 20
348
c
349
c %-------------------------------------------%
350
c | Back from computing user specified shifts |
351
c %-------------------------------------------%
352
c
353
if (ushift) go to 50
354
c
355
c %-------------------------------------%
356
c | Back from computing residual norm |
357
c | at the end of the current iteration |
358
c %-------------------------------------%
359
c
360
if (cnorm) go to 100
361
c
362
c %----------------------------------------------------------%
363
c | Compute the first NEV steps of the Arnoldi factorization |
364
c %----------------------------------------------------------%
365
c
366
call cnaitr (ido, bmat, n, 0, nev, mode, resid, rnorm, v, ldv,
367
& h, ldh, ipntr, workd, info)
368
c
369
if (ido .ne. 99) go to 9000
370
c
371
if (info .gt. 0) then
372
np = info
373
mxiter = iter
374
info = -9999
375
go to 1200
376
end if
377
c
378
c %--------------------------------------------------------------%
379
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. |
383
c | |
384
c %--------------------------------------------------------------%
385
c
386
1000 continue
387
c
388
iter = iter + 1
389
c
390
if (msglvl .gt. 0) then
391
call ivout (logfil, 1, [iter], ndigit,
392
& '_naup2: **** Start of major iteration number ****')
393
end if
394
c
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 cnapps. |
399
c %-----------------------------------------------------------%
400
c
401
np = kplusp - nev
402
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')
408
end if
409
c
410
c %-----------------------------------------------------------%
411
c | Compute NP additional steps of the Arnoldi factorization. |
412
c %-----------------------------------------------------------%
413
c
414
ido = 0
415
20 continue
416
update = .true.
417
c
418
call cnaitr (ido, bmat, n, nev, np, mode, resid, rnorm, v, ldv,
419
& h, ldh, ipntr, workd, info)
420
c
421
if (ido .ne. 99) go to 9000
422
c
423
if (info .gt. 0) then
424
np = info
425
mxiter = iter
426
info = -9999
427
go to 1200
428
end if
429
update = .false.
430
c
431
if (msglvl .gt. 1) then
432
call svout (logfil, 1, [rnorm], ndigit,
433
& '_naup2: Corresponding B-norm of the residual')
434
end if
435
c
436
c %--------------------------------------------------------%
437
c | Compute the eigenvalues and corresponding error bounds |
438
c | of the current upper Hessenberg matrix. |
439
c %--------------------------------------------------------%
440
c
441
call cneigh (rnorm, kplusp, h, ldh, ritz, bounds,
442
& q, ldq, workl, rwork, ierr)
443
c
444
if (ierr .ne. 0) then
445
info = -8
446
go to 1200
447
end if
448
c
449
c %---------------------------------------------------%
450
c | Select the wanted Ritz values and their bounds |
451
c | to be used in the convergence test. |
452
c | The wanted part of the spectrum and corresponding |
453
c | error bounds are in the last NEV loc. of RITZ, |
454
c | and BOUNDS respectively. |
455
c %---------------------------------------------------%
456
c
457
nev = nev0
458
np = np0
459
c
460
c %--------------------------------------------------%
461
c | Make a copy of Ritz values and the corresponding |
462
c | Ritz estimates obtained from cneigh. |
463
c %--------------------------------------------------%
464
c
465
call ccopy(kplusp,ritz,1,workl(kplusp**2+1),1)
466
call ccopy(kplusp,bounds,1,workl(kplusp**2+kplusp+1),1)
467
c
468
c %---------------------------------------------------%
469
c | Select the wanted Ritz values and their bounds |
470
c | to be used in the convergence test. |
471
c | The wanted part of the spectrum and corresponding |
472
c | bounds are in the last NEV loc. of RITZ |
473
c | BOUNDS respectively. |
474
c %---------------------------------------------------%
475
c
476
call cngets (ishift, which, nev, np, ritz, bounds)
477
c
478
c %------------------------------------------------------------%
479
c | Convergence test: currently we use the following criteria. |
480
c | The relative accuracy of a Ritz value is considered |
481
c | acceptable if: |
482
c | |
483
c | error_bounds(i) .le. tol*max(eps23, magnitude_of_ritz(i)). |
484
c | |
485
c %------------------------------------------------------------%
486
c
487
nconv = 0
488
c
489
do 25 i = 1, nev
490
rtemp = max( eps23, slapy2( real(ritz(np+i)),
491
& aimag(ritz(np+i)) ) )
492
if ( slapy2(real(bounds(np+i)),aimag(bounds(np+i)))
493
& .le. tol*rtemp ) then
494
nconv = nconv + 1
495
end if
496
25 continue
497
c
498
if (msglvl .gt. 2) then
499
kp(1) = nev
500
kp(2) = np
501
kp(3) = nconv
502
call ivout (logfil, 3, kp, ndigit,
503
& '_naup2: NEV, NP, NCONV are')
504
call cvout (logfil, kplusp, ritz, ndigit,
505
& '_naup2: The eigenvalues of H')
506
call cvout (logfil, kplusp, bounds, ndigit,
507
& '_naup2: Ritz estimates of the current NCV Ritz values')
508
end if
509
c
510
c %---------------------------------------------------------%
511
c | Count the number of unwanted Ritz values that have zero |
512
c | Ritz estimates. If any Ritz estimates are equal to zero |
513
c | then a leading block of H of order equal to at least |
514
c | the number of Ritz values with zero Ritz estimates has |
515
c | split off. None of these Ritz values may be removed by |
516
c | shifting. Decrease NP the number of shifts to apply. If |
517
c | no shifts may be applied, then prepare to exit |
518
c %---------------------------------------------------------%
519
c
520
nptemp = np
521
do 30 j=1, nptemp
522
if (bounds(j) .eq. zero) then
523
np = np - 1
524
nev = nev + 1
525
end if
526
30 continue
527
c
528
if ( (nconv .ge. nev0) .or.
529
& (iter .gt. mxiter) .or.
530
& (np .eq. 0) ) then
531
c
532
if (msglvl .gt. 4) then
533
call cvout(logfil, kplusp, workl(kplusp**2+1), ndigit,
534
& '_naup2: Eigenvalues computed by _neigh:')
535
call cvout(logfil, kplusp, workl(kplusp**2+kplusp+1),
536
& ndigit,
537
& '_naup2: Ritz estimates computed by _neigh:')
538
end if
539
c
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 %------------------------------------------------%
546
c
547
c %------------------------------------------%
548
c | Use h( 3,1 ) as storage to communicate |
549
c | rnorm to cneupd if needed |
550
c %------------------------------------------%
551
552
h(3,1) = cmplx(rnorm,rzero)
553
c
554
c %----------------------------------------------%
555
c | Sort Ritz values so that converged Ritz |
556
c | values appear within the first NEV locations |
557
c | of ritz and bounds, and the most desired one |
558
c | appears at the front. |
559
c %----------------------------------------------%
560
c
561
if (which .eq. 'LM') wprime = 'SM'
562
if (which .eq. 'SM') wprime = 'LM'
563
if (which .eq. 'LR') wprime = 'SR'
564
if (which .eq. 'SR') wprime = 'LR'
565
if (which .eq. 'LI') wprime = 'SI'
566
if (which .eq. 'SI') wprime = 'LI'
567
c
568
call csortc(wprime, .true., kplusp, ritz, bounds)
569
c
570
c %--------------------------------------------------%
571
c | Scale the Ritz estimate of each Ritz value |
572
c | by 1 / max(eps23, magnitude of the Ritz value). |
573
c %--------------------------------------------------%
574
c
575
do 35 j = 1, nev0
576
rtemp = max( eps23, slapy2( real(ritz(j)),
577
& aimag(ritz(j)) ) )
578
bounds(j) = bounds(j)/rtemp
579
35 continue
580
c
581
c %---------------------------------------------------%
582
c | Sort the Ritz values according to the scaled Ritz |
583
c | estimates. This will push all the converged ones |
584
c | towards the front of ritz, bounds (in the case |
585
c | when NCONV < NEV.) |
586
c %---------------------------------------------------%
587
c
588
wprime = 'LM'
589
call csortc(wprime, .true., nev0, bounds, ritz)
590
c
591
c %----------------------------------------------%
592
c | Scale the Ritz estimate back to its original |
593
c | value. |
594
c %----------------------------------------------%
595
c
596
do 40 j = 1, nev0
597
rtemp = max( eps23, slapy2( real(ritz(j)),
598
& aimag(ritz(j)) ) )
599
bounds(j) = bounds(j)*rtemp
600
40 continue
601
c
602
c %-----------------------------------------------%
603
c | Sort the converged Ritz values again so that |
604
c | the "threshold" value appears at the front of |
605
c | ritz and bound. |
606
c %-----------------------------------------------%
607
c
608
call csortc(which, .true., nconv, ritz, bounds)
609
c
610
if (msglvl .gt. 1) then
611
call cvout (logfil, kplusp, ritz, ndigit,
612
& '_naup2: Sorted eigenvalues')
613
call cvout (logfil, kplusp, bounds, ndigit,
614
& '_naup2: Sorted ritz estimates.')
615
end if
616
c
617
c %------------------------------------%
618
c | Max iterations have been exceeded. |
619
c %------------------------------------%
620
c
621
if (iter .gt. mxiter .and. nconv .lt. nev0) info = 1
622
c
623
c %---------------------%
624
c | No shifts to apply. |
625
c %---------------------%
626
c
627
if (np .eq. 0 .and. nconv .lt. nev0) info = 2
628
c
629
np = nconv
630
go to 1100
631
c
632
else if ( (nconv .lt. nev0) .and. (ishift .eq. 1) ) then
633
c
634
c %-------------------------------------------------%
635
c | Do not have all the requested eigenvalues yet. |
636
c | To prevent possible stagnation, adjust the size |
637
c | of NEV. |
638
c %-------------------------------------------------%
639
c
640
nevbef = nev
641
nev = nev + min(nconv, np/2)
642
if (nev .eq. 1 .and. kplusp .ge. 6) then
643
nev = kplusp / 2
644
else if (nev .eq. 1 .and. kplusp .gt. 3) then
645
nev = 2
646
end if
647
np = kplusp - nev
648
c
649
c %---------------------------------------%
650
c | If the size of NEV was just increased |
651
c | resort the eigenvalues. |
652
c %---------------------------------------%
653
c
654
if (nevbef .lt. nev)
655
& call cngets (ishift, which, nev, np, ritz, bounds)
656
c
657
end if
658
c
659
if (msglvl .gt. 0) then
660
call ivout (logfil, 1, [nconv], ndigit,
661
& '_naup2: no. of "converged" Ritz values at this iter.')
662
if (msglvl .gt. 1) then
663
kp(1) = nev
664
kp(2) = np
665
call ivout (logfil, 2, kp, ndigit,
666
& '_naup2: NEV and NP are')
667
call cvout (logfil, nev, ritz(np+1), ndigit,
668
& '_naup2: "wanted" Ritz values ')
669
call cvout (logfil, nev, bounds(np+1), ndigit,
670
& '_naup2: Ritz estimates of the "wanted" values ')
671
end if
672
end if
673
c
674
if (ishift .eq. 0) then
675
c
676
c %-------------------------------------------------------%
677
c | User specified shifts: pop back out to get the shifts |
678
c | and return them in the first 2*NP locations of WORKL. |
679
c %-------------------------------------------------------%
680
c
681
ushift = .true.
682
ido = 3
683
go to 9000
684
end if
685
50 continue
686
ushift = .false.
687
c
688
if ( ishift .ne. 1 ) then
689
c
690
c %----------------------------------%
691
c | Move the NP shifts from WORKL to |
692
c | RITZ, to free up WORKL |
693
c | for non-exact shift case. |
694
c %----------------------------------%
695
c
696
call ccopy (np, workl, 1, ritz, 1)
697
end if
698
c
699
if (msglvl .gt. 2) then
700
call ivout (logfil, 1, [np], ndigit,
701
& '_naup2: The number of shifts to apply ')
702
call cvout (logfil, np, ritz, ndigit,
703
& '_naup2: values of the shifts')
704
if ( ishift .eq. 1 )
705
& call cvout (logfil, np, bounds, ndigit,
706
& '_naup2: Ritz estimates of the shifts')
707
end if
708
c
709
c %---------------------------------------------------------%
710
c | Apply the NP implicit shifts by QR bulge chasing. |
711
c | Each shift is applied to the whole upper Hessenberg |
712
c | matrix H. |
713
c | The first 2*N locations of WORKD are used as workspace. |
714
c %---------------------------------------------------------%
715
c
716
call cnapps (n, nev, np, ritz, v, ldv,
717
& h, ldh, resid, q, ldq, workl, workd)
718
c
719
c %---------------------------------------------%
720
c | Compute the B-norm of the updated residual. |
721
c | Keep B*RESID in WORKD(1:N) to be used in |
722
c | the first step of the next call to cnaitr. |
723
c %---------------------------------------------%
724
c
725
cnorm = .true.
726
call second (t2)
727
if (bmat .eq. 'G') then
728
nbx = nbx + 1
729
call ccopy (n, resid, 1, workd(n+1), 1)
730
ipntr(1) = n + 1
731
ipntr(2) = 1
732
ido = 2
733
c
734
c %----------------------------------%
735
c | Exit in order to compute B*RESID |
736
c %----------------------------------%
737
c
738
go to 9000
739
else if (bmat .eq. 'I') then
740
call ccopy (n, resid, 1, workd, 1)
741
end if
742
c
743
100 continue
744
c
745
c %----------------------------------%
746
c | Back from reverse communication; |
747
c | WORKD(1:N) := B*RESID |
748
c %----------------------------------%
749
c
750
if (bmat .eq. 'G') then
751
call second (t3)
752
tmvbx = tmvbx + (t3 - t2)
753
end if
754
c
755
if (bmat .eq. 'G') then
756
cmpnorm = cdotc (n, resid, 1, workd, 1)
757
rnorm = sqrt(slapy2(real(cmpnorm),aimag(cmpnorm)))
758
else if (bmat .eq. 'I') then
759
rnorm = scnrm2(n, resid, 1)
760
end if
761
cnorm = .false.
762
c
763
if (msglvl .gt. 2) then
764
call svout (logfil, 1, [rnorm], ndigit,
765
& '_naup2: B-norm of residual for compressed factorization')
766
call cmout (logfil, nev, nev, h, ldh, ndigit,
767
& '_naup2: Compressed upper Hessenberg matrix H')
768
end if
769
c
770
go to 1000
771
c
772
c %---------------------------------------------------------------%
773
c | |
774
c | E N D O F M A I N I T E R A T I O N L O O P |
775
c | |
776
c %---------------------------------------------------------------%
777
c
778
1100 continue
779
c
780
mxiter = iter
781
nev = nconv
782
c
783
1200 continue
784
ido = 99
785
c
786
c %------------%
787
c | Error Exit |
788
c %------------%
789
c
790
call second (t1)
791
tcaup2 = t1 - t0
792
c
793
9000 continue
794
c
795
c %---------------%
796
c | End of cnaup2 |
797
c %---------------%
798
c
799
return
800
end
801
802