Actual source code: xmon.c

  1: #include <petsc/private/kspimpl.h>
  2: #include <petscdraw.h>

  4: /*@C
  5:   KSPMonitorLGRange - Prints line graphs summarizing the residual norm, the fraction of elements that dominate the residual, and the convergence factor at each iteration of the `KSP` solver

  7:   Collective

  9:   Input Parameters:
 10: + ksp    - iterative context
 11: . n      - iteration number
 12: . rnorm  - the 2-norm of the residual (or an approximation)
 13: - monctx - a `PetscViewer` (typically of type `PETSCVIEWERDRAW`) containing the line graphs to update

 15:   Level: intermediate

 17:   Note:
 18:   Suitable for use as a `KSP` monitor via `KSPMonitorSet()`. Draws four line graphs: the log residual norm, the
 19:   percentage of entries whose magnitude exceeds $0.2$ times the maximum, the relative change in residual norm per
 20:   iteration, and their product.

 22: .seealso: [](ch_ksp), `KSP`, `KSPMonitorSet()`, `KSPMonitorResidual()`, `PETSCVIEWERDRAW`, `PetscDrawLG`
 23: @*/
 24: PetscErrorCode KSPMonitorLGRange(KSP ksp, PetscInt n, PetscReal rnorm, void *monctx)
 25: {
 26:   PetscDrawLG      lg;
 27:   PetscReal        x, y, per;
 28:   PetscViewer      v = (PetscViewer)monctx;
 29:   static PetscReal prev; /* should be in the context */
 30:   PetscDraw        draw;

 32:   PetscFunctionBegin;

 35:   PetscCall(KSPMonitorRange_Private(ksp, n, &per));
 36:   if (!n) prev = rnorm;

 38:   PetscCall(PetscViewerDrawGetDrawLG(v, 0, &lg));
 39:   if (!n) PetscCall(PetscDrawLGReset(lg));
 40:   PetscCall(PetscDrawLGGetDraw(lg, &draw));
 41:   PetscCall(PetscDrawSetTitle(draw, "Residual norm"));
 42:   x = (PetscReal)n;
 43:   if (rnorm > 0.0) y = PetscLog10Real(rnorm);
 44:   else y = -15.0;
 45:   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
 46:   if (n < 20 || !(n % 5) || ksp->reason) {
 47:     PetscCall(PetscDrawLGDraw(lg));
 48:     PetscCall(PetscDrawLGSave(lg));
 49:   }

 51:   PetscCall(PetscViewerDrawGetDrawLG(v, 1, &lg));
 52:   if (!n) PetscCall(PetscDrawLGReset(lg));
 53:   PetscCall(PetscDrawLGGetDraw(lg, &draw));
 54:   PetscCall(PetscDrawSetTitle(draw, "% elements > .2*max element"));
 55:   x = (PetscReal)n;
 56:   y = 100.0 * per;
 57:   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
 58:   if (n < 20 || !(n % 5) || ksp->reason) {
 59:     PetscCall(PetscDrawLGDraw(lg));
 60:     PetscCall(PetscDrawLGSave(lg));
 61:   }

 63:   PetscCall(PetscViewerDrawGetDrawLG(v, 2, &lg));
 64:   if (!n) PetscCall(PetscDrawLGReset(lg));
 65:   PetscCall(PetscDrawLGGetDraw(lg, &draw));
 66:   PetscCall(PetscDrawSetTitle(draw, "(norm - oldnorm)/oldnorm"));
 67:   x = (PetscReal)n;
 68:   y = (prev - rnorm) / prev;
 69:   PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
 70:   if (n < 20 || !(n % 5) || ksp->reason) {
 71:     PetscCall(PetscDrawLGDraw(lg));
 72:     PetscCall(PetscDrawLGSave(lg));
 73:   }

 75:   PetscCall(PetscViewerDrawGetDrawLG(v, 3, &lg));
 76:   if (!n) PetscCall(PetscDrawLGReset(lg));
 77:   PetscCall(PetscDrawLGGetDraw(lg, &draw));
 78:   PetscCall(PetscDrawSetTitle(draw, "(norm - oldnorm)/oldnorm*(% > .2 max)"));
 79:   x = (PetscReal)n;
 80:   y = (prev - rnorm) / (prev * per);
 81:   if (n > 5) PetscCall(PetscDrawLGAddPoint(lg, &x, &y));
 82:   if (n < 20 || !(n % 5) || ksp->reason) {
 83:     PetscCall(PetscDrawLGDraw(lg));
 84:     PetscCall(PetscDrawLGSave(lg));
 85:   }
 86:   prev = rnorm;
 87:   PetscFunctionReturn(PETSC_SUCCESS);
 88: }