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:    Note:
 23:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
 24:    to be used during the `SNESSolve()`

 26:    Level: intermediate

 28: .seealso: `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;

 36:   SNESGetSolution(snes, &x);
 37:   PetscViewerPushFormat(viewer, vf->format);
 38:   VecView(x, viewer);
 39:   PetscViewerPopFormat(viewer);
 40:   return 0;
 41: }

 43: /*@C
 44:    SNESMonitorResidual - Monitors progress of the `SNES` solvers 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: -  dummy -  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:    Note:
 59:    This is not called directly by users, rather one calls `SNESMonitorSet()`, with this function as an argument, to cause the monitor
 60:    to be used during the SNES solve.

 62:    Level: intermediate

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

 71:   SNESGetFunction(snes, &x, NULL, NULL);
 72:   PetscViewerPushFormat(vf->viewer, vf->format);
 73:   VecView(x, vf->viewer);
 74:   PetscViewerPopFormat(vf->viewer);
 75:   return 0;
 76: }

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

 82:    Collective

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

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

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

 97:    Level: intermediate

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

107:   SNESGetSolutionUpdate(snes, &x);
108:   PetscViewerPushFormat(viewer, vf->format);
109:   VecView(x, viewer);
110:   PetscViewerPopFormat(viewer);
111:   return 0;
112: }

114: #include <petscdraw.h>

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

119:   Collective

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

127:   Options Database Key:
128: . -snes_monitor_ksp - Activates `KSPMonitorSNESResidual()`

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

134:   Level: intermediate

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

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

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

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

173:   Collective

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

181:   Options Database Key:
182: . -snes_monitor_ksp draw::draw_lg - Activates `KSPMonitorSNESResidualDrawLG()`

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

188:   Level: intermediate

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

205:   SNESGetSolution(snes, &snes_solution);
206:   VecDuplicate(snes_solution, &work1);
207:   VecDuplicate(snes_solution, &work2);
208:   KSPBuildSolution(ksp, work1, NULL);
209:   VecAYPX(work1, -1.0, snes_solution);
210:   SNESComputeFunction(snes, work1, work2);
211:   VecNorm(work2, NORM_2, &snorm);
212:   VecDestroy(&work1);
213:   VecDestroy(&work2);

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

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

236:   Collective

238:   Input Parameters:
239: + viewer - The PetscViewer
240: . format - The viewer format
241: - ctx    - An optional user context

243:   Output Parameter:
244: . vf    - The viewer context

246:   Level: intermediate

248: .seealso: `KSP`, `SNES`, `KSPMonitorSet()`, `KSPMonitorTrueResidual()`
249: @*/
250: PetscErrorCode KSPMonitorSNESResidualDrawLGCreate(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
251: {
252:   const char *names[] = {"linear", "nonlinear"};

254:   PetscViewerAndFormatCreate(viewer, format, vf);
255:   (*vf)->data = ctx;
256:   KSPMonitorLGCreate(PetscObjectComm((PetscObject)viewer), NULL, NULL, "Log Residual Norm", 2, names, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &(*vf)->lg);
257:   return 0;
258: }

260: PetscErrorCode SNESMonitorDefaultSetUp(SNES snes, PetscViewerAndFormat *vf)
261: {
262:   if (vf->format == PETSC_VIEWER_DRAW_LG) KSPMonitorLGCreate(PetscObjectComm((PetscObject)vf->viewer), NULL, NULL, "Log Residual Norm", 1, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &vf->lg);
263:   return 0;
264: }

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

269:    Collective

271:    Input Parameters:
272: +  snes - the `SNES` context
273: .  its - iteration number
274: .  fgnorm - 2-norm of residual
275: -  vf - viewer and format structure

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

280:    Notes:
281:    This routine prints the residual norm at each iteration.

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

286:    Level: intermediate

288: .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorFunction()`, `SNESMonitorSolution()`, `SNESMonitorResidual()`,
289:           `SNESMonitorSolutionUpdate()`, `SNESMonitorDefault()`, `SNESMonitorScaling()`, `SNESMonitorRange()`, `SNESMonitorRatio()`,
290:           `SNESMonitorDefaultField()`
291: @*/
292: PetscErrorCode SNESMonitorDefault(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
293: {
294:   PetscViewer       viewer = vf->viewer;
295:   PetscViewerFormat format = vf->format;
296:   PetscBool         isascii, isdraw;

299:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii);
300:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw);
301:   PetscViewerPushFormat(viewer, format);
302:   if (isascii) {
303:     PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel);
304:     PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e \n", its, (double)fgnorm);
305:     PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel);
306:   } else if (isdraw) {
307:     if (format == PETSC_VIEWER_DRAW_LG) {
308:       PetscDrawLG lg = (PetscDrawLG)vf->lg;
309:       PetscReal   x, y;

312:       if (!its) PetscDrawLGReset(lg);
313:       x = (PetscReal)its;
314:       if (fgnorm > 0.0) y = PetscLog10Real(fgnorm);
315:       else y = -15.0;
316:       PetscDrawLGAddPoint(lg, &x, &y);
317:       if (its <= 20 || !(its % 5) || snes->reason) {
318:         PetscDrawLGDraw(lg);
319:         PetscDrawLGSave(lg);
320:       }
321:     }
322:   }
323:   PetscViewerPopFormat(viewer);
324:   return 0;
325: }

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

