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 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 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 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 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 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 KSPTrueMonitor(KSP ksp,PetscInt n,PetscReal rnorm,void *dummy)
245: {
247: Vec resid,work;
248: PetscReal scnorm,bnorm;
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: VecNorm(ksp->vec_rhs,NORM_2,&bnorm);
272: PetscViewerASCIIPrintf(viewer,"%3D KSP preconditioned resid norm %14.12e true resid norm %14.12e ||Ae||/||Ax|| %14.12e\n",n,rnorm,scnorm,scnorm/bnorm);
273: return(0);
274: }
278: /*
279: Default (short) KSP Monitor, same as KSPDefaultMonitor() except
280: it prints fewer digits of the residual as the residual gets smaller.
281: This is because the later digits are meaningless and are often
282: different on different machines; by using this routine different
283: machines will usually generate the same output.
284: */
285: PetscErrorCode KSPDefaultSMonitor(KSP ksp,PetscInt its,PetscReal fnorm,void *dummy)
286: {
288: PetscViewer viewer = (PetscViewer) dummy;
291: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);
293: if (fnorm > 1.e-9) {
294: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %G \n",its,fnorm);
295: } else if (fnorm > 1.e-11){
296: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %5.3e \n",its,fnorm);
297: } else {
298: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm < 1.e-11\n",its);
299: }
300: return(0);
301: }
305: /*@C
306: KSPSkipConverged - Convergence test that NEVER returns as converged.
308: Collective on KSP
310: Input Parameters:
311: + ksp - iterative context
312: . n - iteration number
313: . rnorm - 2-norm residual value (may be estimated)
314: - dummy - unused convergence context
316: Returns:
317: . reason - always KSP_CONVERGED_ITERATING
319: Notes:
320: This is used as the convergence test with the option KSPSetNormType(ksp,KSP_NO_NORM),
321: since norms of the residual are not computed. Convergence is then declared
322: after a fixed number of iterations have been used. Useful when one is
323: using CG or Bi-CG-stab as a smoother.
324:
325: Level: advanced
327: .keywords: KSP, default, convergence, residual
329: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSetNormType()
330: @*/
331: PetscErrorCode KSPSkipConverged(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
332: {
335: return(0);
336: }
340: /*@C
341: KSPDefaultConvergedSetUIRNorm - makes the default convergence test use || B*(b - A*(initial guess))||
342: instead of || B*b ||. In the case of right preconditioner or if KSPSetNormType(ksp,KSP_UNPRECONDIITONED_NORM)
343: is used there is no B in the above formula. UIRNorm is short for Use Initial Residual Norm.
345: Collective on KSP
347: Input Parameters:
348: . ksp - iterative context
350: Options Database:
351: . -ksp_converged_use_initial_residual_norm
353: Use KSPSetTolerances() to alter the defaults for rtol, abstol, dtol.
355: The precise values of reason are macros such as KSP_CONVERGED_RTOL, which
356: are defined in petscksp.h.
358: Level: intermediate
360: .keywords: KSP, default, convergence, residual
362: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSkipConverged(), KSPConvergedReason, KSPGetConvergedReason(), KSPDefaultConvergedSetUMIRNorm()
363: @*/
364: PetscErrorCode KSPDefaultConvergedSetUIRNorm(KSP ksp)
365: {
368: if (ksp->defaultconvergedmininitialrtol) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Can use KSPDefaultConvergedSetUIRNorm() and KSPDefaultConvergedSetUMIRNorm() together");
369: ksp->defaultconvergedinitialrtol = PETSC_TRUE;
370: return(0);
371: }
375: /*@C
376: KSPDefaultConvergedSetUMIRNorm - makes the default convergence test use min(|| B*(b - A*(initial guess))||,|| B*b ||)
377: In the case of right preconditioner or if KSPSetNormType(ksp,KSP_UNPRECONDIITONED_NORM)
378: is used there is no B in the above formula. UMIRNorm is short for Use Minimum Initial Residual Norm.
380: Collective on KSP
382: Input Parameters:
383: . ksp - iterative context
385: Options Database:
386: . -ksp_converged_use_min_initial_residual_norm
388: Use KSPSetTolerances() to alter the defaults for rtol, abstol, dtol.
390: The precise values of reason are macros such as KSP_CONVERGED_RTOL, which
391: are defined in petscksp.h.
393: Level: intermediate
395: .keywords: KSP, default, convergence, residual
397: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSkipConverged(), KSPConvergedReason, KSPGetConvergedReason(), KSPDefaultConvergedSetUIRNorm()
398: @*/
399: PetscErrorCode KSPDefaultConvergedSetUMIRNorm(KSP ksp)
400: {
403: if (ksp->defaultconvergedinitialrtol) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Can use KSPDefaultConvergedSetUIRNorm() and KSPDefaultConvergedSetUMIRNorm() together");
404: ksp->defaultconvergedmininitialrtol = PETSC_TRUE;
405: return(0);
406: }
410: /*@C
411: KSPDefaultConverged - Determines convergence of
412: the iterative solvers (default code).
414: Collective on KSP
416: Input Parameters:
417: + ksp - iterative context
418: . n - iteration number
419: . rnorm - 2-norm residual value (may be estimated)
420: - dummy - unused convergence context
422: Returns:
423: + positive - if the iteration has converged;
424: . negative - if residual norm exceeds divergence threshold;
425: - 0 - otherwise.
427: Notes:
428: KSPDefaultConverged() reaches convergence when
429: $ rnorm < MAX (rtol * rnorm_0, abstol);
430: Divergence is detected if
431: $ rnorm > dtol * rnorm_0,
433: where
434: + rtol = relative tolerance,
435: . abstol = absolute tolerance.
436: . dtol = divergence tolerance,
437: - rnorm_0 is the two norm of the right hand side. When initial guess is non-zero you
438: can call KSPDefaultConvergedSetUIRNorm() to use the norm of (b - A*(initial guess))
439: as the starting point for relative norm convergence testing.
441: Use KSPSetTolerances() to alter the defaults for rtol, abstol, dtol.
443: The precise values of reason are macros such as KSP_CONVERGED_RTOL, which
444: are defined in petscksp.h.
446: Level: intermediate
448: .keywords: KSP, default, convergence, residual
450: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSkipConverged(), KSPConvergedReason, KSPGetConvergedReason(),
451: KSPDefaultConvergedSetUIRNorm().
452: @*/
453: PetscErrorCode KSPDefaultConverged(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
454: {
460: *reason = KSP_CONVERGED_ITERATING;
462: if (!n) {
463: /* if user gives initial guess need to compute norm of b */
464: if (!ksp->guess_zero && !ksp->defaultconvergedinitialrtol) {
465: PetscReal snorm;
466: if (ksp->normtype == KSP_UNPRECONDITIONED_NORM || ksp->pc_side == PC_RIGHT) {
467: PetscInfo(ksp,"user has provided nonzero initial guess, computing 2-norm of RHS\n");
468: VecNorm(ksp->vec_rhs,NORM_2,&snorm); /* <- b'*b */
469: } else {
470: Vec z;
471: VecDuplicate(ksp->vec_rhs,&z);
472: KSP_PCApply(ksp,ksp->vec_rhs,z);
473: if (ksp->normtype == KSP_PRECONDITIONED_NORM) {
474: PetscInfo(ksp,"user has provided nonzero initial guess, computing 2-norm of preconditioned RHS\n");
475: VecNorm(z,NORM_2,&snorm); /* dp <- b'*B'*B*b */
476: } else if (ksp->normtype == KSP_NATURAL_NORM) {
477: PetscScalar norm;
478: PetscInfo(ksp,"user has provided nonzero initial guess, computing natural norm of RHS\n");
479: VecDot(ksp->vec_rhs,z,&norm);
480: snorm = sqrt(PetscAbsScalar(norm)); /* dp <- b'*B*b */
481: }
482: VecDestroy(z);
483: }
484: /* handle special case of zero RHS and nonzero guess */
485: if (!snorm) {
486: PetscInfo(ksp,"Special case, user has provided nonzero initial guess and zero RHS\n");
487: snorm = rnorm;
488: }
489: if (ksp->defaultconvergedmininitialrtol) {
490: ksp->rnorm0 = PetscMin(snorm,rnorm);
491: } else {
492: ksp->rnorm0 = snorm;
493: }
494: } else {
495: ksp->rnorm0 = rnorm;
496: }
497: ksp->ttol = PetscMax(ksp->rtol*ksp->rnorm0,ksp->abstol);
498: }
500: if (rnorm != rnorm) {
501: PetscInfo(ksp,"Linear solver has created a not a number (NaN) as the residual norm, declaring divergence \n");
502: *reason = KSP_DIVERGED_NAN;
503: } else if (rnorm <= ksp->ttol) {
504: if (rnorm < ksp->abstol) {
505: PetscInfo3(ksp,"Linear solver has converged. Residual norm %G is less than absolute tolerance %G at iteration %D\n",rnorm,ksp->abstol,n);
506: *reason = KSP_CONVERGED_ATOL;
507: } else {
508: 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);
509: *reason = KSP_CONVERGED_RTOL;
510: }
511: } else if (rnorm >= ksp->divtol*ksp->rnorm0) {
512: PetscInfo3(ksp,"Linear solver is diverging. Initial right hand size norm %G, current residual norm %G at iteration %D\n",ksp->rnorm0,rnorm,n);
513: *reason = KSP_DIVERGED_DTOL;
514: }
515: return(0);
516: }
520: /*
521: KSPDefaultBuildSolution - Default code to create/move the solution.
523: Input Parameters:
524: + ksp - iterative context
525: - v - pointer to the user's vector
527: Output Parameter:
528: . V - pointer to a vector containing the solution
530: Level: advanced
532: .keywords: KSP, build, solution, default
534: .seealso: KSPGetSolution(), KSPDefaultBuildResidual()
535: */
536: PetscErrorCode KSPDefaultBuildSolution(KSP ksp,Vec v,Vec *V)
537: {
540: if (ksp->pc_side == PC_RIGHT) {
541: if (ksp->pc) {
542: if (v) {KSP_PCApply(ksp,ksp->vec_sol,v); *V = v;}
543: else {SETERRQ(PETSC_ERR_SUP,"Not working with right preconditioner");}
544: } else {
545: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
546: else { *V = ksp->vec_sol;}
547: }
548: } else if (ksp->pc_side == PC_SYMMETRIC) {
549: if (ksp->pc) {
550: if (ksp->transpose_solve) SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner and transpose solve");
551: if (v) {PCApplySymmetricRight(ksp->pc,ksp->vec_sol,v); *V = v;}
552: else {SETERRQ(PETSC_ERR_SUP,"Not working with symmetric preconditioner");}
553: } else {
554: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
555: else { *V = ksp->vec_sol;}
556: }
557: } else {
558: if (v) {VecCopy(ksp->vec_sol,v); *V = v;}
559: else { *V = ksp->vec_sol; }
560: }
561: return(0);
562: }
566: /*
567: KSPDefaultBuildResidual - Default code to compute the residual.
569: Input Parameters:
570: . ksp - iterative context
571: . t - pointer to temporary vector
572: . v - pointer to user vector
574: Output Parameter:
575: . V - pointer to a vector containing the residual
577: Level: advanced
579: .keywords: KSP, build, residual, default
581: .seealso: KSPDefaultBuildSolution()
582: */
583: PetscErrorCode KSPDefaultBuildResidual(KSP ksp,Vec t,Vec v,Vec *V)
584: {
586: MatStructure pflag;
587: Mat Amat,Pmat;
590: PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);
591: KSPBuildSolution(ksp,t,PETSC_NULL);
592: KSP_MatMult(ksp,Amat,t,v);
593: VecAYPX(v,-1.0,ksp->vec_rhs);
594: *V = v;
595: return(0);
596: }
600: /*@C
601: KSPGetVecs - Gets a number of work vectors.
603: Input Parameters:
604: + ksp - iterative context
605: . rightn - number of right work vectors
606: - leftn - number of left work vectors to allocate
608: Output Parameter:
609: + right - the array of vectors created
610: - left - the array of left vectors
612: Note: The right vector has as many elements as the matrix has columns. The left
613: vector has as many elements as the matrix has rows.
615: Level: advanced
617: .seealso: MatGetVecs()
619: @*/
620: PetscErrorCode KSPGetVecs(KSP ksp,PetscInt rightn, Vec **right,PetscInt leftn,Vec **left)
621: {
623: Vec vecr,vecl;
626: if (rightn) {
627: if (!right) SETERRQ(PETSC_ERR_ARG_INCOMP,"You asked for right vectors but did not pass a pointer to hold them");
628: if (ksp->vec_sol) vecr = ksp->vec_sol;
629: else {
630: Mat pmat;
631: PCGetOperators(ksp->pc,PETSC_NULL,&pmat,PETSC_NULL);
632: MatGetVecs(pmat,&vecr,PETSC_NULL);
633: }
634: VecDuplicateVecs(vecr,rightn,right);
635: if (!ksp->vec_sol) {
636: VecDestroy(vecr);
637: }
638: }
639: if (leftn) {
640: if (!left) SETERRQ(PETSC_ERR_ARG_INCOMP,"You asked for left vectors but did not pass a pointer to hold them");
641: if (ksp->vec_rhs) vecl = ksp->vec_rhs;
642: else {
643: Mat pmat;
644: PCGetOperators(ksp->pc,PETSC_NULL,&pmat,PETSC_NULL);
645: MatGetVecs(pmat,PETSC_NULL,&vecl);
646: }
647: VecDuplicateVecs(vecl,leftn,left);
648: if (!ksp->vec_rhs) {
649: VecDestroy(vecl);
650: }
651: }
652: return(0);
653: }
657: /*
658: KSPDefaultGetWork - Gets a number of work vectors.
660: Input Parameters:
661: . ksp - iterative context
662: . nw - number of work vectors to allocate
664: Notes:
665: Call this only if no work vectors have been allocated
666: */
667: PetscErrorCode KSPDefaultGetWork(KSP ksp,PetscInt nw)
668: {
672: if (ksp->work) {KSPDefaultFreeWork(ksp);}
673: ksp->nwork = nw;
674: KSPGetVecs(ksp,nw,&ksp->work,0,PETSC_NULL);
675: PetscLogObjectParents(ksp,nw,ksp->work);
676: return(0);
677: }
681: /*
682: KSPDefaultDestroy - Destroys a iterative context variable for methods with
683: no separate context. Preferred calling sequence KSPDestroy().
685: Input Parameter:
686: . ksp - the iterative context
687: */
688: PetscErrorCode KSPDefaultDestroy(KSP ksp)
689: {
694: PetscFree(ksp->data);
696: /* free work vectors */
697: KSPDefaultFreeWork(ksp);
698: return(0);
699: }
703: /*@
704: KSPGetConvergedReason - Gets the reason the KSP iteration was stopped.
706: Not Collective
708: Input Parameter:
709: . ksp - the KSP context
711: Output Parameter:
712: . reason - negative value indicates diverged, positive value converged, see KSPConvergedReason
714: Possible values for reason:
715: + KSP_CONVERGED_RTOL (residual 2-norm decreased by a factor of rtol, from 2-norm of right hand side)
716: . KSP_CONVERGED_ATOL (residual 2-norm less than abstol)
717: . KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration)
718: . KSP_CONVERGED_QCG_NEG_CURVE
719: . KSP_CONVERGED_QCG_CONSTRAINED
720: . KSP_CONVERGED_STEP_LENGTH
721: . KSP_DIVERGED_ITS (required more than its to reach convergence)
722: . KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol)
723: . KSP_DIVERGED_NAN (residual norm became Not-a-number likely do to 0/0)
724: . KSP_DIVERGED_BREAKDOWN (generic breakdown in method)
725: - KSP_DIVERGED_BREAKDOWN_BICG (Initial residual is orthogonal to preconditioned initial
726: residual. Try a different preconditioner, or a different initial guess.)
727:
729: Level: beginner
731: Notes: Can only be called after the call the KSPSolve() is complete.
733: .keywords: KSP, nonlinear, set, convergence, test
735: .seealso: KSPSetConvergenceTest(), KSPDefaultConverged(), KSPSetTolerances(), KSPConvergedReason
736: @*/
737: PetscErrorCode KSPGetConvergedReason(KSP ksp,KSPConvergedReason *reason)
738: {
742: *reason = ksp->reason;
743: return(0);
744: }