~njansson/dolfin/hpc

« back to all changes in this revision

Viewing changes to sandbox/la/poisson/Krylov.py

  • Committer: Niclas Jansson
  • Date: 2011-06-10 14:33:43 UTC
  • Revision ID: njansson@csc.kth.se-20110610143343-d21p4am8rghiojfm
Added rudimentary header to binary files

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
 
3
 
"""
4
 
@license: Copyright (C) 2005
5
 
Author: Åsmund Ødegård, Ola Skavhaug, Gunnar Staff
6
 
 
7
 
Simula Research Laboratory AS
8
 
 
9
 
This file is part of PyCC.
10
 
 
11
 
PyCC  free software; you can redistribute it and/or modify
12
 
it under the terms of the GNU General Public License as published by
13
 
the Free Software Foundation; either version 2 of the License, or
14
 
(at your option) any later version.
15
 
 
16
 
PyCC is distributed in the hope that it will be useful,
17
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 
GNU General Public License for more details.
20
 
 
21
 
You should have received a copy of the GNU General Public License
22
 
along with PyFDM; if not, write to the Free Software
23
 
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
 
 
25
 
 
26
 
ConjGrad: A generic implementation of the (preconditioned) conjugate gradient method.
27
 
"""
28
 
 
29
 
"""
30
 
Solve Ax = b with the Krylov methods.
31
 
 
32
 
A: Matrix or discrete operator. Must support A*x to operate on x.
33
 
 
34
 
x: Anything that A can operate on, as well as support inner product
35
 
and multiplication/addition/subtraction with scalars and vectors. Also
36
 
incremental operators like __imul__ and __iadd__ might be needed
37
 
 
38
 
b: Right-hand side, probably the same type as x.
39
 
"""
40
 
 
41
 
 
42
 
 
43
 
#from debug import debug
44
 
 
45
 
def debug(string, level):
46
 
    print string
47
 
 
48
 
 
49
 
import numpy as _n
50
 
from math import sqrt
51
 
 
52
 
#debug("Deprecation warning: You have imported Krylov.py. Use Solvers.py instead",level=0)
53
 
 
54
 
def inner(u,v):
55
 
    """Compute innerproduct of u and v.
56
 
       It is not computed here, we just check type of operands and
57
 
       call a suitable innerproduct method"""
58
 
 
59
 
    if isinstance(u,_n.ndarray):
60
 
        # assume both are numarrays:
61
 
        return _n.dot(u,v)
62
 
    else:
63
 
        # assume that left operand implements inner
64
 
        return u.inner(v) 
65
 
 
66
 
"""Conjugate Gradient Methods"""
67
 
 
68
 
def conjgrad(A, x, b, tolerance=1.0E-05, relativeconv=False, maxit=500):
69
 
    """
70
 
    conjgrad(A,x,b): Solve Ax = b with the conjugate gradient method.
71
 
 
72
 
    @param A: See module documentation
73
 
    @param x: See module documentation
74
 
    @param b: See module documentation
75
 
 
76
 
    @param tolerance: Convergence criterion
77
 
    @type tolerance: float
78
 
 
79
 
    @param relativeconv: Control relative vs. absolute convergence criterion.
80
 
    That is, if relativeconv is True, ||r||_2/||r_init||_2 is used as
81
 
    convergence criterion, else just ||r||_2 is used.  Actually ||r||_2^2 is
82
 
    used, since that save a few cycles.
83
 
 
84
 
    @type relativeconv: bool
85
 
 
86
 
    @return:  the solution x.
87
 
    """
88
 
 
89
 
    r = b - A*x
90
 
    p = 1.0*r
91
 
    r0 = inner(r,r)
92
 
 
93
 
    if relativeconv:
94
 
        tolerance *= sqrt(inner(b,b))
95
 
    iter = 0
96
 
    while sqrt(r0) > tolerance and iter <= maxit:
97
 
        w = A*p
98
 
        a = r0/inner(p,w)
99
 
        x += a*p
100
 
        r -= a*w
101
 
        r1 = inner(r,r)
102
 
        p *= r1/r0
103
 
        p += r
104
 
        r0 = r1
105
 
        print "rho ", sqrt(r0)
106
 
        iter += 1
107
 
    #debug("CG finished, iter: %d, ||e||=%e" % (iter,sqrt(r0)))
108
 
    return x
109
 
 
110
 
