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