1 2 #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/ 3 4 /*@ 5 PetscDrawTriangle - draws a triangle onto a drawable. 6 7 Not Collective 8 9 Input Parameters: 10 + draw - the drawing context 11 . x1 - coordinate of the first vertex 12 . y_1 - coordinate of the first vertex 13 . x2 - coordinate of the second vertex 14 . y2 - coordinate of the second vertex 15 . x3 - coordinate of the third vertex 16 . y3 - coordinate of the third vertex 17 . c1 - color of the first vertex 18 . c2 - color of the second vertex 19 - c3 - color of the third vertext 20 21 Level: beginner 22 23 .seealso: `PetscDraw`, `PetscDrawLine()`, `PetscDrawRectangle()`, `PetscDrawEllipse()`, `PetscDrawMarker()`, `PetscDrawPoint()`, `PetscDrawArrow()` 24 @*/ 25 PetscErrorCode PetscDrawTriangle(PetscDraw draw, PetscReal x1, PetscReal y_1, PetscReal x2, PetscReal y2, PetscReal x3, PetscReal y3, int c1, int c2, int c3) 26 { 27 PetscFunctionBegin; 28 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 29 PetscUseTypeMethod(draw, triangle, x1, y_1, x2, y2, x3, y3, c1, c2, c3); 30 PetscFunctionReturn(PETSC_SUCCESS); 31 } 32 33 /*@ 34 PetscDrawScalePopup - draws a contour scale window. 35 36 Collective 37 38 Input Parameters: 39 + popup - the window (often a window obtained via `PetscDrawGetPopup()` 40 . min - minimum value being plotted 41 - max - maximum value being plotted 42 43 Level: intermediate 44 45 Note: 46 All processors that share the draw MUST call this routine 47 48 .seealso: `PetscDraw`, `PetscDrawGetPopup()`, `PetscDrawTensorContour()` 49 @*/ 50 PetscErrorCode PetscDrawScalePopup(PetscDraw popup, PetscReal min, PetscReal max) 51 { 52 PetscBool isnull; 53 PetscReal xl = 0.0, yl = 0.0, xr = 1.0, yr = 1.0; 54 PetscMPIInt rank; 55 int i; 56 char string[32]; 57 58 PetscFunctionBegin; 59 if (!popup) PetscFunctionReturn(PETSC_SUCCESS); 60 PetscValidHeaderSpecific(popup, PETSC_DRAW_CLASSID, 1); 61 PetscCall(PetscDrawIsNull(popup, &isnull)); 62 if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 63 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)popup), &rank)); 64 65 PetscCall(PetscDrawCheckResizedWindow(popup)); 66 PetscCall(PetscDrawClear(popup)); 67 PetscCall(PetscDrawSetTitle(popup, "Contour Scale")); 68 PetscCall(PetscDrawSetCoordinates(popup, xl, yl, xr, yr)); 69 PetscDrawCollectiveBegin(popup); 70 if (rank == 0) { 71 for (i = 0; i < 10; i++) { 72 int c = PetscDrawRealToColor((PetscReal)i / 9, 0, 1); 73 PetscCall(PetscDrawRectangle(popup, xl, yl, xr, yr, c, c, c, c)); 74 yl += 0.1; 75 } 76 for (i = 0; i < 10; i++) { 77 PetscReal value = min + i * (max - min) / 9; 78 /* look for a value that should be zero, but is not due to round-off */ 79 if (PetscAbsReal(value) < 1.e-10 && max - min > 1.e-6) value = 0.0; 80 PetscCall(PetscSNPrintf(string, sizeof(string), "%18.16e", (double)value)); 81 PetscCall(PetscDrawString(popup, 0.2, 0.02 + i / 10.0, PETSC_DRAW_BLACK, string)); 82 } 83 } 84 PetscDrawCollectiveEnd(popup); 85 PetscCall(PetscDrawFlush(popup)); 86 PetscCall(PetscDrawSave(popup)); 87 PetscFunctionReturn(PETSC_SUCCESS); 88 } 89 90 typedef struct { 91 int m, n; 92 PetscReal *x, *y, min, max, *v; 93 PetscBool showgrid; 94 } ZoomCtx; 95 96 static PetscErrorCode PetscDrawTensorContour_Zoom(PetscDraw win, void *dctx) 97 { 98 int i; 99 ZoomCtx *ctx = (ZoomCtx *)dctx; 100 101 PetscFunctionBegin; 102 PetscCall(PetscDrawTensorContourPatch(win, ctx->m, ctx->n, ctx->x, ctx->y, ctx->min, ctx->max, ctx->v)); 103 if (ctx->showgrid) { 104 for (i = 0; i < ctx->m; i++) PetscCall(PetscDrawLine(win, ctx->x[i], ctx->y[0], ctx->x[i], ctx->y[ctx->n - 1], PETSC_DRAW_BLACK)); 105 for (i = 0; i < ctx->n; i++) PetscCall(PetscDrawLine(win, ctx->x[0], ctx->y[i], ctx->x[ctx->m - 1], ctx->y[i], PETSC_DRAW_BLACK)); 106 } 107 PetscFunctionReturn(PETSC_SUCCESS); 108 } 109 110 /*@C 111 PetscDrawTensorContour - draws a contour plot for a two-dimensional array 112 113 Collective on draw, but draw must be sequential 114 115 Input Parameters: 116 + draw - the draw context 117 . m - the number of local mesh points in the x direction 118 . n - the number of local mesh points in the y direction 119 . xi - the locations of the global mesh points in the horizontal direction (optional, use `NULL` to indicate uniform spacing on [0,1]) 120 . yi - the locations of the global mesh points in the vertical direction (optional, use `NULL` to indicate uniform spacing on [0,1]) 121 - v - the values 122 123 Options Database Keys: 124 + -draw_x_shared_colormap - Indicates use of private colormap 125 - -draw_contour_grid - draws grid contour 126 127 Level: intermediate 128 129 .seealso: `PetscDraw`, `PetscDrawTensorContourPatch()`, `PetscDrawScalePopup()` 130 @*/ 131 PetscErrorCode PetscDrawTensorContour(PetscDraw draw, int m, int n, const PetscReal xi[], const PetscReal yi[], PetscReal *v) 132 { 133 int N = m * n; 134 PetscBool isnull; 135 PetscDraw popup; 136 int xin = 1, yin = 1, i; 137 PetscMPIInt size; 138 PetscReal h; 139 ZoomCtx ctx; 140 141 PetscFunctionBegin; 142 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 143 PetscCall(PetscDrawIsNull(draw, &isnull)); 144 if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 145 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size)); 146 PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "May only be used with single processor PetscDraw"); 147 PetscCheck(N > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n %d and m %d must be positive", m, n); 148 149 ctx.v = v; 150 ctx.m = m; 151 ctx.n = n; 152 ctx.max = ctx.min = v[0]; 153 for (i = 0; i < N; i++) { 154 if (ctx.max < ctx.v[i]) ctx.max = ctx.v[i]; 155 if (ctx.min > ctx.v[i]) ctx.min = ctx.v[i]; 156 } 157 if (ctx.max - ctx.min < 1.e-7) { 158 ctx.min -= 5.e-8; 159 ctx.max += 5.e-8; 160 } 161 162 /* PetscDraw the scale window */ 163 PetscCall(PetscDrawGetPopup(draw, &popup)); 164 PetscCall(PetscDrawScalePopup(popup, ctx.min, ctx.max)); 165 166 ctx.showgrid = PETSC_FALSE; 167 PetscCall(PetscOptionsGetBool(((PetscObject)draw)->options, NULL, "-draw_contour_grid", &ctx.showgrid, NULL)); 168 169 /* fill up x and y coordinates */ 170 if (!xi) { 171 xin = 0; 172 PetscCall(PetscMalloc1(ctx.m, &ctx.x)); 173 h = 1.0 / (ctx.m - 1); 174 ctx.x[0] = 0.0; 175 for (i = 1; i < ctx.m; i++) ctx.x[i] = ctx.x[i - 1] + h; 176 } else ctx.x = (PetscReal *)xi; 177 178 if (!yi) { 179 yin = 0; 180 PetscCall(PetscMalloc1(ctx.n, &ctx.y)); 181 h = 1.0 / (ctx.n - 1); 182 ctx.y[0] = 0.0; 183 for (i = 1; i < ctx.n; i++) ctx.y[i] = ctx.y[i - 1] + h; 184 } else ctx.y = (PetscReal *)yi; 185 186 PetscCall(PetscDrawZoom(draw, PetscDrawTensorContour_Zoom, &ctx)); 187 188 if (!xin) PetscCall(PetscFree(ctx.x)); 189 if (!yin) PetscCall(PetscFree(ctx.y)); 190 PetscFunctionReturn(PETSC_SUCCESS); 191 } 192 193 /*@ 194 PetscDrawTensorContourPatch - draws a rectangular patch of a contour plot 195 for a two-dimensional array. 196 197 Not Collective 198 199 Input Parameters: 200 + draw - the draw context 201 . m - the number of local mesh points in the x direction 202 . n - the number of local mesh points in the y direction 203 . x - the horizontal locations of the local mesh points 204 . y - the vertical locations of the local mesh points 205 . min - the minimum value in the entire contour 206 . max - the maximum value in the entire contour 207 - v - the data 208 209 Options Database Key: 210 . -draw_x_shared_colormap - Activates private colormap 211 212 Level: advanced 213 214 Note: 215 This is a lower level support routine, usually the user will call 216 `PetscDrawTensorContour()`. 217 218 .seealso: `PetscDraw`, `PetscDrawTensorContour()` 219 @*/ 220 PetscErrorCode PetscDrawTensorContourPatch(PetscDraw draw, int m, int n, PetscReal *x, PetscReal *y, PetscReal min, PetscReal max, PetscReal *v) 221 { 222 int c1, c2, c3, c4, i, j; 223 PetscReal x1, x2, x3, x4, y_1, y2, y3, y4; 224 225 PetscFunctionBegin; 226 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 227 /* PetscDraw the contour plot patch */ 228 for (j = 0; j < n - 1; j++) { 229 for (i = 0; i < m - 1; i++) { 230 x1 = x[i]; 231 y_1 = y[j]; 232 c1 = PetscDrawRealToColor(v[i + j * m], min, max); 233 x2 = x[i + 1]; 234 y2 = y_1; 235 c2 = PetscDrawRealToColor(v[i + j * m + 1], min, max); 236 x3 = x2; 237 y3 = y[j + 1]; 238 c3 = PetscDrawRealToColor(v[i + j * m + 1 + m], min, max); 239 x4 = x1; 240 y4 = y3; 241 c4 = PetscDrawRealToColor(v[i + j * m + m], min, max); 242 243 PetscCall(PetscDrawTriangle(draw, x1, y_1, x2, y2, x3, y3, c1, c2, c3)); 244 PetscCall(PetscDrawTriangle(draw, x1, y_1, x3, y3, x4, y4, c1, c3, c4)); 245 } 246 } 247 PetscFunctionReturn(PETSC_SUCCESS); 248 } 249