Actual source code: tsmon.c

  1: #include <petsc/private/tsimpl.h>
  2: #include <petscdm.h>
  3: #include <petscds.h>
  4: #include <petscdmswarm.h>
  5: #include <petscdraw.h>

  7: /*@C
  8:   TSMonitor - Runs all user-provided monitor routines set using `TSMonitorSet()`

 10:   Collective

 12:   Input Parameters:
 13: + ts    - time stepping context obtained from `TSCreate()`
 14: . step  - step number that has just completed
 15: . ptime - model time of the state
 16: - u     - state at the current model time

 18:   Level: developer

 20:   Notes:
 21:   `TSMonitor()` is typically used automatically within the time stepping implementations.
 22:   Users would almost never call this routine directly.

 24:   A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions

 26: .seealso: `TS`, `TSMonitorSet()`, `TSMonitorSetFromOptions()`
 27: @*/
 28: PetscErrorCode TSMonitor(TS ts, PetscInt step, PetscReal ptime, Vec u)
 29: {
 30:   DM       dm;
 31:   PetscInt i, n = ts->numbermonitors;

 33:   PetscFunctionBegin;

 37:   PetscCall(TSGetDM(ts, &dm));
 38:   PetscCall(DMSetOutputSequenceNumber(dm, step, ptime));

 40:   PetscCall(VecLockReadPush(u));
 41:   for (i = 0; i < n; i++) PetscCall((*ts->monitor[i])(ts, step, ptime, u, ts->monitorcontext[i]));
 42:   PetscCall(VecLockReadPop(u));
 43:   PetscFunctionReturn(PETSC_SUCCESS);
 44: }

 46: /*@C
 47:   TSMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user

 49:   Collective

 51:   Input Parameters:
 52: + ts           - `TS` object you wish to monitor
 53: . name         - the monitor type one is seeking
 54: . help         - message indicating what monitoring is done
 55: . manual       - manual page for the monitor
 56: . monitor      - the monitor function
 57: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `TS` or `PetscViewer` objects

 59:   Level: developer

 61: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
 62:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
 63:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
 64:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
 65:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
 66:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
 67:           `PetscOptionsFList()`, `PetscOptionsEList()`
 68: @*/
 69: PetscErrorCode TSMonitorSetFromOptions(TS ts, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(TS, PetscInt, PetscReal, Vec, PetscViewerAndFormat *), PetscErrorCode (*monitorsetup)(TS, PetscViewerAndFormat *))
 70: {
 71:   PetscViewer       viewer;
 72:   PetscViewerFormat format;
 73:   PetscBool         flg;

 75:   PetscFunctionBegin;
 76:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, name, &viewer, &format, &flg));
 77:   if (flg) {
 78:     PetscViewerAndFormat *vf;
 79:     char                  interval_key[1024];

 81:     PetscCall(PetscSNPrintf(interval_key, sizeof interval_key, "%s_interval", name));
 82:     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
 83:     vf->view_interval = 1;
 84:     PetscCall(PetscOptionsGetInt(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, interval_key, &vf->view_interval, NULL));
 85:     PetscCall(PetscViewerDestroy(&viewer));
 86:     if (monitorsetup) PetscCall((*monitorsetup)(ts, vf));
 87:     PetscCall(TSMonitorSet(ts, (PetscErrorCode (*)(TS, PetscInt, PetscReal, Vec, void *))monitor, vf, (PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy));
 88:   }
 89:   PetscFunctionReturn(PETSC_SUCCESS);
 90: }

 92: /*@C
 93:   TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
 94:   timestep to display the iteration's  progress.

 96:   Logically Collective

 98:   Input Parameters:
 99: + ts       - the `TS` context obtained from `TSCreate()`
100: . monitor  - monitoring routine
101: . mctx     - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
102: - mdestroy - [optional] routine that frees monitor context (may be `NULL`)

104:   Calling sequence of `monitor`:
105: + ts    - the `TS` context
106: . steps - iteration number (after the final time step the monitor routine may be called with a step of -1, this indicates the solution has been interpolated to this time)
107: . time  - current time
108: . u     - current iterate
109: - ctx   - [optional] monitoring context

111:   Level: intermediate

113:   Note:
114:   This routine adds an additional monitor to the list of monitors that already has been loaded.

116:   Fortran Notes:
117:   Only a single monitor function can be set for each `TS` object

119: .seealso: [](ch_ts), `TSMonitorDefault()`, `TSMonitorCancel()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
120:           `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
121:           `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`
122: @*/
123: PetscErrorCode TSMonitorSet(TS ts, PetscErrorCode (*monitor)(TS ts, PetscInt steps, PetscReal time, Vec u, void *ctx), void *mctx, PetscErrorCode (*mdestroy)(void **))
124: {
125:   PetscInt  i;
126:   PetscBool identical;

128:   PetscFunctionBegin;
130:   for (i = 0; i < ts->numbermonitors; i++) {
131:     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))monitor, mctx, mdestroy, (PetscErrorCode (*)(void))ts->monitor[i], ts->monitorcontext[i], ts->monitordestroy[i], &identical));
132:     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
133:   }
134:   PetscCheck(ts->numbermonitors < MAXTSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
135:   ts->monitor[ts->numbermonitors]          = monitor;
136:   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
137:   ts->monitorcontext[ts->numbermonitors++] = (void *)mctx;
138:   PetscFunctionReturn(PETSC_SUCCESS);
139: }

141: /*@C
142:   TSMonitorCancel - Clears all the monitors that have been set on a time-step object.

144:   Logically Collective

146:   Input Parameter:
147: . ts - the `TS` context obtained from `TSCreate()`

149:   Level: intermediate

151:   Note:
152:   There is no way to remove a single, specific monitor.

154: .seealso: [](ch_ts), `TS`, `TSMonitorDefault()`, `TSMonitorSet()`
155: @*/
156: PetscErrorCode TSMonitorCancel(TS ts)
157: {
158:   PetscInt i;

160:   PetscFunctionBegin;
162:   for (i = 0; i < ts->numbermonitors; i++) {
163:     if (ts->monitordestroy[i]) PetscCall((*ts->monitordestroy[i])(&ts->monitorcontext[i]));
164:   }
165:   ts->numbermonitors = 0;
166:   PetscFunctionReturn(PETSC_SUCCESS);
167: }

169: /*@C
170:   TSMonitorDefault - The default monitor, prints the timestep and time for each step

172:   Input Parameters:
173: + ts    - the `TS` context
174: . step  - iteration number (after the final time step the monitor routine may be called with a step of -1, this indicates the solution has been interpolated to this time)
175: . ptime - current time
176: . v     - current iterate
177: - vf    - the viewer and format

179:   Options Database Key:
180: . -ts_monitor - monitors the time integration

182:   Level: intermediate

184:   Notes:
185:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
186:   to be used during the `TS` integration.

188: .seealso: [](ch_ts), `TSMonitorSet()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
189:           `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
190:           `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`
191: @*/
192: PetscErrorCode TSMonitorDefault(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
193: {
194:   PetscViewer viewer = vf->viewer;
195:   PetscBool   iascii, ibinary;

197:   PetscFunctionBegin;
199:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
200:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
201:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
202:   if (iascii) {
203:     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
204:     if (step == -1) { /* this indicates it is an interpolated solution */
205:       PetscCall(PetscViewerASCIIPrintf(viewer, "Interpolated solution at time %g between steps %" PetscInt_FMT " and %" PetscInt_FMT "\n", (double)ptime, ts->steps - 1, ts->steps));
206:     } else {
207:       PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)\n" : "\n"));
208:     }
209:     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
210:   } else if (ibinary) {
211:     PetscMPIInt rank;
212:     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
213:     if (rank == 0) {
214:       PetscBool skipHeader;
215:       PetscInt  classid = REAL_FILE_CLASSID;

217:       PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
218:       if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
219:       PetscCall(PetscRealView(1, &ptime, viewer));
220:     } else {
221:       PetscCall(PetscRealView(0, &ptime, viewer));
222:     }
223:   }
224:   PetscCall(PetscViewerPopFormat(viewer));
225:   PetscFunctionReturn(PETSC_SUCCESS);
226: }

