Actual source code: snesut.c

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

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

 10:   Collective

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

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

 21:   Level: intermediate

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

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

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

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

 47:   Collective

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

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

 58:   Level: intermediate

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

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

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

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

 83:   Collective

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

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

 94:   Level: intermediate

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

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

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

116: #include <petscdraw.h>

118: /*@C
119:   KSPMonitorSNESResidual - Prints the `SNES` residual norm, as well as the `KSP` residual norm, at each iteration of a `KSPSolve()` called within a `SNESSolve()`.

121:   Collective

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

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

132:   Level: intermediate

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

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

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

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

173: /*@C
174:   KSPMonitorSNESResidualDrawLG - Plots the linear `KSP` residual norm and the `SNES` residual norm of a `KSPSolve()` called within a `SNESSolve()`.

176:   Collective

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

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

187:   Level: intermediate

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

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

206:   PetscFunctionBegin;
208:   PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
209:   PetscCall(SNESGetSolution(snes, &snes_solution));
210:   PetscCall(VecDuplicate(snes_solution, &work1));
211:   PetscCall(VecDuplicate(snes_solution, &work2));
212:   PetscCall(KSPBuildSolution(ksp, work1, NULL));
213:   PetscCall(VecAYPX(work1, -1.0, snes_solution));
214:   PetscCall(SNESComputeFunction(snes, work1, work2));
215:   PetscCall(VecNorm(work2, NORM_2, &snorm));
216:   PetscCall(VecDestroy(&work1));
217:   PetscCall(VecDestroy(&work2));

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

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

240:   Collective

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

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

250:   Level: intermediate

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

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

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

268:   Collective

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

274:   Level: developer

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

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

288:   Collective

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

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

299:   Level: intermediate

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

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

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

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

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

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

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

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

370:   Collective

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

378:   Level: intermediate

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

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

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

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

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

415:   Collective

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

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

426:   Level: intermediate

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

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

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

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

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

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

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

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

511: /*@C
512:   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()`

514:   Collective

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

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

525:   Level: intermediate

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

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

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

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

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

558:   Collective

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

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

569:   Level: intermediate

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

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

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

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

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

603:   Collective

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

609:   Level: intermediate

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

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

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

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

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

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

655:   Collective

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

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

666:   Level: intermediate

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

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

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

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

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

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

717:   Collective

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

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

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

740:   Level: developer

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

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

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

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

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

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

792:   Logically Collective

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

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

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

808:   Level: advanced

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

813: .seealso: [](ch_snes), `SNES`, `SNESSolve()`, `SNESConvergedDefault()`, `SNESSetConvergenceTest()`, `SNESConvergedReason`
814: @*/
815: PetscErrorCode SNESConvergedSkip(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, PetscCtx ctx)
816: {
817:   PetscFunctionBegin;
819:   PetscAssertPointer(reason, 6);

821:   *reason = SNES_CONVERGED_ITERATING;

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

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

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

839:   Level: developer

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

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

851:   PetscFunctionBegin;
852:   if (snes->work) PetscCall(VecDestroyVecs(snes->nwork, &snes->work));
853:   snes->nwork = nw;

855:   PetscCall(SNESGetDM(snes, &dm));
856:   PetscCall(DMGetGlobalVector(dm, &v));
857:   PetscCall(VecDuplicateVecs(v, snes->nwork, &snes->work));
858:   PetscCall(DMRestoreGlobalVector(dm, &v));
859:   PetscFunctionReturn(PETSC_SUCCESS);
860: }