Date: 2026-07-30T21:14:32+00:00

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