228: /*@C
229:   TSMonitorExtreme - Prints the extreme values of the solution at each timestep

231:   Input Parameters:
232: + ts    - the `TS` context
233: . step  - iteration number (after the final time step the monitor routine may be called with a step of -1, this indicates the solution has been interpolated to this time)
234: . ptime - current time
235: . v     - current iterate
236: - vf    - the viewer and format

238:   Level: intermediate

240:   Note:
241:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
242:   to be used during the `TS` integration.

244: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`
245: @*/
246: PetscErrorCode TSMonitorExtreme(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
247: {
248:   PetscViewer viewer = vf->viewer;
249:   PetscBool   iascii;
250:   PetscReal   max, min;

252:   PetscFunctionBegin;
254:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
255:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
256:   if (iascii) {
257:     PetscCall(VecMax(v, NULL, &max));
258:     PetscCall(VecMin(v, NULL, &min));
259:     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
260:     PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s max %g min %g\n", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)" : "", (double)max, (double)min));
261:     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
262:   }
263:   PetscCall(PetscViewerPopFormat(viewer));
264:   PetscFunctionReturn(PETSC_SUCCESS);
265: }

267: /*@C
268:   TSMonitorLGCtxCreate - Creates a `TSMonitorLGCtx` context for use with
269:   `TS` to monitor the solution process graphically in various ways

271:   Collective

273:   Input Parameters:
274: + comm     - the MPI communicator to use
275: . host     - the X display to open, or `NULL` for the local machine
276: . label    - the title to put in the title bar
277: . x        - the x screen coordinates of the upper left coordinate of the window
278: . y        - the y screen coordinates of the upper left coordinate of the window
279: . m        - the screen width in pixels
280: . n        - the screen height in pixels
281: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time

283:   Output Parameter:
284: . ctx - the context

286:   Options Database Keys:
287: + -ts_monitor_lg_timestep        - automatically sets line graph monitor
288: . -ts_monitor_lg_timestep_log    - automatically sets line graph monitor
289: . -ts_monitor_lg_solution        - monitor the solution (or certain values of the solution by calling `TSMonitorLGSetDisplayVariables()` or `TSMonitorLGCtxSetDisplayVariables()`)
290: . -ts_monitor_lg_error           - monitor the error
291: . -ts_monitor_lg_ksp_iterations  - monitor the number of `KSP` iterations needed for each timestep
292: . -ts_monitor_lg_snes_iterations - monitor the number of `SNES` iterations needed for each timestep
293: - -lg_use_markers <true,false>   - mark the data points (at each time step) on the plot; default is true

295:   Level: intermediate

297:   Notes:
298:   Pass the context and `TSMonitorLGCtxDestroy()` to `TSMonitorSet()` to have the context destroyed when no longer needed.

300:   One can provide a function that transforms the solution before plotting it with `TSMonitorLGCtxSetTransform()` or `TSMonitorLGSetTransform()`

302:   Many of the functions that control the monitoring have two forms\: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a `TS` object as the
303:   first argument (if that `TS` object does not have a `TSMonitorLGCtx` associated with it the function call is ignored) and the second takes a `TSMonitorLGCtx` object
304:   as the first argument.

306:   One can control the names displayed for each solution or error variable with `TSMonitorLGCtxSetVariableNames()` or `TSMonitorLGSetVariableNames()`

308: .seealso: [](ch_ts), `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorDefault()`, `VecView()`,
309:           `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
310:           `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
311:           `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
312:           `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
313: @*/
314: PetscErrorCode TSMonitorLGCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorLGCtx *ctx)
315: {
316:   PetscDraw draw;

318:   PetscFunctionBegin;
319:   PetscCall(PetscNew(ctx));
320:   PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
321:   PetscCall(PetscDrawSetFromOptions(draw));
322:   PetscCall(PetscDrawLGCreate(draw, 1, &(*ctx)->lg));
323:   PetscCall(PetscDrawLGSetFromOptions((*ctx)->lg));
324:   PetscCall(PetscDrawDestroy(&draw));
325:   (*ctx)->howoften = howoften;
326:   PetscFunctionReturn(PETSC_SUCCESS);
327: }

329: /*@C
330:   TSMonitorLGTimeStep - Monitors a `TS` by printing the time-steps

332:   Collective

334:   Input Parameters:
335: + ts     - the time integrator
336: . step   - the current time step
337: . ptime  - the current time
338: . v      - the current state
339: - monctx - the monitor context obtained with `TSMonitorLGCtxCreate()`

341:   Level: advanced

343:   Note:
344:   This is not called directly by users, rather one calls `TSMonitorSet()` along the `ctx` created by `TSMonitorLGCtxCreate()`
345:   and `TSMonitorLGCtxDestroy()`

347: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGCtxDestroy()`
348: @*/
349: PetscErrorCode TSMonitorLGTimeStep(TS ts, PetscInt step, PetscReal ptime, Vec v, void *monctx)
350: {
351:   TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
352:   PetscReal      x   = ptime, y;

354:   PetscFunctionBegin;
355:   if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates an interpolated solution */
356:   if (!step) {
357:     PetscDrawAxis axis;
358:     const char   *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
359:     PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
360:     PetscCall(PetscDrawAxisSetLabels(axis, "Timestep as function of time", "Time", ylabel));
361:     PetscCall(PetscDrawLGReset(ctx->lg));
362:   }
363:   PetscCall(TSGetTimeStep(ts, &y));
364:   if (ctx->semilogy) y = PetscLog10Real(y);
365:   PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
366:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
367:     PetscCall(PetscDrawLGDraw(ctx->lg));
368:     PetscCall(PetscDrawLGSave(ctx->lg));
369:   }
370:   PetscFunctionReturn(PETSC_SUCCESS);
371: }

373: /*@C
374:   TSMonitorLGCtxDestroy - Destroys a line graph context that was created with `TSMonitorLGCtxCreate()`.

376:   Collective

378:   Input Parameter:
379: . ctx - the monitor context

381:   Level: intermediate

383:   Note:
384:   Pass to `TSMonitorSet()` along with the context and `TSMonitorLGTimeStep()`

386: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
387: @*/
388: PetscErrorCode TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
389: {
390:   PetscFunctionBegin;
391:   if ((*ctx)->transformdestroy) PetscCall(((*ctx)->transformdestroy)((*ctx)->transformctx));
392:   PetscCall(PetscDrawLGDestroy(&(*ctx)->lg));
393:   PetscCall(PetscStrArrayDestroy(&(*ctx)->names));
394:   PetscCall(PetscStrArrayDestroy(&(*ctx)->displaynames));
395:   PetscCall(PetscFree((*ctx)->displayvariables));
396:   PetscCall(PetscFree((*ctx)->displayvalues));
397:   PetscCall(PetscFree(*ctx));
398:   PetscFunctionReturn(PETSC_SUCCESS);
399: }

401: /* Creates a TSMonitorSPCtx for use with DMSwarm particle visualizations */
402: PetscErrorCode TSMonitorSPCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, PetscInt retain, PetscBool phase, PetscBool multispecies, TSMonitorSPCtx *ctx)
403: {
404:   PetscDraw draw;

406:   PetscFunctionBegin;
407:   PetscCall(PetscNew(ctx));
408:   PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
409:   PetscCall(PetscDrawSetFromOptions(draw));
410:   PetscCall(PetscDrawSPCreate(draw, 1, &(*ctx)->sp));
411:   PetscCall(PetscDrawDestroy(&draw));
412:   (*ctx)->howoften     = howoften;
413:   (*ctx)->retain       = retain;
414:   (*ctx)->phase        = phase;
415:   (*ctx)->multispecies = multispecies;
416:   PetscFunctionReturn(PETSC_SUCCESS);
417: }

419: /* Destroys a TSMonitorSPCtx that was created with TSMonitorSPCtxCreate */
420: PetscErrorCode TSMonitorSPCtxDestroy(TSMonitorSPCtx *ctx)
421: {
422:   PetscFunctionBegin;
423:   PetscCall(PetscDrawSPDestroy(&(*ctx)->sp));
424:   PetscCall(PetscFree(*ctx));
425:   PetscFunctionReturn(PETSC_SUCCESS);
426: }

