Actual source code: snesut.c

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

  7: /*@C
  8:   SNESMonitorSolution - Monitors progress of a `SNES` `SNESSolve()` 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: - vf     - 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 a `SNESSolve()` 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: - vf     - 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 a `SNESSolve()` 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: - vf     - 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()`
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 a `KSPSolve()` called within a `SNESSolve()`.

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), `SNES`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `KSPMonitorTrueResidualMaxNorm()`, `KSPMonitor()`, `SNESMonitor()`, `PetscViewerAndFormat()`
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 of a `KSPSolve()` called within a `SNESSolve()`.

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;
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;
209:   PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
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 application 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, PetscCtx ctx, PetscViewerAndFormat **vf)
256: {
257:   const char *names[] = {"linear", "nonlinear"};

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

266: /*@C
267:   SNESMonitorDefaultSetUp - Prepare the `PetscViewerAndFormat` associated with `SNESMonitorDefault()`, in particular by initializing the underlying `PetscDrawLG` when the viewer format is `PETSC_VIEWER_DRAW_LG`

269:   Collective

271:   Input Parameters:
272: + snes - the `SNES` context
273: - vf   - the viewer/format pair passed to `SNESMonitorSet()` along with `SNESMonitorDefault()`

275:   Level: developer

277: .seealso: [](ch_snes), `SNES`, `SNESMonitorSet()`, `SNESMonitorDefault()`, `PetscViewerAndFormat`, `PetscViewerMonitorLGSetUp()`
278: @*/
279: PetscErrorCode SNESMonitorDefaultSetUp(SNES snes, PetscViewerAndFormat *vf)
280: {
281:   PetscFunctionBegin;
282:   if (vf->format == PETSC_VIEWER_DRAW_LG) PetscCall(PetscViewerMonitorLGSetUp(vf->viewer, NULL, NULL, "Log Residual Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300));
283:   PetscFunctionReturn(PETSC_SUCCESS);
284: }

286: /*@C
287:   SNESMonitorDefault - Monitors progress of a `SNESSolve()` (default).

289:   Collective

291:   Input Parameters:
292: + snes   - the `SNES` context
293: . its    - iteration number
294: . fgnorm - 2-norm of residual
295: - vf     - viewer and format structure

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

300:   Level: intermediate

302:   Notes:
303:   Prints the residual norm at each iteration.

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

308: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorFunction()`, `SNESMonitorResidual()`,
309:           `SNESMonitorSolutionUpdate()`, `SNESMonitorScaling()`, `SNESMonitorRange()`, `SNESMonitorRatio()`,
310:           `SNESMonitorDefaultField()`, `PetscViewerFormat`, `PetscViewerAndFormat`
311: @*/
312: PetscErrorCode SNESMonitorDefault(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
313: {
314:   PetscViewer       viewer = vf->viewer;
315:   PetscViewerFormat format = vf->format;
316:   PetscBool         isascii, isdraw;

318:   PetscFunctionBegin;
320:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
321:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
322:   PetscCall(PetscViewerPushFormat(viewer, format));
323:   if (isascii) {
324:     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
325:     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
326:       Vec              dx;
327:       PetscReal        upnorm;
328:       SNESObjectiveFn *objective;

330:       PetscCall(SNESGetSolutionUpdate(snes, &dx));
331:       PetscCall(VecNorm(dx, NORM_2, &upnorm));
332:       PetscCall(SNESGetObjective(snes, &objective, NULL));
333:       if (objective) {
334:         Vec       x;
335:         PetscReal obj;

337:         PetscCall(SNESGetSolution(snes, &x));
338:         PetscCall(SNESComputeObjective(snes, x, &obj));
339:         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));
340:       } else {
341:         PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e, Update norm %14.12e\n", its, (double)fgnorm, (double)upnorm));
342:       }
343:     } else {
344:       PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e\n", its, (double)fgnorm));
345:     }
346:     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
347:   } else if (isdraw) {
348:     if (format == PETSC_VIEWER_DRAW_LG) {
349:       PetscDrawLG lg;
350:       PetscReal   x, y;

352:       PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
353:       if (!its) PetscCall(PetscDrawLGReset(lg));
354:       x = (PetscReal)its;
355:       if (fgnorm > 0.0) y = PetscLog10Real(fgnorm);
356:       else y = -15.0;
357:       PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
358:       if (its <= 20 || !(its % 5) || snes->reason) {
359:         PetscCall(PetscDrawLGDraw(lg));
360:         PetscCall(PetscDrawLGSave(lg));
361:       }
362:     }
363:   }
364:   PetscCall(PetscViewerPopFormat(viewer));
365:   PetscFunctionReturn(PETSC_SUCCESS);
366: }

