Actual source code: snesut.c


  2: #include <petsc/private/snesimpl.h>
  3: #include <petscdm.h>
  4: #include <petscsection.h>
  5: #include <petscblaslapack.h>

  7: /*@C
  8:    SNESMonitorSolution - Monitors progress of the `SNES` solvers by calling
  9:    `VecView()` for the approximate solution at each iteration.

 11:    Collective

 13:    Input Parameters:
 14: +  snes - the `SNES` context
 15: .  its - iteration number
 16: .  fgnorm - 2-norm of residual
 17: -  dummy -  a viewer

 19:    Options Database Key:
 20: .  -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration

 22:    Level: intermediate

 24:    Note:
 25:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
 26:    to be used during the `SNESSolve()`

 28: .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()`
 29: @*/
 30: PetscErrorCode SNESMonitorSolution(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
 31: {
 32:   Vec         x;
 33:   PetscViewer viewer = vf->viewer;

 35:   PetscFunctionBegin;
 37:   PetscCall(SNESGetSolution(snes, &x));
 38:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
 39:   PetscCall(VecView(x, viewer));
 40:   PetscCall(PetscViewerPopFormat(viewer));
 41:   PetscFunctionReturn(PETSC_SUCCESS);
 42: }

 44: /*@C
 45:    SNESMonitorResidual - Monitors progress of the `SNES` solvers by calling
 46:    `VecView()` for the residual at each iteration.

 48:    Collective

 50:    Input Parameters:
 51: +  snes - the `SNES` context
 52: .  its - iteration number
 53: .  fgnorm - 2-norm of residual
 54: -  dummy -  a viewer

 56:    Options Database Key:
 57: .  -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration

 59:    Level: intermediate

 61:    Note:
 62:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
 63:    to be used during the `SNES` solve.

 65: .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()`, `SNESMonitor()`
 66: @*/
 67: PetscErrorCode SNESMonitorResidual(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
 68: {
 69:   Vec x;

 71:   PetscFunctionBegin;
 73:   PetscCall(SNESGetFunction(snes, &x, NULL, NULL));
 74:   PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
 75:   PetscCall(VecView(x, vf->viewer));
 76:   PetscCall(PetscViewerPopFormat(vf->viewer));
 77:   PetscFunctionReturn(PETSC_SUCCESS);
 78: }

 80: /*@C
 81:    SNESMonitorSolutionUpdate - Monitors progress of the `SNES` solvers by calling
 82:    `VecView()` for the UPDATE to the solution at each iteration.

 84:    Collective

 86:    Input Parameters:
 87: +  snes - the `SNES` context
 88: .  its - iteration number
 89: .  fgnorm - 2-norm of residual
 90: -  dummy - a viewer

 92:    Options Database Key:
 93: .  -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration

 95:    Level: intermediate

 97:    Note:
 98:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
 99:    to be used during the `SNES` solve.

101: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorDefault()`, `VecView()`, `SNESMonitor()`, `SNESMonitor()`
102: @*/
103: PetscErrorCode SNESMonitorSolutionUpdate(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
104: {
105:   Vec         x;
106:   PetscViewer viewer = vf->viewer;

108:   PetscFunctionBegin;
110:   PetscCall(SNESGetSolutionUpdate(snes, &x));
111:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
112:   PetscCall(VecView(x, viewer));
113:   PetscCall(PetscViewerPopFormat(viewer));
114:   PetscFunctionReturn(PETSC_SUCCESS);
115: }

117: #include <petscdraw.h>

119: /*@C
120:   KSPMonitorSNESResidual - Prints the `SNES` residual norm, as well as the `KSP` residual norm, at each iteration of an iterative solver.

122:   Collective

124:   Input Parameters:
125: + ksp   - iterative context
126: . n     - iteration number
127: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
128: - vf    - The viewer context

130:   Options Database Key:
131: . -snes_monitor_ksp - Activates `KSPMonitorSNESResidual()`

133:   Level: intermediate

135:    Note:
136:    This is not called directly by users, rather one calls `KSPMonitorSet()`, with this function as an argument, to cause the monitor
137:    to be used during the `KSP` solve.

139: .seealso: [](ch_snes), `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`, `KSPMonitor()`, `SNESMonitor()`
140: @*/
141: PetscErrorCode KSPMonitorSNESResidual(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
142: {
143:   PetscViewer       viewer = vf->viewer;
144:   PetscViewerFormat format = vf->format;
145:   SNES              snes   = (SNES)vf->data;
146:   Vec               snes_solution, work1, work2;
147:   PetscReal         snorm;
148:   PetscInt          tablevel;
149:   const char       *prefix;

151:   PetscFunctionBegin;
153:   PetscCall(SNESGetSolution(snes, &snes_solution));
154:   PetscCall(VecDuplicate(snes_solution, &work1));
155:   PetscCall(VecDuplicate(snes_solution, &work2));
156:   PetscCall(KSPBuildSolution(ksp, work1, NULL));
157:   PetscCall(VecAYPX(work1, -1.0, snes_solution));
158:   PetscCall(SNESComputeFunction(snes, work1, work2));
159:   PetscCall(VecNorm(work2, NORM_2, &snorm));
160:   PetscCall(VecDestroy(&work1));
161:   PetscCall(VecDestroy(&work2));

163:   PetscCall(PetscObjectGetTabLevel((PetscObject)ksp, &tablevel));
164:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
165:   PetscCall(PetscViewerPushFormat(viewer, format));
166:   PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
167:   if (n == 0 && prefix) PetscCall(PetscViewerASCIIPrintf(viewer, "  Residual norms for %s solve.\n", prefix));
168:   PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Residual norm %5.3e KSP Residual norm %5.3e \n", n, (double)snorm, (double)rnorm));
169:   PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
170:   PetscCall(PetscViewerPopFormat(viewer));
171:   PetscFunctionReturn(PETSC_SUCCESS);
172: }

174: /*@C
175:   KSPMonitorSNESResidualDrawLG - Plots the linear `KSP` residual norm and the `SNES` residual norm at each iteration of an iterative solver.

177:   Collective

179:   Input Parameters:
180: + ksp   - iterative context
181: . n     - iteration number
182: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
183: - vf    - The viewer context, created with `KSPMonitorSNESResidualDrawLGCreate()`

185:   Options Database Key:
186: . -snes_monitor_ksp draw::draw_lg - Activates `KSPMonitorSNESResidualDrawLG()`

188:   Level: intermediate

190:    Note:
191:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
192:    to be used during the `SNESSolve()`

194: .seealso: [](ch_snes), `KSPMonitorSet()`, `KSPMonitorTrueResidual()`, `SNESMonitor()`, `KSPMonitor()`, `KSPMonitorSNESResidualDrawLGCreate()`
195: @*/
196: PetscErrorCode KSPMonitorSNESResidualDrawLG(KSP ksp, PetscInt n, PetscReal rnorm, PetscViewerAndFormat *vf)
197: {
198:   PetscViewer        viewer = vf->viewer;
199:   PetscViewerFormat  format = vf->format;
200:   PetscDrawLG        lg     = vf->lg;
201:   SNES               snes   = (SNES)vf->data;
202:   Vec                snes_solution, work1, work2;
203:   PetscReal          snorm;
204:   KSPConvergedReason reason;
205:   PetscReal          x[2], y[2];

207:   PetscFunctionBegin;
210:   PetscCall(SNESGetSolution(snes, &snes_solution));
211:   PetscCall(VecDuplicate(snes_solution, &work1));
212:   PetscCall(VecDuplicate(snes_solution, &work2));
213:   PetscCall(KSPBuildSolution(ksp, work1, NULL));
214:   PetscCall(VecAYPX(work1, -1.0, snes_solution));
215:   PetscCall(SNESComputeFunction(snes, work1, work2));
216:   PetscCall(VecNorm(work2, NORM_2, &snorm));
217:   PetscCall(VecDestroy(&work1));
218:   PetscCall(VecDestroy(&work2));

220:   PetscCall(PetscViewerPushFormat(viewer, format));
221:   if (!n) PetscCall(PetscDrawLGReset(lg));
222:   x[0] = (PetscReal)n;
223:   if (rnorm > 0.0) y[0] = PetscLog10Real(rnorm);
224:   else y[0] = -15.0;
225:   x[1] = (PetscReal)n;
226:   if (snorm > 0.0) y[1] = PetscLog10Real(snorm);
227:   else y[1] = -15.0;
228:   PetscCall(PetscDrawLGAddPoint(lg, x, y));
229:   PetscCall(KSPGetConvergedReason(ksp, &reason));
230:   if (n <= 20 || !(n % 5) || reason) {
231:     PetscCall(PetscDrawLGDraw(lg));
232:     PetscCall(PetscDrawLGSave(lg));
233:   }
234:   PetscCall(PetscViewerPopFormat(viewer));
235:   PetscFunctionReturn(PETSC_SUCCESS);
236: }

238: /*@C
239:   KSPMonitorSNESResidualDrawLGCreate - Creates the `PetscViewer` used by `KSPMonitorSNESResidualDrawLG()`

241:   Collective

243:   Input Parameters:
244: + viewer - The `PetscViewer`
245: . format - The viewer format
246: - ctx    - An optional user context

248:   Output Parameter:
249: . vf    - The viewer context

251:   Level: intermediate

253: .seealso: [](ch_snes), `KSP`, `SNES`, `PetscViewerFormat`, `PetscViewerAndFormat`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
254: @*/
255: PetscErrorCode KSPMonitorSNESResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
256: {
257:   const char *names[] = {"linear", "nonlinear"};

259:   PetscFunctionBegin;
260:   PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
261:   (*vf)->data = ctx;
262:   PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject)viewer), NULL, NULL, "Log Residual Norm", 2, names, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg));
263:   PetscFunctionReturn(PETSC_SUCCESS);
264: }