428: /* Creates a TSMonitorHGCtx for use with DMSwarm particle visualizations */
429: PetscErrorCode TSMonitorHGCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, PetscInt Ns, PetscInt Nb, PetscBool velocity, TSMonitorHGCtx *ctx)
430: {
431:   PetscDraw draw;
432:   PetscInt  s;

434:   PetscFunctionBegin;
435:   PetscCall(PetscNew(ctx));
436:   PetscCall(PetscMalloc1(Ns, &(*ctx)->hg));
437:   for (s = 0; s < Ns; ++s) {
438:     PetscCall(PetscDrawCreate(comm, host, label, (int)(x + s * m), y, m, n, &draw));
439:     PetscCall(PetscDrawSetFromOptions(draw));
440:     PetscCall(PetscDrawHGCreate(draw, (int)Nb, &(*ctx)->hg[s]));
441:     PetscCall(PetscDrawHGCalcStats((*ctx)->hg[s], PETSC_TRUE));
442:     PetscCall(PetscDrawDestroy(&draw));
443:   }
444:   (*ctx)->howoften = howoften;
445:   (*ctx)->Ns       = Ns;
446:   (*ctx)->velocity = velocity;
447:   PetscFunctionReturn(PETSC_SUCCESS);
448: }

450: /* Destroys a TSMonitorHGCtx that was created with TSMonitorHGCtxCreate */
451: PetscErrorCode TSMonitorHGCtxDestroy(TSMonitorHGCtx *ctx)
452: {
453:   PetscInt s;

455:   PetscFunctionBegin;
456:   for (s = 0; s < (*ctx)->Ns; ++s) PetscCall(PetscDrawHGDestroy(&(*ctx)->hg[s]));
457:   PetscCall(PetscFree((*ctx)->hg));
458:   PetscCall(PetscFree(*ctx));
459:   PetscFunctionReturn(PETSC_SUCCESS);
460: }

462: /*@C
463:   TSMonitorDrawSolution - Monitors progress of the `TS` solvers by calling
464:   `VecView()` for the solution at each timestep

466:   Collective

468:   Input Parameters:
469: + ts    - the `TS` context
470: . step  - current time-step
471: . ptime - current time
472: . u     - the solution at the current time
473: - dummy - either a viewer or `NULL`

475:   Options Database Keys:
476: + -ts_monitor_draw_solution         - draw the solution at each time-step
477: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution

479:   Level: intermediate

481:   Notes:
482:   The initial solution and current solution are not displayed with a common axis scaling so generally the option `-ts_monitor_draw_solution_initial`
483:   will look bad

485:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, as well as the context created with
486:   `TSMonitorDrawCtxCreate()` and the function `TSMonitorDrawCtxDestroy()` to cause the monitor to be used during the `TS` integration.

488: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtxCreate()`, `TSMonitorDrawCtxDestroy()`
489: @*/
490: PetscErrorCode TSMonitorDrawSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
491: {
492:   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
493:   PetscDraw        draw;

495:   PetscFunctionBegin;
496:   if (!step && ictx->showinitial) {
497:     if (!ictx->initialsolution) PetscCall(VecDuplicate(u, &ictx->initialsolution));
498:     PetscCall(VecCopy(u, ictx->initialsolution));
499:   }
500:   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);

502:   if (ictx->showinitial) {
503:     PetscReal pause;
504:     PetscCall(PetscViewerDrawGetPause(ictx->viewer, &pause));
505:     PetscCall(PetscViewerDrawSetPause(ictx->viewer, 0.0));
506:     PetscCall(VecView(ictx->initialsolution, ictx->viewer));
507:     PetscCall(PetscViewerDrawSetPause(ictx->viewer, pause));
508:     PetscCall(PetscViewerDrawSetHold(ictx->viewer, PETSC_TRUE));
509:   }
510:   PetscCall(VecView(u, ictx->viewer));
511:   if (ictx->showtimestepandtime) {
512:     PetscReal xl, yl, xr, yr, h;
513:     char      time[32];

515:     PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
516:     PetscCall(PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime));
517:     PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
518:     h = yl + .95 * (yr - yl);
519:     PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
520:     PetscCall(PetscDrawFlush(draw));
521:   }

523:   if (ictx->showinitial) PetscCall(PetscViewerDrawSetHold(ictx->viewer, PETSC_FALSE));
524:   PetscFunctionReturn(PETSC_SUCCESS);
525: }

527: /*@C
528:   TSMonitorDrawSolutionPhase - Monitors progress of the `TS` solvers by plotting the solution as a phase diagram

530:   Collective

532:   Input Parameters:
533: + ts    - the `TS` context
534: . step  - current time-step
535: . ptime - current time
536: . u     - the solution at the current time
537: - dummy - either a viewer or `NULL`

539:   Level: intermediate

541:   Notes:
542:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
543:   to be used during the `TS` integration.

545: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
546: @*/
547: PetscErrorCode TSMonitorDrawSolutionPhase(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
548: {
549:   TSMonitorDrawCtx   ictx = (TSMonitorDrawCtx)dummy;
550:   PetscDraw          draw;
551:   PetscDrawAxis      axis;
552:   PetscInt           n;
553:   PetscMPIInt        size;
554:   PetscReal          U0, U1, xl, yl, xr, yr, h;
555:   char               time[32];
556:   const PetscScalar *U;

558:   PetscFunctionBegin;
559:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)ts), &size));
560:   PetscCheck(size == 1, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only allowed for sequential runs");
561:   PetscCall(VecGetSize(u, &n));
562:   PetscCheck(n == 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only for ODEs with two unknowns");

564:   PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
565:   PetscCall(PetscViewerDrawGetDrawAxis(ictx->viewer, 0, &axis));
566:   PetscCall(PetscDrawAxisGetLimits(axis, &xl, &xr, &yl, &yr));
567:   if (!step) {
568:     PetscCall(PetscDrawClear(draw));
569:     PetscCall(PetscDrawAxisDraw(axis));
570:   }

572:   PetscCall(VecGetArrayRead(u, &U));
573:   U0 = PetscRealPart(U[0]);
574:   U1 = PetscRealPart(U[1]);
575:   PetscCall(VecRestoreArrayRead(u, &U));
576:   if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(PETSC_SUCCESS);

578:   PetscDrawCollectiveBegin(draw);
579:   PetscCall(PetscDrawPoint(draw, U0, U1, PETSC_DRAW_BLACK));
580:   if (ictx->showtimestepandtime) {
581:     PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
582:     PetscCall(PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime));
583:     h = yl + .95 * (yr - yl);
584:     PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
585:   }
586:   PetscDrawCollectiveEnd(draw);
587:   PetscCall(PetscDrawFlush(draw));
588:   PetscCall(PetscDrawPause(draw));
589:   PetscCall(PetscDrawSave(draw));
590:   PetscFunctionReturn(PETSC_SUCCESS);
591: }

593: /*@C
594:   TSMonitorDrawCtxDestroy - Destroys the monitor context for `TSMonitorDrawSolution()`

596:   Collective

598:   Input Parameter:
599: . ictx - the monitor context

601:   Level: intermediate

603: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawSolution()`, `TSMonitorDrawError()`, `TSMonitorDrawCtx`
604: @*/
605: PetscErrorCode TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
606: {
607:   PetscFunctionBegin;
608:   PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
609:   PetscCall(VecDestroy(&(*ictx)->initialsolution));
610:   PetscCall(PetscFree(*ictx));
611:   PetscFunctionReturn(PETSC_SUCCESS);
612: }

614: /*@C
615:   TSMonitorDrawCtxCreate - Creates the monitor context for `TSMonitorDrawCtx`

617:   Collective

619:   Input Parameters:
620: + comm     - the MPI communicator to use
621: . host     - the X display to open, or `NULL` for the local machine
622: . label    - the title to put in the title bar
623: . x        - the x screen coordinates of the upper left coordinate of the window
624: . y        - the y screen coordinates of the upper left coordinate of the window
625: . m        - the screen width in pixels
626: . n        - the screen height in pixels
627: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time

629:   Output Parameter:
630: . ctx - the monitor context

632:   Options Database Keys:
633: + -ts_monitor_draw_solution         - draw the solution at each time-step
634: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution

636:   Level: intermediate

638:   Note:
639:   The context created by this function, `PetscMonitorDrawSolution()`, and `TSMonitorDrawCtxDestroy()` should be passed together to `TSMonitorSet()`.

641: .seealso: [](ch_ts), `TS`, `TSMonitorDrawCtxDestroy()`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtx`, `PetscMonitorDrawSolution()`
642: @*/
643: PetscErrorCode TSMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorDrawCtx *ctx)
644: {
645:   PetscFunctionBegin;
646:   PetscCall(PetscNew(ctx));
647:   PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
648:   PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));