330:    Collective

332:    Input Parameters:
333: +  snes - the `SNES` context
334: .  its - iteration number
335: .  fgnorm - 2-norm of residual
336: -  vf - viewer and format structure

338:    Notes:
339:    This routine prints the largest value in each row of the Jacobian

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

344:    Level: intermediate

346: .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`, `SNESMonitorJacUpdateSpectrum()`
347: @*/
348: PetscErrorCode SNESMonitorScaling(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
349: {
350:   PetscViewer viewer = vf->viewer;
351:   KSP         ksp;
352:   Mat         J;
353:   Vec         v;

356:   SNESGetKSP(snes, &ksp);
357:   KSPGetOperators(ksp, &J, NULL);
358:   MatCreateVecs(J, &v, NULL);
359:   MatGetRowMaxAbs(J, v, NULL);
360:   PetscViewerPushFormat(viewer, vf->format);
361:   PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel);
362:   PetscViewerASCIIPrintf(viewer, "SNES Jacobian maximum row entries\n");
363:   VecView(v, viewer);
364:   PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel);
365:   PetscViewerPopFormat(viewer);
366:   VecDestroy(&v);
367:   return 0;
368: }

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

373:    Collective

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

381:    Option Database Key:
382: .  -snes_monitor_jacupdate_spectrum - activates this monitor

384:    Notes:
385:    This routine prints the eigenvalues of the difference in the Jacobians

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

390:    Level: intermediate

392: .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorRange()`
393: @*/
394: PetscErrorCode SNESMonitorJacUpdateSpectrum(SNES snes, PetscInt it, PetscReal fnorm, PetscViewerAndFormat *vf)
395: {
396:   Vec X;
397:   Mat J, dJ, dJdense;
398:   PetscErrorCode (*func)(SNES, Vec, Mat, Mat, void *);
399:   PetscInt     n;
400:   PetscBLASInt nb = 0, lwork;
401:   PetscReal   *eigr, *eigi;
402:   PetscScalar *work;
403:   PetscScalar *a;

405:   if (it == 0) return 0;
406:   /* create the difference between the current update and the current Jacobian */
407:   SNESGetSolution(snes, &X);
408:   SNESGetJacobian(snes, NULL, &J, &func, NULL);
409:   MatDuplicate(J, MAT_COPY_VALUES, &dJ);
410:   SNESComputeJacobian(snes, X, dJ, dJ);
411:   MatAXPY(dJ, -1.0, J, SAME_NONZERO_PATTERN);

413:   /* compute the spectrum directly */
414:   MatConvert(dJ, MATSEQDENSE, MAT_INITIAL_MATRIX, &dJdense);
415:   MatGetSize(dJ, &n, NULL);
416:   PetscBLASIntCast(n, &nb);
417:   lwork = 3 * nb;
418:   PetscMalloc1(n, &eigr);
419:   PetscMalloc1(n, &eigi);
420:   PetscMalloc1(lwork, &work);
421:   MatDenseGetArray(dJdense, &a);
422: #if !defined(PETSC_USE_COMPLEX)
423:   {
424:     PetscBLASInt lierr;
425:     PetscInt     i;
426:     PetscFPTrapPush(PETSC_FP_TRAP_OFF);
427:     PetscCallBLAS("LAPACKgeev", LAPACKgeev_("N", "N", &nb, a, &nb, eigr, eigi, NULL, &nb, NULL, &nb, work, &lwork, &lierr));
429:     PetscFPTrapPop();
430:     PetscPrintf(PetscObjectComm((PetscObject)snes), "Eigenvalues of J_%" PetscInt_FMT " - J_%" PetscInt_FMT ":\n", it, it - 1);
431:     for (i = 0; i < n; i++) PetscPrintf(PetscObjectComm((PetscObject)snes), "%5" PetscInt_FMT ": %20.5g + %20.5gi\n", i, (double)eigr[i], (double)eigi[i]);
432:   }
433:   MatDenseRestoreArray(dJdense, &a);
434:   MatDestroy(&dJ);
435:   MatDestroy(&dJdense);
436:   PetscFree(eigr);
437:   PetscFree(eigi);
438:   PetscFree(work);
439:   return 0;
440: #else
441:   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Not coded for complex");
442: #endif
443: }

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

