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/sles/ksp/kspimpl.h
12: /*
13: KSPDefaultFreeWork - Free work vectors
15: Input Parameters:
16: . ksp - iterative context
17: */
18: int KSPDefaultFreeWork(KSP ksp)
19: {
23: if (ksp->work) {
24: VecDestroyVecs(ksp->work,ksp->nwork);
25: }
26: return(0);
27: }
29: /*@C
30: KSPGetResidualNorm - Gets the last (approximate preconditioned)
31: residual norm that has been computed.
32:
33: Not Collective
35: Input Parameters:
36: . ksp - the iterative context
38: Output Parameters:
39: . rnorm - residual norm
41: Level: intermediate
43: .keywords: KSP, get, residual norm
45: .seealso: KSPComputeResidual()
46: @*/
47: int KSPGetResidualNorm(KSP ksp,PetscReal *rnorm)
48: {
51: *rnorm = ksp->rnorm;
52: return(0);
53: }
55: /*@
56: KSPGetIterationNumber - Gets the current iteration number (if the
57: KSPSolve() (SLESSolve()) is complete, returns the number of iterations
58: used.
59:
60: Not Collective
62: Input Parameters:
63: . ksp - the iterative context
65: Output Parameters:
66: . its - number of iterations
68: Level: intermediate
70: Notes:
71: During the ith iteration this returns i-1
72: .keywords: KSP, get, residual norm
74: .seealso: KSPComputeResidual(), KSPGetResidualNorm()
75: @*/
76: int KSPGetIterationNumber(KSP ksp,int *its)
77: {
80: *its = ksp->its;
81: return(0);
82: }
84: /*@C
85: KSPSingularValueMonitor - Prints the two norm of the true residual and
86: estimation of the extreme singular values of the preconditioned problem
87: at each iteration.
88:
89: Collective on KSP
91: Input Parameters:
92: + ksp - the iterative context
93: . n - the iteration
94: - rnorm - the two norm of the residual
96: Options Database Key:
97: . -ksp_singmonitor - Activates KSPSingularValueMonitor()
99: Notes:
100: The CG solver uses the Lanczos technique for eigenvalue computation,
101: while GMRES uses the Arnoldi technique; other iterative methods do
102: not currently compute singular values.
104: Level: intermediate
106: .keywords: KSP, CG, default, monitor, extreme, singular values, Lanczos, Arnoldi
108: .seealso: KSPComputeExtremeSingularValues()
109: @*/
110: int KSPSingularValueMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
111: {
112: PetscReal emin,emax,c;
113: int ierr;
117: if (!ksp->calc_sings) {
118: PetscPrintf(ksp->comm,"%3d KSP Residual norm %14.12e n",n,rnorm);
119: } else {
120: KSPComputeExtremeSingularValues(ksp,&emax,&emin);
121: c = emax/emin;
122: PetscPrintf(ksp->comm,"%3d KSP Residual norm %14.12e %% max %g min %g max/min %gn",n,rnorm,emax,emin,c);
123: }
124: return(0);
125: }
127: /*@C
128: KSPVecViewMonitor - Monitors progress of the KSP solvers by calling
129: VecView() for the approximate solution at each iteration.
131: Collective on KSP
133: Input Parameters:
134: + ksp - the KSP context
135: . its - iteration number
136: . fgnorm - 2-norm of residual (or gradient)
137: - dummy - either a viewer or PETSC_NULL
139: Level: intermediate
141: Notes:
142: For some Krylov methods such as GMRES constructing the solution at
143: each iteration is expensive, hence using this will slow the code.
145: .keywords: KSP, nonlinear, vector, monitor, view
147: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), VecView()
148: @*/
149: int KSPVecViewMonitor(KSP ksp,int its,PetscReal fgnorm,void *dummy)
150: {
151: int ierr;
152: Vec x;
153: PetscViewer viewer = (PetscViewer) dummy;
156: KSPBuildSolution(ksp,PETSC_NULL,&x);
157: if (!viewer) {
158: MPI_Comm comm;
159: ierr = PetscObjectGetComm((PetscObject)ksp,&comm);
160: viewer = PETSC_VIEWER_DRAW_(comm);
161: }
162: VecView(x,viewer);
164: return(0);
165: }
167: /*@C
168: KSPDefaultMonitor - Print the residual norm at each iteration of an
169: iterative solver.
171: Collective on KSP
173: Input Parameters:
174: + ksp - iterative context
175: . n - iteration number
176: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
177: - dummy - unused monitor context
179: Level: intermediate
181: .keywords: KSP, default, monitor, residual
183: .seealso: KSPSetMonitor(), KSPTrueMonitor(), KSPLGMonitorCreate()
184: @*/
185: int KSPDefaultMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
186: {
187: int ierr;
188: PetscViewer viewer = (PetscViewer) dummy;
191: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
192: PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %14.12e n",n,rnorm);
193: return(0);
194: }
196: /*@C
197: KSPTrueMonitor - Prints the true residual norm as well as the preconditioned
198: residual norm at each iteration of an iterative solver.
200: Collective on KSP
202: Input Parameters:
203: + ksp - iterative context
204: . n - iteration number
205: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
206: - dummy - unused monitor context
208: Options Database Key:
209: . -ksp_truemonitor - Activates KSPTrueMonitor()
211: Notes:
212: When using right preconditioning, these values are equivalent.
214: When using either ICC or ILU preconditioners in BlockSolve95
215: (via MATMPIROWBS matrix format), then use this monitor will
216: print both the residual norm associated with the original
217: (unscaled) matrix.
219: Level: intermediate
221: .keywords: KSP, default, monitor, residual
223: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), KSPLGMonitorCreate()
224: @*/
225: int KSPTrueMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy)
226: {
227: int ierr;
228: Vec resid,work;
229: PetscReal scnorm;
230: PC pc;
231: Mat A,B;
232: PetscViewer viewer = (PetscViewer) dummy;
233:
235: VecDuplicate(ksp->vec_rhs,&work);
236: KSPBuildResidual(ksp,0,work,&resid);
238: /*
239: Unscale the residual if the matrix is, for example, a BlockSolve matrix
240: but only if both matrices are the same matrix, since only then would
241: they be scaled.
242: */
243: VecCopy(resid,work);
244: KSPGetPC(ksp,&pc);
245: PCGetOperators(pc,&A,&B,PETSC_NULL);
246: if (A == B) {
247: MatUnScaleSystem(A,PETSC_NULL,work);
248: }
249: VecNorm(work,NORM_2,&scnorm);
250: VecDestroy(work);
251: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
252: PetscViewerASCIIPrintf(viewer,"%3d KSP preconditioned resid norm %14.12e true resid norm %14.12en",n,rnorm,scnorm);
253: return(0);
254: }
256: /*
257: Default (short) KSP Monitor, same as KSPDefaultMonitor() except
258: it prints fewer digits of the residual as the residual gets smaller.
259: This is because the later digits are meaningless and are often
260: different on different machines; by using this routine different
261: machines will usually generate the same output.
262: */
263: int KSPDefaultSMonitor(KSP ksp,int its,PetscReal fnorm,void *dummy)
264: {
265: int ierr;
266: PetscViewer viewer = (PetscViewer) dummy;
269: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
271: if (fnorm > 1.e-9) {
272: PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %g n",its,fnorm);
273: } else if (fnorm > 1.e-11){
274: PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm %5.3e n",its,fnorm);
275: } else {
276: PetscViewerASCIIPrintf(viewer,"%3d KSP Residual norm < 1.e-11n",its);
277: }
278: return(0);
279: }
281: /*@C
282: KSPSkipConverged - Convergence test that NEVER returns as converged.
284: Collective on KSP
286: Input Parameters:
287: + ksp - iterative context
288: . n - iteration number
289: . rnorm - 2-norm residual value (may be estimated)
290: - dummy - unused convergence context
292: Returns:
293: . 0 - always
295: Notes:
296: This is used as the convergence test with the option KSPSetNormType(ksp,KSP_NO_NORM),
297: since norms of the residual are not computed. Convergence is then declared
298: after a fixed number of iterations have been used. Useful when one is
299: using CG or Bi-CG-stab as a smoother.
300:
301: Level: advanced
303: .keywords: KSP, default, convergence, residual
305: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSetNormType()
306: @*/
307: int KSPSkipConverged(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
308: {
311: return(0);
312: }
314: /*@C
315: KSPDefaultConverged - Determines convergence of
316: the iterative solvers (default code).
318: Collective on KSP
320: Input Parameters:
321: + ksp - iterative context
322: . n - iteration number
323: . rnorm - 2-norm residual value (may be estimated)
324: - dummy - unused convergence context
326: Returns:
327: + 1 - if the iteration has converged;
328: . -1 - if residual norm exceeds divergence threshold;
329: - 0 - otherwise.
331: Notes:
332: KSPDefaultConverged() reaches convergence when
333: $ rnorm < MAX (rtol * rnorm_0, atol);
334: Divergence is detected if
335: $ rnorm > dtol * rnorm_0,
337: where
338: + rtol = relative tolerance,
339: . atol = absolute tolerance.
340: . dtol = divergence tolerance,
341: - rnorm_0 = initial residual norm
343: Use KSPSetTolerances() to alter the defaults for rtol, atol, dtol.
345: Level: intermediate
347: .keywords: KSP, default, convergence, residual
349: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSkipConverged()
350: @*/
351: int KSPDefaultConverged(KSP ksp,int n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
352: {
355: *reason = KSP_CONVERGED_ITERATING;
357: if (!n) {
358: ksp->ttol = PetscMax(ksp->rtol*rnorm,ksp->atol);
359: ksp->rnorm0 = rnorm;
360: }
361: if (rnorm <= ksp->ttol) {
362: if (rnorm < ksp->atol) {
363: PetscLogInfo(ksp,"Linear solver has converged. Residual norm %g is less than absolute tolerance %g at iteration %dn",rnorm,ksp->atol,n);
364: *reason = KSP_CONVERGED_ATOL;
365: } else {
366: PetscLogInfo(ksp,"Linear solver has converged. Residual norm %g is less than relative tolerance %g times initial residual norm %g at iteration %dn",rnorm,ksp->rtol,ksp->rnorm0,n);
367: *reason = KSP_CONVERGED_RTOL;
368: }
369: } else if (rnorm >= ksp->divtol*ksp->rnorm0) {
370: PetscLogInfo(ksp,"Linear solver is diverging. Initial residual norm %g, current residual norm %g at iteration %dn",ksp->rnorm0,rnorm,n);
371: *reason = KSP_DIVERGED_DTOL;
372: } else if (rnorm != rnorm) {
373: PetscLogInfo(ksp,"Linear solver has created a not a number (NaN) as the residual norm, declaring divergencen");
374: *reason = KSP_DIVERGED_DTOL;
375: }
376: return(0);
377: }
379: /*
380: KSPDefaultBuildSolution - Default code to create/move the solution.
382: Input Parameters:
383: + ksp - iterative context
384: - v - pointer to the user's vector
386: Output Parameter:
387: . V - pointer to a vector containing the solution
389: Level: advanced
391: .keywords: KSP, build, solution, default
393: .seealso: KSPGetSolution(), KSPDefaultBuildResidual()
394: */
395: int KSPDefaultBuildSolution(KSP ksp,Vec v,Vec *V)
396: {
399: if (ksp->pc_side == PC_RIGHT) {
400: if (ksp->B) {
401: if (v) {KSP_PCApply(ksp,ksp->B,ksp->vec_sol,v); *V = v;}
402: else {SETERRQ(PETSC_ERR_SUP,"Not working with right preconditioner");}
403: } else {
404: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
405: else { *V = ksp->vec_sol;}
406: }
407: } else if (ksp->pc_side == PC_SYMMETRIC) {
408: if (ksp->B) {
409: if (ksp->transpose_solve) SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner and transpose solve");
410: if (v) {PCApplySymmetricRight(ksp->B,ksp->vec_sol,v); *V = v;}
411: else {SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner");}
412: } else {
413: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
414: else { *V = ksp->vec_sol;}
415: }
416: } else {
417: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
418: else { *V = ksp->vec_sol; }
419: }
420: return(0);
421: }
423: /*
424: KSPDefaultBuildResidual - Default code to compute the residual.
426: Input Parameters:
427: . ksp - iterative context
428: . t - pointer to temporary vector
429: . v - pointer to user vector
431: Output Parameter:
432: . V - pointer to a vector containing the residual
434: Level: advanced
436: .keywords: KSP, build, residual, default
438: .seealso: KSPDefaultBuildSolution()
439: */
440: int KSPDefaultBuildResidual(KSP ksp,Vec t,Vec v,Vec *V)
441: {
442: int ierr;
443: MatStructure pflag;
444: Vec T;
445: PetscScalar mone = -1.0;
446: Mat Amat,Pmat;
449: PCGetOperators(ksp->B,&Amat,&Pmat,&pflag);
450: KSPBuildSolution(ksp,t,&T);
451: KSP_MatMult(ksp,Amat,t,v);
452: VecAYPX(&mone,ksp->vec_rhs,v);
453: *V = v;
454: return(0);
455: }
457: /*
458: KSPDefaultGetWork - Gets a number of work vectors.
460: Input Parameters:
461: . ksp - iterative context
462: . nw - number of work vectors to allocate
464: Notes:
465: Call this only if no work vectors have been allocated
466: */
467: int KSPDefaultGetWork(KSP ksp,int nw)
468: {
472: if (ksp->work) {KSPDefaultFreeWork(ksp);}
473: ksp->nwork = nw;
474: VecDuplicateVecs(ksp->vec_rhs,nw,&ksp->work);
475: PetscLogObjectParents(ksp,nw,ksp->work);
476: return(0);
477: }
479: /*
480: KSPDefaultDestroy - Destroys a iterative context variable for methods with
481: no separate context. Preferred calling sequence KSPDestroy().
483: Input Parameter:
484: . ksp - the iterative context
485: */
486: int KSPDefaultDestroy(KSP ksp)
487: {
492: if (ksp->data) {PetscFree(ksp->data);}
494: /* free work vectors */
495: KSPDefaultFreeWork(ksp);
496: return(0);
497: }
499: /*@C
500: KSPGetConvergedReason - Gets the reason the KSP iteration was stopped.
502: Not Collective
504: Input Parameter:
505: . ksp - the KSP context
507: Output Parameter:
508: . reason - negative value indicates diverged, positive value converged, see KSPConvergedReason
510: Possible values for reason:
511: + KSP_CONVERGED_RTOL (residual norm decreased by a factor of rtol)
512: . KSP_CONVERGED_ATOL (residual norm less than atol)
513: . KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration)
514: . KSP_CONVERGED_QCG_NEG_CURVE
515: . KSP_CONVERGED_QCG_CONSTRAINED
516: . KSP_CONVERGED_STEP_LENGTH
517: . KSP_DIVERGED_ITS (required more than its to reach convergence)
518: . KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol)
519: . KSP_DIVERGED_BREAKDOWN (generic breakdown in method)
520: - KSP_DIVERGED_BREAKDOWN_BICG (Initial residual is orthogonal to preconditioned initial
521: residual. Try a different preconditioner, or a different initial guess.
522:
524: Level: intermediate
526: Notes: Can only be called after the call the KSPSolve() is complete.
528: .keywords: KSP, nonlinear, set, convergence, test
530: .seealso: KSPSetConvergenceTest(), KSPDefaultConverged(), KSPSetTolerances(), KSPConvergedReason
531: @*/
532: int KSPGetConvergedReason(KSP ksp,KSPConvergedReason *reason)
533: {
536: *reason = ksp->reason;
537: return(0);
538: }