650:   (*ctx)->howoften    = howoften;
651:   (*ctx)->showinitial = PETSC_FALSE;
652:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_initial", &(*ctx)->showinitial, NULL));

654:   (*ctx)->showtimestepandtime = PETSC_FALSE;
655:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_show_time", &(*ctx)->showtimestepandtime, NULL));
656:   PetscFunctionReturn(PETSC_SUCCESS);
657: }

659: /*@C
660:   TSMonitorDrawSolutionFunction - Monitors progress of the `TS` solvers by calling
661:   `VecView()` for the solution provided by `TSSetSolutionFunction()` at each timestep

663:   Collective

665:   Input Parameters:
666: + ts    - the `TS` context
667: . step  - current time-step
668: . ptime - current time
669: . u     - solution at current time
670: - dummy - either a viewer or `NULL`

672:   Options Database Key:
673: . -ts_monitor_draw_solution_function - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`

675:   Level: intermediate

677:   Note:
678:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
679:   to be used during the `TS` integration.

681: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
682: @*/
683: PetscErrorCode TSMonitorDrawSolutionFunction(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
684: {
685:   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
686:   PetscViewer      viewer = ctx->viewer;
687:   Vec              work;

689:   PetscFunctionBegin;
690:   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
691:   PetscCall(VecDuplicate(u, &work));
692:   PetscCall(TSComputeSolutionFunction(ts, ptime, work));
693:   PetscCall(VecView(work, viewer));
694:   PetscCall(VecDestroy(&work));
695:   PetscFunctionReturn(PETSC_SUCCESS);
696: }

698: /*@C
699:   TSMonitorDrawError - Monitors progress of the `TS` solvers by calling
700:   `VecView()` for the error at each timestep

702:   Collective

704:   Input Parameters:
705: + ts    - the `TS` context
706: . step  - current time-step
707: . ptime - current time
708: . u     - solution at current time
709: - dummy - either a viewer or `NULL`

711:   Options Database Key:
712: . -ts_monitor_draw_error - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`

714:   Level: intermediate

716:   Notes:
717:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
718:   to be used during the `TS` integration.

720: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
721: @*/
722: PetscErrorCode TSMonitorDrawError(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
723: {
724:   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
725:   PetscViewer      viewer = ctx->viewer;
726:   Vec              work;

728:   PetscFunctionBegin;
729:   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
730:   PetscCall(VecDuplicate(u, &work));
731:   PetscCall(TSComputeSolutionFunction(ts, ptime, work));
732:   PetscCall(VecAXPY(work, -1.0, u));
733:   PetscCall(VecView(work, viewer));
734:   PetscCall(VecDestroy(&work));
735:   PetscFunctionReturn(PETSC_SUCCESS);
736: }

738: /*@C
739:   TSMonitorSolution - Monitors progress of the `TS` solvers by `VecView()` for the solution at each timestep. Normally the viewer is a binary file or a `PetscDraw` object

741:   Collective

743:   Input Parameters:
744: + ts    - the `TS` context
745: . step  - current time-step
746: . ptime - current time
747: . u     - current state
748: - vf    - viewer and its format

750:   Level: intermediate

752:   Notes:
753:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
754:   to be used during the `TS` integration.

756: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
757: @*/
758: PetscErrorCode TSMonitorSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
759: {
760:   PetscFunctionBegin;
761:   if ((vf->view_interval > 0 && !(step % vf->view_interval)) || (vf->view_interval && ts->reason)) {
762:     PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
763:     PetscCall(VecView(u, vf->viewer));
764:     PetscCall(PetscViewerPopFormat(vf->viewer));
765:   }
766:   PetscFunctionReturn(PETSC_SUCCESS);
767: }

769: /*@C
770:   TSMonitorSolutionVTK - Monitors progress of the `TS` solvers by `VecView()` for the solution at selected timesteps.

772:   Collective

774:   Input Parameters:
775: + ts    - the `TS` context
776: . step  - current time-step
777: . ptime - current time
778: . u     - current state
779: - ctx   - monitor context obtained with `TSMonitorSolutionVTKCtxCreate()`

781:   Level: developer

783:   Notes:
784:   The VTK format does not allow writing multiple time steps in the same file, therefore a different file will be written for each time step.
785:   These are named according to the file name template.

787:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
788:   to be used during the `TS` integration.

790: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
791: @*/
792: PetscErrorCode TSMonitorSolutionVTK(TS ts, PetscInt step, PetscReal ptime, Vec u, TSMonitorVTKCtx ctx)
793: {
794:   char        filename[PETSC_MAX_PATH_LEN];
795:   PetscViewer viewer;

797:   PetscFunctionBegin;
798:   if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
799:   if (((ctx->interval > 0) && (!(step % ctx->interval))) || (ctx->interval && ts->reason)) {
800:     PetscCall(PetscSNPrintf(filename, sizeof(filename), (const char *)ctx->filenametemplate, step));
801:     PetscCall(PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts), filename, FILE_MODE_WRITE, &viewer));
802:     PetscCall(VecView(u, viewer));
803:     PetscCall(PetscViewerDestroy(&viewer));
804:   }
805:   PetscFunctionReturn(PETSC_SUCCESS);
806: }

808: /*@C
809:   TSMonitorSolutionVTKDestroy - Destroy the monitor context created with `TSMonitorSolutionVTKCtxCreate()`

811:   Not Collective

813:   Input Parameter:
814: . ctx - the monitor context

816:   Level: developer

818:   Note:
819:   This function is normally passed to `TSMonitorSet()` along with `TSMonitorSolutionVTK()`.

821: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorSolutionVTK()`
822: @*/
823: PetscErrorCode TSMonitorSolutionVTKDestroy(TSMonitorVTKCtx *ctx)
824: {
825:   PetscFunctionBegin;
826:   PetscCall(PetscFree((*ctx)->filenametemplate));
827:   PetscCall(PetscFree(*ctx));
828:   PetscFunctionReturn(PETSC_SUCCESS);
829: }

831: /*@C
832:   TSMonitorSolutionVTKCtxCreate - Create the monitor context to be used in `TSMonitorSolutionVTK()`

834:   Not collective

836:   Input Parameter:
837: . filenametemplate - the template file name, e.g. foo-%03d.vts

839:   Output Parameter:
840: . ctx - the monitor context

842:   Level: developer

844:   Note:
845:   This function is normally used inside `TSSetFromOptions()` to pass the context created to `TSMonitorSet()` along with `TSMonitorSolutionVTK()`.

847: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorSolutionVTK()`, `TSMonitorSolutionVTKDestroy()`
848: @*/
849: PetscErrorCode TSMonitorSolutionVTKCtxCreate(const char *filenametemplate, TSMonitorVTKCtx *ctx)
850: {
851:   const char     *ptr = NULL, *ptr2 = NULL;
852:   TSMonitorVTKCtx ictx;

854:   PetscFunctionBegin;
855:   PetscAssertPointer(filenametemplate, 1);
856:   PetscAssertPointer(ctx, 2);
857:   /* Do some cursory validation of the input. */
858:   PetscCall(PetscStrstr(filenametemplate, "%", (char **)&ptr));
859:   PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_USER, "-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03" PetscInt_FMT ".vts");
860:   for (ptr++; ptr && *ptr; ptr++) {
861:     PetscCall(PetscStrchr("DdiouxX", *ptr, (char **)&ptr2));
862:     PetscCheck(ptr2 || (*ptr >= '0' && *ptr <= '9'), PETSC_COMM_SELF, PETSC_ERR_USER, "Invalid file template argument to -ts_monitor_solution_vtk, should look like filename-%%03" PetscInt_FMT ".vts");
863:     if (ptr2) break;
864:   }
865:   PetscCall(PetscNew(&ictx));
866:   PetscCall(PetscStrallocpy(filenametemplate, &ictx->filenametemplate));
867:   ictx->interval = 1;

869:   *ctx = ictx;
870:   PetscFunctionReturn(PETSC_SUCCESS);
871: }