447: PetscErrorCode SNESMonitorRange_Private(SNES snes, PetscInt it, PetscReal *per)
448: {
449:   Vec          resid;
450:   PetscReal    rmax, pwork;
451:   PetscInt     i, n, N;
452:   PetscScalar *r;

454:   SNESGetFunction(snes, &resid, NULL, NULL);
455:   VecNorm(resid, NORM_INFINITY, &rmax);
456:   VecGetLocalSize(resid, &n);
457:   VecGetSize(resid, &N);
458:   VecGetArray(resid, &r);
459:   pwork = 0.0;
460:   for (i = 0; i < n; i++) pwork += (PetscAbsScalar(r[i]) > .20 * rmax);
461:   MPIU_Allreduce(&pwork, per, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)snes));
462:   VecRestoreArray(resid, &r);
463:   *per = *per / N;
464:   return 0;
465: }

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

470:    Collective

472:    Input Parameters:
473: +  snes   - iterative context
474: .  it    - iteration number
475: .  rnorm - 2-norm (preconditioned) residual value (may be estimated).
476: -  dummy - unused monitor context

478:    Options Database Key:
479: .  -snes_monitor_range - Activates `SNESMonitorRange()`

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

485:    Level: intermediate

487: .seealso: `SNESMonitorSet()`, `SNESMonitorDefault()`, `SNESMonitorLGCreate()`, `SNESMonitorScaling()`
488: @*/
489: PetscErrorCode SNESMonitorRange(SNES snes, PetscInt it, PetscReal rnorm, PetscViewerAndFormat *vf)
490: {
491:   PetscReal   perc, rel;
492:   PetscViewer viewer = vf->viewer;
493:   /* should be in a MonitorRangeContext */
494:   static PetscReal prev;

497:   if (!it) prev = rnorm;
498:   SNESMonitorRange_Private(snes, it, &perc);

500:   rel  = (prev - rnorm) / prev;
501:   prev = rnorm;
502:   PetscViewerPushFormat(viewer, vf->format);
503:   PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel);
504:   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));
505:   PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel);
506:   PetscViewerPopFormat(viewer);
507:   return 0;
508: }

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

514:    Collective

516:    Input Parameters:
517: +  snes - the `SNES` context
518: .  its - iteration number
519: .  fgnorm - 2-norm of residual (or gradient)
520: -  dummy -  context of monitor