def precondconjgrad(B, A, x, b, tolerance=1.0E-05, relativeconv=False, maxiter=500):
111
 
    r"""Preconditioned Conjugate Gradients method. Algorithm described here; 
112
 
    http://www.math-linux.com/spip.php?article55"""
113
 
    r = b - A*x
114
 
    z = B*r
115
 
    d = 1.0*z
116
 
 
117
 
    rz = inner(r,z)
118
 
 
119
 
    if relativeconv: tolerance *= sqrt(rz)
120
 
    iter = 0
121
 
    while sqrt(rz) > tolerance and iter <= maxiter:
122
 
        z = A*d
123
 
        alpha = rz / inner(d,z)
124
 
        x += alpha*d
125
 
        r -= alpha*z
126
 
        z = B*r
127
 
        rz_prev = rz
128
 
        rz = inner(r,z)
129
 
        print "rho ", sqrt(rz) 
130
 
        beta =  rz / rz_prev
131
 
        d = z + beta*d
132
 
        iter += 1
133
 
    return x
134
 
 
135
 
 
136
 
 
137
 
def old_precondconjgrad(B, A, x, b, tolerance=1.0E-05, relativeconv=False, maxiter=500):
138
 
    """
139
 
    conjgrad(B,A,x,b): Solve Ax = b with the preconditioned conjugate gradient method.
140
 
 
141
 
    @param B: Preconditioner supporting the __mul__ operator for operating on
142
 
    x.
143
 
 
144
 
    @param A: Matrix or discrete operator. Must support A*x to operate on x.
145
 
 
146
 
    @param x: Anything that A can operate on, as well as support inner product
147
 
    and multiplication/addition/subtraction with scalar and something of the
148
 
    same type
149
 
 
150
 
    @param b: Right-hand side, probably the same type as x.
151
 
 
152
 
    @param tolerance: Convergence criterion
153
 
    @type tolerance: float
154
 
 
155
 
    @param relativeconv: Control relative vs. absolute convergence criterion.
156
 
    That is, if relativeconv is True, ||r||_2/||r_init||_2 is used as
157
 
    convergence criterion, else just ||r||_2 is used.  Actually ||r||_2^2 is
158
 
    used, since that save a few cycles.
159
 
 
160
 
    @type relativeconv: bool
161
 
 
162
 
    @return:  the solution x.
163
 
 
164
 
    """
165
 
 
166
 
    r0 = b - A*x
167
 
    r = 1.0*r0
168
 
    z = 1.0*r
169
 
    s = B*r
170
 
    p = 1.0*s
171
 
    rho = rho0 = inner(s, r)
172
 
    if relativeconv:
173
 
        tolerance *= sqrt(inner(B*b,b))
174
 
    iter = 0
175
 
    while sqrt(rho0) > tolerance and iter <= maxiter:
176
 
        z = A*p
177
 
        t = B*z
178
 
        g = inner(p,z)
179
 
        a = rho0/g
180
 
        x += a*p
181
 
        r -= a*z
182
 
        s -= a*t
183
 
        rho = inner(s, r)
184
 
        b = rho/rho0
185
 
        p *= b; p += s
186
 
        rho0 = rho
187
 
        iter += 1
188
 
    debug("PCG finished, iter: %d, ||rho||=%e" % (iter,sqrt(rho0)))
189
 
    return x
190
 
 
191
 
 
192
 
"""Bi-conjugate gradients method"""
193
 
 
194
 
def BiCGStab(A, x, b, tolerance=1.0E-05, relativeconv=False, maxiter=1000, info=False):
195
 
    """
196
 
    BiCGStab(A,x,b): Solve Ax = b with the Biconjugate gradient stabilized
197
 
    method.
198
 
 
199
 
    @param A: Matrix or discrete operator. Must support A*x to operate on x.
200
 
 
201
 
    @param x: Anything that A can operate on, as well as support inner product
202
 
    and multiplication/addition/subtraction with scalar and something of the
203
 
    same type
204
 
 
205
 
    @param b: Right-hand side, probably the same type as x.
206
 
 
207
 
    @param tolerance: Convergence criterion
208
 
    @type tolerance: float
209
 
 
210
 
    @param relativeconv: Control relative vs. absolute convergence criterion.
211
 
    That is, if relativeconv is True, ||r||_2/||r_init||_2 is used as
212
 
    convergence criterion, else just ||r||_2 is used.  Actually ||r||_2^2 is
213
 
    used, since that save a few cycles.
214
 
 
215
 
    @type relativeconv: bool
216
 
 
217
 
    @return:  the solution x.
218
 
    """