873: /*@C
874:   TSMonitorLGSolution - Monitors progress of the `TS` solvers by plotting each component of the solution vector
875:   in a time based line graph

877:   Collective

879:   Input Parameters:
880: + ts    - the `TS` context
881: . step  - current time-step
882: . ptime - current time
883: . u     - current solution
884: - dctx  - the `TSMonitorLGCtx` object that contains all the options for the monitoring, this is created with `TSMonitorLGCtxCreate()`

886:   Options Database Key:
887: . -ts_monitor_lg_solution_variables - enable monitor of lg solution variables

889:   Level: intermediate

891:   Notes:
892:   Each process in a parallel run displays its component solutions in a separate window

894:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
895:   to be used during the `TS` integration.

897: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
898:           `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
899:           `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGError()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
900:           `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
901: @*/
902: PetscErrorCode TSMonitorLGSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
903: {
904:   TSMonitorLGCtx     ctx = (TSMonitorLGCtx)dctx;
905:   const PetscScalar *yy;
906:   Vec                v;

908:   PetscFunctionBegin;
909:   if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
910:   if (!step) {
911:     PetscDrawAxis axis;
912:     PetscInt      dim;
913:     PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
914:     PetscCall(PetscDrawAxisSetLabels(axis, "Solution as function of time", "Time", "Solution"));
915:     if (!ctx->names) {
916:       PetscBool flg;
917:       /* user provides names of variables to plot but no names has been set so assume names are integer values */
918:       PetscCall(PetscOptionsHasName(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", &flg));
919:       if (flg) {
920:         PetscInt i, n;
921:         char   **names;
922:         PetscCall(VecGetSize(u, &n));
923:         PetscCall(PetscMalloc1(n + 1, &names));
924:         for (i = 0; i < n; i++) {
925:           PetscCall(PetscMalloc1(5, &names[i]));
926:           PetscCall(PetscSNPrintf(names[i], 5, "%" PetscInt_FMT, i));
927:         }
928:         names[n]   = NULL;
929:         ctx->names = names;
930:       }
931:     }
932:     if (ctx->names && !ctx->displaynames) {
933:       char    **displaynames;
934:       PetscBool flg;
935:       PetscCall(VecGetLocalSize(u, &dim));
936:       PetscCall(PetscCalloc1(dim + 1, &displaynames));
937:       PetscCall(PetscOptionsGetStringArray(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", displaynames, &dim, &flg));
938:       if (flg) PetscCall(TSMonitorLGCtxSetDisplayVariables(ctx, (const char *const *)displaynames));
939:       PetscCall(PetscStrArrayDestroy(&displaynames));
940:     }
941:     if (ctx->displaynames) {
942:       PetscCall(PetscDrawLGSetDimension(ctx->lg, ctx->ndisplayvariables));
943:       PetscCall(PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->displaynames));
944:     } else if (ctx->names) {
945:       PetscCall(VecGetLocalSize(u, &dim));
946:       PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
947:       PetscCall(PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->names));
948:     } else {
949:       PetscCall(VecGetLocalSize(u, &dim));
950:       PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
951:     }
952:     PetscCall(PetscDrawLGReset(ctx->lg));
953:   }

955:   if (!ctx->transform) v = u;
956:   else PetscCall((*ctx->transform)(ctx->transformctx, u, &v));
957:   PetscCall(VecGetArrayRead(v, &yy));
958:   if (ctx->displaynames) {
959:     PetscInt i;
960:     for (i = 0; i < ctx->ndisplayvariables; i++) ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
961:     PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, ctx->displayvalues));
962:   } else {
963: #if defined(PETSC_USE_COMPLEX)
964:     PetscInt   i, n;
965:     PetscReal *yreal;
966:     PetscCall(VecGetLocalSize(v, &n));
967:     PetscCall(PetscMalloc1(n, &yreal));
968:     for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
969:     PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal));
970:     PetscCall(PetscFree(yreal));
971: #else
972:     PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy));
973: #endif
974:   }
975:   PetscCall(VecRestoreArrayRead(v, &yy));
976:   if (ctx->transform) PetscCall(VecDestroy(&v));

978:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
979:     PetscCall(PetscDrawLGDraw(ctx->lg));
980:     PetscCall(PetscDrawLGSave(ctx->lg));
981:   }
982:   PetscFunctionReturn(PETSC_SUCCESS);
983: }

985: /*@C
986:   TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot

988:   Collective

990:   Input Parameters:
991: + ts    - the `TS` context
992: - names - the names of the components, final string must be `NULL`

994:   Level: intermediate

996:   Notes:
997:   If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored

999: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetVariableNames()`
1000: @*/
1001: PetscErrorCode TSMonitorLGSetVariableNames(TS ts, const char *const *names)
1002: {
1003:   PetscInt i;

1005:   PetscFunctionBegin;
1006:   for (i = 0; i < ts->numbermonitors; i++) {
1007:     if (ts->monitor[i] == TSMonitorLGSolution) {
1008:       PetscCall(TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i], names));
1009:       break;
1010:     }
1011:   }
1012:   PetscFunctionReturn(PETSC_SUCCESS);
1013: }

1015: /*@C
1016:   TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot

1018:   Collective

1020:   Input Parameters:
1021: + ctx   - the `TS` context
1022: - names - the names of the components, final string must be `NULL`

1024:   Level: intermediate

1026: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGSetVariableNames()`
1027: @*/
1028: PetscErrorCode TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx, const char *const *names)
1029: {
1030:   PetscFunctionBegin;
1031:   PetscCall(PetscStrArrayDestroy(&ctx->names));
1032:   PetscCall(PetscStrArrayallocpy(names, &ctx->names));
1033:   PetscFunctionReturn(PETSC_SUCCESS);
1034: }

1036: /*@C
1037:   TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot

1039:   Collective

1041:   Input Parameter:
1042: . ts - the `TS` context

1044:   Output Parameter:
1045: . names - the names of the components, final string must be `NULL`

1047:   Level: intermediate

1049:   Note:
1050:   If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored

1052: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
1053: @*/
1054: PetscErrorCode TSMonitorLGGetVariableNames(TS ts, const char *const **names)
1055: {
1056:   PetscInt i;

1058:   PetscFunctionBegin;
1059:   *names = NULL;
1060:   for (i = 0; i < ts->numbermonitors; i++) {
1061:     if (ts->monitor[i] == TSMonitorLGSolution) {
1062:       TSMonitorLGCtx ctx = (TSMonitorLGCtx)ts->monitorcontext[i];
1063:       *names             = (const char *const *)ctx->names;
1064:       break;
1065:     }
1066:   }
1067:   PetscFunctionReturn(PETSC_SUCCESS);
1068: }

1070: /*@C
1071:   TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor

1073:   Collective

1075:   Input Parameters:
1076: + ctx          - the `TSMonitorLG` context
1077: - displaynames - the names of the components, final string must be `NULL`

1079:   Level: intermediate

1081: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
1082: @*/
1083: PetscErrorCode TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx, const char *const *displaynames)
1084: {
1085:   PetscInt j = 0, k;

1087:   PetscFunctionBegin;
1088:   if (!ctx->names) PetscFunctionReturn(PETSC_SUCCESS);
1089:   PetscCall(PetscStrArrayDestroy(&ctx->displaynames));
1090:   PetscCall(PetscStrArrayallocpy(displaynames, &ctx->displaynames));
1091:   while (displaynames[j]) j++;
1092:   ctx->ndisplayvariables = j;
1093:   PetscCall(PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvariables));
1094:   PetscCall(PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvalues));
1095:   j = 0;
1096:   while (displaynames[j]) {
1097:     k = 0;
1098:     while (ctx->names[k]) {
1099:       PetscBool flg;
1100:       PetscCall(PetscStrcmp(displaynames[j], ctx->names[k], &flg));
1101:       if (flg) {
1102:         ctx->displayvariables[j] = k;
1103:         break;
1104:       }
1105:       k++;
1106:     }
1107:     j++;
1108:   }
1109:   PetscFunctionReturn(PETSC_SUCCESS);
1110: }

