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: }