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