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;


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

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

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

 48:    Collective

 50:    Input Parameters:
 51: +  ts - `TS` object you wish to monitor
 52: .  name - the monitor type one is seeking
 53: .  help - message indicating what monitoring is done
 54: .  manual - manual page for the monitor
 55: .  monitor - the monitor function
 56: -  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

 58:    Level: developer

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

 74:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, name, &viewer, &format, &flg);
 75:   if (flg) {
 76:     PetscViewerAndFormat *vf;
 77:     PetscViewerAndFormatCreate(viewer, format, &vf);
 78:     PetscObjectDereference((PetscObject)viewer);
 79:     if (monitorsetup) (*monitorsetup)(ts, vf);
 80:     TSMonitorSet(ts, (PetscErrorCode(*)(TS, PetscInt, PetscReal, Vec, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy);
 81:   }
 82:   return 0;
 83: }

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

 89:    Logically Collective

 91:    Input Parameters:
 92: +  ts - the `TS` context obtained from `TSCreate()`
 93: .  monitor - monitoring routine
 94: .  mctx - [optional] user-defined context for private data for the
 95:              monitor routine (use NULL if no context is desired)
 96: -  monitordestroy - [optional] routine that frees monitor context
 97:           (may be NULL)

 99:    Calling sequence of monitor:
100: $    PetscErrorCode monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)

102: +    ts - the TS context
103: .    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)
104: .    time - current time
105: .    u - current iterate
106: -    mctx - [optional] monitoring context

108:    Level: intermediate

110:    Note:
111:    This routine adds an additional monitor to the list of monitors that
112:    already has been loaded.

114:    Fortran Note:
115:     Only a single monitor function can be set for each `TS` object

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

127:   for (i = 0; i < ts->numbermonitors; i++) {
128:     PetscMonitorCompare((PetscErrorCode(*)(void))monitor, mctx, mdestroy, (PetscErrorCode(*)(void))ts->monitor[i], ts->monitorcontext[i], ts->monitordestroy[i], &identical);
129:     if (identical) return 0;
130:   }
132:   ts->monitor[ts->numbermonitors]          = monitor;
133:   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
134:   ts->monitorcontext[ts->numbermonitors++] = (void *)mctx;
135:   return 0;
136: }

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

141:    Logically Collective

143:    Input Parameters:
144: .  ts - the `TS` context obtained from `TSCreate()`

146:    Level: intermediate

148:    Note:
149:    There is no way to remove a single, specific monitor.

151: .seealso: [](chapter_ts), `TS`, `TSMonitorDefault()`, `TSMonitorSet()`
152: @*/
153: PetscErrorCode TSMonitorCancel(TS ts)
154: {
155:   PetscInt i;

158:   for (i = 0; i < ts->numbermonitors; i++) {
159:     if (ts->monitordestroy[i]) (*ts->monitordestroy[i])(&ts->monitorcontext[i]);
160:   }
161:   ts->numbermonitors = 0;
162:   return 0;
163: }

165: /*@C
166:    TSMonitorDefault - The Default monitor, prints the timestep and time for each step

168:    Options Database Key:
169: .  -ts_monitor - monitors the time integration

171:    Level: intermediate

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

177: .seealso: [](chapter_ts), `TSMonitorSet()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
178:           `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
179:           `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`, `TSDMSwarmMonitorMoments()`
180: @*/
181: PetscErrorCode TSMonitorDefault(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
182: {
183:   PetscViewer viewer = vf->viewer;
184:   PetscBool   iascii, ibinary;

187:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
188:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary);
189:   PetscViewerPushFormat(viewer, vf->format);
190:   if (iascii) {
191:     PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel);
192:     if (step == -1) { /* this indicates it is an interpolated solution */
193:       PetscViewerASCIIPrintf(viewer, "Interpolated solution at time %g between steps %" PetscInt_FMT " and %" PetscInt_FMT "\n", (double)ptime, ts->steps - 1, ts->steps);
194:     } else {
195:       PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)\n" : "\n");
196:     }
197:     PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel);
198:   } else if (ibinary) {
199:     PetscMPIInt rank;
200:     MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
201:     if (rank == 0) {
202:       PetscBool skipHeader;
203:       PetscInt  classid = REAL_FILE_CLASSID;

205:       PetscViewerBinaryGetSkipHeader(viewer, &skipHeader);
206:       if (!skipHeader) PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT);
207:       PetscRealView(1, &ptime, viewer);
208:     } else {
209:       PetscRealView(0, &ptime, viewer);
210:     }
211:   }
212:   PetscViewerPopFormat(viewer);
213:   return 0;
214: }

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

219:    Level: intermediate

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