266: PetscErrorCode SNESMonitorDefaultSetUp(SNES snes, PetscViewerAndFormat *vf)
267: {
268:   PetscFunctionBegin;
269:   if (vf->format == PETSC_VIEWER_DRAW_LG) PetscCall(KSPMonitorLGCreate(PetscObjectComm((PetscObject)vf->viewer), NULL, NULL, "Log Residual Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &vf->lg));
270:   PetscFunctionReturn(PETSC_SUCCESS);
271: }

273: /*@C
274:    SNESMonitorDefault - Monitors progress of the `SNES` solvers (default).

276:    Collective

278:    Input Parameters:
279: +  snes - the `SNES` context
280: .  its - iteration number
281: .  fgnorm - 2-norm of residual
282: -  vf - viewer and format structure

284:    Options Database Key:
285: .  -snes_monitor - use this function to monitor the convergence of the nonlinear solver

287:    Level: intermediate

289:    Notes:
290:    This routine prints the residual norm at each iteration.

292:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
293:    to be used during the `SNES` solve.

295: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorFunction()`, `SNESMonitorSolution()`, `SNESMonitorResidual()`,
296:           `SNESMonitorSolutionUpdate()`, `SNESMonitorDefault()`, `SNESMonitorScaling()`, `SNESMonitorRange()`, `SNESMonitorRatio()`,
297:           `SNESMonitorDefaultField()`, `PetscViewerFormat`, `PetscViewerAndFormat`
298: @*/
299: PetscErrorCode SNESMonitorDefault(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
300: {
301:   PetscViewer       viewer = vf->viewer;
302:   PetscViewerFormat format = vf->format;
303:   PetscBool         isascii, isdraw;

305:   PetscFunctionBegin;
307:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
308:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
309:   PetscCall(PetscViewerPushFormat(viewer, format));
310:   if (isascii) {
311:     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
312:     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
313:       Vec       dx;
314:       PetscReal upnorm;
315:       PetscErrorCode (*objective)(SNES, Vec, PetscReal *, void *);

317:       PetscCall(SNESGetSolutionUpdate(snes, &dx));
318:       PetscCall(VecNorm(dx, NORM_2, &upnorm));
319:       PetscCall(SNESGetObjective(snes, &objective, NULL));
320:       if (objective) {
321:         Vec       x;
322:         PetscReal obj;

324:         PetscCall(SNESGetSolution(snes, &x));
325:         PetscCall(SNESComputeObjective(snes, x, &obj));
326:         PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e, Update norm %14.12e, Objective %14.12e\n", its, (double)fgnorm, (double)upnorm, (double)obj));
327:       } else {
328:         PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e, Update norm %14.12e\n", its, (double)fgnorm, (double)upnorm));
329:       }
330:     } else {
331:       PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e \n", its, (double)fgnorm));
332:     }
333:     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
334:   } else if (isdraw) {
335:     if (format == PETSC_VIEWER_DRAW_LG) {
336:       PetscDrawLG lg = (PetscDrawLG)vf->lg;
337:       PetscReal   x, y;

340:       if (!its) PetscCall(PetscDrawLGReset(lg));
341:       x = (PetscReal)its;
342:       if (fgnorm > 0.0) y = PetscLog10Real(fgnorm);
343:       else y = -15.0;
344:       PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
345:       if (its <= 20 || !(its % 5) || snes->reason) {
346:         PetscCall(PetscDrawLGDraw(lg));
347:         PetscCall(PetscDrawLGSave(lg));
348:       }
349:     }
350:   }
351:   PetscCall(PetscViewerPopFormat(viewer));
352:   PetscFunctionReturn(PETSC_SUCCESS);
353: }

355: /*@C
356:    SNESMonitorScaling - Monitors the largest value in each row of the Jacobian.

358:    Collective

360:    Input Parameters:
361: +  snes - the `SNES` context
362: .  its - iteration number
363: .  fgnorm - 2-norm of residual
364: -  vf - viewer and format structure

366:    Level: intermediate

368:    Notes:
369:    This routine prints the largest value in each row of the Jacobian

371:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
372:    to be used during the `SNES` solve.

374: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `SNESMonitorJacUpdateSpectrum()`,
375:           `PetscViewerFormat`, `PetscViewerAndFormat`
376: @*/
377: PetscErrorCode SNESMonitorScaling(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
378: {
379:   PetscViewer viewer = vf->viewer;
380:   KSP         ksp;
381:   Mat         J;
382:   Vec         v;

384:   PetscFunctionBegin;
386:   PetscCall(SNESGetKSP(snes, &ksp));
387:   PetscCall(KSPGetOperators(ksp, &J, NULL));
388:   PetscCall(MatCreateVecs(J, &v, NULL));
389:   PetscCall(MatGetRowMaxAbs(J, v, NULL));
390:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
391:   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
392:   PetscCall(PetscViewerASCIIPrintf(viewer, "SNES Jacobian maximum row entries\n"));
393:   PetscCall(VecView(v, viewer));
394:   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
395:   PetscCall(PetscViewerPopFormat(viewer));
396:   PetscCall(VecDestroy(&v));
397:   PetscFunctionReturn(PETSC_SUCCESS);
398: }

400: /*@C
401:    SNESMonitorJacUpdateSpectrum - Monitors the spectrun of the change in the Jacobian from the last Jacobian evaluation

403:    Collective

405:    Input Parameters:
406: +  snes - the `SNES` context
407: .  its - iteration number
408: .  fgnorm - 2-norm of residual
409: -  vf - viewer and format structure

411:    Options Database Key:
412: .  -snes_monitor_jacupdate_spectrum - activates this monitor

414:    Level: intermediate

416:    Notes:
417:    This routine prints the eigenvalues of the difference in the Jacobians

419:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
420:    to be used during the `SNES` solve.

422: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `PetscViewerFormat`, `PetscViewerAndFormat`
423: @*/
424: PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes, PetscInt it, PetscReal fnorm, PetscViewerAndFormat *vf)
425: {
426:   Vec X;
427:   Mat J, dJ, dJdense;
428:   PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);
429:   PetscInt     n;
430:   PetscBLASInt nb = 0, lwork;
431:   PetscReal   *eigr, *eigi;
432:   PetscScalar *work;
433:   PetscScalar *a;

435:   PetscFunctionBegin;
436:   if (it == 0) PetscFunctionReturn(PETSC_SUCCESS);
437:   /* create the difference between the current update and the current Jacobian */
438:   PetscCall(SNESGetSolution(snes, &X));
439:   PetscCall(SNESGetJacobian(snes, NULL, &J, &func, NULL));
440:   PetscCall(MatDuplicate(J, MAT_COPY_VALUES, &dJ));
441:   PetscCall(SNESComputeJacobian(snes, X, dJ, dJ));
442:   PetscCall(MatAXPY(dJ, -1.0, J, SAME_NONZERO_PATTERN));

444:   /* compute the spectrum directly */
445:   PetscCall(MatConvert(dJ, MATSEQDENSE, MAT_INITIAL_MATRIX, &dJdense));
446:   PetscCall(MatGetSize(dJ, &n, NULL));
447:   PetscCall(PetscBLASIntCast(n, &nb));
448:   lwork = 3 * nb;
449:   PetscCall(PetscMalloc1(n, &eigr));
450:   PetscCall(PetscMalloc1(n, &eigi));
451:   PetscCall(PetscMalloc1(lwork, &work));
452:   PetscCall(MatDenseGetArray(dJdense, &a));
453: #if !defined(PETSC_USE_COMPLEX)
454:   {
455:     PetscBLASInt lierr;
456:     PetscInt     i;
457:     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
458:     PetscCallBLAS("LAPACKgeev", LAPACKgeev_("N", "N", &nb, a, &nb, eigr, eigi, NULL, &nb, NULL, &nb, work, &lwork, &lierr));
459:     PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "geev() error %" PetscBLASInt_FMT, lierr);
460:     PetscCall(PetscFPTrapPop());
461:     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Eigenvalues of J_%" PetscInt_FMT " - J_%" PetscInt_FMT ":\n", it, it - 1));
462:     for (i = 0; i < n; i++) PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "%5" PetscInt_FMT ": %20.5g + %20.5gi\n", i, (double)eigr[i], (double)eigi[i]));
463:   }
464:   PetscCall(MatDenseRestoreArray(dJdense, &a));
465:   PetscCall(MatDestroy(&dJ));
466:   PetscCall(MatDestroy(&dJdense));
467:   PetscCall(PetscFree(eigr));
468:   PetscCall(PetscFree(eigi));
469:   PetscCall(PetscFree(work));
470:   PetscFunctionReturn(PETSC_SUCCESS);
471: #else
472:   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded for complex");
473: #endif
474: }

