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