225: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`
226: @*/
227: PetscErrorCode TSMonitorExtreme(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
228: {
229:   PetscViewer viewer = vf->viewer;
230:   PetscBool   iascii;
231:   PetscReal   max, min;

234:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
235:   PetscViewerPushFormat(viewer, vf->format);
236:   if (iascii) {
237:     VecMax(v, NULL, &max);
238:     VecMin(v, NULL, &min);
239:     PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel);
240:     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);
241:     PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel);
242:   }
243:   PetscViewerPopFormat(viewer);
244:   return 0;
245: }

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

251:    Collective

253:    Input Parameters:
254: +  host - the X display to open, or null for the local machine
255: .  label - the title to put in the title bar
256: .  x, y - the screen coordinates of the upper left coordinate of the window
257: .  m, n - the screen width and height in pixels
258: -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time

260:    Output Parameter:
261: .  ctx - the context

263:    Options Database Keys:
264: +  -ts_monitor_lg_timestep - automatically sets line graph monitor
265: +  -ts_monitor_lg_timestep_log - automatically sets line graph monitor
266: .  -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling `TSMonitorLGSetDisplayVariables()` or `TSMonitorLGCtxSetDisplayVariables()`)
267: .  -ts_monitor_lg_error -  monitor the error
268: .  -ts_monitor_lg_ksp_iterations - monitor the number of `KSP` iterations needed for each timestep
269: .  -ts_monitor_lg_snes_iterations - monitor the number of `SNES` iterations needed for each timestep
270: -  -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true

272:    Level: intermediate

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

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

279:    Many of the functions that control the monitoring have two forms: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a `TS` object as the
280:    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
281:    as the first argument.

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

285: .seealso: [](chapter_ts), `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorDefault()`, `VecView()`,
286:           `TSMonitorLGCtxCreate()`, `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
287:           `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
288:           `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGError()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
289:           `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
290: @*/
291: PetscErrorCode TSMonitorLGCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorLGCtx *ctx)
292: {
293:   PetscDraw draw;

295:   PetscNew(ctx);
296:   PetscDrawCreate(comm, host, label, x, y, m, n, &draw);
297:   PetscDrawSetFromOptions(draw);
298:   PetscDrawLGCreate(draw, 1, &(*ctx)->lg);
299:   PetscDrawLGSetFromOptions((*ctx)->lg);
300:   PetscDrawDestroy(&draw);
301:   (*ctx)->howoften = howoften;
302:   return 0;
303: }

305: PetscErrorCode TSMonitorLGTimeStep(TS ts, PetscInt step, PetscReal ptime, Vec v, void *monctx)
306: {
307:   TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
308:   PetscReal      x   = ptime, y;

310:   if (step < 0) return 0; /* -1 indicates an interpolated solution */
311:   if (!step) {
312:     PetscDrawAxis axis;
313:     const char   *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
314:     PetscDrawLGGetAxis(ctx->lg, &axis);
315:     PetscDrawAxisSetLabels(axis, "Timestep as function of time", "Time", ylabel);
316:     PetscDrawLGReset(ctx->lg);
317:   }
318:   TSGetTimeStep(ts, &y);
319:   if (ctx->semilogy) y = PetscLog10Real(y);
320:   PetscDrawLGAddPoint(ctx->lg, &x, &y);
321:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
322:     PetscDrawLGDraw(ctx->lg);
323:     PetscDrawLGSave(ctx->lg);
324:   }
325:   return 0;
326: }

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

332:    Collective

334:    Input Parameter:
335: .  ctx - the monitor context

337:    Level: intermediate

339:    Note:
340:    Pass to `TSMonitorSet()` along with the context and `TSMonitorLGTimeStep()`

342: .seealso: [](chapter_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep();`
343: @*/
344: PetscErrorCode TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
345: {
346:   if ((*ctx)->transformdestroy) ((*ctx)->transformdestroy)((*ctx)->transformctx);
347:   PetscDrawLGDestroy(&(*ctx)->lg);
348:   PetscStrArrayDestroy(&(*ctx)->names);
349:   PetscStrArrayDestroy(&(*ctx)->displaynames);
350:   PetscFree((*ctx)->displayvariables);
351:   PetscFree((*ctx)->displayvalues);
352:   PetscFree(*ctx);
353:   return 0;
354: }

356: /* Creates a TS Monitor SPCtx for use with DMSwarm particle visualizations */
357: 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, TSMonitorSPCtx *ctx)
358: {
359:   PetscDraw draw;

361:   PetscNew(ctx);
362:   PetscDrawCreate(comm, host, label, x, y, m, n, &draw);
363:   PetscDrawSetFromOptions(draw);
364:   PetscDrawSPCreate(draw, 1, &(*ctx)->sp);
365:   PetscDrawDestroy(&draw);
366:   (*ctx)->howoften = howoften;
367:   (*ctx)->retain   = retain;
368:   (*ctx)->phase    = phase;
369:   return 0;
370: }

372: /*
373:   Destroys a TSMonitorSPCtx that was created with TSMonitorSPCtxCreate
374: */
375: PetscErrorCode TSMonitorSPCtxDestroy(TSMonitorSPCtx *ctx)
376: {

378:   PetscDrawSPDestroy(&(*ctx)->sp);
379:   PetscFree(*ctx);

381:   return 0;
382: }

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

388:    Collective

390:    Input Parameters:
391: +  ts - the `TS` context
392: .  step - current time-step
393: .  ptime - current time
394: -  dummy - either a viewer or NULL

396:    Options Database Keys:
397: +   -ts_monitor_draw_solution - draw the solution at each time-step
398: -   -ts_monitor_draw_solution_initial - show initial solution as well as current solution

400:    Level: intermediate

402:    Notes:
403:    The initial solution and current solution are not displayed with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
404:    will look bad

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

