Actual source code: dmnetworkts.c
1: #include <petsc/private/dmnetworkimpl.h>
2: #include <petscts.h>
3: #include <petscdraw.h>
5: /*@C
6: TSMonitorLGCtxNetworkDestroy - Destroys line graph contexts that where created with `TSMonitorLGCtxNetworkCreate()`.
8: Collective
10: Input Parameter:
11: . ctx - the monitor context
13: Level: intermediate
15: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxNetworkSolution()`
16: @*/
17: PetscErrorCode TSMonitorLGCtxNetworkDestroy(TSMonitorLGCtxNetwork *ctx)
18: {
19: PetscInt i;
21: PetscFunctionBegin;
22: for (i = 0; i < (*ctx)->nlg; i++) PetscCall(PetscDrawLGDestroy(&(*ctx)->lg[i]));
23: PetscCall(PetscFree((*ctx)->lg));
24: PetscCall(PetscFree(*ctx));
25: PetscFunctionReturn(PETSC_SUCCESS);
26: }
28: /*@C
29: TSMonitorLGCtxNetworkCreate - Creates a `TSMonitorLGCtxNetwork` context with one line-graph window for each edge and each vertex of a `DMNETWORK`
31: Collective
33: Input Parameters:
34: + ts - the `TS` context whose `DM` is a `DMNETWORK`
35: . host - the X display to open, or `NULL` for the local machine
36: . label - the title to put in the title bar
37: . x - the x screen coordinates of the upper left coordinate of the window
38: . y - the y screen coordinates of the upper left coordinate of the window
39: . m - the screen width in pixels
40: . n - the screen height in pixels
41: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
43: Output Parameter:
44: . ctx - the newly created network line-graph monitor context
46: Level: intermediate
48: Note:
49: Pass this context and `TSMonitorLGCtxNetworkDestroy()` to `TSMonitorSet()` with `TSMonitorLGCtxNetworkSolution()` to display the solution on the network during integration.
51: .seealso: [](ch_ts), `TS`, `DMNETWORK`, `TSMonitorSet()`, `TSMonitorLGCtxNetworkSolution()`, `TSMonitorLGCtxNetworkDestroy()`
52: @*/
53: PetscErrorCode TSMonitorLGCtxNetworkCreate(TS ts, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorLGCtxNetwork *ctx)
54: {
55: PetscDraw draw;
56: MPI_Comm comm;
57: DM dm;
58: PetscInt i, Start, End, e, nvar;
60: PetscFunctionBegin;
61: PetscCall(TSGetDM(ts, &dm));
62: PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
63: PetscCall(PetscNew(ctx));
64: i = 0;
65: /* loop over edges counting number of line graphs needed */
66: PetscCall(DMNetworkGetEdgeRange(dm, &Start, &End));
67: for (e = Start; e < End; e++) {
68: PetscCall(DMNetworkGetComponent(dm, e, ALL_COMPONENTS, NULL, NULL, &nvar));
69: if (!nvar) continue;
70: i++;
71: }
72: /* loop over vertices */
73: PetscCall(DMNetworkGetVertexRange(dm, &Start, &End));
74: for (e = Start; e < End; e++) {
75: PetscCall(DMNetworkGetComponent(dm, e, ALL_COMPONENTS, NULL, NULL, &nvar));
76: if (!nvar) continue;
77: i++;
78: }
79: (*ctx)->nlg = i;
80: PetscCall(PetscMalloc1(i, &(*ctx)->lg));
82: i = 0;
83: /* loop over edges creating all needed line graphs*/
84: PetscCall(DMNetworkGetEdgeRange(dm, &Start, &End));
85: for (e = Start; e < End; e++) {
86: PetscCall(DMNetworkGetComponent(dm, e, ALL_COMPONENTS, NULL, NULL, &nvar));
87: if (!nvar) continue;
88: PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
89: PetscCall(PetscDrawSetFromOptions(draw));
90: PetscCall(PetscDrawLGCreate(draw, nvar, &(*ctx)->lg[i]));
91: PetscCall(PetscDrawLGSetFromOptions((*ctx)->lg[i]));
92: PetscCall(PetscDrawDestroy(&draw));
93: i++;
94: }
95: /* loop over vertices */
96: PetscCall(DMNetworkGetVertexRange(dm, &Start, &End));
97: for (e = Start; e < End; e++) {
98: PetscCall(DMNetworkGetComponent(dm, e, ALL_COMPONENTS, NULL, NULL, &nvar));
99: if (!nvar) continue;
100: PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
101: PetscCall(PetscDrawSetFromOptions(draw));
102: PetscCall(PetscDrawLGCreate(draw, nvar, &(*ctx)->lg[i]));
103: PetscCall(PetscDrawLGSetFromOptions((*ctx)->lg[i]));
104: PetscCall(PetscDrawDestroy(&draw));
105: i++;
106: }
107: PetscCall(PetscDrawDestroy(&draw));
108: (*ctx)->howoften = howoften;
109: PetscFunctionReturn(PETSC_SUCCESS);
110: }
112: /*@C
113: TSMonitorLGCtxNetworkSolution - Monitors progress of the `TS` solvers for a `DMNETWORK` solution with one window for each vertex and each edge
115: Collective
117: Input Parameters:
118: + ts - the `TS` context
119: . step - current time-step
120: . ptime - current time
121: . u - current solution
122: - dctx - the `TSMonitorLGCtxNetwork` object that contains all the options for the monitoring, this is created with `TSMonitorLGCtxCreateNetwork()`
124: Options Database Key:
125: . -ts_monitor_lg_solution_variables - monitor solution variables
127: Level: intermediate
129: Note:
130: Each process in a parallel run displays its component solutions in a separate graphics window
132: .seealso: [](ch_ts), `TS`, `TSMonitorLGCtxNetworkDestroy()`
133: @*/
134: PetscErrorCode TSMonitorLGCtxNetworkSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
135: {
136: #if defined(PETSC_USE_COMPLEX)
137: PetscFunctionBegin;
138: PetscFunctionReturn(PETSC_SUCCESS);
139: #else
140: TSMonitorLGCtxNetwork ctx = (TSMonitorLGCtxNetwork)dctx;
141: const PetscScalar *xv;
142: PetscScalar *yv;
143: PetscInt i, v, Start, End, offset, nvar, e;
144: TSConvergedReason reason;
145: DM dm;
146: Vec uv;
148: PetscFunctionBegin;
149: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
150: if (!step) {
151: PetscDrawAxis axis;
153: for (i = 0; i < ctx->nlg; i++) {
154: PetscCall(PetscDrawLGGetAxis(ctx->lg[i], &axis));
155: PetscCall(PetscDrawAxisSetLabels(axis, "Solution as function of time", "Time", "Solution"));
156: PetscCall(PetscDrawLGReset(ctx->lg[i]));
157: }
158: }
160: if (ctx->semilogy) {
161: PetscInt n, j;
163: PetscCall(VecDuplicate(u, &uv));
164: PetscCall(VecCopy(u, uv));
165: PetscCall(VecGetArray(uv, &yv));
166: PetscCall(VecGetLocalSize(uv, &n));
167: for (j = 0; j < n; j++) {
168: if (PetscRealPart(yv[j]) <= 0.0) yv[j] = -12;
169: else yv[j] = PetscLog10Real(PetscRealPart(yv[j]));
170: }
171: xv = yv;
172: } else {
173: PetscCall(VecGetArrayRead(u, &xv));
174: }
175: /* iterate over edges */
176: PetscCall(TSGetDM(ts, &dm));
177: i = 0;
178: PetscCall(DMNetworkGetEdgeRange(dm, &Start, &End));
179: for (e = Start; e < End; e++) {
180: PetscCall(DMNetworkGetComponent(dm, e, ALL_COMPONENTS, NULL, NULL, &nvar));
181: if (!nvar) continue;
183: PetscCall(DMNetworkGetLocalVecOffset(dm, e, ALL_COMPONENTS, &offset));
184: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg[i], ptime, xv + offset));
185: i++;
186: }
188: /* iterate over vertices */
189: PetscCall(DMNetworkGetVertexRange(dm, &Start, &End));
190: for (v = Start; v < End; v++) {
191: PetscCall(DMNetworkGetComponent(dm, v, ALL_COMPONENTS, NULL, NULL, &nvar));
192: if (!nvar) continue;
194: PetscCall(DMNetworkGetLocalVecOffset(dm, v, ALL_COMPONENTS, &offset));
195: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg[i], ptime, xv + offset));
196: i++;
197: }
198: if (ctx->semilogy) {
199: PetscCall(VecRestoreArray(uv, &yv));
200: PetscCall(VecDestroy(&uv));
201: } else {
202: PetscCall(VecRestoreArrayRead(u, &xv));
203: }
205: PetscCall(TSGetConvergedReason(ts, &reason));
206: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && reason)) {
207: for (i = 0; i < ctx->nlg; i++) {
208: PetscCall(PetscDrawLGDraw(ctx->lg[i]));
209: PetscCall(PetscDrawLGSave(ctx->lg[i]));
210: }
211: }
212: PetscFunctionReturn(PETSC_SUCCESS);
213: #endif
214: }