Actual source code: iterativ.c
1: /*$Id: iterativ.c,v 1.108 2001/08/07 03:03:45 balay Exp $*/
3: /*
4: This file contains some simple default routines.
5: These routines should be SHORT, since they will be included in every
6: executable image that uses the iterative routines (note that, through
7: the registry system, we provide a way to load only the truely necessary
8: files)
9: */
10: #include src/ksp/ksp/kspimpl.h
14: /*
15: KSPDefaultFreeWork - Free work vectors
17: Input Parameters:
18: . ksp - iterative context
19: */
20: int KSPDefaultFreeWork(KSP ksp)
21: {
25: if (ksp->work) {
26: VecDestroyVecs(ksp->work,ksp->nwork);
27: ksp->work = PETSC_NULL;
28: }
29: return(0);
30: }
34: /*@C
35: KSPGetResidualNorm - Gets the last (approximate preconditioned)
36: residual norm that has been computed.
37:
38: Not Collective
40: Input Parameters:
41: . ksp - the iterative context
43: Output Parameters:
44: . rnorm - residual norm
46: Level: intermediate
48: .keywords: KSP, get, residual norm
50: .seealso: KSPComputeResidual()
51: @*/
52: int KSPGetResidualNorm(KSP ksp,PetscReal *rnorm)
53: {
57: *rnorm = ksp->rnorm;
58: return(0);
59: }
63: /*@
64: KSPGetIterationNumber - Gets the current iteration number; if the
65: KSPSolve() is complete, returns the number of iterations
66: used.
67:
68: Not Collective
70: Input Parameters:
71: . ksp - the iterative context
73: Output Parameters:
74: . its - number of iterations
76: Level: intermediate
78: Notes:
79: During the ith iteration this returns i-1
80: .keywords: KSP, get, residual norm
82: .seealso: KSPComputeResidual(), KSPGetResidualNorm()
83: @*/
84: int KSPGetIterationNumber(KSP ksp,int *its)
85: {
89: *its = ksp->its;
90: return(0);
91: }
95: /*@C
96: KSPSingularValueMonitor - Prints the two norm of the true residual and
97: estimation of the extreme singular values of the preconditioned problem
98: at each iteration.
99:
100: Collective on KSP
102: Input Parameters:
103: + ksp - the iterative context
104: . n - the iteration
105: - rnorm - the two norm of the residual
107: Options Database Key:
108: . -ksp_singmonitor - Activates KSPSingularValueMonitor()
110: Notes:
111: The CG solver uses the Lanczos technique for eigenvalue computation,
112: while GMRES uses the Arnoldi technique; other iterative methods do
113: not currently compute singular values.
115: Level: intermediate
117: .keywords: KSP, CG, default, monitor, extreme, singular values, Lanczos, Arnoldi
119: .seealso: KSPComputeExtremeSingularValues()
120: @*/
121: int KSPSingularValueMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
122: {
123: PetscReal emin,emax,c;
124: int ierr;
128: if (!ksp->calc_sings) {
129: PetscPrintf(ksp->comm,"%3d KSP Residual norm %14.12e \n",n,rnorm);
130: } else {
131: KSPComputeExtremeSingularValues(ksp,&emax,&emin);
132: c = emax/emin;
133: PetscPrintf(ksp->comm,"%3d KSP Residual norm %14.12e %% max %g min %g max/min %g\n",n,rnorm,emax,emin,c);
134: }
135: return(0);
136: }
140: /*@C
141: KSPVecViewMonitor - Monitors progress of the KSP solvers by calling
142: VecView() for the approximate solution at each iteration.
144: Collective on KSP
146: Input Parameters:
147: + ksp - the KSP context
148: . its - iteration number
149: . fgnorm - 2-norm of residual (or gradient)
150: - dummy - either a viewer or PETSC_NULL
152: Level: intermediate
154: Notes:
155: For some Krylov methods such as GMRES constructing the solution at
156: each iteration is expensive, hence using this will slow the code.
158: .keywords: KSP, nonlinear, vector, monitor, view
160: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), VecView()
161: @*/
162: int KSPVecViewMonitor(KSP ksp,int its,PetscReal fgnorm,void *dummy)
163: {
164: int ierr;
165: Vec x;
166: PetscViewer viewer = (PetscViewer) dummy;
169: KSPBuildSolution(ksp,PETSC_NULL,&x);
170: if (!viewer) {
171: MPI_Comm comm;
172: PetscObjectGetComm((PetscObject)ksp,&comm);
173: viewer = PETSC_VIEWER_DRAW_(comm);
174: }
175: VecView(x,viewer);
177: return(0);
178: }
182: /*@C
183: KSPDefaultMonitor - Print the residual norm at each iteration of an
184: iterative solver.
186: Collective on KSP
188: Input Parameters:
189: + ksp - iterative context
190: . n - iteration number
191: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
192: - dummy - unused monitor context
194: Level: intermediate
196: .keywords: KSP, default, monitor, residual
198: .seealso: KSPSetMonitor(), KSPTrueMonitor(), KSPLGMonitorCreate()
199: @*/
200: int KSPDefaultMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
201: {
202: int ierr;
203: PetscViewer viewer = (PetscViewer) dummy;
206: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
207: PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %14.12e \n",n,rnorm);
208: return(0);
209: }
213: /*@C
214: KSPTrueMonitor - Prints the true residual norm as well as the preconditioned
215: residual norm at each iteration of an iterative solver.
217: Collective on KSP
219: Input Parameters:
220: + ksp - iterative context
221: . n - iteration number
222: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
223: - dummy - unused monitor context
225: Options Database Key:
226: . -ksp_truemonitor - Activates KSPTrueMonitor()
228: Notes:
229: When using right preconditioning, these values are equivalent.
231: When using either ICC or ILU preconditioners in BlockSolve95
232: (via MATMPIROWBS matrix format), then use this monitor will
233: print both the residual norm associated with the original
234: (unscaled) matrix.
236: Level: intermediate
238: .keywords: KSP, default, monitor, residual
240: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), KSPLGMonitorCreate()
241: @*/
242: int KSPTrueMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
243: {
244: int ierr;
245: Vec resid,work;
246: PetscReal scnorm;
247: PC pc;
248: Mat A,B;
249: PetscViewer viewer = (PetscViewer) dummy;
250:
252: VecDuplicate(ksp->vec_rhs,&work);
253: KSPBuildResidual(ksp,0,work,&resid);
255: /*
256: Unscale the residual if the matrix is, for example, a BlockSolve matrix
257: but only if both matrices are the same matrix, since only then would
258: they be scaled.
259: */
260: VecCopy(resid,work);
261: KSPGetPC(ksp,&pc);
262: PCGetOperators(pc,&A,&B,PETSC_NULL);
263: if (A == B) {
264: MatUnScaleSystem(A,PETSC_NULL,work);
265: }
266: VecNorm(work,NORM_2,&scnorm);
267: VecDestroy(work);
268: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
269: PetscViewerASCIIPrintf(viewer,"%3d KSP preconditioned resid norm %14.12e true resid norm %14.12e\n",n,rnorm,scnorm);
270: return(0);
271: }
275: /*
276: Default (short) KSP Monitor, same as KSPDefaultMonitor() except
277: it prints fewer digits of the residual as the residual gets smaller.
278: This is because the later digits are meaningless and are often
279: different on different machines; by using this routine different
280: machines will usually generate the same output.
281: */
282: int KSPDefaultSMonitor(KSP ksp,int its,PetscReal fnorm,void *dummy)
283: {
284: int ierr;
285: PetscViewer viewer = (PetscViewer) dummy;
288: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
290: if (fnorm > 1.e-9) {
291: PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %g \n",its,fnorm);
292: } else if (fnorm > 1.e-11){
293: PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %5.3e \n",its,fnorm);
294: } else {
295: PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm < 1.e-11\n",its);
296: }
297: return(0);
298: }
302: /*@C
303: KSPSkipConverged - Convergence test that NEVER returns as converged.
305: Collective on KSP
307: Input Parameters:
308: + ksp - iterative context
309: . n - iteration number
310: . rnorm - 2-norm residual value (may be estimated)
311: - dummy - unused convergence context
313: Returns:
314: . 0 - always
316: Notes:
317: This is used as the convergence test with the option KSPSetNormType(ksp,KSP_NO_NORM),
318: since norms of the residual are not computed. Convergence is then declared
319: after a fixed number of iterations have been used. Useful when one is
320: using CG or Bi-CG-stab as a smoother.
321:
322: Level: advanced
324: .keywords: KSP, default, convergence, residual
326: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSetNormType()
327: @*/
328: int KSPSkipConverged(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
329: {
332: return(0);
333: }
337: /*@C
338: KSPDefaultConverged - Determines convergence of
339: the iterative solvers (default code).
341: Collective on KSP
343: Input Parameters:
344: + ksp - iterative context
345: . n - iteration number
346: . rnorm - 2-norm residual value (may be estimated)
347: - dummy - unused convergence context
349: Returns:
350: + 1 - if the iteration has converged;
351: . -1 - if residual norm exceeds divergence threshold;
352: - 0 - otherwise.
354: Notes:
355: KSPDefaultConverged() reaches convergence when
356: $ rnorm < MAX (rtol * rnorm_0, atol);
357: Divergence is detected if
358: $ rnorm > dtol * rnorm_0,
360: where
361: + rtol = relative tolerance,
362: . atol = absolute tolerance.
363: . dtol = divergence tolerance,
364: - rnorm_0 = initial residual norm
366: Use KSPSetTolerances() to alter the defaults for rtol, atol, dtol.
368: Level: intermediate
370: .keywords: KSP, default, convergence, residual
372: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSkipConverged()
373: @*/
374: int KSPDefaultConverged(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
375: {
379: *reason = KSP_CONVERGED_ITERATING;
381: if (!n) {
382: ksp->ttol = PetscMax(ksp->rtol*rnorm,ksp->atol);
383: ksp->rnorm0 = rnorm;
384: }
385: if (rnorm <= ksp->ttol) {
386: if (rnorm < ksp->atol) {
387: PetscLogInfo(ksp,"Linear solver has converged. Residual norm %g is less than absolute tolerance %g at iteration %d\n",rnorm,ksp->atol,n);
388: *reason = KSP_CONVERGED_ATOL;
389: } else {
390: PetscLogInfo(ksp,"Linear solver has converged. Residual norm %g is less than relative tolerance %g times initial residual norm %g at iteration %d\n",rnorm,ksp->rtol,ksp->rnorm0,n);
391: *reason = KSP_CONVERGED_RTOL;
392: }
393: } else if (rnorm >= ksp->divtol*ksp->rnorm0) {
394: PetscLogInfo(ksp,"Linear solver is diverging. Initial residual norm %g, current residual norm %g at iteration %d\n",ksp->rnorm0,rnorm,n);
395: *reason = KSP_DIVERGED_DTOL;
396: } else if (rnorm != rnorm) {
397: PetscLogInfo(ksp,"Linear solver has created a not a number (NaN) as the residual norm, declaring divergence\n");
398: *reason = KSP_DIVERGED_DTOL;
399: }
400: return(0);
401: }
405: /*
406: KSPDefaultBuildSolution - Default code to create/move the solution.
408: Input Parameters:
409: + ksp - iterative context
410: - v - pointer to the user's vector
412: Output Parameter:
413: . V - pointer to a vector containing the solution
415: Level: advanced
417: .keywords: KSP, build, solution, default
419: .seealso: KSPGetSolution(), KSPDefaultBuildResidual()
420: */
421: int KSPDefaultBuildSolution(KSP ksp,Vec v,Vec *V)
422: {
425: if (ksp->pc_side == PC_RIGHT) {
426: if (ksp->B) {
427: if (v) {KSP_PCApply(ksp,ksp->B,ksp->vec_sol,v); *V = v;}
428: else {SETERRQ(PETSC_ERR_SUP,"Not working with right preconditioner");}
429: } else {
430: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
431: else { *V = ksp->vec_sol;}
432: }
433: } else if (ksp->pc_side == PC_SYMMETRIC) {
434: if (ksp->B) {
435: if (ksp->transpose_solve) SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner and transpose solve");
436: if (v) {PCApplySymmetricRight(ksp->B,ksp->vec_sol,v); *V = v;}
437: else {SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner");}
438: } else {
439: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
440: else { *V = ksp->vec_sol;}
441: }
442: } else {
443: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
444: else { *V = ksp->vec_sol; }
445: }
446: return(0);
447: }
451: /*
452: KSPDefaultBuildResidual - Default code to compute the residual.
454: Input Parameters:
455: . ksp - iterative context
456: . t - pointer to temporary vector
457: . v - pointer to user vector
459: Output Parameter:
460: . V - pointer to a vector containing the residual
462: Level: advanced
464: .keywords: KSP, build, residual, default
466: .seealso: KSPDefaultBuildSolution()
467: */
468: int KSPDefaultBuildResidual(KSP ksp,Vec t,Vec v,Vec *V)
469: {
470: int ierr;
471: MatStructure pflag;
472: Vec T;
473: PetscScalar mone = -1.0;
474: Mat Amat,Pmat;
477: PCGetOperators(ksp->B,&Amat,&Pmat,&pflag);
478: KSPBuildSolution(ksp,t,&T);
479: KSP_MatMult(ksp,Amat,t,v);
480: VecAYPX(&mone,ksp->vec_rhs,v);
481: *V = v;
482: return(0);
483: }
487: /*
488: KSPDefaultGetWork - Gets a number of work vectors.
490: Input Parameters:
491: . ksp - iterative context
492: . nw - number of work vectors to allocate
494: Notes:
495: Call this only if no work vectors have been allocated
496: */
497: int KSPDefaultGetWork(KSP ksp,int nw)
498: {
502: if (ksp->work) {KSPDefaultFreeWork(ksp);}
503: ksp->nwork = nw;
504: VecDuplicateVecs(ksp->vec_rhs,nw,&ksp->work);
505: PetscLogObjectParents(ksp,nw,ksp->work);
506: return(0);
507: }
511: /*
512: KSPDefaultDestroy - Destroys a iterative context variable for methods with
513: no separate context. Preferred calling sequence KSPDestroy().
515: Input Parameter:
516: . ksp - the iterative context
517: */
518: int KSPDefaultDestroy(KSP ksp)
519: {
524: if (ksp->data) {
525: PetscFree(ksp->data);
526: ksp->data = 0;
527: }
529: /* free work vectors */
530: KSPDefaultFreeWork(ksp);
531: return(0);
532: }
536: /*@C
537: KSPGetConvergedReason - Gets the reason the KSP iteration was stopped.
539: Not Collective
541: Input Parameter:
542: . ksp - the KSP context
544: Output Parameter:
545: . reason - negative value indicates diverged, positive value converged, see KSPConvergedReason
547: Possible values for reason:
548: + KSP_CONVERGED_RTOL (residual norm decreased by a factor of rtol)
549: . KSP_CONVERGED_ATOL (residual norm less than atol)
550: . KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration)
551: . KSP_CONVERGED_QCG_NEG_CURVE
552: . KSP_CONVERGED_QCG_CONSTRAINED
553: . KSP_CONVERGED_STEP_LENGTH
554: . KSP_DIVERGED_ITS (required more than its to reach convergence)
555: . KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol)
556: . KSP_DIVERGED_BREAKDOWN (generic breakdown in method)
557: - KSP_DIVERGED_BREAKDOWN_BICG (Initial residual is orthogonal to preconditioned initial
558: residual. Try a different preconditioner, or a different initial guess.
559:
561: Level: intermediate
563: Notes: Can only be called after the call the KSPSolve() is complete.
565: .keywords: KSP, nonlinear, set, convergence, test
567: .seealso: KSPSetConvergenceTest(), KSPDefaultConverged(), KSPSetTolerances(), KSPConvergedReason
568: @*/
569: int KSPGetConvergedReason(KSP ksp,KSPConvergedReason *reason)
570: {
574: *reason = ksp->reason;
575: return(0);
576: }