409: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtxCreate()`, `TSMonitorDrawCtxDestroy()`
410: @*/
411: PetscErrorCode TSMonitorDrawSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
412: {
413:   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
414:   PetscDraw        draw;

416:   if (!step && ictx->showinitial) {
417:     if (!ictx->initialsolution) VecDuplicate(u, &ictx->initialsolution);
418:     VecCopy(u, ictx->initialsolution);
419:   }
420:   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) return 0;

422:   if (ictx->showinitial) {
423:     PetscReal pause;
424:     PetscViewerDrawGetPause(ictx->viewer, &pause);
425:     PetscViewerDrawSetPause(ictx->viewer, 0.0);
426:     VecView(ictx->initialsolution, ictx->viewer);
427:     PetscViewerDrawSetPause(ictx->viewer, pause);
428:     PetscViewerDrawSetHold(ictx->viewer, PETSC_TRUE);
429:   }
430:   VecView(u, ictx->viewer);
431:   if (ictx->showtimestepandtime) {
432:     PetscReal xl, yl, xr, yr, h;
433:     char      time[32];

435:     PetscViewerDrawGetDraw(ictx->viewer, 0, &draw);
436:     PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime);
437:     PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr);
438:     h = yl + .95 * (yr - yl);
439:     PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time);
440:     PetscDrawFlush(draw);
441:   }

443:   if (ictx->showinitial) PetscViewerDrawSetHold(ictx->viewer, PETSC_FALSE);
444:   return 0;
445: }

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

450:    Collective

452:    Input Parameters:
453: +  ts - the `TS` context
454: .  step - current time-step
455: .  ptime - current time
456: -  dummy - either a viewer or NULL

458:    Level: intermediate

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

464: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
465: @*/
466: PetscErrorCode TSMonitorDrawSolutionPhase(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
467: {
468:   TSMonitorDrawCtx   ictx = (TSMonitorDrawCtx)dummy;
469:   PetscDraw          draw;
470:   PetscDrawAxis      axis;
471:   PetscInt           n;
472:   PetscMPIInt        size;
473:   PetscReal          U0, U1, xl, yl, xr, yr, h;
474:   char               time[32];
475:   const PetscScalar *U;

477:   MPI_Comm_size(PetscObjectComm((PetscObject)ts), &size);
479:   VecGetSize(u, &n);

482:   PetscViewerDrawGetDraw(ictx->viewer, 0, &draw);
483:   PetscViewerDrawGetDrawAxis(ictx->viewer, 0, &axis);
484:   PetscDrawAxisGetLimits(axis, &xl, &xr, &yl, &yr);
485:   if (!step) {
486:     PetscDrawClear(draw);
487:     PetscDrawAxisDraw(axis);
488:   }

490:   VecGetArrayRead(u, &U);
491:   U0 = PetscRealPart(U[0]);
492:   U1 = PetscRealPart(U[1]);
493:   VecRestoreArrayRead(u, &U);
494:   if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) return 0;

496:   PetscDrawCollectiveBegin(draw);
497:   PetscDrawPoint(draw, U0, U1, PETSC_DRAW_BLACK);
498:   if (ictx->showtimestepandtime) {
499:     PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr);
500:     PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime);
501:     h = yl + .95 * (yr - yl);
502:     PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time);
503:   }
504:   PetscDrawCollectiveEnd(draw);
505:   PetscDrawFlush(draw);
506:   PetscDrawPause(draw);
507:   PetscDrawSave(draw);
508:   return 0;
509: }

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

514:    Collective

516:    Input Parameters:
517: .    ctx - the monitor context

519:    Level: intermediate

521: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawSolution()`, `TSMonitorDrawError()`, `TSMonitorDrawCtx`
522: @*/
523: PetscErrorCode TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
524: {
525:   PetscViewerDestroy(&(*ictx)->viewer);
526:   VecDestroy(&(*ictx)->initialsolution);
527:   PetscFree(*ictx);
528:   return 0;
529: }

531: /*@C
532:    TSMonitorDrawCtxCreate - Creates the monitor context for `TSMonitorDrawCtx`

534:    Collective

536:    Input Parameter:
537: .    ts - time-step context

539:    Output Parameter:
540: .    ctx - the monitor context

542:    Options Database Keys:
543: +   -ts_monitor_draw_solution - draw the solution at each time-step
544: -   -ts_monitor_draw_solution_initial - show initial solution as well as current solution

546:    Level: intermediate

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

551: .seealso: [](chapter_ts), `TS`, `TSMonitorDrawCtxDestroy()`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtx`, `PetscMonitorDrawSolution()`
552: @*/
553: PetscErrorCode TSMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorDrawCtx *ctx)
554: {
555:   PetscNew(ctx);
556:   PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer);
557:   PetscViewerSetFromOptions((*ctx)->viewer);

559:   (*ctx)->howoften    = howoften;
560:   (*ctx)->showinitial = PETSC_FALSE;
561:   PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_initial", &(*ctx)->showinitial, NULL);

563:   (*ctx)->showtimestepandtime = PETSC_FALSE;
564:   PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_show_time", &(*ctx)->showtimestepandtime, NULL);
565:   return 0;
566: }

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

572:    Collective

574:    Input Parameters:
575: +  ts - the `TS` context
576: .  step - current time-step
577: .  ptime - current time
578: -  dummy - either a viewer or NULL

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

583:    Level: intermediate

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

589: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
590: @*/
591: PetscErrorCode TSMonitorDrawSolutionFunction(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
592: {
593:   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
594:   PetscViewer      viewer = ctx->viewer;
595:   Vec              work;

597:   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) return 0;
598:   VecDuplicate(u, &work);
599:   TSComputeSolutionFunction(ts, ptime, work);
600:   VecView(work, viewer);
601:   VecDestroy(&work);
602:   return 0;
603: }

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

609:    Collective

611:    Input Parameters:
612: +  ts - the `TS` context
613: .  step - current time-step
614: .  ptime - current time
615: -  dummy - either a viewer or NULL

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