522:    Option Database Key:
523: .  -snes_monitor_ratio - activate this monitor

525:    Level: intermediate

527:    Notes:
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:    Be sure to call `SNESMonitorRationSetUp()` before using this monitor.

533: .seealso: `SNESMonitorRationSetUp()`, `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`
534: @*/
535: PetscErrorCode SNESMonitorRatio(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
536: {
537:   PetscInt    len;
538:   PetscReal  *history;
539:   PetscViewer viewer = vf->viewer;

541:   SNESGetConvergenceHistory(snes, &history, NULL, &len);
542:   PetscViewerPushFormat(viewer, vf->format);
543:   PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel);
544:   if (!its || !history || its > len) {
545:     PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e \n", its, (double)fgnorm);
546:   } else {
547:     PetscReal ratio = fgnorm / history[its - 1];
548:     PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e %14.12e \n", its, (double)fgnorm, (double)ratio);
549:   }
550:   PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel);
551:   PetscViewerPopFormat(viewer);
552:   return 0;
553: }

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

558:    Collective

560:    Input Parameters:
561: +   snes - the `SNES` context
562: -   viewer - the `PetscViewer` object (ignored)

564:    Level: intermediate

566: .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`, `SNESMonitorRatio()`
567: @*/
568: PetscErrorCode SNESMonitorRatioSetUp(SNES snes, PetscViewerAndFormat *vf)
569: {
570:   PetscReal *history;

572:   SNESGetConvergenceHistory(snes, &history, NULL, NULL);
573:   if (!history) SNESSetConvergenceHistory(snes, NULL, NULL, 100, PETSC_TRUE);
574:   return 0;
575: }

577: /*
578:      Default (short) SNES Monitor, same as SNESMonitorDefault() except
579:   it prints fewer digits of the residual as the residual gets smaller.
580:   This is because the later digits are meaningless and are often
581:   different on different machines; by using this routine different
582:   machines will usually generate the same output.

584:   Deprecated: Intentionally has no manual page
585: */
586: PetscErrorCode SNESMonitorDefaultShort(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
587: {
588:   PetscViewer viewer = vf->viewer;

591:   PetscViewerPushFormat(viewer, vf->format);
592:   PetscViewerASCIIAddTab(viewer, ((PetscObject)snes)->tablevel);
593:   if (fgnorm > 1.e-9) {
594:     PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %g \n", its, (double)fgnorm);
595:   } else if (fgnorm > 1.e-11) {
596:     PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %5.3e \n", its, (double)fgnorm);
597:   } else {
598:     PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm < 1.e-11\n", its);
599:   }
600:   PetscViewerASCIISubtractTab(viewer, ((PetscObject)snes)->tablevel);
601:   PetscViewerPopFormat(viewer);
602:   return 0;
603: }

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

608:   Collective

610:   Input Parameters:
611: + snes   - the `SNES` context
612: . its    - iteration number
613: . fgnorm - 2-norm of residual
614: - ctx    - the PetscViewer

616:    Option Database Key:
617: .  -snes_monitor_field - activate this monitor

619:   Notes:
620:   This routine uses the `DM` attached to the residual vector to define the fields.

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

625:   Level: intermediate

627: .seealso: `SNESMonitorSet()`, `SNESMonitorSolution()`, `SNESMonitorDefault()`
628: @*/
629: PetscErrorCode SNESMonitorDefaultField(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf)
630: {
631:   PetscViewer viewer = vf->viewer;
632:   Vec         r;
633:   DM          dm;
634:   PetscReal   res[256];
635:   PetscInt    tablevel;

638:   SNESGetFunction(snes, &r, NULL, NULL);
639:   VecGetDM(r, &dm);
640:   if (!dm) SNESMonitorDefault(snes, its, fgnorm, vf);
641:   else {
642:     PetscSection s, gs;
643:     PetscInt     Nf, f;

645:     DMGetLocalSection(dm, &s);
646:     DMGetGlobalSection(dm, &gs);
647:     if (!s || !gs) SNESMonitorDefault(snes, its, fgnorm, vf);
648:     PetscSectionGetNumFields(s, &Nf);
650:     PetscSectionVecNorm(s, gs, r, NORM_2, res);
651:     PetscObjectGetTabLevel((PetscObject)snes, &tablevel);
652:     PetscViewerPushFormat(viewer, vf->format);
653:     PetscViewerASCIIAddTab(viewer, tablevel);
654:     PetscViewerASCIIPrintf(viewer, "%3" PetscInt_FMT " SNES Function norm %14.12e [", its, (double)fgnorm);
655:     for (f = 0; f < Nf; ++f) {
656:       if (f) PetscViewerASCIIPrintf(viewer, ", ");
657:       PetscViewerASCIIPrintf(viewer, "%14.12e", (double)res[f]);
658:     }
659:     PetscViewerASCIIPrintf(viewer, "] \n");
660:     PetscViewerASCIISubtractTab(viewer, tablevel);
661:     PetscViewerPopFormat(viewer);
662:   }
663:   return 0;
664: }

666: /*@C
667:    SNESConvergedDefault - Default onvergence test of the solvers for
668:    systems of nonlinear equations.

670:    Collective

672:    Input Parameters:
673: +  snes - the `SNES` context
674: .  it - the iteration (0 indicates before any Newton steps)
675: .  xnorm - 2-norm of current iterate
676: .  snorm - 2-norm of current step
677: .  fnorm - 2-norm of function at current iterate
678: -  dummy - unused context

680:    Output Parameter:
681: .   reason  - one of
682: .vb
683:    SNES_CONVERGED_FNORM_ABS       - (fnorm < abstol),
684:    SNES_CONVERGED_SNORM_RELATIVE  - (snorm < stol*xnorm),
685:    SNES_CONVERGED_FNORM_RELATIVE  - (fnorm < rtol*fnorm0),
686:    SNES_DIVERGED_FUNCTION_COUNT   - (nfct > maxf),
687:    SNES_DIVERGED_FNORM_NAN        - (fnorm == NaN),
688:    SNES_CONVERGED_ITERATING       - (otherwise),
689:    SNES_DIVERGED_DTOL             - (fnorm > divtol*snes->fnorm0)
690: .ve

692:    where
693: +    maxf - maximum number of function evaluations,  set with `SNESSetTolerances()`
694: .    nfct - number of function evaluations,
695: .    abstol - absolute function norm tolerance, set with `SNESSetTolerances()`
696: .    rtol - relative function norm tolerance, set with `SNESSetTolerances()`
697: .    divtol - divergence tolerance, set with `SNESSetDivergenceTolerance()`
698: -    fnorm0 - 2-norm of the function at the initial solution (initial guess; zeroth iteration)

700:   Options Database Keys:
701: +  -snes_convergence_test default - see `SNESSetFromOptions()`
702: .  -snes_stol - convergence tolerance in terms of the norm  of the change in the solution between steps
703: .  -snes_atol <abstol> - absolute tolerance of residual norm
704: .  -snes_rtol <rtol> - relative decrease in tolerance norm from the initial 2-norm of the solution
705: .  -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence
706: .  -snes_max_funcs <max_funcs> - maximum number of function evaluations
707: .  -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none
708: -  -snes_max_linear_solve_fail - number of linear solver failures before `SNESSolve()` stops

710:    Level: intermediate

712: .seealso: `SNES`, `SNESSolve()`, `SNESSetConvergenceTest()`, `SNESConvergedSkip()`, `SNESSetTolerances()`, `SNESSetDivergenceTolerance()`
713: @*/
714: PetscErrorCode SNESConvergedDefault(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy)
715: {

719:   *reason = SNES_CONVERGED_ITERATING;
720:   if (!it) {
721:     /* set parameter for default relative tolerance convergence test */
722:     snes->ttol   = fnorm * snes->rtol;
723:     snes->rnorm0 = fnorm;
724:   }
725:   if (PetscIsInfOrNanReal(fnorm)) {
726:     PetscInfo(snes, "Failed to converged, function norm is NaN\n");
727:     *reason = SNES_DIVERGED_FNORM_NAN;
728:   } else if (fnorm < snes->abstol && (it || !snes->forceiteration)) {
729:     PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e\n", (double)fnorm, (double)snes->abstol);
730:     *reason = SNES_CONVERGED_FNORM_ABS;
731:   } else if (snes->nfuncs >= snes->max_funcs && snes->max_funcs >= 0) {
732:     PetscInfo(snes, "Exceeded maximum number of function evaluations: %" PetscInt_FMT " > %" PetscInt_FMT "\n", snes->nfuncs, snes->max_funcs);
733:     *reason = SNES_DIVERGED_FUNCTION_COUNT;
734:   }

736:   if (it && !*reason) {
737:     if (fnorm <= snes->ttol) {
738:       PetscInfo(snes, "Converged due to function norm %14.12e < %14.12e (relative tolerance)\n", (double)fnorm, (double)snes->ttol);
739:       *reason = SNES_CONVERGED_FNORM_RELATIVE;
740:     } else if (snorm < snes->stol * xnorm) {
741:       PetscInfo(snes, "Converged due to small update length: %14.12e < %14.12e * %14.12e\n", (double)snorm, (double)snes->stol, (double)xnorm);
742:       *reason = SNES_CONVERGED_SNORM_RELATIVE;
743:     } else if (snes->divtol > 0 && (fnorm > snes->divtol * snes->rnorm0)) {
744:       PetscInfo(snes, "Diverged due to increase in function norm: %14.12e > %14.12e * %14.12e\n", (double)fnorm, (double)snes->divtol, (double)snes->rnorm0);
745:       *reason = SNES_DIVERGED_DTOL;
746:     }
747:   }
748:   return 0;
749: }

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

755:    Logically Collective

757:    Input Parameters:
758: +  snes - the `SNES` context
759: .  it - the iteration (0 indicates before any Newton steps)
760: .  xnorm - 2-norm of current iterate
761: .  snorm - 2-norm of current step
762: .  fnorm - 2-norm of function at current iterate
763: -  dummy - unused context

765:    Output Parameter:
766: .   reason  - `SNES_CONVERGED_ITERATING`, `SNES_CONVERGED_ITS`, or `SNES_DIVERGED_FNORM_NAN`

768:    Options Database Key:
769: .  -snes_convergence_test skip - see `SNESSetFromOptions()`

771:    Level: advanced

773: .seealso: `SNES`, `SNESSolve()`, `SNESConvergedDefault()`, `SNESSetConvergenceTest()`
774: @*/
775: PetscErrorCode SNESConvergedSkip(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, void *dummy)
776: {

780:   *reason = SNES_CONVERGED_ITERATING;

782:   if (fnorm != fnorm) {
783:     PetscInfo(snes, "Failed to converged, function norm is NaN\n");
784:     *reason = SNES_DIVERGED_FNORM_NAN;
785:   } else if (it == snes->max_its) {
786:     *reason = SNES_CONVERGED_ITS;
787:   }
788:   return 0;
789: }

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

794:   Input Parameters:
795: + snes  - the `SNES` context
796: - nw - number of work vectors to allocate

798:   Level: developer

800: @*/
801: PetscErrorCode SNESSetWorkVecs(SNES snes, PetscInt nw)
802: {
803:   DM  dm;
804:   Vec v;

806:   if (snes->work) VecDestroyVecs(snes->nwork, &snes->work);
807:   snes->nwork = nw;

809:   SNESGetDM(snes, &dm);
810:   DMGetGlobalVector(dm, &v);
811:   VecDuplicateVecs(v, snes->nwork, &snes->work);
812:   DMRestoreGlobalVector(dm, &v);
813:   return 0;
814: }