Actual source code: dmnetworkts.c
1: #include <petsc/private/dmnetworkimpl.h>
2: #include <petscts.h>
3: #include <petscdraw.h>
5: /*
6: TSMonitorLGCtxDestroy - Destroys line graph contexts that where created with TSMonitorLGCtxNetworkCreate().
8: Collective
10: Input Parameter:
11: . ctx - the monitor context
13: */
14: PetscErrorCode TSMonitorLGCtxNetworkDestroy(TSMonitorLGCtxNetwork *ctx)
15: {
16: PetscInt i;
18: PetscFunctionBegin;
19: for (i = 0; i < (*ctx)->nlg; i++) PetscCall(PetscDrawLGDestroy(&(*ctx)->lg[i]));
20: PetscCall(PetscFree((*ctx)->lg));
21: PetscCall(PetscFree(*ctx));
22: PetscFunctionReturn(PETSC_SUCCESS);
23: }
25: PetscErrorCode TSMonitorLGCtxNetworkCreate(TS ts, const char host[], const char label[], int x, int y, int m, int n, PetscInt howoften, TSMonitorLGCtxNetwork *ctx)
26: {
27: PetscDraw draw;
28: MPI_Comm comm;
29: DM dm;
30: PetscInt i, Start, End, e, nvar;
32: PetscFunctionBegin;
33: PetscCall(TSGetDM(ts, &dm));
34: PetscCall(PetscObjectGetComm((PetscObject)ts, &comm));
35: PetscCall(PetscNew(ctx));
36: i = 0;
37: /* loop over edges counting number of line graphs needed */
38: PetscCall(DMNetworkGetEdgeRange(dm, &Start, &End));
39: for (e = Start; e < End; e++) {
40: PetscCall(DMNetworkGetComponent(dm, e, ALL_COMPONENTS, NULL, NULL, &nvar));
41: if (!nvar) continue;
42: i++;
43: }
44: /* loop over vertices */
45: PetscCall(DMNetworkGetVertexRange(dm, &Start, &End));
46: for (e = Start; e < End; e++) {
47: PetscCall(DMNetworkGetComponent(dm, e, ALL_COMPONENTS, NULL, NULL, &nvar));
48: if (!nvar) continue;
49: i++;
50: }
51: (*ctx)->nlg = i;
52: PetscCall(PetscMalloc1(i, &(*ctx)->lg));
54: i = 0;
55: /* loop over edges creating all needed line graphs*/
56: PetscCall(DMNetworkGetEdgeRange(dm, &Start, &End));
57: for (e = Start; e < End; e++) {
58: PetscCall(DMNetworkGetComponent(dm, e, ALL_COMPONENTS, NULL, NULL, &nvar));
59: if (!nvar) continue;
60: PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
61: PetscCall(PetscDrawSetFromOptions(draw));
62: PetscCall(PetscDrawLGCreate(draw, nvar, &(*ctx)->lg[i]));
63: PetscCall(PetscDrawLGSetFromOptions((*ctx)->lg[i]));
64: PetscCall(PetscDrawDestroy(&draw));
65: i++;
66: }
67: /* loop over vertices */
68: PetscCall(DMNetworkGetVertexRange(dm, &Start, &End));
69: for (e = Start; e < End; e++) {
70: PetscCall(DMNetworkGetComponent(dm, e, ALL_COMPONENTS, NULL, NULL, &nvar));
71: if (!nvar) continue;
72: PetscCall(PetscDrawCreate(comm, host, label, x, y, m, n, &draw));
73: PetscCall(PetscDrawSetFromOptions(draw));
74: PetscCall(PetscDrawLGCreate(draw, nvar, &(*ctx)->lg[i]));
75: PetscCall(PetscDrawLGSetFromOptions((*ctx)->lg[i]));
76: PetscCall(PetscDrawDestroy(&draw));
77: i++;
78: }
79: PetscCall(PetscDrawDestroy(&draw));
80: (*ctx)->howoften = howoften;
81: PetscFunctionReturn(PETSC_SUCCESS);
82: }
84: /*
85: TSMonitorLGCtxNetworkSolution - Monitors progress of the `TS` solvers for a `DMNETWORK` solution with one window for each vertex and each edge
87: Collective
89: Input Parameters:
90: + ts - the `TS` context
91: . step - current time-step
92: . ptime - current time
93: . u - current solution
94: - dctx - the `TSMonitorLGCtxNetwork` object that contains all the options for the monitoring, this is created with `TSMonitorLGCtxCreateNetwork()`
96: Options Database Key:
97: . -ts_monitor_lg_solution_variables
99: Level: intermediate
101: Note:
102: Each process in a parallel run displays its component solutions in a separate window
104: */
105: PetscErrorCode TSMonitorLGCtxNetworkSolution(TS ts, PetscInt step, PetscReal ptime, Vec u, void *dctx)
106: {
107: TSMonitorLGCtxNetwork ctx = (TSMonitorLGCtxNetwork)dctx;
108: const PetscScalar *xv;
109: PetscScalar *yv;
110: PetscInt i, v, Start, End, offset, nvar, e;
111: TSConvergedReason reason;
112: DM dm;
113: Vec uv;
115: PetscFunctionBegin;
116: if (step < 0) PetscFunctionReturn(PETSC_SUCCESS); /* -1 indicates interpolated solution */
117: if (!step) {
118: PetscDrawAxis axis;
120: for (i = 0; i < ctx->nlg; i++) {
121: PetscCall(PetscDrawLGGetAxis(ctx->lg[i], &axis));
122: PetscCall(PetscDrawAxisSetLabels(axis, "Solution as function of time", "Time", "Solution"));
123: PetscCall(PetscDrawLGReset(ctx->lg[i]));
124: }
125: }
127: if (ctx->semilogy) {
128: PetscInt n, j;
130: PetscCall(VecDuplicate(u, &uv));
131: PetscCall(VecCopy(u, uv));
132: PetscCall(VecGetArray(uv, &yv));
133: PetscCall(VecGetLocalSize(uv, &n));
134: for (j = 0; j < n; j++) {
135: if (PetscRealPart(yv[j]) <= 0.0) yv[j] = -12;
136: else yv[j] = PetscLog10Real(PetscRealPart(yv[j]));
137: }
138: xv = yv;
139: } else {
140: PetscCall(VecGetArrayRead(u, &xv));
141: }
142: /* iterate over edges */
143: PetscCall(TSGetDM(ts, &dm));
144: i = 0;
145: PetscCall(DMNetworkGetEdgeRange(dm, &Start, &End));
146: for (e = Start; e < End; e++) {
147: PetscCall(DMNetworkGetComponent(dm, e, ALL_COMPONENTS, NULL, NULL, &nvar));
148: if (!nvar) continue;
150: PetscCall(DMNetworkGetLocalVecOffset(dm, e, ALL_COMPONENTS, &offset));
151: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg[i], ptime, (const PetscReal *)(xv + offset)));
152: i++;
153: }
155: /* iterate over vertices */
156: PetscCall(DMNetworkGetVertexRange(dm, &Start, &End));
157: for (v = Start; v < End; v++) {
158: PetscCall(DMNetworkGetComponent(dm, v, ALL_COMPONENTS, NULL, NULL, &nvar));
159: if (!nvar) continue;
161: PetscCall(DMNetworkGetLocalVecOffset(dm, v, ALL_COMPONENTS, &offset));
162: PetscCall(PetscDrawLGAddCommonPoint(ctx->lg[i], ptime, (const PetscReal *)(xv + offset)));
163: i++;
164: }
165: if (ctx->semilogy) {
166: PetscCall(VecRestoreArray(uv, &yv));
167: PetscCall(VecDestroy(&uv));
168: } else {
169: PetscCall(VecRestoreArrayRead(u, &xv));
170: }
172: PetscCall(TSGetConvergedReason(ts, &reason));
173: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && reason)) {
174: for (i = 0; i < ctx->nlg; i++) {
175: PetscCall(PetscDrawLGDraw(ctx->lg[i]));
176: PetscCall(PetscDrawLGSave(ctx->lg[i]));
177: }
178: }
179: PetscFunctionReturn(PETSC_SUCCESS);
180: }