620:    Level: intermediate

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

626: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
627: @*/
628: PetscErrorCode TSMonitorDrawError(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
629: {
630:   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)dummy;
631:   PetscViewer      viewer = ctx->viewer;
632:   Vec              work;

634:   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) return 0;
635:   VecDuplicate(u, &work);
636:   TSComputeSolutionFunction(ts, ptime, work);
637:   VecAXPY(work, -1.0, u);
638:   VecView(work, viewer);
639:   VecDestroy(&work);
640:   return 0;
641: }

643: /*@C
644:    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

646:    Collective

648:    Input Parameters:
649: +  ts - the `TS` context
650: .  step - current time-step
651: .  ptime - current time
652: .  u - current state
653: -  vf - viewer and its format

655:    Level: intermediate

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

661: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
662: @*/
663: PetscErrorCode TSMonitorSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
664: {
665:   PetscViewerPushFormat(vf->viewer, vf->format);
666:   VecView(u, vf->viewer);
667:   PetscViewerPopFormat(vf->viewer);
668:   return 0;
669: }

671: /*@C
672:    TSMonitorSolutionVTK - Monitors progress of the `TS` solvers by `VecView()` for the solution at each timestep.

674:    Collective

676:    Input Parameters:
677: +  ts - the `TS` context
678: .  step - current time-step
679: .  ptime - current time
680: .  u - current state
681: -  filenametemplate - string containing a format specifier for the integer time step (e.g. %03" PetscInt_FMT ")

683:    Level: intermediate

685:    Notes:
686:    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.
687:    These are named according to the file name template.

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

692: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
693: @*/
694: PetscErrorCode TSMonitorSolutionVTK(TS ts, PetscInt step, PetscReal ptime, Vec u, void *filenametemplate)
695: {
696:   char        filename[PETSC_MAX_PATH_LEN];
697:   PetscViewer viewer;

699:   if (step < 0) return 0; /* -1 indicates interpolated solution */
700:   PetscSNPrintf(filename, sizeof(filename), (const char *)filenametemplate, step);
701:   PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts), filename, FILE_MODE_WRITE, &viewer);
702:   VecView(u, viewer);
703:   PetscViewerDestroy(&viewer);
704:   return 0;
705: }

707: /*@C
708:    TSMonitorSolutionVTKDestroy - Destroy filename template string created for use with `TSMonitorSolutionVTK()`

710:    Not Collective

712:    Input Parameters:
713: .  filenametemplate - string containing a format specifier for the integer time step (e.g. %03" PetscInt_FMT ")

715:    Level: intermediate

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

720: .seealso: [](chapter_ts), `TSMonitorSet()`, `TSMonitorSolutionVTK()`
721: @*/
722: PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
723: {
724:   PetscFree(*(char **)filenametemplate);
725:   return 0;
726: }

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

732:    Collective

734:    Input Parameters:
735: +  ts - the `TS` context
736: .  step - current time-step
737: .  ptime - current time
738: .  u - current solution
739: -  dctx - the `TSMonitorLGCtx` object that contains all the options for the monitoring, this is created with `TSMonitorLGCtxCreate()`

741:    Options Database Key:
742: .   -ts_monitor_lg_solution_variables - enable monitor of lg solution variables

744:    Level: intermediate

746:    Notes:
747:    Each process in a parallel run displays its component solutions in a separate window

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

752: .seealso: [](chapter_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
753:           `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
754:           `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGError()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
755:           `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
756: @*/
757: PetscErrorCode TSMonitorLGSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
758: {
759:   TSMonitorLGCtx     ctx = (TSMonitorLGCtx)dctx;
760:   const PetscScalar *yy;
761:   Vec                v;

763:   if (step < 0) return 0; /* -1 indicates interpolated solution */
764:   if (!step) {
765:     PetscDrawAxis axis;
766:     PetscInt      dim;
767:     PetscDrawLGGetAxis(ctx->lg, &axis);
768:     PetscDrawAxisSetLabels(axis, "Solution as function of time", "Time", "Solution");
769:     if (!ctx->names) {
770:       PetscBool flg;
771:       /* user provides names of variables to plot but no names has been set so assume names are integer values */
772:       PetscOptionsHasName(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", &flg);
773:       if (flg) {
774:         PetscInt i, n;
775:         char   **names;
776:         VecGetSize(u, &n);
777:         PetscMalloc1(n + 1, &names);
778:         for (i = 0; i < n; i++) {
779:           PetscMalloc1(5, &names[i]);
780:           PetscSNPrintf(names[i], 5, "%" PetscInt_FMT, i);
781:         }
782:         names[n]   = NULL;
783:         ctx->names = names;
784:       }
785:     }
786:     if (ctx->names && !ctx->displaynames) {
787:       char    **displaynames;
788:       PetscBool flg;
789:       VecGetLocalSize(u, &dim);
790:       PetscCalloc1(dim + 1, &displaynames);
791:       PetscOptionsGetStringArray(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", displaynames, &dim, &flg);
792:       if (flg) TSMonitorLGCtxSetDisplayVariables(ctx, (const char *const *)displaynames);
793:       PetscStrArrayDestroy(&displaynames);
794:     }
795:     if (ctx->displaynames) {
796:       PetscDrawLGSetDimension(ctx->lg, ctx->ndisplayvariables);
797:       PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->displaynames);
798:     } else if (ctx->names) {
799:       VecGetLocalSize(u, &dim);
800:       PetscDrawLGSetDimension(ctx->lg, dim);
801:       PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->names);
802:     } else {
803:       VecGetLocalSize(u, &dim);
804:       PetscDrawLGSetDimension(ctx->lg, dim);
805:     }
806:     PetscDrawLGReset(ctx->lg);
807:   }

809:   if (!ctx->transform) v = u;
810:   else (*ctx->transform)(ctx->transformctx, u, &v);
811:   VecGetArrayRead(v, &yy);
812:   if (ctx->displaynames) {
813:     PetscInt i;
814:     for (i = 0; i < ctx->ndisplayvariables; i++) ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
815:     PetscDrawLGAddCommonPoint(ctx->lg, ptime, ctx->displayvalues);
816:   } else {
817: #if defined(PETSC_USE_COMPLEX)
818:     PetscInt   i, n;
819:     PetscReal *yreal;
820:     VecGetLocalSize(v, &n);
821:     PetscMalloc1(n, &yreal);
822:     for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
823:     PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal);
824:     PetscFree(yreal);
825: #else
826:     PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy);
827: #endif
828:   }
829:   VecRestoreArrayRead(v, &yy);
830:   if (ctx->transform) VecDestroy(&v);

832:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
833:     PetscDrawLGDraw(ctx->lg);
834:     PetscDrawLGSave(ctx->lg);
835:   }
836:   return 0;
837: }

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

842:    Collective

844:    Input Parameters:
845: +  ts - the `TS` context
846: -  names - the names of the components, final string must be NULL

848:    Level: intermediate

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

853: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetVariableNames()`
854: @*/
855: PetscErrorCode TSMonitorLGSetVariableNames(TS ts, const char *const *names)
856: {
857:   PetscInt i;

859:   for (i = 0; i < ts->numbermonitors; i++) {
860:     if (ts->monitor[i] == TSMonitorLGSolution) {
861:       TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i], names);
862:       break;
863:     }
864:   }
865:   return 0;
866: }

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