1112: /*@C
1113:   TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor

1115:   Collective

1117:   Input Parameters:
1118: + ts           - the `TS` context
1119: - displaynames - the names of the components, final string must be `NULL`

1121:   Level: intermediate

1123:   Note:
1124:   If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored

1126: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
1127: @*/
1128: PetscErrorCode TSMonitorLGSetDisplayVariables(TS ts, const char *const *displaynames)
1129: {
1130:   PetscInt i;

1132:   PetscFunctionBegin;
1133:   for (i = 0; i < ts->numbermonitors; i++) {
1134:     if (ts->monitor[i] == TSMonitorLGSolution) {
1135:       PetscCall(TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i], displaynames));
1136:       break;
1137:     }
1138:   }
1139:   PetscFunctionReturn(PETSC_SUCCESS);
1140: }

1142: /*@C
1143:   TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed

1145:   Collective

1147:   Input Parameters:
1148: + ts        - the `TS` context
1149: . transform - the transform function
1150: . destroy   - function to destroy the optional context
1151: - tctx      - optional context used by transform function

1153:   Level: intermediate

1155:   Note:
1156:   If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored

1158: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGCtxSetTransform()`
1159: @*/
1160: PetscErrorCode TSMonitorLGSetTransform(TS ts, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
1161: {
1162:   PetscInt i;

1164:   PetscFunctionBegin;
1165:   for (i = 0; i < ts->numbermonitors; i++) {
1166:     if (ts->monitor[i] == TSMonitorLGSolution) PetscCall(TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i], transform, destroy, tctx));
1167:   }
1168:   PetscFunctionReturn(PETSC_SUCCESS);
1169: }

1171: /*@C
1172:   TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed

1174:   Collective

1176:   Input Parameters:
1177: + tctx      - the `TS` context
1178: . transform - the transform function
1179: . destroy   - function to destroy the optional context
1180: - ctx       - optional context used by transform function

1182:   Level: intermediate

1184: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGSetTransform()`
1185: @*/
1186: PetscErrorCode TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
1187: {
1188:   PetscFunctionBegin;
1189:   ctx->transform        = transform;
1190:   ctx->transformdestroy = destroy;
1191:   ctx->transformctx     = tctx;
1192:   PetscFunctionReturn(PETSC_SUCCESS);
1193: }

1195: /*@C
1196:   TSMonitorLGError - Monitors progress of the `TS` solvers by plotting each component of the error
1197:   in a time based line graph

1199:   Collective

1201:   Input Parameters:
1202: + ts    - the `TS` context
1203: . step  - current time-step
1204: . ptime - current time
1205: . u     - current solution
1206: - dummy - `TSMonitorLGCtx` object created with `TSMonitorLGCtxCreate()`

1208:   Options Database Key:
1209: . -ts_monitor_lg_error - create a graphical monitor of error history

1211:   Level: intermediate

1213:   Notes:
1214:   Each process in a parallel run displays its component errors in a separate window

1216:   The user must provide the solution using `TSSetSolutionFunction()` to use this monitor.

1218:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1219:   to be used during the TS integration.

1221: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1222: @*/
1223: PetscErrorCode TSMonitorLGError(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
1224: {
1225:   TSMonitorLGCtx     ctx = (TSMonitorLGCtx)dummy;
1226:   const PetscScalar *yy;
1227:   Vec                y;

1229:   PetscFunctionBegin;
1230:   if (!step) {
1231:     PetscDrawAxis axis;
1232:     PetscInt      dim;
1233:     PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1234:     PetscCall(PetscDrawAxisSetLabels(axis, "Error in solution as function of time", "Time", "Error"));
1235:     PetscCall(VecGetLocalSize(u, &dim));
1236:     PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
1237:     PetscCall(PetscDrawLGReset(ctx->lg));
1238:   }
1239:   PetscCall(VecDuplicate(u, &y));
1240:   PetscCall(TSComputeSolutionFunction(ts, ptime, y));
1241:   PetscCall(VecAXPY(y, -1.0, u));
1242:   PetscCall(VecGetArrayRead(y, &yy));
1243: #if defined(PETSC_USE_COMPLEX)
1244:   {
1245:     PetscReal *yreal;
1246:     PetscInt   i, n;
1247:     PetscCall(VecGetLocalSize(y, &n));
1248:     PetscCall(PetscMalloc1(n, &yreal));
1249:     for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
1250:     PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal));
1251:     PetscCall(PetscFree(yreal));
1252:   }
1253: #else
1254:   PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy));
1255: #endif
1256:   PetscCall(VecRestoreArrayRead(y, &yy));
1257:   PetscCall(VecDestroy(&y));
1258:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1259:     PetscCall(PetscDrawLGDraw(ctx->lg));
1260:     PetscCall(PetscDrawLGSave(ctx->lg));
1261:   }
1262:   PetscFunctionReturn(PETSC_SUCCESS);
1263: }

1265: /*@C
1266:   TSMonitorSPSwarmSolution - Graphically displays phase plots of `DMSWARM` particles on a scatter plot

1268:   Input Parameters:
1269: + ts    - the `TS` context
1270: . step  - current time-step
1271: . ptime - current time
1272: . u     - current solution
1273: - dctx  - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorSPCtxCreate()`

1275:   Options Database Keys:
1276: + -ts_monitor_sp_swarm <n>                  - Monitor the solution every n steps, or -1 for plotting only the final solution
1277: . -ts_monitor_sp_swarm_retain <n>           - Retain n old points so we can see the history, or -1 for all points
1278: . -ts_monitor_sp_swarm_multi_species <bool> - Color each species differently
1279: - -ts_monitor_sp_swarm_phase <bool>         - Plot in phase space, as opposed to coordinate space

1281:   Level: intermediate

1283:   Notes:
1284:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1285:   to be used during the `TS` integration.

1287: .seealso: [](ch_ts), `TS`, `TSMonitoSet()`, `DMSWARM`, `TSMonitorSPCtxCreate()`
1288: @*/
1289: PetscErrorCode TSMonitorSPSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1290: {
1291:   TSMonitorSPCtx     ctx = (TSMonitorSPCtx)dctx;
1292:   PetscDraw          draw;
1293:   DM                 dm, cdm;
1294:   const PetscScalar *yy;
1295:   PetscInt           Np, p, dim = 2, *species;
1296:   PetscReal          species_color;

1298:   PetscFunctionBegin;
1299:   if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1300:   PetscCall(TSGetDM(ts, &dm));
1301:   if (!step) {
1302:     PetscDrawAxis axis;
1303:     PetscReal     dmboxlower[2], dmboxupper[2];

1305:     PetscCall(TSGetDM(ts, &dm));
1306:     PetscCall(DMGetDimension(dm, &dim));
1307:     PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Monitor only supports two dimensional fields");
1308:     PetscCall(DMSwarmGetCellDM(dm, &cdm));
1309:     PetscCall(DMGetBoundingBox(cdm, dmboxlower, dmboxupper));
1310:     PetscCall(VecGetLocalSize(u, &Np));
1311:     Np /= dim * 2;
1312:     PetscCall(PetscDrawSPGetAxis(ctx->sp, &axis));
1313:     if (ctx->phase) {
1314:       PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "X", "V"));
1315:       PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], -10, 10));
1316:     } else {
1317:       PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "X", "Y"));
1318:       PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], dmboxlower[1], dmboxupper[1]));
1319:     }
1320:     PetscCall(PetscDrawAxisSetHoldLimits(axis, PETSC_TRUE));
1321:     PetscCall(PetscDrawSPReset(ctx->sp));
1322:   }
1323:   if (ctx->multispecies) PetscCall(DMSwarmGetField(dm, "species", NULL, NULL, (void **)&species));
1324:   PetscCall(VecGetLocalSize(u, &Np));
1325:   Np /= dim * 2;
1326:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1327:     PetscCall(PetscDrawSPGetDraw(ctx->sp, &draw));
1328:     if ((ctx->retain == 0) || (ctx->retain > 0 && !(step % ctx->retain))) PetscCall(PetscDrawClear(draw));
1329:     PetscCall(PetscDrawFlush(draw));
1330:     PetscCall(PetscDrawSPReset(ctx->sp));
1331:     PetscCall(VecGetArrayRead(u, &yy));
1332:     for (p = 0; p < Np; ++p) {
1333:       PetscReal x, y;

1335:       if (ctx->phase) {
1336:         x = PetscRealPart(yy[p * dim * 2]);
1337:         y = PetscRealPart(yy[p * dim * 2 + dim]);
1338:       } else {
1339:         x = PetscRealPart(yy[p * dim * 2]);
1340:         y = PetscRealPart(yy[p * dim * 2 + 1]);
1341:       }
1342:       if (ctx->multispecies) {
1343:         species_color = species[p] + 2;
1344:         PetscCall(PetscDrawSPAddPointColorized(ctx->sp, &x, &y, &species_color));
1345:       } else {
1346:         PetscCall(PetscDrawSPAddPoint(ctx->sp, &x, &y));
1347:       }
1348:       PetscCall(PetscDrawSPAddPoint(ctx->sp, &x, &y));
1349:     }
1350:     PetscCall(VecRestoreArrayRead(u, &yy));
1351:     PetscCall(PetscDrawSPDraw(ctx->sp, PETSC_FALSE));
1352:     PetscCall(PetscDrawSPSave(ctx->sp));
1353:     if (ctx->multispecies) PetscCall(DMSwarmRestoreField(dm, "species", NULL, NULL, (void **)&species));
1354:   }
1355:   PetscFunctionReturn(PETSC_SUCCESS);
1356: }

