Actual source code: tsmon.c
1: #include <petsc/private/tsimpl.h>
2: #include <petscdm.h>
3: #include <petscds.h>
4: #include <petscdmswarm.h>
5: #include <petscdraw.h>
7: /*@C
8: TSMonitor - Runs all user-provided monitor routines set using `TSMonitorSet()`
10: Collective
12: Input Parameters:
13: + ts - time stepping context obtained from `TSCreate()`
14: . step - step number that has just completed
15: . ptime - model time of the state
16: - u - state at the current model time
18: Level: developer
20: Notes:
21: `TSMonitor()` is typically used automatically within the time stepping implementations.
22: Users would almost never call this routine directly.
24: A step of -1 indicates that the monitor is being called on a solution obtained by interpolating from computed solutions
26: .seealso: `TS`, `TSMonitorSet()`, `TSMonitorSetFromOptions()`
27: @*/
28: PetscErrorCode TSMonitor(TS ts, PetscInt step, PetscReal ptime, Vec u)
29: {
30: DM dm;
31: PetscInt i, n = ts->numbermonitors;
33: PetscFunctionBegin;
37: PetscCall(TSGetDM(ts, &dm));
38: PetscCall(DMSetOutputSequenceNumber(dm, step, ptime));
40: PetscCall(VecLockReadPush(u));
41: for (i = 0; i < n; i++) PetscCall((*ts->monitor[i])(ts, step, ptime, u, ts->monitorcontext[i]));
42: PetscCall(VecLockReadPop(u));
43: PetscFunctionReturn(PETSC_SUCCESS);
44: }
46: /*@C
47: TSMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
49: Collective
51: Input Parameters:
52: + ts - `TS` object you wish to monitor
53: . name - the monitor type one is seeking
54: . help - message indicating what monitoring is done
55: . manual - manual page for the monitor
56: . monitor - the monitor function, this must use a `PetscViewerFormat` as its context
57: - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `TS` or `PetscViewer` objects
59: Calling sequence of `monitor`:
60: + ts - the `TS` to monitor
61: . step - the current time-step
62: . time - the current time
63: . u - the current solution
64: - vf - the `PetscViewer` and format to monitor with
66: Calling sequence of `monitorsetup`:
67: + ts - the `TS` to monitor
68: - vf - the `PetscViewer` and format to monitor with
70: Level: developer
72: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
73: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
74: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
75: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
76: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
77: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
78: `PetscOptionsFList()`, `PetscOptionsEList()`
79: @*/
80: PetscErrorCode TSMonitorSetFromOptions(TS ts, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(TS ts, PetscInt step, PetscReal time, Vec u, PetscViewerAndFormat *vf), PetscErrorCode (*monitorsetup)(TS ts, PetscViewerAndFormat *vf))
81: {
82: PetscViewer viewer;
83: PetscViewerFormat format;
84: PetscBool flg;
86: PetscFunctionBegin;
87: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ts), ((PetscObject)ts)->options, ((PetscObject)ts)->prefix, name, &viewer, &format, &flg));
88: if (flg) {
89: PetscViewerAndFormat *vf;
90: char interval_key[1024];
92: PetscCall(PetscSNPrintf(interval_key, sizeof interval_key, "%s_interval", name));
93: PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
94: vf->view_interval = 1;
95: PetscCall(PetscOptionsGetInt(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, interval_key, &vf->view_interval, NULL));
97: PetscCall(PetscViewerDestroy(&viewer));
98: if (monitorsetup) PetscCall((*monitorsetup)(ts, vf));
99: PetscCall(TSMonitorSet(ts, (PetscErrorCode (*)(TS, PetscInt, PetscReal, Vec, PetscCtx))monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
100: }
101: PetscFunctionReturn(PETSC_SUCCESS);
102: }
104: /*@C
105: TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
106: timestep to display the iteration's progress.
108: Logically Collective
110: Input Parameters:
111: + ts - the `TS` context obtained from `TSCreate()`
112: . monitor - monitoring routine
113: . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
114: - mdestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
116: Calling sequence of `monitor`:
117: + ts - the `TS` context
118: . steps - iteration number (after the final time step the monitor routine may be called with a step of -1, this indicates the solution has been interpolated to this time)
119: . time - current time
120: . u - current iterate
121: - ctx - [optional] monitoring context
123: Level: intermediate
125: Note:
126: This routine adds an additional monitor to the list of monitors that already has been loaded.
128: Fortran Notes:
129: Only a single monitor function can be set for each `TS` object
131: .seealso: [](ch_ts), `TSMonitorDefault()`, `TSMonitorCancel()`, `TSDMSwarmMonitorMoments()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
132: `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
133: `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`, `PetscCtxDestroyFn`
134: @*/
135: PetscErrorCode TSMonitorSet(TS ts, PetscErrorCode (*monitor)(TS ts, PetscInt steps, PetscReal time, Vec u, PetscCtx ctx), PetscCtx mctx, PetscCtxDestroyFn *mdestroy)
136: {
137: PetscFunctionBegin;
139: for (PetscInt i = 0; i < ts->numbermonitors; i++) {
140: PetscBool identical;
142: PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))(PetscVoidFn *)monitor, mctx, mdestroy, (PetscErrorCode (*)(void))(PetscVoidFn *)ts->monitor[i], ts->monitorcontext[i], ts->monitordestroy[i], &identical));
143: if (identical) PetscFunctionReturn(PETSC_SUCCESS);
144: }
145: PetscCheck(ts->numbermonitors < MAXTSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
146: ts->monitor[ts->numbermonitors] = monitor;
147: ts->monitordestroy[ts->numbermonitors] = mdestroy;
148: ts->monitorcontext[ts->numbermonitors++] = mctx;
149: PetscFunctionReturn(PETSC_SUCCESS);
150: }
152: /*@C
153: TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
155: Logically Collective
157: Input Parameter:
158: . ts - the `TS` context obtained from `TSCreate()`
160: Level: intermediate
162: Note:
163: There is no way to remove a single, specific monitor.
165: .seealso: [](ch_ts), `TS`, `TSMonitorDefault()`, `TSMonitorSet()`
166: @*/
167: PetscErrorCode TSMonitorCancel(TS ts)
168: {
169: PetscInt i;
171: PetscFunctionBegin;
173: for (i = 0; i < ts->numbermonitors; i++) {
174: if (ts->monitordestroy[i]) PetscCall((*ts->monitordestroy[i])(&ts->monitorcontext[i]));
175: }
176: ts->numbermonitors = 0;
177: PetscFunctionReturn(PETSC_SUCCESS);
178: }
180: /*@C
181: TSMonitorDefault - The default monitor, prints the timestep and time for each step
183: Input Parameters:
184: + ts - the `TS` context
185: . step - iteration number (after the final time step the monitor routine may be called with a step of -1, this indicates the solution has been interpolated to this time)
186: . ptime - current time
187: . v - current iterate
188: - vf - the viewer and format
190: Options Database Key:
191: . -ts_monitor - monitors the time integration
193: Level: intermediate
195: Notes:
196: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
197: to be used during the `TS` integration.
199: .seealso: [](ch_ts), `TSMonitorSet()`, `TSDMSwarmMonitorMoments()`, `TSMonitorWallClockTime()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
200: `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
201: `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`
202: @*/
203: PetscErrorCode TSMonitorDefault(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
204: {
205: PetscViewer viewer = vf->viewer;
206: PetscBool isascii, ibinary;
208: PetscFunctionBegin;
210: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
211: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
212: PetscCall(PetscViewerPushFormat(viewer, vf->format));
213: if (isascii) {
214: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
215: if (step == -1) { /* this indicates it is an interpolated solution */
216: PetscCall(PetscViewerASCIIPrintf(viewer, "Interpolated solution at time %g between steps %" PetscInt_FMT " and %" PetscInt_FMT "\n", (double)ptime, ts->steps - 1, ts->steps));
217: } else {
218: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)\n" : "\n"));
219: }
220: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
221: } else if (ibinary) {
222: PetscMPIInt rank;
223: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
224: if (rank == 0) {
225: PetscBool skipHeader;
226: PetscInt classid = REAL_FILE_CLASSID;
228: PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
229: if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, &classid, 1, PETSC_INT));
230: PetscCall(PetscRealView(1, &ptime, viewer));
231: } else {
232: PetscCall(PetscRealView(0, &ptime, viewer));
233: }
234: }
235: PetscCall(PetscViewerPopFormat(viewer));
236: PetscFunctionReturn(PETSC_SUCCESS);
237: }
239: typedef struct {
240: PetscLogDouble time_start;
241: PetscLogDouble time_last;
242: PetscInt snes_its;
243: PetscInt ksp_its;
244: } *TSMonitorWallClockTimeContext;
246: /*@C
247: TSMonitorWallClockTimeSetUp - Setup routine passed to `TSMonitorSetFromOptions()` when using `-ts_monitor_wall_clock_time`
249: Input Parameters:
250: + ts - the `TS` context
251: - vf - the viewer and format
253: Level: intermediate
255: Note:
256: This is not called directly by users, rather one calls `TSMonitorSetFromOptions()`, with `TSMonitorWallClockTime()` and this function as arguments, to cause the monitor
257: to be used during the `TS` integration.
259: .seealso: [](ch_ts), `TSMonitorSet()`
260: @*/
261: PetscErrorCode TSMonitorWallClockTimeSetUp(TS ts, PetscViewerAndFormat *vf)
262: {
263: TSMonitorWallClockTimeContext speed;
265: PetscFunctionBegin;
266: PetscCall(PetscNew(&speed));
267: speed->time_start = PETSC_DECIDE;
268: vf->data_destroy = PetscCtxDestroyDefault;
269: vf->data = speed;
270: PetscFunctionReturn(PETSC_SUCCESS);
271: }
273: /*@C
274: TSMonitorWallClockTime - Monitor wall-clock time, KSP iterations, and SNES iterations per step.
276: Input Parameters:
277: + ts - the `TS` context
278: . step - iteration number (after the final time step the monitor routine may be called with a step of -1, this indicates the solution has been interpolated to this time)
279: . ptime - current time
280: . v - current solution
281: - vf - the viewer and format
283: Options Database Key:
284: . -ts_monitor_wall_clock_time - Monitor wall-clock time, KSP iterations, and SNES iterations per step.
286: Level: intermediate
288: Note:
289: This is not called directly by users, rather one calls `TSMonitorSetFromOptions()`, with this function and `TSMonitorWallClockTimeSetUp()` as arguments, to cause the monitor
290: to be used during the `TS` integration.
292: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `TSMonitorExtreme()`, `TSMonitorDrawSolution()`,
293: `TSMonitorDrawSolutionPhase()`, `TSMonitorDrawSolutionFunction()`, `TSMonitorDrawError()`, `TSMonitorSolution()`, `TSMonitorSolutionVTK()`,
294: `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorSPSwarmSolution()`, `TSMonitorError()`, `TSMonitorEnvelope()`, `TSDMSwarmMonitorMoments()`
295: @*/
296: PetscErrorCode TSMonitorWallClockTime(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
297: {
298: PetscViewer viewer = vf->viewer;
299: TSMonitorWallClockTimeContext speed = (TSMonitorWallClockTimeContext)vf->data;
300: PetscBool isascii;
301: PetscLogDouble now;
302: PetscInt snes_its, ksp_its;
304: PetscFunctionBegin;
306: PetscCall(PetscTime(&now));
307: if (speed->time_start == PETSC_DECIDE) {
308: speed->time_start = now;
309: speed->time_last = now;
310: }
311: PetscCall(TSGetSNESIterations(ts, &snes_its));
312: PetscCall(TSGetKSPIterations(ts, &ksp_its));
313: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
314: PetscCall(PetscViewerPushFormat(viewer, vf->format));
315: if (isascii) {
316: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
317: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s elapsed %.6f of %.6f snes %" PetscInt_FMT " ksp %" PetscInt_FMT "\n", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)" : "", now - speed->time_last,
318: now - speed->time_start, snes_its - speed->snes_its, ksp_its - speed->ksp_its));
319: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
320: }
321: PetscCall(PetscViewerPopFormat(viewer));
322: speed->time_last = now;
323: speed->snes_its = snes_its;
324: speed->ksp_its = ksp_its;
325: PetscFunctionReturn(PETSC_SUCCESS);
326: }
328: /*@C
329: TSMonitorExtreme - Prints the extreme values of the solution at each timestep
331: Input Parameters:
332: + ts - the `TS` context
333: . step - iteration number (after the final time step the monitor routine may be called with a step of -1, this indicates the solution has been interpolated to this time)
334: . ptime - current time
335: . v - current iterate
336: - vf - the viewer and format
338: Level: intermediate
340: Note:
341: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
342: to be used during the `TS` integration.
344: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`
345: @*/
346: PetscErrorCode TSMonitorExtreme(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscViewerAndFormat *vf)
347: {
348: PetscViewer viewer = vf->viewer;
349: PetscBool isascii;
350: PetscReal max, min;
352: PetscFunctionBegin;
354: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
355: PetscCall(PetscViewerPushFormat(viewer, vf->format));
356: if (isascii) {
357: PetscCall(VecMax(v, NULL, &max));
358: PetscCall(VecMin(v, NULL, &min));
359: PetscCall(PetscViewerASCIIAddTab(viewer, ((PetscObject)ts)->tablevel));
360: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " TS dt %g time %g%s max %g min %g\n", step, (double)ts->time_step, (double)ptime, ts->steprollback ? " (r)" : "", (double)max, (double)min));
361: PetscCall(PetscViewerASCIISubtractTab(viewer, ((PetscObject)ts)->tablevel));
362: }
363: PetscCall(PetscViewerPopFormat(viewer));
364: PetscFunctionReturn(PETSC_SUCCESS);
365: }
367: /*@C
368: TSMonitorLGCtxCreate - Creates a `TSMonitorLGCtx` context for use with
369: `TS` to monitor the solution process graphically in various ways
371: Collective
373: Input Parameters:
374: + comm - the MPI communicator to use
375: . host - the X display to open, or `NULL` for the local machine
376: . label - the title to put in the title bar
377: . x - the x screen coordinates of the upper left coordinate of the window
378: . y - the y screen coordinates of the upper left coordinate of the window
379: . m - the screen width in pixels
380: . n - the screen height in pixels
381: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
383: Output Parameter:
384: . ctx - the context
386: Options Database Keys:
387: + -ts_monitor_lg_timestep - automatically sets line graph monitor
388: . -ts_monitor_lg_timestep_log - automatically sets line graph monitor
389: . -ts_monitor_lg_solution - monitor the solution (or certain values of the solution by calling `TSMonitorLGSetDisplayVariables()` or `TSMonitorLGCtxSetDisplayVariables()`)
390: . -ts_monitor_lg_error - monitor the error
391: . -ts_monitor_lg_ksp_iterations - monitor the number of `KSP` iterations needed for each timestep
392: . -ts_monitor_lg_snes_iterations - monitor the number of `SNES` iterations needed for each timestep
393: - -lg_use_markers (true|false) - mark the data points (at each time step) on the plot; default is true
395: Level: intermediate
397: Notes:
398: Pass the context and `TSMonitorLGCtxDestroy()` to `TSMonitorSet()` to have the context destroyed when no longer needed.
400: One can provide a function that transforms the solution before plotting it with `TSMonitorLGCtxSetTransform()` or `TSMonitorLGSetTransform()`
402: Many of the functions that control the monitoring have two forms\: TSMonitorLGSet/GetXXXX() and TSMonitorLGCtxSet/GetXXXX() the first take a `TS` object as the
403: first argument (if that `TS` object does not have a `TSMonitorLGCtx` associated with it the function call is ignored) and the second takes a `TSMonitorLGCtx` object
404: as the first argument.
406: One can control the names displayed for each solution or error variable with `TSMonitorLGCtxSetVariableNames()` or `TSMonitorLGSetVariableNames()`
408: .seealso: [](ch_ts), `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`, `TSMonitorDefault()`, `VecView()`,
409: `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
410: `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
411: `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
412: `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
413: @*/
414: PetscErrorCode TSMonitorLGCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorLGCtx *ctx)
415: {
416: PetscDraw draw;
418: PetscFunctionBegin;
419: PetscCall(PetscNew(ctx));
420: PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
421: PetscCall(PetscDrawSetFromOptions(draw));
422: PetscCall(PetscDrawLGCreate(draw, 1, &(*ctx)->lg));
423: PetscCall(PetscDrawLGSetFromOptions((*ctx)->lg));
424: PetscCall(PetscDrawDestroy(&draw));
425: (*ctx)->howoften = howoften;
426: PetscFunctionReturn(PETSC_SUCCESS);
427: }
429: /*@C
430: TSMonitorLGTimeStep - Monitors a `TS` by printing the time-steps
432: Collective
434: Input Parameters:
435: + ts - the time integrator
436: . step - the current time step
437: . ptime - the current time
438: . v - the current state
439: - monctx - the monitor context obtained with `TSMonitorLGCtxCreate()`
441: Level: advanced
443: Note:
444: This is not called directly by users, rather one calls `TSMonitorSet()` along the `ctx` created by `TSMonitorLGCtxCreate()`
445: and `TSMonitorLGCtxDestroy()`
447: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGCtxDestroy()`
448: @*/
449: PetscErrorCode TSMonitorLGTimeStep(TS ts, PetscInt step, PetscReal ptime, Vec v, PetscCtx monctx)
450: {
451: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
452: PetscReal x = ptime, y;
454: PetscFunctionBegin;
455: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates an interpolated solution */
456: if (!step) {
457: PetscDrawAxis axis;
458: const char *ylabel = ctx->semilogy ? "Log Time Step" : "Time Step";
459: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
460: PetscCall(PetscDrawAxisSetLabels(axis, "Timestep as function of time", "Time", ylabel));
461: PetscCall(PetscDrawLGReset(ctx->lg));
462: }
463: PetscCall(TSGetTimeStep(ts, &y));
464: if (ctx->semilogy) y = PetscLog10Real(y);
465: PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
466: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
467: PetscCall(PetscDrawLGDraw(ctx->lg));
468: PetscCall(PetscDrawLGSave(ctx->lg));
469: }
470: PetscFunctionReturn(PETSC_SUCCESS);
471: }
473: /*@C
474: TSMonitorLGCtxDestroy - Destroys a line graph context that was created with `TSMonitorLGCtxCreate()`.
476: Collective
478: Input Parameter:
479: . ctx - the monitor context
481: Level: intermediate
483: Note:
484: Pass to `TSMonitorSet()` along with the context and `TSMonitorLGTimeStep()`
486: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
487: @*/
488: PetscErrorCode TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
489: {
490: PetscFunctionBegin;
491: if ((*ctx)->transformdestroy) PetscCall(((*ctx)->transformdestroy)(&(*ctx)->transformctx));
492: PetscCall(PetscDrawLGDestroy(&(*ctx)->lg));
493: PetscCall(PetscStrArrayDestroy(&(*ctx)->names));
494: PetscCall(PetscStrArrayDestroy(&(*ctx)->displaynames));
495: PetscCall(PetscFree((*ctx)->displayvariables));
496: PetscCall(PetscFree((*ctx)->displayvalues));
497: PetscCall(PetscFree(*ctx));
498: PetscFunctionReturn(PETSC_SUCCESS);
499: }
501: /*@C
502: TSMonitorSPCtxCreate - Creates a `TSMonitorSPCtx` scatter-plot monitor context for use with `DMSWARM` particle visualizations
504: Collective
506: Input Parameters:
507: + comm - the MPI communicator to use
508: . host - the X display to open, or `NULL` for the local machine
509: . label - the title to put in the title bar
510: . x - the x screen coordinates of the upper left coordinate of the window
511: . y - the y screen coordinates of the upper left coordinate of the window
512: . m - the screen width in pixels
513: . n - the screen height in pixels
514: . howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
515: . retain - the number of old points to retain in the plot, or 0 to clear, or -1 to retain all
516: . phase - `PETSC_TRUE` to plot in phase space rather than coordinate space
517: - multispecies - `PETSC_TRUE` to color particles by species
519: Output Parameter:
520: . ctx - the newly created scatter plot monitor context
522: Level: intermediate
524: Note:
525: Pass this context and `TSMonitorSPCtxDestroy()` to `TSMonitorSet()` with `TSMonitorSPSwarmSolution()` to display particles during the integration.
527: .seealso: [](ch_ts), `TS`, `DMSWARM`, `TSMonitorSet()`, `TSMonitorSPSwarmSolution()`, `TSMonitorSPCtxDestroy()`
528: @*/
529: PetscErrorCode TSMonitorSPCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, PetscInt retain, PetscBool phase, PetscBool multispecies, TSMonitorSPCtx *ctx)
530: {
531: PetscDraw draw;
533: PetscFunctionBegin;
534: PetscCall(PetscNew(ctx));
535: PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
536: PetscCall(PetscDrawSetFromOptions(draw));
537: PetscCall(PetscDrawSPCreate(draw, 1, &(*ctx)->sp));
538: PetscCall(PetscDrawDestroy(&draw));
539: (*ctx)->howoften = howoften;
540: (*ctx)->retain = retain;
541: (*ctx)->phase = phase;
542: (*ctx)->multispecies = multispecies;
543: PetscFunctionReturn(PETSC_SUCCESS);
544: }
546: /*@C
547: TSMonitorSPCtxDestroy - Destroys a `TSMonitorSPCtx` that was created with `TSMonitorSPCtxCreate()`
549: Not Collective
551: Input Parameter:
552: . ctx - the scatter plot monitor context
554: Level: intermediate
556: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorSPCtxCreate()`, `TSMonitorSPSwarmSolution()`
557: @*/
558: PetscErrorCode TSMonitorSPCtxDestroy(TSMonitorSPCtx *ctx)
559: {
560: PetscFunctionBegin;
561: PetscCall(PetscDrawSPDestroy(&(*ctx)->sp));
562: PetscCall(PetscFree(*ctx));
563: PetscFunctionReturn(PETSC_SUCCESS);
564: }
566: /*@C
567: TSMonitorHGCtxCreate - Creates a `TSMonitorHGCtx` histogram monitor context for use with `DMSWARM` particle visualizations
569: Collective
571: Input Parameters:
572: + comm - the MPI communicator to use
573: . host - the X display to open, or `NULL` for the local machine
574: . label - the title to put in the title bar
575: . x - the x screen coordinates of the upper left coordinate of the window
576: . y - the y screen coordinates of the upper left coordinate of the window
577: . m - the screen width in pixels
578: . n - the screen height in pixels
579: . howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
580: . Ns - the number of species to histogram
581: . Nb - the number of histogram bins
582: - velocity - `PETSC_TRUE` to plot histograms in velocity space, `PETSC_FALSE` for coordinate space
584: Output Parameter:
585: . ctx - the newly created histogram monitor context
587: Level: intermediate
589: Note:
590: Pass this context and `TSMonitorHGCtxDestroy()` to `TSMonitorSet()` with `TSMonitorHGSwarmSolution()` to display particle histograms during integration.
592: .seealso: [](ch_ts), `TS`, `DMSWARM`, `TSMonitorSet()`, `TSMonitorHGSwarmSolution()`, `TSMonitorHGCtxDestroy()`
593: @*/
594: PetscErrorCode TSMonitorHGCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, PetscInt Ns, PetscInt Nb, PetscBool velocity, TSMonitorHGCtx *ctx)
595: {
596: PetscDraw draw;
597: int Nsi, Nbi;
599: PetscFunctionBegin;
600: PetscCall(PetscMPIIntCast(Ns, &Nsi));
601: PetscCall(PetscMPIIntCast(Nb, &Nbi));
602: PetscCall(PetscNew(ctx));
603: PetscCall(PetscMalloc1(Ns, &(*ctx)->hg));
604: for (int s = 0; s < Nsi; ++s) {
605: PetscCall(PetscDrawCreate(comm, host, label, x + s * m, y, m, n, &draw));
606: PetscCall(PetscDrawSetFromOptions(draw));
607: PetscCall(PetscDrawHGCreate(draw, Nbi, &(*ctx)->hg[s]));
608: PetscCall(PetscDrawHGCalcStats((*ctx)->hg[s], PETSC_TRUE));
609: PetscCall(PetscDrawDestroy(&draw));
610: }
611: (*ctx)->howoften = howoften;
612: (*ctx)->Ns = Ns;
613: (*ctx)->velocity = velocity;
614: PetscFunctionReturn(PETSC_SUCCESS);
615: }
617: /*@C
618: TSMonitorHGCtxDestroy - Destroys a `TSMonitorHGCtx` that was created with `TSMonitorHGCtxCreate()`
620: Not Collective
622: Input Parameter:
623: . ctx - the histogram monitor context
625: Level: intermediate
627: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorHGCtxCreate()`, `TSMonitorHGSwarmSolution()`
628: @*/
629: PetscErrorCode TSMonitorHGCtxDestroy(TSMonitorHGCtx *ctx)
630: {
631: PetscInt s;
633: PetscFunctionBegin;
634: for (s = 0; s < (*ctx)->Ns; ++s) PetscCall(PetscDrawHGDestroy(&(*ctx)->hg[s]));
635: PetscCall(PetscFree((*ctx)->hg));
636: PetscCall(PetscFree(*ctx));
637: PetscFunctionReturn(PETSC_SUCCESS);
638: }
640: /*@C
641: TSMonitorDrawSolution - Monitors progress of the `TS` solvers by calling
642: `VecView()` for the solution at each timestep
644: Collective
646: Input Parameters:
647: + ts - the `TS` context
648: . step - current time-step
649: . ptime - current time
650: . u - the solution at the current time
651: - ctx - either a viewer or `NULL`
653: Options Database Keys:
654: + -ts_monitor_draw_solution - draw the solution at each time-step
655: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution
657: Level: intermediate
659: Notes:
660: The initial solution and current solution are not displayed with a common axis scaling so generally the option `-ts_monitor_draw_solution_initial`
661: will look bad
663: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, as well as the context created with
664: `TSMonitorDrawCtxCreate()` and the function `TSMonitorDrawCtxDestroy()` to cause the monitor to be used during the `TS` integration.
666: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtxCreate()`, `TSMonitorDrawCtxDestroy()`
667: @*/
668: PetscErrorCode TSMonitorDrawSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx ctx)
669: {
670: TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)ctx;
671: PetscDraw draw;
673: PetscFunctionBegin;
674: if (!step && ictx->showinitial) {
675: if (!ictx->initialsolution) PetscCall(VecDuplicate(u, &ictx->initialsolution));
676: PetscCall(VecCopy(u, ictx->initialsolution));
677: }
678: if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
680: if (ictx->showinitial) {
681: PetscReal pause;
682: PetscCall(PetscViewerDrawGetPause(ictx->viewer, &pause));
683: PetscCall(PetscViewerDrawSetPause(ictx->viewer, 0.0));
684: PetscCall(VecView(ictx->initialsolution, ictx->viewer));
685: PetscCall(PetscViewerDrawSetPause(ictx->viewer, pause));
686: PetscCall(PetscViewerDrawSetHold(ictx->viewer, PETSC_TRUE));
687: }
688: PetscCall(VecView(u, ictx->viewer));
689: if (ictx->showtimestepandtime) {
690: PetscReal xl, yl, xr, yr, h;
691: char time[32];
693: PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
694: PetscCall(PetscSNPrintf(time, 32, "Timestep %" PetscInt_FMT " Time %g", step, (double)ptime));
695: PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
696: h = yl + .95 * (yr - yl);
697: PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
698: PetscCall(PetscDrawFlush(draw));
699: }
701: if (ictx->showinitial) PetscCall(PetscViewerDrawSetHold(ictx->viewer, PETSC_FALSE));
702: PetscFunctionReturn(PETSC_SUCCESS);
703: }
705: /*@C
706: TSMonitorDrawSolutionPhase - Monitors progress of the `TS` solvers by plotting the solution as a phase diagram
708: Collective
710: Input Parameters:
711: + ts - the `TS` context
712: . step - current time-step
713: . ptime - current time
714: . u - the solution at the current time
715: - ctx - either a viewer or `NULL`
717: Level: intermediate
719: Notes:
720: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
721: to be used during the `TS` integration.
723: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
724: @*/
725: PetscErrorCode TSMonitorDrawSolutionPhase(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx ctx)
726: {
727: TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)ctx;
728: PetscDraw draw;
729: PetscDrawAxis axis;
730: PetscInt n;
731: PetscMPIInt size;
732: PetscReal U0, U1, xl, yl, xr, yr, h;
733: char time[32];
734: const PetscScalar *U;
736: PetscFunctionBegin;
737: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)ts), &size));
738: PetscCheck(size == 1, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only allowed for sequential runs");
739: PetscCall(VecGetSize(u, &n));
740: PetscCheck(n == 2, PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Only for ODEs with two unknowns");
742: PetscCall(PetscViewerDrawGetDraw(ictx->viewer, 0, &draw));
743: PetscCall(PetscViewerDrawGetDrawAxis(ictx->viewer, 0, &axis));
744: PetscCall(PetscDrawAxisGetLimits(axis, &xl, &xr, &yl, &yr));
745: if (!step) {
746: PetscCall(PetscDrawClear(draw));
747: PetscCall(PetscDrawAxisDraw(axis));
748: }
750: PetscCall(VecGetArrayRead(u, &U));
751: U0 = PetscRealPart(U[0]);
752: U1 = PetscRealPart(U[1]);
753: PetscCall(VecRestoreArrayRead(u, &U));
754: if ((U0 < xl) || (U1 < yl) || (U0 > xr) || (U1 > yr)) PetscFunctionReturn(PETSC_SUCCESS);
756: PetscDrawCollectiveBegin(draw);
757: PetscCall(PetscDrawPoint(draw, U0, U1, PETSC_DRAW_BLACK));
758: if (ictx->showtimestepandtime) {
759: PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
760: PetscCall(PetscSNPrintf(time, 32, "Timestep %" PetscInt_FMT " Time %g", step, (double)ptime));
761: h = yl + .95 * (yr - yl);
762: PetscCall(PetscDrawStringCentered(draw, .5 * (xl + xr), h, PETSC_DRAW_BLACK, time));
763: }
764: PetscDrawCollectiveEnd(draw);
765: PetscCall(PetscDrawFlush(draw));
766: PetscCall(PetscDrawPause(draw));
767: PetscCall(PetscDrawSave(draw));
768: PetscFunctionReturn(PETSC_SUCCESS);
769: }
771: /*@C
772: TSMonitorDrawCtxDestroy - Destroys the monitor context for `TSMonitorDrawSolution()`
774: Collective
776: Input Parameter:
777: . ictx - the monitor context
779: Level: intermediate
781: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawSolution()`, `TSMonitorDrawError()`, `TSMonitorDrawCtx`
782: @*/
783: PetscErrorCode TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
784: {
785: PetscFunctionBegin;
786: PetscCall(PetscViewerDestroy(&(*ictx)->viewer));
787: PetscCall(VecDestroy(&(*ictx)->initialsolution));
788: PetscCall(PetscFree(*ictx));
789: PetscFunctionReturn(PETSC_SUCCESS);
790: }
792: /*@C
793: TSMonitorDrawCtxCreate - Creates the monitor context for `TSMonitorDrawCtx`
795: Collective
797: Input Parameters:
798: + comm - the MPI communicator to use
799: . host - the X display to open, or `NULL` for the local machine
800: . label - the title to put in the title bar
801: . x - the x screen coordinates of the upper left coordinate of the window
802: . y - the y screen coordinates of the upper left coordinate of the window
803: . m - the screen width in pixels
804: . n - the screen height in pixels
805: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
807: Output Parameter:
808: . ctx - the monitor context
810: Options Database Keys:
811: + -ts_monitor_draw_solution - draw the solution at each time-step
812: - -ts_monitor_draw_solution_initial - show initial solution as well as current solution
814: Level: intermediate
816: Note:
817: The context created by this function, `PetscMonitorDrawSolution()`, and `TSMonitorDrawCtxDestroy()` should be passed together to `TSMonitorSet()`.
819: .seealso: [](ch_ts), `TS`, `TSMonitorDrawCtxDestroy()`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorDrawCtx`, `PetscMonitorDrawSolution()`
820: @*/
821: PetscErrorCode TSMonitorDrawCtxCreate(MPI_Comm comm, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorDrawCtx *ctx)
822: {
823: PetscFunctionBegin;
824: PetscCall(PetscNew(ctx));
825: PetscCall(PetscViewerDrawOpen(comm, host, label, x, y, m, n, &(*ctx)->viewer));
826: PetscCall(PetscViewerSetFromOptions((*ctx)->viewer));
828: (*ctx)->howoften = howoften;
829: (*ctx)->showinitial = PETSC_FALSE;
830: PetscCall(PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_initial", &(*ctx)->showinitial, NULL));
832: (*ctx)->showtimestepandtime = PETSC_FALSE;
833: PetscCall(PetscOptionsGetBool(NULL, NULL, "-ts_monitor_draw_solution_show_time", &(*ctx)->showtimestepandtime, NULL));
834: PetscFunctionReturn(PETSC_SUCCESS);
835: }
837: /*@C
838: TSMonitorDrawSolutionFunction - Monitors progress of the `TS` solvers by calling
839: `VecView()` for the solution provided by `TSSetSolutionFunction()` at each timestep
841: Collective
843: Input Parameters:
844: + ts - the `TS` context
845: . step - current time-step
846: . ptime - current time
847: . u - solution at current time
848: - Ctx - either a viewer or `NULL`
850: Options Database Key:
851: . -ts_monitor_draw_solution_function - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`
853: Level: intermediate
855: Note:
856: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
857: to be used during the `TS` integration.
859: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
860: @*/
861: PetscErrorCode TSMonitorDrawSolutionFunction(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx Ctx)
862: {
863: TSMonitorDrawCtx ctx = (TSMonitorDrawCtx)Ctx;
864: PetscViewer viewer = ctx->viewer;
865: Vec work;
867: PetscFunctionBegin;
868: if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
869: PetscCall(VecDuplicate(u, &work));
870: PetscCall(TSComputeSolutionFunction(ts, ptime, work));
871: PetscCall(VecView(work, viewer));
872: PetscCall(VecDestroy(&work));
873: PetscFunctionReturn(PETSC_SUCCESS);
874: }
876: /*@C
877: TSMonitorDrawError - Monitors progress of the `TS` solvers by calling
878: `VecView()` for the error at each timestep
880: Collective
882: Input Parameters:
883: + ts - the `TS` context
884: . step - current time-step
885: . ptime - current time
886: . u - solution at current time
887: - Ctx - either a viewer or `NULL`
889: Options Database Key:
890: . -ts_monitor_draw_error - Monitor error graphically, requires user to have provided `TSSetSolutionFunction()`
892: Level: intermediate
894: Notes:
895: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
896: to be used during the `TS` integration.
898: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
899: @*/
900: PetscErrorCode TSMonitorDrawError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx Ctx)
901: {
902: TSMonitorDrawCtx ctx = (TSMonitorDrawCtx)Ctx;
903: PetscViewer viewer = ctx->viewer;
904: Vec work;
906: PetscFunctionBegin;
907: if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) PetscFunctionReturn(PETSC_SUCCESS);
908: PetscCall(VecDuplicate(u, &work));
909: PetscCall(TSComputeSolutionFunction(ts, ptime, work));
910: PetscCall(VecAXPY(work, -1.0, u));
911: PetscCall(VecView(work, viewer));
912: PetscCall(VecDestroy(&work));
913: PetscFunctionReturn(PETSC_SUCCESS);
914: }
916: /*@C
917: TSMonitorSolutionSetup - Setups the context for `TSMonitorSolution()`
919: Collective
921: Input Parameters:
922: + ts - the `TS` context
923: - vf - viewer and its format
925: Level: intermediate
927: .seealso: [](ch_ts), `TS`, `TSMonitorSolution()`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorSetFromOptions()`
928: @*/
929: PetscErrorCode TSMonitorSolutionSetup(TS ts, PetscViewerAndFormat *vf)
930: {
931: TSMonitorSolutionCtx ctx;
933: PetscFunctionBegin;
934: PetscCall(PetscNew(&ctx));
935: PetscCall(PetscOptionsGetBool(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_solution_skip_initial", &ctx->skip_initial, NULL));
936: vf->data = ctx;
937: vf->data_destroy = PetscCtxDestroyDefault;
938: PetscFunctionReturn(PETSC_SUCCESS);
939: }
941: /*@C
942: TSMonitorSolution - Monitors progress of the `TS` solvers by `VecView()` for the solution at each timestep. Normally the viewer is a binary file or a `PetscDraw` object
944: Collective
946: Input Parameters:
947: + ts - the `TS` context
948: . step - current time-step
949: . ptime - current time
950: . u - current state
951: - vf - viewer and its format
953: Level: intermediate
955: Notes:
956: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
957: to be used during the `TS` integration.
959: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorSolutionSetup()`
960: @*/
961: PetscErrorCode TSMonitorSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
962: {
963: TSMonitorSolutionCtx ctx = (TSMonitorSolutionCtx)vf->data;
965: PetscFunctionBegin;
966: if (ctx->skip_initial && step == ts->start_step) PetscFunctionReturn(PETSC_SUCCESS);
967: if ((vf->view_interval > 0 && !(step % vf->view_interval)) || (vf->view_interval && ts->reason)) {
968: PetscCall(PetscViewerPushFormat(vf->viewer, vf->format));
969: PetscCall(VecView(u, vf->viewer));
970: PetscCall(PetscViewerPopFormat(vf->viewer));
971: }
972: PetscFunctionReturn(PETSC_SUCCESS);
973: }
975: /*@C
976: TSMonitorSolutionVTK - Monitors progress of the `TS` solvers by `VecView()` for the solution at selected timesteps.
978: Collective
980: Input Parameters:
981: + ts - the `TS` context
982: . step - current time-step
983: . ptime - current time
984: . u - current state
985: - ctx - monitor context obtained with `TSMonitorSolutionVTKCtxCreate()`
987: Level: developer
989: Notes:
990: The VTK format does not allow writing multiple time steps in the same file, therefore a different file will be written for each time step.
991: These are named according to the file name template.
993: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
994: to be used during the `TS` integration.
996: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`
997: @*/
998: PetscErrorCode TSMonitorSolutionVTK(TS ts, PetscInt step, PetscReal ptime, Vec u, TSMonitorVTKCtx ctx)
999: {
1000: char filename[PETSC_MAX_PATH_LEN];
1001: PetscViewer viewer;
1003: PetscFunctionBegin;
1004: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1005: if (((ctx->interval > 0) && (!(step % ctx->interval))) || (ctx->interval && ts->reason)) {
1006: PetscCall(PetscSNPrintf(filename, sizeof(filename), (const char *)ctx->filenametemplate, step));
1007: PetscCall(PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts), filename, FILE_MODE_WRITE, &viewer));
1008: PetscCall(VecView(u, viewer));
1009: PetscCall(PetscViewerDestroy(&viewer));
1010: }
1011: PetscFunctionReturn(PETSC_SUCCESS);
1012: }
1014: /*@C
1015: TSMonitorSolutionVTKDestroy - Destroy the monitor context created with `TSMonitorSolutionVTKCtxCreate()`
1017: Not Collective
1019: Input Parameter:
1020: . ctx - the monitor context
1022: Level: developer
1024: Note:
1025: This function is normally passed to `TSMonitorSet()` along with `TSMonitorSolutionVTK()`.
1027: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorSolutionVTK()`
1028: @*/
1029: PetscErrorCode TSMonitorSolutionVTKDestroy(TSMonitorVTKCtx *ctx)
1030: {
1031: PetscFunctionBegin;
1032: if (!*ctx) PetscFunctionReturn(PETSC_SUCCESS);
1033: PetscCall(PetscFree((*ctx)->filenametemplate));
1034: PetscCall(PetscFree(*ctx));
1035: PetscFunctionReturn(PETSC_SUCCESS);
1036: }
1038: /*@C
1039: TSMonitorSolutionVTKCtxCreate - Create the monitor context to be used in `TSMonitorSolutionVTK()`
1041: Not collective
1043: Input Parameter:
1044: . filenametemplate - the template file name, e.g. foo-%03d.vts
1046: Output Parameter:
1047: . ctx - the monitor context
1049: Level: developer
1051: Note:
1052: This function is normally used inside `TSSetFromOptions()` to pass the context created to `TSMonitorSet()` along with `TSMonitorSolutionVTK()`.
1054: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorSolutionVTK()`, `TSMonitorSolutionVTKDestroy()`
1055: @*/
1056: PetscErrorCode TSMonitorSolutionVTKCtxCreate(const char *filenametemplate, TSMonitorVTKCtx *ctx)
1057: {
1058: const char *ptr = NULL, *ptr2 = NULL;
1059: TSMonitorVTKCtx ictx;
1061: PetscFunctionBegin;
1062: PetscAssertPointer(filenametemplate, 1);
1063: PetscAssertPointer(ctx, 2);
1064: /* Do some cursory validation of the input. */
1065: PetscCall(PetscStrstr(filenametemplate, "%", (char **)&ptr));
1066: PetscCheck(ptr, PETSC_COMM_SELF, PETSC_ERR_USER, "-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03" PetscInt_FMT ".vts");
1067: for (ptr++; ptr && *ptr; ptr++) {
1068: PetscCall(PetscStrchr("DdiouxX", *ptr, (char **)&ptr2));
1069: PetscCheck(ptr2 || (*ptr >= '0' && *ptr <= '9'), PETSC_COMM_SELF, PETSC_ERR_USER, "Invalid file template argument to -ts_monitor_solution_vtk, should look like filename-%%03" PetscInt_FMT ".vts");
1070: if (ptr2) break;
1071: }
1072: PetscCall(PetscNew(&ictx));
1073: PetscCall(PetscStrallocpy(filenametemplate, &ictx->filenametemplate));
1074: ictx->interval = 1;
1076: *ctx = ictx;
1077: PetscFunctionReturn(PETSC_SUCCESS);
1078: }
1080: /*@C
1081: TSMonitorLGSolution - Monitors progress of the `TS` solvers by plotting each component of the solution vector
1082: in a time based line graph
1084: Collective
1086: Input Parameters:
1087: + ts - the `TS` context
1088: . step - current time-step
1089: . ptime - current time
1090: . u - current solution
1091: - dctx - the `TSMonitorLGCtx` object that contains all the options for the monitoring, this is created with `TSMonitorLGCtxCreate()`
1093: Options Database Key:
1094: . -ts_monitor_lg_solution_variables - enable monitor of lg solution variables
1096: Level: intermediate
1098: Notes:
1099: Each process in a parallel run displays its component solutions in a separate window
1101: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1102: to be used during the `TS` integration.
1104: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGCtxSetVariableNames()`, `TSMonitorLGCtxGetVariableNames()`,
1105: `TSMonitorLGSetVariableNames()`, `TSMonitorLGGetVariableNames()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetDisplayVariables()`,
1106: `TSMonitorLGCtxSetTransform()`, `TSMonitorLGSetTransform()`, `TSMonitorLGError()`, `TSMonitorLGSNESIterations()`, `TSMonitorLGKSPIterations()`,
1107: `TSMonitorEnvelopeCtxCreate()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxDestroy()`, `TSMonitorEnvelop()`
1108: @*/
1109: PetscErrorCode TSMonitorLGSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
1110: {
1111: TSMonitorLGCtx ctx = (TSMonitorLGCtx)dctx;
1112: const PetscScalar *yy;
1113: Vec v;
1115: PetscFunctionBegin;
1116: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1117: if (!step) {
1118: PetscDrawAxis axis;
1119: PetscInt dim;
1120: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1121: PetscCall(PetscDrawAxisSetLabels(axis, "Solution as function of time", "Time", "Solution"));
1122: if (!ctx->names) {
1123: PetscBool flg;
1124: /* user provides names of variables to plot but no names has been set so assume names are integer values */
1125: PetscCall(PetscOptionsHasName(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", &flg));
1126: if (flg) {
1127: PetscInt i, n;
1128: char **names;
1129: PetscCall(VecGetSize(u, &n));
1130: PetscCall(PetscMalloc1(n + 1, &names));
1131: for (i = 0; i < n; i++) {
1132: PetscCall(PetscMalloc1(5, &names[i]));
1133: PetscCall(PetscSNPrintf(names[i], 5, "%" PetscInt_FMT, i));
1134: }
1135: names[n] = NULL;
1136: ctx->names = names;
1137: }
1138: }
1139: if (ctx->names && !ctx->displaynames) {
1140: char **displaynames;
1141: PetscBool flg;
1142: PetscCall(VecGetLocalSize(u, &dim));
1143: PetscCall(PetscCalloc1(dim + 1, &displaynames));
1144: PetscCall(PetscOptionsGetStringArray(((PetscObject)ts)->options, ((PetscObject)ts)->prefix, "-ts_monitor_lg_solution_variables", displaynames, &dim, &flg));
1145: if (flg) PetscCall(TSMonitorLGCtxSetDisplayVariables(ctx, (const char *const *)displaynames));
1146: PetscCall(PetscStrArrayDestroy(&displaynames));
1147: }
1148: if (ctx->displaynames) {
1149: PetscCall(PetscDrawLGSetDimension(ctx->lg, ctx->ndisplayvariables));
1150: PetscCall(PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->displaynames));
1151: } else if (ctx->names) {
1152: PetscCall(VecGetLocalSize(u, &dim));
1153: PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
1154: PetscCall(PetscDrawLGSetLegend(ctx->lg, (const char *const *)ctx->names));
1155: } else {
1156: PetscCall(VecGetLocalSize(u, &dim));
1157: PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
1158: }
1159: PetscCall(PetscDrawLGReset(ctx->lg));
1160: }
1162: if (!ctx->transform) v = u;
1163: else PetscCall((*ctx->transform)(ctx->transformctx, u, &v));
1164: PetscCall(VecGetArrayRead(v, &yy));
1165: if (ctx->displaynames) {
1166: PetscInt i;
1167: for (i = 0; i < ctx->ndisplayvariables; i++) ctx->displayvalues[i] = PetscRealPart(yy[ctx->displayvariables[i]]);
1168: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, ctx->displayvalues));
1169: } else {
1170: #if defined(PETSC_USE_COMPLEX)
1171: PetscInt i, n;
1172: PetscReal *yreal;
1173: PetscCall(VecGetLocalSize(v, &n));
1174: PetscCall(PetscMalloc1(n, &yreal));
1175: for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
1176: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal));
1177: PetscCall(PetscFree(yreal));
1178: #else
1179: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy));
1180: #endif
1181: }
1182: PetscCall(VecRestoreArrayRead(v, &yy));
1183: if (ctx->transform) PetscCall(VecDestroy(&v));
1185: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1186: PetscCall(PetscDrawLGDraw(ctx->lg));
1187: PetscCall(PetscDrawLGSave(ctx->lg));
1188: }
1189: PetscFunctionReturn(PETSC_SUCCESS);
1190: }
1192: /*@C
1193: TSMonitorLGSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
1195: Collective
1197: Input Parameters:
1198: + ts - the `TS` context
1199: - names - the names of the components, final string must be `NULL`
1201: Level: intermediate
1203: Notes:
1204: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
1206: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGCtxSetVariableNames()`
1207: @*/
1208: PetscErrorCode TSMonitorLGSetVariableNames(TS ts, const char *const *names)
1209: {
1210: PetscInt i;
1212: PetscFunctionBegin;
1213: for (i = 0; i < ts->numbermonitors; i++) {
1214: if (ts->monitor[i] == TSMonitorLGSolution) {
1215: PetscCall(TSMonitorLGCtxSetVariableNames((TSMonitorLGCtx)ts->monitorcontext[i], names));
1216: break;
1217: }
1218: }
1219: PetscFunctionReturn(PETSC_SUCCESS);
1220: }
1222: /*@C
1223: TSMonitorLGCtxSetVariableNames - Sets the name of each component in the solution vector so that it may be displayed in the plot
1225: Collective
1227: Input Parameters:
1228: + ctx - the `TS` context
1229: - names - the names of the components, final string must be `NULL`
1231: Level: intermediate
1233: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`, `TSMonitorLGSetVariableNames()`
1234: @*/
1235: PetscErrorCode TSMonitorLGCtxSetVariableNames(TSMonitorLGCtx ctx, const char *const *names)
1236: {
1237: PetscFunctionBegin;
1238: PetscCall(PetscStrArrayDestroy(&ctx->names));
1239: PetscCall(PetscStrArrayallocpy(names, &ctx->names));
1240: PetscFunctionReturn(PETSC_SUCCESS);
1241: }
1243: /*@C
1244: TSMonitorLGGetVariableNames - Gets the name of each component in the solution vector so that it may be displayed in the plot
1246: Collective
1248: Input Parameter:
1249: . ts - the `TS` context
1251: Output Parameter:
1252: . names - the names of the components, final string must be `NULL`
1254: Level: intermediate
1256: Note:
1257: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
1259: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
1260: @*/
1261: PetscErrorCode TSMonitorLGGetVariableNames(TS ts, const char *const **names)
1262: {
1263: PetscInt i;
1265: PetscFunctionBegin;
1266: *names = NULL;
1267: for (i = 0; i < ts->numbermonitors; i++) {
1268: if (ts->monitor[i] == TSMonitorLGSolution) {
1269: TSMonitorLGCtx ctx = (TSMonitorLGCtx)ts->monitorcontext[i];
1270: *names = (const char *const *)ctx->names;
1271: break;
1272: }
1273: }
1274: PetscFunctionReturn(PETSC_SUCCESS);
1275: }
1277: /*@C
1278: TSMonitorLGCtxSetDisplayVariables - Sets the variables that are to be display in the monitor
1280: Collective
1282: Input Parameters:
1283: + ctx - the `TSMonitorLG` context
1284: - displaynames - the names of the components, final string must be `NULL`
1286: Level: intermediate
1288: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
1289: @*/
1290: PetscErrorCode TSMonitorLGCtxSetDisplayVariables(TSMonitorLGCtx ctx, const char *const *displaynames)
1291: {
1292: PetscInt j = 0, k;
1294: PetscFunctionBegin;
1295: if (!ctx->names) PetscFunctionReturn(PETSC_SUCCESS);
1296: PetscCall(PetscStrArrayDestroy(&ctx->displaynames));
1297: PetscCall(PetscStrArrayallocpy(displaynames, &ctx->displaynames));
1298: while (displaynames[j]) j++;
1299: ctx->ndisplayvariables = j;
1300: PetscCall(PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvariables));
1301: PetscCall(PetscMalloc1(ctx->ndisplayvariables, &ctx->displayvalues));
1302: j = 0;
1303: while (displaynames[j]) {
1304: k = 0;
1305: while (ctx->names[k]) {
1306: PetscBool flg;
1307: PetscCall(PetscStrcmp(displaynames[j], ctx->names[k], &flg));
1308: if (flg) {
1309: ctx->displayvariables[j] = k;
1310: break;
1311: }
1312: k++;
1313: }
1314: j++;
1315: }
1316: PetscFunctionReturn(PETSC_SUCCESS);
1317: }
1319: /*@C
1320: TSMonitorLGSetDisplayVariables - Sets the variables that are to be display in the monitor
1322: Collective
1324: Input Parameters:
1325: + ts - the `TS` context
1326: - displaynames - the names of the components, final string must be `NULL`
1328: Level: intermediate
1330: Note:
1331: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
1333: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`
1334: @*/
1335: PetscErrorCode TSMonitorLGSetDisplayVariables(TS ts, const char *const *displaynames)
1336: {
1337: PetscInt i;
1339: PetscFunctionBegin;
1340: for (i = 0; i < ts->numbermonitors; i++) {
1341: if (ts->monitor[i] == TSMonitorLGSolution) {
1342: PetscCall(TSMonitorLGCtxSetDisplayVariables((TSMonitorLGCtx)ts->monitorcontext[i], displaynames));
1343: break;
1344: }
1345: }
1346: PetscFunctionReturn(PETSC_SUCCESS);
1347: }
1349: /*@C
1350: TSMonitorLGSetTransform - Solution vector will be transformed by provided function before being displayed
1352: Collective
1354: Input Parameters:
1355: + ts - the `TS` context
1356: . transform - the transform function
1357: . destroy - function to destroy the optional context, see `PetscCtxDestroyFn` for its calling sequence
1358: - tctx - optional context used by transform function
1360: Calling sequence of `transform`:
1361: + tctx - context used by the transform function
1362: . u - the input solution vector
1363: - w - the output transformed vector
1365: Level: intermediate
1367: Note:
1368: If the `TS` object does not have a `TSMonitorLGCtx` associated with it then this function is ignored
1370: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorLGCtxSetTransform()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `PetscCtxDestroyFn`
1371: @*/
1372: PetscErrorCode TSMonitorLGSetTransform(TS ts, PetscErrorCode (*transform)(PetscCtx tctx, Vec u, Vec *w), PetscCtxDestroyFn *destroy, PetscCtx tctx)
1373: {
1374: PetscInt i;
1376: PetscFunctionBegin;
1377: for (i = 0; i < ts->numbermonitors; i++) {
1378: if (ts->monitor[i] == TSMonitorLGSolution) PetscCall(TSMonitorLGCtxSetTransform((TSMonitorLGCtx)ts->monitorcontext[i], transform, destroy, tctx));
1379: }
1380: PetscFunctionReturn(PETSC_SUCCESS);
1381: }
1383: /*@C
1384: TSMonitorLGCtxSetTransform - Solution vector will be transformed by provided function before being displayed
1386: Collective
1388: Input Parameters:
1389: + tctx - the `TS` context
1390: . transform - the transform function
1391: . destroy - function to destroy the optional context, see `PetscCtxDestroyFn` for its calling sequence
1392: - ctx - optional context used by transform function
1394: Calling sequence of `transform`:
1395: + tctx - context used by the transform function
1396: . u - the input solution vector
1397: - w - the output transformed vector
1399: Level: intermediate
1401: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetVariableNames()`, `TSMonitorLGSetTransform()`, `PetscCtxDestroyFn`
1402: @*/
1403: PetscErrorCode TSMonitorLGCtxSetTransform(TSMonitorLGCtx ctx, PetscErrorCode (*transform)(PetscCtx tctx, Vec u, Vec *w), PetscCtxDestroyFn *destroy, PetscCtx tctx)
1404: {
1405: PetscFunctionBegin;
1406: ctx->transform = transform;
1407: ctx->transformdestroy = destroy;
1408: ctx->transformctx = tctx;
1409: PetscFunctionReturn(PETSC_SUCCESS);
1410: }
1412: /*@C
1413: TSMonitorLGError - Monitors progress of the `TS` solvers by plotting each component of the error
1414: in a time based line graph
1416: Collective
1418: Input Parameters:
1419: + ts - the `TS` context
1420: . step - current time-step
1421: . ptime - current time
1422: . u - current solution
1423: - Ctx - `TSMonitorLGCtx` object created with `TSMonitorLGCtxCreate()`
1425: Options Database Key:
1426: . -ts_monitor_lg_error - create a graphical monitor of error history
1428: Level: intermediate
1430: Notes:
1431: Each process in a parallel run displays its component errors in a separate window
1433: The user must provide the solution using `TSSetSolutionFunction()` to use this monitor.
1435: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1436: to be used during the TS integration.
1438: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1439: @*/
1440: PetscErrorCode TSMonitorLGError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx Ctx)
1441: {
1442: TSMonitorLGCtx ctx = (TSMonitorLGCtx)Ctx;
1443: const PetscScalar *yy;
1444: Vec y;
1446: PetscFunctionBegin;
1447: if (!step) {
1448: PetscDrawAxis axis;
1449: PetscInt dim;
1450: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1451: PetscCall(PetscDrawAxisSetLabels(axis, "Error in solution as function of time", "Time", "Error"));
1452: PetscCall(VecGetLocalSize(u, &dim));
1453: PetscCall(PetscDrawLGSetDimension(ctx->lg, dim));
1454: PetscCall(PetscDrawLGReset(ctx->lg));
1455: }
1456: PetscCall(VecDuplicate(u, &y));
1457: PetscCall(TSComputeSolutionFunction(ts, ptime, y));
1458: PetscCall(VecAXPY(y, -1.0, u));
1459: PetscCall(VecGetArrayRead(y, &yy));
1460: #if defined(PETSC_USE_COMPLEX)
1461: {
1462: PetscReal *yreal;
1463: PetscInt i, n;
1464: PetscCall(VecGetLocalSize(y, &n));
1465: PetscCall(PetscMalloc1(n, &yreal));
1466: for (i = 0; i < n; i++) yreal[i] = PetscRealPart(yy[i]);
1467: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yreal));
1468: PetscCall(PetscFree(yreal));
1469: }
1470: #else
1471: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg, ptime, yy));
1472: #endif
1473: PetscCall(VecRestoreArrayRead(y, &yy));
1474: PetscCall(VecDestroy(&y));
1475: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1476: PetscCall(PetscDrawLGDraw(ctx->lg));
1477: PetscCall(PetscDrawLGSave(ctx->lg));
1478: }
1479: PetscFunctionReturn(PETSC_SUCCESS);
1480: }
1482: /*@C
1483: TSMonitorSPSwarmSolution - Graphically displays phase plots of `DMSWARM` particles on a scatter plot
1485: Input Parameters:
1486: + ts - the `TS` context
1487: . step - current time-step
1488: . ptime - current time
1489: . u - current solution
1490: - dctx - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorSPCtxCreate()`
1492: Options Database Keys:
1493: + -ts_monitor_sp_swarm n - Monitor the solution every n steps, or -1 for plotting only the final solution
1494: . -ts_monitor_sp_swarm_retain n - Retain n old points so we can see the history, or -1 for all points
1495: . -ts_monitor_sp_swarm_multi_species (true|false) - Color each species differently
1496: - -ts_monitor_sp_swarm_phase (true|false) - Plot in phase space, as opposed to coordinate space
1498: Level: intermediate
1500: Notes:
1501: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1502: to be used during the `TS` integration.
1504: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `DMSWARM`, `TSMonitorSPCtxCreate()`
1505: @*/
1506: PetscErrorCode TSMonitorSPSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx dctx)
1507: {
1508: TSMonitorSPCtx ctx = (TSMonitorSPCtx)dctx;
1509: PetscDraw draw;
1510: DM dm, cdm;
1511: const PetscScalar *yy;
1512: PetscInt Np, p, dim = 2, *species;
1513: PetscReal species_color;
1515: PetscFunctionBegin;
1516: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1517: PetscCall(TSGetDM(ts, &dm));
1518: if (!step) {
1519: PetscDrawAxis axis;
1520: PetscReal dmboxlower[2], dmboxupper[2];
1522: PetscCall(TSGetDM(ts, &dm));
1523: PetscCall(DMGetDimension(dm, &dim));
1524: PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Monitor only supports two dimensional fields");
1525: PetscCall(DMSwarmGetCellDM(dm, &cdm));
1526: PetscCall(DMGetBoundingBox(cdm, dmboxlower, dmboxupper));
1527: PetscCall(VecGetLocalSize(u, &Np));
1528: Np /= dim * 2;
1529: PetscCall(PetscDrawSPGetAxis(ctx->sp, &axis));
1530: if (ctx->phase) {
1531: PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "X", "V"));
1532: PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], -10, 10));
1533: } else {
1534: PetscCall(PetscDrawAxisSetLabels(axis, "Particles", "X", "Y"));
1535: PetscCall(PetscDrawAxisSetLimits(axis, dmboxlower[0], dmboxupper[0], dmboxlower[1], dmboxupper[1]));
1536: }
1537: PetscCall(PetscDrawAxisSetHoldLimits(axis, PETSC_TRUE));
1538: PetscCall(PetscDrawSPReset(ctx->sp));
1539: }
1540: if (ctx->multispecies) PetscCall(DMSwarmGetField(dm, "species", NULL, NULL, (void **)&species));
1541: PetscCall(VecGetLocalSize(u, &Np));
1542: Np /= dim * 2;
1543: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1544: PetscCall(PetscDrawSPGetDraw(ctx->sp, &draw));
1545: if ((ctx->retain == 0) || (ctx->retain > 0 && !(step % ctx->retain))) PetscCall(PetscDrawClear(draw));
1546: PetscCall(PetscDrawFlush(draw));
1547: PetscCall(PetscDrawSPReset(ctx->sp));
1548: PetscCall(VecGetArrayRead(u, &yy));
1549: for (p = 0; p < Np; ++p) {
1550: PetscReal x, y;
1552: if (ctx->phase) {
1553: x = PetscRealPart(yy[p * dim * 2]);
1554: y = PetscRealPart(yy[p * dim * 2 + dim]);
1555: } else {
1556: x = PetscRealPart(yy[p * dim * 2]);
1557: y = PetscRealPart(yy[p * dim * 2 + 1]);
1558: }
1559: if (ctx->multispecies) {
1560: species_color = species[p] + 2;
1561: PetscCall(PetscDrawSPAddPointColorized(ctx->sp, &x, &y, &species_color));
1562: } else {
1563: PetscCall(PetscDrawSPAddPoint(ctx->sp, &x, &y));
1564: }
1565: PetscCall(PetscDrawSPAddPoint(ctx->sp, &x, &y));
1566: }
1567: PetscCall(VecRestoreArrayRead(u, &yy));
1568: PetscCall(PetscDrawSPDraw(ctx->sp, PETSC_FALSE));
1569: PetscCall(PetscDrawSPSave(ctx->sp));
1570: if (ctx->multispecies) PetscCall(DMSwarmRestoreField(dm, "species", NULL, NULL, (void **)&species));
1571: }
1572: PetscFunctionReturn(PETSC_SUCCESS);
1573: }
1575: /*@C
1576: TSMonitorHGSwarmSolution - Graphically displays histograms of `DMSWARM` particles
1578: Input Parameters:
1579: + ts - the `TS` context
1580: . step - current time-step
1581: . ptime - current time
1582: . u - current solution
1583: - dctx - the `TSMonitorSPCtx` object that contains all the options for the monitoring, this is created with `TSMonitorHGCtxCreate()`
1585: Options Database Keys:
1586: + -ts_monitor_hg_swarm n - Monitor the solution every n steps, or -1 for plotting only the final solution
1587: . -ts_monitor_hg_swarm_species num - Number of species to histogram
1588: . -ts_monitor_hg_swarm_bins num - Number of histogram bins
1589: - -ts_monitor_hg_swarm_velocity (true|false) - Plot in velocity space, as opposed to coordinate space
1591: Level: intermediate
1593: Note:
1594: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1595: to be used during the `TS` integration.
1597: .seealso: `TSMonitorSet()`
1598: @*/
1599: PetscErrorCode TSMonitorHGSwarmSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx dctx)
1600: {
1601: TSMonitorHGCtx ctx = (TSMonitorHGCtx)dctx;
1602: PetscDraw draw;
1603: DM sw;
1604: const PetscScalar *yy;
1605: PetscInt *species;
1606: PetscInt dim, d = 0, Np, p, Ns, s;
1608: PetscFunctionBegin;
1609: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1610: PetscCall(TSGetDM(ts, &sw));
1611: PetscCall(DMGetDimension(sw, &dim));
1612: PetscCall(DMSwarmGetNumSpecies(sw, &Ns));
1613: Ns = PetscMin(Ns, ctx->Ns);
1614: PetscCall(VecGetLocalSize(u, &Np));
1615: Np /= dim * 2;
1616: if (!step) {
1617: PetscDrawAxis axis;
1618: char title[PETSC_MAX_PATH_LEN];
1620: for (s = 0; s < Ns; ++s) {
1621: PetscCall(PetscDrawHGGetAxis(ctx->hg[s], &axis));
1622: PetscCall(PetscSNPrintf(title, PETSC_MAX_PATH_LEN, "Species %" PetscInt_FMT, s));
1623: if (ctx->velocity) PetscCall(PetscDrawAxisSetLabels(axis, title, "V", "N"));
1624: else PetscCall(PetscDrawAxisSetLabels(axis, title, "X", "N"));
1625: }
1626: }
1627: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
1628: PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species));
1629: for (s = 0; s < Ns; ++s) {
1630: PetscCall(PetscDrawHGReset(ctx->hg[s]));
1631: PetscCall(PetscDrawHGGetDraw(ctx->hg[s], &draw));
1632: PetscCall(PetscDrawClear(draw));
1633: PetscCall(PetscDrawFlush(draw));
1634: }
1635: PetscCall(VecGetArrayRead(u, &yy));
1636: for (p = 0; p < Np; ++p) {
1637: const PetscInt s = species[p] < Ns ? species[p] : 0;
1638: PetscReal v;
1640: if (ctx->velocity) v = PetscRealPart(yy[p * dim * 2 + d + dim]);
1641: else v = PetscRealPart(yy[p * dim * 2 + d]);
1642: PetscCall(PetscDrawHGAddValue(ctx->hg[s], v));
1643: }
1644: PetscCall(VecRestoreArrayRead(u, &yy));
1645: for (s = 0; s < Ns; ++s) {
1646: PetscCall(PetscDrawHGDraw(ctx->hg[s]));
1647: PetscCall(PetscDrawHGSave(ctx->hg[s]));
1648: }
1649: PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species));
1650: }
1651: PetscFunctionReturn(PETSC_SUCCESS);
1652: }
1654: /*@C
1655: TSMonitorError - Monitors progress of the `TS` solvers by printing the 2 norm of the error at each timestep
1657: Collective
1659: Input Parameters:
1660: + ts - the `TS` context
1661: . step - current time-step
1662: . ptime - current time
1663: . u - current solution
1664: - vf - unused context
1666: Options Database Key:
1667: . -ts_monitor_error - create a graphical monitor of error history
1669: Level: intermediate
1671: Notes:
1672: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1673: to be used during the `TS` integration.
1675: The user must provide the solution using `TSSetSolutionFunction()` to use this monitor.
1677: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSSetSolutionFunction()`
1678: @*/
1679: PetscErrorCode TSMonitorError(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscViewerAndFormat *vf)
1680: {
1681: DM dm;
1682: PetscDS ds = NULL;
1683: PetscInt Nf = -1, f;
1684: PetscBool flg;
1686: PetscFunctionBegin;
1687: PetscCall(TSGetDM(ts, &dm));
1688: if (dm) PetscCall(DMGetDS(dm, &ds));
1689: if (ds) PetscCall(PetscDSGetNumFields(ds, &Nf));
1690: if (Nf <= 0) {
1691: Vec y;
1692: PetscReal nrm;
1694: PetscCall(VecDuplicate(u, &y));
1695: PetscCall(TSComputeSolutionFunction(ts, ptime, y));
1696: PetscCall(VecAXPY(y, -1.0, u));
1697: PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERASCII, &flg));
1698: if (flg) {
1699: PetscCall(VecNorm(y, NORM_2, &nrm));
1700: PetscCall(PetscViewerASCIIPrintf(vf->viewer, "2-norm of error %g\n", (double)nrm));
1701: }
1702: PetscCall(PetscObjectTypeCompare((PetscObject)vf->viewer, PETSCVIEWERDRAW, &flg));
1703: if (flg) PetscCall(VecView(y, vf->viewer));
1704: PetscCall(VecDestroy(&y));
1705: } else {
1706: PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, PetscCtx ctx);
1707: void **ctxs;
1708: Vec v;
1709: PetscReal ferrors[1];
1711: PetscCall(PetscMalloc2(Nf, &exactFuncs, Nf, &ctxs));
1712: for (f = 0; f < Nf; ++f) PetscCall(PetscDSGetExactSolution(ds, f, &exactFuncs[f], &ctxs[f]));
1713: PetscCall(DMComputeL2FieldDiff(dm, ptime, exactFuncs, ctxs, u, ferrors));
1714: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Timestep: %04" PetscInt_FMT " time = %-8.4g \t L_2 Error: [", step, (double)ptime));
1715: for (f = 0; f < Nf; ++f) {
1716: if (f > 0) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ", "));
1717: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%2.3g", (double)ferrors[f]));
1718: }
1719: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "]\n"));
1721: PetscCall(VecViewFromOptions(u, NULL, "-sol_vec_view"));
1723: PetscCall(PetscOptionsHasName(NULL, NULL, "-exact_vec_view", &flg));
1724: if (flg) {
1725: PetscCall(DMGetGlobalVector(dm, &v));
1726: PetscCall(DMProjectFunction(dm, ptime, exactFuncs, ctxs, INSERT_ALL_VALUES, v));
1727: PetscCall(PetscObjectSetName((PetscObject)v, "Exact Solution"));
1728: PetscCall(VecViewFromOptions(v, NULL, "-exact_vec_view"));
1729: PetscCall(DMRestoreGlobalVector(dm, &v));
1730: }
1731: PetscCall(PetscFree2(exactFuncs, ctxs));
1732: }
1733: PetscFunctionReturn(PETSC_SUCCESS);
1734: }
1736: /*@C
1737: TSMonitorLGSNESIterations - Monitors the number of nonlinear (`SNES`) iterations used per time step in a line-graph plot
1739: Collective
1741: Input Parameters:
1742: + ts - the `TS` context
1743: . n - iteration number (a negative value indicates an interpolated solution and is ignored)
1744: . ptime - current time
1745: . v - current solution
1746: - monctx - the `TSMonitorLGCtx` object that contains all the options for the monitoring, created with `TSMonitorLGCtxCreate()`
1748: Level: intermediate
1750: Note:
1751: This is not called directly by users; pass this function to `TSMonitorSet()` along with the context created by `TSMonitorLGCtxCreate()` and `TSMonitorLGCtxDestroy()`.
1753: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGKSPIterations()`
1754: @*/
1755: PetscErrorCode TSMonitorLGSNESIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, PetscCtx monctx)
1756: {
1757: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1758: PetscReal x = ptime, y;
1759: PetscInt its;
1761: PetscFunctionBegin;
1762: if (n < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1763: if (!n) {
1764: PetscDrawAxis axis;
1765: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1766: PetscCall(PetscDrawAxisSetLabels(axis, "Nonlinear iterations as function of time", "Time", "SNES Iterations"));
1767: PetscCall(PetscDrawLGReset(ctx->lg));
1768: ctx->snes_its = 0;
1769: }
1770: PetscCall(TSGetSNESIterations(ts, &its));
1771: y = its - ctx->snes_its;
1772: PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
1773: if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1774: PetscCall(PetscDrawLGDraw(ctx->lg));
1775: PetscCall(PetscDrawLGSave(ctx->lg));
1776: }
1777: ctx->snes_its = its;
1778: PetscFunctionReturn(PETSC_SUCCESS);
1779: }
1781: /*@C
1782: TSMonitorLGKSPIterations - Monitors the number of linear (`KSP`) iterations used per time step in a line-graph plot
1784: Collective
1786: Input Parameters:
1787: + ts - the `TS` context
1788: . n - iteration number (a negative value indicates an interpolated solution and is ignored)
1789: . ptime - current time
1790: . v - current solution
1791: - monctx - the `TSMonitorLGCtx` object that contains all the options for the monitoring, created with `TSMonitorLGCtxCreate()`
1793: Level: intermediate
1795: Note:
1796: This is not called directly by users; pass this function to `TSMonitorSet()` along with the context created by `TSMonitorLGCtxCreate()` and `TSMonitorLGCtxDestroy()`.
1798: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorLGCtxCreate()`, `TSMonitorLGSNESIterations()`
1799: @*/
1800: PetscErrorCode TSMonitorLGKSPIterations(TS ts, PetscInt n, PetscReal ptime, Vec v, PetscCtx monctx)
1801: {
1802: TSMonitorLGCtx ctx = (TSMonitorLGCtx)monctx;
1803: PetscReal x = ptime, y;
1804: PetscInt its;
1806: PetscFunctionBegin;
1807: if (n < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
1808: if (!n) {
1809: PetscDrawAxis axis;
1810: PetscCall(PetscDrawLGGetAxis(ctx->lg, &axis));
1811: PetscCall(PetscDrawAxisSetLabels(axis, "Linear iterations as function of time", "Time", "KSP Iterations"));
1812: PetscCall(PetscDrawLGReset(ctx->lg));
1813: ctx->ksp_its = 0;
1814: }
1815: PetscCall(TSGetKSPIterations(ts, &its));
1816: y = its - ctx->ksp_its;
1817: PetscCall(PetscDrawLGAddPoint(ctx->lg, &x, &y));
1818: if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
1819: PetscCall(PetscDrawLGDraw(ctx->lg));
1820: PetscCall(PetscDrawLGSave(ctx->lg));
1821: }
1822: ctx->ksp_its = its;
1823: PetscFunctionReturn(PETSC_SUCCESS);
1824: }
1826: /*@C
1827: TSMonitorEnvelopeCtxCreate - Creates a context for use with `TSMonitorEnvelope()`
1829: Collective
1831: Input Parameter:
1832: . ts - the `TS` solver object
1834: Output Parameter:
1835: . ctx - the context
1837: Level: intermediate
1839: .seealso: [](ch_ts), `TS`, `TSMonitorLGTimeStep()`, `TSMonitorSet()`, `TSMonitorLGSolution()`, `TSMonitorLGError()`
1840: @*/
1841: PetscErrorCode TSMonitorEnvelopeCtxCreate(TS ts, TSMonitorEnvelopeCtx *ctx)
1842: {
1843: PetscFunctionBegin;
1844: PetscCall(PetscNew(ctx));
1845: PetscFunctionReturn(PETSC_SUCCESS);
1846: }
1848: /*@C
1849: TSMonitorEnvelope - Monitors the maximum and minimum value of each component of the solution
1851: Collective
1853: Input Parameters:
1854: + ts - the `TS` context
1855: . step - current time-step
1856: . ptime - current time
1857: . u - current solution
1858: - dctx - the envelope context
1860: Options Database Key:
1861: . -ts_monitor_envelope - determine maximum and minimum value of each component of the solution over the solution time
1863: Level: intermediate
1865: Notes:
1866: After a solve you can use `TSMonitorEnvelopeGetBounds()` to access the envelope
1868: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1869: to be used during the `TS` integration.
1871: .seealso: [](ch_ts), `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorEnvelopeGetBounds()`, `TSMonitorEnvelopeCtxCreate()`
1872: @*/
1873: PetscErrorCode TSMonitorEnvelope(TS ts, PetscInt step, PetscReal ptime, Vec u, PetscCtx dctx)
1874: {
1875: TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)dctx;
1877: PetscFunctionBegin;
1878: if (!ctx->max) {
1879: PetscCall(VecDuplicate(u, &ctx->max));
1880: PetscCall(VecDuplicate(u, &ctx->min));
1881: PetscCall(VecCopy(u, ctx->max));
1882: PetscCall(VecCopy(u, ctx->min));
1883: } else {
1884: PetscCall(VecPointwiseMax(ctx->max, u, ctx->max));
1885: PetscCall(VecPointwiseMin(ctx->min, u, ctx->min));
1886: }
1887: PetscFunctionReturn(PETSC_SUCCESS);
1888: }
1890: /*@C
1891: TSMonitorEnvelopeGetBounds - Gets the bounds for the components of the solution
1893: Collective
1895: Input Parameter:
1896: . ts - the `TS` context
1898: Output Parameters:
1899: + max - the maximum values
1900: - min - the minimum values
1902: Level: intermediate
1904: Notes:
1905: If the `TS` does not have a `TSMonitorEnvelopeCtx` associated with it then this function is ignored
1907: .seealso: [](ch_ts), `TSMonitorEnvelopeCtx`, `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `VecView()`, `TSMonitorLGSetDisplayVariables()`
1908: @*/
1909: PetscErrorCode TSMonitorEnvelopeGetBounds(TS ts, Vec *max, Vec *min)
1910: {
1911: PetscInt i;
1913: PetscFunctionBegin;
1914: if (max) *max = NULL;
1915: if (min) *min = NULL;
1916: for (i = 0; i < ts->numbermonitors; i++) {
1917: if (ts->monitor[i] == TSMonitorEnvelope) {
1918: TSMonitorEnvelopeCtx ctx = (TSMonitorEnvelopeCtx)ts->monitorcontext[i];
1919: if (max) *max = ctx->max;
1920: if (min) *min = ctx->min;
1921: break;
1922: }
1923: }
1924: PetscFunctionReturn(PETSC_SUCCESS);
1925: }
1927: /*@C
1928: TSMonitorEnvelopeCtxDestroy - Destroys a context that was created with `TSMonitorEnvelopeCtxCreate()`.
1930: Collective
1932: Input Parameter:
1933: . ctx - the monitor context
1935: Level: intermediate
1937: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxCreate()`, `TSMonitorSet()`, `TSMonitorLGTimeStep()`
1938: @*/
1939: PetscErrorCode TSMonitorEnvelopeCtxDestroy(TSMonitorEnvelopeCtx *ctx)
1940: {
1941: PetscFunctionBegin;
1942: PetscCall(VecDestroy(&(*ctx)->min));
1943: PetscCall(VecDestroy(&(*ctx)->max));
1944: PetscCall(PetscFree(*ctx));
1945: PetscFunctionReturn(PETSC_SUCCESS);
1946: }
1948: /*@C
1949: TSDMSwarmMonitorMoments - Monitors the first three moments of a `DMSWARM` being evolved by the `TS`
1951: Not Collective
1953: Input Parameters:
1954: + ts - the `TS` context
1955: . step - current timestep
1956: . t - current time
1957: . U - current solution
1958: - vf - not used
1960: Options Database Key:
1961: + -ts_dmswarm_monitor_moments - Monitor moments of particle distribution
1962: - -ts_dmswarm_monitor_moments_interval - Interval of timesteps between monitor outputs
1964: Level: intermediate
1966: Notes:
1967: This requires a `DMSWARM` be attached to the `TS`.
1969: This is not called directly by users, rather one calls `TSMonitorSet()`, with this function as an argument, to cause the monitor
1970: to be used during the TS integration.
1972: .seealso: [](ch_ts), `TS`, `TSMonitorSet()`, `TSMonitorDefault()`, `DMSWARM`
1973: @*/
1974: PetscErrorCode TSDMSwarmMonitorMoments(TS ts, PetscInt step, PetscReal t, Vec U, PetscViewerAndFormat *vf)
1975: {
1976: DM sw;
1977: const PetscScalar *u;
1978: PetscReal m = 1.0, totE = 0., totMom[3] = {0., 0., 0.};
1979: PetscInt dim, d, Np, p;
1980: MPI_Comm comm;
1982: PetscFunctionBeginUser;
1983: (void)t;
1984: (void)vf;
1985: PetscCall(TSGetDM(ts, &sw));
1986: if (!sw || step % vf->view_interval != 0) PetscFunctionReturn(PETSC_SUCCESS);
1987: PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
1988: PetscCall(DMGetDimension(sw, &dim));
1989: PetscCall(VecGetLocalSize(U, &Np));
1990: Np /= dim;
1991: PetscCall(VecGetArrayRead(U, &u));
1992: for (p = 0; p < Np; ++p) {
1993: for (d = 0; d < dim; ++d) {
1994: totE += PetscRealPart(u[p * dim + d] * u[p * dim + d]);
1995: totMom[d] += PetscRealPart(u[p * dim + d]);
1996: }
1997: }
1998: PetscCall(VecRestoreArrayRead(U, &u));
1999: for (d = 0; d < dim; ++d) totMom[d] *= m;
2000: totE *= 0.5 * m;
2001: PetscCall(PetscPrintf(comm, "Step %4" PetscInt_FMT " Total Energy: %10.8lf", step, (double)totE));
2002: for (d = 0; d < dim; ++d) PetscCall(PetscPrintf(comm, " Total Momentum %c: %10.8lf", (char)('x' + d), (double)totMom[d]));
2003: PetscCall(PetscPrintf(comm, "\n"));
2004: PetscFunctionReturn(PETSC_SUCCESS);
2005: }