871:    Collective

873:    Input Parameters:
874: +  ts - the `TS` context
875: -  names - the names of the components, final string must be NULL

877:    Level: intermediate

879: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGSetVariableNames()`
880: @*/
881: PetscErrorCode TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx, const char *const *names)
882: {
883:   PetscStrArrayDestroy(&ctx->names);
884:   PetscStrArrayallocpy(names, &ctx->names);
885:   return 0;
886: }

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

891:    Collective

893:    Input Parameter:
894: .  ts - the `TS` context

896:    Output Parameter:
897: .  names - the names of the components, final string must be NULL

899:    Level: intermediate

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

904: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
905: @*/
906: PetscErrorCode TSMonitorLGGetVariableNames(TS ts, const char *const **names)
907: {
908:   PetscInt i;

910:   *names = NULL;
911:   for (i = 0; i < ts->numbermonitors; i++) {
912:     if (ts->monitor[i] == TSMonitorLGSolution) {
913:       TSMonitorLGCtx ctx = (TSMonitorLGCtx)ts->monitorcontext[i];
914:       *names             = (const char *const *)ctx->names;
915:       break;
916:     }
917:   }
918:   return 0;
919: }

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

924:    Collective

926:    Input Parameters:
927: +  ctx - the `TSMonitorLG` context
928: -  displaynames - the names of the components, final string must be NULL

930:    Level: intermediate

932: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
933: @*/
934: PetscErrorCode TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx, const char *const *displaynames)
935: {
936:   PetscInt j = 0, k;

938:   if (!ctx->names) return 0;
939:   PetscStrArrayDestroy(&ctx->displaynames);
940:   PetscStrArrayallocpy(displaynames, &ctx->displaynames);
941:   while (displaynames[j]) j++;
942:   ctx->ndisplayvariables = j;
943:   PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvariables);
944:   PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvalues);
945:   j = 0;
946:   while (displaynames[j]) {
947:     k = 0;
948:     while (ctx->names[k]) {
949:       PetscBool flg;
950:       PetscStrcmp(displaynames[j], ctx->names[k], &flg);
951:       if (flg) {
952:         ctx->displayvariables[j] = k;
953:         break;
954:       }
955:       k++;
956:     }
957:     j++;
958:   }
959:   return 0;
960: }

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

965:    Collective

967:    Input Parameters:
968: +  ts - the `TS` context
969: -  displaynames - the names of the components, final string must be NULL

971:    Level: intermediate

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

976: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
977: @*/
978: PetscErrorCode TSMonitorLGSetDisplayVariables(TS ts, const char *const *displaynames)
979: {
980:   PetscInt i;

982:   for (i = 0; i < ts->numbermonitors; i++) {
983:     if (ts->monitor[i] == TSMonitorLGSolution) {
984:       TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i], displaynames);
985:       break;
986:     }
987:   }
988:   return 0;
989: }

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

994:    Collective

996:    Input Parameters:
997: +  ts - the `TS` context
998: .  transform - the transform function
999: .  destroy - function to destroy the optional context
1000: -  ctx - optional context used by transform function

1002:    Level: intermediate

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

1007: .seealso: [](chapter_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGCtxSetTransform()`
1008: @*/
1009: PetscErrorCode TSMonitorLGSetTransform(TS ts, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
1010: {
1011:   PetscInt i;

1013:   for (i = 0; i < ts->numbermonitors; i++) {
1014:     if (ts->monitor[i] == TSMonitorLGSolution) TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i], transform, destroy, tctx);
1015:   }
1016:   return 0;
1017: }

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