476: PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES, PetscInt, PetscReal *);

478: PetscErrorCode SNESMonitorRange_Private(SNES snes, PetscInt it, PetscReal *per)
479: {
480:   Vec          resid;
481:   PetscReal    rmax, pwork;
482:   PetscInt     i, n, N;
483:   PetscScalar *r;

485:   PetscFunctionBegin;
486:   PetscCall(SNESGetFunction(snes, &resid, NULL, NULL));
487:   PetscCall(VecNorm(resid, NORM_INFINITY, &rmax));
488:   PetscCall(VecGetLocalSize(resid, &n));
489:   PetscCall(VecGetSize(resid, &N));
490:   PetscCall(VecGetArray(resid, &r));
491:   pwork = 0.0;
492:   for (i = 0; i < n; i++) pwork += (PetscAbsScalar(r[i]) > .20 * rmax);
493:   PetscCall(MPIU_Allreduce(&pwork, per, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)snes)));
494:   PetscCall(VecRestoreArray(resid, &r));
495:   *per = *per / N;
496:   PetscFunctionReturn(PETSC_SUCCESS);
497: }

499: /*@C
500:    SNESMonitorRange - Prints the percentage of residual elements that are more then 10 percent of the maximum entry in the residual

502:    Collective

504:    Input Parameters:
505: +  snes   - iterative context
506: .  it    - iteration number
507: .  rnorm - 2-norm (preconditioned) residual value (may be estimated).
508: -  dummy - unused monitor context

510:    Options Database Key:
511: .  -snes_monitor_range - Activates `SNESMonitorRange()`

513:    Level: intermediate

515:    Note:
516:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
517:    to be used during the `SNES` solve.

519: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorDefault()`, `SNESMonitorLGCreate()`, `SNESMonitorScaling()`, `PetscViewerFormat`, `PetscViewerAndFormat`
520: @*/
521: PetscErrorCode SNESMonitorRange(SNES snes, PetscInt it, PetscReal rnorm, PetscViewerAndFormat *vf)
522: {
523:   PetscReal   perc, rel;
524:   PetscViewer viewer = vf->viewer;
525:   /* should be in a MonitorRangeContext */
526:   static PetscReal prev;

528:   PetscFunctionBegin;
530:   if (!it) prev = rnorm;
531:   PetscCall(SNESMonitorRange_Private(snes, it, &perc));

533:   rel  = (prev - rnorm) / prev;
534:   prev = rnorm;
535:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
536:   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
537:   PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES preconditioned resid norm %14.12e Percent values above 20 percent of maximum %5.2g relative decrease %5.2e ratio %5.2e \n", it, (double)rnorm, (double)(100.0 * perc), (double)rel, (double)(rel / perc)));
538:   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
539:   PetscCall(PetscViewerPopFormat(viewer));
540:   PetscFunctionReturn(PETSC_SUCCESS);
541: }

