~ubuntu-branches/ubuntu/karmic/python-scipy/karmic

« back to all changes in this revision

Viewing changes to Lib/linalg/iterative/BiCGSTABREVCOM.f.src

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T. Chen (new)
  • Date: 2005-03-16 02:15:29 UTC
  • Revision ID: james.westby@ubuntu.com-20050316021529-xrjlowsejs0cijig
Tags: upstream-0.3.2
ImportĀ upstreamĀ versionĀ 0.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
*
 
2
      SUBROUTINE <_c>BICGSTABREVCOM(N, B, X, WORK, LDW, ITER, RESID, 
 
3
     $                    INFO,NDX1, NDX2, SCLR1, SCLR2, IJOB)
 
4
*
 
5
*  -- Iterative template routine --
 
6
*     Univ. of Tennessee and Oak Ridge National Laboratory
 
7
*     October 1, 1993
 
8
*     Details of this algorithm are described in "Templates for the 
 
9
*     Solution of Linear Systems: Building Blocks for Iterative 
 
10
*     Methods", Barrett, Berry, Chan, Demmel, Donato, Dongarra, 
 
11
*     Eijkhout, Pozo, Romine, and van der Vorst, SIAM Publications,
 
12
*     1993. (ftp netlib2.cs.utk.edu; cd linalg; get templates.ps).
 
13
*
 
14
*     .. Scalar Arguments ..
 
15
      INTEGER            N, LDW, ITER, INFO 
 
16
      <rt=real,double precision,real,double precision>   RESID
 
17
      INTEGER            NDX1, NDX2
 
18
      <_t>   SCLR1, SCLR2
 
19
      INTEGER            IJOB
 
20
*     ..
 
21
*     .. Array Arguments ..
 
22
      <_t>   X( * ), B( * ), WORK( LDW,* )
 
23
*     ..
 
24
*
 
25
*  Purpose
 
26
*  =======
 
27
*
 
28
*  BICGSTAB solves the linear system A*x = b using the
 
29
*  BiConjugate Gradient Stabilized iterative method with 
 
30
*  preconditioning.
 
31
*
 
32
*  Arguments
 
33
*  =========
 
34
*
 
35
*  N       (input) INTEGER. 
 
36
*          On entry, the dimension of the matrix.
 
37
*          Unchanged on exit.
 
38
 
39
*  B       (input) DOUBLE PRECISION array, dimension N.
 
40
*          On entry, right hand side vector B.
 
41
*          Unchanged on exit.
 
42
*
 
43
*  X       (input/output) DOUBLE PRECISION array, dimension N.
 
44
*          On input, the initial guess. This is commonly set to 
 
45
*          the zero vector. 
 
46
*          On exit, if INFO = 0, the iterated approximate solution.
 
47
*
 
48
*  WORK    (workspace) DOUBLE PRECISION array, dimension (LDW,7)
 
49
*          Workspace for residual, direction vector, etc.
 
50
*          Note that vectors R and S shared the same workspace.
 
51
*
 
52
*  LDW     (input) INTEGER
 
53
*          The leading dimension of the array WORK. LDW .gt. = max(1,N).
 
54
*
 
55
*  ITER    (input/output) INTEGER
 
56
*          On input, the maximum iterations to be performed.
 
57
*          On output, actual number of iterations performed.
 
58
*
 
59
*  RESID   (input/output) DOUBLE PRECISION
 
60
*          On input, the allowable convergence measure for
 
61
*          norm( b - A*x ) / norm( b ).
 
62
*          On output, the final value of this measure.
 
63
*
 
64
*  INFO    (output) INTEGER
 
65
*
 
66
*          =  0: Successful exit. Iterated approximate solution returned.
 
67
*
 
68
*          .gt.   0: Convergence to tolerance not achieved. This will be 
 
69
*                set to the number of iterations performed.
 
70
*
 
71
*           .ls.   0: Illegal input parameter, or breakdown occurred
 
72
*                during iteration.
 
73
*
 
74
*                Illegal parameter:
 
75
*
 
76
*                   -1: matrix dimension N  .ls.  0
 