1022:    Collective

1024:    Input Parameters:
1025: +  ts - the `TS` context
1026: .  transform - the transform function
1027: .  destroy - function to destroy the optional context
1028: -  ctx - optional context used by transform function

1030:    Level: intermediate

1032: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGSetTransform()`
1033: @*/
1034: PetscErrorCode TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
1035: {
1036:   ctx->transform        = transform;
1037:   ctx->transformdestroy = destroy;
1038:   ctx->transformctx     = tctx;
1039:   return 0;
1040: }

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

1046:    Collective

1048:    Input Parameters:
1049: +  ts - the `TS` context
1050: .  step - current time-step
1051: .  ptime - current time
1052: .  u - current solution
1053: -  dctx - `TSMonitorLGCtx` object created with `TSMonitorLGCtxCreate()`

1055:    Options Database Key:
1056: .  -ts_monitor_lg_error - create a graphical monitor of error history

1058:    Level: intermediate

1060:    Notes:
1061:     Each process in a parallel run displays its component errors in a separate window

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

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

1068: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1069: @*/
1070: PetscErrorCode TSMonitorLGError(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
1071: {
1072:   TSMonitorLGCtx     ctx = (TSMonitorLGCtx)dummy;
1073:   const PetscScalar *yy;
1074:   Vec                y;

1076:   if (!step) {
1077:     PetscDrawAxis axis;
1078:     PetscInt      dim;
1079:     PetscDrawLGGetAxis(ctx->lg, &axis);
1080:     PetscDrawAxisSetLabels(axis, "Error in solution as function of time", "Time", "Error");
1081:     VecGetLocalSize(u, &dim);
1082:     PetscDrawLGSetDimension(ctx->lg, dim);
1083:     PetscDrawLGReset(ctx->lg);
1084:   }
1085:   VecDuplicate(u, &y);
1086:   TSComputeSolutionFunction(ts, ptime, y);
1087:   VecAXPY(y, -1.0, u);
1088:   VecGetArrayRead(y, &yy);
1089: #if defined(PETSC_USE_COMPLEX)
1090:   {
1091:     PetscReal *yreal;
1092:     PetscInt   i, n;
1093:     VecGetLocalSize(y, &n);
1094:     PetscMalloc1(n, &yreal);
1095:     for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
1096:     PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal);
1097:     PetscFree(yreal);
1098:   }
1099: #else
1100:   PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy);
1101: #endif
1102:   VecRestoreArrayRead(y, &yy);
1103:   VecDestroy(&y);
1104:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1105:     PetscDrawLGDraw(ctx->lg);
1106:     PetscDrawLGSave(ctx->lg);
1107:   }
1108:   return 0;
1109: }

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

1114:    Input Parameters:
1115: +  ts - the `TS` context
1116: .  step - current time-step
1117: .  ptime - current time
1118: .  u - current solution
1119: -  dctx - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorSPCtxCreate()`

1121:    Options Database Keys:
1122: + -ts_monitor_sp_swarm <n>          - Monitor the solution every n steps, or -1 for plotting only the final solution
1123: . -ts_monitor_sp_swarm_retain <n>   - Retain n old points so we can see the history, or -1 for all points
1124: - -ts_monitor_sp_swarm_phase <bool> - Plot in phase space, as opposed to coordinate space

1126:    Level: intermediate

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

1132: .seealso: [](chapter_ts), `TS`, `TSMonitoSet()`, `DMSWARM`, `TSMonitorSPCtxCreate()`
1133: @*/
1134: PetscErrorCode TSMonitorSPSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1135: {
1136:   TSMonitorSPCtx     ctx = (TSMonitorSPCtx)dctx;
1137:   PetscDraw          draw;
1138:   DM                 dm, cdm;
1139:   const PetscScalar *yy;
1140:   PetscInt           Np, p, dim = 2;

1142:   if (step < 0) return 0; /* -1 indicates interpolated solution */
1143:   if (!step) {
1144:     PetscDrawAxis axis;
1145:     PetscReal     dmboxlower[2], dmboxupper[2];

1147:     TSGetDM(ts, &dm);
1148:     DMGetDimension(dm, &dim);
1150:     DMSwarmGetCellDM(dm, &cdm);
1151:     DMGetBoundingBox(cdm, dmboxlower, dmboxupper);
1152:     VecGetLocalSize(u, &Np);
1153:     Np /= dim * 2;
1154:     PetscDrawSPGetAxis(ctx->sp, &axis);
1155:     if (ctx->phase) {
1156:       PetscDrawAxisSetLabels(axis, "Particles", "X", "V");
1157:       PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], -5, 5);
1158:     } else {
1159:       PetscDrawAxisSetLabels(axis, "Particles", "X", "Y");
1160:       PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], dmboxlower[1], dmboxupper[1]);
1161:     }
1162:     PetscDrawAxisSetHoldLimits(axis, PETSC_TRUE);
1163:     PetscDrawSPReset(ctx->sp);
1164:   }
1165:   VecGetLocalSize(u, &Np);
1166:   Np /= dim * 2;
1167:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1168:     PetscDrawSPGetDraw(ctx->sp, &draw);
1169:     if ((ctx->retain == 0) || (ctx->retain > 0 && !(step % ctx->retain))) PetscDrawClear(draw);
1170:     PetscDrawFlush(draw);
1171:     PetscDrawSPReset(ctx->sp);
1172:     VecGetArrayRead(u, &yy);
1173:     for (p = 0; p < Np; ++p) {
1174:       PetscReal x, y;

1176:       if (ctx->phase) {
1177:         x = PetscRealPart(yy[p * dim * 2]);
1178:         y = PetscRealPart(yy[p * dim * 2 + dim]);
1179:       } else {
1180:         x = PetscRealPart(yy[p * dim * 2]);
1181:         y = PetscRealPart(yy[p * dim * 2 + 1]);
1182:       }
1183:       PetscDrawSPAddPoint(ctx->sp, &x, &y);
1184:     }
1185:     VecRestoreArrayRead(u, &yy);
1186:     PetscDrawSPDraw(ctx->sp, PETSC_FALSE);
1187:     PetscDrawSPSave(ctx->sp);
1188:   }
1189:   return 0;
1190: }

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