219
 
 
220
 
    r = b - A*x
221
 
    p = r.copy()
222
 
    rs= r.copy()
223
 
    rr = inner(r,rs)
224
 
 
225
 
    if relativeconv:
226
 
        tolerance *= sqrt(inner(b,b))
227
 
    iter = 0
228
 
    debug("r0=" +  str(sqrt(inner(r,r))), 0)
229
 
    while sqrt(inner(r,r)) > tolerance  and  iter < maxiter:
230
 
        Ap    = A*p
231
 
        alpha = rr/inner(rs,Ap)
232
 
        print "alpha ", alpha
233
 
        s     = r-alpha*Ap
234
 
        As    = A*s
235
 
        w     = inner(As,s)/inner(As,As)
236
 
        x    += alpha*p+w*s
237
 
        r     = s -w*As
238
 
#        r = b - A*x
239
 
        rrn   = inner(r,rs)
240
 
        beta  = (rrn/rr)*(alpha/w)
241
 
        if beta==0.0:
242
 
            debug("BiCGStab breakdown, beta=0, at iter=" + str(iter) + " with residual=" + str(sqrt(inner(r,r))), 0)
243
 
#            return (x,iter,sqrt(inner(r,r)))
244
 
            return x 
245
 
        rr    = rrn
246
 
        p     = r+beta*(p-w*Ap)
247
 
        iter += 1
248
 
        #debug("r=",sqrt(inner(r,r)))
249
 
    debug("BiCGStab finished, iter: " + str(iter) + "|r|= " + str(sqrt(inner(r,r))), 0)
250
 
    if info:
251
 
        info = {}
252
 
        info["iter"] = iter
253
 
        print "Her jeg her" 
254
 
        return x, info
255
 
    return x
256
 
 
257
 
 
258
 
def precondBiCGStab(B, A, x, b, tolerance=1.0E-05, relativeconv=False, maxit=200):
259
 
    """
260
 
    precondBiCGStab(B,A,x,b): Solve Ax = b with the preconditioned biconjugate
261
 
    gradient stabilized method.
262
 
 
263
 
    @param B: Preconditioner supporting the __mul__ operator for operating on
264
 
    x.
265
 
 
266
 
    @param A: Matrix or discrete operator. Must support A*x to operate on x.
267
 
 
268
 
    @param x: Anything that A can operate on, as well as support inner product
269
 
    and multiplication/addition/subtraction with scalar and something of the
270
 
    same type
271
 
 
272
 
    @param b: Right-hand side, probably the same type as x.
273
 
 
274
 
    @param tolerance: Convergence criterion
275
 
    @type tolerance: float
276
 
 
277
 
    @param relativeconv: Control relative vs. absolute convergence criterion.
278
 
    That is, if relativeconv is True, ||r||_2/||r_init||_2 is used as
279
 
    convergence criterion, else just ||r||_2 is used.  Actually ||r||_2^2 is
280
 
    used, since that save a few cycles.
281
 
 
282
 
    @type relativeconv: bool
283
 
 
284
 
    @return:  the solution x.
285
 
 
286
 
    """
287
 
 
288
 
 
289
 
    r = b - A*x
290
 
 
291
 
    debug("b0=%e"%sqrt(inner(b,b)),1)
292
 
    p = r.copy()
293
 
    rs= r.copy()
294
 
    rr = inner(r,rs)
295
 
 
296
 
 
297
 
 
298
 
    if relativeconv:
299
 
        tolerance *= sqrt(inner(B*r,r))
300
 
    iter = 0
301
 
    # Alloc w
302
 
    debug("r0=%e"%sqrt(inner(r,r)),1)
303
 
    while sqrt(inner(r,r)) > tolerance and iter <= maxit:
304
 
        #debug("iter, sqrt(inner(r,r))", iter, sqrt(inner(r,r)))
305
 
        ph    = B*p
306
 
        Ap    = A*ph
307
 
        alpha = rr/inner(rs,Ap)
308
 
        s     = r-alpha*Ap
309
 
        sh    = B*s
310
 
        As    = A*sh
311
 
        w     = inner(As,s)/inner(As,As)
