Actual source code: tsmon.c
1: #include <petsc/private/tsimpl.h>
2: #include <petscdm.h>
3: #include <petscds.h>
4: #include <petscdmswarm.h>
5: #include <petscdraw.h>
7: /*@C
8: TSMonitor - Runs all user-provided monitor routines set using `TSMonitorSet()`
10: Collective
12: Input Parameters:
13: + ts - time stepping context obtained from `TSCreate()`
14: . step - step number that has just completed
15: . ptime - model time of the state
16: - u - state at the current model time
18: Level: developer
20: Notes:
21: `TSMonitor()` is typically used automatically within the time stepping implementations.
22: Users would almost never call this routine directly.
24: A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions
26: .seealso: `TS`, `TSMonitorSet()`, `TSMonitorSetFromOptions()`
27: @*/
28: PetscErrorCode TSMonitor(TS ts, PetscInt step, PetscReal ptime, Vec u)
29: {
30: DM dm;
31: PetscInt i, n = ts->numbermonitors;
36: TSGetDM(ts, &dm);
37: DMSetOutputSequenceNumber(dm, step, ptime);
39: VecLockReadPush(u);
40: for (i = 0; i < n; i++) (*ts->monitor[i])(ts, step, ptime, u, ts->monitorcontext[i]);
41: VecLockReadPop(u);
42: return 0;
43: }
45: /*@C
46: TSMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
48: Collective
50: Input Parameters:
51: + ts - `TS` object you wish to monitor
52: . name - the monitor type one is seeking
53: . help - message indicating what monitoring is done
54: . manual - manual page for the monitor
55: . monitor - the monitor function
56: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `TS` or `PetscViewer` objects
58: Level: developer
60: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
61: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
62: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
63: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
64: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
65: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
66: `PetscOptionsFList()`, `PetscOptionsEList()`
67: @*/
68: PetscErrorCode TSMonitorSetFromOptions(TS ts, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(TS, PetscInt, PetscReal, Vec, PetscViewerAndFormat *), PetscErrorCode (*monitorsetup)(TS, PetscViewerAndFormat *))
69: {
70: PetscViewer viewer;
71: PetscViewerFormat format;
72: PetscBool flg;
74: PetscOptionsGetViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, name, &viewer, &format, &flg);
75: if (flg) {
76: PetscViewerAndFormat *vf;
77: PetscViewerAndFormatCreate(viewer, format, &vf);
78: PetscObjectDereference((PetscObject)viewer);
79: if (monitorsetup) (*monitorsetup)(ts, vf);
80: TSMonitorSet(ts, (PetscErrorCode(*)(TS, PetscInt, PetscReal, Vec, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy);
81: }
82: return 0;
83: }
85: /*@C
86: TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
87: timestep to display the iteration's progress.
89: Logically Collective
91: Input Parameters:
92: + ts - the `TS` context obtained from `TSCreate()`
93: . monitor - monitoring routine
94: . mctx - [optional] user-defined context for private data for the
95: monitor routine (use NULL if no context is desired)
96: - monitordestroy - [optional] routine that frees monitor context
97: (may be NULL)
99: Calling sequence of monitor:
100: $ PetscErrorCode monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
102: + ts - the TS context
103: . steps - iteration number (after the final time step the monitor routine may be called with a step of -1, this indicates the solution has been interpolated to this time)
104: . time - current time
105: . u - current iterate
106: - mctx - [optional] monitoring context
108: Level: intermediate
110: Note:
111: This routine adds an additional monitor to the list of monitors that
112: already has been loaded.
114: Fortran Note:
115: Only a single monitor function can be set for each `TS` object
117: .seealso: [](chapter_ts), `TSMonitorDefault()`, `TSMonitorCancel()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
118: `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
119: `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`, `TSDMSwarmMonitorMoments()`
120: @*/
121: PetscErrorCode TSMonitorSet(TS ts, PetscErrorCode (*monitor)(TS, PetscInt, PetscReal, Vec, void *), void *mctx, PetscErrorCode (*mdestroy)(void **))
122: {
123: PetscInt i;
124: PetscBool identical;
127: for (i = 0; i < ts->numbermonitors; i++) {
128: PetscMonitorCompare((PetscErrorCode(*)(void))monitor, mctx, mdestroy, (PetscErrorCode(*)(void))ts->monitor[i], ts->monitorcontext[i], ts->monitordestroy[i], &identical);
129: if (identical) return 0;
130: }
132: ts->monitor[ts->numbermonitors] = monitor;
133: ts->monitordestroy[ts->numbermonitors] = mdestroy;
134: ts->monitorcontext[ts->numbermonitors++] = (void *)mctx;
135: return 0;
136: }
138: /*@C
139: TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
141: Logically Collective
143: Input Parameters:
144: . ts - the `TS` context obtained from `TSCreate()`
146: Level: intermediate
148: Note:
149: There is no way to remove a single, specific monitor.
151: .seealso: [](chapter_ts), `TS`, `TSMonitorDefault()`, `TSMonitorSet()`
152: @*/
153: PetscErrorCode TSMonitorCancel(TS ts)
154: {
155: PetscInt i;
158: for (i = 0; i < ts->numbermonitors; i++) {
159: if (ts->monitordestroy[i]) (*ts->monitordestroy[i])(&ts->monitorcontext[i]);
160: }
161: ts->numbermonitors = 0;
162: return 0;
163: }
165: /*@C
166: TSMonitorDefault - The Default monitor, prints the timestep and time for each step
168: Options Database Key:
169: . -ts_monitor - monitors the time integration
171: Level: intermediate
173: Notes:
174: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
175: to be used during the `TS` integration.
177: .seealso: [](chapter_ts), `TSMonitorSet()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
178: `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
179: `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`, `TSDMSwarmMonitorMoments()`
180: @*/
181: PetscErrorCode TSMonitorDefault(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
182: {
183: PetscViewer viewer = vf->viewer;
184: PetscBool iascii, ibinary;
187: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
188: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary);
189: PetscViewerPushFormat(viewer, vf->format);
190: if (iascii) {
191: PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel);
192: if (step == -1) { /* this indicates it is an interpolated solution */
193: PetscViewerASCIIPrintf(viewer, "Interpolated solution at time %g between steps %" PetscInt_FMT " and %" PetscInt_FMT "\n", (double)ptime, ts->steps - 1, ts->steps);
194: } else {
195: PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)\n" : "\n");
196: }
197: PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel);
198: } else if (ibinary) {
199: PetscMPIInt rank;
200: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
201: if (rank == 0) {
202: PetscBool skipHeader;
203: PetscInt classid = REAL_FILE_CLASSID;
205: PetscViewerBinaryGetSkipHeader(viewer, &skipHeader);
206: if (!skipHeader) PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT);
207: PetscRealView(1, &ptime, viewer);
208: } else {
209: PetscRealView(0, &ptime, viewer);
210: }
211: }
212: PetscViewerPopFormat(viewer);
213: return 0;
214: }
216: /*@C
217: TSMonitorExtreme - Prints the extreme values of the solution at each timestep
219: Level: intermediate
221: Notes:
222: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
223: to be used during the TS integration.
225: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`
226: @*/
227: PetscErrorCode TSMonitorExtreme(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
228: {
229: PetscViewer viewer = vf->viewer;
230: PetscBool iascii;
231: PetscReal max, min;
234: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
235: PetscViewerPushFormat(viewer, vf->format);
236: if (iascii) {
237: VecMax(v, NULL, &max);
238: VecMin(v, NULL, &min);
239: PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel);
240: PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s max %g min %g\n", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)" : "", (double)max, (double)min);
241: PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel);
242: }
243: PetscViewerPopFormat(viewer);
244: return 0;
245: }
247: /*@C
248: TSMonitorLGCtxCreate - Creates a `TSMonitorLGCtx` context for use with
249: `TS` to monitor the solution process graphically in various ways
251: Collective
253: Input Parameters:
254: + host - the X display to open, or null for the local machine
255: . label - the title to put in the title bar
256: . x, y - the screen coordinates of the upper left coordinate of the window
257: . m, n - the screen width and height in pixels
258: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
260: Output Parameter:
261: . ctx - the context
263: Options Database Keys:
264: + -ts_monitor_lg_timestep - automatically sets line graph monitor
265: + -ts_monitor_lg_timestep_log - automatically sets line graph monitor
266: . -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling `TSMonitorLGSetDisplayVariables()` or `TSMonitorLGCtxSetDisplayVariables()`)
267: . -ts_monitor_lg_error - monitor the error
268: . -ts_monitor_lg_ksp_iterations - monitor the number of `KSP` iterations needed for each timestep
269: . -ts_monitor_lg_snes_iterations - monitor the number of `SNES` iterations needed for each timestep
270: - -lg_use_markers <true,false> - mark the data points (at each time step) on the plot; default is true
272: Level: intermediate
274: Notes:
275: Pass the context and `TSMonitorLGCtxDestroy()` to `TSMonitorSet()` to have the context destroyed when no longer needed.
277: One can provide a function that transforms the solution before plotting it with `TSMonitorLGCtxSetTransform()` or `TSMonitorLGSetTransform()`
279: Many of the functions that control the monitoring have two forms: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a `TS` object as the
280: first argument (if that `TS` object does not have a `TSMonitorLGCtx` associated with it the function call is ignored) and the second takes a `TSMonitorLGCtx` object
281: as the first argument.
283: One can control the names displayed for each solution or error variable with `TSMonitorLGCtxSetVariableNames()` or `TSMonitorLGSetVariableNames()`
285: .seealso: [](chapter_ts), `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorDefault()`, `VecView()`,
286: `TSMonitorLGCtxCreate()`, `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
287: `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
288: `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGError()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
289: `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
290: @*/
291: PetscErrorCode TSMonitorLGCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorLGCtx *ctx)
292: {
293: PetscDraw draw;
295: PetscNew(ctx);
296: PetscDrawCreate(comm, host, label, x, y, m, n, &draw);
297: PetscDrawSetFromOptions(draw);
298: PetscDrawLGCreate(draw, 1, &(*ctx)->lg);
299: PetscDrawLGSetFromOptions((*ctx)->lg);
300: PetscDrawDestroy(&draw);
301: (*ctx)->howoften = howoften;
302: return 0;
303: }
305: PetscErrorCode TSMonitorLGTimeStep(TS ts, PetscInt step, PetscReal ptime, Vec v, void *monctx)
306: {
307: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
308: PetscReal x = ptime, y;
310: if (step < 0) return 0; /* -1 indicates an interpolated solution */
311: if (!step) {
312: PetscDrawAxis axis;
313: const char *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
314: PetscDrawLGGetAxis(ctx->lg, &axis);
315: PetscDrawAxisSetLabels(axis, "Timestep as function of time", "Time", ylabel);
316: PetscDrawLGReset(ctx->lg);
317: }
318: TSGetTimeStep(ts, &y);
319: if (ctx->semilogy) y = PetscLog10Real(y);
320: PetscDrawLGAddPoint(ctx->lg, &x, &y);
321: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
322: PetscDrawLGDraw(ctx->lg);
323: PetscDrawLGSave(ctx->lg);
324: }
325: return 0;
326: }
328: /*@C
329: TSMonitorLGCtxDestroy - Destroys a line graph context that was created
330: with `TSMonitorLGCtxCreate()`.
332: Collective
334: Input Parameter:
335: . ctx - the monitor context
337: Level: intermediate
339: Note:
340: Pass to `TSMonitorSet()` along with the context and `TSMonitorLGTimeStep()`
342: .seealso: [](chapter_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep();`
343: @*/
344: PetscErrorCode TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
345: {
346: if ((*ctx)->transformdestroy) ((*ctx)->transformdestroy)((*ctx)->transformctx);
347: PetscDrawLGDestroy(&(*ctx)->lg);
348: PetscStrArrayDestroy(&(*ctx)->names);
349: PetscStrArrayDestroy(&(*ctx)->displaynames);
350: PetscFree((*ctx)->displayvariables);
351: PetscFree((*ctx)->displayvalues);
352: PetscFree(*ctx);
353: return 0;
354: }
356: /* Creates a TS Monitor SPCtx for use with DMSwarm particle visualizations */
357: PetscErrorCode TSMonitorSPCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, PetscInt retain, PetscBool phase, TSMonitorSPCtx *ctx)
358: {
359: PetscDraw draw;
361: PetscNew(ctx);
362: PetscDrawCreate(comm, host, label, x, y, m, n, &draw);
363: PetscDrawSetFromOptions(draw);
364: PetscDrawSPCreate(draw, 1, &(*ctx)->sp);
365: PetscDrawDestroy(&draw);
366: (*ctx)->howoften = howoften;
367: (*ctx)->retain = retain;
368: (*ctx)->phase = phase;
369: return 0;
370: }
372: /*
373: Destroys a TSMonitorSPCtx that was created with TSMonitorSPCtxCreate
374: */
375: PetscErrorCode TSMonitorSPCtxDestroy(TSMonitorSPCtx *ctx)
376: {
378: PetscDrawSPDestroy(&(*ctx)->sp);
379: PetscFree(*ctx);
381: return 0;
382: }
384: /*@C
385: TSMonitorDrawSolution - Monitors progress of the `TS` solvers by calling
386: `VecView()` for the solution at each timestep
388: Collective
390: Input Parameters:
391: + ts - the `TS` context
392: . step - current time-step
393: . ptime - current time
394: - dummy - either a viewer or NULL
396: Options Database Keys:
397: + -ts_monitor_draw_solution - draw the solution at each time-step
398: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution
400: Level: intermediate
402: Notes:
403: The initial solution and current solution are not displayed with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
404: will look bad
406: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, as well as the context created with
407: `TSMonitorDrawCtxCreate()` and the function `TSMonitorDrawCtxDestroy()` to cause the monitor to be used during the `TS` integration.
409: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtxCreate()`, `TSMonitorDrawCtxDestroy()`
410: @*/
411: PetscErrorCode TSMonitorDrawSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
412: {
413: TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
414: PetscDraw draw;
416: if (!step && ictx->showinitial) {
417: if (!ictx->initialsolution) VecDuplicate(u, &ictx->initialsolution);
418: VecCopy(u, ictx->initialsolution);
419: }
420: if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) return 0;
422: if (ictx->showinitial) {
423: PetscReal pause;
424: PetscViewerDrawGetPause(ictx->viewer, &pause);
425: PetscViewerDrawSetPause(ictx->viewer, 0.0);
426: VecView(ictx->initialsolution, ictx->viewer);
427: PetscViewerDrawSetPause(ictx->viewer, pause);
428: PetscViewerDrawSetHold(ictx->viewer, PETSC_TRUE);
429: }
430: VecView(u, ictx->viewer);
431: if (ictx->showtimestepandtime) {
432: PetscReal xl, yl, xr, yr, h;
433: char time[32];
435: PetscViewerDrawGetDraw(ictx->viewer, 0, &draw);
436: PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime);
437: PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr);
438: h = yl + .95 * (yr - yl);
439: PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time);
440: PetscDrawFlush(draw);
441: }
443: if (ictx->showinitial) PetscViewerDrawSetHold(ictx->viewer, PETSC_FALSE);
444: return 0;
445: }
447: /*@C
448: TSMonitorDrawSolutionPhase - Monitors progress of the `TS` solvers by plotting the solution as a phase diagram
450: Collective
452: Input Parameters:
453: + ts - the `TS` context
454: . step - current time-step
455: . ptime - current time
456: - dummy - either a viewer or NULL
458: Level: intermediate
460: Notes:
461: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
462: to be used during the `TS` integration.
464: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
465: @*/
466: PetscErrorCode TSMonitorDrawSolutionPhase(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
467: {
468: TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
469: PetscDraw draw;
470: PetscDrawAxis axis;
471: PetscInt n;
472: PetscMPIInt size;
473: PetscReal U0, U1, xl, yl, xr, yr, h;
474: char time[32];
475: const PetscScalar *U;
477: MPI_Comm_size(PetscObjectComm((PetscObject)ts), &size);
479: VecGetSize(u, &n);
482: PetscViewerDrawGetDraw(ictx->viewer, 0, &draw);
483: PetscViewerDrawGetDrawAxis(ictx->viewer, 0, &axis);
484: PetscDrawAxisGetLimits(axis, &xl, &xr, &yl, &yr);
485: if (!step) {
486: PetscDrawClear(draw);
487: PetscDrawAxisDraw(axis);
488: }
490: VecGetArrayRead(u, &U);
491: U0 = PetscRealPart(U[0]);
492: U1 = PetscRealPart(U[1]);
493: VecRestoreArrayRead(u, &U);
494: if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) return 0;
496: PetscDrawCollectiveBegin(draw);
497: PetscDrawPoint(draw, U0, U1, PETSC_DRAW_BLACK);
498: if (ictx->showtimestepandtime) {
499: PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr);
500: PetscSNPrintf(time, 32, "Timestep %d Time %g", (int)step, (double)ptime);
501: h = yl + .95 * (yr - yl);
502: PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time);
503: }
504: PetscDrawCollectiveEnd(draw);
505: PetscDrawFlush(draw);
506: PetscDrawPause(draw);
507: PetscDrawSave(draw);
508: return 0;
509: }
511: /*@C
512: TSMonitorDrawCtxDestroy - Destroys the monitor context for `TSMonitorDrawSolution()`
514: Collective
516: Input Parameters:
517: . ctx - the monitor context
519: Level: intermediate
521: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawSolution()`, `TSMonitorDrawError()`, `TSMonitorDrawCtx`
522: @*/
523: PetscErrorCode TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
524: {
525: PetscViewerDestroy(&(*ictx)->viewer);
526: VecDestroy(&(*ictx)->initialsolution);
527: PetscFree(*ictx);
528: return 0;
529: }
531: /*@C
532: TSMonitorDrawCtxCreate - Creates the monitor context for `TSMonitorDrawCtx`
534: Collective
536: Input Parameter:
537: . ts - time-step context
539: Output Parameter:
540: . ctx - the monitor context
542: Options Database Keys:
543: + -ts_monitor_draw_solution - draw the solution at each time-step
544: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution
546: Level: intermediate
548: Note:
549: The context created by this function, `PetscMonitorDrawSolution()`, and `TSMonitorDrawCtxDestroy()` should be passed together to `TSMonitorSet()`.
551: .seealso: [](chapter_ts), `TS`, `TSMonitorDrawCtxDestroy()`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtx`, `PetscMonitorDrawSolution()`
552: @*/
553: PetscErrorCode TSMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorDrawCtx *ctx)
554: {
555: PetscNew(ctx);
556: PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer);
557: PetscViewerSetFromOptions((*ctx)->viewer);
559: (*ctx)->howoften = howoften;
560: (*ctx)->showinitial = PETSC_FALSE;
561: PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_initial", &(*ctx)->showinitial, NULL);
563: (*ctx)->showtimestepandtime = PETSC_FALSE;
564: PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_show_time", &(*ctx)->showtimestepandtime, NULL);
565: return 0;
566: }
568: /*@C
569: TSMonitorDrawSolutionFunction - Monitors progress of the `TS` solvers by calling
570: `VecView()` for the solution provided by `TSSetSolutionFunction()` at each timestep
572: Collective
574: Input Parameters:
575: + ts - the `TS` context
576: . step - current time-step
577: . ptime - current time
578: - dummy - either a viewer or NULL
580: Options Database Key:
581: . -ts_monitor_draw_solution_function - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`
583: Level: intermediate
585: Note:
586: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
587: to be used during the `TS` integration.
589: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
590: @*/
591: PetscErrorCode TSMonitorDrawSolutionFunction(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
592: {
593: TSMonitorDrawCtx ctx = (TSMonitorDrawCtx)dummy;
594: PetscViewer viewer = ctx->viewer;
595: Vec work;
597: if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) return 0;
598: VecDuplicate(u, &work);
599: TSComputeSolutionFunction(ts, ptime, work);
600: VecView(work, viewer);
601: VecDestroy(&work);
602: return 0;
603: }
605: /*@C
606: TSMonitorDrawError - Monitors progress of the `TS` solvers by calling
607: `VecView()` for the error at each timestep
609: Collective
611: Input Parameters:
612: + ts - the `TS` context
613: . step - current time-step
614: . ptime - current time
615: - dummy - either a viewer or NULL
617: Options Database Key:
618: . -ts_monitor_draw_error - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`
620: Level: intermediate
622: Notes:
623: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
624: to be used during the `TS` integration.
626: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
627: @*/
628: PetscErrorCode TSMonitorDrawError(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
629: {
630: TSMonitorDrawCtx ctx = (TSMonitorDrawCtx)dummy;
631: PetscViewer viewer = ctx->viewer;
632: Vec work;
634: if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) return 0;
635: VecDuplicate(u, &work);
636: TSComputeSolutionFunction(ts, ptime, work);
637: VecAXPY(work, -1.0, u);
638: VecView(work, viewer);
639: VecDestroy(&work);
640: return 0;
641: }
643: /*@C
644: TSMonitorSolution - Monitors progress of the TS solvers by `VecView()` for the solution at each timestep. Normally the viewer is a binary file or a `PetscDraw` object
646: Collective
648: Input Parameters:
649: + ts - the `TS` context
650: . step - current time-step
651: . ptime - current time
652: . u - current state
653: - vf - viewer and its format
655: Level: intermediate
657: Notes:
658: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
659: to be used during the `TS` integration.
661: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
662: @*/
663: PetscErrorCode TSMonitorSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
664: {
665: PetscViewerPushFormat(vf->viewer, vf->format);
666: VecView(u, vf->viewer);
667: PetscViewerPopFormat(vf->viewer);
668: return 0;
669: }
671: /*@C
672: TSMonitorSolutionVTK - Monitors progress of the `TS` solvers by `VecView()` for the solution at each timestep.
674: Collective
676: Input Parameters:
677: + ts - the `TS` context
678: . step - current time-step
679: . ptime - current time
680: . u - current state
681: - filenametemplate - string containing a format specifier for the integer time step (e.g. %03" PetscInt_FMT ")
683: Level: intermediate
685: Notes:
686: The VTK format does not allow writing multiple time steps in the same file, therefore a different file will be written for each time step.
687: These are named according to the file name template.
689: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
690: to be used during the `TS` integration.
692: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
693: @*/
694: PetscErrorCode TSMonitorSolutionVTK(TS ts, PetscInt step, PetscReal ptime, Vec u, void *filenametemplate)
695: {
696: char filename[PETSC_MAX_PATH_LEN];
697: PetscViewer viewer;
699: if (step < 0) return 0; /* -1 indicates interpolated solution */
700: PetscSNPrintf(filename, sizeof(filename), (const char *)filenametemplate, step);
701: PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts), filename, FILE_MODE_WRITE, &viewer);
702: VecView(u, viewer);
703: PetscViewerDestroy(&viewer);
704: return 0;
705: }
707: /*@C
708: TSMonitorSolutionVTKDestroy - Destroy filename template string created for use with `TSMonitorSolutionVTK()`
710: Not Collective
712: Input Parameters:
713: . filenametemplate - string containing a format specifier for the integer time step (e.g. %03" PetscInt_FMT ")
715: Level: intermediate
717: Note:
718: This function is normally passed to `TSMonitorSet()` along with `TSMonitorSolutionVTK()`.
720: .seealso: [](chapter_ts), `TSMonitorSet()`, `TSMonitorSolutionVTK()`
721: @*/
722: PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
723: {
724: PetscFree(*(char **)filenametemplate);
725: return 0;
726: }
728: /*@C
729: TSMonitorLGSolution - Monitors progress of the `TS` solvers by plotting each component of the solution vector
730: in a time based line graph
732: Collective
734: Input Parameters:
735: + ts - the `TS` context
736: . step - current time-step
737: . ptime - current time
738: . u - current solution
739: - dctx - the `TSMonitorLGCtx` object that contains all the options for the monitoring, this is created with `TSMonitorLGCtxCreate()`
741: Options Database Key:
742: . -ts_monitor_lg_solution_variables - enable monitor of lg solution variables
744: Level: intermediate
746: Notes:
747: Each process in a parallel run displays its component solutions in a separate window
749: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
750: to be used during the `TS` integration.
752: .seealso: [](chapter_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
753: `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
754: `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGError()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
755: `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
756: @*/
757: PetscErrorCode TSMonitorLGSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
758: {
759: TSMonitorLGCtx ctx = (TSMonitorLGCtx)dctx;
760: const PetscScalar *yy;
761: Vec v;
763: if (step < 0) return 0; /* -1 indicates interpolated solution */
764: if (!step) {
765: PetscDrawAxis axis;
766: PetscInt dim;
767: PetscDrawLGGetAxis(ctx->lg, &axis);
768: PetscDrawAxisSetLabels(axis, "Solution as function of time", "Time", "Solution");
769: if (!ctx->names) {
770: PetscBool flg;
771: /* user provides names of variables to plot but no names has been set so assume names are integer values */
772: PetscOptionsHasName(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", &flg);
773: if (flg) {
774: PetscInt i, n;
775: char **names;
776: VecGetSize(u, &n);
777: PetscMalloc1(n + 1, &names);
778: for (i = 0; i < n; i++) {
779: PetscMalloc1(5, &names[i]);
780: PetscSNPrintf(names[i], 5, "%" PetscInt_FMT, i);
781: }
782: names[n] = NULL;
783: ctx->names = names;
784: }
785: }
786: if (ctx->names && !ctx->displaynames) {
787: char **displaynames;
788: PetscBool flg;
789: VecGetLocalSize(u, &dim);
790: PetscCalloc1(dim + 1, &displaynames);
791: PetscOptionsGetStringArray(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", displaynames, &dim, &flg);
792: if (flg) TSMonitorLGCtxSetDisplayVariables(ctx, (const char *const *)displaynames);
793: PetscStrArrayDestroy(&displaynames);
794: }
795: if (ctx->displaynames) {
796: PetscDrawLGSetDimension(ctx->lg, ctx->ndisplayvariables);
797: PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->displaynames);
798: } else if (ctx->names) {
799: VecGetLocalSize(u, &dim);
800: PetscDrawLGSetDimension(ctx->lg, dim);
801: PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->names);
802: } else {
803: VecGetLocalSize(u, &dim);
804: PetscDrawLGSetDimension(ctx->lg, dim);
805: }
806: PetscDrawLGReset(ctx->lg);
807: }
809: if (!ctx->transform) v = u;
810: else (*ctx->transform)(ctx->transformctx, u, &v);
811: VecGetArrayRead(v, &yy);
812: if (ctx->displaynames) {
813: PetscInt i;
814: for (i = 0; i < ctx->ndisplayvariables; i++) ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
815: PetscDrawLGAddCommonPoint(ctx->lg, ptime, ctx->displayvalues);
816: } else {
817: #if defined(PETSC_USE_COMPLEX)
818: PetscInt i, n;
819: PetscReal *yreal;
820: VecGetLocalSize(v, &n);
821: PetscMalloc1(n, &yreal);
822: for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
823: PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal);
824: PetscFree(yreal);
825: #else
826: PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy);
827: #endif
828: }
829: VecRestoreArrayRead(v, &yy);
830: if (ctx->transform) VecDestroy(&v);
832: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
833: PetscDrawLGDraw(ctx->lg);
834: PetscDrawLGSave(ctx->lg);
835: }
836: return 0;
837: }
839: /*@C
840: TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
842: Collective
844: Input Parameters:
845: + ts - the `TS` context
846: - names - the names of the components, final string must be NULL
848: Level: intermediate
850: Notes:
851: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
853: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetVariableNames()`
854: @*/
855: PetscErrorCode TSMonitorLGSetVariableNames(TS ts, const char *const *names)
856: {
857: PetscInt i;
859: for (i = 0; i < ts->numbermonitors; i++) {
860: if (ts->monitor[i] == TSMonitorLGSolution) {
861: TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i], names);
862: break;
863: }
864: }
865: return 0;
866: }
868: /*@C
869: TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
871: Collective
873: Input Parameters:
874: + ts - the `TS` context
875: - names - the names of the components, final string must be NULL
877: Level: intermediate
879: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGSetVariableNames()`
880: @*/
881: PetscErrorCode TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx, const char *const *names)
882: {
883: PetscStrArrayDestroy(&ctx->names);
884: PetscStrArrayallocpy(names, &ctx->names);
885: return 0;
886: }
888: /*@C
889: TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
891: Collective
893: Input Parameter:
894: . ts - the `TS` context
896: Output Parameter:
897: . names - the names of the components, final string must be NULL
899: Level: intermediate
901: Note:
902: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
904: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
905: @*/
906: PetscErrorCode TSMonitorLGGetVariableNames(TS ts, const char *const **names)
907: {
908: PetscInt i;
910: *names = NULL;
911: for (i = 0; i < ts->numbermonitors; i++) {
912: if (ts->monitor[i] == TSMonitorLGSolution) {
913: TSMonitorLGCtx ctx = (TSMonitorLGCtx)ts->monitorcontext[i];
914: *names = (const char *const *)ctx->names;
915: break;
916: }
917: }
918: return 0;
919: }
921: /*@C
922: TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
924: Collective
926: Input Parameters:
927: + ctx - the `TSMonitorLG` context
928: - displaynames - the names of the components, final string must be NULL
930: Level: intermediate
932: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
933: @*/
934: PetscErrorCode TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx, const char *const *displaynames)
935: {
936: PetscInt j = 0, k;
938: if (!ctx->names) return 0;
939: PetscStrArrayDestroy(&ctx->displaynames);
940: PetscStrArrayallocpy(displaynames, &ctx->displaynames);
941: while (displaynames[j]) j++;
942: ctx->ndisplayvariables = j;
943: PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvariables);
944: PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvalues);
945: j = 0;
946: while (displaynames[j]) {
947: k = 0;
948: while (ctx->names[k]) {
949: PetscBool flg;
950: PetscStrcmp(displaynames[j], ctx->names[k], &flg);
951: if (flg) {
952: ctx->displayvariables[j] = k;
953: break;
954: }
955: k++;
956: }
957: j++;
958: }
959: return 0;
960: }
962: /*@C
963: TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
965: Collective
967: Input Parameters:
968: + ts - the `TS` context
969: - displaynames - the names of the components, final string must be NULL
971: Level: intermediate
973: Note:
974: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
976: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
977: @*/
978: PetscErrorCode TSMonitorLGSetDisplayVariables(TS ts, const char *const *displaynames)
979: {
980: PetscInt i;
982: for (i = 0; i < ts->numbermonitors; i++) {
983: if (ts->monitor[i] == TSMonitorLGSolution) {
984: TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i], displaynames);
985: break;
986: }
987: }
988: return 0;
989: }
991: /*@C
992: TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
994: Collective
996: Input Parameters:
997: + ts - the `TS` context
998: . transform - the transform function
999: . destroy - function to destroy the optional context
1000: - ctx - optional context used by transform function
1002: Level: intermediate
1004: Note:
1005: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
1007: .seealso: [](chapter_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGCtxSetTransform()`
1008: @*/
1009: PetscErrorCode TSMonitorLGSetTransform(TS ts, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
1010: {
1011: PetscInt i;
1013: for (i = 0; i < ts->numbermonitors; i++) {
1014: if (ts->monitor[i] == TSMonitorLGSolution) TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i], transform, destroy, tctx);
1015: }
1016: return 0;
1017: }
1019: /*@C
1020: TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
1022: Collective
1024: Input Parameters:
1025: + ts - the `TS` context
1026: . transform - the transform function
1027: . destroy - function to destroy the optional context
1028: - ctx - optional context used by transform function
1030: Level: intermediate
1032: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGSetTransform()`
1033: @*/
1034: PetscErrorCode TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx, PetscErrorCode (*transform)(void *, Vec, Vec *), PetscErrorCode (*destroy)(void *), void *tctx)
1035: {
1036: ctx->transform = transform;
1037: ctx->transformdestroy = destroy;
1038: ctx->transformctx = tctx;
1039: return 0;
1040: }
1042: /*@C
1043: TSMonitorLGError - Monitors progress of the `TS` solvers by plotting each component of the error
1044: in a time based line graph
1046: Collective
1048: Input Parameters:
1049: + ts - the `TS` context
1050: . step - current time-step
1051: . ptime - current time
1052: . u - current solution
1053: - dctx - `TSMonitorLGCtx` object created with `TSMonitorLGCtxCreate()`
1055: Options Database Key:
1056: . -ts_monitor_lg_error - create a graphical monitor of error history
1058: Level: intermediate
1060: Notes:
1061: Each process in a parallel run displays its component errors in a separate window
1063: The user must provide the solution using `TSSetSolutionFunction()` to use this monitor.
1065: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1066: to be used during the TS integration.
1068: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1069: @*/
1070: PetscErrorCode TSMonitorLGError(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dummy)
1071: {
1072: TSMonitorLGCtx ctx = (TSMonitorLGCtx)dummy;
1073: const PetscScalar *yy;
1074: Vec y;
1076: if (!step) {
1077: PetscDrawAxis axis;
1078: PetscInt dim;
1079: PetscDrawLGGetAxis(ctx->lg, &axis);
1080: PetscDrawAxisSetLabels(axis, "Error in solution as function of time", "Time", "Error");
1081: VecGetLocalSize(u, &dim);
1082: PetscDrawLGSetDimension(ctx->lg, dim);
1083: PetscDrawLGReset(ctx->lg);
1084: }
1085: VecDuplicate(u, &y);
1086: TSComputeSolutionFunction(ts, ptime, y);
1087: VecAXPY(y, -1.0, u);
1088: VecGetArrayRead(y, &yy);
1089: #if defined(PETSC_USE_COMPLEX)
1090: {
1091: PetscReal *yreal;
1092: PetscInt i, n;
1093: VecGetLocalSize(y, &n);
1094: PetscMalloc1(n, &yreal);
1095: for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
1096: PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal);
1097: PetscFree(yreal);
1098: }
1099: #else
1100: PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy);
1101: #endif
1102: VecRestoreArrayRead(y, &yy);
1103: VecDestroy(&y);
1104: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1105: PetscDrawLGDraw(ctx->lg);
1106: PetscDrawLGSave(ctx->lg);
1107: }
1108: return 0;
1109: }
1111: /*@C
1112: TSMonitorSPSwarmSolution - Graphically displays phase plots of `DMSWARM` particles on a scatter plot
1114: Input Parameters:
1115: + ts - the `TS` context
1116: . step - current time-step
1117: . ptime - current time
1118: . u - current solution
1119: - dctx - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorSPCtxCreate()`
1121: Options Database Keys:
1122: + -ts_monitor_sp_swarm <n> - Monitor the solution every n steps, or -1 for plotting only the final solution
1123: . -ts_monitor_sp_swarm_retain <n> - Retain n old points so we can see the history, or -1 for all points
1124: - -ts_monitor_sp_swarm_phase <bool> - Plot in phase space, as opposed to coordinate space
1126: Level: intermediate
1128: Notes:
1129: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1130: to be used during the `TS` integration.
1132: .seealso: [](chapter_ts), `TS`, `TSMonitoSet()`, `DMSWARM`, `TSMonitorSPCtxCreate()`
1133: @*/
1134: PetscErrorCode TSMonitorSPSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1135: {
1136: TSMonitorSPCtx ctx = (TSMonitorSPCtx)dctx;
1137: PetscDraw draw;
1138: DM dm, cdm;
1139: const PetscScalar *yy;
1140: PetscInt Np, p, dim = 2;
1142: if (step < 0) return 0; /* -1 indicates interpolated solution */
1143: if (!step) {
1144: PetscDrawAxis axis;
1145: PetscReal dmboxlower[2], dmboxupper[2];
1147: TSGetDM(ts, &dm);
1148: DMGetDimension(dm, &dim);
1150: DMSwarmGetCellDM(dm, &cdm);
1151: DMGetBoundingBox(cdm, dmboxlower, dmboxupper);
1152: VecGetLocalSize(u, &Np);
1153: Np /= dim * 2;
1154: PetscDrawSPGetAxis(ctx->sp, &axis);
1155: if (ctx->phase) {
1156: PetscDrawAxisSetLabels(axis, "Particles", "X", "V");
1157: PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], -5, 5);
1158: } else {
1159: PetscDrawAxisSetLabels(axis, "Particles", "X", "Y");
1160: PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], dmboxlower[1], dmboxupper[1]);
1161: }
1162: PetscDrawAxisSetHoldLimits(axis, PETSC_TRUE);
1163: PetscDrawSPReset(ctx->sp);
1164: }
1165: VecGetLocalSize(u, &Np);
1166: Np /= dim * 2;
1167: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1168: PetscDrawSPGetDraw(ctx->sp, &draw);
1169: if ((ctx->retain == 0) || (ctx->retain > 0 && !(step % ctx->retain))) PetscDrawClear(draw);
1170: PetscDrawFlush(draw);
1171: PetscDrawSPReset(ctx->sp);
1172: VecGetArrayRead(u, &yy);
1173: for (p = 0; p < Np; ++p) {
1174: PetscReal x, y;
1176: if (ctx->phase) {
1177: x = PetscRealPart(yy[p * dim * 2]);
1178: y = PetscRealPart(yy[p * dim * 2 + dim]);
1179: } else {
1180: x = PetscRealPart(yy[p * dim * 2]);
1181: y = PetscRealPart(yy[p * dim * 2 + 1]);
1182: }
1183: PetscDrawSPAddPoint(ctx->sp, &x, &y);
1184: }
1185: VecRestoreArrayRead(u, &yy);
1186: PetscDrawSPDraw(ctx->sp, PETSC_FALSE);
1187: PetscDrawSPSave(ctx->sp);
1188: }
1189: return 0;
1190: }
1192: /*@C
1193: TSMonitorError - Monitors progress of the `TS` solvers by printing the 2 norm of the error at each timestep
1195: Collective
1197: Input Parameters:
1198: + ts - the `TS` context
1199: . step - current time-step
1200: . ptime - current time
1201: . u - current solution
1202: - dctx - unused context
1204: Options Database Key:
1205: . -ts_monitor_error - create a graphical monitor of error history
1207: Level: intermediate
1209: Notes:
1210: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1211: to be used during the `TS` integration.
1213: The user must provide the solution using `TSSetSolutionFunction()` to use this monitor.
1215: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1216: @*/
1217: PetscErrorCode TSMonitorError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
1218: {
1219: DM dm;
1220: PetscDS ds = NULL;
1221: PetscInt Nf = -1, f;
1222: PetscBool flg;
1224: TSGetDM(ts, &dm);
1225: if (dm) DMGetDS(dm, &ds);
1226: if (ds) PetscDSGetNumFields(ds, &Nf);
1227: if (Nf <= 0) {
1228: Vec y;
1229: PetscReal nrm;
1231: VecDuplicate(u, &y);
1232: TSComputeSolutionFunction(ts, ptime, y);
1233: VecAXPY(y, -1.0, u);
1234: PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERASCII, &flg);
1235: if (flg) {
1236: VecNorm(y, NORM_2, &nrm);
1237: PetscViewerASCIIPrintf(vf->viewer, "2-norm of error %g\n", (double)nrm);
1238: }
1239: PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &flg);
1240: if (flg) VecView(y, vf->viewer);
1241: VecDestroy(&y);
1242: } else {
1243: PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx);
1244: void **ctxs;
1245: Vec v;
1246: PetscReal ferrors[1];
1248: PetscMalloc2(Nf, &exactFuncs, Nf, &ctxs);
1249: for (f = 0; f < Nf; ++f) PetscDSGetExactSolution(ds, f, &exactFuncs[f], &ctxs[f]);
1250: DMComputeL2FieldDiff(dm, ptime, exactFuncs, ctxs, u, ferrors);
1251: PetscPrintf(PETSC_COMM_WORLD, "Timestep: %04d time = %-8.4g \t L_2 Error: [", (int)step, (double)ptime);
1252: for (f = 0; f < Nf; ++f) {
1253: if (f > 0) PetscPrintf(PETSC_COMM_WORLD, ", ");
1254: PetscPrintf(PETSC_COMM_WORLD, "%2.3g", (double)ferrors[f]);
1255: }
1256: PetscPrintf(PETSC_COMM_WORLD, "]\n");
1258: VecViewFromOptions(u, NULL, "-sol_vec_view");
1260: PetscOptionsHasName(NULL, NULL, "-exact_vec_view", &flg);
1261: if (flg) {
1262: DMGetGlobalVector(dm, &v);
1263: DMProjectFunction(dm, ptime, exactFuncs, ctxs, INSERT_ALL_VALUES, v);
1264: PetscObjectSetName((PetscObject)v, "Exact Solution");
1265: VecViewFromOptions(v, NULL, "-exact_vec_view");
1266: DMRestoreGlobalVector(dm, &v);
1267: }
1268: PetscFree2(exactFuncs, ctxs);
1269: }
1270: return 0;
1271: }
1273: PetscErrorCode TSMonitorLGSNESIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, void *monctx)
1274: {
1275: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1276: PetscReal x = ptime, y;
1277: PetscInt its;
1279: if (n < 0) return 0; /* -1 indicates interpolated solution */
1280: if (!n) {
1281: PetscDrawAxis axis;
1282: PetscDrawLGGetAxis(ctx->lg, &axis);
1283: PetscDrawAxisSetLabels(axis, "Nonlinear iterations as function of time", "Time", "SNES Iterations");
1284: PetscDrawLGReset(ctx->lg);
1285: ctx->snes_its = 0;
1286: }
1287: TSGetSNESIterations(ts, &its);
1288: y = its - ctx->snes_its;
1289: PetscDrawLGAddPoint(ctx->lg, &x, &y);
1290: if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1291: PetscDrawLGDraw(ctx->lg);
1292: PetscDrawLGSave(ctx->lg);
1293: }
1294: ctx->snes_its = its;
1295: return 0;
1296: }
1298: PetscErrorCode TSMonitorLGKSPIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, void *monctx)
1299: {
1300: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1301: PetscReal x = ptime, y;
1302: PetscInt its;
1304: if (n < 0) return 0; /* -1 indicates interpolated solution */
1305: if (!n) {
1306: PetscDrawAxis axis;
1307: PetscDrawLGGetAxis(ctx->lg, &axis);
1308: PetscDrawAxisSetLabels(axis, "Linear iterations as function of time", "Time", "KSP Iterations");
1309: PetscDrawLGReset(ctx->lg);
1310: ctx->ksp_its = 0;
1311: }
1312: TSGetKSPIterations(ts, &its);
1313: y = its - ctx->ksp_its;
1314: PetscDrawLGAddPoint(ctx->lg, &x, &y);
1315: if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1316: PetscDrawLGDraw(ctx->lg);
1317: PetscDrawLGSave(ctx->lg);
1318: }
1319: ctx->ksp_its = its;
1320: return 0;
1321: }
1323: /*@C
1324: TSMonitorEnvelopeCtxCreate - Creates a context for use with `TSMonitorEnvelope()`
1326: Collective
1328: Input Parameters:
1329: . ts - the `TS` solver object
1331: Output Parameter:
1332: . ctx - the context
1334: Level: intermediate
1336: .seealso: [](chapter_ts), `TS`, `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`
1337: @*/
1338: PetscErrorCode TSMonitorEnvelopeCtxCreate(TS ts, TSMonitorEnvelopeCtx *ctx)
1339: {
1340: PetscNew(ctx);
1341: return 0;
1342: }
1344: /*@C
1345: TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
1347: Collective
1349: Input Parameters:
1350: + ts - the TS context
1351: . step - current time-step
1352: . ptime - current time
1353: . u - current solution
1354: - dctx - the envelope context
1356: Options Database Key:
1357: . -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time
1359: Level: intermediate
1361: Notes:
1362: After a solve you can use `TSMonitorEnvelopeGetBounds()` to access the envelope
1364: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1365: to be used during the `TS` integration.
1367: .seealso: [](chapter_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxCreate()`
1368: @*/
1369: PetscErrorCode TSMonitorEnvelope(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1370: {
1371: TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
1373: if (!ctx->max) {
1374: VecDuplicate(u, &ctx->max);
1375: VecDuplicate(u, &ctx->min);
1376: VecCopy(u, ctx->max);
1377: VecCopy(u, ctx->min);
1378: } else {
1379: VecPointwiseMax(ctx->max, u, ctx->max);
1380: VecPointwiseMin(ctx->min, u, ctx->min);
1381: }
1382: return 0;
1383: }
1385: /*@C
1386: TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
1388: Collective
1390: Input Parameter:
1391: . ts - the `TS` context
1393: Output Parameters:
1394: + max - the maximum values
1395: - min - the minimum values
1397: Notes:
1398: If the `TS` does not have a `TSMonitorEnvelopeCtx` associated with it then this function is ignored
1400: Level: intermediate
1402: .seealso: [](chapter_ts), `TSMonitorEnvelopeCtx`, `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
1403: @*/
1404: PetscErrorCode TSMonitorEnvelopeGetBounds(TS ts, Vec *max, Vec *min)
1405: {
1406: PetscInt i;
1408: if (max) *max = NULL;
1409: if (min) *min = NULL;
1410: for (i = 0; i < ts->numbermonitors; i++) {
1411: if (ts->monitor[i] == TSMonitorEnvelope) {
1412: TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)ts->monitorcontext[i];
1413: if (max) *max = ctx->max;
1414: if (min) *min = ctx->min;
1415: break;
1416: }
1417: }
1418: return 0;
1419: }
1421: /*@C
1422: TSMonitorEnvelopeCtxDestroy - Destroys a context that was created with `TSMonitorEnvelopeCtxCreate()`.
1424: Collective
1426: Input Parameter:
1427: . ctx - the monitor context
1429: Level: intermediate
1431: .seealso: [](chapter_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
1432: @*/
1433: PetscErrorCode TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
1434: {
1435: VecDestroy(&(*ctx)->min);
1436: VecDestroy(&(*ctx)->max);
1437: PetscFree(*ctx);
1438: return 0;
1439: }
1441: /*@C
1442: TSDMSwarmMonitorMoments - Monitors the first three moments of a `DMSWARM` being evolved by the `TS`
1444: Not collective
1446: Input Parameters:
1447: + ts - the `TS` context
1448: . step - current timestep
1449: . t - current time
1450: . u - current solution
1451: - ctx - not used
1453: Options Database Key:
1454: . -ts_dmswarm_monitor_moments - Monitor moments of particle distribution
1456: Level: intermediate
1458: Notes:
1459: This requires a `DMSWARM` be attached to the `TS`.
1461: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1462: to be used during the TS integration.
1464: .seealso: [](chapter_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `DMSWARM`
1465: @*/
1466: PetscErrorCode TSDMSwarmMonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, PetscViewerAndFormat *vf)
1467: {
1468: DM sw;
1469: const PetscScalar *u;
1470: PetscReal m = 1.0, totE = 0., totMom[3] = {0., 0., 0.};
1471: PetscInt dim, d, Np, p;
1472: MPI_Comm comm;
1475: TSGetDM(ts, &sw);
1476: if (!sw || step % ts->monitorFrequency != 0) return 0;
1477: PetscObjectGetComm((PetscObject)ts, &comm);
1478: DMGetDimension(sw, &dim);
1479: VecGetLocalSize(U, &Np);
1480: Np /= dim;
1481: VecGetArrayRead(U, &u);
1482: for (p = 0; p < Np; ++p) {
1483: for (d = 0; d < dim; ++d) {
1484: totE += PetscRealPart(u[p * dim + d] * u[p * dim + d]);
1485: totMom[d] += PetscRealPart(u[p * dim + d]);
1486: }
1487: }
1488: VecRestoreArrayRead(U, &u);
1489: for (d = 0; d < dim; ++d) totMom[d] *= m;
1490: totE *= 0.5 * m;
1491: PetscPrintf(comm, "Step %4" PetscInt_FMT " Total Energy: %10.8lf", step, (double)totE);
1492: for (d = 0; d < dim; ++d) PetscPrintf(comm, " Total Momentum %c: %10.8lf", (char)('x' + d), (double)totMom[d]);
1493: PetscPrintf(comm, "\n");
1494: return 0;
1495: }