Actual source code: iterativ.c
1: #define PETSCKSP_DLL
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: PetscErrorCode 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: /*@
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: KSPBuildResidual()
51: @*/
52: PetscErrorCode PETSCKSP_DLLEXPORT 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: KSPBuildResidual(), KSPGetResidualNorm()
83: @*/
84: PetscErrorCode PETSCKSP_DLLEXPORT KSPGetIterationNumber(KSP ksp,PetscInt *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: PetscErrorCode PETSCKSP_DLLEXPORT KSPSingularValueMonitor(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
122: {
123: PetscReal emin,emax,c;
125: PetscViewer viewer = (PetscViewer) dummy;
129: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
130: if (!ksp->calc_sings) {
131: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %14.12e \n",n,rnorm);
132: } else {
133: KSPComputeExtremeSingularValues(ksp,&emax,&emin);
134: c = emax/emin;
135: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %14.12e %% max %G min %G max/min %G\n",n,rnorm,emax,emin,c);
136: }
137: return(0);
138: }
142: /*@C
143: KSPVecViewMonitor - Monitors progress of the KSP solvers by calling
144: VecView() for the approximate solution at each iteration.
146: Collective on KSP
148: Input Parameters:
149: + ksp - the KSP context
150: . its - iteration number
151: . fgnorm - 2-norm of residual (or gradient)
152: - dummy - either a viewer or PETSC_NULL
154: Level: intermediate
156: Notes:
157: For some Krylov methods such as GMRES constructing the solution at
158: each iteration is expensive, hence using this will slow the code.
160: .keywords: KSP, nonlinear, vector, monitor, view
162: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), VecView()
163: @*/
164: PetscErrorCode PETSCKSP_DLLEXPORT KSPVecViewMonitor(KSP ksp,PetscInt its,PetscReal fgnorm,void *dummy)
165: {
167: Vec x;
168: PetscViewer viewer = (PetscViewer) dummy;
171: KSPBuildSolution(ksp,PETSC_NULL,&x);
172: if (!viewer) {
173: MPI_Comm comm;
174: PetscObjectGetComm((PetscObject)ksp,&comm);
175: viewer = PETSC_VIEWER_DRAW_(comm);
176: }
177: VecView(x,viewer);
179: return(0);
180: }
184: /*@C
185: KSPDefaultMonitor - Print the residual norm at each iteration of an
186: iterative solver.
188: Collective on KSP
190: Input Parameters:
191: + ksp - iterative context
192: . n - iteration number
193: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
194: - dummy - unused monitor context
196: Level: intermediate
198: .keywords: KSP, default, monitor, residual
200: .seealso: KSPSetMonitor(), KSPTrueMonitor(), KSPLGMonitorCreate()
201: @*/
202: PetscErrorCode PETSCKSP_DLLEXPORT KSPDefaultMonitor(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
203: {
205: PetscViewer viewer = (PetscViewer) dummy;
208: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
209: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %14.12e \n",n,rnorm);
210: return(0);
211: }
215: /*@C
216: KSPTrueMonitor - Prints the true residual norm as well as the preconditioned
217: residual norm at each iteration of an iterative solver.
219: Collective on KSP
221: Input Parameters:
222: + ksp - iterative context
223: . n - iteration number
224: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
225: - dummy - unused monitor context
227: Options Database Key:
228: . -ksp_truemonitor - Activates KSPTrueMonitor()
230: Notes:
231: When using right preconditioning, these values are equivalent.
233: When using either ICC or ILU preconditioners in BlockSolve95
234: (via MATMPIROWBS matrix format), then use this monitor will
235: print both the residual norm associated with the original
236: (unscaled) matrix.
238: Level: intermediate
240: .keywords: KSP, default, monitor, residual
242: .seealso: KSPSetMonitor(), KSPDefaultMonitor(), KSPLGMonitorCreate()
243: @*/
244: PetscErrorCode PETSCKSP_DLLEXPORT KSPTrueMonitor(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
245: {
247: Vec resid,work;
248: PetscReal scnorm;
249: PC pc;
250: Mat A,B;
251: PetscViewer viewer = (PetscViewer) dummy;
252:
254: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
255: VecDuplicate(ksp->vec_rhs,&work);
256: KSPBuildResidual(ksp,0,work,&resid);
258: /*
259: Unscale the residual if the matrix is, for example, a BlockSolve matrix
260: but only if both matrices are the same matrix, since only then would
261: they be scaled.
262: */
263: VecCopy(resid,work);
264: KSPGetPC(ksp,&pc);
265: PCGetOperators(pc,&A,&B,PETSC_NULL);
266: if (A == B) {
267: MatUnScaleSystem(A,work,PETSC_NULL);
268: }
269: VecNorm(work,NORM_2,&scnorm);
270: VecDestroy(work);
271: PetscViewerASCIIPrintf(viewer,"%3D KSP preconditioned resid norm %14.12e true resid norm %14.12e\n",n,rnorm,scnorm);
272: return(0);
273: }
277: /*
278: Default (short) KSP Monitor, same as KSPDefaultMonitor() except
279: it prints fewer digits of the residual as the residual gets smaller.
280: This is because the later digits are meaningless and are often
281: different on different machines; by using this routine different
282: machines will usually generate the same output.
283: */
284: PetscErrorCode PETSCKSP_DLLEXPORT KSPDefaultSMonitor(KSP ksp,PetscInt its,PetscReal fnorm,void *dummy)
285: {
287: PetscViewer viewer = (PetscViewer) dummy;
290: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
292: if (fnorm > 1.e-9) {
293: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %G \n",its,fnorm);
294: } else if (fnorm > 1.e-11){
295: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %5.3e \n",its,fnorm);
296: } else {
297: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm < 1.e-11\n",its);
298: }
299: return(0);
300: }
304: /*@C
305: KSPSkipConverged - Convergence test that NEVER returns as converged.
307: Collective on KSP
309: Input Parameters:
310: + ksp - iterative context
311: . n - iteration number
312: . rnorm - 2-norm residual value (may be estimated)
313: - dummy - unused convergence context
315: Returns:
316: . reason - always KSP_CONVERGED_ITERATING
318: Notes:
319: This is used as the convergence test with the option KSPSetNormType(ksp,KSP_NO_NORM),
320: since norms of the residual are not computed. Convergence is then declared
321: after a fixed number of iterations have been used. Useful when one is
322: using CG or Bi-CG-stab as a smoother.
323:
324: Level: advanced
326: .keywords: KSP, default, convergence, residual
328: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSetNormType()
329: @*/
330: PetscErrorCode PETSCKSP_DLLEXPORT KSPSkipConverged(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
331: {
334: return(0);
335: }
339: /*@C
340: KSPDefaultConverged - Determines convergence of
341: the iterative solvers (default code).
343: Collective on KSP
345: Input Parameters:
346: + ksp - iterative context
347: . n - iteration number
348: . rnorm - 2-norm residual value (may be estimated)
349: - dummy - unused convergence context
351: Returns:
352: + positive - if the iteration has converged;
353: . negative - if residual norm exceeds divergence threshold;
354: - 0 - otherwise.
356: Notes:
357: KSPDefaultConverged() reaches convergence when
358: $ rnorm < MAX (rtol * rnorm_0, abstol);
359: Divergence is detected if
360: $ rnorm > dtol * rnorm_0,
362: where
363: + rtol = relative tolerance,
364: . abstol = absolute tolerance.
365: . dtol = divergence tolerance,
366: - rnorm_0 = initial residual norm
368: Use KSPSetTolerances() to alter the defaults for rtol, abstol, dtol.
370: The precise values of reason are macros such as KSP_CONVERGED_RTOL, which
371: are defined in petscksp.h.
373: Level: intermediate
375: .keywords: KSP, default, convergence, residual
377: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSkipConverged(), KSPConvergedReason, KSPGetConvergedReason()
378: @*/
379: PetscErrorCode PETSCKSP_DLLEXPORT KSPDefaultConverged(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
380: {
386: *reason = KSP_CONVERGED_ITERATING;
388: if (!n) {
389: /* if user gives initial guess need to compute norm of b */
390: if (!ksp->guess_zero) {
391: PetscReal snorm;
392: if (ksp->normtype == KSP_UNPRECONDITIONED_NORM || ksp->pc_side == PC_RIGHT) {
393: PetscInfo(ksp,"user has provided nonzero initial guess, computing 2-norm of RHS\n");
394: VecNorm(ksp->vec_rhs,NORM_2,&snorm); /* <- b'*b */
395: } else {
396: Vec z;
397: VecDuplicate(ksp->vec_rhs,&z);
398: KSP_PCApply(ksp,ksp->vec_rhs,z);
399: if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
400: PetscInfo(ksp,"user has provided nonzero initial guess, computing 2-norm of preconditioned RHS\n");
401: VecNorm(z,NORM_2,&snorm); /* dp <- b'*B'*B*b */
402: } else if (ksp->normtype == KSP_NATURAL_NORM) {
403: PetscScalar norm;
404: PetscInfo(ksp,"user has provided nonzero initial guess, computing natural norm of RHS\n");
405: VecDot(ksp->vec_rhs,z,&norm);
406: snorm = sqrt(PetscAbsScalar(norm)); /* dp <- b'*B*b */
407: }
408: VecDestroy(z);
409: }
410: /* handle special case of zero RHS and nonzero guess */
411: if (!snorm) {
412: PetscInfo(ksp,"Special case, user has provided nonzero initial guess and zero RHS\n");
413: snorm = rnorm;
414: }
415: ksp->ttol = PetscMax(ksp->rtol*snorm,ksp->abstol);
416: ksp->rnorm0 = snorm;
417: } else {
418: ksp->ttol = PetscMax(ksp->rtol*rnorm,ksp->abstol);
419: ksp->rnorm0 = rnorm;
420: }
421: }
423: if (rnorm != rnorm) {
424: PetscInfo(ksp,"Linear solver has created a not a number (NaN) as the residual norm, declaring divergence \n");
425: *reason = KSP_DIVERGED_NAN;
426: } else if (rnorm <= ksp->ttol) {
427: if (rnorm < ksp->abstol) {
428: PetscInfo3(ksp,"Linear solver has converged. Residual norm %G is less than absolute tolerance %G at iteration %D\n",rnorm,ksp->abstol,n);
429: *reason = KSP_CONVERGED_ATOL;
430: } else {
431: PetscInfo4(ksp,"Linear solver has converged. Residual norm %G is less than relative tolerance %G times initial right hand side norm %G at iteration %D\n",rnorm,ksp->rtol,ksp->rnorm0,n);
432: *reason = KSP_CONVERGED_RTOL;
433: }
434: } else if (rnorm >= ksp->divtol*ksp->rnorm0) {
435: PetscInfo3(ksp,"Linear solver is diverging. Initial right hand size norm %G, current residual norm %G at iteration %D\n",ksp->rnorm0,rnorm,n);
436: *reason = KSP_DIVERGED_DTOL;
437: }
438: return(0);
439: }
443: /*
444: KSPDefaultBuildSolution - Default code to create/move the solution.
446: Input Parameters:
447: + ksp - iterative context
448: - v - pointer to the user's vector
450: Output Parameter:
451: . V - pointer to a vector containing the solution
453: Level: advanced
455: .keywords: KSP, build, solution, default
457: .seealso: KSPGetSolution(), KSPDefaultBuildResidual()
458: */
459: PetscErrorCode KSPDefaultBuildSolution(KSP ksp,Vec v,Vec *V)
460: {
463: if (ksp->pc_side == PC_RIGHT) {
464: if (ksp->pc) {
465: if (v) {KSP_PCApply(ksp,ksp->vec_sol,v); *V = v;}
466: else {SETERRQ(PETSC_ERR_SUP,"Not working with right preconditioner");}
467: } else {
468: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
469: else { *V = ksp->vec_sol;}
470: }
471: } else if (ksp->pc_side == PC_SYMMETRIC) {
472: if (ksp->pc) {
473: if (ksp->transpose_solve) SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner and transpose solve");
474: if (v) {PCApplySymmetricRight(ksp->pc,ksp->vec_sol,v); *V = v;}
475: else {SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner");}
476: } else {
477: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
478: else { *V = ksp->vec_sol;}
479: }
480: } else {
481: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
482: else { *V = ksp->vec_sol; }
483: }
484: return(0);
485: }
489: /*
490: KSPDefaultBuildResidual - Default code to compute the residual.
492: Input Parameters:
493: . ksp - iterative context
494: . t - pointer to temporary vector
495: . v - pointer to user vector
497: Output Parameter:
498: . V - pointer to a vector containing the residual
500: Level: advanced
502: .keywords: KSP, build, residual, default
504: .seealso: KSPDefaultBuildSolution()
505: */
506: PetscErrorCode KSPDefaultBuildResidual(KSP ksp,Vec t,Vec v,Vec *V)
507: {
509: MatStructure pflag;
510: Mat Amat,Pmat;
513: PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);
514: KSPBuildSolution(ksp,t,PETSC_NULL);
515: KSP_MatMult(ksp,Amat,t,v);
516: VecAYPX(v,-1.0,ksp->vec_rhs);
517: *V = v;
518: return(0);
519: }
523: /*@C
524: KSPGetVecs - Gets a number of work vectors.
526: Input Parameters:
527: + ksp - iterative context
528: . rightn - number of right work vectors
529: - leftn - number of left work vectors to allocate
531: Output Parameter:
532: + right - the array of vectors created
533: - left - the array of left vectors
535: Note: The right vector has as many elements as the matrix has columns. The left
536: vector has as many elements as the matrix has rows.
538: Level: advanced
540: .seealso: MatGetVecs()
542: @*/
543: PetscErrorCode KSPGetVecs(KSP ksp,PetscInt rightn, Vec **right,PetscInt leftn,Vec **left)
544: {
546: Vec vecr,vecl;
549: if (rightn) {
550: if (!right) SETERRQ(PETSC_ERR_ARG_INCOMP,"You asked for right vectors but did not pass a pointer to hold them");
551: if (ksp->vec_sol) vecr = ksp->vec_sol;
552: else {
553: Mat pmat;
554: PCGetOperators(ksp->pc,0,&pmat,0);
555: MatGetVecs(pmat,&vecr,0);
556: }
557: VecDuplicateVecs(vecr,rightn,right);
558: if (!ksp->vec_sol) {
559: VecDestroy(vecr);
560: }
561: }
562: if (leftn) {
563: if (!left) SETERRQ(PETSC_ERR_ARG_INCOMP,"You asked for left vectors but did not pass a pointer to hold them");
564: if (ksp->vec_rhs) vecl = ksp->vec_rhs;
565: else {
566: Mat pmat;
567: PCGetOperators(ksp->pc,0,&pmat,0);
568: MatGetVecs(pmat,0,&vecl);
569: }
570: VecDuplicateVecs(vecl,leftn,left);
571: if (!ksp->vec_rhs) {
572: VecDestroy(vecl);
573: }
574: }
575: return(0);
576: }
580: /*
581: KSPDefaultGetWork - Gets a number of work vectors.
583: Input Parameters:
584: . ksp - iterative context
585: . nw - number of work vectors to allocate
587: Notes:
588: Call this only if no work vectors have been allocated
589: */
590: PetscErrorCode KSPDefaultGetWork(KSP ksp,PetscInt nw)
591: {
595: if (ksp->work) {KSPDefaultFreeWork(ksp);}
596: ksp->nwork = nw;
597: KSPGetVecs(ksp,nw,&ksp->work,0,PETSC_NULL);
598: PetscLogObjectParents(ksp,nw,ksp->work);
599: return(0);
600: }
604: /*
605: KSPDefaultDestroy - Destroys a iterative context variable for methods with
606: no separate context. Preferred calling sequence KSPDestroy().
608: Input Parameter:
609: . ksp - the iterative context
610: */
611: PetscErrorCode KSPDefaultDestroy(KSP ksp)
612: {
617: PetscFree(ksp->data);
619: /* free work vectors */
620: KSPDefaultFreeWork(ksp);
621: return(0);
622: }
626: /*@
627: KSPGetConvergedReason - Gets the reason the KSP iteration was stopped.
629: Not Collective
631: Input Parameter:
632: . ksp - the KSP context
634: Output Parameter:
635: . reason - negative value indicates diverged, positive value converged, see KSPConvergedReason
637: Possible values for reason:
638: + KSP_CONVERGED_RTOL (residual 2-norm decreased by a factor of rtol, from 2-norm of right hand side)
639: . KSP_CONVERGED_ATOL (residual 2-norm less than abstol)
640: . KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration)
641: . KSP_CONVERGED_QCG_NEG_CURVE
642: . KSP_CONVERGED_QCG_CONSTRAINED
643: . KSP_CONVERGED_STEP_LENGTH
644: . KSP_DIVERGED_ITS (required more than its to reach convergence)
645: . KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol)
646: . KSP_DIVERGED_NAN (residual norm became Not-a-number likely do to 0/0)
647: . KSP_DIVERGED_BREAKDOWN (generic breakdown in method)
648: - KSP_DIVERGED_BREAKDOWN_BICG (Initial residual is orthogonal to preconditioned initial
649: residual. Try a different preconditioner, or a different initial guess.)
650:
652: Level: beginner
654: Notes: Can only be called after the call the KSPSolve() is complete.
656: .keywords: KSP, nonlinear, set, convergence, test
658: .seealso: KSPSetConvergenceTest(), KSPDefaultConverged(), KSPSetTolerances(), KSPConvergedReason
659: @*/
660: PetscErrorCode PETSCKSP_DLLEXPORT KSPGetConvergedReason(KSP ksp,KSPConvergedReason *reason)
661: {
665: *reason = ksp->reason;
666: return(0);
667: }