ivan@154
|
1 % cgsolve.m
|
ivan@154
|
2 %
|
ivan@154
|
3 % Solve a symmetric positive definite system Ax = b via conjugate gradients.
|
ivan@154
|
4 %
|
ivan@154
|
5 % Usage: [x, res, iter] = cgsolve(A, b, tol, maxiter, verbose)
|
ivan@154
|
6 %
|
ivan@154
|
7 % A - Either an NxN matrix, or a function handle.
|
ivan@154
|
8 %
|
ivan@154
|
9 % b - N vector
|
ivan@154
|
10 %
|
ivan@154
|
11 % tol - Desired precision. Algorithm terminates when
|
ivan@154
|
12 % norm(Ax-b)/norm(b) < tol .
|
ivan@154
|
13 %
|
ivan@154
|
14 % maxiter - Maximum number of iterations.
|
ivan@154
|
15 %
|
ivan@154
|
16 % verbose - If 0, do not print out progress messages.
|
ivan@154
|
17 % Default = 1.
|
ivan@154
|
18 %
|
ivan@154
|
19 % Written by: Justin Romberg, Caltech
|
ivan@154
|
20 % Email: jrom@acm.caltech.edu
|
ivan@154
|
21 % Created: October 2005
|
ivan@154
|
22 %
|
ivan@154
|
23
|
ivan@154
|
24 function [x, res, iter] = cgsolve(A, b, tol, maxiter, verbose)
|
ivan@154
|
25
|
ivan@154
|
26 if (nargin < 5), verbose = 1; end
|
ivan@154
|
27
|
ivan@154
|
28 implicit = isa(A,'function_handle');
|
ivan@154
|
29
|
ivan@154
|
30 x = zeros(length(b),1);
|
ivan@154
|
31 r = b;
|
ivan@154
|
32 d = r;
|
ivan@154
|
33 delta = r'*r;
|
ivan@154
|
34 delta0 = b'*b;
|
ivan@154
|
35 numiter = 0;
|
ivan@154
|
36 bestx = x;
|
ivan@154
|
37 bestres = sqrt(delta/delta0);
|
ivan@154
|
38 while ((numiter < maxiter) & (delta > tol^2*delta0))
|
ivan@154
|
39
|
ivan@154
|
40 % q = A*d
|
ivan@154
|
41 if (implicit), q = A(d); else, q = A*d; end
|
ivan@154
|
42
|
ivan@154
|
43 alpha = delta/(d'*q);
|
ivan@154
|
44 x = x + alpha*d;
|
ivan@154
|
45
|
ivan@154
|
46 if (mod(numiter+1,50) == 0)
|
ivan@154
|
47 % r = b - Aux*x
|
ivan@154
|
48 if (implicit), r = b - A(x); else, r = b - A*x; end
|
ivan@154
|
49 else
|
ivan@154
|
50 r = r - alpha*q;
|
ivan@154
|
51 end
|
ivan@154
|
52
|
ivan@154
|
53 deltaold = delta;
|
ivan@154
|
54 delta = r'*r;
|
ivan@154
|
55 beta = delta/deltaold;
|
ivan@154
|
56 d = r + beta*d;
|
ivan@154
|
57 numiter = numiter + 1;
|
ivan@154
|
58 if (sqrt(delta/delta0) < bestres)
|
ivan@154
|
59 bestx = x;
|
ivan@154
|
60 bestres = sqrt(delta/delta0);
|
ivan@154
|
61 end
|
ivan@154
|
62
|
ivan@154
|
63 if ((verbose) & (mod(numiter,50)==0))
|
ivan@154
|
64 disp(sprintf('cg: Iter = %d, Best residual = %8.3e, Current residual = %8.3e', ...
|
ivan@154
|
65 numiter, bestres, sqrt(delta/delta0)));
|
ivan@154
|
66 end
|
ivan@154
|
67
|
ivan@154
|
68 end
|
ivan@154
|
69
|
ivan@154
|
70 if (verbose)
|
ivan@154
|
71 disp(sprintf('cg: Iterations = %d, best residual = %14.8e', numiter, bestres));
|
ivan@154
|
72 end
|
ivan@154
|
73 x = bestx;
|
ivan@154
|
74 res = bestres;
|
ivan@154
|
75 iter = numiter;
|
ivan@154
|
76
|