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()`,
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: - mdestroy - [optional] routine that frees monitor context (may be `NULL`)
102: Calling sequence of `monitor`:
103: + ts - the `TS` context
104: . 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)
105: . time - current time
106: . u - current iterate
107: - ctx - [optional] monitoring context
109: Level: intermediate
111: Note:
112: This routine adds an additional monitor to the list of monitors that already has been loaded.
114: Fortran Notes:
115: Only a single monitor function can be set for each `TS` object
117: .seealso: [](ch_ts), `TSMonitorDefault()`, `TSMonitorCancel()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
118: `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
119: `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`
120: @*/
121: PetscErrorCode TSMonitorSet(TS ts, PetscErrorCode (*monitor)(TS ts, PetscInt steps, PetscReal time, Vec u, void *ctx), void *mctx, PetscErrorCode (*mdestroy)(void **))
122: {
123: PetscInt i;
124: PetscBool identical;
126: PetscFunctionBegin;
128: for (i = 0; i < ts->numbermonitors; i++) {
129: PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))monitor, mctx, mdestroy, (PetscErrorCode(*)(void))ts->monitor[i], ts->monitorcontext[i], ts->monitordestroy[i], &identical));
130: if (identical) PetscFunctionReturn(PETSC_SUCCESS);
131: }
132: PetscCheck(ts->numbermonitors < MAXTSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
133: ts->monitor[ts->numbermonitors] = monitor;
134: ts->monitordestroy[ts->numbermonitors] = mdestroy;
135: ts->monitorcontext[ts->numbermonitors++] = (void *)mctx;
136: PetscFunctionReturn(PETSC_SUCCESS);
137: }
139: /*@C
140: TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
142: Logically Collective
144: Input Parameter:
145: . ts - the `TS` context obtained from `TSCreate()`
147: Level: intermediate
149: Note:
150: There is no way to remove a single, specific monitor.
152: .seealso: [](ch_ts), `TS`, `TSMonitorDefault()`, `TSMonitorSet()`
153: @*/
154: PetscErrorCode TSMonitorCancel(TS ts)
155: {
156: PetscInt i;
158: PetscFunctionBegin;
160: for (i = 0; i < ts->numbermonitors; i++) {
161: if (ts->monitordestroy[i]) PetscCall((*ts->monitordestroy[i])(&ts->monitorcontext[i]));
162: }
163: ts->numbermonitors = 0;
164: PetscFunctionReturn(PETSC_SUCCESS);
165: }
167: /*@C
168: TSMonitorDefault - The default monitor, prints the timestep and time for each step
170: Input Parameters:
171: + ts - the `TS` context
172: . 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)
173: . ptime - current time
174: . v - current iterate
175: - vf - the viewer and format
177: Options Database Key:
178: . -ts_monitor - monitors the time integration
180: Level: intermediate
182: Notes:
183: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
184: to be used during the `TS` integration.
186: .seealso: [](ch_ts), `TSMonitorSet()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
187: `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
188: `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`
189: @*/
190: PetscErrorCode TSMonitorDefault(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
191: {
192: PetscViewer viewer = vf->viewer;
193: PetscBool iascii, ibinary;
195: PetscFunctionBegin;
197: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
198: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
199: PetscCall(PetscViewerPushFormat(viewer, vf->format));
200: if (iascii) {
201: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
202: if (step == -1) { /* this indicates it is an interpolated solution */
203: PetscCall(PetscViewerASCIIPrintf(viewer, "Interpolated solution at time %g between steps %" PetscInt_FMT " and %" PetscInt_FMT "\n", (double)ptime, ts->steps - 1, ts->steps));
204: } else {
205: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)\n" : "\n"));
206: }
207: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
208: } else if (ibinary) {
209: PetscMPIInt rank;
210: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
211: if (rank == 0) {
212: PetscBool skipHeader;
213: PetscInt classid = REAL_FILE_CLASSID;
215: PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
216: if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
217: PetscCall(PetscRealView(1, &ptime, viewer));
218: } else {
219: PetscCall(PetscRealView(0, &ptime, viewer));
220: }
221: }
222: PetscCall(PetscViewerPopFormat(viewer));
223: PetscFunctionReturn(PETSC_SUCCESS);
224: }
226: /*@C
227: TSMonitorExtreme - Prints the extreme values of the solution at each timestep
229: Input Parameters:
230: + ts - the `TS` context
231: . 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)
232: . ptime - current time
233: . v - current iterate
234: - vf - the viewer and format
236: Level: intermediate
238: Note:
239: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
240: to be used during the `TS` integration.
242: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`
243: @*/
244: PetscErrorCode TSMonitorExtreme(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
245: {
246: PetscViewer viewer = vf->viewer;
247: PetscBool iascii;
248: PetscReal max, min;
250: PetscFunctionBegin;
252: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
253: PetscCall(PetscViewerPushFormat(viewer, vf->format));
254: if (iascii) {
255: PetscCall(VecMax(v, NULL, &max));
256: PetscCall(VecMin(v, NULL, &min));
257: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
258: 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));
259: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
260: }
261: PetscCall(PetscViewerPopFormat(viewer));
262: PetscFunctionReturn(PETSC_SUCCESS);
263: }
265: /*@C
266: TSMonitorLGCtxCreate - Creates a `TSMonitorLGCtx` context for use with
267: `TS` to monitor the solution process graphically in various ways
269: Collective
271: Input Parameters:
272: + comm - the MPI communicator to use
273: . host - the X display to open, or `NULL` for the local machine
274: . label - the title to put in the title bar
275: . x - the x screen coordinates of the upper left coordinate of the window
276: . y - the y screen coordinates of the upper left coordinate of the window
277: . m - the screen width in pixels
278: . n - the screen height in pixels
279: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
281: Output Parameter:
282: . ctx - the context
284: Options Database Keys:
285: + -ts_monitor_lg_timestep - automatically sets line graph monitor
286: . -ts_monitor_lg_timestep_log - automatically sets line graph monitor
287: . -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling `TSMonitorLGSetDisplayVariables()` or `TSMonitorLGCtxSetDisplayVariables()`)
288: . -ts_monitor_lg_error - monitor the error
289: . -ts_monitor_lg_ksp_iterations - monitor the number of `KSP` iterations needed for each timestep
290: . -ts_monitor_lg_snes_iterations - monitor the number of `SNES` iterations needed for each timestep
291: - -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
293: Level: intermediate
295: Notes:
296: Pass the context and `TSMonitorLGCtxDestroy()` to `TSMonitorSet()` to have the context destroyed when no longer needed.
298: One can provide a function that transforms the solution before plotting it with `TSMonitorLGCtxSetTransform()` or `TSMonitorLGSetTransform()`
300: Many of the functions that control the monitoring have two forms\: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a `TS` object as the
301: 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
302: as the first argument.
304: One can control the names displayed for each solution or error variable with `TSMonitorLGCtxSetVariableNames()` or `TSMonitorLGSetVariableNames()`
306: .seealso: [](ch_ts), `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorDefault()`, `VecView()`,
307: `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
308: `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
309: `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
310: `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
311: @*/
312: PetscErrorCode TSMonitorLGCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorLGCtx *ctx)
313: {
314: PetscDraw draw;
316: PetscFunctionBegin;
317: PetscCall(PetscNew(ctx));
318: PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
319: PetscCall(PetscDrawSetFromOptions(draw));
320: PetscCall(PetscDrawLGCreate(draw, 1, &(*ctx)->lg));
321: PetscCall(PetscDrawLGSetFromOptions((*ctx)->lg));
322: PetscCall(PetscDrawDestroy(&draw));
323: (*ctx)->howoften = howoften;
324: PetscFunctionReturn(PETSC_SUCCESS);
325: }
327: /*@C
328: TSMonitorLGTimeStep - Monitors a `TS` by printing the time-steps
330: Collective
332: Input Parameters:
333: + ts - the time integrator
334: . step - the current time step
335: . ptime - the current time
336: . v - the current state
337: - monctx - the monitor context obtained with `TSMonitorLGCtxCreate()`
339: Level: advanced
341: Note:
342: This is not called directly by users, rather one calls `TSMonitorSet()` along the `ctx` created by `TSMonitorLGCtxCreate()`
343: and `TSMonitorLGCtxDestroy()`
345: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGCtxDestroy()`
346: @*/
347: PetscErrorCode TSMonitorLGTimeStep(TS ts, PetscInt step, PetscReal ptime, Vec v, void *monctx)
348: {
349: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
350: PetscReal x = ptime, y;
352: PetscFunctionBegin;
353: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates an interpolated solution */
354: if (!step) {
355: PetscDrawAxis axis;
356: const char *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
357: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
358: PetscCall(PetscDrawAxisSetLabels(axis, "Timestep as function of time", "Time", ylabel));
359: PetscCall(PetscDrawLGReset(ctx->lg));
360: }
361: PetscCall(TSGetTimeStep(ts, &y));
362: if (ctx->semilogy) y = PetscLog10Real(y);
363: PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
364: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
365: PetscCall(PetscDrawLGDraw(ctx->lg));
366: PetscCall(PetscDrawLGSave(ctx->lg));
367: }
368: PetscFunctionReturn(PETSC_SUCCESS);
369: }
371: /*@C
372: TSMonitorLGCtxDestroy - Destroys a line graph context that was created with `TSMonitorLGCtxCreate()`.
374: Collective
376: Input Parameter:
377: . ctx - the monitor context
379: Level: intermediate
381: Note:
382: Pass to `TSMonitorSet()` along with the context and `TSMonitorLGTimeStep()`
384: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
385: @*/
386: PetscErrorCode TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
387: {
388: PetscFunctionBegin;
389: if ((*ctx)->transformdestroy) PetscCall(((*ctx)->transformdestroy)((*ctx)->transformctx));
390: PetscCall(PetscDrawLGDestroy(&(*ctx)->lg));
391: PetscCall(PetscStrArrayDestroy(&(*ctx)->names));
392: PetscCall(PetscStrArrayDestroy(&(*ctx)->displaynames));
393: PetscCall(PetscFree((*ctx)->displayvariables));
394: PetscCall(PetscFree((*ctx)->displayvalues));
395: PetscCall(PetscFree(*ctx));
396: PetscFunctionReturn(PETSC_SUCCESS);
397: }
399: /* Creates a TSMonitorSPCtx for use with DMSwarm particle visualizations */
400: 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)
401: {
402: PetscDraw draw;
404: PetscFunctionBegin;
405: PetscCall(PetscNew(ctx));
406: PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
407: PetscCall(PetscDrawSetFromOptions(draw));
408: PetscCall(PetscDrawSPCreate(draw, 1, &(*ctx)->sp));
409: PetscCall(PetscDrawDestroy(&draw));
410: (*ctx)->howoften = howoften;
411: (*ctx)->retain = retain;
412: (*ctx)->phase = phase;
413: (*ctx)->multispecies = multispecies;
414: PetscFunctionReturn(PETSC_SUCCESS);
415: }
417: /* Destroys a TSMonitorSPCtx that was created with TSMonitorSPCtxCreate */
418: PetscErrorCode TSMonitorSPCtxDestroy(TSMonitorSPCtx *ctx)
419: {
420: PetscFunctionBegin;
422: PetscCall(PetscDrawSPDestroy(&(*ctx)->sp));
423: PetscCall(PetscFree(*ctx));
424: PetscFunctionReturn(PETSC_SUCCESS);
425: }
427: /* Creates a TSMonitorHGCtx for use with DMSwarm particle visualizations */
428: 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)
429: {
430: PetscDraw draw;
431: PetscInt s;
433: PetscFunctionBegin;
434: PetscCall(PetscNew(ctx));
435: PetscCall(PetscMalloc1(Ns, &(*ctx)->hg));
436: for (s = 0; s < Ns; ++s) {
437: PetscCall(PetscDrawCreate(comm, host, label, x + s * m, y, m, n, &draw));
438: PetscCall(PetscDrawSetFromOptions(draw));
439: PetscCall(PetscDrawHGCreate(draw, Nb, &(*ctx)->hg[s]));
440: PetscCall(PetscDrawHGCalcStats((*ctx)->hg[s], PETSC_TRUE));
441: PetscCall(PetscDrawDestroy(&draw));
442: }
443: (*ctx)->howoften = howoften;
444: (*ctx)->Ns = Ns;
445: (*ctx)->velocity = velocity;
446: PetscFunctionReturn(PETSC_SUCCESS);
447: }
449: /* Destroys a TSMonitorHGCtx that was created with TSMonitorHGCtxCreate */
450: PetscErrorCode TSMonitorHGCtxDestroy(TSMonitorHGCtx *ctx)
451: {
452: PetscInt s;
454: PetscFunctionBegin;
455: for (s = 0; s < (*ctx)->Ns; ++s) PetscCall(PetscDrawHGDestroy(&(*ctx)->hg[s]));
456: PetscCall(PetscFree((*ctx)->hg));
457: PetscCall(PetscFree(*ctx));
458: PetscFunctionReturn(PETSC_SUCCESS);
459: }
461: /*@C
462: TSMonitorDrawSolution - Monitors progress of the `TS` solvers by calling
463: `VecView()` for the solution at each timestep
465: Collective
467: Input Parameters:
468: + ts - the `TS` context
469: . step - current time-step
470: . ptime - current time
471: . u - the solution at the current time
472: - dummy - either a viewer or `NULL`
474: Options Database Keys:
475: + -ts_monitor_draw_solution - draw the solution at each time-step
476: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution
478: Level: intermediate
480: Notes:
481: The initial solution and current solution are not displayed with a common axis scaling so generally the option `-ts_monitor_draw_solution_initial`
482: will look bad
484: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, as well as the context created with
485: `TSMonitorDrawCtxCreate()` and the function `TSMonitorDrawCtxDestroy()` to cause the monitor to be used during the `TS` integration.
487: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtxCreate()`, `TSMonitorDrawCtxDestroy()`
488: @*/
489: PetscErrorCode TSMonitorDrawSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
490: {
491: TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
492: PetscDraw draw;
494: PetscFunctionBegin;
495: if (!step && ictx->showinitial) {
496: if (!ictx->initialsolution) PetscCall(VecDuplicate(u, &ictx->initialsolution));
497: PetscCall(VecCopy(u, ictx->initialsolution));
498: }
499: if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
501: if (ictx->showinitial) {
502: PetscReal pause;
503: PetscCall(PetscViewerDrawGetPause(ictx->viewer, &pause));
504: PetscCall(PetscViewerDrawSetPause(ictx->viewer, 0.0));
505: PetscCall(VecView(ictx->initialsolution, ictx->viewer));
506: PetscCall(PetscViewerDrawSetPause(ictx->viewer, pause));
507: PetscCall(PetscViewerDrawSetHold(ictx->viewer, PETSC_TRUE));
508: }
509: PetscCall(VecView(u, ictx->viewer));
510: if (ictx->showtimestepandtime) {
511: PetscReal xl, yl, xr, yr, h;
512: char time[32];
514: PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
515: PetscCall(PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime));
516: PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
517: h = yl + .95 * (yr - yl);
518: PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
519: PetscCall(PetscDrawFlush(draw));
520: }
522: if (ictx->showinitial) PetscCall(PetscViewerDrawSetHold(ictx->viewer, PETSC_FALSE));
523: PetscFunctionReturn(PETSC_SUCCESS);
524: }
526: /*@C
527: TSMonitorDrawSolutionPhase - Monitors progress of the `TS` solvers by plotting the solution as a phase diagram
529: Collective
531: Input Parameters:
532: + ts - the `TS` context
533: . step - current time-step
534: . ptime - current time
535: . u - the solution at the current time
536: - dummy - either a viewer or `NULL`
538: Level: intermediate
540: Notes:
541: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
542: to be used during the `TS` integration.
544: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
545: @*/
546: PetscErrorCode TSMonitorDrawSolutionPhase(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
547: {
548: TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
549: PetscDraw draw;
550: PetscDrawAxis axis;
551: PetscInt n;
552: PetscMPIInt size;
553: PetscReal U0, U1, xl, yl, xr, yr, h;
554: char time[32];
555: const PetscScalar *U;
557: PetscFunctionBegin;
558: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)ts), &size));
559: PetscCheck(size == 1, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only allowed for sequential runs");
560: PetscCall(VecGetSize(u, &n));
561: PetscCheck(n == 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only for ODEs with two unknowns");
563: PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
564: PetscCall(PetscViewerDrawGetDrawAxis(ictx->viewer, 0, &axis));
565: PetscCall(PetscDrawAxisGetLimits(axis, &xl, &xr, &yl, &yr));
566: if (!step) {
567: PetscCall(PetscDrawClear(draw));
568: PetscCall(PetscDrawAxisDraw(axis));
569: }
571: PetscCall(VecGetArrayRead(u, &U));
572: U0 = PetscRealPart(U[0]);
573: U1 = PetscRealPart(U[1]);
574: PetscCall(VecRestoreArrayRead(u, &U));
575: if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(PETSC_SUCCESS);
577: PetscDrawCollectiveBegin(draw);
578: PetscCall(PetscDrawPoint(draw, U0, U1, PETSC_DRAW_BLACK));
579: if (ictx->showtimestepandtime) {
580: PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
581: PetscCall(PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime));
582: h = yl + .95 * (yr - yl);
583: PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
584: }
585: PetscDrawCollectiveEnd(draw);
586: PetscCall(PetscDrawFlush(draw));
587: PetscCall(PetscDrawPause(draw));
588: PetscCall(PetscDrawSave(draw));
589: PetscFunctionReturn(PETSC_SUCCESS);
590: }
592: /*@C
593: TSMonitorDrawCtxDestroy - Destroys the monitor context for `TSMonitorDrawSolution()`
595: Collective
597: Input Parameter:
598: . ictx - the monitor context
600: Level: intermediate
602: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawSolution()`, `TSMonitorDrawError()`, `TSMonitorDrawCtx`
603: @*/
604: PetscErrorCode TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
605: {
606: PetscFunctionBegin;
607: PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
608: PetscCall(VecDestroy(&(*ictx)->initialsolution));
609: PetscCall(PetscFree(*ictx));
610: PetscFunctionReturn(PETSC_SUCCESS);
611: }
613: /*@C
614: TSMonitorDrawCtxCreate - Creates the monitor context for `TSMonitorDrawCtx`
616: Collective
618: Input Parameters:
619: + comm - the MPI communicator to use
620: . host - the X display to open, or `NULL` for the local machine
621: . label - the title to put in the title bar
622: . x - the x screen coordinates of the upper left coordinate of the window
623: . y - the y screen coordinates of the upper left coordinate of the window
624: . m - the screen width in pixels
625: . n - the screen height in pixels
626: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
628: Output Parameter:
629: . ctx - the monitor context
631: Options Database Keys:
632: + -ts_monitor_draw_solution - draw the solution at each time-step
633: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution
635: Level: intermediate
637: Note:
638: The context created by this function, `PetscMonitorDrawSolution()`, and `TSMonitorDrawCtxDestroy()` should be passed together to `TSMonitorSet()`.
640: .seealso: [](ch_ts), `TS`, `TSMonitorDrawCtxDestroy()`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtx`, `PetscMonitorDrawSolution()`
641: @*/
642: PetscErrorCode TSMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorDrawCtx *ctx)
643: {
644: PetscFunctionBegin;
645: PetscCall(PetscNew(ctx));
646: PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
647: PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
649: (*ctx)->howoften = howoften;
650: (*ctx)->showinitial = PETSC_FALSE;
651: PetscCall(PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_initial", &(*ctx)->showinitial, NULL));
653: (*ctx)->showtimestepandtime = PETSC_FALSE;
654: PetscCall(PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_show_time", &(*ctx)->showtimestepandtime, NULL));
655: PetscFunctionReturn(PETSC_SUCCESS);
656: }
658: /*@C
659: TSMonitorDrawSolutionFunction - Monitors progress of the `TS` solvers by calling
660: `VecView()` for the solution provided by `TSSetSolutionFunction()` at each timestep
662: Collective
664: Input Parameters:
665: + ts - the `TS` context
666: . step - current time-step
667: . ptime - current time
668: . u - solution at current time
669: - dummy - either a viewer or `NULL`
671: Options Database Key:
672: . -ts_monitor_draw_solution_function - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`
674: Level: intermediate
676: Note:
677: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
678: to be used during the `TS` integration.
680: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
681: @*/
682: PetscErrorCode TSMonitorDrawSolutionFunction(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
683: {
684: TSMonitorDrawCtx ctx = (TSMonitorDrawCtx)dummy;
685: PetscViewer viewer = ctx->viewer;
686: Vec work;
688: PetscFunctionBegin;
689: if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
690: PetscCall(VecDuplicate(u, &work));
691: PetscCall(TSComputeSolutionFunction(ts, ptime, work));
692: PetscCall(VecView(work, viewer));
693: PetscCall(VecDestroy(&work));
694: PetscFunctionReturn(PETSC_SUCCESS);
695: }
697: /*@C
698: TSMonitorDrawError - Monitors progress of the `TS` solvers by calling
699: `VecView()` for the error at each timestep
701: Collective
703: Input Parameters:
704: + ts - the `TS` context
705: . step - current time-step
706: . ptime - current time
707: . u - solution at current time
708: - dummy - either a viewer or `NULL`
710: Options Database Key:
711: . -ts_monitor_draw_error - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`
713: Level: intermediate
715: Notes:
716: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
717: to be used during the `TS` integration.
719: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
720: @*/
721: PetscErrorCode TSMonitorDrawError(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
722: {
723: TSMonitorDrawCtx ctx = (TSMonitorDrawCtx)dummy;
724: PetscViewer viewer = ctx->viewer;
725: Vec work;
727: PetscFunctionBegin;
728: if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
729: PetscCall(VecDuplicate(u, &work));
730: PetscCall(TSComputeSolutionFunction(ts, ptime, work));
731: PetscCall(VecAXPY(work, -1.0, u));
732: PetscCall(VecView(work, viewer));
733: PetscCall(VecDestroy(&work));
734: PetscFunctionReturn(PETSC_SUCCESS);
735: }
737: /*@C
738: 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
740: Collective
742: Input Parameters:
743: + ts - the `TS` context
744: . step - current time-step
745: . ptime - current time
746: . u - current state
747: - vf - viewer and its format
749: Level: intermediate
751: Notes:
752: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
753: to be used during the `TS` integration.
755: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
756: @*/
757: PetscErrorCode TSMonitorSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
758: {
759: PetscFunctionBegin;
760: if (vf->view_interval > 0 && !ts->reason && step % vf->view_interval != 0) PetscFunctionReturn(PETSC_SUCCESS);
761: PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
762: PetscCall(VecView(u, vf->viewer));
763: PetscCall(PetscViewerPopFormat(vf->viewer));
764: PetscFunctionReturn(PETSC_SUCCESS);
765: }
767: /*@C
768: TSMonitorSolutionVTK - Monitors progress of the `TS` solvers by `VecView()` for the solution at each timestep.
770: Collective
772: Input Parameters:
773: + ts - the `TS` context
774: . step - current time-step
775: . ptime - current time
776: . u - current state
777: - filenametemplate - string containing a format specifier for the integer time step (e.g. %03" PetscInt_FMT ")
779: Level: intermediate
781: Notes:
782: 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.
783: These are named according to the file name template.
785: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
786: to be used during the `TS` integration.
788: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
789: @*/
790: PetscErrorCode TSMonitorSolutionVTK(TS ts, PetscInt step, PetscReal ptime, Vec u, void *filenametemplate)
791: {
792: char filename[PETSC_MAX_PATH_LEN];
793: PetscViewer viewer;
795: PetscFunctionBegin;
796: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
797: PetscCall(PetscSNPrintf(filename, sizeof(filename), (const char *)filenametemplate, step));
798: PetscCall(PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts), filename, FILE_MODE_WRITE, &viewer));
799: PetscCall(VecView(u, viewer));
800: PetscCall(PetscViewerDestroy(&viewer));
801: PetscFunctionReturn(PETSC_SUCCESS);
802: }
804: /*@C
805: TSMonitorSolutionVTKDestroy - Destroy filename template string created for use with `TSMonitorSolutionVTK()`
807: Not Collective
809: Input Parameter:
810: . filenametemplate - string containing a format specifier for the integer time step (e.g. %03" PetscInt_FMT ")
812: Level: intermediate
814: Note:
815: This function is normally passed to `TSMonitorSet()` along with `TSMonitorSolutionVTK()`.
817: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorSolutionVTK()`
818: @*/
819: PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
820: {
821: PetscFunctionBegin;
822: PetscCall(PetscFree(*(char **)filenametemplate));
823: PetscFunctionReturn(PETSC_SUCCESS);
824: }
826: /*@C
827: TSMonitorLGSolution - Monitors progress of the `TS` solvers by plotting each component of the solution vector
828: in a time based line graph
830: Collective
832: Input Parameters:
833: + ts - the `TS` context
834: . step - current time-step
835: . ptime - current time
836: . u - current solution
837: - dctx - the `TSMonitorLGCtx` object that contains all the options for the monitoring, this is created with `TSMonitorLGCtxCreate()`
839: Options Database Key:
840: . -ts_monitor_lg_solution_variables - enable monitor of lg solution variables
842: Level: intermediate
844: Notes:
845: Each process in a parallel run displays its component solutions in a separate window
847: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
848: to be used during the `TS` integration.
850: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
851: `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
852: `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGError()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
853: `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
854: @*/
855: PetscErrorCode TSMonitorLGSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
856: {
857: TSMonitorLGCtx ctx = (TSMonitorLGCtx)dctx;
858: const PetscScalar *yy;
859: Vec v;
861: PetscFunctionBegin;
862: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
863: if (!step) {
864: PetscDrawAxis axis;
865: PetscInt dim;
866: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
867: PetscCall(PetscDrawAxisSetLabels(axis, "Solution as function of time", "Time", "Solution"));
868: if (!ctx->names) {
869: PetscBool flg;
870: /* user provides names of variables to plot but no names has been set so assume names are integer values */
871: PetscCall(PetscOptionsHasName(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", &flg));
872: if (flg) {
873: PetscInt i, n;
874: char **names;
875: PetscCall(VecGetSize(u, &n));
876: PetscCall(PetscMalloc1(n + 1, &names));
877: for (i = 0; i < n; i++) {
878: PetscCall(PetscMalloc1(5, &names[i]));
879: PetscCall(PetscSNPrintf(names[i], 5, "%" PetscInt_FMT, i));
880: }
881: names[n] = NULL;
882: ctx->names = names;
883: }
884: }
885: if (ctx->names && !ctx->displaynames) {
886: char **displaynames;
887: PetscBool flg;
888: PetscCall(VecGetLocalSize(u, &dim));
889: PetscCall(PetscCalloc1(dim + 1, &displaynames));
890: PetscCall(PetscOptionsGetStringArray(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", displaynames, &dim, &flg));
891: if (flg) PetscCall(TSMonitorLGCtxSetDisplayVariables(ctx, (const char *const *)displaynames));
892: PetscCall(PetscStrArrayDestroy(&displaynames));
893: }
894: if (ctx->displaynames) {
895: PetscCall(PetscDrawLGSetDimension(ctx->lg, ctx->ndisplayvariables));
896: PetscCall(PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->displaynames));
897: } else if (ctx->names) {
898: PetscCall(VecGetLocalSize(u, &dim));
899: PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
900: PetscCall(PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->names));
901: } else {
902: PetscCall(VecGetLocalSize(u, &dim));
903: PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
904: }
905: PetscCall(PetscDrawLGReset(ctx->lg));
906: }
908: if (!ctx->transform) v = u;
909: else PetscCall((*ctx->transform)(ctx->transformctx, u, &v));
910: PetscCall(VecGetArrayRead(v, &yy));
911: if (ctx->displaynames) {
912: PetscInt i;
913: for (i = 0; i < ctx->ndisplayvariables; i++) ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
914: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, ctx->displayvalues));
915: } else {
916: #if defined(PETSC_USE_COMPLEX)
917: PetscInt i, n;
918: PetscReal *yreal;
919: PetscCall(VecGetLocalSize(v, &n));
920: PetscCall(PetscMalloc1(n, &yreal));
921: for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
922: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal));
923: PetscCall(PetscFree(yreal));
924: #else
925: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy));
926: #endif
927: }
928: PetscCall(VecRestoreArrayRead(v, &yy));
929: if (ctx->transform) PetscCall(VecDestroy(&v));
931: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
932: PetscCall(PetscDrawLGDraw(ctx->lg));
933: PetscCall(PetscDrawLGSave(ctx->lg));
934: }
935: PetscFunctionReturn(PETSC_SUCCESS);
936: }
938: /*@C
939: TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
941: Collective
943: Input Parameters:
944: + ts - the `TS` context
945: - names - the names of the components, final string must be `NULL`
947: Level: intermediate
949: Notes:
950: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
952: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetVariableNames()`
953: @*/
954: PetscErrorCode TSMonitorLGSetVariableNames(TS ts, const char *const *names)
955: {
956: PetscInt i;
958: PetscFunctionBegin;
959: for (i = 0; i < ts->numbermonitors; i++) {
960: if (ts->monitor[i] == TSMonitorLGSolution) {
961: PetscCall(TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i], names));
962: break;
963: }
964: }
965: PetscFunctionReturn(PETSC_SUCCESS);
966: }
968: /*@C
969: TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
971: Collective
973: Input Parameters:
974: + ctx - the `TS` context
975: - names - the names of the components, final string must be `NULL`
977: Level: intermediate
979: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGSetVariableNames()`
980: @*/
981: PetscErrorCode TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx, const char *const *names)
982: {
983: PetscFunctionBegin;
984: PetscCall(PetscStrArrayDestroy(&ctx->names));
985: PetscCall(PetscStrArrayallocpy(names, &ctx->names));
986: PetscFunctionReturn(PETSC_SUCCESS);
987: }
989: /*@C
990: TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
992: Collective
994: Input Parameter:
995: . ts - the `TS` context
997: Output Parameter:
998: . names - the names of the components, final string must be `NULL`
1000: Level: intermediate
1002: Note:
1003: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
1005: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
1006: @*/
1007: PetscErrorCode TSMonitorLGGetVariableNames(TS ts, const char *const **names)
1008: {
1009: PetscInt i;
1011: PetscFunctionBegin;
1012: *names = NULL;
1013: for (i = 0; i < ts->numbermonitors; i++) {
1014: if (ts->monitor[i] == TSMonitorLGSolution) {
1015: TSMonitorLGCtx ctx = (TSMonitorLGCtx)ts->monitorcontext[i];
1016: *names = (const char *const *)ctx->names;
1017: break;
1018: }
1019: }
1020: PetscFunctionReturn(PETSC_SUCCESS);
1021: }
1023: /*@C
1024: TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
1026: Collective
1028: Input Parameters:
1029: + ctx - the `TSMonitorLG` context
1030: - displaynames - the names of the components, final string must be `NULL`
1032: Level: intermediate
1034: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
1035: @*/
1036: PetscErrorCode TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx, const char *const *displaynames)
1037: {
1038: PetscInt j = 0, k;
1040: PetscFunctionBegin;
1041: if (!ctx->names) PetscFunctionReturn(PETSC_SUCCESS);
1042: PetscCall(PetscStrArrayDestroy(&ctx->displaynames));
1043: PetscCall(PetscStrArrayallocpy(displaynames, &ctx->displaynames));
1044: while (displaynames[j]) j++;
1045: ctx->ndisplayvariables = j;
1046: PetscCall(PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvariables));
1047: PetscCall(PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvalues));
1048: j = 0;
1049: while (displaynames[j]) {
1050: k = 0;
1051: while (ctx->names[k]) {
1052: PetscBool flg;
1053: PetscCall(PetscStrcmp(displaynames[j], ctx->names[k], &flg));
1054: if (flg) {
1055: ctx->displayvariables[j] = k;
1056: break;
1057: }
1058: k++;
1059: }
1060: j++;
1061: }
1062: PetscFunctionReturn(PETSC_SUCCESS);
1063: }
1065: /*@C
1066: TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
1068: Collective
1070: Input Parameters:
1071: + ts - the `TS` context
1072: - displaynames - the names of the components, final string must be `NULL`
1074: Level: intermediate
1076: Note:
1077: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
1079: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
1080: @*/
1081: PetscErrorCode TSMonitorLGSetDisplayVariables(TS ts, const char *const *displaynames)
1082: {
1083: PetscInt i;
1085: PetscFunctionBegin;
1086: for (i = 0; i < ts->numbermonitors; i++) {
1087: if (ts->monitor[i] == TSMonitorLGSolution) {
1088: PetscCall(TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i], displaynames));
1089: break;
1090: }
1091: }
1092: PetscFunctionReturn(PETSC_SUCCESS);
1093: }
1095: /*@C
1096: TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
1098: Collective
1100: Input Parameters:
1101: + ts - the `TS` context
1102: . transform - the transform function
1103: . destroy - function to destroy the optional context
1104: - tctx - optional context used by transform function
1106: Level: intermediate
1108: Note:
1109: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
1111: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGCtxSetTransform()`
1112: @*/
1113: PetscErrorCode TSMonitorLGSetTransform(TS ts, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
1114: {
1115: PetscInt i;
1117: PetscFunctionBegin;
1118: for (i = 0; i < ts->numbermonitors; i++) {
1119: if (ts->monitor[i] == TSMonitorLGSolution) PetscCall(TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i], transform, destroy, tctx));
1120: }
1121: PetscFunctionReturn(PETSC_SUCCESS);
1122: }
1124: /*@C
1125: TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
1127: Collective
1129: Input Parameters:
1130: + tctx - the `TS` context
1131: . transform - the transform function
1132: . destroy - function to destroy the optional context
1133: - ctx - optional context used by transform function
1135: Level: intermediate
1137: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGSetTransform()`
1138: @*/
1139: PetscErrorCode TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
1140: {
1141: PetscFunctionBegin;
1142: ctx->transform = transform;
1143: ctx->transformdestroy = destroy;
1144: ctx->transformctx = tctx;
1145: PetscFunctionReturn(PETSC_SUCCESS);
1146: }
1148: /*@C
1149: TSMonitorLGError - Monitors progress of the `TS` solvers by plotting each component of the error
1150: in a time based line graph
1152: Collective
1154: Input Parameters:
1155: + ts - the `TS` context
1156: . step - current time-step
1157: . ptime - current time
1158: . u - current solution
1159: - dummy - `TSMonitorLGCtx` object created with `TSMonitorLGCtxCreate()`
1161: Options Database Key:
1162: . -ts_monitor_lg_error - create a graphical monitor of error history
1164: Level: intermediate
1166: Notes:
1167: Each process in a parallel run displays its component errors in a separate window
1169: The user must provide the solution using `TSSetSolutionFunction()` to use this monitor.
1171: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1172: to be used during the TS integration.
1174: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1175: @*/
1176: PetscErrorCode TSMonitorLGError(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
1177: {
1178: TSMonitorLGCtx ctx = (TSMonitorLGCtx)dummy;
1179: const PetscScalar *yy;
1180: Vec y;
1182: PetscFunctionBegin;
1183: if (!step) {
1184: PetscDrawAxis axis;
1185: PetscInt dim;
1186: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1187: PetscCall(PetscDrawAxisSetLabels(axis, "Error in solution as function of time", "Time", "Error"));
1188: PetscCall(VecGetLocalSize(u, &dim));
1189: PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
1190: PetscCall(PetscDrawLGReset(ctx->lg));
1191: }
1192: PetscCall(VecDuplicate(u, &y));
1193: PetscCall(TSComputeSolutionFunction(ts, ptime, y));
1194: PetscCall(VecAXPY(y, -1.0, u));
1195: PetscCall(VecGetArrayRead(y, &yy));
1196: #if defined(PETSC_USE_COMPLEX)
1197: {
1198: PetscReal *yreal;
1199: PetscInt i, n;
1200: PetscCall(VecGetLocalSize(y, &n));
1201: PetscCall(PetscMalloc1(n, &yreal));
1202: for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
1203: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal));
1204: PetscCall(PetscFree(yreal));
1205: }
1206: #else
1207: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy));
1208: #endif
1209: PetscCall(VecRestoreArrayRead(y, &yy));
1210: PetscCall(VecDestroy(&y));
1211: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1212: PetscCall(PetscDrawLGDraw(ctx->lg));
1213: PetscCall(PetscDrawLGSave(ctx->lg));
1214: }
1215: PetscFunctionReturn(PETSC_SUCCESS);
1216: }
1218: /*@C
1219: TSMonitorSPSwarmSolution - Graphically displays phase plots of `DMSWARM` particles on a scatter plot
1221: Input Parameters:
1222: + ts - the `TS` context
1223: . step - current time-step
1224: . ptime - current time
1225: . u - current solution
1226: - dctx - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorSPCtxCreate()`
1228: Options Database Keys:
1229: + -ts_monitor_sp_swarm <n> - Monitor the solution every n steps, or -1 for plotting only the final solution
1230: . -ts_monitor_sp_swarm_retain <n> - Retain n old points so we can see the history, or -1 for all points
1231: . -ts_monitor_sp_swarm_multi_species <bool> - Color each species differently
1232: - -ts_monitor_sp_swarm_phase <bool> - Plot in phase space, as opposed to coordinate space
1234: Level: intermediate
1236: Notes:
1237: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1238: to be used during the `TS` integration.
1240: .seealso: [](ch_ts), `TS`, `TSMonitoSet()`, `DMSWARM`, `TSMonitorSPCtxCreate()`
1241: @*/
1242: PetscErrorCode TSMonitorSPSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1243: {
1244: TSMonitorSPCtx ctx = (TSMonitorSPCtx)dctx;
1245: PetscDraw draw;
1246: DM dm, cdm;
1247: const PetscScalar *yy;
1248: PetscInt Np, p, dim = 2, *species;
1249: PetscReal species_color;
1251: PetscFunctionBegin;
1252: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1253: PetscCall(TSGetDM(ts, &dm));
1254: if (!step) {
1255: PetscDrawAxis axis;
1256: PetscReal dmboxlower[2], dmboxupper[2];
1258: PetscCall(TSGetDM(ts, &dm));
1259: PetscCall(DMGetDimension(dm, &dim));
1260: PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Monitor only supports two dimensional fields");
1261: PetscCall(DMSwarmGetCellDM(dm, &cdm));
1262: PetscCall(DMGetBoundingBox(cdm, dmboxlower, dmboxupper));
1263: PetscCall(VecGetLocalSize(u, &Np));
1264: Np /= dim * 2;
1265: PetscCall(PetscDrawSPGetAxis(ctx->sp, &axis));
1266: if (ctx->phase) {
1267: PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "X", "V"));
1268: PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], -10, 10));
1269: } else {
1270: PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "X", "Y"));
1271: PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], dmboxlower[1], dmboxupper[1]));
1272: }
1273: PetscCall(PetscDrawAxisSetHoldLimits(axis, PETSC_TRUE));
1274: PetscCall(PetscDrawSPReset(ctx->sp));
1275: }
1276: if (ctx->multispecies) PetscCall(DMSwarmGetField(dm, "species", NULL, NULL, (void **)&species));
1277: PetscCall(VecGetLocalSize(u, &Np));
1278: Np /= dim * 2;
1279: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1280: PetscCall(PetscDrawSPGetDraw(ctx->sp, &draw));
1281: if ((ctx->retain == 0) || (ctx->retain > 0 && !(step % ctx->retain))) PetscCall(PetscDrawClear(draw));
1282: PetscCall(PetscDrawFlush(draw));
1283: PetscCall(PetscDrawSPReset(ctx->sp));
1284: PetscCall(VecGetArrayRead(u, &yy));
1285: for (p = 0; p < Np; ++p) {
1286: PetscReal x, y;
1288: if (ctx->phase) {
1289: x = PetscRealPart(yy[p * dim * 2]);
1290: y = PetscRealPart(yy[p * dim * 2 + dim]);
1291: } else {
1292: x = PetscRealPart(yy[p * dim * 2]);
1293: y = PetscRealPart(yy[p * dim * 2 + 1]);
1294: }
1295: if (ctx->multispecies) {
1296: species_color = species[p] + 2;
1297: PetscCall(PetscDrawSPAddPointColorized(ctx->sp, &x, &y, &species_color));
1298: } else {
1299: PetscCall(PetscDrawSPAddPoint(ctx->sp, &x, &y));
1300: }
1301: PetscCall(PetscDrawSPAddPoint(ctx->sp, &x, &y));
1302: }
1303: PetscCall(VecRestoreArrayRead(u, &yy));
1304: PetscCall(PetscDrawSPDraw(ctx->sp, PETSC_FALSE));
1305: PetscCall(PetscDrawSPSave(ctx->sp));
1306: if (ctx->multispecies) PetscCall(DMSwarmRestoreField(dm, "species", NULL, NULL, (void **)&species));
1307: }
1308: PetscFunctionReturn(PETSC_SUCCESS);
1309: }
1311: /*@C
1312: TSMonitorHGSwarmSolution - Graphically displays histograms of `DMSWARM` particles
1314: Input Parameters:
1315: + ts - the `TS` context
1316: . step - current time-step
1317: . ptime - current time
1318: . u - current solution
1319: - dctx - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorHGCtxCreate()`
1321: Options Database Keys:
1322: + -ts_monitor_hg_swarm <n> - Monitor the solution every n steps, or -1 for plotting only the final solution
1323: . -ts_monitor_hg_swarm_species <num> - Number of species to histogram
1324: . -ts_monitor_hg_swarm_bins <num> - Number of histogram bins
1325: - -ts_monitor_hg_swarm_velocity <bool> - Plot in velocity space, as opposed to coordinate space
1327: Level: intermediate
1329: Note:
1330: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1331: to be used during the `TS` integration.
1333: .seealso: `TSMonitoSet()`
1334: @*/
1335: PetscErrorCode TSMonitorHGSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1336: {
1337: TSMonitorHGCtx ctx = (TSMonitorHGCtx)dctx;
1338: PetscDraw draw;
1339: DM sw;
1340: const PetscScalar *yy;
1341: PetscInt *species;
1342: PetscInt dim, d = 0, Np, p, Ns, s;
1344: PetscFunctionBegin;
1345: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1346: PetscCall(TSGetDM(ts, &sw));
1347: PetscCall(DMGetDimension(sw, &dim));
1348: PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
1349: Ns = PetscMin(Ns, ctx->Ns);
1350: PetscCall(VecGetLocalSize(u, &Np));
1351: Np /= dim * 2;
1352: if (!step) {
1353: PetscDrawAxis axis;
1354: char title[PETSC_MAX_PATH_LEN];
1356: for (s = 0; s < Ns; ++s) {
1357: PetscCall(PetscDrawHGGetAxis(ctx->hg[s], &axis));
1358: PetscCall(PetscSNPrintf(title, PETSC_MAX_PATH_LEN, "Species %" PetscInt_FMT, s));
1359: if (ctx->velocity) PetscCall(PetscDrawAxisSetLabels(axis, title, "V", "N"));
1360: else PetscCall(PetscDrawAxisSetLabels(axis, title, "X", "N"));
1361: }
1362: }
1363: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1364: PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
1365: for (s = 0; s < Ns; ++s) {
1366: PetscCall(PetscDrawHGReset(ctx->hg[s]));
1367: PetscCall(PetscDrawHGGetDraw(ctx->hg[s], &draw));
1368: PetscCall(PetscDrawClear(draw));
1369: PetscCall(PetscDrawFlush(draw));
1370: }
1371: PetscCall(VecGetArrayRead(u, &yy));
1372: for (p = 0; p < Np; ++p) {
1373: const PetscInt s = species[p] < Ns ? species[p] : 0;
1374: PetscReal v;
1376: if (ctx->velocity) v = PetscRealPart(yy[p * dim * 2 + d + dim]);
1377: else v = PetscRealPart(yy[p * dim * 2 + d]);
1378: PetscCall(PetscDrawHGAddValue(ctx->hg[s], v));
1379: }
1380: PetscCall(VecRestoreArrayRead(u, &yy));
1381: for (s = 0; s < Ns; ++s) {
1382: PetscCall(PetscDrawHGDraw(ctx->hg[s]));
1383: PetscCall(PetscDrawHGSave(ctx->hg[s]));
1384: }
1385: PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
1386: }
1387: PetscFunctionReturn(PETSC_SUCCESS);
1388: }
1390: /*@C
1391: TSMonitorError - Monitors progress of the `TS` solvers by printing the 2 norm of the error at each timestep
1393: Collective
1395: Input Parameters:
1396: + ts - the `TS` context
1397: . step - current time-step
1398: . ptime - current time
1399: . u - current solution
1400: - vf - unused context
1402: Options Database Key:
1403: . -ts_monitor_error - create a graphical monitor of error history
1405: Level: intermediate
1407: Notes:
1408: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1409: to be used during the `TS` integration.
1411: The user must provide the solution using `TSSetSolutionFunction()` to use this monitor.
1413: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1414: @*/
1415: PetscErrorCode TSMonitorError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
1416: {
1417: DM dm;
1418: PetscDS ds = NULL;
1419: PetscInt Nf = -1, f;
1420: PetscBool flg;
1422: PetscFunctionBegin;
1423: PetscCall(TSGetDM(ts, &dm));
1424: if (dm) PetscCall(DMGetDS(dm, &ds));
1425: if (ds) PetscCall(PetscDSGetNumFields(ds, &Nf));
1426: if (Nf <= 0) {
1427: Vec y;
1428: PetscReal nrm;
1430: PetscCall(VecDuplicate(u, &y));
1431: PetscCall(TSComputeSolutionFunction(ts, ptime, y));
1432: PetscCall(VecAXPY(y, -1.0, u));
1433: PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERASCII, &flg));
1434: if (flg) {
1435: PetscCall(VecNorm(y, NORM_2, &nrm));
1436: PetscCall(PetscViewerASCIIPrintf(vf->viewer, "2-norm of error %g\n", (double)nrm));
1437: }
1438: PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &flg));
1439: if (flg) PetscCall(VecView(y, vf->viewer));
1440: PetscCall(VecDestroy(&y));
1441: } else {
1442: PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx);
1443: void **ctxs;
1444: Vec v;
1445: PetscReal ferrors[1];
1447: PetscCall(PetscMalloc2(Nf, &exactFuncs, Nf, &ctxs));
1448: for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(ds, f, &exactFuncs[f], &ctxs[f]));
1449: PetscCall(DMComputeL2FieldDiff(dm, ptime, exactFuncs, ctxs, u, ferrors));
1450: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Timestep: %04d time = %-8.4g \t L_2 Error: [", (int)step, (double)ptime));
1451: for (f = 0; f < Nf; ++f) {
1452: if (f > 0) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ", "));
1453: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%2.3g", (double)ferrors[f]));
1454: }
1455: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "]\n"));
1457: PetscCall(VecViewFromOptions(u, NULL, "-sol_vec_view"));
1459: PetscCall(PetscOptionsHasName(NULL, NULL, "-exact_vec_view", &flg));
1460: if (flg) {
1461: PetscCall(DMGetGlobalVector(dm, &v));
1462: PetscCall(DMProjectFunction(dm, ptime, exactFuncs, ctxs, INSERT_ALL_VALUES, v));
1463: PetscCall(PetscObjectSetName((PetscObject)v, "Exact Solution"));
1464: PetscCall(VecViewFromOptions(v, NULL, "-exact_vec_view"));
1465: PetscCall(DMRestoreGlobalVector(dm, &v));
1466: }
1467: PetscCall(PetscFree2(exactFuncs, ctxs));
1468: }
1469: PetscFunctionReturn(PETSC_SUCCESS);
1470: }
1472: PetscErrorCode TSMonitorLGSNESIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, void *monctx)
1473: {
1474: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1475: PetscReal x = ptime, y;
1476: PetscInt its;
1478: PetscFunctionBegin;
1479: if (n < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1480: if (!n) {
1481: PetscDrawAxis axis;
1482: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1483: PetscCall(PetscDrawAxisSetLabels(axis, "Nonlinear iterations as function of time", "Time", "SNES Iterations"));
1484: PetscCall(PetscDrawLGReset(ctx->lg));
1485: ctx->snes_its = 0;
1486: }
1487: PetscCall(TSGetSNESIterations(ts, &its));
1488: y = its - ctx->snes_its;
1489: PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
1490: if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1491: PetscCall(PetscDrawLGDraw(ctx->lg));
1492: PetscCall(PetscDrawLGSave(ctx->lg));
1493: }
1494: ctx->snes_its = its;
1495: PetscFunctionReturn(PETSC_SUCCESS);
1496: }
1498: PetscErrorCode TSMonitorLGKSPIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, void *monctx)
1499: {
1500: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1501: PetscReal x = ptime, y;
1502: PetscInt its;
1504: PetscFunctionBegin;
1505: if (n < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1506: if (!n) {
1507: PetscDrawAxis axis;
1508: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1509: PetscCall(PetscDrawAxisSetLabels(axis, "Linear iterations as function of time", "Time", "KSP Iterations"));
1510: PetscCall(PetscDrawLGReset(ctx->lg));
1511: ctx->ksp_its = 0;
1512: }
1513: PetscCall(TSGetKSPIterations(ts, &its));
1514: y = its - ctx->ksp_its;
1515: PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
1516: if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1517: PetscCall(PetscDrawLGDraw(ctx->lg));
1518: PetscCall(PetscDrawLGSave(ctx->lg));
1519: }
1520: ctx->ksp_its = its;
1521: PetscFunctionReturn(PETSC_SUCCESS);
1522: }
1524: /*@C
1525: TSMonitorEnvelopeCtxCreate - Creates a context for use with `TSMonitorEnvelope()`
1527: Collective
1529: Input Parameter:
1530: . ts - the `TS` solver object
1532: Output Parameter:
1533: . ctx - the context
1535: Level: intermediate
1537: .seealso: [](ch_ts), `TS`, `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`
1538: @*/
1539: PetscErrorCode TSMonitorEnvelopeCtxCreate(TS ts, TSMonitorEnvelopeCtx *ctx)
1540: {
1541: PetscFunctionBegin;
1542: PetscCall(PetscNew(ctx));
1543: PetscFunctionReturn(PETSC_SUCCESS);
1544: }
1546: /*@C
1547: TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
1549: Collective
1551: Input Parameters:
1552: + ts - the `TS` context
1553: . step - current time-step
1554: . ptime - current time
1555: . u - current solution
1556: - dctx - the envelope context
1558: Options Database Key:
1559: . -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time
1561: Level: intermediate
1563: Notes:
1564: After a solve you can use `TSMonitorEnvelopeGetBounds()` to access the envelope
1566: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1567: to be used during the `TS` integration.
1569: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxCreate()`
1570: @*/
1571: PetscErrorCode TSMonitorEnvelope(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1572: {
1573: TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
1575: PetscFunctionBegin;
1576: if (!ctx->max) {
1577: PetscCall(VecDuplicate(u, &ctx->max));
1578: PetscCall(VecDuplicate(u, &ctx->min));
1579: PetscCall(VecCopy(u, ctx->max));
1580: PetscCall(VecCopy(u, ctx->min));
1581: } else {
1582: PetscCall(VecPointwiseMax(ctx->max, u, ctx->max));
1583: PetscCall(VecPointwiseMin(ctx->min, u, ctx->min));
1584: }
1585: PetscFunctionReturn(PETSC_SUCCESS);
1586: }
1588: /*@C
1589: TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
1591: Collective
1593: Input Parameter:
1594: . ts - the `TS` context
1596: Output Parameters:
1597: + max - the maximum values
1598: - min - the minimum values
1600: Level: intermediate
1602: Notes:
1603: If the `TS` does not have a `TSMonitorEnvelopeCtx` associated with it then this function is ignored
1605: .seealso: [](ch_ts), `TSMonitorEnvelopeCtx`, `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
1606: @*/
1607: PetscErrorCode TSMonitorEnvelopeGetBounds(TS ts, Vec *max, Vec *min)
1608: {
1609: PetscInt i;
1611: PetscFunctionBegin;
1612: if (max) *max = NULL;
1613: if (min) *min = NULL;
1614: for (i = 0; i < ts->numbermonitors; i++) {
1615: if (ts->monitor[i] == TSMonitorEnvelope) {
1616: TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)ts->monitorcontext[i];
1617: if (max) *max = ctx->max;
1618: if (min) *min = ctx->min;
1619: break;
1620: }
1621: }
1622: PetscFunctionReturn(PETSC_SUCCESS);
1623: }
1625: /*@C
1626: TSMonitorEnvelopeCtxDestroy - Destroys a context that was created with `TSMonitorEnvelopeCtxCreate()`.
1628: Collective
1630: Input Parameter:
1631: . ctx - the monitor context
1633: Level: intermediate
1635: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
1636: @*/
1637: PetscErrorCode TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
1638: {
1639: PetscFunctionBegin;
1640: PetscCall(VecDestroy(&(*ctx)->min));
1641: PetscCall(VecDestroy(&(*ctx)->max));
1642: PetscCall(PetscFree(*ctx));
1643: PetscFunctionReturn(PETSC_SUCCESS);
1644: }
1646: /*@C
1647: TSDMSwarmMonitorMoments - Monitors the first three moments of a `DMSWARM` being evolved by the `TS`
1649: Not Collective
1651: Input Parameters:
1652: + ts - the `TS` context
1653: . step - current timestep
1654: . t - current time
1655: . U - current solution
1656: - vf - not used
1658: Options Database Key:
1659: . -ts_dmswarm_monitor_moments - Monitor moments of particle distribution
1661: Level: intermediate
1663: Notes:
1664: This requires a `DMSWARM` be attached to the `TS`.
1666: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1667: to be used during the TS integration.
1669: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `DMSWARM`
1670: @*/
1671: PetscErrorCode TSDMSwarmMonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, PetscViewerAndFormat *vf)
1672: {
1673: DM sw;
1674: const PetscScalar *u;
1675: PetscReal m = 1.0, totE = 0., totMom[3] = {0., 0., 0.};
1676: PetscInt dim, d, Np, p;
1677: MPI_Comm comm;
1679: PetscFunctionBeginUser;
1680: (void)t;
1681: (void)vf;
1682: PetscCall(TSGetDM(ts, &sw));
1683: if (!sw || step % ts->monitorFrequency != 0) PetscFunctionReturn(PETSC_SUCCESS);
1684: PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
1685: PetscCall(DMGetDimension(sw, &dim));
1686: PetscCall(VecGetLocalSize(U, &Np));
1687: Np /= dim;
1688: PetscCall(VecGetArrayRead(U, &u));
1689: for (p = 0; p < Np; ++p) {
1690: for (d = 0; d < dim; ++d) {
1691: totE += PetscRealPart(u[p * dim + d] * u[p * dim + d]);
1692: totMom[d] += PetscRealPart(u[p * dim + d]);
1693: }
1694: }
1695: PetscCall(VecRestoreArrayRead(U, &u));
1696: for (d = 0; d < dim; ++d) totMom[d] *= m;
1697: totE *= 0.5 * m;
1698: PetscCall(PetscPrintf(comm, "Step %4" PetscInt_FMT " Total Energy: %10.8lf", step, (double)totE));
1699: for (d = 0; d < dim; ++d) PetscCall(PetscPrintf(comm, " Total Momentum %c: %10.8lf", (char)('x' + d), (double)totMom[d]));
1700: PetscCall(PetscPrintf(comm, "\n"));
1701: PetscFunctionReturn(PETSC_SUCCESS);
1702: }