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: }