77
*                   -2: LDW  .ls.  N
 
78
*                   -3: Maximum number of iterations ITER  .ls. = 0.
 
79
*                   -5: Erroneous NDX1/NDX2 in INIT call.
 
80
*                   -6: Erroneous RLBL.
 
81
*
 
82
*                BREAKDOWN: If parameters RHO or OMEGA become smaller
 
83
*                   than some tolerance, the program will terminate.
 
84
*                   Here we check against tolerance BREAKTOL.
 
85
*
 
86
*                  -10: RHO  .ls.  BREAKTOL: RHO and RTLD have become 
 
87
*                                       orthogonal.
 
88
*                  -11: OMEGA  .ls.  BREAKTOL: S and T have become 
 
89
*                                         orthogonal relative to T'*T.
 
90
*
 
91
*                  BREAKTOL is set in func GETBREAK.
 
92
*
 
93
*  NDX1    (input/output) INTEGER. 
 
94
*  NDX2    On entry in INIT call contain indices required by interface
 
95
*          level for stopping test.
 
96
*          All other times, used as output, to indicate indices into
 
97
*          WORK[] for the MATVEC, PSOLVE done by the interface level.
 
98
*
 
99
*  SCLR1   (output) DOUBLE PRECISION.
 
100
*  SCLR2   Used to pass the scalars used in MATVEC. Scalars are reqd because
 
101
*          original routines use dgemv.
 
102
*
 
103
*  IJOB    (input/output) INTEGER. 
 
104
*          Used to communicate job code between the two levels.
 
105
*
 
106
*  BLAS CALLS: DAXPY, DCOPY, DDOT, DNRM2, DSCAL
 
107
*  ==============================================================
 
108
*
 
109
*     .. Parameters ..
 
110
      DOUBLE PRECISION   ZERO, ONE
 
111
      PARAMETER        ( ZERO = 0.0D+0, ONE = 1.0D+0 )
 
112
*     ..
 
113
*     .. Local Scalars ..
 
114
      INTEGER            R, RTLD, P, PHAT, V, S, SHAT, T, MAXIT,
 
115
     $                   NEED1, NEED2
 
116
      <rt>   TOL, BNRM2, 
 
117
     $     RHOTOL, OMEGATOL, <sdsd=s,d,s,d>GETBREAK, 
 
118
     $     <rc=s,d,sc,dz>NRM2
 
119
      <_t>   ALPHA, BETA, RHO, RHO1, OMEGA,
 
120
     $     <xdot=sdot,ddot,cdotc,zdotc>
 
121
*     indicates where to resume from. Only valid when IJOB = 2!
 
122
      INTEGER RLBL
 
123
*
 
124
*     saving all.
 
125
      SAVE
 
126
*     ..
 
127
*     .. External Funcs ..
 
128
      EXTERNAL           <sdsd>GETBREAK, <_c>AXPY, <_c>COPY, 
 
129
     $      <xdot>, <rc>NRM2, <_c>SCAL
 
130
*     ..
 
131
*     .. Intrinsic Funcs ..
 
132
      INTRINSIC          ABS, MAX
 
133
*     ..
 
134
*     .. Executable Statements ..
 
135
*
 
136
*     Entry point, so test IJOB
 
137
      IF (IJOB .eq. 1) THEN
 
138
         GOTO 1
 
139
      ELSEIF (IJOB .eq. 2) THEN
 
140
*        here we do resumption handling
 
141
         IF (RLBL .eq. 2) GOTO 2
 
142
         IF (RLBL .eq. 3) GOTO 3
 
143
         IF (RLBL .eq. 4) GOTO 4
 
144
         IF (RLBL .eq. 5) GOTO 5
 
145
         IF (RLBL .eq. 6) GOTO 6
 
146
         IF (RLBL .eq. 7) GOTO 7
 
147
*        if neither of these, then error
 
148
         INFO = -6
 
149
         GOTO 20
 
150
      ENDIF
 
151
*
 
152
*
 
153
*****************
 
154
 1    CONTINUE
 
155
*****************
 
156
*
 
