Mercurial > octave
comparison scripts/sparse/pcg.m @ 30893:e1788b1a315f
maint: Use "fcn" as preferred abbreviation for "function" in m-files.
* accumarray.m, accumdim.m, quadl.m, quadv.m, randi.m, structfun.m,
__is_function__.m, uigetfile.m, uimenu.m, uiputfile.m, doc_cache_create.m,
colorspace_conversion_input_check.m, imageIO.m, argnames.m, vectorize.m,
vectorize.m, normest1.m, inputname.m, nthargout.m, display_info_file.m,
decic.m, ode15i.m, ode15s.m, ode23.m, ode23s.m, ode45.m, odeset.m,
check_default_input.m, integrate_adaptive.m, ode_event_handler.m,
runge_kutta_23.m, runge_kutta_23s.m, runge_kutta_45_dorpri.m,
runge_kutta_interpolate.m, starting_stepsize.m, __all_opts__.m, fminbnd.m,
fminsearch.m, fminunc.m, fsolve.m, fzero.m, sqp.m, fplot.m, plotyy.m,
__bar__.m, __ezplot__.m, flat_entry.html, profexport.m, movfun.m, bicg.m,
bicgstab.m, cgs.m, eigs.m, gmres.m, pcg.m, __alltohandles__.m, __sprand__.m,
qmr.m, tfqmr.m, dump_demos.m:
Replace "func", "fun", "fn" in documentation and variable names with "fcn".
author | Rik <rik@octave.org> |
---|---|
date | Mon, 04 Apr 2022 18:14:56 -0700 |
parents | 796f54d4ddbf |
children | 597f3ee61a48 |
comparison
equal
deleted
inserted
replaced
30892:1a3cc2811090 | 30893:e1788b1a315f |
---|---|
34 ## The input arguments are: | 34 ## The input arguments are: |
35 ## | 35 ## |
36 ## @itemize | 36 ## @itemize |
37 ## @item @var{A} is the matrix of the linear system and it must be square. | 37 ## @item @var{A} is the matrix of the linear system and it must be square. |
38 ## @var{A} can be passed as a matrix, function handle, or inline function | 38 ## @var{A} can be passed as a matrix, function handle, or inline function |
39 ## @code{Afun} such that @code{Afun(x) = A * x}. Additional parameters to | 39 ## @code{Afcn} such that @code{Afcn(x) = A * x}. Additional parameters to |
40 ## @code{Afun} may be passed after @var{x0}. | 40 ## @code{Afcn} may be passed after @var{x0}. |
41 ## | 41 ## |
42 ## @var{A} has to be Hermitian and Positive Definite (@nospell{HPD})@. If | 42 ## @var{A} has to be Hermitian and Positive Definite (@nospell{HPD})@. If |
43 ## @code{pcg} detects @var{A} not to be positive definite, a warning is printed | 43 ## @code{pcg} detects @var{A} not to be positive definite, a warning is printed |
44 ## and the @var{flag} output is set. | 44 ## and the @var{flag} output is set. |
45 ## | 45 ## |
161 ## A = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, n)); | 161 ## A = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, n)); |
162 ## b = A * ones (n, 1); | 162 ## b = A * ones (n, 1); |
163 ## M1 = ichol (A); # in this tridiagonal case it corresponds to chol (A)' | 163 ## M1 = ichol (A); # in this tridiagonal case it corresponds to chol (A)' |
164 ## M2 = M1'; | 164 ## M2 = M1'; |
165 ## M = M1 * M2; | 165 ## M = M1 * M2; |
166 ## Afun = @@(x) A * x; | 166 ## Afcn = @@(x) A * x; |
167 ## Mfun = @@(x) M \ x; | 167 ## Mfcn = @@(x) M \ x; |
168 ## M1fun = @@(x) M1 \ x; | 168 ## M1fcn = @@(x) M1 \ x; |
169 ## M2fun = @@(x) M2 \ x; | 169 ## M2fcn = @@(x) M2 \ x; |
170 ## @end group | 170 ## @end group |
171 ## @end example | 171 ## @end example |
172 ## | 172 ## |
173 ## @sc{Example 1:} Simplest use of @code{pcg} | 173 ## @sc{Example 1:} Simplest use of @code{pcg} |
174 ## | 174 ## |
178 ## | 178 ## |
179 ## @sc{Example 2:} @code{pcg} with a function which computes | 179 ## @sc{Example 2:} @code{pcg} with a function which computes |
180 ## @code{@var{A} * @var{x}} | 180 ## @code{@var{A} * @var{x}} |
181 ## | 181 ## |
182 ## @example | 182 ## @example |
183 ## x = pcg (Afun, b) | 183 ## x = pcg (Afcn, b) |
184 ## @end example | 184 ## @end example |
185 ## | 185 ## |
186 ## @sc{Example 3:} @code{pcg} with a preconditioner matrix @var{M} | 186 ## @sc{Example 3:} @code{pcg} with a preconditioner matrix @var{M} |
187 ## | 187 ## |
188 ## @example | 188 ## @example |
190 ## @end example | 190 ## @end example |
191 ## | 191 ## |
192 ## @sc{Example 4:} @code{pcg} with a function as preconditioner | 192 ## @sc{Example 4:} @code{pcg} with a function as preconditioner |
193 ## | 193 ## |
194 ## @example | 194 ## @example |
195 ## x = pcg (Afun, b, 1e-6, 100, Mfun) | 195 ## x = pcg (Afcn, b, 1e-6, 100, Mfcn) |
196 ## @end example | 196 ## @end example |
197 ## | 197 ## |
198 ## @sc{Example 5:} @code{pcg} with preconditioner matrices @var{M1} | 198 ## @sc{Example 5:} @code{pcg} with preconditioner matrices @var{M1} |
199 ## and @var{M2} | 199 ## and @var{M2} |
200 ## | 200 ## |
203 ## @end example | 203 ## @end example |
204 ## | 204 ## |
205 ## @sc{Example 6:} @code{pcg} with functions as preconditioners | 205 ## @sc{Example 6:} @code{pcg} with functions as preconditioners |
206 ## | 206 ## |
207 ## @example | 207 ## @example |
208 ## x = pcg (Afun, b, 1e-6, 100, M1fun, M2fun) | 208 ## x = pcg (Afcn, b, 1e-6, 100, M1fcn, M2fcn) |
209 ## @end example | 209 ## @end example |
210 ## | 210 ## |
211 ## @sc{Example 7:} @code{pcg} with as input a function requiring an argument | 211 ## @sc{Example 7:} @code{pcg} with as input a function requiring an argument |
212 ## | 212 ## |
213 ## @example | 213 ## @example |
216 ## y = x; | 216 ## y = x; |
217 ## for i = 1:p | 217 ## for i = 1:p |
218 ## y = A * y; | 218 ## y = A * y; |
219 ## endfor | 219 ## endfor |
220 ## endfunction | 220 ## endfunction |
221 ## Apfun = @@(x, p) Ap (A, x, p); | 221 ## Apfcn = @@(x, p) Ap (A, x, p); |
222 ## x = pcg (Apfun, b, [], [], [], [], [], 2); | 222 ## x = pcg (Apfcn, b, [], [], [], [], [], 2); |
223 ## @end group | 223 ## @end group |
224 ## @end example | 224 ## @end example |
225 ## | 225 ## |
226 ## @sc{Example 8:} explicit example to show that @code{pcg} uses a | 226 ## @sc{Example 8:} explicit example to show that @code{pcg} uses a |
227 ## split preconditioner | 227 ## split preconditioner |
273 endif | 273 endif |
274 | 274 |
275 ## Check if the input data A,b,m1,m2 are consistent (i.e. if they are | 275 ## Check if the input data A,b,m1,m2 are consistent (i.e. if they are |
276 ## matrix or function handle) | 276 ## matrix or function handle) |
277 | 277 |
278 [Afun, M1fun, M2fun] = __alltohandles__ (A, b, M1, M2, "pcg"); | 278 [Afcn, M1fcn, M2fcn] = __alltohandles__ (A, b, M1, M2, "pcg"); |
279 | 279 |
280 maxit += 2; | 280 maxit += 2; |
281 n_arg_out = nargout; | 281 n_arg_out = nargout; |
282 | 282 |
283 ## Set Initial data | 283 ## Set Initial data |
299 x = x_pr = x_min = x0; | 299 x = x_pr = x_min = x0; |
300 | 300 |
301 ## x_pr (x previous) needs to check the stagnation | 301 ## x_pr (x previous) needs to check the stagnation |
302 ## x_min needs to save the iterated with minimum residual | 302 ## x_min needs to save the iterated with minimum residual |
303 | 303 |
304 r = b - feval (Afun, x, varargin{:}); | 304 r = b - feval (Afcn, x, varargin{:}); |
305 iter = 2; | 305 iter = 2; |
306 iter_min = 0; | 306 iter_min = 0; |
307 flag = 1; | 307 flag = 1; |
308 resvec = zeros (maxit + 1, 2); | 308 resvec = zeros (maxit + 1, 2); |
309 resvec(1, 1) = norm (r); | 309 resvec(1, 1) = norm (r); |
318 | 318 |
319 while (resvec(iter-1,1) > tol * b_norm && iter < maxit) | 319 while (resvec(iter-1,1) > tol * b_norm && iter < maxit) |
320 if (iter == 2) # Check whether M1 or M2 are singular | 320 if (iter == 2) # Check whether M1 or M2 are singular |
321 try | 321 try |
322 warning ("error","Octave:singular-matrix","local"); | 322 warning ("error","Octave:singular-matrix","local"); |
323 z = feval (M1fun, r, varargin{:}); | 323 z = feval (M1fcn, r, varargin{:}); |
324 z = feval (M2fun, z, varargin{:}); | 324 z = feval (M2fcn, z, varargin{:}); |
325 catch | 325 catch |
326 flag = 2; | 326 flag = 2; |
327 break; | 327 break; |
328 end_try_catch | 328 end_try_catch |
329 else | 329 else |
330 z = feval (M1fun, r, varargin{:}); | 330 z = feval (M1fcn, r, varargin{:}); |
331 z = feval (M2fun, z, varargin{:}); | 331 z = feval (M2fcn, z, varargin{:}); |
332 endif | 332 endif |
333 | 333 |
334 tau = z' * r; | 334 tau = z' * r; |
335 resvec(iter - 1, 2) = sqrt (tau); | 335 resvec(iter - 1, 2) = sqrt (tau); |
336 beta = tau / old_tau; | 336 beta = tau / old_tau; |
337 old_tau = tau; | 337 old_tau = tau; |
338 p = z + beta * p; | 338 p = z + beta * p; |
339 w = feval (Afun, p, varargin{:}); | 339 w = feval (Afcn, p, varargin{:}); |
340 | 340 |
341 ## Needed only for eigest. | 341 ## Needed only for eigest. |
342 | 342 |
343 old_alpha = alpha; | 343 old_alpha = alpha; |
344 den = p' * w; | 344 den = p' * w; |
376 endwhile | 376 endwhile |
377 | 377 |
378 if (n_arg_out > 5) | 378 if (n_arg_out > 5) |
379 ## Apply the preconditioner once more and finish with the precond | 379 ## Apply the preconditioner once more and finish with the precond |
380 ## residual. | 380 ## residual. |
381 z = feval (M1fun, r, varargin{:}); | 381 z = feval (M1fcn, r, varargin{:}); |
382 z = feval (M2fun, z, varargin{:}); | 382 z = feval (M2fcn, z, varargin{:}); |
383 endif | 383 endif |
384 | 384 |
385 ## (Eventually) computes the eigenvalue of inv(m2)*inv(m1)*A | 385 ## (Eventually) computes the eigenvalue of inv(m2)*inv(m1)*A |
386 if (n_arg_out > 5) | 386 if (n_arg_out > 5) |
387 if (flag != 4) | 387 if (flag != 4) |
464 %! b = A * ones (n, 1); | 464 %! b = A * ones (n, 1); |
465 %! M1 = ichol (A); # for this tridiagonal case it corresponds to chol (A)' | 465 %! M1 = ichol (A); # for this tridiagonal case it corresponds to chol (A)' |
466 %! M2 = M1'; | 466 %! M2 = M1'; |
467 %! M = M1 * M2; | 467 %! M = M1 * M2; |
468 %! x = pcg (A, b); | 468 %! x = pcg (A, b); |
469 %! Afun = @(x) A * x; | 469 %! Afcn = @(x) A * x; |
470 %! x = pcg (Afun, b); | 470 %! x = pcg (Afcn, b); |
471 %! x = pcg (A, b, 1e-6, 100, M); | 471 %! x = pcg (A, b, 1e-6, 100, M); |
472 %! x = pcg (A, b, 1e-6, 100, M1, M2); | 472 %! x = pcg (A, b, 1e-6, 100, M1, M2); |
473 %! Mfun = @(x) M \ x; | 473 %! Mfcn = @(x) M \ x; |
474 %! x = pcg (Afun, b, 1e-6, 100, Mfun); | 474 %! x = pcg (Afcn, b, 1e-6, 100, Mfcn); |
475 %! M1fun = @(x) M1 \ x; | 475 %! M1fcn = @(x) M1 \ x; |
476 %! M2fun = @(x) M2 \ x; | 476 %! M2fcn = @(x) M2 \ x; |
477 %! x = pcg (Afun, b, 1e-6, 100, M1fun, M2fun); | 477 %! x = pcg (Afcn, b, 1e-6, 100, M1fcn, M2fcn); |
478 %! function y = Ap (A, x, p) # compute A^p * x | 478 %! function y = Ap (A, x, p) # compute A^p * x |
479 %! y = x; | 479 %! y = x; |
480 %! for i = 1:p | 480 %! for i = 1:p |
481 %! y = A * y; | 481 %! y = A * y; |
482 %! endfor | 482 %! endfor |
483 %! endfunction | 483 %! endfunction |
484 %! Afun = @(x, p) Ap (A, x, p); | 484 %! Afcn = @(x, p) Ap (A, x, p); |
485 %! ## solution of A^2 * x = b | 485 %! ## solution of A^2 * x = b |
486 %! x = pcg (Afun, b, [], [], [], [], [], 2); | 486 %! x = pcg (Afcn, b, [], [], [], [], [], 2); |
487 | 487 |
488 %!demo | 488 %!demo |
489 %! n = 10; | 489 %! n = 10; |
490 %! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, n)); | 490 %! A = toeplitz (sparse ([1, 1], [1, 2], [2, 1], 1, n)); |
491 %! b = A * ones (n, 1); | 491 %! b = A * ones (n, 1); |
504 %! ## Check that all type of inputs work | 504 %! ## Check that all type of inputs work |
505 %! A = toeplitz (sparse ([2, 1 ,0, 0, 0])); | 505 %! A = toeplitz (sparse ([2, 1 ,0, 0, 0])); |
506 %! b = A * ones (5, 1); | 506 %! b = A * ones (5, 1); |
507 %! M1 = diag (sqrt (diag (A))); | 507 %! M1 = diag (sqrt (diag (A))); |
508 %! M2 = M1; # M1 * M2 is the Jacobi preconditioner | 508 %! M2 = M1; # M1 * M2 is the Jacobi preconditioner |
509 %! Afun = @(z) A*z; | 509 %! Afcn = @(z) A*z; |
510 %! M1_fun = @(z) M1 \ z; | 510 %! M1_fcn = @(z) M1 \ z; |
511 %! M2_fun = @(z) M2 \ z; | 511 %! M2_fcn = @(z) M2 \ z; |
512 %! [x, flag, ~, iter] = pcg (A,b); | 512 %! [x, flag, ~, iter] = pcg (A,b); |
513 %! assert (flag, 0); | 513 %! assert (flag, 0); |
514 %! [x, flag, ~ , iter] = pcg (A, b, [], [], M1 * M2); | 514 %! [x, flag, ~ , iter] = pcg (A, b, [], [], M1 * M2); |
515 %! assert (flag, 0); | 515 %! assert (flag, 0); |
516 %! [x, flag, ~ , iter] = pcg (A, b, [], [], M1, M2); | 516 %! [x, flag, ~ , iter] = pcg (A, b, [], [], M1, M2); |
517 %! assert (flag, 0); | 517 %! assert (flag, 0); |
518 %! [x, flag] = pcg (A, b, [], [], M1_fun, M2_fun); | 518 %! [x, flag] = pcg (A, b, [], [], M1_fcn, M2_fcn); |
519 %! assert (flag, 0); | 519 %! assert (flag, 0); |
520 %! [x, flag] = pcg (A, b,[],[], M1_fun, M2); | 520 %! [x, flag] = pcg (A, b,[],[], M1_fcn, M2); |
521 %! assert (flag, 0); | 521 %! assert (flag, 0); |
522 %! [x, flag] = pcg (A, b,[],[], M1, M2_fun); | 522 %! [x, flag] = pcg (A, b,[],[], M1, M2_fcn); |
523 %! assert (flag, 0); | 523 %! assert (flag, 0); |
524 %! [x, flag] = pcg (Afun, b); | 524 %! [x, flag] = pcg (Afcn, b); |
525 %! assert (flag, 0); | 525 %! assert (flag, 0); |
526 %! [x, flag] = pcg (Afun, b,[],[], M1 * M2); | 526 %! [x, flag] = pcg (Afcn, b,[],[], M1 * M2); |
527 %! assert (flag, 0); | 527 %! assert (flag, 0); |
528 %! [x, flag] = pcg (Afun, b,[],[], M1, M2); | 528 %! [x, flag] = pcg (Afcn, b,[],[], M1, M2); |
529 %! assert (flag, 0); | 529 %! assert (flag, 0); |
530 %! [x, flag] = pcg (Afun, b,[],[], M1_fun, M2); | 530 %! [x, flag] = pcg (Afcn, b,[],[], M1_fcn, M2); |
531 %! assert (flag, 0); | 531 %! assert (flag, 0); |
532 %! [x, flag] = pcg (Afun, b,[],[], M1, M2_fun); | 532 %! [x, flag] = pcg (Afcn, b,[],[], M1, M2_fcn); |
533 %! assert (flag, 0); | 533 %! assert (flag, 0); |
534 %! [x, flag] = pcg (Afun, b,[],[], M1_fun, M2_fun); | 534 %! [x, flag] = pcg (Afcn, b,[],[], M1_fcn, M2_fcn); |
535 %! assert (flag, 0); | 535 %! assert (flag, 0); |
536 | 536 |
537 %!test | 537 %!test |
538 %! ## solve a small diagonal system | 538 %! ## solve a small diagonal system |
539 %! N = 10; | 539 %! N = 10; |
656 %! b = single (1); | 656 %! b = single (1); |
657 %! [x, flag] = pcg (A, b); | 657 %! [x, flag] = pcg (A, b); |
658 %! assert (class (x), "single"); | 658 %! assert (class (x), "single"); |
659 | 659 |
660 %!test | 660 %!test |
661 %!function y = Afun (x) | 661 %!function y = Afcn (x) |
662 %! A = toeplitz ([2, 1, 0, 0]); | 662 %! A = toeplitz ([2, 1, 0, 0]); |
663 %! y = A * x; | 663 %! y = A * x; |
664 %!endfunction | 664 %!endfunction |
665 %! [x, flag] = pcg ("Afun", [3; 4; 4; 3]); | 665 %! [x, flag] = pcg ("Afcn", [3; 4; 4; 3]); |
666 %! assert (x, ones (4, 1), 1e-6); | 666 %! assert (x, ones (4, 1), 1e-6); |
667 | 667 |
668 %!test | 668 %!test |
669 %! ## unpreconditioned residual | 669 %! ## unpreconditioned residual |
670 %! A = toeplitz (sparse ([4, 1, 0, 0, 0])); | 670 %! A = toeplitz (sparse ([4, 1, 0, 0, 0])); |