1195:    Collective

1197:    Input Parameters:
1198: +  ts - the `TS` context
1199: .  step - current time-step
1200: .  ptime - current time
1201: .  u - current solution
1202: -  dctx - unused context

1204:    Options Database Key:
1205: .  -ts_monitor_error - create a graphical monitor of error history

1207:    Level: intermediate

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

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

1215: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1216: @*/
1217: PetscErrorCode TSMonitorError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
1218: {
1219:   DM        dm;
1220:   PetscDS   ds = NULL;
1221:   PetscInt  Nf = -1, f;
1222:   PetscBool flg;

1224:   TSGetDM(ts, &dm);
1225:   if (dm) DMGetDS(dm, &ds);
1226:   if (ds) PetscDSGetNumFields(ds, &Nf);
1227:   if (Nf <= 0) {
1228:     Vec       y;
1229:     PetscReal nrm;

1231:     VecDuplicate(u, &y);
1232:     TSComputeSolutionFunction(ts, ptime, y);
1233:     VecAXPY(y, -1.0, u);
1234:     PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERASCII, &flg);
1235:     if (flg) {
1236:       VecNorm(y, NORM_2, &nrm);
1237:       PetscViewerASCIIPrintf(vf->viewer, "2-norm of error %g\n", (double)nrm);
1238:     }
1239:     PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &flg);
1240:     if (flg) VecView(y, vf->viewer);
1241:     VecDestroy(&y);
1242:   } else {
1243:     PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx);
1244:     void    **ctxs;
1245:     Vec       v;
1246:     PetscReal ferrors[1];

1248:     PetscMalloc2(Nf, &exactFuncs, Nf, &ctxs);
1249:     for (f = 0; f < Nf; ++f) PetscDSGetExactSolution(ds, f, &exactFuncs[f], &ctxs[f]);
1250:     DMComputeL2FieldDiff(dm, ptime, exactFuncs, ctxs, u, ferrors);
1251:     PetscPrintf(PETSC_COMM_WORLD, "Timestep: %04d time = %-8.4g \t L_2 Error: [", (int)step, (double)ptime);
1252:     for (f = 0; f < Nf; ++f) {
1253:       if (f > 0) PetscPrintf(PETSC_COMM_WORLD, ", ");
1254:       PetscPrintf(PETSC_COMM_WORLD, "%2.3g", (double)ferrors[f]);
1255:     }
1256:     PetscPrintf(PETSC_COMM_WORLD, "]\n");

1258:     VecViewFromOptions(u, NULL, "-sol_vec_view");

1260:     PetscOptionsHasName(NULL, NULL, "-exact_vec_view", &flg);
1261:     if (flg) {
1262:       DMGetGlobalVector(dm, &v);
1263:       DMProjectFunction(dm, ptime, exactFuncs, ctxs, INSERT_ALL_VALUES, v);
1264:       PetscObjectSetName((PetscObject)v, "Exact Solution");
1265:       VecViewFromOptions(v, NULL, "-exact_vec_view");
1266:       DMRestoreGlobalVector(dm, &v);
1267:     }
1268:     PetscFree2(exactFuncs, ctxs);
1269:   }
1270:   return 0;
1271: }

1273: PetscErrorCode TSMonitorLGSNESIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, void *monctx)
1274: {
1275:   TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1276:   PetscReal      x   = ptime, y;
1277:   PetscInt       its;

1279:   if (n < 0) return 0; /* -1 indicates interpolated solution */
1280:   if (!n) {
1281:     PetscDrawAxis axis;
1282:     PetscDrawLGGetAxis(ctx->lg, &axis);
1283:     PetscDrawAxisSetLabels(axis, "Nonlinear iterations as function of time", "Time", "SNES Iterations");
1284:     PetscDrawLGReset(ctx->lg);
1285:     ctx->snes_its = 0;
1286:   }
1287:   TSGetSNESIterations(ts, &its);
1288:   y = its - ctx->snes_its;
1289:   PetscDrawLGAddPoint(ctx->lg, &x, &y);
1290:   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1291:     PetscDrawLGDraw(ctx->lg);
1292:     PetscDrawLGSave(ctx->lg);
1293:   }
1294:   ctx->snes_its = its;
1295:   return 0;
1296: }