368: /*@C
369:   SNESMonitorScaling - Monitors the largest value in each row of the Jacobian of a `SNESSolve()`

371:   Collective

373:   Input Parameters:
374: + snes   - the `SNES` context
375: . its    - iteration number
376: . fgnorm - 2-norm of residual
377: - vf     - viewer and format structure

379:   Level: intermediate

381:   Notes:
382:   This routine prints the largest value in each row of the Jacobian

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

387: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `SNESMonitorJacUpdateSpectrum()`,
388:           `PetscViewerFormat`, `PetscViewerAndFormat`
389: @*/
390: PetscErrorCode SNESMonitorScaling(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
391: {
392:   PetscViewer viewer = vf->viewer;
393:   KSP         ksp;
394:   Mat         J;
395:   Vec         v;

397:   PetscFunctionBegin;
399:   PetscCall(SNESGetKSP(snes, &ksp));
400:   PetscCall(KSPGetOperators(ksp, &J, NULL));
401:   PetscCall(MatCreateVecs(J, &v, NULL));
402:   PetscCall(MatGetRowMaxAbs(J, v, NULL));
403:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
404:   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
405:   PetscCall(PetscViewerASCIIPrintf(viewer, "SNES Jacobian maximum row entries\n"));
406:   PetscCall(VecView(v, viewer));
407:   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
408:   PetscCall(PetscViewerPopFormat(viewer));
409:   PetscCall(VecDestroy(&v));
410:   PetscFunctionReturn(PETSC_SUCCESS);
411: }

413: /*@C
414:   SNESMonitorJacUpdateSpectrum - Monitors the spectrun of the change in the Jacobian from the last Jacobian evaluation of a `SNESSolve()`

416:   Collective

418:   Input Parameters:
419: + snes  - the `SNES` context
420: . it    - iteration number
421: . fnorm - 2-norm of residual
422: - vf    - viewer and format structure

424:   Options Database Key:
425: . -snes_monitor_jacupdate_spectrum - activates this monitor

427:   Level: intermediate

429:   Notes:
430:   This routine prints the eigenvalues of the difference in the Jacobians

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

435: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `PetscViewerFormat`, `PetscViewerAndFormat`
436: @*/
437: PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes, PetscInt it, PetscReal fnorm, PetscViewerAndFormat *vf)
438: {
439:   Vec X;
440:   Mat J, dJ, dJdense;
441:   PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);
442:   PetscInt     n;
443:   PetscBLASInt nb = 0, lwork;
444:   PetscReal   *eigr, *eigi;
445:   PetscScalar *work;
446:   PetscScalar *a;

448:   PetscFunctionBegin;
449:   if (it == 0) PetscFunctionReturn(PETSC_SUCCESS);
450:   /* create the difference between the current update and the current Jacobian */
451:   PetscCall(SNESGetSolution(snes, &X));
452:   PetscCall(SNESGetJacobian(snes, NULL, &J, &func, NULL));
453:   PetscCall(MatDuplicate(J, MAT_COPY_VALUES, &dJ));
454:   PetscCall(SNESComputeJacobian(snes, X, dJ, dJ));
455:   PetscCall(MatAXPY(dJ, -1.0, J, SAME_NONZERO_PATTERN));

457:   /* compute the spectrum directly */
458:   PetscCall(MatConvert(dJ, MATSEQDENSE, MAT_INITIAL_MATRIX, &dJdense));
459:   PetscCall(MatGetSize(dJ, &n, NULL));
460:   PetscCall(PetscBLASIntCast(n, &nb));
461:   lwork = 3 * nb;
462:   PetscCall(PetscMalloc1(n, &eigr));
463:   PetscCall(PetscMalloc1(n, &eigi));
464:   PetscCall(PetscMalloc1(lwork, &work));
465:   PetscCall(MatDenseGetArray(dJdense, &a));
466: #if !PetscDefined(USE_COMPLEX)
467:   {
468:     PetscInt i;
469:     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
470:     PetscCallLAPACKInfo("LAPACKgeev", LAPACKgeev_("N", "N", &nb, a, &nb, eigr, eigi, NULL, &nb, NULL, &nb, work, &lwork, &info));
471:     PetscCall(PetscFPTrapPop());
472:     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)snes), "Eigenvalues of J_%" PetscInt_FMT " - J_%" PetscInt_FMT ":\n", it, it - 1));
473:     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]));
474:   }
475:   PetscCall(MatDenseRestoreArray(dJdense, &a));
476:   PetscCall(MatDestroy(&dJ));
477:   PetscCall(MatDestroy(&dJdense));
478:   PetscCall(PetscFree(eigr));
479:   PetscCall(PetscFree(eigi));
480:   PetscCall(PetscFree(work));
481:   PetscFunctionReturn(PETSC_SUCCESS);
482: #else
483:   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded for complex");
484: #endif
485: }

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