312
 
        x    += alpha*ph+w*sh
313
 
        r     = s -w*As
314
 
        rrn   = inner(r,rs)
315
 
        beta  = (rrn/rr)*(alpha/w)
316
 
        if beta==0.0:
317
 
            debug("BiCGStab breakdown, beta=0, at iter=" + str(iter)+" with residual=" + str(sqrt(inner(r,r))), 0)
318
 
#            return (x,iter,sqrt(inner(r,r)))
319
 
            return x
320
 
        debug("|r|_%d = %e " %(iter,sqrt(inner(r,r))), 1)
321
 
        rr    = rrn
322
 
        p     = r+beta*(p-w*Ap)
323
 
        iter += 1
324
 
 
325
 
    debug("precondBiCGStab finished, iter: %d, ||e||=%e" % (iter,sqrt(inner(r,r))),1)
326
 
    return (x,iter,sqrt(inner(r,r)))
327
 
 
328
 
 
329
 
def precondLBiCGStab(B, A, x, b, tolerance=1.0E-05, relativeconv=False):
330
 
    """
331
 
    precondBiCGStab(B,A,x,b): Solve Ax = b with the preconditioned biconjugate
332
 
    gradient stabilized method.
333
 
 
334
 
    @param B: Preconditioner supporting the __mul__ operator for operating on
335
 
    x.
336
 
 
337
 
    @param A: Matrix or discrete operator. Must support A*x to operate on x.
338
 
 
339
 
    @param x: Anything that A can operate on, as well as support inner product
340
 
    and multiplication/addition/subtraction with scalar and something of the
341
 
    same type
342
 
 
343
 
    @param b: Right-hand side, probably the same type as x.
344
 
 
345
 
    @param tolerance: Convergence criterion
346
 
    @type tolerance: float
347
 
 
348
 
    @param relativeconv: Control relative vs. absolute convergence criterion.
349
 
    That is, if relativeconv is True, ||r||_2/||r_init||_2 is used as
350
 
    convergence criterion, else just ||r||_2 is used.  Actually ||r||_2^2 is
351
 
    used, since that save a few cycles.
352
 
 
353
 
    @type relativeconv: bool
354
 
 
355
 
    @return:  the solution x.
356
 
 
357
 
    """
358
 
 
359
 
    r = b - A*x
360
 
    p = 1.0*r
361
 
    rs= 1.0*r
362
 
    rr = inner(r,rs)
363
 
 
364
 
    if relativeconv:
365
 
        tolerance *= sqrt(inner(b,b))
366
 
    iter = 0
367
 
    while sqrt(inner(r,r)) > tolerance:
368
 
        Ap    = A*p
369
 
        BAp   = B*Ap
370
 
        alpha = rr/inner(rs,BAp)
371
 
        s     = r-alpha*BAp
372
 
        As    = A*s
373
 
        BAs   = B*As
374
 
        w     = inner(BAs,s)/inner(BAs,BAs)
375
 
        x    += alpha*p+w*s
376
 
        r     = s -w*BAs
377
 
        rrn   = inner(r,rs)
378
 
        beta  = (rrn/rr)*(alpha/w)
379
 
        rr    = rrn
380
 
        p     = r+beta*(p-w*BAp)
381
 
        iter += 1
382
 
    debug("precondBiCGStab finished, iter: %d, ||e||=%e" % (iter,sqrt(inner(r,r))))
383
 
    return (x,iter)
384
 
 
385
 
 
386
 
"""Conjugate Gradients Method for the normal equations"""
387
 
 
388
 
def CGN_AA(A, x, b, tolerance=1.0E-05, relativeconv=False):
389
 
    """
390
 
    CGN_AA(B,A,x,b): Solve Ax = b with the conjugate
391
 
    gradient method applied to the normal equation.
392
 
 
393
 
 
394
 
    @param A: Matrix or discrete operator. Must support A*x to operate on x.
395
 
 
396
 
    @param x: Anything that A can operate on, as well as support inner product
397
 
    and multiplication/addition/subtraction with scalar and something of the
398
 
    same type
399
 
 
400
 
    @param b: Right-hand side, probably the same type as x.
401
 
 
402
 
    @param tolerance: Convergence criterion
403
 
    @type tolerance: float
404
 
 
405
 
    @param relativeconv: Control relative vs. absolute convergence criterion.
406
 
    That is, if relativeconv is True, ||r||_2/||r_init||_2 is used as
407
 
    convergence criterion, else just ||r||_2 is used.  Actually ||r||_2^2 is
408
 
    used, since that save a few cycles.
409
 
 
410
 
    @type relativeconv: bool
411
 
 
412
 
    @return:  the solution x.
413
 
 
414
 
    """