543: /*@C
544:    SNESMonitorRatio - Monitors progress of the `SNES` solvers by printing the ratio
545:    of residual norm at each iteration to the previous.

547:    Collective

549:    Input Parameters:
550: +  snes - the `SNES` context
551: .  its - iteration number
552: .  fgnorm - 2-norm of residual (or gradient)
553: -  dummy -  context of monitor

555:    Options Database Key:
556: .  -snes_monitor_ratio - activate this monitor

558:    Level: intermediate

560:    Notes:
561:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
562:    to be used during the `SNES` solve.

564:    Be sure to call `SNESMonitorRationSetUp()` before using this monitor.

566: .seealso: [](ch_snes), `SNESMonitorRationSetUp()`, `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `PetscViewerFormat`, `PetscViewerAndFormat`
567: @*/
568: PetscErrorCode SNESMonitorRatio(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
569: {
570:   PetscInt    len;
571:   PetscReal  *history;
572:   PetscViewer viewer = vf->viewer;

574:   PetscFunctionBegin;
575:   PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, &len));
576:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
577:   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
578:   if (!its || !history || its > len) {
579:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e \n", its, (double)fgnorm));
580:   } else {
581:     PetscReal ratio = fgnorm / history[its - 1];
582:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e %14.12e \n", its, (double)fgnorm, (double)ratio));
583:   }
584:   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
585:   PetscCall(PetscViewerPopFormat(viewer));
586:   PetscFunctionReturn(PETSC_SUCCESS);
587: }