489: PetscErrorCode SNESMonitorRange_Private(SNES snes, PetscInt it, PetscReal *per)
490: {
491:   Vec          resid;
492:   PetscReal    rmax;
493:   PetscInt     i, n, N;
494:   PetscScalar *r;

496:   PetscFunctionBegin;
497:   PetscCall(SNESGetFunction(snes, &resid, NULL, NULL));
498:   PetscCall(VecNorm(resid, NORM_INFINITY, &rmax));
499:   PetscCall(VecGetLocalSize(resid, &n));
500:   PetscCall(VecGetSize(resid, &N));
501:   PetscCall(VecGetArray(resid, &r));
502:   *per = 0.0;
503:   for (i = 0; i < n; i++) *per += (PetscAbsScalar(r[i]) > .20 * rmax);
504:   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, per, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)snes)));
505:   PetscCall(VecRestoreArray(resid, &r));
506:   *per = *per / N;
507:   PetscFunctionReturn(PETSC_SUCCESS);
508: }

510: /*@C
511:   SNESMonitorRange - Prints the percentage of residual elements that are more than 10 percent of the maximum entry in the residual in each iteration of a `SNESSolve()`

513:   Collective

515:   Input Parameters:
516: + snes  - `SNES` iterative context
517: . it    - iteration number
518: . rnorm - 2-norm (preconditioned) residual value (may be estimated).
519: - vf    - unused monitor context

521:   Options Database Key:
522: . -snes_monitor_range - Activates `SNESMonitorRange()`

524:   Level: intermediate

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

530: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorDefault()`, `SNESMonitorLGCreate()`, `SNESMonitorScaling()`, `PetscViewerFormat`, `PetscViewerAndFormat`
531: @*/
532: PetscErrorCode SNESMonitorRange(SNES snes, PetscInt it, PetscReal rnorm, PetscViewerAndFormat *vf)
533: {
534:   PetscReal   perc, rel;
535:   PetscViewer viewer = vf->viewer;
536:   /* should be in a MonitorRangeContext */
537:   static PetscReal prev;

539:   PetscFunctionBegin;
541:   if (!it) prev = rnorm;
542:   PetscCall(SNESMonitorRange_Private(snes, it, &perc));

544:   rel  = (prev - rnorm) / prev;
545:   prev = rnorm;
546:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
547:   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
548:   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 * perc), (double)rel, (double)(rel / perc)));
549:   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
550:   PetscCall(PetscViewerPopFormat(viewer));
551:   PetscFunctionReturn(PETSC_SUCCESS);
552: }

554: /*@C
555:   SNESMonitorRatio - Monitors progress of a `SNESSolve()` by printing the ratio of residual norm at each iteration to the previous.

557:   Collective

559:   Input Parameters:
560: + snes   - the `SNES` context
561: . its    - iteration number
562: . fgnorm - 2-norm of residual (or gradient)
563: - vf     - context of monitor

565:   Options Database Key:
566: . -snes_monitor_ratio - activate this monitor

568:   Level: intermediate

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

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

576: .seealso: [](ch_snes), `SNESMonitorRationSetUp()`, `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `PetscViewerFormat`, `PetscViewerAndFormat`
577: @*/
578: PetscErrorCode SNESMonitorRatio(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
579: {
580:   PetscInt    len;
581:   PetscReal  *history;
582:   PetscViewer viewer = vf->viewer;

584:   PetscFunctionBegin;
585:   PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, &len));
586:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
587:   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
588:   if (!its || !history || its > len) {
589:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e\n", its, (double)fgnorm));
590:   } else {
591:     PetscReal ratio = fgnorm / history[its - 1];
592:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e %14.12e\n", its, (double)fgnorm, (double)ratio));
593:   }
594:   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
595:   PetscCall(PetscViewerPopFormat(viewer));
596:   PetscFunctionReturn(PETSC_SUCCESS);
597: }

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

602:   Collective

604:   Input Parameters:
605: + snes - the `SNES` context
606: - vf   - `PetscViewerAndFormat` (ignored)

608:   Level: intermediate