415
 
 
416
 
    """
417
 
    Allocate some memory
418
 
    """
419
 
    r_a   = 1.0*x
420
 
    p_aa  = 1.0*x
421
 
 
422
 
 
423
 
    r = b - A*x
424
 
    bnrm2=sqrt(inner(b,b))
425
 
    A.prod(r,r_a,True)
426
 
 
427
 
    rho=inner(r_a,r_a)
428
 
    rho1=rho
429
 
    p = 1.0*r_a
430
 
 
431
 
    # Used to compute an estimate of the condition number
432
 
    alpha_v=[]
433
 
    beta_v=[]
434
 
    iter=0
435
 
    error   = sqrt(rho)/bnrm2
436
 
    debug("error0="+str(error), 0)
437
 
 
438
 
    while error>=tolerance:
439
 
        p_a     = A*p
440
 
        A.prod(p_a,p_aa)
441
 
        alpha   = rho/inner(p,p_aa)
442
 
        x       = x + alpha*p
443
 
        r       = b-A*x
444
 
        A.prod(r,r_a,True)
445
 
        rho     = inner(r_a,r_a)
446
 
        beta    = rho/rho1
447
 
        error   = sqrt(rho)/bnrm2
448
 
        debug("error = " + str(error), 0)
449
 
 
450
 
        alpha_v.append(alpha)
451
 
        beta_v.append(beta)
452
 
 
453
 
        rho1    = rho
454
 
        p       = r_a+beta*p
455
 
        iter   += 1
456
 
 
457
 
 
458
 
    debug("CGN_ABBA finished, iter: %d, ||e||=%e" % (iter,error))
459
 
    return (x,iter,alpha_v,beta_v)
460
 
 
461
 
def CGN_ABBA(B, A, x, b, tolerance=1.0E-05, relativeconv=False):
462
 
    """
463
 
    CGN_ABBA(B,A,x,b): Solve Ax = b with the preconditioned conjugate
464
 
    gradient method applied to the normal equation.
465
 
 
466
 
    @param B: Preconditioner supporting the __mul__ operator for operating on
467
 
    x.
468
 
 
469
 
    @param A: Matrix or discrete operator. Must support A*x to operate on x.
470
 
 
471
 
    @param x: Anything that A can operate on, as well as support inner product
472
 
    and multiplication/addition/subtraction with scalar and something of the
473
 
    same type
474
 
 
475
 
    @param b: Right-hand side, probably the same type as x.
476
 
 
477
 
    @param tolerance: Convergence criterion
478
 
    @type tolerance: float
479
 
 
480
 
    @param relativeconv: Control relative vs. absolute convergence criterion.
481
 
    That is, if relativeconv is True, ||r||_2/||r_init||_2 is used as
482
 
    convergence criterion, else just ||r||_2 is used.  Actually ||r||_2^2 is
483
 
    used, since that save a few cycles.
484
 
 
485
 
    @type relativeconv: bool
486
 
 
487
 
    @return:  the solution x.
488
 
 
489
 
    """
490
 
 
491
 
    """
492
 
    Allocate some memory
493
 
    """
494
 
    r_bb   = 1.0*x
495
 
    r_abb  = 1.0*x
496
 
    p_bba  = 1.0*x
497
 
    p_abba = 1.0*x
498
 
 
499
 
    r = b - A*x
500
 
 
501
 
    bnrm2 = sqrt(inner(b,b))
502
 
    r_b = B*r
503
 
    r_bb = B*r_b #Should be transposed
504
 
 
505
 
    A.data[0][0].prod(r_bb[0],r_abb[0])
506
 
    A.prod(r_bb,r_abb,True)
507
 
 
508
 
    rho=inner(r_abb,r_abb)
509
 
    rho1=rho
510
 
    p=r_abb.copy()
511
 
 
512
 
    # Used to compute an estimate of the condition number
513
 
    alpha_v=[]
514
 
    beta_v=[]
515
 
    iter=0
516
 
    error  = sqrt(rho)/bnrm2