1358: /*@C
1359:   TSMonitorHGSwarmSolution - Graphically displays histograms of `DMSWARM` particles

1361:   Input Parameters:
1362: + ts    - the `TS` context
1363: . step  - current time-step
1364: . ptime - current time
1365: . u     - current solution
1366: - dctx  - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorHGCtxCreate()`

1368:   Options Database Keys:
1369: + -ts_monitor_hg_swarm <n>             - Monitor the solution every n steps, or -1 for plotting only the final solution
1370: . -ts_monitor_hg_swarm_species <num>   - Number of species to histogram
1371: . -ts_monitor_hg_swarm_bins <num>      - Number of histogram bins
1372: - -ts_monitor_hg_swarm_velocity <bool> - Plot in velocity space, as opposed to coordinate space

1374:   Level: intermediate

1376:   Note:
1377:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1378:   to be used during the `TS` integration.

1380: .seealso: `TSMonitoSet()`
1381: @*/
1382: PetscErrorCode TSMonitorHGSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1383: {
1384:   TSMonitorHGCtx     ctx = (TSMonitorHGCtx)dctx;
1385:   PetscDraw          draw;
1386:   DM                 sw;
1387:   const PetscScalar *yy;
1388:   PetscInt          *species;
1389:   PetscInt           dim, d = 0, Np, p, Ns, s;

1391:   PetscFunctionBegin;
1392:   if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1393:   PetscCall(TSGetDM(ts, &sw));
1394:   PetscCall(DMGetDimension(sw, &dim));
1395:   PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
1396:   Ns = PetscMin(Ns, ctx->Ns);
1397:   PetscCall(VecGetLocalSize(u, &Np));
1398:   Np /= dim * 2;
1399:   if (!step) {
1400:     PetscDrawAxis axis;
1401:     char          title[PETSC_MAX_PATH_LEN];

1403:     for (s = 0; s < Ns; ++s) {
1404:       PetscCall(PetscDrawHGGetAxis(ctx->hg[s], &axis));
1405:       PetscCall(PetscSNPrintf(title, PETSC_MAX_PATH_LEN, "Species %" PetscInt_FMT, s));
1406:       if (ctx->velocity) PetscCall(PetscDrawAxisSetLabels(axis, title, "V", "N"));
1407:       else PetscCall(PetscDrawAxisSetLabels(axis, title, "X", "N"));
1408:     }
1409:   }
1410:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1411:     PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
1412:     for (s = 0; s < Ns; ++s) {
1413:       PetscCall(PetscDrawHGReset(ctx->hg[s]));
1414:       PetscCall(PetscDrawHGGetDraw(ctx->hg[s], &draw));
1415:       PetscCall(PetscDrawClear(draw));
1416:       PetscCall(PetscDrawFlush(draw));
1417:     }
1418:     PetscCall(VecGetArrayRead(u, &yy));
1419:     for (p = 0; p < Np; ++p) {
1420:       const PetscInt s = species[p] < Ns ? species[p] : 0;
1421:       PetscReal      v;

1423:       if (ctx->velocity) v = PetscRealPart(yy[p * dim * 2 + d + dim]);
1424:       else v = PetscRealPart(yy[p * dim * 2 + d]);
1425:       PetscCall(PetscDrawHGAddValue(ctx->hg[s], v));
1426:     }
1427:     PetscCall(VecRestoreArrayRead(u, &yy));
1428:     for (s = 0; s < Ns; ++s) {
1429:       PetscCall(PetscDrawHGDraw(ctx->hg[s]));
1430:       PetscCall(PetscDrawHGSave(ctx->hg[s]));
1431:     }
1432:     PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
1433:   }
1434:   PetscFunctionReturn(PETSC_SUCCESS);
1435: }

1437: /*@C
1438:   TSMonitorError - Monitors progress of the `TS` solvers by printing the 2 norm of the error at each timestep

1440:   Collective

1442:   Input Parameters:
1443: + ts    - the `TS` context
1444: . step  - current time-step
1445: . ptime - current time
1446: . u     - current solution
1447: - vf    - unused context

1449:   Options Database Key:
1450: . -ts_monitor_error - create a graphical monitor of error history

1452:   Level: intermediate

1454:   Notes:
1455:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1456:   to be used during the `TS` integration.

1458:   The user must provide the solution using `TSSetSolutionFunction()` to use this monitor.

1460: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1461: @*/
1462: PetscErrorCode TSMonitorError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
1463: {
1464:   DM        dm;
1465:   PetscDS   ds = NULL;
1466:   PetscInt  Nf = -1, f;
1467:   PetscBool flg;

1469:   PetscFunctionBegin;
1470:   PetscCall(TSGetDM(ts, &dm));
1471:   if (dm) PetscCall(DMGetDS(dm, &ds));
1472:   if (ds) PetscCall(PetscDSGetNumFields(ds, &Nf));
1473:   if (Nf <= 0) {
1474:     Vec       y;
1475:     PetscReal nrm;

1477:     PetscCall(VecDuplicate(u, &y));
1478:     PetscCall(TSComputeSolutionFunction(ts, ptime, y));
1479:     PetscCall(VecAXPY(y, -1.0, u));
1480:     PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERASCII, &flg));
1481:     if (flg) {
1482:       PetscCall(VecNorm(y, NORM_2, &nrm));
1483:       PetscCall(PetscViewerASCIIPrintf(vf->viewer, "2-norm of error %g\n", (double)nrm));
1484:     }
1485:     PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &flg));
1486:     if (flg) PetscCall(VecView(y, vf->viewer));
1487:     PetscCall(VecDestroy(&y));
1488:   } else {
1489:     PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx);
1490:     void    **ctxs;
1491:     Vec       v;
1492:     PetscReal ferrors[1];

1494:     PetscCall(PetscMalloc2(Nf, &exactFuncs, Nf, &ctxs));
1495:     for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(ds, f, &exactFuncs[f], &ctxs[f]));
1496:     PetscCall(DMComputeL2FieldDiff(dm, ptime, exactFuncs, ctxs, u, ferrors));
1497:     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Timestep: %04d time = %-8.4g \t L_2 Error: [", (int)step, (double)ptime));
1498:     for (f = 0; f < Nf; ++f) {
1499:       if (f > 0) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ", "));
1500:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%2.3g", (double)ferrors[f]));
1501:     }
1502:     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "]\n"));

1504:     PetscCall(VecViewFromOptions(u, NULL, "-sol_vec_view"));

1506:     PetscCall(PetscOptionsHasName(NULL, NULL, "-exact_vec_view", &flg));
1507:     if (flg) {
1508:       PetscCall(DMGetGlobalVector(dm, &v));
1509:       PetscCall(DMProjectFunction(dm, ptime, exactFuncs, ctxs, INSERT_ALL_VALUES, v));
1510:       PetscCall(PetscObjectSetName((PetscObject)v, "Exact Solution"));
1511:       PetscCall(VecViewFromOptions(v, NULL, "-exact_vec_view"));
1512:       PetscCall(DMRestoreGlobalVector(dm, &v));
1513:     }
1514:     PetscCall(PetscFree2(exactFuncs, ctxs));
1515:   }
1516:   PetscFunctionReturn(PETSC_SUCCESS);
1517: }

