Mercurial > hg > octave-nkf
comparison scripts/sparse/pcr.m @ 10549:95c3e38098bf
Untabify .m scripts
author | Rik <code@nomad.inbox5.com> |
---|---|
date | Fri, 23 Apr 2010 11:28:50 -0700 |
parents | 1bf0ce0930be |
children | 3140cb7a05a1 |
comparison
equal
deleted
inserted
replaced
10548:479536c5bb10 | 10549:95c3e38098bf |
---|---|
98 ## Let us consider a trivial problem with a diagonal matrix (we exploit the | 98 ## Let us consider a trivial problem with a diagonal matrix (we exploit the |
99 ## sparsity of A) | 99 ## sparsity of A) |
100 ## | 100 ## |
101 ## @example | 101 ## @example |
102 ## @group | 102 ## @group |
103 ## n = 10; | 103 ## n = 10; |
104 ## a = sparse (diag (1:n)); | 104 ## a = sparse (diag (1:n)); |
105 ## b = rand (N, 1); | 105 ## b = rand (N, 1); |
106 ## @end group | 106 ## @end group |
107 ## @end example | 107 ## @end example |
108 ## | 108 ## |
109 ## @sc{Example 1:} Simplest use of @code{pcr} | 109 ## @sc{Example 1:} Simplest use of @code{pcr} |
110 ## | 110 ## |
129 ## preconditioner (quite strange, because even the original matrix | 129 ## preconditioner (quite strange, because even the original matrix |
130 ## @var{a} is trivial) is defined as a function | 130 ## @var{a} is trivial) is defined as a function |
131 ## | 131 ## |
132 ## @example | 132 ## @example |
133 ## @group | 133 ## @group |
134 ## function y = apply_m (x) | 134 ## function y = apply_m (x) |
135 ## k = floor (length(x)-2); | 135 ## k = floor (length(x)-2); |
136 ## y = x; | 136 ## y = x; |
137 ## y(1:k) = x(1:k)./[1:k]'; | 137 ## y(1:k) = x(1:k)./[1:k]'; |
138 ## endfunction | 138 ## endfunction |
139 ## | 139 ## |
140 ## [x, flag, relres, iter, resvec] = ... | 140 ## [x, flag, relres, iter, resvec] = ... |
141 ## pcr (a, b, [], [], "apply_m") | 141 ## pcr (a, b, [], [], "apply_m") |
142 ## semilogy([1:iter+1], resvec); | 142 ## semilogy([1:iter+1], resvec); |
148 ## | 148 ## |
149 ## @example | 149 ## @example |
150 ## @group | 150 ## @group |
151 ## function y = apply_m (x, varargin) | 151 ## function y = apply_m (x, varargin) |
152 ## k = varargin@{1@}; | 152 ## k = varargin@{1@}; |
153 ## y = x; y(1:k) = x(1:k)./[1:k]'; | 153 ## y = x; y(1:k) = x(1:k)./[1:k]'; |
154 ## endfunction | 154 ## endfunction |
155 ## | 155 ## |
156 ## [x, flag, relres, iter, resvec] = ... | 156 ## [x, flag, relres, iter, resvec] = ... |
157 ## pcr (a, b, [], [], "apply_m"', [], 3) | 157 ## pcr (a, b, [], [], "apply_m"', [], 3) |
158 ## @end group | 158 ## @end group |
159 ## @end example | 159 ## @end example |
160 ## | 160 ## |
161 ## @sc{References} | 161 ## @sc{References} |
162 ## | 162 ## |
163 ## [1] W. Hackbusch, "Iterative Solution of Large Sparse Systems of | 163 ## [1] W. Hackbusch, "Iterative Solution of Large Sparse Systems of |
164 ## Equations", section 9.5.4; Springer, 1994 | 164 ## Equations", section 9.5.4; Springer, 1994 |
165 ## | 165 ## |
166 ## @seealso{sparse, pcg} | 166 ## @seealso{sparse, pcg} |
167 ## @end deftypefn | 167 ## @end deftypefn |
168 | 168 |
169 ## Author: Piotr Krzyzanowski <piotr.krzyzanowski@mimuw.edu.pl> | 169 ## Author: Piotr Krzyzanowski <piotr.krzyzanowski@mimuw.edu.pl> |
195 if (nargin < 2) | 195 if (nargin < 2) |
196 print_usage (); | 196 print_usage (); |
197 endif | 197 endif |
198 | 198 |
199 ## init | 199 ## init |
200 if (isnumeric (a)) # is A a matrix? | 200 if (isnumeric (a)) # is A a matrix? |
201 r = b - a*x; | 201 r = b - a*x; |
202 else # then A should be a function! | 202 else # then A should be a function! |
203 r = b - feval (a, x, varargin{:}); | 203 r = b - feval (a, x, varargin{:}); |
204 endif | 204 endif |
205 | 205 |
206 if (isnumeric (m)) # is M a matrix? | 206 if (isnumeric (m)) # is M a matrix? |
207 if (isempty (m)) # if M is empty, use no precond | 207 if (isempty (m)) # if M is empty, use no precond |
208 p = r; | 208 p = r; |
209 else # otherwise, apply the precond | 209 else # otherwise, apply the precond |
210 p = m \ r; | 210 p = m \ r; |
211 endif | 211 endif |
212 else # then M should be a function! | 212 else # then M should be a function! |
213 p = feval (m, r, varargin{:}); | 213 p = feval (m, r, varargin{:}); |
214 endif | 214 endif |
215 | 215 |
216 iter = 2; | 216 iter = 2; |
217 | 217 |
218 b_bot_old = 1; | 218 b_bot_old = 1; |
219 q_old = p_old = s_old = zeros (size (x)); | 219 q_old = p_old = s_old = zeros (size (x)); |
220 | 220 |
221 if (isnumeric (a)) # is A a matrix? | 221 if (isnumeric (a)) # is A a matrix? |
222 q = a * p; | 222 q = a * p; |
223 else # then A should be a function! | 223 else # then A should be a function! |
224 q = feval (a, p, varargin{:}); | 224 q = feval (a, p, varargin{:}); |
225 endif | 225 endif |
226 | 226 |
227 resvec(1) = abs (norm (r)); | 227 resvec(1) = abs (norm (r)); |
228 | 228 |
229 ## iteration | 229 ## iteration |
230 while (resvec(iter-1) > tol*resvec(1) && iter < maxit) | 230 while (resvec(iter-1) > tol*resvec(1) && iter < maxit) |
231 | 231 |
232 if (isnumeric (m)) # is M a matrix? | 232 if (isnumeric (m)) # is M a matrix? |
233 if (isempty (m)) # if M is empty, use no precond | 233 if (isempty (m)) # if M is empty, use no precond |
234 s = q; | 234 s = q; |
235 else # otherwise, apply the precond | 235 else # otherwise, apply the precond |
236 s = m \ q; | 236 s = m \ q; |
237 endif | 237 endif |
238 else # then M should be a function! | 238 else # then M should be a function! |
239 s = feval (m, q, varargin{:}); | 239 s = feval (m, q, varargin{:}); |
240 endif | 240 endif |
241 b_top = r' * s; | 241 b_top = r' * s; |
242 b_bot = q' * s; | 242 b_bot = q' * s; |
243 | 243 |
244 if (b_bot == 0.0) | 244 if (b_bot == 0.0) |
245 breakdown = true; | 245 breakdown = true; |
246 break; | 246 break; |
247 endif | 247 endif |
248 lambda = b_top / b_bot; | 248 lambda = b_top / b_bot; |
249 | 249 |
250 x += lambda*p; | 250 x += lambda*p; |
251 r -= lambda*q; | 251 r -= lambda*q; |
252 | 252 |
253 if (isnumeric(a)) # is A a matrix? | 253 if (isnumeric(a)) # is A a matrix? |
254 t = a*s; | 254 t = a*s; |
255 else # then A should be a function! | 255 else # then A should be a function! |
256 t = feval (a, s, varargin{:}); | 256 t = feval (a, s, varargin{:}); |
257 endif | 257 endif |
258 | 258 |
259 alpha0 = (t'*s) / b_bot; | 259 alpha0 = (t'*s) / b_bot; |
260 alpha1 = (t'*s_old) / b_bot_old; | 260 alpha1 = (t'*s_old) / b_bot_old; |
261 | 261 |
262 p_temp = p; | 262 p_temp = p; |
263 q_temp = q; | 263 q_temp = q; |
264 | 264 |
265 p = s - alpha0*p - alpha1*p_old; | 265 p = s - alpha0*p - alpha1*p_old; |
266 q = t - alpha0*q - alpha1*q_old; | 266 q = t - alpha0*q - alpha1*q_old; |
267 | 267 |
268 s_old = s; | 268 s_old = s; |
269 p_old = p_temp; | 269 p_old = p_temp; |
270 q_old = q_temp; | 270 q_old = q_temp; |
271 b_bot_old = b_bot; | 271 b_bot_old = b_bot; |
272 | 272 |
273 resvec(iter) = abs (norm (r)); | 273 resvec(iter) = abs (norm (r)); |
274 iter++; | 274 iter++; |
275 endwhile | 275 endwhile |
276 | 276 |
277 flag = 0; | 277 flag = 0; |
284 warning ("the initial residual norm was reduced %g times.\n", 1.0/relres); | 284 warning ("the initial residual norm was reduced %g times.\n", 1.0/relres); |
285 endif | 285 endif |
286 elseif (nargout < 2 && ! breakdown) | 286 elseif (nargout < 2 && ! breakdown) |
287 fprintf (stderr, "pcr: converged in %d iterations. \n", iter); | 287 fprintf (stderr, "pcr: converged in %d iterations. \n", iter); |
288 fprintf (stderr, "the initial residual norm was reduced %g times.\n", | 288 fprintf (stderr, "the initial residual norm was reduced %g times.\n", |
289 1.0 / relres); | 289 1.0 / relres); |
290 endif | 290 endif |
291 | 291 |
292 if (breakdown) | 292 if (breakdown) |
293 flag = 3; | 293 flag = 3; |
294 if (nargout < 2) | 294 if (nargout < 2) |
299 | 299 |
300 endfunction | 300 endfunction |
301 | 301 |
302 %!demo | 302 %!demo |
303 %! | 303 %! |
304 %! # Simplest usage of PCR (see also 'help pcr') | 304 %! # Simplest usage of PCR (see also 'help pcr') |
305 %! | 305 %! |
306 %! N = 20; | 306 %! N = 20; |
307 %! A = diag(linspace(-3.1,3,N)); b = rand(N,1); y = A\b; #y is the true solution | 307 %! A = diag(linspace(-3.1,3,N)); b = rand(N,1); y = A\b; #y is the true solution |
308 %! x = pcr(A,b); | 308 %! x = pcr(A,b); |
309 %! printf('The solution relative error is %g\n', norm(x-y)/norm(y)); | 309 %! printf('The solution relative error is %g\n', norm(x-y)/norm(y)); |
310 %! | 310 %! |
311 %! # You shouldn't be afraid if PCR issues some warning messages in this | 311 %! # You shouldn't be afraid if PCR issues some warning messages in this |
312 %! # example: watch out in the second example, why it takes N iterations | 312 %! # example: watch out in the second example, why it takes N iterations |
313 %! # of PCR to converge to (a very accurate, by the way) solution | 313 %! # of PCR to converge to (a very accurate, by the way) solution |
314 %!demo | 314 %!demo |
315 %! | 315 %! |
316 %! # Full output from PCR | 316 %! # Full output from PCR |
317 %! # We use this output to plot the convergence history | 317 %! # We use this output to plot the convergence history |
318 %! | 318 %! |
319 %! N = 20; | 319 %! N = 20; |
320 %! A = diag(linspace(-3.1,30,N)); b = rand(N,1); X = A\b; #X is the true solution | 320 %! A = diag(linspace(-3.1,30,N)); b = rand(N,1); X = A\b; #X is the true solution |
321 %! [x, flag, relres, iter, resvec] = pcr(A,b); | 321 %! [x, flag, relres, iter, resvec] = pcr(A,b); |
322 %! printf('The solution relative error is %g\n', norm(x-X)/norm(X)); | 322 %! printf('The solution relative error is %g\n', norm(x-X)/norm(X)); |
323 %! title('Convergence history'); xlabel('Iteration'); ylabel('log(||b-Ax||/||b||)'); | 323 %! title('Convergence history'); xlabel('Iteration'); ylabel('log(||b-Ax||/||b||)'); |
324 %! semilogy([0:iter],resvec/resvec(1),'o-g;relative residual;'); | 324 %! semilogy([0:iter],resvec/resvec(1),'o-g;relative residual;'); |
325 %!demo | 325 %!demo |
326 %! | 326 %! |
327 %! # Full output from PCR | 327 %! # Full output from PCR |
328 %! # We use indefinite matrix based on the Hilbert matrix, with one | 328 %! # We use indefinite matrix based on the Hilbert matrix, with one |
329 %! # strongly negative eigenvalue | 329 %! # strongly negative eigenvalue |
330 %! # Hilbert matrix is extremely ill conditioned, so is ours, | 330 %! # Hilbert matrix is extremely ill conditioned, so is ours, |
331 %! # and that's why PCR WILL have problems | 331 %! # and that's why PCR WILL have problems |
332 %! | 332 %! |
333 %! N = 10; | 333 %! N = 10; |
334 %! A = hilb(N); A(1,1)=-A(1,1); b = rand(N,1); X = A\b; #X is the true solution | 334 %! A = hilb(N); A(1,1)=-A(1,1); b = rand(N,1); X = A\b; #X is the true solution |
335 %! printf('Condition number of A is %g\n', cond(A)); | 335 %! printf('Condition number of A is %g\n', cond(A)); |
336 %! [x, flag, relres, iter, resvec] = pcr(A,b,[],200); | 336 %! [x, flag, relres, iter, resvec] = pcr(A,b,[],200); |
337 %! if (flag == 3) | 337 %! if (flag == 3) |
338 %! printf('PCR breakdown. System matrix is [close to] singular\n'); | 338 %! printf('PCR breakdown. System matrix is [close to] singular\n'); |
339 %! end | 339 %! end |
340 %! title('Convergence history'); xlabel('Iteration'); ylabel('log(||b-Ax||)'); | 340 %! title('Convergence history'); xlabel('Iteration'); ylabel('log(||b-Ax||)'); |
341 %! semilogy([0:iter],resvec,'o-g;absolute residual;'); | 341 %! semilogy([0:iter],resvec,'o-g;absolute residual;'); |
342 %!demo | 342 %!demo |
343 %! | 343 %! |
344 %! # Full output from PCR | 344 %! # Full output from PCR |
345 %! # We use an indefinite matrix based on the 1-D Laplacian matrix for A, | 345 %! # We use an indefinite matrix based on the 1-D Laplacian matrix for A, |
346 %! # and here we have cond(A) = O(N^2) | 346 %! # and here we have cond(A) = O(N^2) |
347 %! # That's the reason we need some preconditioner; here we take | 347 %! # That's the reason we need some preconditioner; here we take |
348 %! # a very simple and not powerful Jacobi preconditioner, | 348 %! # a very simple and not powerful Jacobi preconditioner, |
349 %! # which is the diagonal of A | 349 %! # which is the diagonal of A |
350 %! | 350 %! |
351 %! # Note that we use here indefinite preconditioners! | 351 %! # Note that we use here indefinite preconditioners! |
352 %! | 352 %! |
353 %! N = 100; | 353 %! N = 100; |
354 %! A = zeros(N,N); | 354 %! A = zeros(N,N); |
355 %! for i=1:N-1 # form 1-D Laplacian matrix | 355 %! for i=1:N-1 # form 1-D Laplacian matrix |
356 %! A(i:i+1,i:i+1) = [2 -1; -1 2]; | 356 %! A(i:i+1,i:i+1) = [2 -1; -1 2]; |
357 %! endfor | 357 %! endfor |
358 %! A = [A, zeros(size(A)); zeros(size(A)), -A]; | 358 %! A = [A, zeros(size(A)); zeros(size(A)), -A]; |
359 %! b = rand(2*N,1); X = A\b; #X is the true solution | 359 %! b = rand(2*N,1); X = A\b; #X is the true solution |
360 %! maxit = 80; | 360 %! maxit = 80; |
361 %! printf('System condition number is %g\n',cond(A)); | 361 %! printf('System condition number is %g\n',cond(A)); |
362 %! # No preconditioner: the convergence is very slow! | 362 %! # No preconditioner: the convergence is very slow! |
363 %! | 363 %! |
364 %! [x, flag, relres, iter, resvec] = pcr(A,b,[],maxit); | 364 %! [x, flag, relres, iter, resvec] = pcr(A,b,[],maxit); |
365 %! title('Convergence history'); xlabel('Iteration'); ylabel('log(||b-Ax||)'); | 365 %! title('Convergence history'); xlabel('Iteration'); ylabel('log(||b-Ax||)'); |
366 %! semilogy([0:iter],resvec,'o-g;NO preconditioning: absolute residual;'); | 366 %! semilogy([0:iter],resvec,'o-g;NO preconditioning: absolute residual;'); |
367 %! | 367 %! |
368 %! pause(1); | 368 %! pause(1); |
369 %! # Test Jacobi preconditioner: it will not help much!!! | 369 %! # Test Jacobi preconditioner: it will not help much!!! |
370 %! | 370 %! |
371 %! M = diag(diag(A)); # Jacobi preconditioner | 371 %! M = diag(diag(A)); # Jacobi preconditioner |
372 %! [x, flag, relres, iter, resvec] = pcr(A,b,[],maxit,M); | 372 %! [x, flag, relres, iter, resvec] = pcr(A,b,[],maxit,M); |
373 %! hold on; | 373 %! hold on; |
374 %! semilogy([0:iter],resvec,'o-r;JACOBI preconditioner: absolute residual;'); | 374 %! semilogy([0:iter],resvec,'o-r;JACOBI preconditioner: absolute residual;'); |
375 %! | 375 %! |
376 %! pause(1); | 376 %! pause(1); |
377 %! # Test nonoverlapping block Jacobi preconditioner: this one should give | 377 %! # Test nonoverlapping block Jacobi preconditioner: this one should give |
378 %! # some convergence speedup! | 378 %! # some convergence speedup! |
379 %! | 379 %! |
380 %! M = zeros(N,N);k=4; | 380 %! M = zeros(N,N);k=4; |
381 %! for i=1:k:N # get k x k diagonal blocks of A | 381 %! for i=1:k:N # get k x k diagonal blocks of A |
382 %! M(i:i+k-1,i:i+k-1) = A(i:i+k-1,i:i+k-1); | 382 %! M(i:i+k-1,i:i+k-1) = A(i:i+k-1,i:i+k-1); |
383 %! endfor | 383 %! endfor |
384 %! M = [M, zeros(size(M)); zeros(size(M)), -M]; | 384 %! M = [M, zeros(size(M)); zeros(size(M)), -M]; |
385 %! [x, flag, relres, iter, resvec] = pcr(A,b,[],maxit,M); | 385 %! [x, flag, relres, iter, resvec] = pcr(A,b,[],maxit,M); |
386 %! semilogy([0:iter],resvec,'o-b;BLOCK JACOBI preconditioner: absolute residual;'); | 386 %! semilogy([0:iter],resvec,'o-b;BLOCK JACOBI preconditioner: absolute residual;'); |
387 %! hold off; | 387 %! hold off; |
388 %!test | 388 %!test |
389 %! | 389 %! |
390 %! #solve small indefinite diagonal system | 390 %! #solve small indefinite diagonal system |
391 %! | 391 %! |
392 %! N = 10; | 392 %! N = 10; |
393 %! A = diag(linspace(-10.1,10,N)); b = ones(N,1); X = A\b; #X is the true solution | 393 %! A = diag(linspace(-10.1,10,N)); b = ones(N,1); X = A\b; #X is the true solution |
394 %! [x, flag] = pcr(A,b,[],N+1); | 394 %! [x, flag] = pcr(A,b,[],N+1); |
395 %! assert(norm(x-X)/norm(X)<1e-10); | 395 %! assert(norm(x-X)/norm(X)<1e-10); |
396 %! assert(flag,0); | 396 %! assert(flag,0); |
397 %! | 397 %! |
398 %!test | 398 %!test |
399 %! | 399 %! |
400 %! #solve tridiagonal system, do not converge in default 20 iterations | 400 %! #solve tridiagonal system, do not converge in default 20 iterations |
401 %! #should perform max allowable default number of iterations | 401 %! #should perform max allowable default number of iterations |
402 %! | 402 %! |
403 %! N = 100; | 403 %! N = 100; |
404 %! A = zeros(N,N); | 404 %! A = zeros(N,N); |
405 %! for i=1:N-1 # form 1-D Laplacian matrix | 405 %! for i=1:N-1 # form 1-D Laplacian matrix |
406 %! A(i:i+1,i:i+1) = [2 -1; -1 2]; | 406 %! A(i:i+1,i:i+1) = [2 -1; -1 2]; |
407 %! endfor | 407 %! endfor |
408 %! b = ones(N,1); X = A\b; #X is the true solution | 408 %! b = ones(N,1); X = A\b; #X is the true solution |
409 %! [x, flag, relres, iter, resvec] = pcr(A,b,1e-12); | 409 %! [x, flag, relres, iter, resvec] = pcr(A,b,1e-12); |
410 %! assert(flag,1); | 410 %! assert(flag,1); |
411 %! assert(relres>0.6); | 411 %! assert(relres>0.6); |
412 %! assert(iter,20); | 412 %! assert(iter,20); |
413 %! | 413 %! |
414 %!test | 414 %!test |
415 %! | 415 %! |
416 %! #solve tridiagonal system with 'prefect' preconditioner | 416 %! #solve tridiagonal system with 'prefect' preconditioner |
417 %! #converges in one iteration | 417 %! #converges in one iteration |
418 %! | 418 %! |
419 %! N = 100; | 419 %! N = 100; |
420 %! A = zeros(N,N); | 420 %! A = zeros(N,N); |
421 %! for i=1:N-1 # form 1-D Laplacian matrix | 421 %! for i=1:N-1 # form 1-D Laplacian matrix |
422 %! A(i:i+1,i:i+1) = [2 -1; -1 2]; | 422 %! A(i:i+1,i:i+1) = [2 -1; -1 2]; |
423 %! endfor | 423 %! endfor |
424 %! b = ones(N,1); X = A\b; #X is the true solution | 424 %! b = ones(N,1); X = A\b; #X is the true solution |
425 %! [x, flag, relres, iter] = pcr(A,b,[],[],A,b); | 425 %! [x, flag, relres, iter] = pcr(A,b,[],[],A,b); |
426 %! assert(norm(x-X)/norm(X)<1e-6); | 426 %! assert(norm(x-X)/norm(X)<1e-6); |
427 %! assert(relres<1e-6); | 427 %! assert(relres<1e-6); |
428 %! assert(flag,0); | 428 %! assert(flag,0); |
429 %! assert(iter,1); #should converge in one iteration | 429 %! assert(iter,1); #should converge in one iteration |
430 %! | 430 %! |