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