1519: PetscErrorCode TSMonitorLGSNESIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, void *monctx)
1520: {
1521:   TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1522:   PetscReal      x   = ptime, y;
1523:   PetscInt       its;

1525:   PetscFunctionBegin;
1526:   if (n < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1527:   if (!n) {
1528:     PetscDrawAxis axis;
1529:     PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1530:     PetscCall(PetscDrawAxisSetLabels(axis, "Nonlinear iterations as function of time", "Time", "SNES Iterations"));
1531:     PetscCall(PetscDrawLGReset(ctx->lg));
1532:     ctx->snes_its = 0;
1533:   }
1534:   PetscCall(TSGetSNESIterations(ts, &its));
1535:   y = its - ctx->snes_its;
1536:   PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
1537:   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1538:     PetscCall(PetscDrawLGDraw(ctx->lg));
1539:     PetscCall(PetscDrawLGSave(ctx->lg));
1540:   }
1541:   ctx->snes_its = its;
1542:   PetscFunctionReturn(PETSC_SUCCESS);
1543: }

1545: PetscErrorCode TSMonitorLGKSPIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, void *monctx)
1546: {
1547:   TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1548:   PetscReal      x   = ptime, y;
1549:   PetscInt       its;

1551:   PetscFunctionBegin;
1552:   if (n < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1553:   if (!n) {
1554:     PetscDrawAxis axis;
1555:     PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1556:     PetscCall(PetscDrawAxisSetLabels(axis, "Linear iterations as function of time", "Time", "KSP Iterations"));
1557:     PetscCall(PetscDrawLGReset(ctx->lg));
1558:     ctx->ksp_its = 0;
1559:   }
1560:   PetscCall(TSGetKSPIterations(ts, &its));
1561:   y = its - ctx->ksp_its;
1562:   PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
1563:   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1564:     PetscCall(PetscDrawLGDraw(ctx->lg));
1565:     PetscCall(PetscDrawLGSave(ctx->lg));
1566:   }
1567:   ctx->ksp_its = its;
1568:   PetscFunctionReturn(PETSC_SUCCESS);
1569: }

1571: /*@C
1572:   TSMonitorEnvelopeCtxCreate - Creates a context for use with `TSMonitorEnvelope()`

1574:   Collective

1576:   Input Parameter:
1577: . ts - the `TS` solver object

1579:   Output Parameter:
1580: . ctx - the context

1582:   Level: intermediate

1584: .seealso: [](ch_ts), `TS`, `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`
1585: @*/
1586: PetscErrorCode TSMonitorEnvelopeCtxCreate(TS ts, TSMonitorEnvelopeCtx *ctx)
1587: {
1588:   PetscFunctionBegin;
1589:   PetscCall(PetscNew(ctx));
1590:   PetscFunctionReturn(PETSC_SUCCESS);
1591: }

1593: /*@C
1594:   TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution

1596:   Collective

1598:   Input Parameters:
1599: + ts    - the `TS` context
1600: . step  - current time-step
1601: . ptime - current time
1602: . u     - current solution
1603: - dctx  - the envelope context

1605:   Options Database Key:
1606: . -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time

1608:   Level: intermediate

1610:   Notes:
1611:   After a solve you can use `TSMonitorEnvelopeGetBounds()` to access the envelope

1613:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1614:   to be used during the `TS` integration.

1616: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxCreate()`
1617: @*/
1618: PetscErrorCode TSMonitorEnvelope(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1619: {
1620:   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;

1622:   PetscFunctionBegin;
1623:   if (!ctx->max) {
1624:     PetscCall(VecDuplicate(u, &ctx->max));
1625:     PetscCall(VecDuplicate(u, &ctx->min));
1626:     PetscCall(VecCopy(u, ctx->max));
1627:     PetscCall(VecCopy(u, ctx->min));
1628:   } else {
1629:     PetscCall(VecPointwiseMax(ctx->max, u, ctx->max));
1630:     PetscCall(VecPointwiseMin(ctx->min, u, ctx->min));
1631:   }
1632:   PetscFunctionReturn(PETSC_SUCCESS);
1633: }

1635: /*@C
1636:   TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution

1638:   Collective

1640:   Input Parameter:
1641: . ts - the `TS` context

1643:   Output Parameters:
1644: + max - the maximum values
1645: - min - the minimum values

1647:   Level: intermediate

1649:   Notes:
1650:   If the `TS` does not have a `TSMonitorEnvelopeCtx` associated with it then this function is ignored

1652: .seealso: [](ch_ts), `TSMonitorEnvelopeCtx`, `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
1653: @*/
1654: PetscErrorCode TSMonitorEnvelopeGetBounds(TS ts, Vec *max, Vec *min)
1655: {
1656:   PetscInt i;

1658:   PetscFunctionBegin;
1659:   if (max) *max = NULL;
1660:   if (min) *min = NULL;
1661:   for (i = 0; i < ts->numbermonitors; i++) {
1662:     if (ts->monitor[i] == TSMonitorEnvelope) {
1663:       TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)ts->monitorcontext[i];
1664:       if (max) *max = ctx->max;
1665:       if (min) *min = ctx->min;
1666:       break;
1667:     }
1668:   }
1669:   PetscFunctionReturn(PETSC_SUCCESS);
1670: }

1672: /*@C
1673:   TSMonitorEnvelopeCtxDestroy - Destroys a context that was created  with `TSMonitorEnvelopeCtxCreate()`.

1675:   Collective

1677:   Input Parameter:
1678: . ctx - the monitor context

1680:   Level: intermediate

1682: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
1683: @*/
1684: PetscErrorCode TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
1685: {
1686:   PetscFunctionBegin;
1687:   PetscCall(VecDestroy(&(*ctx)->min));
1688:   PetscCall(VecDestroy(&(*ctx)->max));
1689:   PetscCall(PetscFree(*ctx));
1690:   PetscFunctionReturn(PETSC_SUCCESS);
1691: }

1693: /*@C
1694:   TSDMSwarmMonitorMoments - Monitors the first three moments of a `DMSWARM` being evolved by the `TS`

1696:   Not Collective

1698:   Input Parameters:
1699: + ts   - the `TS` context
1700: . step - current timestep
1701: . t    - current time
1702: . U    - current solution
1703: - vf   - not used

1705:   Options Database Key:
1706: . -ts_dmswarm_monitor_moments - Monitor moments of particle distribution

1708:   Level: intermediate

1710:   Notes:
1711:   This requires a `DMSWARM` be attached to the `TS`.

1713:   This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1714:   to be used during the TS integration.

1716: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `DMSWARM`
1717: @*/
1718: PetscErrorCode TSDMSwarmMonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, PetscViewerAndFormat *vf)
1719: {
1720:   DM                 sw;
1721:   const PetscScalar *u;
1722:   PetscReal          m = 1.0, totE = 0., totMom[3] = {0., 0., 0.};
1723:   PetscInt           dim, d, Np, p;
1724:   MPI_Comm           comm;

1726:   PetscFunctionBeginUser;
1727:   (void)t;
1728:   (void)vf;
1729:   PetscCall(TSGetDM(ts, &sw));
1730:   if (!sw || step % ts->monitorFrequency != 0) PetscFunctionReturn(PETSC_SUCCESS);
1731:   PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
1732:   PetscCall(DMGetDimension(sw, &dim));
1733:   PetscCall(VecGetLocalSize(U, &Np));
1734:   Np /= dim;
1735:   PetscCall(VecGetArrayRead(U, &u));
1736:   for (p = 0; p < Np; ++p) {
1737:     for (d = 0; d < dim; ++d) {
1738:       totE += PetscRealPart(u[p * dim + d] * u[p * dim + d]);
1739:       totMom[d] += PetscRealPart(u[p * dim + d]);
1740:     }
1741:   }
1742:   PetscCall(VecRestoreArrayRead(U, &u));
1743:   for (d = 0; d < dim; ++d) totMom[d] *= m;
1744:   totE *= 0.5 * m;
1745:   PetscCall(PetscPrintf(comm, "Step %4" PetscInt_FMT " Total Energy: %10.8lf", step, (double)totE));
1746:   for (d = 0; d < dim; ++d) PetscCall(PetscPrintf(comm, "    Total Momentum %c: %10.8lf", (char)('x' + d), (double)totMom[d]));
1747:   PetscCall(PetscPrintf(comm, "\n"));
1748:   PetscFunctionReturn(PETSC_SUCCESS);
1749: }