157
      INFO = 0
 
158
      MAXIT = ITER
 
159
      TOL   = RESID
 
160
*
 
161
*     Alias workspace columns.
 
162
*
 
163
      R    = 1
 
164
      RTLD = 2
 
165
      P    = 3
 
166
      V    = 4
 
167
      T    = 5
 
168
      PHAT = 6
 
169
      SHAT = 7
 
170
      S    = 1
 
171
*
 
172
*     Check if caller will need indexing info.
 
173
*
 
174
      IF( NDX1.NE.-1 ) THEN
 
175
         IF( NDX1.EQ.1 ) THEN
 
176
            NEED1 = ((R - 1) * LDW) + 1
 
177
         ELSEIF( NDX1.EQ.2 ) THEN
 
178
            NEED1 = ((RTLD - 1) * LDW) + 1
 
179
         ELSEIF( NDX1.EQ.3 ) THEN
 
180
            NEED1 = ((P - 1) * LDW) + 1
 
181
         ELSEIF( NDX1.EQ.4 ) THEN
 
182
            NEED1 = ((V - 1) * LDW) + 1
 
183
         ELSEIF( NDX1.EQ.5 ) THEN
 
184
            NEED1 = ((T - 1) * LDW) + 1
 
185
         ELSEIF( NDX1.EQ.6 ) THEN
 
186
            NEED1 = ((PHAT - 1) * LDW) + 1
 
187
         ELSEIF( NDX1.EQ.7 ) THEN
 
188
            NEED1 = ((SHAT - 1) * LDW) + 1
 
189
         ELSEIF( NDX1.EQ.8 ) THEN
 
190
            NEED1 = ((S - 1) * LDW) + 1
 
191
         ELSE
 
192
*           report error
 
193
            INFO = -5
 
194
            GO TO 20
 
195
         ENDIF
 
196
      ELSE
 
197
         NEED1 = NDX1
 
198
      ENDIF
 
199
*
 
200
      IF( NDX2.NE.-1 ) THEN
 
201
         IF( NDX2.EQ.1 ) THEN
 
202
            NEED2 = ((R - 1) * LDW) + 1
 
203
         ELSEIF( NDX2.EQ.2 ) THEN
 
204
            NEED2 = ((RTLD - 1) * LDW) + 1
 
205
         ELSEIF( NDX2.EQ.3 ) THEN
 
206
            NEED2 = ((P - 1) * LDW) + 1
 
207
         ELSEIF( NDX2.EQ.4 ) THEN
 
208
            NEED2 = ((V - 1) * LDW) + 1
 
209
         ELSEIF( NDX2.EQ.5 ) THEN
 
210
            NEED2 = ((T - 1) * LDW) + 1
 
211
         ELSEIF( NDX2.EQ.6 ) THEN
 
212
            NEED2 = ((PHAT - 1) * LDW) + 1
 
213
         ELSEIF( NDX2.EQ.7 ) THEN
 
214
            NEED2 = ((SHAT - 1) * LDW) + 1
 
215
         ELSEIF( NDX2.EQ.8 ) THEN
 
216
            NEED2 = ((S - 1) * LDW) + 1
 
217
         ELSE
 
218
*           report error
 
219
            INFO = -5
 
220
            GO TO 20
 
221
         ENDIF
 
222
      ELSE
 
223
         NEED2 = NDX2
 
224
      ENDIF
 
225
*
 
226
*     Set parameter tolerances.
 
227
*
 
228
      RHOTOL = <sdsd>GETBREAK()
 
229
      OMEGATOL = <sdsd>GETBREAK()
 
230
*
 
231
*     Set initial residual.
 
232
*
 
233
      CALL <_c>COPY( N, B, 1, WORK(1,R), 1 )
 
234
      IF ( <rc>NRM2( N, X, 1 ).NE.ZERO ) THEN
 
235
*********CALL <_c>MATVEC( -ONE, X, ONE, WORK(1,R) )
 
236
*        Note: using RTLD[] as temp. storage.
 
237
*********CALL <_c>COPY(N, X, 1, WORK(1,RTLD), 1)
 