517
 
 
518
 
    while error>=tolerance:
519
 
        p_a     = A*p
520
 
        p_ba    = B*p_a;
521
 
        p_bba   = B*p_ba
522
 
        A.prod(p_bba,p_abba)
523
 
        alpha   = rho/inner(p,p_abba)
524
 
        x       = x + alpha*p
525
 
        r       = b-A*x
526
 
        r_b     = B*r
527
 
        r_bb    = B*r_b
528
 
        A.prod(r_bb,r_abb,True)
529
 
        rho     = inner(r_abb,r_abb)
530
 
        beta    = rho/rho1
531
 
        error   = sqrt(rho)/bnrm2
532
 
        debug("i = ", error)
533
 
 
534
 
        alpha_v.append(alpha)
535
 
        beta_v.append(beta)
536
 
 
537
 
        rho1    = rho
538
 
        p       = r_abb+beta*p
539
 
        iter   += 1
540
 
 
541
 
 
542
 
    debug("CGN_ABBA finished, iter: %d, ||e||=%e" % (iter,error))
543
 
    return (x,iter,alpha_v,beta_v)
544
 
 
545
 
 
546
 
 
547
 
 
548
 
def CGN_BABA(B, A, x, b, tolerance=1.0E-05, relativeconv=False):
549
 
    """
550
 
    CGN_BABA(B,A,x,b): Solve Ax = b with the preconditioned conjugate
551
 
    gradient method applied to the normal equation.
552
 
 
553
 
    @param B: Preconditioner supporting the __mul__ operator for operating on
554
 
    x.
555
 
 
556
 
    @param A: Matrix or discrete operator. Must support A*x to operate on x.
557
 
 
558
 
    @param x: Anything that A can operate on, as well as support inner product
559
 
    and multiplication/addition/subtraction with scalar and something of the
560
 
    same type
561
 
 
562
 
    @param b: Right-hand side, probably the same type as x.
563
 
 
564
 
    @param tolerance: Convergence criterion
565
 
    @type tolerance: float
566
 
 
567
 
    @param relativeconv: Control relative vs. absolute convergence criterion.
568
 
    That is, if relativeconv is True, ||r||_2/||r_init||_2 is used as
569
 
    convergence criterion, else just ||r||_2 is used.  Actually ||r||_2^2 is
570
 
    used, since that save a few cycles.
571
 
 
572
 
    @type relativeconv: bool
573
 
 
574
 
    @return:  the solution x.
575
 
 
576
 
    """
577
 
 
578
 
    # Is this correct?? Should we not transpose the preconditoner somewhere??
579
 
 
580
 
    """
581
 
    Allocate some memory
582
 
    """
583
 
    r_ab   = 1.0*x
584
 
    p_aba  = 1.0*x
585
 
 
586
 
    r      = b - A*x
587
 
    bnrm2  = sqrt(inner(b,b))
588
 
    r_b    = B*r
589
 
    A.prod(r_b,r_ab,True)
590
 
    r_bab  = B*r_ab
591
 
 
592
 
    rho     = inner(r_bab,r_ab)
593
 
    rho1    = rho
594
 
    p       = r_bab.copy()
595
 
 
596
 
    # Used to compute an estimate of the condition number
597
 
    alpha_v=[]
598
 
    beta_v=[]
599
 
    iter=0
600
 
    error   = sqrt(rho)/bnrm2
601
 
 
602
 
    while error>=tolerance:
603
 
        p_a     = A*p
604
 
        p_ba    = B*p_a;
605
 
        A.prod(p_ba,p_aba,True)
606
 
        p_baba  = B*p_aba
607
 
        alpha   = rho/inner(p,p_aba)
608
 
        x       = x + alpha*p
609
 
        r       = b-A*x
610
 
        r_b     = B*r
611
 
        A.prod(r_b,r_ab,True)
612
 
        r_bab   = A*r_ab
613
 
        rho     = inner(r_bab,r_ab)
614
 
        beta    = rho/rho1
615
 
        error   = sqrt(rho)/bnrm2
616
 
 
617
 
        alpha_v.append(alpha)
618
 
        beta_v.append(beta)
619
 
 
620
 
        rho1    = rho
621
 
        p       = r_bab+beta*p
622
 
        iter   += 1
623
 
 
624
 
 
625
 
    debug("CGN_BABA finished, iter: %d, ||e||=%e" % (iter,error))
