Actual source code: iterativ.c
petsc-3.8.4 2018-03-24
1: /*
2: This file contains some simple default routines.
3: These routines should be SHORT, since they will be included in every
4: executable image that uses the iterative routines (note that, through
5: the registry system, we provide a way to load only the truely necessary
6: files)
7: */
8: #include <petsc/private/kspimpl.h>
9: #include <petscdmshell.h>
11: /*@
12: KSPGetResidualNorm - Gets the last (approximate preconditioned)
13: residual norm that has been computed.
15: Not Collective
17: Input Parameters:
18: . ksp - the iterative context
20: Output Parameters:
21: . rnorm - residual norm
23: Level: intermediate
25: .keywords: KSP, get, residual norm
27: .seealso: KSPBuildResidual()
28: @*/
29: PetscErrorCode KSPGetResidualNorm(KSP ksp,PetscReal *rnorm)
30: {
34: *rnorm = ksp->rnorm;
35: return(0);
36: }
38: /*@
39: KSPGetIterationNumber - Gets the current iteration number; if the
40: KSPSolve() is complete, returns the number of iterations
41: used.
43: Not Collective
45: Input Parameters:
46: . ksp - the iterative context
48: Output Parameters:
49: . its - number of iterations
51: Level: intermediate
53: Notes:
54: During the ith iteration this returns i-1
55: .keywords: KSP, get, residual norm
57: .seealso: KSPBuildResidual(), KSPGetResidualNorm(), KSPGetTotalIterations()
58: @*/
59: PetscErrorCode KSPGetIterationNumber(KSP ksp,PetscInt *its)
60: {
64: *its = ksp->its;
65: return(0);
66: }
68: /*@
69: KSPGetTotalIterations - Gets the total number of iterations this KSP object has performed since was created, counted over all linear solves
71: Not Collective
73: Input Parameters:
74: . ksp - the iterative context
76: Output Parameters:
77: . its - total number of iterations
79: Level: intermediate
81: Notes: Use KSPGetIterationNumber() to get the count for the most recent solve only
82: If this is called within a linear solve (such as in a KSPMonitor routine) then it does not include iterations within that current solve
84: .keywords: KSP, get, residual norm
86: .seealso: KSPBuildResidual(), KSPGetResidualNorm(), KSPGetIterationNumber()
87: @*/
88: PetscErrorCode KSPGetTotalIterations(KSP ksp,PetscInt *its)
89: {
93: *its = ksp->totalits;
94: return(0);
95: }
97: /*@C
98: KSPMonitorSingularValue - Prints the two norm of the true residual and
99: estimation of the extreme singular values of the preconditioned problem
100: at each iteration.
102: Logically Collective on KSP
104: Input Parameters:
105: + ksp - the iterative context
106: . n - the iteration
107: - rnorm - the two norm of the residual
109: Options Database Key:
110: . -ksp_monitor_singular_value - Activates KSPMonitorSingularValue()
112: Notes:
113: The CG solver uses the Lanczos technique for eigenvalue computation,
114: while GMRES uses the Arnoldi technique; other iterative methods do
115: not currently compute singular values.
117: Level: intermediate
119: .keywords: KSP, CG, default, monitor, extreme, singular values, Lanczos, Arnoldi
121: .seealso: KSPComputeExtremeSingularValues()
122: @*/
123: PetscErrorCode KSPMonitorSingularValue(KSP ksp,PetscInt n,PetscReal rnorm,PetscViewerAndFormat *dummy)
124: {
125: PetscReal emin,emax,c;
127: PetscViewer viewer = dummy->viewer;
132: PetscViewerPushFormat(viewer,dummy->format);
133: PetscViewerASCIIAddTab(viewer,((PetscObject)ksp)->tablevel);
134: if (!ksp->calc_sings) {
135: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %14.12e \n",n,(double)rnorm);
136: } else {
137: KSPComputeExtremeSingularValues(ksp,&emax,&emin);
138: c = emax/emin;
139: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %14.12e %% max %14.12e min %14.12e max/min %14.12e\n",n,(double)rnorm,(double)emax,(double)emin,(double)c);
140: }
141: PetscViewerASCIISubtractTab(viewer,((PetscObject)ksp)->tablevel);
142: PetscViewerPopFormat(viewer);
143: return(0);
144: }
146: /*@C
147: KSPMonitorSolution - Monitors progress of the KSP solvers by calling
148: VecView() for the approximate solution at each iteration.
150: Collective on KSP
152: Input Parameters:
153: + ksp - the KSP context
154: . its - iteration number
155: . fgnorm - 2-norm of residual (or gradient)
156: - dummy - a viewer
158: Level: intermediate
160: Notes:
161: For some Krylov methods such as GMRES constructing the solution at
162: each iteration is expensive, hence using this will slow the code.
164: .keywords: KSP, nonlinear, vector, monitor, view
166: .seealso: KSPMonitorSet(), KSPMonitorDefault(), VecView()
167: @*/
168: PetscErrorCode KSPMonitorSolution(KSP ksp,PetscInt its,PetscReal fgnorm,PetscViewerAndFormat *dummy)
169: {
171: Vec x;
172: PetscViewer viewer = dummy->viewer;
176: KSPBuildSolution(ksp,NULL,&x);
177: PetscViewerPushFormat(viewer,dummy->format);
178: VecView(x,viewer);
179: PetscViewerPopFormat(viewer);
180: return(0);
181: }
183: /*@C
184: KSPMonitorDefault - Print the residual norm at each iteration of an
185: iterative solver.
187: Collective on KSP
189: Input Parameters:
190: + ksp - iterative context
191: . n - iteration number
192: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
193: - dummy - an ASCII PetscViewer
195: Level: intermediate
197: .keywords: KSP, default, monitor, residual
199: .seealso: KSPMonitorSet(), KSPMonitorTrueResidualNorm(), KSPMonitorLGResidualNormCreate()
200: @*/
201: PetscErrorCode KSPMonitorDefault(KSP ksp,PetscInt n,PetscReal rnorm,PetscViewerAndFormat *dummy)
202: {
204: PetscViewer viewer = dummy->viewer;
208: PetscViewerPushFormat(viewer,dummy->format);
209: PetscViewerASCIIAddTab(viewer,((PetscObject)ksp)->tablevel);
210: if (n == 0 && ((PetscObject)ksp)->prefix) {
211: PetscViewerASCIIPrintf(viewer," Residual norms for %s solve.\n",((PetscObject)ksp)->prefix);
212: }
213: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %14.12e \n",n,(double)rnorm);
214: PetscViewerASCIISubtractTab(viewer,((PetscObject)ksp)->tablevel);
215: PetscViewerPopFormat(viewer);
216: return(0);
217: }
219: /*@C
220: KSPMonitorTrueResidualNorm - Prints the true residual norm as well as the preconditioned
221: residual norm at each iteration of an iterative solver.
223: Collective on KSP
225: Input Parameters:
226: + ksp - iterative context
227: . n - iteration number
228: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
229: - dummy - an ASCII PetscViewer
231: Options Database Key:
232: . -ksp_monitor_true_residual - Activates KSPMonitorTrueResidualNorm()
234: Notes:
235: When using right preconditioning, these values are equivalent.
237: Level: intermediate
239: .keywords: KSP, default, monitor, residual
241: .seealso: KSPMonitorSet(), KSPMonitorDefault(), KSPMonitorLGResidualNormCreate(),KSPMonitorTrueResidualMaxNorm()
242: @*/
243: PetscErrorCode KSPMonitorTrueResidualNorm(KSP ksp,PetscInt n,PetscReal rnorm,PetscViewerAndFormat *dummy)
244: {
246: Vec resid;
247: PetscReal truenorm,bnorm;
248: PetscViewer viewer = dummy->viewer;
249: char normtype[256];
253: PetscViewerPushFormat(viewer,dummy->format);
254: PetscViewerASCIIAddTab(viewer,((PetscObject)ksp)->tablevel);
255: if (n == 0 && ((PetscObject)ksp)->prefix) {
256: PetscViewerASCIIPrintf(viewer," Residual norms for %s solve.\n",((PetscObject)ksp)->prefix);
257: }
258: KSPBuildResidual(ksp,NULL,NULL,&resid);
259: VecNorm(resid,NORM_2,&truenorm);
260: VecDestroy(&resid);
261: VecNorm(ksp->vec_rhs,NORM_2,&bnorm);
262: PetscStrncpy(normtype,KSPNormTypes[ksp->normtype],sizeof(normtype));
263: PetscStrtolower(normtype);
264: PetscViewerASCIIPrintf(viewer,"%3D KSP %s resid norm %14.12e true resid norm %14.12e ||r(i)||/||b|| %14.12e\n",n,normtype,(double)rnorm,(double)truenorm,(double)(truenorm/bnorm));
265: PetscViewerASCIISubtractTab(viewer,((PetscObject)ksp)->tablevel);
266: PetscViewerPopFormat(viewer);
267: return(0);
268: }
270: /*@C
271: KSPMonitorTrueResidualMaxNorm - Prints the true residual max norm each iteration of an iterative solver.
273: Collective on KSP
275: Input Parameters:
276: + ksp - iterative context
277: . n - iteration number
278: . rnorm - norm (preconditioned) residual value (may be estimated).
279: - dummy - an ASCII viewer
281: Options Database Key:
282: . -ksp_monitor_max - Activates KSPMonitorTrueResidualMaxNorm()
284: Notes:
285: This could be implemented (better) with a flag in ksp.
287: Level: intermediate
289: .keywords: KSP, default, monitor, residual
291: .seealso: KSPMonitorSet(), KSPMonitorDefault(), KSPMonitorLGResidualNormCreate(),KSPMonitorTrueResidualNorm()
292: @*/
293: PetscErrorCode KSPMonitorTrueResidualMaxNorm(KSP ksp,PetscInt n,PetscReal rnorm,PetscViewerAndFormat *dummy)
294: {
296: Vec resid;
297: PetscReal truenorm,bnorm;
298: PetscViewer viewer = dummy->viewer;
299: char normtype[256];
303: PetscViewerPushFormat(viewer,dummy->format);
304: PetscViewerASCIIAddTab(viewer,((PetscObject)ksp)->tablevel);
305: if (n == 0 && ((PetscObject)ksp)->prefix) {
306: PetscViewerASCIIPrintf(viewer," Residual norms (max) for %s solve.\n",((PetscObject)ksp)->prefix);
307: }
308: KSPBuildResidual(ksp,NULL,NULL,&resid);
309: VecNorm(resid,NORM_INFINITY,&truenorm);
310: VecDestroy(&resid);
311: VecNorm(ksp->vec_rhs,NORM_INFINITY,&bnorm);
312: PetscStrncpy(normtype,KSPNormTypes[ksp->normtype],sizeof(normtype));
313: PetscStrtolower(normtype);
314: PetscViewerASCIIPrintf(viewer,"%3D KSP true resid max norm %14.12e ||r(i)||/||b|| %14.12e\n",n,(double)truenorm,(double)(truenorm/bnorm));
315: PetscViewerASCIISubtractTab(viewer,((PetscObject)ksp)->tablevel);
316: PetscViewerPopFormat(viewer);
317: return(0);
318: }
320: PetscErrorCode KSPMonitorRange_Private(KSP ksp,PetscInt it,PetscReal *per)
321: {
323: Vec resid;
324: PetscReal rmax,pwork;
325: PetscInt i,n,N;
326: const PetscScalar *r;
329: KSPBuildResidual(ksp,NULL,NULL,&resid);
330: VecNorm(resid,NORM_INFINITY,&rmax);
331: VecGetLocalSize(resid,&n);
332: VecGetSize(resid,&N);
333: VecGetArrayRead(resid,&r);
334: pwork = 0.0;
335: for (i=0; i<n; i++) pwork += (PetscAbsScalar(r[i]) > .20*rmax);
336: VecRestoreArrayRead(resid,&r);
337: VecDestroy(&resid);
338: MPIU_Allreduce(&pwork,per,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ksp));
339: *per = *per/N;
340: return(0);
341: }
343: /*@C
344: KSPMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum value.
346: Collective on KSP
348: Input Parameters:
349: + ksp - iterative context
350: . it - iteration number
351: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
352: - dummy - an ASCII viewer
354: Options Database Key:
355: . -ksp_monitor_range - Activates KSPMonitorRange()
357: Level: intermediate
359: .keywords: KSP, default, monitor, residual
361: .seealso: KSPMonitorSet(), KSPMonitorDefault(), KSPMonitorLGResidualNormCreate()
362: @*/
363: PetscErrorCode KSPMonitorRange(KSP ksp,PetscInt it,PetscReal rnorm,PetscViewerAndFormat *dummy)
364: {
365: PetscErrorCode ierr;
366: PetscReal perc,rel;
367: PetscViewer viewer = dummy->viewer;
368: /* should be in a MonitorRangeContext */
369: static PetscReal prev;
373: PetscViewerPushFormat(viewer,dummy->format);
374: PetscViewerASCIIAddTab(viewer,((PetscObject)ksp)->tablevel);
375: if (!it) prev = rnorm;
376: if (it == 0 && ((PetscObject)ksp)->prefix) {
377: PetscViewerASCIIPrintf(viewer," Residual norms for %s solve.\n",((PetscObject)ksp)->prefix);
378: }
379: KSPMonitorRange_Private(ksp,it,&perc);
381: rel = (prev - rnorm)/prev;
382: prev = rnorm;
383: PetscViewerASCIIPrintf(viewer,"%3D KSP preconditioned resid norm %14.12e Percent values above 20 percent of maximum %5.2f relative decrease %5.2e ratio %5.2e \n",it,(double)rnorm,(double)(100.0*perc),(double)rel,(double)(rel/perc));
384: PetscViewerASCIISubtractTab(viewer,((PetscObject)ksp)->tablevel);
385: PetscViewerPopFormat(viewer);
386: return(0);
387: }
389: /*@C
390: KSPMonitorDynamicTolerance - Recompute the inner tolerance in every
391: outer iteration in an adaptive way.
393: Collective on KSP
395: Input Parameters:
396: + ksp - iterative context
397: . n - iteration number (not used)
398: . fnorm - the current residual norm
399: . dummy - some context as a C struct. fields:
400: coef: a scaling coefficient. default 1.0. can be passed through
401: -sub_ksp_dynamic_tolerance_param
402: bnrm: norm of the right-hand side. store it to avoid repeated calculation
404: Notes:
405: This may be useful for a flexibly preconditioner Krylov method to
406: control the accuracy of the inner solves needed to gaurantee the
407: convergence of the outer iterations.
409: Level: advanced
411: .keywords: KSP, inner tolerance
413: .seealso: KSPMonitorDynamicToleranceDestroy()
414: @*/
415: PetscErrorCode KSPMonitorDynamicTolerance(KSP ksp,PetscInt its,PetscReal fnorm,void *dummy)
416: {
418: PC pc;
419: PetscReal outer_rtol, outer_abstol, outer_dtol, inner_rtol;
420: PetscInt outer_maxits,nksp,first,i;
421: KSPDynTolCtx *scale = (KSPDynTolCtx*)dummy;
422: KSP kspinner = NULL, *subksp = NULL;
425: KSPGetPC(ksp, &pc);
427: /* compute inner_rtol */
428: if (scale->bnrm < 0.0) {
429: Vec b;
430: KSPGetRhs(ksp, &b);
431: VecNorm(b, NORM_2, &(scale->bnrm));
432: }
433: KSPGetTolerances(ksp, &outer_rtol, &outer_abstol, &outer_dtol, &outer_maxits);
434: inner_rtol = PetscMin(scale->coef * scale->bnrm * outer_rtol / fnorm, 0.999);
435: /*PetscPrintf(PETSC_COMM_WORLD, " Inner rtol = %g\n", (double)inner_rtol);*/
437: /* if pc is ksp */
438: PCKSPGetKSP(pc, &kspinner);
439: if (kspinner) {
440: KSPSetTolerances(kspinner, inner_rtol, outer_abstol, outer_dtol, outer_maxits);
441: return(0);
442: }
444: /* if pc is bjacobi */
445: PCBJacobiGetSubKSP(pc, &nksp, &first, &subksp);
446: if (subksp) {
447: for (i=0; i<nksp; i++) {
448: KSPSetTolerances(subksp[i], inner_rtol, outer_abstol, outer_dtol, outer_maxits);
449: }
450: return(0);
451: }
453: /* todo: dynamic tolerance may apply to other types of pc too */
454: return(0);
455: }
457: /*
458: Destroy the dummy context used in KSPMonitorDynamicTolerance()
459: */
460: PetscErrorCode KSPMonitorDynamicToleranceDestroy(void **dummy)
461: {
465: PetscFree(*dummy);
466: return(0);
467: }
469: /*
470: Default (short) KSP Monitor, same as KSPMonitorDefault() except
471: it prints fewer digits of the residual as the residual gets smaller.
472: This is because the later digits are meaningless and are often
473: different on different machines; by using this routine different
474: machines will usually generate the same output.
475: */
476: PetscErrorCode KSPMonitorDefaultShort(KSP ksp,PetscInt its,PetscReal fnorm,PetscViewerAndFormat *dummy)
477: {
479: PetscViewer viewer = dummy->viewer;
483: PetscViewerPushFormat(viewer,dummy->format);
484: PetscViewerASCIIAddTab(viewer,((PetscObject)ksp)->tablevel);
485: if (its == 0 && ((PetscObject)ksp)->prefix) {
486: PetscViewerASCIIPrintf(viewer," Residual norms for %s solve.\n",((PetscObject)ksp)->prefix);
487: }
489: if (fnorm > 1.e-9) {
490: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %g \n",its,(double)fnorm);
491: } else if (fnorm > 1.e-11) {
492: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm %5.3e \n",its,(double)fnorm);
493: } else {
494: PetscViewerASCIIPrintf(viewer,"%3D KSP Residual norm < 1.e-11\n",its);
495: }
496: PetscViewerASCIISubtractTab(viewer,((PetscObject)ksp)->tablevel);
497: PetscViewerPopFormat(viewer);
498: return(0);
499: }
501: /*@C
502: KSPConvergedSkip - Convergence test that do not return as converged
503: until the maximum number of iterations is reached.
505: Collective on KSP
507: Input Parameters:
508: + ksp - iterative context
509: . n - iteration number
510: . rnorm - 2-norm residual value (may be estimated)
511: - dummy - unused convergence context
513: Returns:
514: . reason - KSP_CONVERGED_ITERATING, KSP_CONVERGED_ITS
516: Notes:
517: This should be used as the convergence test with the option
518: KSPSetNormType(ksp,KSP_NORM_NONE), since norms of the residual are
519: not computed. Convergence is then declared after the maximum number
520: of iterations have been reached. Useful when one is using CG or
521: BiCGStab as a smoother.
523: Level: advanced
525: .keywords: KSP, default, convergence, residual
527: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPSetNormType()
528: @*/
529: PetscErrorCode KSPConvergedSkip(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *dummy)
530: {
534: *reason = KSP_CONVERGED_ITERATING;
535: if (n >= ksp->max_it) *reason = KSP_CONVERGED_ITS;
536: return(0);
537: }
540: /*@C
541: KSPConvergedDefaultCreate - Creates and initializes the space used by the KSPConvergedDefault() function context
543: Collective on KSP
545: Output Parameter:
546: . ctx - convergence context
548: Level: intermediate
550: .keywords: KSP, default, convergence, residual
552: .seealso: KSPConvergedDefault(), KSPConvergedDefaultDestroy(), KSPSetConvergenceTest(), KSPSetTolerances(),
553: KSPConvergedSkip(), KSPConvergedReason, KSPGetConvergedReason(), KSPConvergedDefaultSetUIRNorm(), KSPConvergedDefaultSetUMIRNorm()
554: @*/
555: PetscErrorCode KSPConvergedDefaultCreate(void **ctx)
556: {
557: PetscErrorCode ierr;
558: KSPConvergedDefaultCtx *cctx;
561: PetscNew(&cctx);
562: *ctx = cctx;
563: return(0);
564: }
566: /*@
567: KSPConvergedDefaultSetUIRNorm - makes the default convergence test use || B*(b - A*(initial guess))||
568: instead of || B*b ||. In the case of right preconditioner or if KSPSetNormType(ksp,KSP_NORM_UNPRECONDIITONED)
569: is used there is no B in the above formula. UIRNorm is short for Use Initial Residual Norm.
571: Collective on KSP
573: Input Parameters:
574: . ksp - iterative context
576: Options Database:
577: . -ksp_converged_use_initial_residual_norm
579: Notes:
580: Use KSPSetTolerances() to alter the defaults for rtol, abstol, dtol.
582: The precise values of reason are macros such as KSP_CONVERGED_RTOL, which
583: are defined in petscksp.h.
585: If the convergence test is not KSPConvergedDefault() then this is ignored.
587: If right preconditioning is being used then B does not appear in the above formula.
590: Level: intermediate
592: .keywords: KSP, default, convergence, residual
594: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPConvergedSkip(), KSPConvergedReason, KSPGetConvergedReason(), KSPConvergedDefaultSetUMIRNorm()
595: @*/
596: PetscErrorCode KSPConvergedDefaultSetUIRNorm(KSP ksp)
597: {
598: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx*) ksp->cnvP;
602: if (ksp->converged != KSPConvergedDefault) return(0);
603: if (ctx->mininitialrtol) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_WRONGSTATE,"Cannot use KSPConvergedDefaultSetUIRNorm() and KSPConvergedDefaultSetUMIRNorm() together");
604: ctx->initialrtol = PETSC_TRUE;
605: return(0);
606: }
608: /*@
609: KSPConvergedDefaultSetUMIRNorm - makes the default convergence test use min(|| B*(b - A*(initial guess))||,|| B*b ||)
610: In the case of right preconditioner or if KSPSetNormType(ksp,KSP_NORM_UNPRECONDIITONED)
611: is used there is no B in the above formula. UMIRNorm is short for Use Minimum Initial Residual Norm.
613: Collective on KSP
615: Input Parameters:
616: . ksp - iterative context
618: Options Database:
619: . -ksp_converged_use_min_initial_residual_norm
621: Use KSPSetTolerances() to alter the defaults for rtol, abstol, dtol.
623: The precise values of reason are macros such as KSP_CONVERGED_RTOL, which
624: are defined in petscksp.h.
626: Level: intermediate
628: .keywords: KSP, default, convergence, residual
630: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPConvergedSkip(), KSPConvergedReason, KSPGetConvergedReason(), KSPConvergedDefaultSetUIRNorm()
631: @*/
632: PetscErrorCode KSPConvergedDefaultSetUMIRNorm(KSP ksp)
633: {
634: KSPConvergedDefaultCtx *ctx = (KSPConvergedDefaultCtx*) ksp->cnvP;
638: if (ksp->converged != KSPConvergedDefault) return(0);
639: if (ctx->initialrtol) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_WRONGSTATE,"Cannot use KSPConvergedDefaultSetUIRNorm() and KSPConvergedDefaultSetUMIRNorm() together");
640: ctx->mininitialrtol = PETSC_TRUE;
641: return(0);
642: }
644: /*@C
645: KSPConvergedDefault - Determines convergence of the linear iterative solvers by default
647: Collective on KSP
649: Input Parameters:
650: + ksp - iterative context
651: . n - iteration number
652: . rnorm - residual norm (may be estimated, depending on the method may be the preconditioned residual norm)
653: - ctx - convergence context which must be created by KSPConvergedDefaultCreate()
655: Output Parameter:
656: + positive - if the iteration has converged;
657: . negative - if residual norm exceeds divergence threshold;
658: - 0 - otherwise.
660: Notes:
661: KSPConvergedDefault() reaches convergence when rnorm < MAX (rtol * rnorm_0, abstol);
662: Divergence is detected if rnorm > dtol * rnorm_0,
664: where:
665: + rtol = relative tolerance,
666: . abstol = absolute tolerance.
667: . dtol = divergence tolerance,
668: - rnorm_0 is the two norm of the right hand side. When initial guess is non-zero you
669: can call KSPConvergedDefaultSetUIRNorm() to use the norm of (b - A*(initial guess))
670: as the starting point for relative norm convergence testing, that is as rnorm_0
672: Use KSPSetTolerances() to alter the defaults for rtol, abstol, dtol.
674: Use KSPSetNormType() (or -ksp_norm_type <none,preconditioned,unpreconditioned,natural>) to change the norm used for computing rnorm
676: The precise values of reason are macros such as KSP_CONVERGED_RTOL, which are defined in petscksp.h.
678: This routine is used by KSP by default so the user generally never needs call it directly.
680: Use KSPSetConvergenceTest() to provide your own test instead of using this one.
682: Level: intermediate
684: .keywords: KSP, default, convergence, residual
686: .seealso: KSPSetConvergenceTest(), KSPSetTolerances(), KSPConvergedSkip(), KSPConvergedReason, KSPGetConvergedReason(),
687: KSPConvergedDefaultSetUIRNorm(), KSPConvergedDefaultSetUMIRNorm(), KSPConvergedDefaultCreate(), KSPConvergedDefaultDestroy()
688: @*/
689: PetscErrorCode KSPConvergedDefault(KSP ksp,PetscInt n,PetscReal rnorm,KSPConvergedReason *reason,void *ctx)
690: {
691: PetscErrorCode ierr;
692: KSPConvergedDefaultCtx *cctx = (KSPConvergedDefaultCtx*) ctx;
693: KSPNormType normtype;
698: *reason = KSP_CONVERGED_ITERATING;
700: KSPGetNormType(ksp,&normtype);
701: if (normtype == KSP_NORM_NONE) return(0);
703: if (!cctx) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_NULL,"Convergence context must have been created with KSPConvergedDefaultCreate()");
704: if (!n) {
705: /* if user gives initial guess need to compute norm of b */
706: if (!ksp->guess_zero && !cctx->initialrtol) {
707: PetscReal snorm = 0.0;
708: if (ksp->normtype == KSP_NORM_UNPRECONDITIONED || ksp->pc_side == PC_RIGHT) {
709: PetscInfo(ksp,"user has provided nonzero initial guess, computing 2-norm of RHS\n");
710: VecNorm(ksp->vec_rhs,NORM_2,&snorm); /* <- b'*b */
711: } else {
712: Vec z;
713: /* Should avoid allocating the z vector each time but cannot stash it in cctx because if KSPReset() is called the vector size might change */
714: VecDuplicate(ksp->vec_rhs,&z);
715: KSP_PCApply(ksp,ksp->vec_rhs,z);
716: if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
717: PetscInfo(ksp,"user has provided nonzero initial guess, computing 2-norm of preconditioned RHS\n");
718: VecNorm(z,NORM_2,&snorm); /* dp <- b'*B'*B*b */
719: } else if (ksp->normtype == KSP_NORM_NATURAL) {
720: PetscScalar norm;
721: PetscInfo(ksp,"user has provided nonzero initial guess, computing natural norm of RHS\n");
722: VecDot(ksp->vec_rhs,z,&norm);
723: snorm = PetscSqrtReal(PetscAbsScalar(norm)); /* dp <- b'*B*b */
724: }
725: VecDestroy(&z);
726: }
727: /* handle special case of zero RHS and nonzero guess */
728: if (!snorm) {
729: PetscInfo(ksp,"Special case, user has provided nonzero initial guess and zero RHS\n");
730: snorm = rnorm;
731: }
732: if (cctx->mininitialrtol) ksp->rnorm0 = PetscMin(snorm,rnorm);
733: else ksp->rnorm0 = snorm;
734: } else {
735: ksp->rnorm0 = rnorm;
736: }
737: ksp->ttol = PetscMax(ksp->rtol*ksp->rnorm0,ksp->abstol);
738: }
740: if (n <= ksp->chknorm) return(0);
742: if (PetscIsInfOrNanReal(rnorm)) {
743: PCFailedReason pcreason;
744: PetscInt sendbuf,pcreason_max;
745: PCGetSetUpFailedReason(ksp->pc,&pcreason);
746: sendbuf = (PetscInt)pcreason;
747: MPI_Allreduce(&sendbuf,&pcreason_max,1,MPIU_INT,MPIU_MAX,PetscObjectComm((PetscObject)ksp));
748: if (pcreason_max) {
749: *reason = KSP_DIVERGED_PCSETUP_FAILED;
750: VecSetInf(ksp->vec_sol);
751: PetscInfo(ksp,"Linear solver pcsetup fails, declaring divergence \n");
752: } else {
753: *reason = KSP_DIVERGED_NANORINF;
754: PetscInfo(ksp,"Linear solver has created a not a number (NaN) as the residual norm, declaring divergence \n");
755: }
756: } else if (rnorm <= ksp->ttol) {
757: if (rnorm < ksp->abstol) {
758: PetscInfo3(ksp,"Linear solver has converged. Residual norm %14.12e is less than absolute tolerance %14.12e at iteration %D\n",(double)rnorm,(double)ksp->abstol,n);
759: *reason = KSP_CONVERGED_ATOL;
760: } else {
761: if (cctx->initialrtol) {
762: PetscInfo4(ksp,"Linear solver has converged. Residual norm %14.12e is less than relative tolerance %14.12e times initial residual norm %14.12e at iteration %D\n",(double)rnorm,(double)ksp->rtol,(double)ksp->rnorm0,n);
763: } else {
764: PetscInfo4(ksp,"Linear solver has converged. Residual norm %14.12e is less than relative tolerance %14.12e times initial right hand side norm %14.12e at iteration %D\n",(double)rnorm,(double)ksp->rtol,(double)ksp->rnorm0,n);
765: }
766: *reason = KSP_CONVERGED_RTOL;
767: }
768: } else if (rnorm >= ksp->divtol*ksp->rnorm0) {
769: PetscInfo3(ksp,"Linear solver is diverging. Initial right hand size norm %14.12e, current residual norm %14.12e at iteration %D\n",(double)ksp->rnorm0,(double)rnorm,n);
770: *reason = KSP_DIVERGED_DTOL;
771: }
772: return(0);
773: }
775: /*@C
776: KSPConvergedDefaultDestroy - Frees the space used by the KSPConvergedDefault() function context
778: Collective on KSP
780: Input Parameters:
781: . ctx - convergence context
783: Level: intermediate
785: .keywords: KSP, default, convergence, residual
787: .seealso: KSPConvergedDefault(), KSPConvergedDefaultCreate(), KSPSetConvergenceTest(), KSPSetTolerances(), KSPConvergedSkip(),
788: KSPConvergedReason, KSPGetConvergedReason(), KSPConvergedDefaultSetUIRNorm(), KSPConvergedDefaultSetUMIRNorm()
789: @*/
790: PetscErrorCode KSPConvergedDefaultDestroy(void *ctx)
791: {
792: PetscErrorCode ierr;
793: KSPConvergedDefaultCtx *cctx = (KSPConvergedDefaultCtx*) ctx;
796: VecDestroy(&cctx->work);
797: PetscFree(ctx);
798: return(0);
799: }
801: /*
802: KSPBuildSolutionDefault - Default code to create/move the solution.
804: Input Parameters:
805: + ksp - iterative context
806: - v - pointer to the user's vector
808: Output Parameter:
809: . V - pointer to a vector containing the solution
811: Level: advanced
813: Developers Note: This is PETSC_EXTERN because it may be used by user written plugin KSP implementations
815: .keywords: KSP, build, solution, default
817: .seealso: KSPGetSolution(), KSPBuildResidualDefault()
818: */
819: PetscErrorCode KSPBuildSolutionDefault(KSP ksp,Vec v,Vec *V)
820: {
824: if (ksp->pc_side == PC_RIGHT) {
825: if (ksp->pc) {
826: if (v) {
827: KSP_PCApply(ksp,ksp->vec_sol,v); *V = v;
828: } else SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Not working with right preconditioner");
829: } else {
830: if (v) {
831: VecCopy(ksp->vec_sol,v); *V = v;
832: } else *V = ksp->vec_sol;
833: }
834: } else if (ksp->pc_side == PC_SYMMETRIC) {
835: if (ksp->pc) {
836: if (ksp->transpose_solve) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Not working with symmetric preconditioner and transpose solve");
837: if (v) {
838: PCApplySymmetricRight(ksp->pc,ksp->vec_sol,v);
839: *V = v;
840: } else SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Not working with symmetric preconditioner");
841: } else {
842: if (v) {
843: VecCopy(ksp->vec_sol,v); *V = v;
844: } else *V = ksp->vec_sol;
845: }
846: } else {
847: if (v) {
848: VecCopy(ksp->vec_sol,v); *V = v;
849: } else *V = ksp->vec_sol;
850: }
851: return(0);
852: }
854: /*
855: KSPBuildResidualDefault - Default code to compute the residual.
857: Input Parameters:
858: . ksp - iterative context
859: . t - pointer to temporary vector
860: . v - pointer to user vector
862: Output Parameter:
863: . V - pointer to a vector containing the residual
865: Level: advanced
867: Developers Note: This is PETSC_EXTERN because it may be used by user written plugin KSP implementations
869: .keywords: KSP, build, residual, default
871: .seealso: KSPBuildSolutionDefault()
872: */
873: PetscErrorCode KSPBuildResidualDefault(KSP ksp,Vec t,Vec v,Vec *V)
874: {
876: Mat Amat,Pmat;
879: if (!ksp->pc) {KSPGetPC(ksp,&ksp->pc);}
880: PCGetOperators(ksp->pc,&Amat,&Pmat);
881: KSPBuildSolution(ksp,t,NULL);
882: KSP_MatMult(ksp,Amat,t,v);
883: VecAYPX(v,-1.0,ksp->vec_rhs);
884: *V = v;
885: return(0);
886: }
888: /*@C
889: KSPCreateVecs - Gets a number of work vectors.
891: Input Parameters:
892: + ksp - iterative context
893: . rightn - number of right work vectors
894: - leftn - number of left work vectors to allocate
896: Output Parameter:
897: + right - the array of vectors created
898: - left - the array of left vectors
900: Note: The right vector has as many elements as the matrix has columns. The left
901: vector has as many elements as the matrix has rows.
903: The vectors are new vectors that are not owned by the KSP, they should be destroyed with calls to VecDestroyVecs() when no longer needed.
905: Developers Note: First tries to duplicate the rhs and solution vectors of the KSP, if they do not exist tries to get them from the matrix, if
906: that does not exist tries to get them from the DM (if it is provided).
908: Level: advanced
910: .seealso: MatCreateVecs(), VecDestroyVecs()
912: @*/
913: PetscErrorCode KSPCreateVecs(KSP ksp,PetscInt rightn, Vec **right,PetscInt leftn,Vec **left)
914: {
916: Vec vecr = NULL,vecl = NULL;
917: PetscBool matset,pmatset;
918: Mat mat = NULL;
921: if (rightn) {
922: if (!right) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_INCOMP,"You asked for right vectors but did not pass a pointer to hold them");
923: if (ksp->vec_sol) vecr = ksp->vec_sol;
924: else {
925: if (ksp->pc) {
926: PCGetOperatorsSet(ksp->pc,&matset,&pmatset);
927: /* check for mat before pmat because for KSPLSQR pmat may be a different size than mat since pmat maybe mat'*mat */
928: if (matset) {
929: PCGetOperators(ksp->pc,&mat,NULL);
930: MatCreateVecs(mat,&vecr,NULL);
931: } else if (pmatset) {
932: PCGetOperators(ksp->pc,NULL,&mat);
933: MatCreateVecs(mat,&vecr,NULL);
934: }
935: }
936: if (!vecr) {
937: if (ksp->dm) {
938: DMGetGlobalVector(ksp->dm,&vecr);
939: } else SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_WRONGSTATE,"You requested a vector from a KSP that cannot provide one");
940: }
941: }
942: VecDuplicateVecs(vecr,rightn,right);
943: if (!ksp->vec_sol) {
944: if (mat) {
945: VecDestroy(&vecr);
946: } else if (ksp->dm) {
947: DMRestoreGlobalVector(ksp->dm,&vecr);
948: }
949: }
950: }
951: if (leftn) {
952: if (!left) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_INCOMP,"You asked for left vectors but did not pass a pointer to hold them");
953: if (ksp->vec_rhs) vecl = ksp->vec_rhs;
954: else {
955: if (ksp->pc) {
956: PCGetOperatorsSet(ksp->pc,&matset,&pmatset);
957: /* check for mat before pmat because for KSPLSQR pmat may be a different size than mat since pmat maybe mat'*mat */
958: if (matset) {
959: PCGetOperators(ksp->pc,&mat,NULL);
960: MatCreateVecs(mat,NULL,&vecl);
961: } else if (pmatset) {
962: PCGetOperators(ksp->pc,NULL,&mat);
963: MatCreateVecs(mat,NULL,&vecl);
964: }
965: }
966: if (!vecl) {
967: if (ksp->dm) {
968: DMGetGlobalVector(ksp->dm,&vecl);
969: } else SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_WRONGSTATE,"You requested a vector from a KSP that cannot provide one");
970: }
971: }
972: VecDuplicateVecs(vecl,leftn,left);
973: if (!ksp->vec_rhs) {
974: if (mat) {
975: VecDestroy(&vecl);
976: } else if (ksp->dm) {
977: DMRestoreGlobalVector(ksp->dm,&vecl);
978: }
979: }
980: }
981: return(0);
982: }
984: /*@C
985: KSPSetWorkVecs - Sets a number of work vectors into a KSP object
987: Collective on KSP
989: Input Parameters:
990: + ksp - iterative context
991: - nw - number of work vectors to allocate
993: Level: developer
995: Developers Note: This is PETSC_EXTERN because it may be used by user written plugin KSP implementations
997: @*/
998: PetscErrorCode KSPSetWorkVecs(KSP ksp,PetscInt nw)
999: {
1003: VecDestroyVecs(ksp->nwork,&ksp->work);
1004: ksp->nwork = nw;
1005: KSPCreateVecs(ksp,nw,&ksp->work,0,NULL);
1006: PetscLogObjectParents(ksp,nw,ksp->work);
1007: return(0);
1008: }
1010: /*
1011: KSPDestroyDefault - Destroys a iterative context variable for methods with
1012: no separate context. Preferred calling sequence KSPDestroy().
1014: Input Parameter:
1015: . ksp - the iterative context
1017: Developers Note: This is PETSC_EXTERN because it may be used by user written plugin KSP implementations
1019: */
1020: PetscErrorCode KSPDestroyDefault(KSP ksp)
1021: {
1026: PetscFree(ksp->data);
1027: return(0);
1028: }
1030: /*@
1031: KSPGetConvergedReason - Gets the reason the KSP iteration was stopped.
1033: Not Collective
1035: Input Parameter:
1036: . ksp - the KSP context
1038: Output Parameter:
1039: . reason - negative value indicates diverged, positive value converged, see KSPConvergedReason
1041: Possible values for reason: See also manual page for each reason
1042: $ KSP_CONVERGED_RTOL (residual 2-norm decreased by a factor of rtol, from 2-norm of right hand side)
1043: $ KSP_CONVERGED_ATOL (residual 2-norm less than abstol)
1044: $ KSP_CONVERGED_ITS (used by the preonly preconditioner that always uses ONE iteration, or when the KSPConvergedSkip() convergence test routine is set.
1045: $ KSP_CONVERGED_CG_NEG_CURVE (see note below)
1046: $ KSP_CONVERGED_CG_CONSTRAINED (see note below)
1047: $ KSP_CONVERGED_STEP_LENGTH (see note below)
1048: $ KSP_CONVERGED_ITERATING (returned if the solver is not yet finished)
1049: $ KSP_DIVERGED_ITS (required more than its to reach convergence)
1050: $ KSP_DIVERGED_DTOL (residual norm increased by a factor of divtol)
1051: $ KSP_DIVERGED_NANORINF (residual norm became Not-a-number or Inf likely due to 0/0)
1052: $ KSP_DIVERGED_BREAKDOWN (generic breakdown in method)
1053: $ KSP_DIVERGED_BREAKDOWN_BICG (Initial residual is orthogonal to preconditioned initial residual. Try a different preconditioner, or a different initial Level.)
1055: Options Database:
1056: . -ksp_converged_reason - prints the reason to standard out
1058: Notes: If this routine is called before or doing the KSPSolve() the value of KSP_CONVERGED_ITERATING is returned
1060: The values KSP_CONVERGED_CG_NEG_CURVE, KSP_CONVERGED_CG_CONSTRAINED, and KSP_CONVERGED_STEP_LENGTH are returned only by the special KSPCGNASH, KSPCGSTCG, and KSPCGGLTR
1061: solvers which are used by the SNESNEWTONTR (trust region) solver.
1063: Level: intermediate
1065: .keywords: KSP, nonlinear, set, convergence, test
1067: .seealso: KSPSetConvergenceTest(), KSPConvergedDefault(), KSPSetTolerances(), KSPConvergedReason
1068: @*/
1069: PetscErrorCode KSPGetConvergedReason(KSP ksp,KSPConvergedReason *reason)
1070: {
1074: *reason = ksp->reason;
1075: return(0);
1076: }
1078: #include <petsc/private/dmimpl.h>
1079: /*@
1080: KSPSetDM - Sets the DM that may be used by some preconditioners
1082: Logically Collective on KSP
1084: Input Parameters:
1085: + ksp - the preconditioner context
1086: - dm - the dm, cannot be NULL
1088: Notes: If this is used then the KSP will attempt to use the DM to create the matrix and use the routine
1089: set with DMKSPSetComputeOperators(). Use KSPSetDMActive(ksp,PETSC_FALSE) to instead use the matrix
1090: you've provided with KSPSetOperators().
1092: Level: intermediate
1094: .seealso: KSPGetDM(), KSPSetDMActive(), KSPSetComputeOperators(), KSPSetComputeRHS(), KSPSetComputeInitialGuess(), DMKSPSetComputeOperators(), DMKSPSetComputeRHS(), DMKSPSetComputeInitialGuess()
1095: @*/
1096: PetscErrorCode KSPSetDM(KSP ksp,DM dm)
1097: {
1099: PC pc;
1104: PetscObjectReference((PetscObject)dm);
1105: if (ksp->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */
1106: if (ksp->dm->dmksp && !dm->dmksp) {
1107: DMKSP kdm;
1108: DMCopyDMKSP(ksp->dm,dm);
1109: DMGetDMKSP(ksp->dm,&kdm);
1110: if (kdm->originaldm == ksp->dm) kdm->originaldm = dm; /* Grant write privileges to the replacement DM */
1111: }
1112: DMDestroy(&ksp->dm);
1113: }
1114: ksp->dm = dm;
1115: ksp->dmAuto = PETSC_FALSE;
1116: KSPGetPC(ksp,&pc);
1117: PCSetDM(pc,dm);
1118: ksp->dmActive = PETSC_TRUE;
1119: return(0);
1120: }
1122: /*@
1123: KSPSetDMActive - Indicates the DM should be used to generate the linear system matrix and right hand side
1125: Logically Collective on KSP
1127: Input Parameters:
1128: + ksp - the preconditioner context
1129: - flg - use the DM
1131: Notes:
1132: By default KSPSetDM() sets the DM as active, call KSPSetDMActive(ksp,PETSC_FALSE); after KSPSetDM(ksp,dm) to not have the KSP object use the DM to generate the matrices.
1134: Level: intermediate
1136: .seealso: KSPGetDM(), KSPSetDM(), SNESSetDM(), KSPSetComputeOperators(), KSPSetComputeRHS(), KSPSetComputeInitialGuess()
1137: @*/
1138: PetscErrorCode KSPSetDMActive(KSP ksp,PetscBool flg)
1139: {
1143: ksp->dmActive = flg;
1144: return(0);
1145: }
1147: /*@
1148: KSPGetDM - Gets the DM that may be used by some preconditioners
1150: Not Collective
1152: Input Parameter:
1153: . ksp - the preconditioner context
1155: Output Parameter:
1156: . dm - the dm
1158: Level: intermediate
1161: .seealso: KSPSetDM(), KSPSetDMActive()
1162: @*/
1163: PetscErrorCode KSPGetDM(KSP ksp,DM *dm)
1164: {
1169: if (!ksp->dm) {
1170: DMShellCreate(PetscObjectComm((PetscObject)ksp),&ksp->dm);
1171: ksp->dmAuto = PETSC_TRUE;
1172: }
1173: *dm = ksp->dm;
1174: return(0);
1175: }
1177: /*@
1178: KSPSetApplicationContext - Sets the optional user-defined context for the linear solver.
1180: Logically Collective on KSP
1182: Input Parameters:
1183: + ksp - the KSP context
1184: - usrP - optional user context
1186: Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this
1187: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1189: Level: intermediate
1191: .keywords: KSP, set, application, context
1193: .seealso: KSPGetApplicationContext()
1194: @*/
1195: PetscErrorCode KSPSetApplicationContext(KSP ksp,void *usrP)
1196: {
1198: PC pc;
1202: ksp->user = usrP;
1203: KSPGetPC(ksp,&pc);
1204: PCSetApplicationContext(pc,usrP);
1205: return(0);
1206: }
1208: /*@
1209: KSPGetApplicationContext - Gets the user-defined context for the linear solver.
1211: Not Collective
1213: Input Parameter:
1214: . ksp - KSP context
1216: Output Parameter:
1217: . usrP - user context
1219: Fortran Notes: To use this from Fortran you must write a Fortran interface definition for this
1220: function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument.
1222: Level: intermediate
1224: .keywords: KSP, get, application, context
1226: .seealso: KSPSetApplicationContext()
1227: @*/
1228: PetscErrorCode KSPGetApplicationContext(KSP ksp,void *usrP)
1229: {
1232: *(void**)usrP = ksp->user;
1233: return(0);
1234: }