610: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `SNESMonitorRatio()`, `PetscViewerFormat`, `PetscViewerAndFormat`
611: @*/
612: PetscErrorCode SNESMonitorRatioSetUp(SNES snes, PetscViewerAndFormat *vf)
613: {
614:   PetscReal *history;

616:   PetscFunctionBegin;
617:   PetscCall(SNESGetConvergenceHistory(snes, &history, NULL, NULL));
618:   if (!history) PetscCall(SNESSetConvergenceHistory(snes, NULL, NULL, 100, PETSC_TRUE));
619:   PetscFunctionReturn(PETSC_SUCCESS);
620: }

622: /*
623:      Default (short) SNES Monitor, same as SNESMonitorDefault() except
624:   it prints fewer digits of the residual as the residual gets smaller.
625:   This is because the later digits are meaningless and are often
626:   different on different machines; by using this routine different
627:   machines will usually generate the same output.

629:   Deprecated: Intentionally has no manual page
630: */
631: PetscErrorCode SNESMonitorDefaultShort(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
632: {
633:   PetscViewer viewer = vf->viewer;

635:   PetscFunctionBegin;
637:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
638:   PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel));
639:   if (fgnorm > 1.e-9) {
640:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %g\n", its, (double)fgnorm));
641:   } else if (fgnorm > 1.e-11) {
642:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %5.3e\n", its, (double)fgnorm));
643:   } else {
644:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm < 1.e-11\n", its));
645:   }
646:   PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel));
647:   PetscCall(PetscViewerPopFormat(viewer));
648:   PetscFunctionReturn(PETSC_SUCCESS);
649: }

651: /*@C
652:   SNESMonitorDefaultField - Monitors progress of a `SNESSolve()`, separated into fields.

654:   Collective

656:   Input Parameters:
657: + snes   - the `SNES` context
658: . its    - iteration number
659: . fgnorm - 2-norm of residual
660: - vf     - the PetscViewer

662:   Options Database Key:
663: . -snes_monitor_field - activate this monitor

665:   Level: intermediate

667:   Notes:
668:   This routine uses the `DM` attached to the residual vector to define the fields.

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

673: .seealso: [](ch_snes), `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `PetscViewerFormat`, `PetscViewerAndFormat`
674: @*/
675: PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
676: {
677:   PetscViewer viewer = vf->viewer;
678:   Vec         r;
679:   DM          dm;
680:   PetscReal   res[256];
681:   PetscInt    tablevel;

683:   PetscFunctionBegin;
685:   PetscCall(SNESGetFunction(snes, &r, NULL, NULL));
686:   PetscCall(VecGetDM(r, &dm));
687:   if (!dm) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf));
688:   else {
689:     PetscSection s, gs;
690:     PetscInt     Nf;

692:     PetscCall(DMGetLocalSection(dm, &s));
693:     PetscCall(DMGetGlobalSection(dm, &gs));
694:     if (!s || !gs) PetscCall(SNESMonitorDefault(snes, its, fgnorm, vf));
695:     PetscCall(PetscSectionGetNumFields(s, &Nf));
696:     PetscCheck(Nf <= 256, PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Do not support %" PetscInt_FMT " fields > 256", Nf);
697:     PetscCall(PetscSectionVecNorm(s, gs, r, NORM_2, res));
698:     PetscCall(PetscObjectGetTabLevel((PetscObject)snes, &tablevel));
699:     PetscCall(PetscViewerPushFormat(viewer, vf->format));
700:     PetscCall(PetscViewerASCIIAddTab(viewer, tablevel));
701:     PetscCall(PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e [", its, (double)fgnorm));
702:     for (PetscInt f = 0; f < Nf; ++f) {
703:       if (f) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
704:       PetscCall(PetscViewerASCIIPrintf(viewer, "%14.12e", (double)res[f]));
705:     }
706:     PetscCall(PetscViewerASCIIPrintf(viewer, "] \n"));
707:     PetscCall(PetscViewerASCIISubtractTab(viewer, tablevel));
708:     PetscCall(PetscViewerPopFormat(viewer));
709:   }
710:   PetscFunctionReturn(PETSC_SUCCESS);
711: }

713: /*@C
714:   SNESConvergedDefault - Default convergence test for `SNESSolve()`.

716:   Collective

718:   Input Parameters:
719: + snes  - the `SNES` context
720: . it    - the iteration (0 indicates before any Newton steps)
721: . xnorm - 2-norm of current iterate
722: . snorm - 2-norm of current step
723: . fnorm - 2-norm of function at current iterate
724: - ctx   - unused context

726:   Output Parameter:
727: . reason - converged reason, see `SNESConvergedReason`

729:   Options Database Keys:
730: + -snes_convergence_test default    - see `SNESSetFromOptions()`
731: . -snes_stol                        - convergence tolerance in terms of the norm of the change in the solution between steps
732: . -snes_atol abstol                 - absolute tolerance of residual norm
733: . -snes_rtol rtol                   - relative decrease in tolerance norm from the initial 2-norm of the solution
734: . -snes_divergence_tolerance divtol - if the residual goes above divtol*rnorm0, exit with divergence
735: . -snes_max_funcs max_funcs         - maximum number of function evaluations, use `unlimited` for no maximum
736: . -snes_max_fail max_fail           - maximum number of line search failures allowed before stopping, default is none
737: - -snes_max_linear_solve_fail       - number of linear solver failures before `SNESSolve()` stops

739:   Level: developer

741:   Notes:
742:   This routine is not generally called directly. It is set with `SNESSetConvergenceTest()` automatically before the `SNESSolve()`.

744:   It can be called within a custom convergence test that should also apply the standard convergence tests

746: .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESConvergedSkip()`, `SNESSetTolerances()`, `SNESSetDivergenceTolerance()`,
747:           `SNESConvergedReason`
748: @*/
749: PetscErrorCode SNESConvergedDefault(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, PetscCtx ctx)
750: {
751:   PetscFunctionBegin;
753:   PetscAssertPointer(reason, 6);

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

772:   if (it && !*reason) {
773:     if (fnorm <= snes->ttol) {
774:       PetscCall(PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e (relative tolerance)\n", (double)fnorm, (double)snes->ttol));
775:       *reason = SNES_CONVERGED_FNORM_RELATIVE;
776:     } else if (snorm < snes->stol * xnorm) {
777:       PetscCall(PetscInfo(snes, "Converged due to small update length: %14.12e < %14.12e * %14.12e\n", (double)snorm, (double)snes->stol, (double)xnorm));
778:       *reason = SNES_CONVERGED_SNORM_RELATIVE;
779:     } else if (snes->divtol != PETSC_UNLIMITED && (fnorm > snes->divtol * snes->rnorm0)) {
780:       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));
781:       *reason = SNES_DIVERGED_DTOL;
782:     }
783:   }
784:   PetscFunctionReturn(PETSC_SUCCESS);
785: }

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

791:   Logically Collective

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

801:   Output Parameter:
802: . reason - `SNES_CONVERGED_ITERATING`, `SNES_CONVERGED_ITS`, or `SNES_DIVERGED_FUNCTION_NANORINF`

804:   Options Database Key:
805: . -snes_convergence_test skip - see `SNESSetFromOptions()`

807:   Level: advanced

809:   Note:
810:   This is often used if `snes` is being used as a nonlinear smoother in `SNESFAS` or possibly other `SNESType`

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, PetscCtx ctx)
815: {
816:   PetscFunctionBegin;
818:   PetscAssertPointer(reason, 6);

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_FUNCTION_NANORINF;
825:   } else if (it == snes->max_its) {
826:     *reason = SNES_CONVERGED_ITS;
827:   }
828:   PetscFunctionReturn(PETSC_SUCCESS);
829: }