238
         SCLR1 = -ONE
 
239
         SCLR2 = ONE
 
240
         NDX1 = -1
 
241
         NDX2 = ((R - 1) * LDW) + 1
 
242
*
 
243
*        Prepare for resumption & return
 
244
         RLBL = 2
 
245
         IJOB = 3
 
246
         RETURN
 
247
*
 
248
*****************
 
249
 2       CONTINUE
 
250
*****************
 
251
*
 
252
         IF ( <rc>NRM2( N, WORK(1,R), 1 ).LE.TOL ) GO TO 30
 
253
      ENDIF
 
254
      CALL <_c>COPY( N, WORK(1,R), 1, WORK(1,RTLD), 1 )
 
255
*
 
256
      BNRM2 = <rc>NRM2( N, B, 1 )
 
257
      IF ( BNRM2 .EQ. ZERO ) BNRM2 = ONE
 
258
*
 
259
      ITER = 0
 
260
*
 
261
   10 CONTINUE
 
262
*
 
263
*     Perform BiConjugate Gradient Stabilized iteration.
 
264
*
 
265
         ITER = ITER + 1
 
266
*
 
267
         RHO = <xdot>( N, WORK(1,RTLD), 1, WORK(1,R), 1 )
 
268
         IF ( ABS( RHO ).LT.RHOTOL ) GO TO 25
 
269
*
 
270
*        Compute vector P.
 
271
*
 
272
         IF ( ITER.GT.1 ) THEN
 
273
            BETA = ( RHO / RHO1 ) * ( ALPHA / OMEGA )
 
274
            CALL <_c>AXPY( N, -OMEGA, WORK(1,V), 1, WORK(1,P), 1 )
 
275
            CALL <_c>SCAL( N, BETA, WORK(1,P), 1 )
 
276
            CALL <_c>AXPY( N, ONE, WORK(1,R), 1, WORK(1,P), 1 )
 
277
         ELSE
 
278
            CALL <_c>COPY( N, WORK(1,R), 1, WORK(1,P), 1 )
 
279
         ENDIF
 
280
*
 
281
*        Compute direction adjusting vector PHAT and scalar ALPHA.
 
282
*
 
283
*********CALL PSOLVE( WORK(1,PHAT), WORK(1,P) )
 
284
*
 
285
         NDX1 = ((PHAT - 1) * LDW) + 1
 
286
         NDX2 = ((P    - 1) * LDW) + 1
 
287
*        Prepare for return & return
 
288
         RLBL = 3
 
289
         IJOB = 2
 
290
         RETURN
 
291
*
 
292
*****************
 
293
 3       CONTINUE
 
294
*****************
 
295
*
 
296
*********CALL MATVEC( ONE, WORK(1,PHAT), ZERO, WORK(1,V) )
 
297
*
 
298
         NDX1 = ((PHAT - 1) * LDW) + 1
 
299
         NDX2 = ((V    - 1) * LDW) + 1
 
300
*        Prepare for return & return
 
301
         SCLR1 = ONE
 
302
         SCLR2 = ZERO
 
303
         RLBL = 4
 
304
         IJOB = 1
 
305
         RETURN
 
306
*
 
307
*****************
 
308
 4       CONTINUE
 
309
*****************
 
310
*
 
311
         ALPHA = RHO / <xdot>( N, WORK(1,RTLD), 1, WORK(1,V), 1 )
 
312
*
 
313
*        Early check for tolerance.
 
314
*
 
315
         CALL <_c>AXPY( N, -ALPHA, WORK(1,V), 1, WORK(1,R), 1 )
 
316
         CALL <_c>COPY( N, WORK(1,R), 1, WORK(1,S), 1 )
 
317
         IF ( <rc>NRM2( N, WORK(1,S), 1 ).LE.TOL ) THEN
 
318
            CALL <_c>AXPY( N, ALPHA, WORK(1,PHAT), 1, X, 1 )
 
319
            RESID = <rc>NRM2( N, WORK(1,S), 1 ) / BNRM2
 
320
            GO TO 30
 
