Actual source code: tsmon.c
1: #include <petsc/private/tsimpl.h>
2: #include <petscdm.h>
3: #include <petscds.h>
4: #include <petscdmswarm.h>
5: #include <petscdraw.h>
7: /*@C
8: TSMonitor - Runs all user-provided monitor routines set using `TSMonitorSet()`
10: Collective
12: Input Parameters:
13: + ts - time stepping context obtained from `TSCreate()`
14: . step - step number that has just completed
15: . ptime - model time of the state
16: - u - state at the current model time
18: Level: developer
20: Notes:
21: `TSMonitor()` is typically used automatically within the time stepping implementations.
22: Users would almost never call this routine directly.
24: A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions
26: .seealso: `TS`, `TSMonitorSet()`, `TSMonitorSetFromOptions()`
27: @*/
28: PetscErrorCode TSMonitor(TS ts, PetscInt step, PetscReal ptime, Vec u)
29: {
30: DM dm;
31: PetscInt i, n = ts->numbermonitors;
33: PetscFunctionBegin;
37: PetscCall(TSGetDM(ts, &dm));
38: PetscCall(DMSetOutputSequenceNumber(dm, step, ptime));
40: PetscCall(VecLockReadPush(u));
41: for (i = 0; i < n; i++) PetscCall((*ts->monitor[i])(ts, step, ptime, u, ts->monitorcontext[i]));
42: PetscCall(VecLockReadPop(u));
43: PetscFunctionReturn(PETSC_SUCCESS);
44: }
46: /*@C
47: TSMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
49: Collective
51: Input Parameters:
52: + ts - `TS` object you wish to monitor
53: . name - the monitor type one is seeking
54: . help - message indicating what monitoring is done
55: . manual - manual page for the monitor
56: . monitor - the monitor function
57: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `TS` or `PetscViewer` objects
59: Level: developer
61: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
62: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
63: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
64: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
65: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
66: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
67: `PetscOptionsFList()`, `PetscOptionsEList()`
68: @*/
69: PetscErrorCode TSMonitorSetFromOptions(TS ts, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(TS, PetscInt, PetscReal, Vec, PetscViewerAndFormat *), PetscErrorCode (*monitorsetup)(TS, PetscViewerAndFormat *))
70: {
71: PetscViewer viewer;
72: PetscViewerFormat format;
73: PetscBool flg;
75: PetscFunctionBegin;
76: PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, name, &viewer, &format, &flg));
77: if (flg) {
78: PetscViewerAndFormat *vf;
79: char interval_key[1024];
80: PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
81: PetscCall(PetscSNPrintf(interval_key, sizeof interval_key, "%s_interval", name));
82: PetscCall(PetscOptionsGetInt(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, interval_key, &vf->view_interval, NULL));
83: PetscCall(PetscObjectDereference((PetscObject)viewer));
84: if (monitorsetup) PetscCall((*monitorsetup)(ts, vf));
85: PetscCall(TSMonitorSet(ts, (PetscErrorCode(*)(TS, PetscInt, PetscReal, Vec, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
86: }
87: PetscFunctionReturn(PETSC_SUCCESS);
88: }
90: /*@C
91: TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
92: timestep to display the iteration's progress.
94: Logically Collective
96: Input Parameters:
97: + ts - the `TS` context obtained from `TSCreate()`
98: . monitor - monitoring routine
99: . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
100: - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
102: Calling sequence of `monitor`:
103: $ PetscErrorCode monitor(TS ts, PetscInt steps, PetscReal time, Vec u, void *mctx)
104: + ts - the `TS` context
105: . 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)
106: . time - current time
107: . u - current iterate
108: - mctx - [optional] monitoring context
110: Level: intermediate
112: Note:
113: This routine adds an additional monitor to the list of monitors that already has been loaded.
115: Fortran Note:
116: Only a single monitor function can be set for each `TS` object
118: .seealso: [](ch_ts), `TSMonitorDefault()`, `TSMonitorCancel()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
119: `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
120: `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`, `TSDMSwarmMonitorMoments()`
121: @*/
122: PetscErrorCode TSMonitorSet(TS ts, PetscErrorCode (*monitor)(TS, PetscInt, PetscReal, Vec, void *), void *mctx, PetscErrorCode (*mdestroy)(void **))
123: {
124: PetscInt i;
125: PetscBool identical;
127: PetscFunctionBegin;
129: for (i = 0; i < ts->numbermonitors; i++) {
130: PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))monitor, mctx, mdestroy, (PetscErrorCode(*)(void))ts->monitor[i], ts->monitorcontext[i], ts->monitordestroy[i], &identical));
131: if (identical) PetscFunctionReturn(PETSC_SUCCESS);
132: }
133: PetscCheck(ts->numbermonitors < MAXTSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
134: ts->monitor[ts->numbermonitors] = monitor;
135: ts->monitordestroy[ts->numbermonitors] = mdestroy;
136: ts->monitorcontext[ts->numbermonitors++] = (void *)mctx;
137: PetscFunctionReturn(PETSC_SUCCESS);
138: }
140: /*@C
141: TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
143: Logically Collective
145: Input Parameter:
146: . ts - the `TS` context obtained from `TSCreate()`
148: Level: intermediate
150: Note:
151: There is no way to remove a single, specific monitor.
153: .seealso: [](ch_ts), `TS`, `TSMonitorDefault()`, `TSMonitorSet()`
154: @*/
155: PetscErrorCode TSMonitorCancel(TS ts)
156: {
157: PetscInt i;
159: PetscFunctionBegin;
161: for (i = 0; i < ts->numbermonitors; i++) {
162: if (ts->monitordestroy[i]) PetscCall((*ts->monitordestroy[i])(&ts->monitorcontext[i]));
163: }
164: ts->numbermonitors = 0;
165: PetscFunctionReturn(PETSC_SUCCESS);
166: }
168: /*@C
169: TSMonitorDefault - The default monitor, prints the timestep and time for each step
171: Options Database Key:
172: . -ts_monitor - monitors the time integration
174: Level: intermediate
176: Notes:
177: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
178: to be used during the `TS` integration.
180: .seealso: [](ch_ts), `TSMonitorSet()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
181: `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
182: `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`, `TSDMSwarmMonitorMoments()`
183: @*/
184: PetscErrorCode TSMonitorDefault(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
185: {
186: PetscViewer viewer = vf->viewer;
187: PetscBool iascii, ibinary;
189: PetscFunctionBegin;
191: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
192: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
193: PetscCall(PetscViewerPushFormat(viewer, vf->format));
194: if (iascii) {
195: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
196: if (step == -1) { /* this indicates it is an interpolated solution */
197: PetscCall(PetscViewerASCIIPrintf(viewer, "Interpolated solution at time %g between steps %" PetscInt_FMT " and %" PetscInt_FMT "\n", (double)ptime, ts->steps - 1, ts->steps));
198: } else {
199: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)\n" : "\n"));
200: }
201: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
202: } else if (ibinary) {
203: PetscMPIInt rank;
204: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
205: if (rank == 0) {
206: PetscBool skipHeader;
207: PetscInt classid = REAL_FILE_CLASSID;
209: PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
210: if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
211: PetscCall(PetscRealView(1, &ptime, viewer));
212: } else {
213: PetscCall(PetscRealView(0, &ptime, viewer));
214: }
215: }
216: PetscCall(PetscViewerPopFormat(viewer));
217: PetscFunctionReturn(PETSC_SUCCESS);
218: }
220: /*@C
221: TSMonitorExtreme - Prints the extreme values of the solution at each timestep
223: Level: intermediate
225: Note:
226: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
227: to be used during the `TS` integration.
229: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`
230: @*/
231: PetscErrorCode TSMonitorExtreme(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
232: {
233: PetscViewer viewer = vf->viewer;
234: PetscBool iascii;
235: PetscReal max, min;
237: PetscFunctionBegin;
239: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
240: PetscCall(PetscViewerPushFormat(viewer, vf->format));
241: if (iascii) {
242: PetscCall(VecMax(v, NULL, &max));
243: PetscCall(VecMin(v, NULL, &min));
244: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
245: 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));
246: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
247: }
248: PetscCall(PetscViewerPopFormat(viewer));
249: PetscFunctionReturn(PETSC_SUCCESS);
250: }
252: /*@C
253: TSMonitorLGCtxCreate - Creates a `TSMonitorLGCtx` context for use with
254: `TS` to monitor the solution process graphically in various ways
256: Collective
258: Input Parameters:
259: + host - the X display to open, or `NULL` for the local machine
260: . label - the title to put in the title bar
261: . x, y - the screen coordinates of the upper left coordinate of the window
262: . m, n - the screen width and height in pixels
263: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
265: Output Parameter:
266: . ctx - the context
268: Options Database Keys:
269: + -ts_monitor_lg_timestep - automatically sets line graph monitor
270: + -ts_monitor_lg_timestep_log - automatically sets line graph monitor
271: . -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling `TSMonitorLGSetDisplayVariables()` or `TSMonitorLGCtxSetDisplayVariables()`)
272: . -ts_monitor_lg_error - monitor the error
273: . -ts_monitor_lg_ksp_iterations - monitor the number of `KSP` iterations needed for each timestep
274: . -ts_monitor_lg_snes_iterations - monitor the number of `SNES` iterations needed for each timestep
275: - -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
277: Level: intermediate
279: Notes:
280: Pass the context and `TSMonitorLGCtxDestroy()` to `TSMonitorSet()` to have the context destroyed when no longer needed.
282: One can provide a function that transforms the solution before plotting it with `TSMonitorLGCtxSetTransform()` or `TSMonitorLGSetTransform()`
284: Many of the functions that control the monitoring have two forms: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a `TS` object as the
285: 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
286: as the first argument.
288: One can control the names displayed for each solution or error variable with `TSMonitorLGCtxSetVariableNames()` or `TSMonitorLGSetVariableNames()`
290: .seealso: [](ch_ts), `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorDefault()`, `VecView()`,
291: `TSMonitorLGCtxCreate()`, `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
292: `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
293: `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGError()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
294: `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
295: @*/
296: PetscErrorCode TSMonitorLGCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorLGCtx *ctx)
297: {
298: PetscDraw draw;
300: PetscFunctionBegin;
301: PetscCall(PetscNew(ctx));
302: PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
303: PetscCall(PetscDrawSetFromOptions(draw));
304: PetscCall(PetscDrawLGCreate(draw, 1, &(*ctx)->lg));
305: PetscCall(PetscDrawLGSetFromOptions((*ctx)->lg));
306: PetscCall(PetscDrawDestroy(&draw));
307: (*ctx)->howoften = howoften;
308: PetscFunctionReturn(PETSC_SUCCESS);
309: }
311: PetscErrorCode TSMonitorLGTimeStep(TS ts, PetscInt step, PetscReal ptime, Vec v, void *monctx)
312: {
313: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
314: PetscReal x = ptime, y;
316: PetscFunctionBegin;
317: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates an interpolated solution */
318: if (!step) {
319: PetscDrawAxis axis;
320: const char *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
321: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
322: PetscCall(PetscDrawAxisSetLabels(axis, "Timestep as function of time", "Time", ylabel));
323: PetscCall(PetscDrawLGReset(ctx->lg));
324: }
325: PetscCall(TSGetTimeStep(ts, &y));
326: if (ctx->semilogy) y = PetscLog10Real(y);
327: PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
328: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
329: PetscCall(PetscDrawLGDraw(ctx->lg));
330: PetscCall(PetscDrawLGSave(ctx->lg));
331: }
332: PetscFunctionReturn(PETSC_SUCCESS);
333: }
335: /*@C
336: TSMonitorLGCtxDestroy - Destroys a line graph context that was created with `TSMonitorLGCtxCreate()`.
338: Collective
340: Input Parameter:
341: . ctx - the monitor context
343: Level: intermediate
345: Note:
346: Pass to `TSMonitorSet()` along with the context and `TSMonitorLGTimeStep()`
348: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep();`
349: @*/
350: PetscErrorCode TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
351: {
352: PetscFunctionBegin;
353: if ((*ctx)->transformdestroy) PetscCall(((*ctx)->transformdestroy)((*ctx)->transformctx));
354: PetscCall(PetscDrawLGDestroy(&(*ctx)->lg));
355: PetscCall(PetscStrArrayDestroy(&(*ctx)->names));
356: PetscCall(PetscStrArrayDestroy(&(*ctx)->displaynames));
357: PetscCall(PetscFree((*ctx)->displayvariables));
358: PetscCall(PetscFree((*ctx)->displayvalues));
359: PetscCall(PetscFree(*ctx));
360: PetscFunctionReturn(PETSC_SUCCESS);
361: }
363: /* Creates a TSMonitorSPCtx for use with DMSwarm particle visualizations */
364: 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)
365: {
366: PetscDraw draw;
368: PetscFunctionBegin;
369: PetscCall(PetscNew(ctx));
370: PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
371: PetscCall(PetscDrawSetFromOptions(draw));
372: PetscCall(PetscDrawSPCreate(draw, 1, &(*ctx)->sp));
373: PetscCall(PetscDrawDestroy(&draw));
374: (*ctx)->howoften = howoften;
375: (*ctx)->retain = retain;
376: (*ctx)->phase = phase;
377: (*ctx)->multispecies = multispecies;
378: PetscFunctionReturn(PETSC_SUCCESS);
379: }
381: /* Destroys a TSMonitorSPCtx that was created with TSMonitorSPCtxCreate */
382: PetscErrorCode TSMonitorSPCtxDestroy(TSMonitorSPCtx *ctx)
383: {
384: PetscFunctionBegin;
386: PetscCall(PetscDrawSPDestroy(&(*ctx)->sp));
387: PetscCall(PetscFree(*ctx));
388: PetscFunctionReturn(PETSC_SUCCESS);
389: }
391: /* Creates a TSMonitorHGCtx for use with DMSwarm particle visualizations */
392: 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)
393: {
394: PetscDraw draw;
395: PetscInt s;
397: PetscFunctionBegin;
398: PetscCall(PetscNew(ctx));
399: PetscCall(PetscMalloc1(Ns, &(*ctx)->hg));
400: for (s = 0; s < Ns; ++s) {
401: PetscCall(PetscDrawCreate(comm, host, label, x + s * m, y, m, n, &draw));
402: PetscCall(PetscDrawSetFromOptions(draw));
403: PetscCall(PetscDrawHGCreate(draw, Nb, &(*ctx)->hg[s]));
404: PetscCall(PetscDrawHGCalcStats((*ctx)->hg[s], PETSC_TRUE));
405: PetscCall(PetscDrawDestroy(&draw));
406: }
407: (*ctx)->howoften = howoften;
408: (*ctx)->Ns = Ns;
409: (*ctx)->velocity = velocity;
410: PetscFunctionReturn(PETSC_SUCCESS);
411: }
413: /* Destroys a TSMonitorHGCtx that was created with TSMonitorHGCtxCreate */
414: PetscErrorCode TSMonitorHGCtxDestroy(TSMonitorHGCtx *ctx)
415: {
416: PetscInt s;
418: PetscFunctionBegin;
419: for (s = 0; s < (*ctx)->Ns; ++s) PetscCall(PetscDrawHGDestroy(&(*ctx)->hg[s]));
420: PetscCall(PetscFree((*ctx)->hg));
421: PetscCall(PetscFree(*ctx));
422: PetscFunctionReturn(PETSC_SUCCESS);
423: }
425: /*@C
426: TSMonitorDrawSolution - Monitors progress of the `TS` solvers by calling
427: `VecView()` for the solution at each timestep
429: Collective
431: Input Parameters:
432: + ts - the `TS` context
433: . step - current time-step
434: . ptime - current time
435: - dummy - either a viewer or `NULL`
437: Options Database Keys:
438: + -ts_monitor_draw_solution - draw the solution at each time-step
439: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution
441: Level: intermediate
443: Notes:
444: The initial solution and current solution are not displayed with a common axis scaling so generally the option `-ts_monitor_draw_solution_initial`
445: will look bad
447: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, as well as the context created with
448: `TSMonitorDrawCtxCreate()` and the function `TSMonitorDrawCtxDestroy()` to cause the monitor to be used during the `TS` integration.
450: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtxCreate()`, `TSMonitorDrawCtxDestroy()`
451: @*/
452: PetscErrorCode TSMonitorDrawSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
453: {
454: TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
455: PetscDraw draw;
457: PetscFunctionBegin;
458: if (!step && ictx->showinitial) {
459: if (!ictx->initialsolution) PetscCall(VecDuplicate(u, &ictx->initialsolution));
460: PetscCall(VecCopy(u, ictx->initialsolution));
461: }
462: if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
464: if (ictx->showinitial) {
465: PetscReal pause;
466: PetscCall(PetscViewerDrawGetPause(ictx->viewer, &pause));
467: PetscCall(PetscViewerDrawSetPause(ictx->viewer, 0.0));
468: PetscCall(VecView(ictx->initialsolution, ictx->viewer));
469: PetscCall(PetscViewerDrawSetPause(ictx->viewer, pause));
470: PetscCall(PetscViewerDrawSetHold(ictx->viewer, PETSC_TRUE));
471: }
472: PetscCall(VecView(u, ictx->viewer));
473: if (ictx->showtimestepandtime) {
474: PetscReal xl, yl, xr, yr, h;
475: char time[32];
477: PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
478: PetscCall(PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime));
479: PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
480: h = yl + .95 * (yr - yl);
481: PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
482: PetscCall(PetscDrawFlush(draw));
483: }
485: if (ictx->showinitial) PetscCall(PetscViewerDrawSetHold(ictx->viewer, PETSC_FALSE));
486: PetscFunctionReturn(PETSC_SUCCESS);
487: }
489: /*@C
490: TSMonitorDrawSolutionPhase - Monitors progress of the `TS` solvers by plotting the solution as a phase diagram
492: Collective
494: Input Parameters:
495: + ts - the `TS` context
496: . step - current time-step
497: . ptime - current time
498: - dummy - either a viewer or `NULL`
500: Level: intermediate
502: Notes:
503: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
504: to be used during the `TS` integration.
506: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
507: @*/
508: PetscErrorCode TSMonitorDrawSolutionPhase(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
509: {
510: TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
511: PetscDraw draw;
512: PetscDrawAxis axis;
513: PetscInt n;
514: PetscMPIInt size;
515: PetscReal U0, U1, xl, yl, xr, yr, h;
516: char time[32];
517: const PetscScalar *U;
519: PetscFunctionBegin;
520: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)ts), &size));
521: PetscCheck(size == 1, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only allowed for sequential runs");
522: PetscCall(VecGetSize(u, &n));
523: PetscCheck(n == 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only for ODEs with two unknowns");
525: PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
526: PetscCall(PetscViewerDrawGetDrawAxis(ictx->viewer, 0, &axis));
527: PetscCall(PetscDrawAxisGetLimits(axis, &xl, &xr, &yl, &yr));
528: if (!step) {
529: PetscCall(PetscDrawClear(draw));
530: PetscCall(PetscDrawAxisDraw(axis));
531: }
533: PetscCall(VecGetArrayRead(u, &U));
534: U0 = PetscRealPart(U[0]);
535: U1 = PetscRealPart(U[1]);
536: PetscCall(VecRestoreArrayRead(u, &U));
537: if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(PETSC_SUCCESS);
539: PetscDrawCollectiveBegin(draw);
540: PetscCall(PetscDrawPoint(draw, U0, U1, PETSC_DRAW_BLACK));
541: if (ictx->showtimestepandtime) {
542: PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
543: PetscCall(PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime));
544: h = yl + .95 * (yr - yl);
545: PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
546: }
547: PetscDrawCollectiveEnd(draw);
548: PetscCall(PetscDrawFlush(draw));
549: PetscCall(PetscDrawPause(draw));
550: PetscCall(PetscDrawSave(draw));
551: PetscFunctionReturn(PETSC_SUCCESS);
552: }
554: /*@C
555: TSMonitorDrawCtxDestroy - Destroys the monitor context for `TSMonitorDrawSolution()`
557: Collective
559: Input Parameter:
560: . ctx - the monitor context
562: Level: intermediate
564: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawSolution()`, `TSMonitorDrawError()`, `TSMonitorDrawCtx`
565: @*/
566: PetscErrorCode TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
567: {
568: PetscFunctionBegin;
569: PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
570: PetscCall(VecDestroy(&(*ictx)->initialsolution));
571: PetscCall(PetscFree(*ictx));
572: PetscFunctionReturn(PETSC_SUCCESS);
573: }
575: /*@C
576: TSMonitorDrawCtxCreate - Creates the monitor context for `TSMonitorDrawCtx`
578: Collective
580: Input Parameter:
581: . ts - time-step context
583: Output Parameter:
584: . ctx - the monitor context
586: Options Database Keys:
587: + -ts_monitor_draw_solution - draw the solution at each time-step
588: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution
590: Level: intermediate
592: Note:
593: The context created by this function, `PetscMonitorDrawSolution()`, and `TSMonitorDrawCtxDestroy()` should be passed together to `TSMonitorSet()`.
595: .seealso: [](ch_ts), `TS`, `TSMonitorDrawCtxDestroy()`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtx`, `PetscMonitorDrawSolution()`
596: @*/
597: PetscErrorCode TSMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorDrawCtx *ctx)
598: {
599: PetscFunctionBegin;
600: PetscCall(PetscNew(ctx));
601: PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
602: PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
604: (*ctx)->howoften = howoften;
605: (*ctx)->showinitial = PETSC_FALSE;
606: PetscCall(PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_initial", &(*ctx)->showinitial, NULL));
608: (*ctx)->showtimestepandtime = PETSC_FALSE;
609: PetscCall(PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_show_time", &(*ctx)->showtimestepandtime, NULL));
610: PetscFunctionReturn(PETSC_SUCCESS);
611: }
613: /*@C
614: TSMonitorDrawSolutionFunction - Monitors progress of the `TS` solvers by calling
615: `VecView()` for the solution provided by `TSSetSolutionFunction()` at each timestep
617: Collective
619: Input Parameters:
620: + ts - the `TS` context
621: . step - current time-step
622: . ptime - current time
623: - dummy - either a viewer or `NULL`
625: Options Database Key:
626: . -ts_monitor_draw_solution_function - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`
628: Level: intermediate
630: Note:
631: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
632: to be used during the `TS` integration.
634: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
635: @*/
636: PetscErrorCode TSMonitorDrawSolutionFunction(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
637: {
638: TSMonitorDrawCtx ctx = (TSMonitorDrawCtx)dummy;
639: PetscViewer viewer = ctx->viewer;
640: Vec work;
642: PetscFunctionBegin;
643: if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
644: PetscCall(VecDuplicate(u, &work));
645: PetscCall(TSComputeSolutionFunction(ts, ptime, work));
646: PetscCall(VecView(work, viewer));
647: PetscCall(VecDestroy(&work));
648: PetscFunctionReturn(PETSC_SUCCESS);
649: }
651: /*@C
652: TSMonitorDrawError - Monitors progress of the `TS` solvers by calling
653: `VecView()` for the error at each timestep
655: Collective
657: Input Parameters:
658: + ts - the `TS` context
659: . step - current time-step
660: . ptime - current time
661: - dummy - either a viewer or `NULL`
663: Options Database Key:
664: . -ts_monitor_draw_error - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`
666: Level: intermediate
668: Notes:
669: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
670: to be used during the `TS` integration.
672: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
673: @*/
674: PetscErrorCode TSMonitorDrawError(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
675: {
676: TSMonitorDrawCtx ctx = (TSMonitorDrawCtx)dummy;
677: PetscViewer viewer = ctx->viewer;
678: Vec work;
680: PetscFunctionBegin;
681: if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
682: PetscCall(VecDuplicate(u, &work));
683: PetscCall(TSComputeSolutionFunction(ts, ptime, work));
684: PetscCall(VecAXPY(work, -1.0, u));
685: PetscCall(VecView(work, viewer));
686: PetscCall(VecDestroy(&work));
687: PetscFunctionReturn(PETSC_SUCCESS);
688: }
690: /*@C
691: 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
693: Collective
695: Input Parameters:
696: + ts - the `TS` context
697: . step - current time-step
698: . ptime - current time
699: . u - current state
700: - vf - viewer and its format
702: Level: intermediate
704: Notes:
705: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
706: to be used during the `TS` integration.
708: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
709: @*/
710: PetscErrorCode TSMonitorSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
711: {
712: PetscFunctionBegin;
713: if (vf->view_interval > 0 && !ts->reason && step % vf->view_interval != 0) PetscFunctionReturn(PETSC_SUCCESS);
714: PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
715: PetscCall(VecView(u, vf->viewer));
716: PetscCall(PetscViewerPopFormat(vf->viewer));
717: PetscFunctionReturn(PETSC_SUCCESS);
718: }
720: /*@C
721: TSMonitorSolutionVTK - Monitors progress of the `TS` solvers by `VecView()` for the solution at each timestep.
723: Collective
725: Input Parameters:
726: + ts - the `TS` context
727: . step - current time-step
728: . ptime - current time
729: . u - current state
730: - filenametemplate - string containing a format specifier for the integer time step (e.g. %03" PetscInt_FMT ")
732: Level: intermediate
734: Notes:
735: 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.
736: These are named according to the file name template.
738: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
739: to be used during the `TS` integration.
741: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
742: @*/
743: PetscErrorCode TSMonitorSolutionVTK(TS ts, PetscInt step, PetscReal ptime, Vec u, void *filenametemplate)
744: {
745: char filename[PETSC_MAX_PATH_LEN];
746: PetscViewer viewer;
748: PetscFunctionBegin;
749: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
750: PetscCall(PetscSNPrintf(filename, sizeof(filename), (const char *)filenametemplate, step));
751: PetscCall(PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts), filename, FILE_MODE_WRITE, &viewer));
752: PetscCall(VecView(u, viewer));
753: PetscCall(PetscViewerDestroy(&viewer));
754: PetscFunctionReturn(PETSC_SUCCESS);
755: }
757: /*@C
758: TSMonitorSolutionVTKDestroy - Destroy filename template string created for use with `TSMonitorSolutionVTK()`
760: Not Collective
762: Input Parameter:
763: . filenametemplate - string containing a format specifier for the integer time step (e.g. %03" PetscInt_FMT ")
765: Level: intermediate
767: Note:
768: This function is normally passed to `TSMonitorSet()` along with `TSMonitorSolutionVTK()`.
770: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorSolutionVTK()`
771: @*/
772: PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
773: {
774: PetscFunctionBegin;
775: PetscCall(PetscFree(*(char **)filenametemplate));
776: PetscFunctionReturn(PETSC_SUCCESS);
777: }
779: /*@C
780: TSMonitorLGSolution - Monitors progress of the `TS` solvers by plotting each component of the solution vector
781: in a time based line graph
783: Collective
785: Input Parameters:
786: + ts - the `TS` context
787: . step - current time-step
788: . ptime - current time
789: . u - current solution
790: - dctx - the `TSMonitorLGCtx` object that contains all the options for the monitoring, this is created with `TSMonitorLGCtxCreate()`
792: Options Database Key:
793: . -ts_monitor_lg_solution_variables - enable monitor of lg solution variables
795: Level: intermediate
797: Notes:
798: Each process in a parallel run displays its component solutions in a separate window
800: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
801: to be used during the `TS` integration.
803: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
804: `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
805: `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGError()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
806: `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
807: @*/
808: PetscErrorCode TSMonitorLGSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
809: {
810: TSMonitorLGCtx ctx = (TSMonitorLGCtx)dctx;
811: const PetscScalar *yy;
812: Vec v;
814: PetscFunctionBegin;
815: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
816: if (!step) {
817: PetscDrawAxis axis;
818: PetscInt dim;
819: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
820: PetscCall(PetscDrawAxisSetLabels(axis, "Solution as function of time", "Time", "Solution"));
821: if (!ctx->names) {
822: PetscBool flg;
823: /* user provides names of variables to plot but no names has been set so assume names are integer values */
824: PetscCall(PetscOptionsHasName(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", &flg));
825: if (flg) {
826: PetscInt i, n;
827: char **names;
828: PetscCall(VecGetSize(u, &n));
829: PetscCall(PetscMalloc1(n + 1, &names));
830: for (i = 0; i < n; i++) {
831: PetscCall(PetscMalloc1(5, &names[i]));
832: PetscCall(PetscSNPrintf(names[i], 5, "%" PetscInt_FMT, i));
833: }
834: names[n] = NULL;
835: ctx->names = names;
836: }
837: }
838: if (ctx->names && !ctx->displaynames) {
839: char **displaynames;
840: PetscBool flg;
841: PetscCall(VecGetLocalSize(u, &dim));
842: PetscCall(PetscCalloc1(dim + 1, &displaynames));
843: PetscCall(PetscOptionsGetStringArray(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", displaynames, &dim, &flg));
844: if (flg) PetscCall(TSMonitorLGCtxSetDisplayVariables(ctx, (const char *const *)displaynames));
845: PetscCall(PetscStrArrayDestroy(&displaynames));
846: }
847: if (ctx->displaynames) {
848: PetscCall(PetscDrawLGSetDimension(ctx->lg, ctx->ndisplayvariables));
849: PetscCall(PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->displaynames));
850: } else if (ctx->names) {
851: PetscCall(VecGetLocalSize(u, &dim));
852: PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
853: PetscCall(PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->names));
854: } else {
855: PetscCall(VecGetLocalSize(u, &dim));
856: PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
857: }
858: PetscCall(PetscDrawLGReset(ctx->lg));
859: }
861: if (!ctx->transform) v = u;
862: else PetscCall((*ctx->transform)(ctx->transformctx, u, &v));
863: PetscCall(VecGetArrayRead(v, &yy));
864: if (ctx->displaynames) {
865: PetscInt i;
866: for (i = 0; i < ctx->ndisplayvariables; i++) ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
867: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, ctx->displayvalues));
868: } else {
869: #if defined(PETSC_USE_COMPLEX)
870: PetscInt i, n;
871: PetscReal *yreal;
872: PetscCall(VecGetLocalSize(v, &n));
873: PetscCall(PetscMalloc1(n, &yreal));
874: for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
875: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal));
876: PetscCall(PetscFree(yreal));
877: #else
878: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy));
879: #endif
880: }
881: PetscCall(VecRestoreArrayRead(v, &yy));
882: if (ctx->transform) PetscCall(VecDestroy(&v));
884: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
885: PetscCall(PetscDrawLGDraw(ctx->lg));
886: PetscCall(PetscDrawLGSave(ctx->lg));
887: }
888: PetscFunctionReturn(PETSC_SUCCESS);
889: }
891: /*@C
892: TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
894: Collective
896: Input Parameters:
897: + ts - the `TS` context
898: - names - the names of the components, final string must be `NULL`
900: Level: intermediate
902: Notes:
903: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
905: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetVariableNames()`
906: @*/
907: PetscErrorCode TSMonitorLGSetVariableNames(TS ts, const char *const *names)
908: {
909: PetscInt i;
911: PetscFunctionBegin;
912: for (i = 0; i < ts->numbermonitors; i++) {
913: if (ts->monitor[i] == TSMonitorLGSolution) {
914: PetscCall(TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i], names));
915: break;
916: }
917: }
918: PetscFunctionReturn(PETSC_SUCCESS);
919: }
921: /*@C
922: TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
924: Collective
926: Input Parameters:
927: + ts - the `TS` context
928: - names - the names of the components, final string must be `NULL`
930: Level: intermediate
932: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGSetVariableNames()`
933: @*/
934: PetscErrorCode TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx, const char *const *names)
935: {
936: PetscFunctionBegin;
937: PetscCall(PetscStrArrayDestroy(&ctx->names));
938: PetscCall(PetscStrArrayallocpy(names, &ctx->names));
939: PetscFunctionReturn(PETSC_SUCCESS);
940: }
942: /*@C
943: TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
945: Collective
947: Input Parameter:
948: . ts - the `TS` context
950: Output Parameter:
951: . names - the names of the components, final string must be `NULL`
953: Level: intermediate
955: Note:
956: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
958: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
959: @*/
960: PetscErrorCode TSMonitorLGGetVariableNames(TS ts, const char *const **names)
961: {
962: PetscInt i;
964: PetscFunctionBegin;
965: *names = NULL;
966: for (i = 0; i < ts->numbermonitors; i++) {
967: if (ts->monitor[i] == TSMonitorLGSolution) {
968: TSMonitorLGCtx ctx = (TSMonitorLGCtx)ts->monitorcontext[i];
969: *names = (const char *const *)ctx->names;
970: break;
971: }
972: }
973: PetscFunctionReturn(PETSC_SUCCESS);
974: }
976: /*@C
977: TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
979: Collective
981: Input Parameters:
982: + ctx - the `TSMonitorLG` context
983: - displaynames - the names of the components, final string must be `NULL`
985: Level: intermediate
987: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
988: @*/
989: PetscErrorCode TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx, const char *const *displaynames)
990: {
991: PetscInt j = 0, k;
993: PetscFunctionBegin;
994: if (!ctx->names) PetscFunctionReturn(PETSC_SUCCESS);
995: PetscCall(PetscStrArrayDestroy(&ctx->displaynames));
996: PetscCall(PetscStrArrayallocpy(displaynames, &ctx->displaynames));
997: while (displaynames[j]) j++;
998: ctx->ndisplayvariables = j;
999: PetscCall(PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvariables));
1000: PetscCall(PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvalues));
1001: j = 0;
1002: while (displaynames[j]) {
1003: k = 0;
1004: while (ctx->names[k]) {
1005: PetscBool flg;
1006: PetscCall(PetscStrcmp(displaynames[j], ctx->names[k], &flg));
1007: if (flg) {
1008: ctx->displayvariables[j] = k;
1009: break;
1010: }
1011: k++;
1012: }
1013: j++;
1014: }
1015: PetscFunctionReturn(PETSC_SUCCESS);
1016: }
1018: /*@C
1019: TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
1021: Collective
1023: Input Parameters:
1024: + ts - the `TS` context
1025: - displaynames - the names of the components, final string must be `NULL`
1027: Level: intermediate
1029: Note:
1030: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
1032: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
1033: @*/
1034: PetscErrorCode TSMonitorLGSetDisplayVariables(TS ts, const char *const *displaynames)
1035: {
1036: PetscInt i;
1038: PetscFunctionBegin;
1039: for (i = 0; i < ts->numbermonitors; i++) {
1040: if (ts->monitor[i] == TSMonitorLGSolution) {
1041: PetscCall(TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i], displaynames));
1042: break;
1043: }
1044: }
1045: PetscFunctionReturn(PETSC_SUCCESS);
1046: }
1048: /*@C
1049: TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
1051: Collective
1053: Input Parameters:
1054: + ts - the `TS` context
1055: . transform - the transform function
1056: . destroy - function to destroy the optional context
1057: - ctx - optional context used by transform function
1059: Level: intermediate
1061: Note:
1062: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
1064: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGCtxSetTransform()`
1065: @*/
1066: PetscErrorCode TSMonitorLGSetTransform(TS ts, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
1067: {
1068: PetscInt i;
1070: PetscFunctionBegin;
1071: for (i = 0; i < ts->numbermonitors; i++) {
1072: if (ts->monitor[i] == TSMonitorLGSolution) PetscCall(TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i], transform, destroy, tctx));
1073: }
1074: PetscFunctionReturn(PETSC_SUCCESS);
1075: }
1077: /*@C
1078: TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
1080: Collective
1082: Input Parameters:
1083: + ts - the `TS` context
1084: . transform - the transform function
1085: . destroy - function to destroy the optional context
1086: - ctx - optional context used by transform function
1088: Level: intermediate
1090: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGSetTransform()`
1091: @*/
1092: PetscErrorCode TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
1093: {
1094: PetscFunctionBegin;
1095: ctx->transform = transform;
1096: ctx->transformdestroy = destroy;
1097: ctx->transformctx = tctx;
1098: PetscFunctionReturn(PETSC_SUCCESS);
1099: }
1101: /*@C
1102: TSMonitorLGError - Monitors progress of the `TS` solvers by plotting each component of the error
1103: in a time based line graph
1105: Collective
1107: Input Parameters:
1108: + ts - the `TS` context
1109: . step - current time-step
1110: . ptime - current time
1111: . u - current solution
1112: - dctx - `TSMonitorLGCtx` object created with `TSMonitorLGCtxCreate()`
1114: Options Database Key:
1115: . -ts_monitor_lg_error - create a graphical monitor of error history
1117: Level: intermediate
1119: Notes:
1120: Each process in a parallel run displays its component errors in a separate window
1122: The user must provide the solution using `TSSetSolutionFunction()` to use this monitor.
1124: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1125: to be used during the TS integration.
1127: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1128: @*/
1129: PetscErrorCode TSMonitorLGError(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
1130: {
1131: TSMonitorLGCtx ctx = (TSMonitorLGCtx)dummy;
1132: const PetscScalar *yy;
1133: Vec y;
1135: PetscFunctionBegin;
1136: if (!step) {
1137: PetscDrawAxis axis;
1138: PetscInt dim;
1139: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1140: PetscCall(PetscDrawAxisSetLabels(axis, "Error in solution as function of time", "Time", "Error"));
1141: PetscCall(VecGetLocalSize(u, &dim));
1142: PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
1143: PetscCall(PetscDrawLGReset(ctx->lg));
1144: }
1145: PetscCall(VecDuplicate(u, &y));
1146: PetscCall(TSComputeSolutionFunction(ts, ptime, y));
1147: PetscCall(VecAXPY(y, -1.0, u));
1148: PetscCall(VecGetArrayRead(y, &yy));
1149: #if defined(PETSC_USE_COMPLEX)
1150: {
1151: PetscReal *yreal;
1152: PetscInt i, n;
1153: PetscCall(VecGetLocalSize(y, &n));
1154: PetscCall(PetscMalloc1(n, &yreal));
1155: for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
1156: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal));
1157: PetscCall(PetscFree(yreal));
1158: }
1159: #else
1160: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy));
1161: #endif
1162: PetscCall(VecRestoreArrayRead(y, &yy));
1163: PetscCall(VecDestroy(&y));
1164: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1165: PetscCall(PetscDrawLGDraw(ctx->lg));
1166: PetscCall(PetscDrawLGSave(ctx->lg));
1167: }
1168: PetscFunctionReturn(PETSC_SUCCESS);
1169: }
1171: /*@C
1172: TSMonitorSPSwarmSolution - Graphically displays phase plots of `DMSWARM` particles on a scatter plot
1174: Input Parameters:
1175: + ts - the `TS` context
1176: . step - current time-step
1177: . ptime - current time
1178: . u - current solution
1179: - dctx - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorSPCtxCreate()`
1181: Options Database Keys:
1182: + -ts_monitor_sp_swarm <n> - Monitor the solution every n steps, or -1 for plotting only the final solution
1183: . -ts_monitor_sp_swarm_retain <n> - Retain n old points so we can see the history, or -1 for all points
1184: . -ts_monitor_sp_swarm_multi_species <bool> - Color each species differently
1185: - -ts_monitor_sp_swarm_phase <bool> - Plot in phase space, as opposed to coordinate space
1187: Level: intermediate
1189: Notes:
1190: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1191: to be used during the `TS` integration.
1193: .seealso: [](ch_ts), `TS`, `TSMonitoSet()`, `DMSWARM`, `TSMonitorSPCtxCreate()`
1194: @*/
1195: PetscErrorCode TSMonitorSPSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1196: {
1197: TSMonitorSPCtx ctx = (TSMonitorSPCtx)dctx;
1198: PetscDraw draw;
1199: DM dm, cdm;
1200: const PetscScalar *yy;
1201: PetscInt Np, p, dim = 2, *species;
1202: PetscReal species_color;
1204: PetscFunctionBegin;
1205: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1206: PetscCall(TSGetDM(ts, &dm));
1207: if (!step) {
1208: PetscDrawAxis axis;
1209: PetscReal dmboxlower[2], dmboxupper[2];
1211: PetscCall(TSGetDM(ts, &dm));
1212: PetscCall(DMGetDimension(dm, &dim));
1213: PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Monitor only supports two dimensional fields");
1214: PetscCall(DMSwarmGetCellDM(dm, &cdm));
1215: PetscCall(DMGetBoundingBox(cdm, dmboxlower, dmboxupper));
1216: PetscCall(VecGetLocalSize(u, &Np));
1217: Np /= dim * 2;
1218: PetscCall(PetscDrawSPGetAxis(ctx->sp, &axis));
1219: if (ctx->phase) {
1220: PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "X", "V"));
1221: PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], -10, 10));
1222: } else {
1223: PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "X", "Y"));
1224: PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], dmboxlower[1], dmboxupper[1]));
1225: }
1226: PetscCall(PetscDrawAxisSetHoldLimits(axis, PETSC_TRUE));
1227: PetscCall(PetscDrawSPReset(ctx->sp));
1228: }
1229: if (ctx->multispecies) PetscCall(DMSwarmGetField(dm, "species", NULL, NULL, (void **)&species));
1230: PetscCall(VecGetLocalSize(u, &Np));
1231: Np /= dim * 2;
1232: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1233: PetscCall(PetscDrawSPGetDraw(ctx->sp, &draw));
1234: if ((ctx->retain == 0) || (ctx->retain > 0 && !(step % ctx->retain))) PetscCall(PetscDrawClear(draw));
1235: PetscCall(PetscDrawFlush(draw));
1236: PetscCall(PetscDrawSPReset(ctx->sp));
1237: PetscCall(VecGetArrayRead(u, &yy));
1238: for (p = 0; p < Np; ++p) {
1239: PetscReal x, y;
1241: if (ctx->phase) {
1242: x = PetscRealPart(yy[p * dim * 2]);
1243: y = PetscRealPart(yy[p * dim * 2 + dim]);
1244: } else {
1245: x = PetscRealPart(yy[p * dim * 2]);
1246: y = PetscRealPart(yy[p * dim * 2 + 1]);
1247: }
1248: if (ctx->multispecies) {
1249: species_color = species[p] + 2;
1250: PetscCall(PetscDrawSPAddPointColorized(ctx->sp, &x, &y, &species_color));
1251: } else {
1252: PetscCall(PetscDrawSPAddPoint(ctx->sp, &x, &y));
1253: }
1254: PetscCall(PetscDrawSPAddPoint(ctx->sp, &x, &y));
1255: }
1256: PetscCall(VecRestoreArrayRead(u, &yy));
1257: PetscCall(PetscDrawSPDraw(ctx->sp, PETSC_FALSE));
1258: PetscCall(PetscDrawSPSave(ctx->sp));
1259: if (ctx->multispecies) PetscCall(DMSwarmRestoreField(dm, "species", NULL, NULL, (void **)&species));
1260: }
1261: PetscFunctionReturn(PETSC_SUCCESS);
1262: }
1264: /*@C
1265: TSMonitorHGSwarmSolution - Graphically displays histograms of `DMSWARM` particles
1267: Input Parameters:
1268: + ts - the `TS` context
1269: . step - current time-step
1270: . ptime - current time
1271: . u - current solution
1272: - dctx - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorHGCtxCreate()`
1274: Options Database Keys:
1275: + -ts_monitor_hg_swarm <n> - Monitor the solution every n steps, or -1 for plotting only the final solution
1276: . -ts_monitor_hg_swarm_species <num> - Number of species to histogram
1277: . -ts_monitor_hg_swarm_bins <num> - Number of histogram bins
1278: - -ts_monitor_hg_swarm_velocity <bool> - Plot in velocity space, as opposed to coordinate space
1280: Level: intermediate
1282: Note:
1283: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1284: to be used during the `TS` integration.
1286: .seealso: `TSMonitoSet()`
1287: @*/
1288: PetscErrorCode TSMonitorHGSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1289: {
1290: TSMonitorHGCtx ctx = (TSMonitorHGCtx)dctx;
1291: PetscDraw draw;
1292: DM sw;
1293: const PetscScalar *yy;
1294: PetscInt *species;
1295: PetscInt dim, d = 0, Np, p, Ns, s;
1297: PetscFunctionBegin;
1298: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1299: PetscCall(TSGetDM(ts, &sw));
1300: PetscCall(DMGetDimension(sw, &dim));
1301: PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
1302: Ns = PetscMin(Ns, ctx->Ns);
1303: PetscCall(VecGetLocalSize(u, &Np));
1304: Np /= dim * 2;
1305: if (!step) {
1306: PetscDrawAxis axis;
1307: char title[PETSC_MAX_PATH_LEN];
1309: for (s = 0; s < Ns; ++s) {
1310: PetscCall(PetscDrawHGGetAxis(ctx->hg[s], &axis));
1311: PetscCall(PetscSNPrintf(title, PETSC_MAX_PATH_LEN, "Species %" PetscInt_FMT, s));
1312: if (ctx->velocity) PetscCall(PetscDrawAxisSetLabels(axis, title, "V", "N"));
1313: else PetscCall(PetscDrawAxisSetLabels(axis, title, "X", "N"));
1314: }
1315: }
1316: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1317: PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
1318: for (s = 0; s < Ns; ++s) {
1319: PetscCall(PetscDrawHGReset(ctx->hg[s]));
1320: PetscCall(PetscDrawHGGetDraw(ctx->hg[s], &draw));
1321: PetscCall(PetscDrawClear(draw));
1322: PetscCall(PetscDrawFlush(draw));
1323: }
1324: PetscCall(VecGetArrayRead(u, &yy));
1325: for (p = 0; p < Np; ++p) {
1326: const PetscInt s = species[p] < Ns ? species[p] : 0;
1327: PetscReal v;
1329: if (ctx->velocity) v = PetscRealPart(yy[p * dim * 2 + d + dim]);
1330: else v = PetscRealPart(yy[p * dim * 2 + d]);
1331: PetscCall(PetscDrawHGAddValue(ctx->hg[s], v));
1332: }
1333: PetscCall(VecRestoreArrayRead(u, &yy));
1334: for (s = 0; s < Ns; ++s) {
1335: PetscCall(PetscDrawHGDraw(ctx->hg[s]));
1336: PetscCall(PetscDrawHGSave(ctx->hg[s]));
1337: }
1338: PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
1339: }
1340: PetscFunctionReturn(PETSC_SUCCESS);
1341: }
1343: /*@C
1344: TSMonitorError - Monitors progress of the `TS` solvers by printing the 2 norm of the error at each timestep
1346: Collective
1348: Input Parameters:
1349: + ts - the `TS` context
1350: . step - current time-step
1351: . ptime - current time
1352: . u - current solution
1353: - dctx - unused context
1355: Options Database Key:
1356: . -ts_monitor_error - create a graphical monitor of error history
1358: Level: intermediate
1360: Notes:
1361: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1362: to be used during the `TS` integration.
1364: The user must provide the solution using `TSSetSolutionFunction()` to use this monitor.
1366: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1367: @*/
1368: PetscErrorCode TSMonitorError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
1369: {
1370: DM dm;
1371: PetscDS ds = NULL;
1372: PetscInt Nf = -1, f;
1373: PetscBool flg;
1375: PetscFunctionBegin;
1376: PetscCall(TSGetDM(ts, &dm));
1377: if (dm) PetscCall(DMGetDS(dm, &ds));
1378: if (ds) PetscCall(PetscDSGetNumFields(ds, &Nf));
1379: if (Nf <= 0) {
1380: Vec y;
1381: PetscReal nrm;
1383: PetscCall(VecDuplicate(u, &y));
1384: PetscCall(TSComputeSolutionFunction(ts, ptime, y));
1385: PetscCall(VecAXPY(y, -1.0, u));
1386: PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERASCII, &flg));
1387: if (flg) {
1388: PetscCall(VecNorm(y, NORM_2, &nrm));
1389: PetscCall(PetscViewerASCIIPrintf(vf->viewer, "2-norm of error %g\n", (double)nrm));
1390: }
1391: PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &flg));
1392: if (flg) PetscCall(VecView(y, vf->viewer));
1393: PetscCall(VecDestroy(&y));
1394: } else {
1395: PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx);
1396: void **ctxs;
1397: Vec v;
1398: PetscReal ferrors[1];
1400: PetscCall(PetscMalloc2(Nf, &exactFuncs, Nf, &ctxs));
1401: for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(ds, f, &exactFuncs[f], &ctxs[f]));
1402: PetscCall(DMComputeL2FieldDiff(dm, ptime, exactFuncs, ctxs, u, ferrors));
1403: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Timestep: %04d time = %-8.4g \t L_2 Error: [", (int)step, (double)ptime));
1404: for (f = 0; f < Nf; ++f) {
1405: if (f > 0) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ", "));
1406: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%2.3g", (double)ferrors[f]));
1407: }
1408: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "]\n"));
1410: PetscCall(VecViewFromOptions(u, NULL, "-sol_vec_view"));
1412: PetscCall(PetscOptionsHasName(NULL, NULL, "-exact_vec_view", &flg));
1413: if (flg) {
1414: PetscCall(DMGetGlobalVector(dm, &v));
1415: PetscCall(DMProjectFunction(dm, ptime, exactFuncs, ctxs, INSERT_ALL_VALUES, v));
1416: PetscCall(PetscObjectSetName((PetscObject)v, "Exact Solution"));
1417: PetscCall(VecViewFromOptions(v, NULL, "-exact_vec_view"));
1418: PetscCall(DMRestoreGlobalVector(dm, &v));
1419: }
1420: PetscCall(PetscFree2(exactFuncs, ctxs));
1421: }
1422: PetscFunctionReturn(PETSC_SUCCESS);
1423: }
1425: PetscErrorCode TSMonitorLGSNESIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, void *monctx)
1426: {
1427: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1428: PetscReal x = ptime, y;
1429: PetscInt its;
1431: PetscFunctionBegin;
1432: if (n < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1433: if (!n) {
1434: PetscDrawAxis axis;
1435: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1436: PetscCall(PetscDrawAxisSetLabels(axis, "Nonlinear iterations as function of time", "Time", "SNES Iterations"));
1437: PetscCall(PetscDrawLGReset(ctx->lg));
1438: ctx->snes_its = 0;
1439: }
1440: PetscCall(TSGetSNESIterations(ts, &its));
1441: y = its - ctx->snes_its;
1442: PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
1443: if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1444: PetscCall(PetscDrawLGDraw(ctx->lg));
1445: PetscCall(PetscDrawLGSave(ctx->lg));
1446: }
1447: ctx->snes_its = its;
1448: PetscFunctionReturn(PETSC_SUCCESS);
1449: }
1451: PetscErrorCode TSMonitorLGKSPIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, void *monctx)
1452: {
1453: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1454: PetscReal x = ptime, y;
1455: PetscInt its;
1457: PetscFunctionBegin;
1458: if (n < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1459: if (!n) {
1460: PetscDrawAxis axis;
1461: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1462: PetscCall(PetscDrawAxisSetLabels(axis, "Linear iterations as function of time", "Time", "KSP Iterations"));
1463: PetscCall(PetscDrawLGReset(ctx->lg));
1464: ctx->ksp_its = 0;
1465: }
1466: PetscCall(TSGetKSPIterations(ts, &its));
1467: y = its - ctx->ksp_its;
1468: PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
1469: if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1470: PetscCall(PetscDrawLGDraw(ctx->lg));
1471: PetscCall(PetscDrawLGSave(ctx->lg));
1472: }
1473: ctx->ksp_its = its;
1474: PetscFunctionReturn(PETSC_SUCCESS);
1475: }
1477: /*@C
1478: TSMonitorEnvelopeCtxCreate - Creates a context for use with `TSMonitorEnvelope()`
1480: Collective
1482: Input Parameter:
1483: . ts - the `TS` solver object
1485: Output Parameter:
1486: . ctx - the context
1488: Level: intermediate
1490: .seealso: [](ch_ts), `TS`, `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`
1491: @*/
1492: PetscErrorCode TSMonitorEnvelopeCtxCreate(TS ts, TSMonitorEnvelopeCtx *ctx)
1493: {
1494: PetscFunctionBegin;
1495: PetscCall(PetscNew(ctx));
1496: PetscFunctionReturn(PETSC_SUCCESS);
1497: }
1499: /*@C
1500: TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
1502: Collective
1504: Input Parameters:
1505: + ts - the `TS` context
1506: . step - current time-step
1507: . ptime - current time
1508: . u - current solution
1509: - dctx - the envelope context
1511: Options Database Key:
1512: . -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time
1514: Level: intermediate
1516: Notes:
1517: After a solve you can use `TSMonitorEnvelopeGetBounds()` to access the envelope
1519: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1520: to be used during the `TS` integration.
1522: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxCreate()`
1523: @*/
1524: PetscErrorCode TSMonitorEnvelope(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1525: {
1526: TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
1528: PetscFunctionBegin;
1529: if (!ctx->max) {
1530: PetscCall(VecDuplicate(u, &ctx->max));
1531: PetscCall(VecDuplicate(u, &ctx->min));
1532: PetscCall(VecCopy(u, ctx->max));
1533: PetscCall(VecCopy(u, ctx->min));
1534: } else {
1535: PetscCall(VecPointwiseMax(ctx->max, u, ctx->max));
1536: PetscCall(VecPointwiseMin(ctx->min, u, ctx->min));
1537: }
1538: PetscFunctionReturn(PETSC_SUCCESS);
1539: }
1541: /*@C
1542: TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
1544: Collective
1546: Input Parameter:
1547: . ts - the `TS` context
1549: Output Parameters:
1550: + max - the maximum values
1551: - min - the minimum values
1553: Level: intermediate
1555: Notes:
1556: If the `TS` does not have a `TSMonitorEnvelopeCtx` associated with it then this function is ignored
1558: .seealso: [](ch_ts), `TSMonitorEnvelopeCtx`, `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
1559: @*/
1560: PetscErrorCode TSMonitorEnvelopeGetBounds(TS ts, Vec *max, Vec *min)
1561: {
1562: PetscInt i;
1564: PetscFunctionBegin;
1565: if (max) *max = NULL;
1566: if (min) *min = NULL;
1567: for (i = 0; i < ts->numbermonitors; i++) {
1568: if (ts->monitor[i] == TSMonitorEnvelope) {
1569: TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)ts->monitorcontext[i];
1570: if (max) *max = ctx->max;
1571: if (min) *min = ctx->min;
1572: break;
1573: }
1574: }
1575: PetscFunctionReturn(PETSC_SUCCESS);
1576: }
1578: /*@C
1579: TSMonitorEnvelopeCtxDestroy - Destroys a context that was created with `TSMonitorEnvelopeCtxCreate()`.
1581: Collective
1583: Input Parameter:
1584: . ctx - the monitor context
1586: Level: intermediate
1588: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
1589: @*/
1590: PetscErrorCode TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
1591: {
1592: PetscFunctionBegin;
1593: PetscCall(VecDestroy(&(*ctx)->min));
1594: PetscCall(VecDestroy(&(*ctx)->max));
1595: PetscCall(PetscFree(*ctx));
1596: PetscFunctionReturn(PETSC_SUCCESS);
1597: }
1599: /*@C
1600: TSDMSwarmMonitorMoments - Monitors the first three moments of a `DMSWARM` being evolved by the `TS`
1602: Not Collective
1604: Input Parameters:
1605: + ts - the `TS` context
1606: . step - current timestep
1607: . t - current time
1608: . u - current solution
1609: - ctx - not used
1611: Options Database Key:
1612: . -ts_dmswarm_monitor_moments - Monitor moments of particle distribution
1614: Level: intermediate
1616: Notes:
1617: This requires a `DMSWARM` be attached to the `TS`.
1619: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1620: to be used during the TS integration.
1622: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `DMSWARM`
1623: @*/
1624: PetscErrorCode TSDMSwarmMonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, PetscViewerAndFormat *vf)
1625: {
1626: DM sw;
1627: const PetscScalar *u;
1628: PetscReal m = 1.0, totE = 0., totMom[3] = {0., 0., 0.};
1629: PetscInt dim, d, Np, p;
1630: MPI_Comm comm;
1632: PetscFunctionBeginUser;
1633: PetscCall(TSGetDM(ts, &sw));
1634: if (!sw || step % ts->monitorFrequency != 0) PetscFunctionReturn(PETSC_SUCCESS);
1635: PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
1636: PetscCall(DMGetDimension(sw, &dim));
1637: PetscCall(VecGetLocalSize(U, &Np));
1638: Np /= dim;
1639: PetscCall(VecGetArrayRead(U, &u));
1640: for (p = 0; p < Np; ++p) {
1641: for (d = 0; d < dim; ++d) {
1642: totE += PetscRealPart(u[p * dim + d] * u[p * dim + d]);
1643: totMom[d] += PetscRealPart(u[p * dim + d]);
1644: }
1645: }
1646: PetscCall(VecRestoreArrayRead(U, &u));
1647: for (d = 0; d < dim; ++d) totMom[d] *= m;
1648: totE *= 0.5 * m;
1649: PetscCall(PetscPrintf(comm, "Step %4" PetscInt_FMT " Total Energy: %10.8lf", step, (double)totE));
1650: for (d = 0; d < dim; ++d) PetscCall(PetscPrintf(comm, " Total Momentum %c: %10.8lf", (char)('x' + d), (double)totMom[d]));
1651: PetscCall(PetscPrintf(comm, "\n"));
1652: PetscFunctionReturn(PETSC_SUCCESS);
1653: }