831: /*@
832:   SNESSetWorkVecs - Allocates a number of work vectors to be used internally by the `SNES` solver

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

838:   Level: developer

840:   Note:
841:   Each `SNESType` calls this with the number of work vectors that particular type needs.

843: .seealso: [](ch_snes), `SNES`
844: @*/
845: PetscErrorCode SNESSetWorkVecs(SNES snes, PetscInt nw)
846: {
847:   DM        dm;
848:   Vec       v;
849:   PetscBool restore = PETSC_FALSE;

851:   PetscFunctionBegin;
854:   if (snes->work) PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
855:   snes->nwork = nw;
856:   if (!nw) PetscFunctionReturn(PETSC_SUCCESS);

858:   PetscCall(SNESGetDM(snes, &dm));
859:   if (snes->dmAuto) {
860:     PetscCall(DMShellGetGlobalVector(dm, &v));
861:     if (!v) v = snes->vec_sol;
862:     if (!v) v = snes->vec_func;
863:     if (!v) v = snes->vec_rhs;
864:   } else {
865:     restore = PETSC_TRUE;
866:     PetscCall(DMGetGlobalVector(dm, &v));
867:   }
868:   PetscCheck(v, PetscObjectComm((PetscObject)snes), PETSC_ERR_SUP, "Vector to be duplicated not found");
869:   PetscCall(VecDuplicateVecs(v, snes->nwork, &snes->work));
870:   if (restore) PetscCall(DMRestoreGlobalVector(dm, &v));
871:   PetscFunctionReturn(PETSC_SUCCESS);
872: }