2
SUBROUTINE <_c>BICGREVCOM( N, B, X, WORK, LDW, ITER, RESID, INFO,
3
$ NDX1, NDX2, SCLR1, SCLR2, IJOB)
6
* -- Iterative template routine --
7
* Univ. of Tennessee and Oak Ridge National Laboratory
9
* Details of this algorithm are described in "Templates for the
10
* Solution of Linear Systems: Building Blocks for Iterative
11
* Methods", Barrett, Berry, Chan, Demmel, Donato, Dongarra,
12
* Eijkhout, Pozo, Romine, and van der Vorst, SIAM Publications,
13
* 1993. (ftp netlib2.cs.utk.edu; cd linalg; get templates.ps).
15
* .. Scalar Arguments ..
16
INTEGER N, LDW, ITER, INFO
17
<rt=real,double precision,real,double precision> RESID
22
* .. Array Arguments ..
23
<_t> X( * ), B( * ), WORK( LDW,* )
30
* BiCG solves the linear system Ax = b using the
31
* BiConjugate Gradient iterative method with preconditioning.
37
* On entry, the dimension of the matrix.
40
* B (input) DOUBLE PRECISION array, dimension N.
41
* On entry, right hand side vector B.
44
* X (input/output) DOUBLE PRECISION array, dimension N.
45
* On input, the initial guess; on exit, the iterated solution.
47
* WORK (workspace) DOUBLE PRECISION array, dimension (LDW,6).
48
* Workspace for residual, direction vector, etc.
49
* Note that Z and Q, and ZTLD and QTLD share workspace.
52
* The leading dimension of the array WORK. LDW .gt. = max(1,N).
54
* ITER (input/output) INTEGER
55
* On input, the maximum iterations to be performed.
56
* On output, actual number of iterations performed.
58
* RESID (input/output) DOUBLE PRECISION
59
* On input, the allowable convergence measure for
60
* norm( b - A*x ) / norm( b ).
61
* On output, the final value of this measure.
63
* INFO (output) INTEGER
65
* = 0: Successful exit. Iterated approximate solution returned.
67
* .gt. 0: Convergence to tolerance not achieved. This will be
68
* set to the number of iterations performed.
70
* .ls. 0: Illegal input parameter, or breakdown occurred
75
* -1: matrix dimension N .ls. 0
77
* -3: Maximum number of iterations ITER .ls. = 0.
78
* -5: Erroneous NDX1/NDX2 in INIT call.
81
* BREAKDOWN: If parameters RHO or OMEGA become smaller
82
* than some tolerance, the program will terminate.
83
* Here we check against tolerance BREAKTOL.
85
* -10: RHO .ls. BREAKTOL: RHO and RTLD have become
88
* BREAKTOL is set in func GETBREAK.
90
* NDX1 (input/output) INTEGER.
91
* NDX2 On entry in INIT call contain indices required by interface
92
* level for stopping test.
93
* All other times, used as output, to indicate indices into
94
* WORK[] for the MATVEC, PSOLVE done by the interface level.
96
* SCLR1 (output) DOUBLE PRECISION.
97
* SCLR2 Used to pass the scalars used in MATVEC. Scalars are reqd because
98
* original routines use dgemv.
100
* IJOB (input/output) INTEGER.
101
* Used to communicate job code between the two levels.
103
* BLAS CALLS: DAXPY, DCOPY, DDOT, DNRM2,
104
* ==============================================================
108
PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
110
* .. Local Scalars ..
111
INTEGER R, RTLD, Z, ZTLD, P, PTLD, Q, QTLD, MAXIT,
113
<rt> TOL, BNRM2, RHOTOL,
114
$ <sdsd=s,d,s,d>GETBREAK,
116
<_t> ALPHA, BETA, RHO, RHO1, <xdot=sdot,ddot,cdotc,zdotc>
118
* indicates where to resume from. Only valid when IJOB = 2!
125
* .. External Routines ..
126
EXTERNAL <_c>AXPY, <_c>COPY, <xdot>, <rc>NRM2
128
* .. Executable Statements ..
130
* Entry point, so test IJOB
131
IF (IJOB .eq. 1) THEN
133
ELSEIF (IJOB .eq. 2) THEN
134
* here we do resumption handling
135
IF (RLBL .eq. 2) GOTO 2
136
IF (RLBL .eq. 3) GOTO 3
137
IF (RLBL .eq. 4) GOTO 4
138
IF (RLBL .eq. 5) GOTO 5
139
IF (RLBL .eq. 6) GOTO 6
140
IF (RLBL .eq. 7) GOTO 7
141
* if neither of these, then error
155
* Alias workspace columns.
166
* Check if caller will need indexing info.
168
IF( NDX1.NE.-1 ) THEN
170
NEED1 = ((R - 1) * LDW) + 1
171
ELSEIF( NDX1.EQ.2 ) THEN
172
NEED1 = ((RTLD - 1) * LDW) + 1
173
ELSEIF( NDX1.EQ.3 ) THEN
174
NEED1 = ((Z - 1) * LDW) + 1
175
ELSEIF( NDX1.EQ.4 ) THEN
176
NEED1 = ((ZTLD - 1) * LDW) + 1
177
ELSEIF( NDX1.EQ.5 ) THEN
178
NEED1 = ((P - 1) * LDW) + 1
179
ELSEIF( NDX1.EQ.6 ) THEN
180
NEED1 = ((PTLD - 1) * LDW) + 1
181
ELSEIF( NDX1.EQ.7 ) THEN
182
NEED1 = ((Q - 1) * LDW) + 1
183
ELSEIF( NDX1.EQ.8 ) THEN
184
NEED1 = ((QTLD - 1) * LDW) + 1
194
IF( NDX2.NE.-1 ) THEN
196
NEED2 = ((R - 1) * LDW) + 1
197
ELSEIF( NDX2.EQ.2 ) THEN
198
NEED2 = ((RTLD - 1) * LDW) + 1
199
ELSEIF( NDX2.EQ.3 ) THEN
200
NEED2 = ((Z - 1) * LDW) + 1
201
ELSEIF( NDX2.EQ.4 ) THEN
202
NEED2 = ((ZTLD - 1) * LDW) + 1
203
ELSEIF( NDX2.EQ.5 ) THEN
204
NEED2 = ((P - 1) * LDW) + 1
205
ELSEIF( NDX2.EQ.6 ) THEN
206
NEED2 = ((PTLD - 1) * LDW) + 1
207
ELSEIF( NDX2.EQ.7 ) THEN
208
NEED2 = ((Q - 1) * LDW) + 1
209
ELSEIF( NDX2.EQ.8 ) THEN
210
NEED2 = ((QTLD - 1) * LDW) + 1
220
* Set breakdown parameters.
222
RHOTOL = <sdsd>GETBREAK()
224
* Set initial residual.
226
CALL <_c>COPY( N, B, 1, WORK(1,R), 1 )
227
IF ( <rc>NRM2( N, X, 1 ).NE.ZERO ) THEN
228
*********CALL MATVEC( -ONE, X, ZERO, WORK(1,R) )
229
* using WORK[RTLD] as temp
230
*********CALL <_c>COPY( N, X, 1, WORK(1,RTLD), 1 )
233
NDX1 = ((RTLD - 1) * LDW) + 1
234
NDX2 = ((R - 1) * LDW) + 1
242
IF ( <rc>NRM2( N, WORK(1,R), 1 ).LE.TOL ) GO TO 30
245
CALL <_c>COPY( N, WORK(1,R), 1, WORK(1,RTLD), 1 )
246
BNRM2 = <rc>NRM2( N, B, 1 )
247
IF ( BNRM2.EQ.ZERO ) BNRM2 = ONE
253
* Perform BiConjugate Gradient iteration.
257
* Compute direction vectors PK and PTLD.
259
*********CALL PSOLVE( WORK(1,Z), WORK(1,R) )
261
NDX1 = ((Z - 1) * LDW) + 1
262
NDX2 = ((R - 1) * LDW) + 1
270
*********CALL PSOLVETRANS( WORK(1,ZTLD), WORK(1,RTLD) )
272
NDX1 = ((ZTLD - 1) * LDW) + 1
273
NDX2 = ((RTLD - 1) * LDW) + 1
282
* RHO = <xdot>( N, WORK(1,Z), 1, WORK(1,RTLD), 1 )
283
RHO = <xdot>( N, WORK(1,RTLD), 1, WORK(1,Z), 1 )
284
IF ( ABS( RHO ).LT.RHOTOL ) GO TO 25
286
IF ( ITER.GT.1 ) THEN
288
CALL <_c>AXPY( N, BETA, WORK(1,P), 1, WORK(1,Z), 1 )
289
* CALL <_c>AXPY( N, BETA, WORK(1,PTLD), 1, WORK(1,ZTLD), 1 )
290
CALL <_c>AXPY( N, <co= , ,conjg,conjg>(BETA),
291
$ WORK(1,PTLD), 1, WORK(1,ZTLD), 1 )
292
CALL <_c>COPY( N, WORK(1,Z), 1, WORK(1,P), 1 )
293
CALL <_c>COPY( N, WORK(1,ZTLD), 1, WORK(1,PTLD), 1 )
295
CALL <_c>COPY( N, WORK(1,Z), 1, WORK(1,P), 1 )
296
CALL <_c>COPY( N, WORK(1,ZTLD), 1, WORK(1,PTLD), 1 )
299
*********CALL MATVEC( ONE, WORK(1,P), ZERO, WORK(1,Q) )
303
NDX1 = ((P - 1) * LDW) + 1
304
NDX2 = ((Q - 1) * LDW) + 1
312
*********CALL MATVECTRANS( ONE, WORK(1,PTLD), ZERO, WORK(1,QTLD) )
316
NDX1 = ((PTLD - 1) * LDW) + 1
317
NDX2 = ((QTLD - 1) * LDW) + 1
324
ALPHA = RHO / <xdot>( N, WORK(1,PTLD), 1, WORK(1,Q), 1 )
326
* Compute current solution vector x.
328
CALL <_c>AXPY( N, ALPHA, WORK(1,P), 1, X, 1 )
330
* Compute residual vector rk, find norm,
331
* then check for tolerance.
333
CALL <_c>AXPY( N, -ALPHA, WORK(1,Q), 1, WORK(1,R), 1 )
335
*********RESID = <rc>NRM2( N, WORK(1,R), 1 ) / BNRM2
336
*********IF ( RESID.LE.TOL ) GO TO 30
340
* Prepare for resumption & return
348
IF( INFO.EQ.1 ) GO TO 30
350
IF ( ITER.EQ.MAXIT ) THEN
355
* CALL <_c>AXPY( N, -ALPHA, WORK(1,QTLD), 1, WORK(1,RTLD), 1 )
356
CALL <_c>AXPY( N, -<co>(ALPHA)
357
$ , WORK(1,QTLD), 1, WORK(1,RTLD), 1 )
372
* Set breakdown flag.
381
* Iteration successful; return.
390
END SUBROUTINE <_c>BICGREVCOM