321
         ELSE
 
322
*
 
323
*           Compute stabilizer vector SHAT and scalar OMEGA.
 
324
*
 
325
************CALL PSOLVE( WORK(1,SHAT), WORK(1,S) )
 
326
*
 
327
            NDX1 = ((SHAT - 1) * LDW) + 1
 
328
            NDX2 = ((S    - 1) * LDW) + 1
 
329
*           Prepare for return & return
 
330
            RLBL = 5
 
331
            IJOB = 2
 
332
            RETURN
 
333
*
 
334
*****************
 
335
 5          CONTINUE
 
336
*****************
 
337
*
 
338
************CALL MATVEC( ONE, WORK(1,SHAT), ZERO, WORK(1,T) )
 
339
*
 
340
            NDX1 = ((SHAT - 1) * LDW) + 1
 
341
            NDX2 = ((T    - 1) * LDW) + 1
 
342
*           Prepare for return & return
 
343
            SCLR1 = ONE
 
344
            SCLR2 = ZERO
 
345
            RLBL = 6
 
346
            IJOB = 1
 
347
            RETURN
 
348
*
 
349
*****************
 
350
 6          CONTINUE
 
351
*****************
 
352
*
 
353
            OMEGA = <xdot>( N, WORK(1,T), 1, WORK(1,S), 1 ) / 
 
354
     $              <xdot>( N, WORK(1,T), 1, WORK(1,T), 1 )
 
355
*
 
356
*           Compute new solution approximation vector X.
 
357
*
 
358
            CALL <_c>AXPY( N, ALPHA, WORK(1,PHAT), 1, X, 1 )
 
359
            CALL <_c>AXPY( N, OMEGA, WORK(1,SHAT), 1, X, 1 )
 
360
*
 
361
*           Compute residual R, check for tolerance.
 
362
*
 
363
            CALL <_c>AXPY( N, -OMEGA, WORK(1,T), 1, WORK(1,R), 1 )
 
364
*
 
365
************RESID = DNRM2( N, WORK(1,R), 1 ) / BNRM2 
 
366
************IF ( RESID.LE.TOL  ) GO TO 30
 
367
*
 
368
            NDX1 = NEED1
 
369
            NDX2 = NEED2
 
370
*           Prepare for resumption & return
 
371
            RLBL = 7
 
372
            IJOB = 4
 
373
            RETURN
 
374
*
 
375
*****************
 
376
 7          CONTINUE
 
377
*****************
 
378
            IF( INFO.EQ.1 ) GO TO 30
 
379
*
 
380
            IF ( ITER.EQ.MAXIT ) THEN
 
381
               INFO = 1
 
382
               GO TO 20
 
383
            ENDIF
 
384
*
 
385
         ENDIF
 
386
*
 
387
      IF ( ABS( OMEGA ).LT.OMEGATOL ) THEN
 
388
         GO TO 25
 
389
      ELSE
 
390
         RHO1 = RHO
 
391
         GO TO 10
 
392
      ENDIF
 
393
*
 
394
   20 CONTINUE
 
395
*
 
396
*     Iteration fails.
 
397
*
 
398
      RLBL = -1
 
399
      IJOB = -1
 
400
      RETURN
 
401
*
 
402
   25 CONTINUE
 
403
*
 
404
*     Set breakdown flag.
 
405
*
 
406
      IF ( ABS( RHO ).LT.RHOTOL ) THEN
 
407
         INFO = -10
 
408
      ELSE IF ( ABS( OMEGA ).LT.OMEGATOL ) THEN
 
409
         INFO = -11
 
410
      ENDIF
 
411
      RLBL = -1
 
412
      IJOB = -1
 
413
      RETURN
 
414
*
 
415
   30 CONTINUE
 
416
*
 
417
*     Iteration successful; return.
 
418
*
 
419
      INFO = 0
 
420
      RLBL = -1
 
421
      IJOB = -1
 
422
      RETURN
 
423
*
 
424
*     End of BICGSTABREVCOM
 
425
*
 
426
      END SUBROUTINE <_c>BICGSTABREVCOM