589: /*@C
590:    SNESMonitorRatioSetUp - Insures the `SNES` object is saving its history since this monitor needs access to it

592:    Collective

594:    Input Parameters:
595: +   snes - the `SNES` context
596: -   viewer - the `PetscViewer` object (ignored)

598:    Level: intermediate

600: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `SNESMonitorRatio()`, `PetscViewerFormat`, `PetscViewerAndFormat`
601: @*/
602: PetscErrorCode SNESMonitorRatioSetUp(SNES snes, PetscViewerAndFormat *vf)
603: {
604:   PetscReal *history;

606:   PetscFunctionBegin;
607:   PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, NULL));
608:   if (!history) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, 100, PETSC_TRUE));
609:   PetscFunctionReturn(PETSC_SUCCESS);
610: }

612: /*
613:      Default (short) SNES Monitor, same as SNESMonitorDefault() except
614:   it prints fewer digits of the residual as the residual gets smaller.
615:   This is because the later digits are meaningless and are often
616:   different on different machines; by using this routine different
617:   machines will usually generate the same output.

619:   Deprecated: Intentionally has no manual page
620: */
621: PetscErrorCode SNESMonitorDefaultShort(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
622: {
623:   PetscViewer viewer = vf->viewer;

625:   PetscFunctionBegin;
627:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
628:   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
629:   if (fgnorm > 1.e-9) {
630:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %g \n", its, (double)fgnorm));
631:   } else if (fgnorm > 1.e-11) {
632:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %5.3e \n", its, (double)fgnorm));
633:   } else {
634:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm < 1.e-11\n", its));
635:   }
636:   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
637:   PetscCall(PetscViewerPopFormat(viewer));
638:   PetscFunctionReturn(PETSC_SUCCESS);
639: }

641: /*@C
642:   SNESMonitorDefaultField - Monitors progress of the `SNES` solvers, separated into fields.

644:   Collective

646:   Input Parameters:
647: + snes   - the `SNES` context
648: . its    - iteration number
649: . fgnorm - 2-norm of residual
650: - ctx    - the PetscViewer

652:    Options Database Key:
653: .  -snes_monitor_field - activate this monitor

655:   Level: intermediate

657:   Notes:
658:   This routine uses the `DM` attached to the residual vector to define the fields.

660:   This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
661:   to be used during the `SNES` solve.

663: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `PetscViewerFormat`, `PetscViewerAndFormat`
664: @*/
665: PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
666: {
667:   PetscViewer viewer = vf->viewer;
668:   Vec         r;
669:   DM          dm;
670:   PetscReal   res[256];
671:   PetscInt    tablevel;

673:   PetscFunctionBegin;
675:   PetscCall(SNESGetFunction(snes, &r, NULL, NULL));
676:   PetscCall(VecGetDM(r, &dm));
677:   if (!dm) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf));
678:   else {
679:     PetscSection s, gs;
680:     PetscInt     Nf, f;

682:     PetscCall(DMGetLocalSection(dm, &s));
683:     PetscCall(DMGetGlobalSection(dm, &gs));
684:     if (!s || !gs) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf));
685:     PetscCall(PetscSectionGetNumFields(s, &Nf));
686:     PetscCheck(Nf <= 256, PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Do not support %" PetscInt_FMT " fields > 256", Nf);
687:     PetscCall(PetscSectionVecNorm(s, gs, r, NORM_2, res));
688:     PetscCall(PetscObjectGetTabLevel((PetscObject)snes, &tablevel));
689:     PetscCall(PetscViewerPushFormat(viewer, vf->format));
690:     PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
691:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e [", its, (double)fgnorm));
692:     for (f = 0; f < Nf; ++f) {
693:       if (f) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
694:       PetscCall(PetscViewerASCIIPrintf(viewer, "%14.12e", (double)res[f]));
695:     }
696:     PetscCall(PetscViewerASCIIPrintf(viewer, "] \n"));
697:     PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
698:     PetscCall(PetscViewerPopFormat(viewer));
699:   }
700:   PetscFunctionReturn(PETSC_SUCCESS);
701: }

