Date: 2026-07-30T21:14:30+00:00

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, this must use a `PetscViewerFormat` as its context
     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:   Calling sequence of `monitor`:
     60: + ts   - the `TS` to monitor
     61: . step - the current time-step
     62: . time - the current time
     63: . u    - the current solution
     64: - vf   - the `PetscViewer` and format to monitor with

     66:   Calling sequence of `monitorsetup`:
     67: + ts - the `TS` to monitor
     68: - vf - the `PetscViewer` and format to monitor with

     70:   Level: developer

     72: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
     73:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
     74:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
     75:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
     76:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
     77:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
     78:           `PetscOptionsFList()`, `PetscOptionsEList()`
     79: @*/
     80: PetscErrorCode TSMonitorSetFromOptions(TS ts, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(TS ts, PetscInt step, PetscReal time, Vec u, PetscViewerAndFormat *vf), PetscErrorCode (*monitorsetup)(TS ts, PetscViewerAndFormat *vf))
     81: {
     82:   PetscViewer       viewer;
     83:   PetscViewerFormat format;
     84:   PetscBool         flg;

     86:   PetscFunctionBegin;
     87:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, name, &viewer, &format, &flg));
     88:   if (flg) {
     89:     PetscViewerAndFormat *vf;
     90:     char                  interval_key[1024];

     92:     PetscCall(PetscSNPrintf(interval_key, sizeof interval_key, "%s_interval", name));
     93:     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
     94:     vf->view_interval = 1;
     95:     PetscCall(PetscOptionsGetInt(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, interval_key, &vf->view_interval, NULL));

     97:     PetscCall(PetscViewerDestroy(&viewer));
     98:     if (monitorsetup) PetscCall((*monitorsetup)(ts, vf));
     99:     PetscCall(TSMonitorSet(ts, (PetscErrorCode (*)(TS, PetscInt, PetscReal, Vec, PetscCtx))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
    100:   }
    101:   PetscFunctionReturn(PETSC_SUCCESS);
    102: }

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

    108:   Logically Collective

    110:   Input Parameters:
    111: + ts       - the `TS` context obtained from `TSCreate()`
    112: . monitor  - monitoring routine
    113: . mctx     - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
    114: - mdestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence

    116:   Calling sequence of `monitor`:
    117: + ts    - the `TS` context
    118: . 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)
    119: . time  - current time
    120: . u     - current iterate
    121: - ctx   - [optional] monitoring context

    123:   Level: intermediate

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

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

    131: .seealso: [](ch_ts), `TSMonitorDefault()`, `TSMonitorCancel()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
    132:           `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
    133:           `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`, `PetscCtxDestroyFn`
    134: @*/
    135: PetscErrorCode TSMonitorSet(TS ts, PetscErrorCode (*monitor)(TS ts, PetscInt steps, PetscReal time, Vec u, PetscCtx ctx), PetscCtx mctx, PetscCtxDestroyFn *mdestroy)
    136: {
    137:   PetscFunctionBegin;
    139:   for (PetscInt i = 0; i < ts->numbermonitors; i++) {
    140:     PetscBool identical;

    142:     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)monitor, mctx, mdestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)ts->monitor[i], ts->monitorcontext[i], ts->monitordestroy[i], &identical));
    143:     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
    144:   }
    145:   PetscCheck(ts->numbermonitors < MAXTSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
    146:   ts->monitor[ts->numbermonitors]          = monitor;
    147:   ts->monitordestroy[ts->numbermonitors]   = mdestroy;
    148:   ts->monitorcontext[ts->numbermonitors++] = mctx;
    149:   PetscFunctionReturn(PETSC_SUCCESS);
    150: }

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

    155:   Logically Collective

    157:   Input Parameter:
    158: . ts - the `TS` context obtained from `TSCreate()`

    160:   Level: intermediate

    162:   Note:
    163:   There is no way to remove a single, specific monitor.

    165: .seealso: [](ch_ts), `TS`, `TSMonitorDefault()`, `TSMonitorSet()`
    166: @*/
    167: PetscErrorCode TSMonitorCancel(TS ts)
    168: {
    169:   PetscInt i;

    171:   PetscFunctionBegin;
    173:   for (i = 0; i < ts->numbermonitors; i++) {
    174:     if (ts->monitordestroy[i]) PetscCall((*ts->monitordestroy[i])(&ts->monitorcontext[i]));
    175:   }
    176:   ts->numbermonitors = 0;
    177:   PetscFunctionReturn(PETSC_SUCCESS);
    178: }

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

    183:   Input Parameters:
    184: + ts    - the `TS` context
    185: . 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)
    186: . ptime - current time
    187: . v     - current iterate
    188: - vf    - the viewer and format

    190:   Options Database Key:
    191: . -ts_monitor - monitors the time integration

    193:   Level: intermediate

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

    199: .seealso: [](ch_ts), `TSMonitorSet()`, `TSDMSwarmMonitorMoments()`, `TSMonitorWallClockTime()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
    200:           `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
    201:           `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`
    202: @*/
    203: PetscErrorCode TSMonitorDefault(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
    204: {
    205:   PetscViewer viewer = vf->viewer;
    206:   PetscBool   isascii, ibinary;

    208:   PetscFunctionBegin;
    210:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
    211:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
    212:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
    213:   if (isascii) {
    214:     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
    215:     if (step == -1) { /* this indicates it is an interpolated solution */
    216:       PetscCall(PetscViewerASCIIPrintf(viewer, "Interpolated solution at time %g between steps %" PetscInt_FMT " and %" PetscInt_FMT "\n", (double)ptime, ts->steps - 1, ts->steps));
    217:     } else {
    218:       PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)\n" : "\n"));
    219:     }
    220:     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
    221:   } else if (ibinary) {
    222:     PetscMPIInt rank;
    223:     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
    224:     if (rank == 0) {
    225:       PetscBool skipHeader;
    226:       PetscInt  classid = REAL_FILE_CLASSID;

    228:       PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
    229:       if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
    230:       PetscCall(PetscRealView(1, &ptime, viewer));
    231:     } else {
    232:       PetscCall(PetscRealView(0, &ptime, viewer));
    233:     }
    234:   }
    235:   PetscCall(PetscViewerPopFormat(viewer));
    236:   PetscFunctionReturn(PETSC_SUCCESS);
    237: }

    239: typedef struct {
    240:   PetscLogDouble time_start;
    241:   PetscLogDouble time_last;
    242:   PetscInt       snes_its;
    243:   PetscInt       ksp_its;
    244: } *TSMonitorWallClockTimeContext;

    246: /*@C
    247:   TSMonitorWallClockTimeSetUp - Setup routine passed to `TSMonitorSetFromOptions()` when using `-ts_monitor_wall_clock_time`

    249:   Input Parameters:
    250: + ts - the `TS` context
    251: - vf - the viewer and format

    253:   Level: intermediate

    255:   Note:
    256:   This is not called directly by users, rather one calls `TSMonitorSetFromOptions()`, with `TSMonitorWallClockTime()` and this function as arguments, to cause the monitor
    257:   to be used during the `TS` integration.

    259: .seealso: [](ch_ts), `TSMonitorSet()`
    260: @*/
    261: PetscErrorCode TSMonitorWallClockTimeSetUp(TS ts, PetscViewerAndFormat *vf)
    262: {
    263:   TSMonitorWallClockTimeContext speed;

    265:   PetscFunctionBegin;
    266:   PetscCall(PetscNew(&speed));
    267:   speed->time_start = PETSC_DECIDE;
    268:   vf->data_destroy  = PetscCtxDestroyDefault;
    269:   vf->data          = speed;
    270:   PetscFunctionReturn(PETSC_SUCCESS);
    271: }

    273: /*@C
    274:   TSMonitorWallClockTime - Monitor wall-clock time, KSP iterations, and SNES iterations per step.

    276:   Input Parameters:
    277: + ts    - the `TS` context
    278: . 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)
    279: . ptime - current time
    280: . v     - current solution
    281: - vf    - the viewer and format

    283:   Options Database Key:
    284: . -ts_monitor_wall_clock_time - Monitor wall-clock time, KSP iterations, and SNES iterations per step.

    286:   Level: intermediate

    288:   Note:
    289:   This is not called directly by users, rather one calls `TSMonitorSetFromOptions()`, with this function and `TSMonitorWallClockTimeSetUp()` as arguments, to cause the monitor
    290:   to be used during the `TS` integration.

    292: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
    293:           `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
    294:           `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`, `TSDMSwarmMonitorMoments()`
    295: @*/
    296: PetscErrorCode TSMonitorWallClockTime(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
    297: {
    298:   PetscViewer                   viewer = vf->viewer;
    299:   TSMonitorWallClockTimeContext speed  = (TSMonitorWallClockTimeContext)vf->data;
    300:   PetscBool                     isascii;
    301:   PetscLogDouble                now;
    302:   PetscInt                      snes_its, ksp_its;

    304:   PetscFunctionBegin;
    306:   PetscCall(PetscTime(&now));
    307:   if (speed->time_start == PETSC_DECIDE) {
    308:     speed->time_start = now;
    309:     speed->time_last  = now;
    310:   }
    311:   PetscCall(TSGetSNESIterations(ts, &snes_its));
    312:   PetscCall(TSGetKSPIterations(ts, &ksp_its));
    313:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
    314:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
    315:   if (isascii) {
    316:     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
    317:     PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s elapsed %.6f of %.6f snes %" PetscInt_FMT " ksp %" PetscInt_FMT "\n", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)" : "", now - speed->time_last,
    318:                                      now - speed->time_start, snes_its - speed->snes_its, ksp_its - speed->ksp_its));
    319:     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
    320:   }
    321:   PetscCall(PetscViewerPopFormat(viewer));
    322:   speed->time_last = now;
    323:   speed->snes_its  = snes_its;
    324:   speed->ksp_its   = ksp_its;
    325:   PetscFunctionReturn(PETSC_SUCCESS);
    326: }

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

    331:   Input Parameters:
    332: + ts    - the `TS` context
    333: . 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)
    334: . ptime - current time
    335: . v     - current iterate
    336: - vf    - the viewer and format

    338:   Level: intermediate

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

    344: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`
    345: @*/
    346: PetscErrorCode TSMonitorExtreme(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
    347: {
    348:   PetscViewer viewer = vf->viewer;
    349:   PetscBool   isascii;
    350:   PetscReal   max, min;

    352:   PetscFunctionBegin;
    354:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
    355:   PetscCall(PetscViewerPushFormat(viewer, vf->format));
    356:   if (isascii) {
    357:     PetscCall(VecMax(v, NULL, &max));
    358:     PetscCall(VecMin(v, NULL, &min));
    359:     PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
    360:     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));
    361:     PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
    362:   }
    363:   PetscCall(PetscViewerPopFormat(viewer));
    364:   PetscFunctionReturn(PETSC_SUCCESS);
    365: }

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

    371:   Collective

    373:   Input Parameters:
    374: + comm     - the MPI communicator to use
    375: . host     - the X display to open, or `NULL` for the local machine
    376: . label    - the title to put in the title bar
    377: . x        - the x screen coordinates of the upper left coordinate of the window
    378: . y        - the y screen coordinates of the upper left coordinate of the window
    379: . m        - the screen width in pixels
    380: . n        - the screen height in pixels
    381: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time

    383:   Output Parameter:
    384: . ctx - the context

    386:   Options Database Keys:
    387: + -ts_monitor_lg_timestep        - automatically sets line graph monitor
    388: . -ts_monitor_lg_timestep_log    - automatically sets line graph monitor
    389: . -ts_monitor_lg_solution        - monitor the solution (or certain values of the solution by calling `TSMonitorLGSetDisplayVariables()` or `TSMonitorLGCtxSetDisplayVariables()`)
    390: . -ts_monitor_lg_error           - monitor the error
    391: . -ts_monitor_lg_ksp_iterations  - monitor the number of `KSP` iterations needed for each timestep
    392: . -ts_monitor_lg_snes_iterations - monitor the number of `SNES` iterations needed for each timestep
    393: - -lg_use_markers (true|false)   - mark the data points (at each time step) on the plot; default is true

    395:   Level: intermediate

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

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

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

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

    408: .seealso: [](ch_ts), `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorDefault()`, `VecView()`,
    409:           `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
    410:           `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
    411:           `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
    412:           `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
    413: @*/
    414: PetscErrorCode TSMonitorLGCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorLGCtx *ctx)
    415: {
    416:   PetscDraw draw;

    418:   PetscFunctionBegin;
    419:   PetscCall(PetscNew(ctx));
    420:   PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
    421:   PetscCall(PetscDrawSetFromOptions(draw));
    422:   PetscCall(PetscDrawLGCreate(draw, 1, &(*ctx)->lg));
    423:   PetscCall(PetscDrawLGSetFromOptions((*ctx)->lg));
    424:   PetscCall(PetscDrawDestroy(&draw));
    425:   (*ctx)->howoften = howoften;
    426:   PetscFunctionReturn(PETSC_SUCCESS);
    427: }

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

    432:   Collective

    434:   Input Parameters:
    435: + ts     - the time integrator
    436: . step   - the current time step
    437: . ptime  - the current time
    438: . v      - the current state
    439: - monctx - the monitor context obtained with `TSMonitorLGCtxCreate()`

    441:   Level: advanced

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

    447: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGCtxDestroy()`
    448: @*/
    449: PetscErrorCode TSMonitorLGTimeStep(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscCtx monctx)
    450: {
    451:   TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
    452:   PetscReal      x   = ptime, y;

    454:   PetscFunctionBegin;
    455:   if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates an interpolated solution */
    456:   if (!step) {
    457:     PetscDrawAxis axis;
    458:     const char   *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
    459:     PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
    460:     PetscCall(PetscDrawAxisSetLabels(axis, "Timestep as function of time", "Time", ylabel));
    461:     PetscCall(PetscDrawLGReset(ctx->lg));
    462:   }
    463:   PetscCall(TSGetTimeStep(ts, &y));
    464:   if (ctx->semilogy) y = PetscLog10Real(y);
    465:   PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
    466:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
    467:     PetscCall(PetscDrawLGDraw(ctx->lg));
    468:     PetscCall(PetscDrawLGSave(ctx->lg));
    469:   }
    470:   PetscFunctionReturn(PETSC_SUCCESS);
    471: }

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

    476:   Collective

    478:   Input Parameter:
    479: . ctx - the monitor context

    481:   Level: intermediate

    483:   Note:
    484:   Pass to `TSMonitorSet()` along with the context and `TSMonitorLGTimeStep()`

    486: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
    487: @*/
    488: PetscErrorCode TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
    489: {
    490:   PetscFunctionBegin;
    491:   if ((*ctx)->transformdestroy) PetscCall(((*ctx)->transformdestroy)(&(*ctx)->transformctx));
    492:   PetscCall(PetscDrawLGDestroy(&(*ctx)->lg));
    493:   PetscCall(PetscStrArrayDestroy(&(*ctx)->names));
    494:   PetscCall(PetscStrArrayDestroy(&(*ctx)->displaynames));
    495:   PetscCall(PetscFree((*ctx)->displayvariables));
    496:   PetscCall(PetscFree((*ctx)->displayvalues));
    497:   PetscCall(PetscFree(*ctx));
    498:   PetscFunctionReturn(PETSC_SUCCESS);
    499: }

    501: /*@C
    502:   TSMonitorSPCtxCreate - Creates a `TSMonitorSPCtx` scatter-plot monitor context for use with `DMSWARM` particle visualizations

    504:   Collective

    506:   Input Parameters:
    507: + comm         - the MPI communicator to use
    508: . host         - the X display to open, or `NULL` for the local machine
    509: . label        - the title to put in the title bar
    510: . x            - the x screen coordinates of the upper left coordinate of the window
    511: . y            - the y screen coordinates of the upper left coordinate of the window
    512: . m            - the screen width in pixels
    513: . n            - the screen height in pixels
    514: . howoften     - if positive then determines the frequency of the plotting, if -1 then only at the final time
    515: . retain       - the number of old points to retain in the plot, or 0 to clear, or -1 to retain all
    516: . phase        - `PETSC_TRUE` to plot in phase space rather than coordinate space
    517: - multispecies - `PETSC_TRUE` to color particles by species

    519:   Output Parameter:
    520: . ctx - the newly created scatter plot monitor context

    522:   Level: intermediate

    524:   Note:
    525:   Pass this context and `TSMonitorSPCtxDestroy()` to `TSMonitorSet()` with `TSMonitorSPSwarmSolution()` to display particles during the integration.

    527: .seealso: [](ch_ts), `TS`, `DMSWARM`, `TSMonitorSet()`, `TSMonitorSPSwarmSolution()`, `TSMonitorSPCtxDestroy()`
    528: @*/
    529: 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)
    530: {
    531:   PetscDraw draw;

    533:   PetscFunctionBegin;
    534:   PetscCall(PetscNew(ctx));
    535:   PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
    536:   PetscCall(PetscDrawSetFromOptions(draw));
    537:   PetscCall(PetscDrawSPCreate(draw, 1, &(*ctx)->sp));
    538:   PetscCall(PetscDrawDestroy(&draw));
    539:   (*ctx)->howoften     = howoften;
    540:   (*ctx)->retain       = retain;
    541:   (*ctx)->phase        = phase;
    542:   (*ctx)->multispecies = multispecies;
    543:   PetscFunctionReturn(PETSC_SUCCESS);
    544: }

    546: /*@C
    547:   TSMonitorSPCtxDestroy - Destroys a `TSMonitorSPCtx` that was created with `TSMonitorSPCtxCreate()`

    549:   Not Collective

    551:   Input Parameter:
    552: . ctx - the scatter plot monitor context

    554:   Level: intermediate

    556: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorSPCtxCreate()`, `TSMonitorSPSwarmSolution()`
    557: @*/
    558: PetscErrorCode TSMonitorSPCtxDestroy(TSMonitorSPCtx *ctx)
    559: {
    560:   PetscFunctionBegin;
    561:   PetscCall(PetscDrawSPDestroy(&(*ctx)->sp));
    562:   PetscCall(PetscFree(*ctx));
    563:   PetscFunctionReturn(PETSC_SUCCESS);
    564: }

    566: /*@C
    567:   TSMonitorHGCtxCreate - Creates a `TSMonitorHGCtx` histogram monitor context for use with `DMSWARM` particle visualizations

    569:   Collective

    571:   Input Parameters:
    572: + comm     - the MPI communicator to use
    573: . host     - the X display to open, or `NULL` for the local machine
    574: . label    - the title to put in the title bar
    575: . x        - the x screen coordinates of the upper left coordinate of the window
    576: . y        - the y screen coordinates of the upper left coordinate of the window
    577: . m        - the screen width in pixels
    578: . n        - the screen height in pixels
    579: . howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
    580: . Ns       - the number of species to histogram
    581: . Nb       - the number of histogram bins
    582: - velocity - `PETSC_TRUE` to plot histograms in velocity space, `PETSC_FALSE` for coordinate space

    584:   Output Parameter:
    585: . ctx - the newly created histogram monitor context

    587:   Level: intermediate

    589:   Note:
    590:   Pass this context and `TSMonitorHGCtxDestroy()` to `TSMonitorSet()` with `TSMonitorHGSwarmSolution()` to display particle histograms during integration.

    592: .seealso: [](ch_ts), `TS`, `DMSWARM`, `TSMonitorSet()`, `TSMonitorHGSwarmSolution()`, `TSMonitorHGCtxDestroy()`
    593: @*/
    594: 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)
    595: {
    596:   PetscDraw draw;
    597:   int       Nsi, Nbi;

    599:   PetscFunctionBegin;
    600:   PetscCall(PetscMPIIntCast(Ns, &Nsi));
    601:   PetscCall(PetscMPIIntCast(Nb, &Nbi));
    602:   PetscCall(PetscNew(ctx));
    603:   PetscCall(PetscMalloc1(Ns, &(*ctx)->hg));
    604:   for (int s = 0; s < Nsi; ++s) {
    605:     PetscCall(PetscDrawCreate(comm, host, label, x + s * m, y, m, n, &draw));
    606:     PetscCall(PetscDrawSetFromOptions(draw));
    607:     PetscCall(PetscDrawHGCreate(draw, Nbi, &(*ctx)->hg[s]));
    608:     PetscCall(PetscDrawHGCalcStats((*ctx)->hg[s], PETSC_TRUE));
    609:     PetscCall(PetscDrawDestroy(&draw));
    610:   }
    611:   (*ctx)->howoften = howoften;
    612:   (*ctx)->Ns       = Ns;
    613:   (*ctx)->velocity = velocity;
    614:   PetscFunctionReturn(PETSC_SUCCESS);
    615: }

    617: /*@C
    618:   TSMonitorHGCtxDestroy - Destroys a `TSMonitorHGCtx` that was created with `TSMonitorHGCtxCreate()`

    620:   Not Collective

    622:   Input Parameter:
    623: . ctx - the histogram monitor context

    625:   Level: intermediate

    627: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorHGCtxCreate()`, `TSMonitorHGSwarmSolution()`
    628: @*/
    629: PetscErrorCode TSMonitorHGCtxDestroy(TSMonitorHGCtx *ctx)
    630: {
    631:   PetscInt s;

    633:   PetscFunctionBegin;
    634:   for (s = 0; s < (*ctx)->Ns; ++s) PetscCall(PetscDrawHGDestroy(&(*ctx)->hg[s]));
    635:   PetscCall(PetscFree((*ctx)->hg));
    636:   PetscCall(PetscFree(*ctx));
    637:   PetscFunctionReturn(PETSC_SUCCESS);
    638: }

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

    644:   Collective

    646:   Input Parameters:
    647: + ts    - the `TS` context
    648: . step  - current time-step
    649: . ptime - current time
    650: . u     - the solution at the current time
    651: - ctx   - either a viewer or `NULL`

    653:   Options Database Keys:
    654: + -ts_monitor_draw_solution         - draw the solution at each time-step
    655: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution

    657:   Level: intermediate

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

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

    666: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtxCreate()`, `TSMonitorDrawCtxDestroy()`
    667: @*/
    668: PetscErrorCode TSMonitorDrawSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx ctx)
    669: {
    670:   TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)ctx;
    671:   PetscDraw        draw;

    673:   PetscFunctionBegin;
    674:   if (!step && ictx->showinitial) {
    675:     if (!ictx->initialsolution) PetscCall(VecDuplicate(u, &ictx->initialsolution));
    676:     PetscCall(VecCopy(u, ictx->initialsolution));
    677:   }
    678:   if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);

    680:   if (ictx->showinitial) {
    681:     PetscReal pause;
    682:     PetscCall(PetscViewerDrawGetPause(ictx->viewer, &pause));
    683:     PetscCall(PetscViewerDrawSetPause(ictx->viewer, 0.0));
    684:     PetscCall(VecView(ictx->initialsolution, ictx->viewer));
    685:     PetscCall(PetscViewerDrawSetPause(ictx->viewer, pause));
    686:     PetscCall(PetscViewerDrawSetHold(ictx->viewer, PETSC_TRUE));
    687:   }
    688:   PetscCall(VecView(u, ictx->viewer));
    689:   if (ictx->showtimestepandtime) {
    690:     PetscReal xl, yl, xr, yr, h;
    691:     char      time[32];

    693:     PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
    694:     PetscCall(PetscSNPrintf(time, 32, "Timestep %" PetscInt_FMT " Time %g", step, (double)ptime));
    695:     PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
    696:     h = yl + .95 * (yr - yl);
    697:     PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
    698:     PetscCall(PetscDrawFlush(draw));
    699:   }

    701:   if (ictx->showinitial) PetscCall(PetscViewerDrawSetHold(ictx->viewer, PETSC_FALSE));
    702:   PetscFunctionReturn(PETSC_SUCCESS);
    703: }

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

    708:   Collective

    710:   Input Parameters:
    711: + ts    - the `TS` context
    712: . step  - current time-step
    713: . ptime - current time
    714: . u     - the solution at the current time
    715: - ctx   - either a viewer or `NULL`

    717:   Level: intermediate

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

    723: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
    724: @*/
    725: PetscErrorCode TSMonitorDrawSolutionPhase(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx ctx)
    726: {
    727:   TSMonitorDrawCtx   ictx = (TSMonitorDrawCtx)ctx;
    728:   PetscDraw          draw;
    729:   PetscDrawAxis      axis;
    730:   PetscInt           n;
    731:   PetscMPIInt        size;
    732:   PetscReal          U0, U1, xl, yl, xr, yr, h;
    733:   char               time[32];
    734:   const PetscScalar *U;

    736:   PetscFunctionBegin;
    737:   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)ts), &size));
    738:   PetscCheck(size == 1, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only allowed for sequential runs");
    739:   PetscCall(VecGetSize(u, &n));
    740:   PetscCheck(n == 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only for ODEs with two unknowns");

    742:   PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
    743:   PetscCall(PetscViewerDrawGetDrawAxis(ictx->viewer, 0, &axis));
    744:   PetscCall(PetscDrawAxisGetLimits(axis, &xl, &xr, &yl, &yr));
    745:   if (!step) {
    746:     PetscCall(PetscDrawClear(draw));
    747:     PetscCall(PetscDrawAxisDraw(axis));
    748:   }

    750:   PetscCall(VecGetArrayRead(u, &U));
    751:   U0 = PetscRealPart(U[0]);
    752:   U1 = PetscRealPart(U[1]);
    753:   PetscCall(VecRestoreArrayRead(u, &U));
    754:   if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(PETSC_SUCCESS);

    756:   PetscDrawCollectiveBegin(draw);
    757:   PetscCall(PetscDrawPoint(draw, U0, U1, PETSC_DRAW_BLACK));
    758:   if (ictx->showtimestepandtime) {
    759:     PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
    760:     PetscCall(PetscSNPrintf(time, 32, "Timestep %" PetscInt_FMT " Time %g", step, (double)ptime));
    761:     h = yl + .95 * (yr - yl);
    762:     PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
    763:   }
    764:   PetscDrawCollectiveEnd(draw);
    765:   PetscCall(PetscDrawFlush(draw));
    766:   PetscCall(PetscDrawPause(draw));
    767:   PetscCall(PetscDrawSave(draw));
    768:   PetscFunctionReturn(PETSC_SUCCESS);
    769: }

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

    774:   Collective

    776:   Input Parameter:
    777: . ictx - the monitor context

    779:   Level: intermediate

    781: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawSolution()`, `TSMonitorDrawError()`, `TSMonitorDrawCtx`
    782: @*/
    783: PetscErrorCode TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
    784: {
    785:   PetscFunctionBegin;
    786:   PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
    787:   PetscCall(VecDestroy(&(*ictx)->initialsolution));
    788:   PetscCall(PetscFree(*ictx));
    789:   PetscFunctionReturn(PETSC_SUCCESS);
    790: }

    792: /*@C
    793:   TSMonitorDrawCtxCreate - Creates the monitor context for `TSMonitorDrawCtx`

    795:   Collective

    797:   Input Parameters:
    798: + comm     - the MPI communicator to use
    799: . host     - the X display to open, or `NULL` for the local machine
    800: . label    - the title to put in the title bar
    801: . x        - the x screen coordinates of the upper left coordinate of the window
    802: . y        - the y screen coordinates of the upper left coordinate of the window
    803: . m        - the screen width in pixels
    804: . n        - the screen height in pixels
    805: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time

    807:   Output Parameter:
    808: . ctx - the monitor context

    810:   Options Database Keys:
    811: + -ts_monitor_draw_solution         - draw the solution at each time-step
    812: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution

    814:   Level: intermediate

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

    819: .seealso: [](ch_ts), `TS`, `TSMonitorDrawCtxDestroy()`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtx`, `PetscMonitorDrawSolution()`
    820: @*/
    821: PetscErrorCode TSMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorDrawCtx *ctx)
    822: {
    823:   PetscFunctionBegin;
    824:   PetscCall(PetscNew(ctx));
    825:   PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
    826:   PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));

    828:   (*ctx)->howoften    = howoften;
    829:   (*ctx)->showinitial = PETSC_FALSE;
    830:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_initial", &(*ctx)->showinitial, NULL));

    832:   (*ctx)->showtimestepandtime = PETSC_FALSE;
    833:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_show_time", &(*ctx)->showtimestepandtime, NULL));
    834:   PetscFunctionReturn(PETSC_SUCCESS);
    835: }

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

    841:   Collective

    843:   Input Parameters:
    844: + ts    - the `TS` context
    845: . step  - current time-step
    846: . ptime - current time
    847: . u     - solution at current time
    848: - Ctx   - either a viewer or `NULL`

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

    853:   Level: intermediate

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

    859: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
    860: @*/
    861: PetscErrorCode TSMonitorDrawSolutionFunction(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx Ctx)
    862: {
    863:   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)Ctx;
    864:   PetscViewer      viewer = ctx->viewer;
    865:   Vec              work;

    867:   PetscFunctionBegin;
    868:   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
    869:   PetscCall(VecDuplicate(u, &work));
    870:   PetscCall(TSComputeSolutionFunction(ts, ptime, work));
    871:   PetscCall(VecView(work, viewer));
    872:   PetscCall(VecDestroy(&work));
    873:   PetscFunctionReturn(PETSC_SUCCESS);
    874: }

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

    880:   Collective

    882:   Input Parameters:
    883: + ts    - the `TS` context
    884: . step  - current time-step
    885: . ptime - current time
    886: . u     - solution at current time
    887: - Ctx   - either a viewer or `NULL`

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

    892:   Level: intermediate

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

    898: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
    899: @*/
    900: PetscErrorCode TSMonitorDrawError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx Ctx)
    901: {
    902:   TSMonitorDrawCtx ctx    = (TSMonitorDrawCtx)Ctx;
    903:   PetscViewer      viewer = ctx->viewer;
    904:   Vec              work;

    906:   PetscFunctionBegin;
    907:   if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
    908:   PetscCall(VecDuplicate(u, &work));
    909:   PetscCall(TSComputeSolutionFunction(ts, ptime, work));
    910:   PetscCall(VecAXPY(work, -1.0, u));
    911:   PetscCall(VecView(work, viewer));
    912:   PetscCall(VecDestroy(&work));
    913:   PetscFunctionReturn(PETSC_SUCCESS);
    914: }

    916: /*@C
    917:   TSMonitorSolutionSetup - Setups the context for `TSMonitorSolution()`

    919:   Collective

    921:   Input Parameters:
    922: + ts - the `TS` context
    923: - vf - viewer and its format

    925:   Level: intermediate

    927: .seealso: [](ch_ts), `TS`, `TSMonitorSolution()`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorSetFromOptions()`
    928: @*/
    929: PetscErrorCode TSMonitorSolutionSetup(TS ts, PetscViewerAndFormat *vf)
    930: {
    931:   TSMonitorSolutionCtx ctx;

    933:   PetscFunctionBegin;
    934:   PetscCall(PetscNew(&ctx));
    935:   PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_solution_skip_initial", &ctx->skip_initial, NULL));
    936:   vf->data         = ctx;
    937:   vf->data_destroy = PetscCtxDestroyDefault;
    938:   PetscFunctionReturn(PETSC_SUCCESS);
    939: }

    941: /*@C
    942:   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

    944:   Collective

    946:   Input Parameters:
    947: + ts    - the `TS` context
    948: . step  - current time-step
    949: . ptime - current time
    950: . u     - current state
    951: - vf    - viewer and its format

    953:   Level: intermediate

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

    959: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorSolutionSetup()`
    960: @*/
    961: PetscErrorCode TSMonitorSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
    962: {
    963:   TSMonitorSolutionCtx ctx = (TSMonitorSolutionCtx)vf->data;

    965:   PetscFunctionBegin;
    966:   if (ctx->skip_initial && step == ts->start_step) PetscFunctionReturn(PETSC_SUCCESS);
    967:   if ((vf->view_interval > 0 && !(step % vf->view_interval)) || (vf->view_interval && ts->reason)) {
    968:     PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
    969:     PetscCall(VecView(u, vf->viewer));
    970:     PetscCall(PetscViewerPopFormat(vf->viewer));
    971:   }
    972:   PetscFunctionReturn(PETSC_SUCCESS);
    973: }

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

    978:   Collective

    980:   Input Parameters:
    981: + ts    - the `TS` context
    982: . step  - current time-step
    983: . ptime - current time
    984: . u     - current state
    985: - ctx   - monitor context obtained with `TSMonitorSolutionVTKCtxCreate()`

    987:   Level: developer

    989:   Notes:
    990:   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.
    991:   These are named according to the file name template.

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

    996: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
    997: @*/
    998: PetscErrorCode TSMonitorSolutionVTK(TS ts, PetscInt step, PetscReal ptime, Vec u, TSMonitorVTKCtx ctx)
    999: {
    1000:   char        filename[PETSC_MAX_PATH_LEN];
    1001:   PetscViewer viewer;

    1003:   PetscFunctionBegin;
    1004:   if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
    1005:   if (((ctx->interval > 0) && (!(step % ctx->interval))) || (ctx->interval && ts->reason)) {
    1006:     PetscCall(PetscSNPrintf(filename, sizeof(filename), (const char *)ctx->filenametemplate, step));
    1007:     PetscCall(PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts), filename, FILE_MODE_WRITE, &viewer));
    1008:     PetscCall(VecView(u, viewer));
    1009:     PetscCall(PetscViewerDestroy(&viewer));
    1010:   }
    1011:   PetscFunctionReturn(PETSC_SUCCESS);
    1012: }

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

    1017:   Not Collective

    1019:   Input Parameter:
    1020: . ctx - the monitor context

    1022:   Level: developer

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

    1027: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorSolutionVTK()`
    1028: @*/
    1029: PetscErrorCode TSMonitorSolutionVTKDestroy(TSMonitorVTKCtx *ctx)
    1030: {
    1031:   PetscFunctionBegin;
    1032:   if (!*ctx) PetscFunctionReturn(PETSC_SUCCESS);
    1033:   PetscCall(PetscFree((*ctx)->filenametemplate));
    1034:   PetscCall(PetscFree(*ctx));
    1035:   PetscFunctionReturn(PETSC_SUCCESS);
    1036: }

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

    1041:   Not collective

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

    1046:   Output Parameter:
    1047: . ctx - the monitor context

    1049:   Level: developer

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

    1054: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorSolutionVTK()`, `TSMonitorSolutionVTKDestroy()`
    1055: @*/
    1056: PetscErrorCode TSMonitorSolutionVTKCtxCreate(const char *filenametemplate, TSMonitorVTKCtx *ctx)
    1057: {
    1058:   const char     *ptr = NULL, *ptr2 = NULL;
    1059:   TSMonitorVTKCtx ictx;

    1061:   PetscFunctionBegin;
    1062:   PetscAssertPointer(filenametemplate, 1);
    1063:   PetscAssertPointer(ctx, 2);
    1064:   /* Do some cursory validation of the input. */
    1065:   PetscCall(PetscStrstr(filenametemplate, "%", (char **)&ptr));
    1066:   PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_USER, "-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03" PetscInt_FMT ".vts");
    1067:   for (ptr++; ptr && *ptr; ptr++) {
    1068:     PetscCall(PetscStrchr("DdiouxX", *ptr, (char **)&ptr2));
    1069:     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");
    1070:     if (ptr2) break;
    1071:   }
    1072:   PetscCall(PetscNew(&ictx));
    1073:   PetscCall(PetscStrallocpy(filenametemplate, &ictx->filenametemplate));
    1074:   ictx->interval = 1;

    1076:   *ctx = ictx;
    1077:   PetscFunctionReturn(PETSC_SUCCESS);
    1078: }

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

    1084:   Collective

    1086:   Input Parameters:
    1087: + ts    - the `TS` context
    1088: . step  - current time-step
    1089: . ptime - current time
    1090: . u     - current solution
    1091: - dctx  - the `TSMonitorLGCtx` object that contains all the options for the monitoring, this is created with `TSMonitorLGCtxCreate()`

    1093:   Options Database Key:
    1094: . -ts_monitor_lg_solution_variables - enable monitor of lg solution variables

    1096:   Level: intermediate

    1098:   Notes:
    1099:   Each process in a parallel run displays its component solutions in a separate window

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

    1104: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
    1105:           `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
    1106:           `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGError()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
    1107:           `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
    1108: @*/
    1109: PetscErrorCode TSMonitorLGSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
    1110: {
    1111:   TSMonitorLGCtx     ctx = (TSMonitorLGCtx)dctx;
    1112:   const PetscScalar *yy;
    1113:   Vec                v;

    1115:   PetscFunctionBegin;
    1116:   if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
    1117:   if (!step) {
    1118:     PetscDrawAxis axis;
    1119:     PetscInt      dim;
    1120:     PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
    1121:     PetscCall(PetscDrawAxisSetLabels(axis, "Solution as function of time", "Time", "Solution"));
    1122:     if (!ctx->names) {
    1123:       PetscBool flg;
    1124:       /* user provides names of variables to plot but no names has been set so assume names are integer values */
    1125:       PetscCall(PetscOptionsHasName(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", &flg));
    1126:       if (flg) {
    1127:         PetscInt i, n;
    1128:         char   **names;
    1129:         PetscCall(VecGetSize(u, &n));
    1130:         PetscCall(PetscMalloc1(n + 1, &names));
    1131:         for (i = 0; i < n; i++) {
    1132:           PetscCall(PetscMalloc1(5, &names[i]));
    1133:           PetscCall(PetscSNPrintf(names[i], 5, "%" PetscInt_FMT, i));
    1134:         }
    1135:         names[n]   = NULL;
    1136:         ctx->names = names;
    1137:       }
    1138:     }
    1139:     if (ctx->names && !ctx->displaynames) {
    1140:       char    **displaynames;
    1141:       PetscBool flg;
    1142:       PetscCall(VecGetLocalSize(u, &dim));
    1143:       PetscCall(PetscCalloc1(dim + 1, &displaynames));
    1144:       PetscCall(PetscOptionsGetStringArray(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", displaynames, &dim, &flg));
    1145:       if (flg) PetscCall(TSMonitorLGCtxSetDisplayVariables(ctx, (const char *const *)displaynames));
    1146:       PetscCall(PetscStrArrayDestroy(&displaynames));
    1147:     }
    1148:     if (ctx->displaynames) {
    1149:       PetscCall(PetscDrawLGSetDimension(ctx->lg, ctx->ndisplayvariables));
    1150:       PetscCall(PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->displaynames));
    1151:     } else if (ctx->names) {
    1152:       PetscCall(VecGetLocalSize(u, &dim));
    1153:       PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
    1154:       PetscCall(PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->names));
    1155:     } else {
    1156:       PetscCall(VecGetLocalSize(u, &dim));
    1157:       PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
    1158:     }
    1159:     PetscCall(PetscDrawLGReset(ctx->lg));
    1160:   }

    1162:   if (!ctx->transform) v = u;
    1163:   else PetscCall((*ctx->transform)(ctx->transformctx, u, &v));
    1164:   PetscCall(VecGetArrayRead(v, &yy));
    1165:   if (ctx->displaynames) {
    1166:     PetscInt i;
    1167:     for (i = 0; i < ctx->ndisplayvariables; i++) ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
    1168:     PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, ctx->displayvalues));
    1169:   } else {
    1170: #if defined(PETSC_USE_COMPLEX)
    1171:     PetscInt   i, n;
    1172:     PetscReal *yreal;
    1173:     PetscCall(VecGetLocalSize(v, &n));
    1174:     PetscCall(PetscMalloc1(n, &yreal));
    1175:     for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
    1176:     PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal));
    1177:     PetscCall(PetscFree(yreal));
    1178: #else
    1179:     PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy));
    1180: #endif
    1181:   }
    1182:   PetscCall(VecRestoreArrayRead(v, &yy));
    1183:   if (ctx->transform) PetscCall(VecDestroy(&v));

    1185:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
    1186:     PetscCall(PetscDrawLGDraw(ctx->lg));
    1187:     PetscCall(PetscDrawLGSave(ctx->lg));
    1188:   }
    1189:   PetscFunctionReturn(PETSC_SUCCESS);
    1190: }

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

    1195:   Collective

    1197:   Input Parameters:
    1198: + ts    - the `TS` context
    1199: - names - the names of the components, final string must be `NULL`

    1201:   Level: intermediate

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

    1206: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetVariableNames()`
    1207: @*/
    1208: PetscErrorCode TSMonitorLGSetVariableNames(TS ts, const char *const *names)
    1209: {
    1210:   PetscInt i;

    1212:   PetscFunctionBegin;
    1213:   for (i = 0; i < ts->numbermonitors; i++) {
    1214:     if (ts->monitor[i] == TSMonitorLGSolution) {
    1215:       PetscCall(TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i], names));
    1216:       break;
    1217:     }
    1218:   }
    1219:   PetscFunctionReturn(PETSC_SUCCESS);
    1220: }

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

    1225:   Collective

    1227:   Input Parameters:
    1228: + ctx   - the `TS` context
    1229: - names - the names of the components, final string must be `NULL`

    1231:   Level: intermediate

    1233: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGSetVariableNames()`
    1234: @*/
    1235: PetscErrorCode TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx, const char *const *names)
    1236: {
    1237:   PetscFunctionBegin;
    1238:   PetscCall(PetscStrArrayDestroy(&ctx->names));
    1239:   PetscCall(PetscStrArrayallocpy(names, &ctx->names));
    1240:   PetscFunctionReturn(PETSC_SUCCESS);
    1241: }

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

    1246:   Collective

    1248:   Input Parameter:
    1249: . ts - the `TS` context

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

    1254:   Level: intermediate

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

    1259: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
    1260: @*/
    1261: PetscErrorCode TSMonitorLGGetVariableNames(TS ts, const char *const **names)
    1262: {
    1263:   PetscInt i;

    1265:   PetscFunctionBegin;
    1266:   *names = NULL;
    1267:   for (i = 0; i < ts->numbermonitors; i++) {
    1268:     if (ts->monitor[i] == TSMonitorLGSolution) {
    1269:       TSMonitorLGCtx ctx = (TSMonitorLGCtx)ts->monitorcontext[i];
    1270:       *names             = (const char *const *)ctx->names;
    1271:       break;
    1272:     }
    1273:   }
    1274:   PetscFunctionReturn(PETSC_SUCCESS);
    1275: }

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

    1280:   Collective

    1282:   Input Parameters:
    1283: + ctx          - the `TSMonitorLG` context
    1284: - displaynames - the names of the components, final string must be `NULL`

    1286:   Level: intermediate

    1288: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
    1289: @*/
    1290: PetscErrorCode TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx, const char *const *displaynames)
    1291: {
    1292:   PetscInt j = 0, k;

    1294:   PetscFunctionBegin;
    1295:   if (!ctx->names) PetscFunctionReturn(PETSC_SUCCESS);
    1296:   PetscCall(PetscStrArrayDestroy(&ctx->displaynames));
    1297:   PetscCall(PetscStrArrayallocpy(displaynames, &ctx->displaynames));
    1298:   while (displaynames[j]) j++;
    1299:   ctx->ndisplayvariables = j;
    1300:   PetscCall(PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvariables));
    1301:   PetscCall(PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvalues));
    1302:   j = 0;
    1303:   while (displaynames[j]) {
    1304:     k = 0;
    1305:     while (ctx->names[k]) {
    1306:       PetscBool flg;
    1307:       PetscCall(PetscStrcmp(displaynames[j], ctx->names[k], &flg));
    1308:       if (flg) {
    1309:         ctx->displayvariables[j] = k;
    1310:         break;
    1311:       }
    1312:       k++;
    1313:     }
    1314:     j++;
    1315:   }
    1316:   PetscFunctionReturn(PETSC_SUCCESS);
    1317: }

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

    1322:   Collective

    1324:   Input Parameters:
    1325: + ts           - the `TS` context
    1326: - displaynames - the names of the components, final string must be `NULL`

    1328:   Level: intermediate

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

    1333: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
    1334: @*/
    1335: PetscErrorCode TSMonitorLGSetDisplayVariables(TS ts, const char *const *displaynames)
    1336: {
    1337:   PetscInt i;

    1339:   PetscFunctionBegin;
    1340:   for (i = 0; i < ts->numbermonitors; i++) {
    1341:     if (ts->monitor[i] == TSMonitorLGSolution) {
    1342:       PetscCall(TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i], displaynames));
    1343:       break;
    1344:     }
    1345:   }
    1346:   PetscFunctionReturn(PETSC_SUCCESS);
    1347: }

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

    1352:   Collective

    1354:   Input Parameters:
    1355: + ts        - the `TS` context
    1356: . transform - the transform function
    1357: . destroy   - function to destroy the optional context, see `PetscCtxDestroyFn` for its calling sequence
    1358: - tctx      - optional context used by transform function

    1360:   Calling sequence of `transform`:
    1361: + tctx - context used by the transform function
    1362: . u    - the input solution vector
    1363: - w    - the output transformed vector

    1365:   Level: intermediate

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

    1370: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorLGCtxSetTransform()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `PetscCtxDestroyFn`
    1371: @*/
    1372: PetscErrorCode TSMonitorLGSetTransform(TS ts, PetscErrorCode (*transform)(PetscCtx tctx, Vec u, Vec *w), PetscCtxDestroyFn *destroy, PetscCtx tctx)
    1373: {
    1374:   PetscInt i;

    1376:   PetscFunctionBegin;
    1377:   for (i = 0; i < ts->numbermonitors; i++) {
    1378:     if (ts->monitor[i] == TSMonitorLGSolution) PetscCall(TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i], transform, destroy, tctx));
    1379:   }
    1380:   PetscFunctionReturn(PETSC_SUCCESS);
    1381: }

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

    1386:   Collective

    1388:   Input Parameters:
    1389: + tctx      - the `TS` context
    1390: . transform - the transform function
    1391: . destroy   - function to destroy the optional context, see `PetscCtxDestroyFn` for its calling sequence
    1392: - ctx       - optional context used by transform function

    1394:   Calling sequence of `transform`:
    1395: + tctx - context used by the transform function
    1396: . u    - the input solution vector
    1397: - w    - the output transformed vector

    1399:   Level: intermediate

    1401: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGSetTransform()`, `PetscCtxDestroyFn`
    1402: @*/
    1403: PetscErrorCode TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx, PetscErrorCode (*transform)(PetscCtx tctx, Vec u, Vec *w), PetscCtxDestroyFn *destroy, PetscCtx tctx)
    1404: {
    1405:   PetscFunctionBegin;
    1406:   ctx->transform        = transform;
    1407:   ctx->transformdestroy = destroy;
    1408:   ctx->transformctx     = tctx;
    1409:   PetscFunctionReturn(PETSC_SUCCESS);
    1410: }

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

    1416:   Collective

    1418:   Input Parameters:
    1419: + ts    - the `TS` context
    1420: . step  - current time-step
    1421: . ptime - current time
    1422: . u     - current solution
    1423: - Ctx   - `TSMonitorLGCtx` object created with `TSMonitorLGCtxCreate()`

    1425:   Options Database Key:
    1426: . -ts_monitor_lg_error - create a graphical monitor of error history

    1428:   Level: intermediate

    1430:   Notes:
    1431:   Each process in a parallel run displays its component errors in a separate window

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

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

    1438: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
    1439: @*/
    1440: PetscErrorCode TSMonitorLGError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx Ctx)
    1441: {
    1442:   TSMonitorLGCtx     ctx = (TSMonitorLGCtx)Ctx;
    1443:   const PetscScalar *yy;
    1444:   Vec                y;

    1446:   PetscFunctionBegin;
    1447:   if (!step) {
    1448:     PetscDrawAxis axis;
    1449:     PetscInt      dim;
    1450:     PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
    1451:     PetscCall(PetscDrawAxisSetLabels(axis, "Error in solution as function of time", "Time", "Error"));
    1452:     PetscCall(VecGetLocalSize(u, &dim));
    1453:     PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
    1454:     PetscCall(PetscDrawLGReset(ctx->lg));
    1455:   }
    1456:   PetscCall(VecDuplicate(u, &y));
    1457:   PetscCall(TSComputeSolutionFunction(ts, ptime, y));
    1458:   PetscCall(VecAXPY(y, -1.0, u));
    1459:   PetscCall(VecGetArrayRead(y, &yy));
    1460: #if defined(PETSC_USE_COMPLEX)
    1461:   {
    1462:     PetscReal *yreal;
    1463:     PetscInt   i, n;
    1464:     PetscCall(VecGetLocalSize(y, &n));
    1465:     PetscCall(PetscMalloc1(n, &yreal));
    1466:     for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
    1467:     PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal));
    1468:     PetscCall(PetscFree(yreal));
    1469:   }
    1470: #else
    1471:   PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy));
    1472: #endif
    1473:   PetscCall(VecRestoreArrayRead(y, &yy));
    1474:   PetscCall(VecDestroy(&y));
    1475:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
    1476:     PetscCall(PetscDrawLGDraw(ctx->lg));
    1477:     PetscCall(PetscDrawLGSave(ctx->lg));
    1478:   }
    1479:   PetscFunctionReturn(PETSC_SUCCESS);
    1480: }

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

    1485:   Input Parameters:
    1486: + ts    - the `TS` context
    1487: . step  - current time-step
    1488: . ptime - current time
    1489: . u     - current solution
    1490: - dctx  - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorSPCtxCreate()`

    1492:   Options Database Keys:
    1493: + -ts_monitor_sp_swarm n                          - Monitor the solution every n steps, or -1 for plotting only the final solution
    1494: . -ts_monitor_sp_swarm_retain n                   - Retain n old points so we can see the history, or -1 for all points
    1495: . -ts_monitor_sp_swarm_multi_species (true|false) - Color each species differently
    1496: - -ts_monitor_sp_swarm_phase (true|false)         - Plot in phase space, as opposed to coordinate space

    1498:   Level: intermediate

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

    1504: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `DMSWARM`, `TSMonitorSPCtxCreate()`
    1505: @*/
    1506: PetscErrorCode TSMonitorSPSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx dctx)
    1507: {
    1508:   TSMonitorSPCtx     ctx = (TSMonitorSPCtx)dctx;
    1509:   PetscDraw          draw;
    1510:   DM                 dm, cdm;
    1511:   const PetscScalar *yy;
    1512:   PetscInt           Np, p, dim = 2, *species;
    1513:   PetscReal          species_color;

    1515:   PetscFunctionBegin;
    1516:   if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
    1517:   PetscCall(TSGetDM(ts, &dm));
    1518:   if (!step) {
    1519:     PetscDrawAxis axis;
    1520:     PetscReal     dmboxlower[2], dmboxupper[2];

    1522:     PetscCall(TSGetDM(ts, &dm));
    1523:     PetscCall(DMGetDimension(dm, &dim));
    1524:     PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Monitor only supports two dimensional fields");
    1525:     PetscCall(DMSwarmGetCellDM(dm, &cdm));
    1526:     PetscCall(DMGetBoundingBox(cdm, dmboxlower, dmboxupper));
    1527:     PetscCall(VecGetLocalSize(u, &Np));
    1528:     Np /= dim * 2;
    1529:     PetscCall(PetscDrawSPGetAxis(ctx->sp, &axis));
    1530:     if (ctx->phase) {
    1531:       PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "X", "V"));
    1532:       PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], -10, 10));
    1533:     } else {
    1534:       PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "X", "Y"));
    1535:       PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], dmboxlower[1], dmboxupper[1]));
    1536:     }
    1537:     PetscCall(PetscDrawAxisSetHoldLimits(axis, PETSC_TRUE));
    1538:     PetscCall(PetscDrawSPReset(ctx->sp));
    1539:   }
    1540:   if (ctx->multispecies) PetscCall(DMSwarmGetField(dm, "species", NULL, NULL, (void **)&species));
    1541:   PetscCall(VecGetLocalSize(u, &Np));
    1542:   Np /= dim * 2;
    1543:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
    1544:     PetscCall(PetscDrawSPGetDraw(ctx->sp, &draw));
    1545:     if ((ctx->retain == 0) || (ctx->retain > 0 && !(step % ctx->retain))) PetscCall(PetscDrawClear(draw));
    1546:     PetscCall(PetscDrawFlush(draw));
    1547:     PetscCall(PetscDrawSPReset(ctx->sp));
    1548:     PetscCall(VecGetArrayRead(u, &yy));
    1549:     for (p = 0; p < Np; ++p) {
    1550:       PetscReal x, y;

    1552:       if (ctx->phase) {
    1553:         x = PetscRealPart(yy[p * dim * 2]);
    1554:         y = PetscRealPart(yy[p * dim * 2 + dim]);
    1555:       } else {
    1556:         x = PetscRealPart(yy[p * dim * 2]);
    1557:         y = PetscRealPart(yy[p * dim * 2 + 1]);
    1558:       }
    1559:       if (ctx->multispecies) {
    1560:         species_color = species[p] + 2;
    1561:         PetscCall(PetscDrawSPAddPointColorized(ctx->sp, &x, &y, &species_color));
    1562:       } else {
    1563:         PetscCall(PetscDrawSPAddPoint(ctx->sp, &x, &y));
    1564:       }
    1565:       PetscCall(PetscDrawSPAddPoint(ctx->sp, &x, &y));
    1566:     }
    1567:     PetscCall(VecRestoreArrayRead(u, &yy));
    1568:     PetscCall(PetscDrawSPDraw(ctx->sp, PETSC_FALSE));
    1569:     PetscCall(PetscDrawSPSave(ctx->sp));
    1570:     if (ctx->multispecies) PetscCall(DMSwarmRestoreField(dm, "species", NULL, NULL, (void **)&species));
    1571:   }
    1572:   PetscFunctionReturn(PETSC_SUCCESS);
    1573: }

    1575: /*@C
    1576:   TSMonitorHGSwarmSolution - Graphically displays histograms of `DMSWARM` particles

    1578:   Input Parameters:
    1579: + ts    - the `TS` context
    1580: . step  - current time-step
    1581: . ptime - current time
    1582: . u     - current solution
    1583: - dctx  - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorHGCtxCreate()`

    1585:   Options Database Keys:
    1586: + -ts_monitor_hg_swarm n                     - Monitor the solution every n steps, or -1 for plotting only the final solution
    1587: . -ts_monitor_hg_swarm_species num           - Number of species to histogram
    1588: . -ts_monitor_hg_swarm_bins num              - Number of histogram bins
    1589: - -ts_monitor_hg_swarm_velocity (true|false) - Plot in velocity space, as opposed to coordinate space

    1591:   Level: intermediate

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

    1597: .seealso: `TSMonitorSet()`
    1598: @*/
    1599: PetscErrorCode TSMonitorHGSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx dctx)
    1600: {
    1601:   TSMonitorHGCtx     ctx = (TSMonitorHGCtx)dctx;
    1602:   PetscDraw          draw;
    1603:   DM                 sw;
    1604:   const PetscScalar *yy;
    1605:   PetscInt          *species;
    1606:   PetscInt           dim, d = 0, Np, p, Ns, s;

    1608:   PetscFunctionBegin;
    1609:   if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
    1610:   PetscCall(TSGetDM(ts, &sw));
    1611:   PetscCall(DMGetDimension(sw, &dim));
    1612:   PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
    1613:   Ns = PetscMin(Ns, ctx->Ns);
    1614:   PetscCall(VecGetLocalSize(u, &Np));
    1615:   Np /= dim * 2;
    1616:   if (!step) {
    1617:     PetscDrawAxis axis;
    1618:     char          title[PETSC_MAX_PATH_LEN];

    1620:     for (s = 0; s < Ns; ++s) {
    1621:       PetscCall(PetscDrawHGGetAxis(ctx->hg[s], &axis));
    1622:       PetscCall(PetscSNPrintf(title, PETSC_MAX_PATH_LEN, "Species %" PetscInt_FMT, s));
    1623:       if (ctx->velocity) PetscCall(PetscDrawAxisSetLabels(axis, title, "V", "N"));
    1624:       else PetscCall(PetscDrawAxisSetLabels(axis, title, "X", "N"));
    1625:     }
    1626:   }
    1627:   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
    1628:     PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
    1629:     for (s = 0; s < Ns; ++s) {
    1630:       PetscCall(PetscDrawHGReset(ctx->hg[s]));
    1631:       PetscCall(PetscDrawHGGetDraw(ctx->hg[s], &draw));
    1632:       PetscCall(PetscDrawClear(draw));
    1633:       PetscCall(PetscDrawFlush(draw));
    1634:     }
    1635:     PetscCall(VecGetArrayRead(u, &yy));
    1636:     for (p = 0; p < Np; ++p) {
    1637:       const PetscInt s = species[p] < Ns ? species[p] : 0;
    1638:       PetscReal      v;

    1640:       if (ctx->velocity) v = PetscRealPart(yy[p * dim * 2 + d + dim]);
    1641:       else v = PetscRealPart(yy[p * dim * 2 + d]);
    1642:       PetscCall(PetscDrawHGAddValue(ctx->hg[s], v));
    1643:     }
    1644:     PetscCall(VecRestoreArrayRead(u, &yy));
    1645:     for (s = 0; s < Ns; ++s) {
    1646:       PetscCall(PetscDrawHGDraw(ctx->hg[s]));
    1647:       PetscCall(PetscDrawHGSave(ctx->hg[s]));
    1648:     }
    1649:     PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
    1650:   }
    1651:   PetscFunctionReturn(PETSC_SUCCESS);
    1652: }

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

    1657:   Collective

    1659:   Input Parameters:
    1660: + ts    - the `TS` context
    1661: . step  - current time-step
    1662: . ptime - current time
    1663: . u     - current solution
    1664: - vf    - unused context

    1666:   Options Database Key:
    1667: . -ts_monitor_error - create a graphical monitor of error history

    1669:   Level: intermediate

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

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

    1677: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
    1678: @*/
    1679: PetscErrorCode TSMonitorError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
    1680: {
    1681:   DM        dm;
    1682:   PetscDS   ds = NULL;
    1683:   PetscInt  Nf = -1, f;
    1684:   PetscBool flg;

    1686:   PetscFunctionBegin;
    1687:   PetscCall(TSGetDM(ts, &dm));
    1688:   if (dm) PetscCall(DMGetDS(dm, &ds));
    1689:   if (ds) PetscCall(PetscDSGetNumFields(ds, &Nf));
    1690:   if (Nf <= 0) {
    1691:     Vec       y;
    1692:     PetscReal nrm;

    1694:     PetscCall(VecDuplicate(u, &y));
    1695:     PetscCall(TSComputeSolutionFunction(ts, ptime, y));
    1696:     PetscCall(VecAXPY(y, -1.0, u));
    1697:     PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERASCII, &flg));
    1698:     if (flg) {
    1699:       PetscCall(VecNorm(y, NORM_2, &nrm));
    1700:       PetscCall(PetscViewerASCIIPrintf(vf->viewer, "2-norm of error %g\n", (double)nrm));
    1701:     }
    1702:     PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &flg));
    1703:     if (flg) PetscCall(VecView(y, vf->viewer));
    1704:     PetscCall(VecDestroy(&y));
    1705:   } else {
    1706:     PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, PetscCtx ctx);
    1707:     void    **ctxs;
    1708:     Vec       v;
    1709:     PetscReal ferrors[1];

    1711:     PetscCall(PetscMalloc2(Nf, &exactFuncs, Nf, &ctxs));
    1712:     for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(ds, f, &exactFuncs[f], &ctxs[f]));
    1713:     PetscCall(DMComputeL2FieldDiff(dm, ptime, exactFuncs, ctxs, u, ferrors));
    1714:     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Timestep: %04" PetscInt_FMT " time = %-8.4g \t L_2 Error: [", step, (double)ptime));
    1715:     for (f = 0; f < Nf; ++f) {
    1716:       if (f > 0) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ", "));
    1717:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%2.3g", (double)ferrors[f]));
    1718:     }
    1719:     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "]\n"));

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

    1723:     PetscCall(PetscOptionsHasName(NULL, NULL, "-exact_vec_view", &flg));
    1724:     if (flg) {
    1725:       PetscCall(DMGetGlobalVector(dm, &v));
    1726:       PetscCall(DMProjectFunction(dm, ptime, exactFuncs, ctxs, INSERT_ALL_VALUES, v));
    1727:       PetscCall(PetscObjectSetName((PetscObject)v, "Exact Solution"));
    1728:       PetscCall(VecViewFromOptions(v, NULL, "-exact_vec_view"));
    1729:       PetscCall(DMRestoreGlobalVector(dm, &v));
    1730:     }
    1731:     PetscCall(PetscFree2(exactFuncs, ctxs));
    1732:   }
    1733:   PetscFunctionReturn(PETSC_SUCCESS);
    1734: }

    1736: /*@C
    1737:   TSMonitorLGSNESIterations - Monitors the number of nonlinear (`SNES`) iterations used per time step in a line-graph plot

    1739:   Collective

    1741:   Input Parameters:
    1742: + ts     - the `TS` context
    1743: . n      - iteration number (a negative value indicates an interpolated solution and is ignored)
    1744: . ptime  - current time
    1745: . v      - current solution
    1746: - monctx - the `TSMonitorLGCtx` object that contains all the options for the monitoring, created with `TSMonitorLGCtxCreate()`

    1748:   Level: intermediate

    1750:   Note:
    1751:   This is not called directly by users; pass this function to `TSMonitorSet()` along with the context created by `TSMonitorLGCtxCreate()` and `TSMonitorLGCtxDestroy()`.

    1753: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGKSPIterations()`
    1754: @*/
    1755: PetscErrorCode TSMonitorLGSNESIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, PetscCtx monctx)
    1756: {
    1757:   TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
    1758:   PetscReal      x   = ptime, y;
    1759:   PetscInt       its;

    1761:   PetscFunctionBegin;
    1762:   if (n < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
    1763:   if (!n) {
    1764:     PetscDrawAxis axis;
    1765:     PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
    1766:     PetscCall(PetscDrawAxisSetLabels(axis, "Nonlinear iterations as function of time", "Time", "SNES Iterations"));
    1767:     PetscCall(PetscDrawLGReset(ctx->lg));
    1768:     ctx->snes_its = 0;
    1769:   }
    1770:   PetscCall(TSGetSNESIterations(ts, &its));
    1771:   y = its - ctx->snes_its;
    1772:   PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
    1773:   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
    1774:     PetscCall(PetscDrawLGDraw(ctx->lg));
    1775:     PetscCall(PetscDrawLGSave(ctx->lg));
    1776:   }
    1777:   ctx->snes_its = its;
    1778:   PetscFunctionReturn(PETSC_SUCCESS);
    1779: }

    1781: /*@C
    1782:   TSMonitorLGKSPIterations - Monitors the number of linear (`KSP`) iterations used per time step in a line-graph plot

    1784:   Collective

    1786:   Input Parameters:
    1787: + ts     - the `TS` context
    1788: . n      - iteration number (a negative value indicates an interpolated solution and is ignored)
    1789: . ptime  - current time
    1790: . v      - current solution
    1791: - monctx - the `TSMonitorLGCtx` object that contains all the options for the monitoring, created with `TSMonitorLGCtxCreate()`

    1793:   Level: intermediate

    1795:   Note:
    1796:   This is not called directly by users; pass this function to `TSMonitorSet()` along with the context created by `TSMonitorLGCtxCreate()` and `TSMonitorLGCtxDestroy()`.

    1798: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGSNESIterations()`
    1799: @*/
    1800: PetscErrorCode TSMonitorLGKSPIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, PetscCtx monctx)
    1801: {
    1802:   TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
    1803:   PetscReal      x   = ptime, y;
    1804:   PetscInt       its;

    1806:   PetscFunctionBegin;
    1807:   if (n < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
    1808:   if (!n) {
    1809:     PetscDrawAxis axis;
    1810:     PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
    1811:     PetscCall(PetscDrawAxisSetLabels(axis, "Linear iterations as function of time", "Time", "KSP Iterations"));
    1812:     PetscCall(PetscDrawLGReset(ctx->lg));
    1813:     ctx->ksp_its = 0;
    1814:   }
    1815:   PetscCall(TSGetKSPIterations(ts, &its));
    1816:   y = its - ctx->ksp_its;
    1817:   PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
    1818:   if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
    1819:     PetscCall(PetscDrawLGDraw(ctx->lg));
    1820:     PetscCall(PetscDrawLGSave(ctx->lg));
    1821:   }
    1822:   ctx->ksp_its = its;
    1823:   PetscFunctionReturn(PETSC_SUCCESS);
    1824: }

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

    1829:   Collective

    1831:   Input Parameter:
    1832: . ts - the `TS` solver object

    1834:   Output Parameter:
    1835: . ctx - the context

    1837:   Level: intermediate

    1839: .seealso: [](ch_ts), `TS`, `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`
    1840: @*/
    1841: PetscErrorCode TSMonitorEnvelopeCtxCreate(TS ts, TSMonitorEnvelopeCtx *ctx)
    1842: {
    1843:   PetscFunctionBegin;
    1844:   PetscCall(PetscNew(ctx));
    1845:   PetscFunctionReturn(PETSC_SUCCESS);
    1846: }

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

    1851:   Collective

    1853:   Input Parameters:
    1854: + ts    - the `TS` context
    1855: . step  - current time-step
    1856: . ptime - current time
    1857: . u     - current solution
    1858: - dctx  - the envelope context

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

    1863:   Level: intermediate

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

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

    1871: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxCreate()`
    1872: @*/
    1873: PetscErrorCode TSMonitorEnvelope(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx dctx)
    1874: {
    1875:   TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;

    1877:   PetscFunctionBegin;
    1878:   if (!ctx->max) {
    1879:     PetscCall(VecDuplicate(u, &ctx->max));
    1880:     PetscCall(VecDuplicate(u, &ctx->min));
    1881:     PetscCall(VecCopy(u, ctx->max));
    1882:     PetscCall(VecCopy(u, ctx->min));
    1883:   } else {
    1884:     PetscCall(VecPointwiseMax(ctx->max, u, ctx->max));
    1885:     PetscCall(VecPointwiseMin(ctx->min, u, ctx->min));
    1886:   }
    1887:   PetscFunctionReturn(PETSC_SUCCESS);
    1888: }

    1890: /*@C
    1891:   TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution

    1893:   Collective

    1895:   Input Parameter:
    1896: . ts - the `TS` context

    1898:   Output Parameters:
    1899: + max - the maximum values
    1900: - min - the minimum values

    1902:   Level: intermediate

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

    1907: .seealso: [](ch_ts), `TSMonitorEnvelopeCtx`, `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
    1908: @*/
    1909: PetscErrorCode TSMonitorEnvelopeGetBounds(TS ts, Vec *max, Vec *min)
    1910: {
    1911:   PetscInt i;

    1913:   PetscFunctionBegin;
    1914:   if (max) *max = NULL;
    1915:   if (min) *min = NULL;
    1916:   for (i = 0; i < ts->numbermonitors; i++) {
    1917:     if (ts->monitor[i] == TSMonitorEnvelope) {
    1918:       TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)ts->monitorcontext[i];
    1919:       if (max) *max = ctx->max;
    1920:       if (min) *min = ctx->min;
    1921:       break;
    1922:     }
    1923:   }
    1924:   PetscFunctionReturn(PETSC_SUCCESS);
    1925: }

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

    1930:   Collective

    1932:   Input Parameter:
    1933: . ctx - the monitor context

    1935:   Level: intermediate

    1937: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
    1938: @*/
    1939: PetscErrorCode TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
    1940: {
    1941:   PetscFunctionBegin;
    1942:   PetscCall(VecDestroy(&(*ctx)->min));
    1943:   PetscCall(VecDestroy(&(*ctx)->max));
    1944:   PetscCall(PetscFree(*ctx));
    1945:   PetscFunctionReturn(PETSC_SUCCESS);
    1946: }

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

    1951:   Not Collective

    1953:   Input Parameters:
    1954: + ts   - the `TS` context
    1955: . step - current timestep
    1956: . t    - current time
    1957: . U    - current solution
    1958: - vf   - not used

    1960:   Options Database Key:
    1961: + -ts_dmswarm_monitor_moments          - Monitor moments of particle distribution
    1962: - -ts_dmswarm_monitor_moments_interval - Interval of timesteps between monitor outputs

    1964:   Level: intermediate

    1966:   Notes:
    1967:   This requires a `DMSWARM` be attached to the `TS`.

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

    1972: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `DMSWARM`
    1973: @*/
    1974: PetscErrorCode TSDMSwarmMonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, PetscViewerAndFormat *vf)
    1975: {
    1976:   DM                 sw;
    1977:   const PetscScalar *u;
    1978:   PetscReal          m = 1.0, totE = 0., totMom[3] = {0., 0., 0.};
    1979:   PetscInt           dim, d, Np, p;
    1980:   MPI_Comm           comm;

    1982:   PetscFunctionBeginUser;
    1983:   (void)t;
    1984:   (void)vf;
    1985:   PetscCall(TSGetDM(ts, &sw));
    1986:   if (!sw || step % vf->view_interval != 0) PetscFunctionReturn(PETSC_SUCCESS);
    1987:   PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
    1988:   PetscCall(DMGetDimension(sw, &dim));
    1989:   PetscCall(VecGetLocalSize(U, &Np));
    1990:   Np /= dim;
    1991:   PetscCall(VecGetArrayRead(U, &u));
    1992:   for (p = 0; p < Np; ++p) {
    1993:     for (d = 0; d < dim; ++d) {
    1994:       totE += PetscRealPart(u[p * dim + d] * u[p * dim + d]);
    1995:       totMom[d] += PetscRealPart(u[p * dim + d]);
    1996:     }
    1997:   }
    1998:   PetscCall(VecRestoreArrayRead(U, &u));
    1999:   for (d = 0; d < dim; ++d) totMom[d] *= m;
    2000:   totE *= 0.5 * m;
    2001:   PetscCall(PetscPrintf(comm, "Step %4" PetscInt_FMT " Total Energy: %10.8lf", step, (double)totE));
    2002:   for (d = 0; d < dim; ++d) PetscCall(PetscPrintf(comm, "    Total Momentum %c: %10.8lf", (char)('x' + d), (double)totMom[d]));
    2003:   PetscCall(PetscPrintf(comm, "\n"));
    2004:   PetscFunctionReturn(PETSC_SUCCESS);
    2005: }