626
 
    return (x,iter,alpha_v,beta_v)
627
 
 
628
 
 
629
 
 
630
 
def precondRconjgrad(B, A, x, b, tolerance=1.0E-05, relativeconv=False):
631
 
    """
632
 
    conjgrad(B,A,x,b): Solve Ax = b with the right preconditioned conjugate gradient method.
633
 
 
634
 
    @param B: Preconditioner supporting the __mul__ operator for operating on
635
 
    x.
636
 
 
637
 
    @param A: Matrix or discrete operator. Must support A*x to operate on x.
638
 
 
639
 
    @param x: Anything that A can operate on, as well as support inner product
640
 
    and multiplication/addition/subtraction with scalar and something of the
641
 
    same type
642
 
 
643
 
    @param b: Right-hand side, probably the same type as x.
644
 
 
645
 
    @param tolerance: Convergence criterion
646
 
    @type tolerance: float
647
 
 
648
 
    @param relativeconv: Control relative vs. absolute convergence criterion.
649
 
    That is, if relativeconv is True, ||r||_2/||r_init||_2 is used as
650
 
    convergence criterion, else just ||r||_2 is used.  Actually ||r||_2^2 is
651
 
    used, since that save a few cycles.
652
 
 
653
 
    @type relativeconv: bool
654
 
 
655
 
    @return:  the solution x.
656
 
 
657
 
    """
658
 
 
659
 
    r0 = b - A*x
660
 
    r = 1.0*r0
661
 
    z = B*r
662
 
    q = z.copy()
663
 
    rho = rho0 = inner(z, r)
664
 
    if relativeconv:
665
 
        tolerance *= sqrt(inner(B*b,b))
666
 
    alpha_v=[]
667
 
    beta_v=[]
668
 
    iter=0
669
 
 
670
 
    while sqrt(fabs(rho0)) > tolerance:
671
 
        Aq=A*q
672
 
        alpha = rho0/inner(Aq,q)
673
 
 
674
 
        x += alpha*q
675
 
        r -= alpha*Aq
676
 
        z  = B*r
677
 
        rho = inner(z, r)
678
 
        beta = rho/rho0
679
 
        q = z+beta*q
680
 
        rho0 = rho
681
 
        alpha_v.append(alpha)
682
 
        beta_v.append(beta)
683
 
        iter += 1
684
 
    return (x,iter,alpha_v,beta_v)
685
 
 
686
 
 
687
 
def Richardson(A, x, b, tau=1, tolerance=1.0E-05, relativeconv=False, maxiter=1000, info=False):
688
 
 
689
 
    print "b ", b.inner(b)
690
 
#    b.disp()
691
 
    print "x ", x.inner(x)
692
 
 
693
 
 
694
 
    r = b - A*x
695
 
    print "r ", r.inner(r)
696
 
    rho = rho0 = inner(r, r)
697
 
    if relativeconv:
698
 
        tolerance *= sqrt(inner(b,b))
699
 
    print "tolerance ", tolerance
700
 
    iter = 0
701
 
    while sqrt(rho) > tolerance and iter <= maxiter:
702
 
        x += tau*r
703
 
        r = b - A*x
704
 
        rho = inner(r,r)
705
 
        print "iteration ", iter, " rho= ",  sqrt(rho)
706
 
        iter += 1
707
 
    return x 
708
 
 
709
 
 
710
 
def precRichardson(B, A, x, b, tau=1, tolerance=1.0E-05, relativeconv=False, maxiter=1000, info=False):
711
 
 
712
 
    print "b ", b.inner(b)
713
 
    print "x ", x.inner(x)
714
 
 
715
 
    r = b - A*x
716
 
    print "r ", r.inner(r)
717
 
    s = B*r
718
 
    rho = rho0 = inner(r, r)
719
 
    if relativeconv:
720
 
        tolerance *= sqrt(inner(b,b))
721
 
    print "tolerance ", tolerance
722
 
    iter = 0
723
 
    while sqrt(rho) > tolerance and iter <= maxiter:
724
 
        x += tau*s
725
 
        r = b - A*x
726
 
        s = B*r 
727
 
        rho = inner(r,r)
728
 
        print "iteration ", iter, " rho= ",  sqrt(rho)
729
 
        iter += 1
730
 
    return x 
731
 
 
732
 
 
733
 
 
734
 
 
735
 
 
736