703: /*@C
704:    SNESConvergedDefault - Default onvergence test of the solvers for
705:    systems of nonlinear equations.

707:    Collective

709:    Input Parameters:
710: +  snes - the `SNES` context
711: .  it - the iteration (0 indicates before any Newton steps)
712: .  xnorm - 2-norm of current iterate
713: .  snorm - 2-norm of current step
714: .  fnorm - 2-norm of function at current iterate
715: -  dummy - unused context

717:    Output Parameter:
718: .   reason  - one of
719: .vb
720:    SNES_CONVERGED_FNORM_ABS       - (fnorm < abstol),
721:    SNES_CONVERGED_SNORM_RELATIVE  - (snorm < stol*xnorm),
722:    SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
723:    SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
724:    SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
725:    SNES_CONVERGED_ITERATING       - (otherwise),
726:    SNES_DIVERGED_DTOL             - (fnorm > divtol*snes->fnorm0)
727: .ve

729:    where
730: +    maxf - maximum number of function evaluations,  set with `SNESSetTolerances()`
731: .    nfct - number of function evaluations,
732: .    abstol - absolute function norm tolerance, set with `SNESSetTolerances()`
733: .    rtol - relative function norm tolerance, set with `SNESSetTolerances()`
734: .    divtol - divergence tolerance, set with `SNESSetDivergenceTolerance()`
735: -    fnorm0 - 2-norm of the function at the initial solution (initial guess; zeroth iteration)

737:   Options Database Keys:
738: +  -snes_convergence_test default - see `SNESSetFromOptions()`
739: .  -snes_stol - convergence tolerance in terms of the norm  of the change in the solution between steps
740: .  -snes_atol <abstol> - absolute tolerance of residual norm
741: .  -snes_rtol <rtol> - relative decrease in tolerance norm from the initial 2-norm of the solution
742: .  -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
743: .  -snes_max_funcs <max_funcs> - maximum number of function evaluations
744: .  -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
745: -  -snes_max_linear_solve_fail - number of linear solver failures before `SNESSolve()` stops

747:    Level: intermediate

749: .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESConvergedSkip()`, `SNESSetTolerances()`, `SNESSetDivergenceTolerance()`,
750:           `SNESConvergedReason`
751: @*/
752: PetscErrorCode SNESConvergedDefault(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy)
753: {
754:   PetscFunctionBegin;

758:   *reason = SNES_CONVERGED_ITERATING;
759:   if (!it) {
760:     /* set parameter for default relative tolerance convergence test */
761:     snes->ttol   = fnorm * snes->rtol;
762:     snes->rnorm0 = fnorm;
763:   }
764:   if (PetscIsInfOrNanReal(fnorm)) {
765:     PetscCall(PetscInfo(snes, "Failed to converged, function norm is NaN\n"));
766:     *reason = SNES_DIVERGED_FNORM_NAN;
767:   } else if (fnorm < snes->abstol && (it || !snes->forceiteration)) {
768:     PetscCall(PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e\n", (double)fnorm, (double)snes->abstol));
769:     *reason = SNES_CONVERGED_FNORM_ABS;
770:   } else if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) {
771:     PetscCall(PetscInfo(snes, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", snes->nfuncs, snes->max_funcs));
772:     *reason = SNES_DIVERGED_FUNCTION_COUNT;
773:   }

775:   if (it && !*reason) {
776:     if (fnorm <= snes->ttol) {
777:       PetscCall(PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e (relative tolerance)\n", (double)fnorm, (double)snes->ttol));
778:       *reason = SNES_CONVERGED_FNORM_RELATIVE;
779:     } else if (snorm < snes->stol * xnorm) {
780:       PetscCall(PetscInfo(snes, "Converged due to small update length: %14.12e < %14.12e * %14.12e\n", (double)snorm, (double)snes->stol, (double)xnorm));
781:       *reason = SNES_CONVERGED_SNORM_RELATIVE;
782:     } else if (snes->divtol > 0 && (fnorm > snes->divtol * snes->rnorm0)) {
783:       PetscCall(PetscInfo(snes, "Diverged due to increase in function norm: %14.12e > %14.12e * %14.12e\n", (double)fnorm, (double)snes->divtol, (double)snes->rnorm0));
784:       *reason = SNES_DIVERGED_DTOL;
785:     }
786:   }
787:   PetscFunctionReturn(PETSC_SUCCESS);
788: }

790: /*@C
791:    SNESConvergedSkip - Convergence test for `SNES` that NEVER returns as
792:    converged, UNLESS the maximum number of iteration have been reached.

794:    Logically Collective

796:    Input Parameters:
797: +  snes - the `SNES` context
798: .  it - the iteration (0 indicates before any Newton steps)
799: .  xnorm - 2-norm of current iterate
800: .  snorm - 2-norm of current step
801: .  fnorm - 2-norm of function at current iterate
802: -  dummy - unused context

804:    Output Parameter:
805: .   reason  - `SNES_CONVERGED_ITERATING`, `SNES_CONVERGED_ITS`, or `SNES_DIVERGED_FNORM_NAN`

807:    Options Database Key:
808: .  -snes_convergence_test skip - see `SNESSetFromOptions()`

810:    Level: advanced

812: .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedDefault()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
813: @*/
814: PetscErrorCode SNESConvergedSkip(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy)
815: {
816:   PetscFunctionBegin;

820:   *reason = SNES_CONVERGED_ITERATING;

822:   if (fnorm != fnorm) {
823:     PetscCall(PetscInfo(snes, "Failed to converged, function norm is NaN\n"));
824:     *reason = SNES_DIVERGED_FNORM_NAN;
825:   } else if (it == snes->max_its) {
826:     *reason = SNES_CONVERGED_ITS;
827:   }
828:   PetscFunctionReturn(PETSC_SUCCESS);
829: }

831: /*@C
832:   SNESSetWorkVecs - Gets a number of work vectors to be used internally by `SNES` solvers

834:   Input Parameters:
835: + snes  - the `SNES` context
836: - nw - number of work vectors to allocate

838:   Level: developer

840: .seealso: [](ch_snes), `SNES`
841: @*/
842: PetscErrorCode SNESSetWorkVecs(SNES snes, PetscInt nw)
843: {
844:   DM  dm;
845:   Vec v;

847:   PetscFunctionBegin;
848:   if (snes->work) PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
849:   snes->nwork = nw;

851:   PetscCall(SNESGetDM(snes, &dm));
852:   PetscCall(DMGetGlobalVector(dm, &v));
853:   PetscCall(VecDuplicateVecs(v, snes->nwork, &snes->work));
854:   PetscCall(DMRestoreGlobalVector(dm, &v));
855:   PetscFunctionReturn(PETSC_SUCCESS);
856: }