1298: PetscErrorCode TSMonitorLGKSPIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, void *monctx)
1299: {
1300:   TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1301:   PetscReal      x   = ptime, y;
1302:   PetscInt       its;

1304:   if (n < 0) return 0; /* -1 indicates interpolated solution */
1305:   if (!n) {
1306:     PetscDrawAxis axis;
1307:     PetscDrawLGGetAxis(ctx->lg, &axis);
1308:     PetscDrawAxisSetLabels(axis, "Linear iterations as function of time", "Time", "KSP Iterations");
1309:     PetscDrawLGReset(ctx->lg);
1310:     ctx->ksp_its = 0;
1311:   }
1312:   TSGetKSPIterations(ts, &its);
1313:   y = its - ctx->ksp_its;
1314:   PetscDrawLGAddPoint(ctx->lg, &x, &y);
1315:   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1316:     PetscDrawLGDraw(ctx->lg);
1317:     PetscDrawLGSave(ctx->lg);
1318:   }
1319:   ctx->ksp_its = its;
1320:   return 0;
1321: }

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

1326:    Collective

1328:    Input Parameters:
1329: .  ts  - the `TS` solver object

1331:    Output Parameter:
1332: .  ctx - the context

1334:    Level: intermediate

1336: .seealso: [](chapter_ts), `TS`, `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`
1337: @*/
1338: PetscErrorCode TSMonitorEnvelopeCtxCreate(TS ts, TSMonitorEnvelopeCtx *ctx)
1339: {
1340:   PetscNew(ctx);
1341:   return 0;
1342: }

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

1347:    Collective

1349:    Input Parameters:
1350: +  ts - the TS context
1351: .  step - current time-step
1352: .  ptime - current time
1353: .  u  - current solution
1354: -  dctx - the envelope context

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

1359:    Level: intermediate

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

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

1367: .seealso: [](chapter_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxCreate()`
1368: @*/
1369: PetscErrorCode TSMonitorEnvelope(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1370: {
1371:   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;

1373:   if (!ctx->max) {
1374:     VecDuplicate(u, &ctx->max);
1375:     VecDuplicate(u, &ctx->min);
1376:     VecCopy(u, ctx->max);
1377:     VecCopy(u, ctx->min);
1378:   } else {
1379:     VecPointwiseMax(ctx->max, u, ctx->max);
1380:     VecPointwiseMin(ctx->min, u, ctx->min);
1381:   }
1382:   return 0;
1383: }

1385: /*@C
1386:    TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution

1388:    Collective

1390:    Input Parameter:
1391: .  ts - the `TS` context

1393:    Output Parameters:
1394: +  max - the maximum values
1395: -  min - the minimum values

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

1400:    Level: intermediate

1402: .seealso: [](chapter_ts), `TSMonitorEnvelopeCtx`, `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
1403: @*/
1404: PetscErrorCode TSMonitorEnvelopeGetBounds(TS ts, Vec *max, Vec *min)
1405: {
1406:   PetscInt i;

1408:   if (max) *max = NULL;
1409:   if (min) *min = NULL;
1410:   for (i = 0; i < ts->numbermonitors; i++) {
1411:     if (ts->monitor[i] == TSMonitorEnvelope) {
1412:       TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)ts->monitorcontext[i];
1413:       if (max) *max = ctx->max;
1414:       if (min) *min = ctx->min;
1415:       break;
1416:     }
1417:   }
1418:   return 0;
1419: }

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

1424:    Collective

1426:    Input Parameter:
1427: .  ctx - the monitor context

1429:    Level: intermediate

1431: .seealso: [](chapter_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
1432: @*/
1433: PetscErrorCode TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
1434: {
1435:   VecDestroy(&(*ctx)->min);
1436:   VecDestroy(&(*ctx)->max);
1437:   PetscFree(*ctx);
1438:   return 0;
1439: }

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

1444:   Not collective

1446:   Input Parameters:
1447: + ts   - the `TS` context
1448: . step - current timestep
1449: . t    - current time
1450: . u    - current solution
1451: - ctx  - not used

1453:   Options Database Key:
1454: . -ts_dmswarm_monitor_moments - Monitor moments of particle distribution

1456:   Level: intermediate

1458:   Notes:
1459:   This requires a `DMSWARM` be attached to the `TS`.

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

1464: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `DMSWARM`
1465: @*/
1466: PetscErrorCode TSDMSwarmMonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, PetscViewerAndFormat *vf)
1467: {
1468:   DM                 sw;
1469:   const PetscScalar *u;
1470:   PetscReal          m = 1.0, totE = 0., totMom[3] = {0., 0., 0.};
1471:   PetscInt           dim, d, Np, p;
1472:   MPI_Comm           comm;

1475:   TSGetDM(ts, &sw);
1476:   if (!sw || step % ts->monitorFrequency != 0) return 0;
1477:   PetscObjectGetComm((PetscObject)ts, &comm);
1478:   DMGetDimension(sw, &dim);
1479:   VecGetLocalSize(U, &Np);
1480:   Np /= dim;
1481:   VecGetArrayRead(U, &u);
1482:   for (p = 0; p < Np; ++p) {
1483:     for (d = 0; d < dim; ++d) {
1484:       totE += PetscRealPart(u[p * dim + d] * u[p * dim + d]);
1485:       totMom[d] += PetscRealPart(u[p * dim + d]);
1486:     }
1487:   }
1488:   VecRestoreArrayRead(U, &u);
1489:   for (d = 0; d < dim; ++d) totMom[d] *= m;
1490:   totE *= 0.5 * m;
1491:   PetscPrintf(comm, "Step %4" PetscInt_FMT " Total Energy: %10.8lf", step, (double)totE);
1492:   for (d = 0; d < dim; ++d) PetscPrintf(comm, "    Total Momentum %c: %10.8lf", (char)('x' + d), (double)totMom[d]);
1493:   PetscPrintf(comm, "\n");
1494:   return 0;
1495: }